Reorganized the screen widget src folder so classes are more organized.

This commit might break some Groovy scripts. There seemed to be a lot of C&P widget import statements, but there were no widget classes being used in the script, so I removed them. I might have overlooked something though.

git-svn-id: https://svn.apache.org/repos/asf/ofbiz/trunk@1652852 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/applications/content/src/org/ofbiz/content/cms/CmsEvents.java b/applications/content/src/org/ofbiz/content/cms/CmsEvents.java
index 6b21bee..6d403b7 100644
--- a/applications/content/src/org/ofbiz/content/cms/CmsEvents.java
+++ b/applications/content/src/org/ofbiz/content/cms/CmsEvents.java
@@ -47,9 +47,9 @@
 import org.ofbiz.service.LocalDispatcher;
 import org.ofbiz.webapp.control.RequestHandler;
 import org.ofbiz.webapp.website.WebSiteWorker;
-import org.ofbiz.widget.form.FormStringRenderer;
-import org.ofbiz.widget.form.MacroFormRenderer;
-import org.ofbiz.widget.screen.ScreenRenderer;
+import org.ofbiz.widget.renderer.FormStringRenderer;
+import org.ofbiz.widget.renderer.ScreenRenderer;
+import org.ofbiz.widget.renderer.macro.MacroFormRenderer;
 
 import freemarker.template.TemplateException;
 
diff --git a/applications/content/src/org/ofbiz/content/content/ContentWorker.java b/applications/content/src/org/ofbiz/content/content/ContentWorker.java
index 3f7d96c..2b57db8 100644
--- a/applications/content/src/org/ofbiz/content/content/ContentWorker.java
+++ b/applications/content/src/org/ofbiz/content/content/ContentWorker.java
@@ -69,7 +69,7 @@
 /**
  * ContentWorker Class
  */
-public class ContentWorker implements org.ofbiz.widget.ContentWorkerInterface {
+public class ContentWorker implements org.ofbiz.widget.content.ContentWorkerInterface {
 
     public static final String module = ContentWorker.class.getName();
 
diff --git a/applications/content/src/org/ofbiz/content/data/DataResourceWorker.java b/applications/content/src/org/ofbiz/content/data/DataResourceWorker.java
index d4f7f4b..876414f 100644
--- a/applications/content/src/org/ofbiz/content/data/DataResourceWorker.java
+++ b/applications/content/src/org/ofbiz/content/data/DataResourceWorker.java
@@ -76,11 +76,11 @@
 import org.ofbiz.entity.util.EntityUtilProperties;
 import org.ofbiz.service.GenericServiceException;
 import org.ofbiz.service.LocalDispatcher;
-import org.ofbiz.widget.screen.MacroScreenRenderer;
-import org.ofbiz.widget.screen.ModelScreen;
-import org.ofbiz.widget.screen.ScreenFactory;
-import org.ofbiz.widget.screen.ScreenRenderer;
-import org.ofbiz.widget.screen.ScreenStringRenderer;
+import org.ofbiz.widget.model.ModelScreen;
+import org.ofbiz.widget.model.ScreenFactory;
+import org.ofbiz.widget.renderer.ScreenRenderer;
+import org.ofbiz.widget.renderer.ScreenStringRenderer;
+import org.ofbiz.widget.renderer.macro.MacroScreenRenderer;
 import org.w3c.dom.Document;
 import org.xml.sax.SAXException;
 
@@ -90,7 +90,7 @@
 /**
  * DataResourceWorker Class
  */
-public class DataResourceWorker  implements org.ofbiz.widget.DataResourceWorkerInterface {
+public class DataResourceWorker  implements org.ofbiz.widget.content.DataResourceWorkerInterface {
 
     public static final String module = DataResourceWorker.class.getName();
     public static final String err_resource = "ContentErrorUiLabels";
diff --git a/applications/content/src/org/ofbiz/content/output/OutputServices.java b/applications/content/src/org/ofbiz/content/output/OutputServices.java
index 1f9b1f8..f6755dd 100644
--- a/applications/content/src/org/ofbiz/content/output/OutputServices.java
+++ b/applications/content/src/org/ofbiz/content/output/OutputServices.java
@@ -63,9 +63,9 @@
 import org.ofbiz.service.DispatchContext;
 import org.ofbiz.service.ServiceUtil;
 import org.ofbiz.webapp.view.ApacheFopWorker;
-import org.ofbiz.widget.fo.FoFormRenderer;
-import org.ofbiz.widget.fo.FoScreenRenderer;
-import org.ofbiz.widget.screen.ScreenRenderer;
+import org.ofbiz.widget.renderer.fo.FoFormRenderer;
+import org.ofbiz.widget.renderer.fo.FoScreenRenderer;
+import org.ofbiz.widget.renderer.ScreenRenderer;
 
 
 /**
diff --git a/applications/content/webapp/content/WEB-INF/actions/survey/EditSurveyQuestions.groovy b/applications/content/webapp/content/WEB-INF/actions/survey/EditSurveyQuestions.groovy
index e5d1ad2..53fa09f 100644
--- a/applications/content/webapp/content/WEB-INF/actions/survey/EditSurveyQuestions.groovy
+++ b/applications/content/webapp/content/WEB-INF/actions/survey/EditSurveyQuestions.groovy
@@ -20,7 +20,7 @@
 import org.ofbiz.entity.*
 import org.ofbiz.entity.condition.*
 import org.ofbiz.base.util.*
-import org.ofbiz.widget.html.*
+import org.ofbiz.widget.renderer.html.*
 
 surveyQuestionId = parameters.surveyQuestionId;
 context.surveyQuestionId = surveyQuestionId;
diff --git a/applications/manufacturing/webapp/manufacturing/WEB-INF/actions/jobshopmgt/ProductionRunActualComponents.groovy b/applications/manufacturing/webapp/manufacturing/WEB-INF/actions/jobshopmgt/ProductionRunActualComponents.groovy
index 49e6897..8163a60 100644
--- a/applications/manufacturing/webapp/manufacturing/WEB-INF/actions/jobshopmgt/ProductionRunActualComponents.groovy
+++ b/applications/manufacturing/webapp/manufacturing/WEB-INF/actions/jobshopmgt/ProductionRunActualComponents.groovy
@@ -17,7 +17,7 @@
  * under the License.
  */
 
-import org.ofbiz.widget.html.HtmlFormWrapper;
+import org.ofbiz.widget.renderer.html.HtmlFormWrapper;
 
 productionRunId = parameters.productionRunId ?: parameters.workEffortId;
 
diff --git a/applications/manufacturing/webapp/manufacturing/WEB-INF/actions/jobshopmgt/ProductionRunComponents.groovy b/applications/manufacturing/webapp/manufacturing/WEB-INF/actions/jobshopmgt/ProductionRunComponents.groovy
index 8bc5a50..db69b53 100644
--- a/applications/manufacturing/webapp/manufacturing/WEB-INF/actions/jobshopmgt/ProductionRunComponents.groovy
+++ b/applications/manufacturing/webapp/manufacturing/WEB-INF/actions/jobshopmgt/ProductionRunComponents.groovy
@@ -17,7 +17,7 @@
  * under the License.
  */
 
-import org.ofbiz.widget.html.HtmlFormWrapper;
+import org.ofbiz.widget.renderer.html.HtmlFormWrapper;
 
 productionRunId = parameters.productionRunId ?: parameters.workEffortId;
 
diff --git a/applications/manufacturing/webapp/manufacturing/WEB-INF/actions/jobshopmgt/ProductionRunCosts.groovy b/applications/manufacturing/webapp/manufacturing/WEB-INF/actions/jobshopmgt/ProductionRunCosts.groovy
index 74d0108..6c25da5 100644
--- a/applications/manufacturing/webapp/manufacturing/WEB-INF/actions/jobshopmgt/ProductionRunCosts.groovy
+++ b/applications/manufacturing/webapp/manufacturing/WEB-INF/actions/jobshopmgt/ProductionRunCosts.groovy
@@ -18,7 +18,7 @@
  */
 
 import org.ofbiz.entity.util.EntityUtil;
-import org.ofbiz.widget.html.HtmlFormWrapper;
+import org.ofbiz.widget.renderer.html.HtmlFormWrapper;
 
 productionRunId = parameters.productionRunId ?: parameters.workEffortId;
 taskCosts = [];
diff --git a/applications/manufacturing/webapp/manufacturing/WEB-INF/actions/jobshopmgt/ProductionRunDeclaration.groovy b/applications/manufacturing/webapp/manufacturing/WEB-INF/actions/jobshopmgt/ProductionRunDeclaration.groovy
index 8367e94..f456717 100644
--- a/applications/manufacturing/webapp/manufacturing/WEB-INF/actions/jobshopmgt/ProductionRunDeclaration.groovy
+++ b/applications/manufacturing/webapp/manufacturing/WEB-INF/actions/jobshopmgt/ProductionRunDeclaration.groovy
@@ -22,7 +22,7 @@
 
 import org.ofbiz.entity.util.EntityUtil;
 import org.ofbiz.entity.GenericValue;
-import org.ofbiz.widget.html.HtmlFormWrapper;
+import org.ofbiz.widget.renderer.html.HtmlFormWrapper;
 import org.ofbiz.manufacturing.jobshopmgt.ProductionRun;
 
 import javolution.util.FastList;
diff --git a/applications/manufacturing/webapp/manufacturing/WEB-INF/actions/jobshopmgt/ProductionRunFixedAssets.groovy b/applications/manufacturing/webapp/manufacturing/WEB-INF/actions/jobshopmgt/ProductionRunFixedAssets.groovy
index c1d6714..eb99298 100644
--- a/applications/manufacturing/webapp/manufacturing/WEB-INF/actions/jobshopmgt/ProductionRunFixedAssets.groovy
+++ b/applications/manufacturing/webapp/manufacturing/WEB-INF/actions/jobshopmgt/ProductionRunFixedAssets.groovy
@@ -17,7 +17,7 @@
  * under the License.
  */
 
-import org.ofbiz.widget.html.HtmlFormWrapper;
+import org.ofbiz.widget.renderer.html.HtmlFormWrapper;
 
 productionRunId = parameters.productionRunId ?: parameters.workEffortId;
 
diff --git a/applications/manufacturing/webapp/manufacturing/WEB-INF/actions/routing/EditCalendarExceptionDay.groovy b/applications/manufacturing/webapp/manufacturing/WEB-INF/actions/routing/EditCalendarExceptionDay.groovy
index e076d6a..ce1dea6 100644
--- a/applications/manufacturing/webapp/manufacturing/WEB-INF/actions/routing/EditCalendarExceptionDay.groovy
+++ b/applications/manufacturing/webapp/manufacturing/WEB-INF/actions/routing/EditCalendarExceptionDay.groovy
@@ -21,7 +21,7 @@
 import java.util.*;
 import org.ofbiz.base.util.*;
 import org.ofbiz.entity.*;
-import org.ofbiz.widget.html.*;
+import org.ofbiz.widget.renderer.html.HtmlFormWrapper;
 
 if (security.hasEntityPermission("MANUFACTURING", "_VIEW", session)) {
     context.hasPermission = Boolean.TRUE;
diff --git a/applications/manufacturing/webapp/manufacturing/WEB-INF/actions/routing/EditCalendarExceptionWeek.groovy b/applications/manufacturing/webapp/manufacturing/WEB-INF/actions/routing/EditCalendarExceptionWeek.groovy
index 7907a4f..8886d69 100644
--- a/applications/manufacturing/webapp/manufacturing/WEB-INF/actions/routing/EditCalendarExceptionWeek.groovy
+++ b/applications/manufacturing/webapp/manufacturing/WEB-INF/actions/routing/EditCalendarExceptionWeek.groovy
@@ -18,7 +18,7 @@
  */
 
 
-import org.ofbiz.widget.html.HtmlFormWrapper;
+import org.ofbiz.widget.renderer.html.HtmlFormWrapper;
 import org.ofbiz.base.util.*;
 
 if (security.hasEntityPermission("MANUFACTURING", "_VIEW", session)) {
diff --git a/applications/manufacturing/webapp/manufacturing/jobshopmgt/ShowProductionRun.groovy b/applications/manufacturing/webapp/manufacturing/jobshopmgt/ShowProductionRun.groovy
index ae8c362..b11a78f 100644
--- a/applications/manufacturing/webapp/manufacturing/jobshopmgt/ShowProductionRun.groovy
+++ b/applications/manufacturing/webapp/manufacturing/jobshopmgt/ShowProductionRun.groovy
@@ -25,7 +25,7 @@
 import org.ofbiz.base.util.*;
 import org.ofbiz.base.util.Debug;
 import org.ofbiz.base.util.UtilValidate;
-import org.ofbiz.widget.html.HtmlFormWrapper;
+import org.ofbiz.widget.renderer.html.HtmlFormWrapper;
 import org.ofbiz.manufacturing.jobshopmgt.ProductionRun;
 
 delegator = request.getAttribute("delegator");
diff --git a/applications/order/webapp/ordermgr/WEB-INF/actions/order/OrderDeliveryScheduleInfo.groovy b/applications/order/webapp/ordermgr/WEB-INF/actions/order/OrderDeliveryScheduleInfo.groovy
index 9fbd1b9..073c609 100644
--- a/applications/order/webapp/ordermgr/WEB-INF/actions/order/OrderDeliveryScheduleInfo.groovy
+++ b/applications/order/webapp/ordermgr/WEB-INF/actions/order/OrderDeliveryScheduleInfo.groovy
@@ -19,7 +19,7 @@
 
 import org.ofbiz.base.util.*;
 import org.ofbiz.entity.*;
-import org.ofbiz.widget.html.*;
+import org.ofbiz.widget.renderer.html.HtmlFormWrapper;
 
 orderId = request.getParameter("orderId");
 orderTypeId = null;
diff --git a/applications/product/webapp/catalog/WEB-INF/actions/config/EditProductConfigItemContent.groovy b/applications/product/webapp/catalog/WEB-INF/actions/config/EditProductConfigItemContent.groovy
index 5ce758f..7fae990 100644
--- a/applications/product/webapp/catalog/WEB-INF/actions/config/EditProductConfigItemContent.groovy
+++ b/applications/product/webapp/catalog/WEB-INF/actions/config/EditProductConfigItemContent.groovy
@@ -21,7 +21,7 @@
 import org.ofbiz.base.util.string.*
 import org.ofbiz.entity.*
 import org.ofbiz.entity.util.EntityUtilProperties;
-import org.ofbiz.widget.html.*
+import org.ofbiz.widget.renderer.html.HtmlFormWrapper;
 
 // make the image file formats
 imageFilenameFormat = "configitems/${configItemId}";
diff --git a/applications/product/webapp/catalog/WEB-INF/actions/config/EditProductConfigItemContentContent.groovy b/applications/product/webapp/catalog/WEB-INF/actions/config/EditProductConfigItemContentContent.groovy
index 0370d1e..65f1414 100644
--- a/applications/product/webapp/catalog/WEB-INF/actions/config/EditProductConfigItemContentContent.groovy
+++ b/applications/product/webapp/catalog/WEB-INF/actions/config/EditProductConfigItemContentContent.groovy
@@ -20,7 +20,7 @@
 import org.ofbiz.entity.*;
 import org.ofbiz.entity.util.*;
 import org.ofbiz.base.util.*;
-import org.ofbiz.widget.html.*;
+import org.ofbiz.widget.renderer.html.HtmlFormWrapper;
 
 contentId = request.getParameter("contentId") ?: null;
 
diff --git a/applications/product/webapp/catalog/WEB-INF/actions/config/EditProductConfigOptions.groovy b/applications/product/webapp/catalog/WEB-INF/actions/config/EditProductConfigOptions.groovy
index bd3a6e4..4db0b0e 100644
--- a/applications/product/webapp/catalog/WEB-INF/actions/config/EditProductConfigOptions.groovy
+++ b/applications/product/webapp/catalog/WEB-INF/actions/config/EditProductConfigOptions.groovy
@@ -17,7 +17,7 @@
  * under the License.
  */
 
-import org.ofbiz.widget.html.*
+import org.ofbiz.widget.renderer.html.HtmlFormWrapper
 
 createConfigOptionWrapper = new HtmlFormWrapper("component://product/widget/catalog/ConfigForms.xml", "CreateConfigOption", request, response);
 createConfigOptionWrapper.putInContext("configItemId", configItemId);
diff --git a/applications/product/webapp/facility/WEB-INF/actions/shipment/EditShipment.groovy b/applications/product/webapp/facility/WEB-INF/actions/shipment/EditShipment.groovy
index a6e5372..7afbd43 100644
--- a/applications/product/webapp/facility/WEB-INF/actions/shipment/EditShipment.groovy
+++ b/applications/product/webapp/facility/WEB-INF/actions/shipment/EditShipment.groovy
@@ -18,7 +18,7 @@
  */
 
 import org.ofbiz.entity.condition.*
-import org.ofbiz.widget.html.HtmlFormWrapper
+import org.ofbiz.widget.renderer.html.HtmlFormWrapper
 
 shipmentId = parameters.shipmentId;
 shipment = from("Shipment").where("shipmentId", shipmentId).queryOne();
diff --git a/applications/product/webapp/facility/WEB-INF/actions/shipment/EditShipmentPlan.groovy b/applications/product/webapp/facility/WEB-INF/actions/shipment/EditShipmentPlan.groovy
index d5288c6..aa17335 100644
--- a/applications/product/webapp/facility/WEB-INF/actions/shipment/EditShipmentPlan.groovy
+++ b/applications/product/webapp/facility/WEB-INF/actions/shipment/EditShipmentPlan.groovy
@@ -17,7 +17,7 @@
  * under the License.
  */
 
-import org.ofbiz.widget.html.*;
+import org.ofbiz.widget.renderer.html.HtmlFormWrapper;
 import org.ofbiz.entity.condition.EntityCondition;
 
 shipmentId = request.getParameter("shipmentId");
diff --git a/framework/common/src/org/ofbiz/common/email/EmailServices.java b/framework/common/src/org/ofbiz/common/email/EmailServices.java
index 475a8f1..477eb08 100644
--- a/framework/common/src/org/ofbiz/common/email/EmailServices.java
+++ b/framework/common/src/org/ofbiz/common/email/EmailServices.java
@@ -73,9 +73,9 @@
 import org.ofbiz.service.ServiceUtil;
 import org.ofbiz.service.mail.MimeMessageWrapper;
 import org.ofbiz.webapp.view.ApacheFopWorker;
-import org.ofbiz.widget.fo.FoScreenRenderer;
-import org.ofbiz.widget.html.HtmlScreenRenderer;
-import org.ofbiz.widget.screen.ScreenRenderer;
+import org.ofbiz.widget.renderer.fo.FoScreenRenderer;
+import org.ofbiz.widget.renderer.html.HtmlScreenRenderer;
+import org.ofbiz.widget.renderer.ScreenRenderer;
 import org.xml.sax.SAXException;
 
 import com.sun.mail.smtp.SMTPAddressFailedException;
diff --git a/framework/common/webcommon/WEB-INF/handlers-controller.xml b/framework/common/webcommon/WEB-INF/handlers-controller.xml
index 23802a7..eb083c3 100644
--- a/framework/common/webcommon/WEB-INF/handlers-controller.xml
+++ b/framework/common/webcommon/WEB-INF/handlers-controller.xml
@@ -35,11 +35,11 @@
     <handler name="script" type="request" class="org.ofbiz.webapp.event.ScriptEventHandler"/>
 
     <!-- view handlers -->
-    <handler name="screen" type="view" class="org.ofbiz.widget.screen.MacroScreenViewHandler"/>
-    <handler name="screenxml" type="view" class="org.ofbiz.widget.screen.MacroScreenViewHandler"/>
-    <handler name="screentext" type="view" class="org.ofbiz.widget.screen.MacroScreenViewHandler"/>
-    <handler name="screencsv" type="view" class="org.ofbiz.widget.screen.MacroScreenViewHandler"/>
-    <handler name="screenfop" type="view" class="org.ofbiz.widget.screen.ScreenFopViewHandler"/>
+    <handler name="screen" type="view" class="org.ofbiz.widget.renderer.macro.MacroScreenViewHandler"/>
+    <handler name="screenxml" type="view" class="org.ofbiz.widget.renderer.macro.MacroScreenViewHandler"/>
+    <handler name="screentext" type="view" class="org.ofbiz.widget.renderer.macro.MacroScreenViewHandler"/>
+    <handler name="screencsv" type="view" class="org.ofbiz.widget.renderer.macro.MacroScreenViewHandler"/>
+    <handler name="screenfop" type="view" class="org.ofbiz.widget.renderer.fo.ScreenFopViewHandler"/>
     <handler name="jsp" type="view" class="org.ofbiz.webapp.view.JspViewHandler"/>
     <handler name="http" type="view" class="org.ofbiz.webapp.view.HttpViewHandler"/>
 </site-conf>
diff --git a/framework/common/widget/PortalPageScreens.xml b/framework/common/widget/PortalPageScreens.xml
index 17a7a08..0c2c16c 100644
--- a/framework/common/widget/PortalPageScreens.xml
+++ b/framework/common/widget/PortalPageScreens.xml
@@ -94,7 +94,7 @@
                 <set field="layoutSettings.javaScripts[]" value="/images/myportal.js" global="true"/>
                 <set field="layoutSettings.styleSheets[+0]" value="/images/myportal.css" global="true"/>
                 <entity-one entity-name="PortalPage" value-field="portalPage"/>
-                <set field="portalPages" value="${groovy:org.ofbiz.widget.PortalPageWorker.getPortalPages(parameters.parentPortalPageId,context)}"/>
+                <set field="portalPages" value="${groovy:org.ofbiz.widget.portal.PortalPageWorker.getPortalPages(parameters.parentPortalPageId,context)}"/>
             </actions>
             <widgets>
                 <decorator-screen name="main-decorator" location="${parameters.mainDecoratorLocation}">
diff --git a/framework/resources/templates/web.xml b/framework/resources/templates/web.xml
index 2ea7747..3e672cb 100644
--- a/framework/resources/templates/web.xml
+++ b/framework/resources/templates/web.xml
@@ -26,7 +26,7 @@
     <context-param>
         <param-name>widgetVerbose</param-name>
         <param-value>false</param-value>
-        <description>Enable widget boundary comments. See org.ofbiz.widget.ModelWidget.widgetBoundaryCommentsEnabled().</description>
+        <description>Enable widget boundary comments. See org.ofbiz.widget.model.ModelWidget.widgetBoundaryCommentsEnabled().</description>
     </context-param>
     -->
     <context-param>
diff --git a/framework/webtools/src/org/ofbiz/webtools/artifactinfo/ArtifactInfoFactory.java b/framework/webtools/src/org/ofbiz/webtools/artifactinfo/ArtifactInfoFactory.java
index b82da97..c64cdae 100644
--- a/framework/webtools/src/org/ofbiz/webtools/artifactinfo/ArtifactInfoFactory.java
+++ b/framework/webtools/src/org/ofbiz/webtools/artifactinfo/ArtifactInfoFactory.java
@@ -42,12 +42,13 @@
 import org.ofbiz.base.util.GeneralException;
 import org.ofbiz.base.util.UtilValidate;
 import org.ofbiz.base.util.cache.UtilCache;
+import org.ofbiz.entity.Delegator;
+import org.ofbiz.entity.DelegatorFactory;
 import org.ofbiz.entity.GenericEntityException;
 import org.ofbiz.entity.config.model.DelegatorElement;
 import org.ofbiz.entity.config.model.EntityConfig;
 import org.ofbiz.entity.model.ModelEntity;
 import org.ofbiz.entity.model.ModelReader;
-import org.ofbiz.entity.*;
 import org.ofbiz.service.DispatchContext;
 import org.ofbiz.service.GenericServiceException;
 import org.ofbiz.service.LocalDispatcher;
@@ -57,10 +58,10 @@
 import org.ofbiz.webapp.control.ConfigXMLReader;
 import org.ofbiz.webapp.control.ConfigXMLReader.ControllerConfig;
 import org.ofbiz.webapp.control.WebAppConfigurationException;
-import org.ofbiz.widget.form.FormFactory;
-import org.ofbiz.widget.form.ModelForm;
-import org.ofbiz.widget.screen.ModelScreen;
-import org.ofbiz.widget.screen.ScreenFactory;
+import org.ofbiz.widget.model.FormFactory;
+import org.ofbiz.widget.model.ModelForm;
+import org.ofbiz.widget.model.ModelScreen;
+import org.ofbiz.widget.model.ScreenFactory;
 import org.xml.sax.SAXException;
 
 public class ArtifactInfoFactory {
diff --git a/framework/webtools/src/org/ofbiz/webtools/artifactinfo/FormWidgetArtifactInfo.java b/framework/webtools/src/org/ofbiz/webtools/artifactinfo/FormWidgetArtifactInfo.java
index 7828dd3..46f0f93 100644
--- a/framework/webtools/src/org/ofbiz/webtools/artifactinfo/FormWidgetArtifactInfo.java
+++ b/framework/webtools/src/org/ofbiz/webtools/artifactinfo/FormWidgetArtifactInfo.java
@@ -33,7 +33,7 @@
 import org.ofbiz.base.util.UtilURL;
 import org.ofbiz.widget.artifact.ArtifactInfoContext;
 import org.ofbiz.widget.artifact.ArtifactInfoGatherer;
-import org.ofbiz.widget.form.ModelForm;
+import org.ofbiz.widget.model.ModelForm;
 import org.xml.sax.SAXException;
 
 /**
diff --git a/framework/webtools/src/org/ofbiz/webtools/artifactinfo/ScreenWidgetArtifactInfo.java b/framework/webtools/src/org/ofbiz/webtools/artifactinfo/ScreenWidgetArtifactInfo.java
index f3ee202..2c2544f 100644
--- a/framework/webtools/src/org/ofbiz/webtools/artifactinfo/ScreenWidgetArtifactInfo.java
+++ b/framework/webtools/src/org/ofbiz/webtools/artifactinfo/ScreenWidgetArtifactInfo.java
@@ -35,7 +35,7 @@
 import org.ofbiz.base.util.UtilURL;
 import org.ofbiz.widget.artifact.ArtifactInfoContext;
 import org.ofbiz.widget.artifact.ArtifactInfoGatherer;
-import org.ofbiz.widget.screen.ModelScreen;
+import org.ofbiz.widget.model.ModelScreen;
 import org.xml.sax.SAXException;
 
 /**
diff --git a/framework/webtools/src/org/ofbiz/webtools/print/FoPrintServerEvents.java b/framework/webtools/src/org/ofbiz/webtools/print/FoPrintServerEvents.java
index cdc032e..53d6a26 100644
--- a/framework/webtools/src/org/ofbiz/webtools/print/FoPrintServerEvents.java
+++ b/framework/webtools/src/org/ofbiz/webtools/print/FoPrintServerEvents.java
@@ -36,8 +36,8 @@
 import org.ofbiz.base.util.UtilValidate;
 import org.ofbiz.entity.GenericValue;
 import org.ofbiz.entity.GenericEntityException;
-import org.ofbiz.widget.screen.ScreenRenderer;
-import org.ofbiz.widget.html.HtmlScreenRenderer;
+import org.ofbiz.widget.renderer.ScreenRenderer;
+import org.ofbiz.widget.renderer.html.HtmlScreenRenderer;
 
 /**
  * FoPrintServerEvents
diff --git a/framework/widget/config/freemarkerTransforms.properties b/framework/widget/config/freemarkerTransforms.properties
index 82b64b8..5b783e2 100644
--- a/framework/widget/config/freemarkerTransforms.properties
+++ b/framework/widget/config/freemarkerTransforms.properties
@@ -21,4 +21,4 @@
 
 # entries are in the form: key=transform name, property=transform class name
 
-menuWrap=org.ofbiz.widget.menu.MenuWrapTransform
+menuWrap=org.ofbiz.widget.renderer.MenuWrapTransform
diff --git a/framework/widget/src/org/ofbiz/widget/WidgetFactory.java b/framework/widget/src/org/ofbiz/widget/WidgetFactory.java
index 5b9f591..a6f1cc2 100644
--- a/framework/widget/src/org/ofbiz/widget/WidgetFactory.java
+++ b/framework/widget/src/org/ofbiz/widget/WidgetFactory.java
@@ -29,9 +29,9 @@
 import org.ofbiz.base.util.Assert;
 import org.ofbiz.base.util.Debug;
 import org.ofbiz.base.util.UtilGenerics;
-import org.ofbiz.widget.screen.IterateSectionWidget;
-import org.ofbiz.widget.screen.ModelScreen;
-import org.ofbiz.widget.screen.ModelScreenWidget;
+import org.ofbiz.widget.model.IterateSectionWidget;
+import org.ofbiz.widget.model.ModelScreen;
+import org.ofbiz.widget.model.ModelScreenWidget;
 import org.w3c.dom.Element;
 
 /**
diff --git a/framework/widget/src/org/ofbiz/widget/WidgetWorker.java b/framework/widget/src/org/ofbiz/widget/WidgetWorker.java
index 093288d..18a7be3 100644
--- a/framework/widget/src/org/ofbiz/widget/WidgetWorker.java
+++ b/framework/widget/src/org/ofbiz/widget/WidgetWorker.java
@@ -39,8 +39,8 @@
 import org.ofbiz.webapp.control.RequestHandler;
 import org.ofbiz.webapp.control.WebAppConfigurationException;
 import org.ofbiz.webapp.taglib.ContentUrlTag;
-import org.ofbiz.widget.form.ModelForm;
-import org.ofbiz.widget.form.ModelFormField;
+import org.ofbiz.widget.model.ModelForm;
+import org.ofbiz.widget.model.ModelFormField;
 
 public final class WidgetWorker {
 
diff --git a/framework/widget/src/org/ofbiz/widget/artifact/ArtifactInfoGatherer.java b/framework/widget/src/org/ofbiz/widget/artifact/ArtifactInfoGatherer.java
index 4bfde5a..a8fb7ee 100644
--- a/framework/widget/src/org/ofbiz/widget/artifact/ArtifactInfoGatherer.java
+++ b/framework/widget/src/org/ofbiz/widget/artifact/ArtifactInfoGatherer.java
@@ -23,83 +23,83 @@
 import org.ofbiz.base.util.GeneralException;

 import org.ofbiz.base.util.UtilValidate;

 import org.ofbiz.webapp.control.ConfigXMLReader;

-import org.ofbiz.widget.AbstractModelAction.EntityAnd;

-import org.ofbiz.widget.AbstractModelAction.EntityCondition;

-import org.ofbiz.widget.AbstractModelAction.EntityOne;

-import org.ofbiz.widget.AbstractModelAction.GetRelated;

-import org.ofbiz.widget.AbstractModelAction.GetRelatedOne;

-import org.ofbiz.widget.AbstractModelAction.PropertyMap;

-import org.ofbiz.widget.AbstractModelAction.PropertyToField;

-import org.ofbiz.widget.AbstractModelAction.Script;

-import org.ofbiz.widget.AbstractModelAction.Service;

-import org.ofbiz.widget.AbstractModelAction.SetField;

-import org.ofbiz.widget.ModelAction;

-import org.ofbiz.widget.ModelActionVisitor;

-import org.ofbiz.widget.ModelFieldVisitor;

-import org.ofbiz.widget.ModelWidgetVisitor;

-import org.ofbiz.widget.form.FieldInfo;

-import org.ofbiz.widget.form.ModelForm;

-import org.ofbiz.widget.form.ModelForm.AltTarget;

-import org.ofbiz.widget.form.ModelForm.AutoFieldsEntity;

-import org.ofbiz.widget.form.ModelForm.AutoFieldsService;

-import org.ofbiz.widget.form.ModelFormAction;

-import org.ofbiz.widget.form.ModelFormAction.CallParentActions;

-import org.ofbiz.widget.form.ModelFormField;

-import org.ofbiz.widget.form.ModelFormField.CheckField;

-import org.ofbiz.widget.form.ModelFormField.ContainerField;

-import org.ofbiz.widget.form.ModelFormField.DateFindField;

-import org.ofbiz.widget.form.ModelFormField.DateTimeField;

-import org.ofbiz.widget.form.ModelFormField.DisplayEntityField;

-import org.ofbiz.widget.form.ModelFormField.DisplayField;

-import org.ofbiz.widget.form.ModelFormField.DropDownField;

-import org.ofbiz.widget.form.ModelFormField.FieldInfoWithOptions;

-import org.ofbiz.widget.form.ModelFormField.FileField;

-import org.ofbiz.widget.form.ModelFormField.HiddenField;

-import org.ofbiz.widget.form.ModelFormField.HyperlinkField;

-import org.ofbiz.widget.form.ModelFormField.IgnoredField;

-import org.ofbiz.widget.form.ModelFormField.ImageField;

-import org.ofbiz.widget.form.ModelFormField.LookupField;

-import org.ofbiz.widget.form.ModelFormField.PasswordField;

-import org.ofbiz.widget.form.ModelFormField.RadioField;

-import org.ofbiz.widget.form.ModelFormField.RangeFindField;

-import org.ofbiz.widget.form.ModelFormField.ResetField;

-import org.ofbiz.widget.form.ModelFormField.SubmitField;

-import org.ofbiz.widget.form.ModelFormField.TextField;

-import org.ofbiz.widget.form.ModelFormField.TextFindField;

-import org.ofbiz.widget.form.ModelFormField.TextareaField;

-import org.ofbiz.widget.menu.ModelMenu;

-import org.ofbiz.widget.menu.ModelMenuAction;

-import org.ofbiz.widget.menu.ModelMenuItem;

-import org.ofbiz.widget.screen.HtmlWidget;

-import org.ofbiz.widget.screen.HtmlWidget.HtmlTemplate;

-import org.ofbiz.widget.screen.HtmlWidget.HtmlTemplateDecorator;

-import org.ofbiz.widget.screen.HtmlWidget.HtmlTemplateDecoratorSection;

-import org.ofbiz.widget.screen.IterateSectionWidget;

-import org.ofbiz.widget.screen.ModelScreen;

-import org.ofbiz.widget.screen.ModelScreenWidget;

-import org.ofbiz.widget.screen.ModelScreenWidget.Column;

-import org.ofbiz.widget.screen.ModelScreenWidget.ColumnContainer;

-import org.ofbiz.widget.screen.ModelScreenWidget.Container;

-import org.ofbiz.widget.screen.ModelScreenWidget.Content;

-import org.ofbiz.widget.screen.ModelScreenWidget.DecoratorScreen;

-import org.ofbiz.widget.screen.ModelScreenWidget.DecoratorSection;

-import org.ofbiz.widget.screen.ModelScreenWidget.DecoratorSectionInclude;

-import org.ofbiz.widget.screen.ModelScreenWidget.Form;

-import org.ofbiz.widget.screen.ModelScreenWidget.HorizontalSeparator;

-import org.ofbiz.widget.screen.ModelScreenWidget.ScreenImage;

-import org.ofbiz.widget.screen.ModelScreenWidget.IncludeScreen;

-import org.ofbiz.widget.screen.ModelScreenWidget.Label;

-import org.ofbiz.widget.screen.ModelScreenWidget.ScreenLink;

-import org.ofbiz.widget.screen.ModelScreenWidget.Menu;

-import org.ofbiz.widget.screen.ModelScreenWidget.PlatformSpecific;

-import org.ofbiz.widget.screen.ModelScreenWidget.PortalPage;

-import org.ofbiz.widget.screen.ModelScreenWidget.Screenlet;

-import org.ofbiz.widget.screen.ModelScreenWidget.Section;

-import org.ofbiz.widget.screen.ModelScreenWidget.Tree;

-import org.ofbiz.widget.tree.ModelTree;

-import org.ofbiz.widget.tree.ModelTree.ModelNode;

-import org.ofbiz.widget.tree.ModelTree.ModelNode.ModelSubNode;

-import org.ofbiz.widget.tree.ModelTreeAction;

+import org.ofbiz.widget.model.AbstractModelAction.EntityAnd;

+import org.ofbiz.widget.model.AbstractModelAction.EntityCondition;

+import org.ofbiz.widget.model.AbstractModelAction.EntityOne;

+import org.ofbiz.widget.model.AbstractModelAction.GetRelated;

+import org.ofbiz.widget.model.AbstractModelAction.GetRelatedOne;

+import org.ofbiz.widget.model.AbstractModelAction.PropertyMap;

+import org.ofbiz.widget.model.AbstractModelAction.PropertyToField;

+import org.ofbiz.widget.model.AbstractModelAction.Script;

+import org.ofbiz.widget.model.AbstractModelAction.Service;

+import org.ofbiz.widget.model.AbstractModelAction.SetField;

+import org.ofbiz.widget.model.FieldInfo;

+import org.ofbiz.widget.model.HtmlWidget;

+import org.ofbiz.widget.model.HtmlWidget.HtmlTemplate;

+import org.ofbiz.widget.model.HtmlWidget.HtmlTemplateDecorator;

+import org.ofbiz.widget.model.HtmlWidget.HtmlTemplateDecoratorSection;

+import org.ofbiz.widget.model.IterateSectionWidget;

+import org.ofbiz.widget.model.ModelAction;

+import org.ofbiz.widget.model.ModelActionVisitor;

+import org.ofbiz.widget.model.ModelFieldVisitor;

+import org.ofbiz.widget.model.ModelForm;

+import org.ofbiz.widget.model.ModelForm.AltTarget;

+import org.ofbiz.widget.model.ModelForm.AutoFieldsEntity;

+import org.ofbiz.widget.model.ModelForm.AutoFieldsService;

+import org.ofbiz.widget.model.ModelFormAction;

+import org.ofbiz.widget.model.ModelFormAction.CallParentActions;

+import org.ofbiz.widget.model.ModelFormField;

+import org.ofbiz.widget.model.ModelFormField.CheckField;

+import org.ofbiz.widget.model.ModelFormField.ContainerField;

+import org.ofbiz.widget.model.ModelFormField.DateFindField;

+import org.ofbiz.widget.model.ModelFormField.DateTimeField;

+import org.ofbiz.widget.model.ModelFormField.DisplayEntityField;

+import org.ofbiz.widget.model.ModelFormField.DisplayField;

+import org.ofbiz.widget.model.ModelFormField.DropDownField;

+import org.ofbiz.widget.model.ModelFormField.FieldInfoWithOptions;

+import org.ofbiz.widget.model.ModelFormField.FileField;

+import org.ofbiz.widget.model.ModelFormField.HiddenField;

+import org.ofbiz.widget.model.ModelFormField.HyperlinkField;

+import org.ofbiz.widget.model.ModelFormField.IgnoredField;

+import org.ofbiz.widget.model.ModelFormField.ImageField;

+import org.ofbiz.widget.model.ModelFormField.LookupField;

+import org.ofbiz.widget.model.ModelFormField.PasswordField;

+import org.ofbiz.widget.model.ModelFormField.RadioField;

+import org.ofbiz.widget.model.ModelFormField.RangeFindField;

+import org.ofbiz.widget.model.ModelFormField.ResetField;

+import org.ofbiz.widget.model.ModelFormField.SubmitField;

+import org.ofbiz.widget.model.ModelFormField.TextField;

+import org.ofbiz.widget.model.ModelFormField.TextFindField;

+import org.ofbiz.widget.model.ModelFormField.TextareaField;

+import org.ofbiz.widget.model.ModelMenu;

+import org.ofbiz.widget.model.ModelMenuAction;

+import org.ofbiz.widget.model.ModelMenuItem;

+import org.ofbiz.widget.model.ModelScreen;

+import org.ofbiz.widget.model.ModelScreenWidget;

+import org.ofbiz.widget.model.ModelScreenWidget.Column;

+import org.ofbiz.widget.model.ModelScreenWidget.ColumnContainer;

+import org.ofbiz.widget.model.ModelScreenWidget.Container;

+import org.ofbiz.widget.model.ModelScreenWidget.Content;

+import org.ofbiz.widget.model.ModelScreenWidget.DecoratorScreen;

+import org.ofbiz.widget.model.ModelScreenWidget.DecoratorSection;

+import org.ofbiz.widget.model.ModelScreenWidget.DecoratorSectionInclude;

+import org.ofbiz.widget.model.ModelScreenWidget.Form;

+import org.ofbiz.widget.model.ModelScreenWidget.HorizontalSeparator;

+import org.ofbiz.widget.model.ModelScreenWidget.IncludeScreen;

+import org.ofbiz.widget.model.ModelScreenWidget.Label;

+import org.ofbiz.widget.model.ModelScreenWidget.Menu;

+import org.ofbiz.widget.model.ModelScreenWidget.PlatformSpecific;

+import org.ofbiz.widget.model.ModelScreenWidget.PortalPage;

+import org.ofbiz.widget.model.ModelScreenWidget.ScreenImage;

+import org.ofbiz.widget.model.ModelScreenWidget.ScreenLink;

+import org.ofbiz.widget.model.ModelScreenWidget.Screenlet;

+import org.ofbiz.widget.model.ModelScreenWidget.Section;

+import org.ofbiz.widget.model.ModelScreenWidget.Tree;

+import org.ofbiz.widget.model.ModelTree;

+import org.ofbiz.widget.model.ModelTree.ModelNode;

+import org.ofbiz.widget.model.ModelTree.ModelNode.ModelSubNode;

+import org.ofbiz.widget.model.ModelTreeAction;

+import org.ofbiz.widget.model.ModelWidgetVisitor;

 

 /**

  * An object that gathers artifact information from screen widgets.

diff --git a/framework/widget/src/org/ofbiz/widget/ContentWorkerInterface.java b/framework/widget/src/org/ofbiz/widget/content/ContentWorkerInterface.java
similarity index 98%
rename from framework/widget/src/org/ofbiz/widget/ContentWorkerInterface.java
rename to framework/widget/src/org/ofbiz/widget/content/ContentWorkerInterface.java
index cceb618..b83f6db 100644
--- a/framework/widget/src/org/ofbiz/widget/ContentWorkerInterface.java
+++ b/framework/widget/src/org/ofbiz/widget/content/ContentWorkerInterface.java
@@ -1,48 +1,48 @@
-/*******************************************************************************
- * 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;
-
-import java.io.IOException;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-
-import org.ofbiz.base.util.GeneralException;
-import org.ofbiz.entity.Delegator;
-import org.ofbiz.entity.GenericEntityException;
-import org.ofbiz.entity.GenericValue;
-import org.ofbiz.service.LocalDispatcher;
-
-/**
- * ContentWorkerInterface
- */
-public interface ContentWorkerInterface {
-
-    // helper methods
-    public GenericValue getCurrentContentExt(Delegator delegator, List<Map<String, ? extends Object>> trail, GenericValue userLogin, Map<String, Object> ctx, Boolean nullThruDatesOnly, String contentAssocPredicateId)  throws GeneralException;
-    public GenericValue getWebSitePublishPointExt(Delegator delegator, String contentId, boolean ignoreCache) throws GenericEntityException;
-    public String getMimeTypeIdExt(Delegator delegator, GenericValue view, Map<String, Object> ctx);
-
-    // new rendering methods
-    public void renderContentAsTextExt(LocalDispatcher dispatcher, Delegator delegator, String contentId, Appendable out, Map<String, Object> templateContext, Locale locale, String mimeTypeId, boolean cache) throws GeneralException, IOException;
-    public String renderContentAsTextExt(LocalDispatcher dispatcher, Delegator delegator, String contentId, Map<String, Object> templateContext, Locale locale, String mimeTypeId, boolean cache) throws GeneralException, IOException;
-
-    public void renderSubContentAsTextExt(LocalDispatcher dispatcher, Delegator delegator, String contentId, Appendable out, String mapKey, Map<String, Object> templateContext, Locale locale, String mimeTypeId, boolean cache) throws GeneralException, IOException;
-    public String renderSubContentAsTextExt(LocalDispatcher dispatcher, Delegator delegator, String contentId, String mapKey, Map<String, Object> templateContext, Locale locale, String mimeTypeId, boolean cache) throws GeneralException, IOException;
-}
+/*******************************************************************************

+ * 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.content;

+

+import java.io.IOException;

+import java.util.List;

+import java.util.Locale;

+import java.util.Map;

+

+import org.ofbiz.base.util.GeneralException;

+import org.ofbiz.entity.Delegator;

+import org.ofbiz.entity.GenericEntityException;

+import org.ofbiz.entity.GenericValue;

+import org.ofbiz.service.LocalDispatcher;

+

+/**

+ * ContentWorkerInterface

+ */

+public interface ContentWorkerInterface {

+

+    // helper methods

+    public GenericValue getCurrentContentExt(Delegator delegator, List<Map<String, ? extends Object>> trail, GenericValue userLogin, Map<String, Object> ctx, Boolean nullThruDatesOnly, String contentAssocPredicateId)  throws GeneralException;

+    public GenericValue getWebSitePublishPointExt(Delegator delegator, String contentId, boolean ignoreCache) throws GenericEntityException;

+    public String getMimeTypeIdExt(Delegator delegator, GenericValue view, Map<String, Object> ctx);

+

+    // new rendering methods

+    public void renderContentAsTextExt(LocalDispatcher dispatcher, Delegator delegator, String contentId, Appendable out, Map<String, Object> templateContext, Locale locale, String mimeTypeId, boolean cache) throws GeneralException, IOException;

+    public String renderContentAsTextExt(LocalDispatcher dispatcher, Delegator delegator, String contentId, Map<String, Object> templateContext, Locale locale, String mimeTypeId, boolean cache) throws GeneralException, IOException;

+

+    public void renderSubContentAsTextExt(LocalDispatcher dispatcher, Delegator delegator, String contentId, Appendable out, String mapKey, Map<String, Object> templateContext, Locale locale, String mimeTypeId, boolean cache) throws GeneralException, IOException;

+    public String renderSubContentAsTextExt(LocalDispatcher dispatcher, Delegator delegator, String contentId, String mapKey, Map<String, Object> templateContext, Locale locale, String mimeTypeId, boolean cache) throws GeneralException, IOException;

+}

diff --git a/framework/widget/src/org/ofbiz/widget/DataResourceWorkerInterface.java b/framework/widget/src/org/ofbiz/widget/content/DataResourceWorkerInterface.java
similarity index 97%
rename from framework/widget/src/org/ofbiz/widget/DataResourceWorkerInterface.java
rename to framework/widget/src/org/ofbiz/widget/content/DataResourceWorkerInterface.java
index 155ace3..e0c505e 100644
--- a/framework/widget/src/org/ofbiz/widget/DataResourceWorkerInterface.java
+++ b/framework/widget/src/org/ofbiz/widget/content/DataResourceWorkerInterface.java
@@ -1,37 +1,37 @@
-/*******************************************************************************
- * 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;
-
-import java.io.IOException;
-import java.util.Locale;
-import java.util.Map;
-
-import org.ofbiz.base.util.GeneralException;
-import org.ofbiz.entity.Delegator;
-
-/**
- * ContentWorkerInterface
- */
-public interface DataResourceWorkerInterface {
-    public String renderDataResourceAsTextExt(Delegator delegator, String dataResourceId, Map<String, Object> templateContext,
-            Locale locale, String targetMimeTypeId, boolean cache) throws GeneralException, IOException;
-
-    public void renderDataResourceAsTextExt(Delegator delegator, String dataResourceId, Appendable out, Map<String, Object> templateContext,
-            Locale locale, String targetMimeTypeId, boolean cache) throws GeneralException, IOException;
-}
+/*******************************************************************************

+ * 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.content;

+

+import java.io.IOException;

+import java.util.Locale;

+import java.util.Map;

+

+import org.ofbiz.base.util.GeneralException;

+import org.ofbiz.entity.Delegator;

+

+/**

+ * ContentWorkerInterface

+ */

+public interface DataResourceWorkerInterface {

+    public String renderDataResourceAsTextExt(Delegator delegator, String dataResourceId, Map<String, Object> templateContext,

+            Locale locale, String targetMimeTypeId, boolean cache) throws GeneralException, IOException;

+

+    public void renderDataResourceAsTextExt(Delegator delegator, String dataResourceId, Appendable out, Map<String, Object> templateContext,

+            Locale locale, String targetMimeTypeId, boolean cache) throws GeneralException, IOException;

+}

diff --git a/framework/widget/src/org/ofbiz/widget/WidgetContentWorker.java b/framework/widget/src/org/ofbiz/widget/content/WidgetContentWorker.java
similarity index 97%
rename from framework/widget/src/org/ofbiz/widget/WidgetContentWorker.java
rename to framework/widget/src/org/ofbiz/widget/content/WidgetContentWorker.java
index c094d19..edea2cf 100644
--- a/framework/widget/src/org/ofbiz/widget/WidgetContentWorker.java
+++ b/framework/widget/src/org/ofbiz/widget/content/WidgetContentWorker.java
@@ -1,42 +1,42 @@
-/*******************************************************************************
- * 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;
-
-import org.ofbiz.base.util.Debug;
-
-/**
- * WidgetContentWorker Class
- */
-public class WidgetContentWorker {
-    public static final String module = WidgetContentWorker.class.getName();
-    public static ContentWorkerInterface contentWorker = null;
-    static {
-        try {
-            ClassLoader loader = Thread.currentThread().getContextClassLoader();
-            // note: loadClass is necessary for these since this class doesn't know anything about them at compile time
-            contentWorker = (ContentWorkerInterface) loader.loadClass("org.ofbiz.content.content.ContentWorker").newInstance();
-        } catch (ClassNotFoundException e) {
-            Debug.logError(e, "Could not pre-initialize dynamically loaded class: ", module);
-        } catch (IllegalAccessException e) {
-            Debug.logError(e, "Could not pre-initialize dynamically loaded class: ", module);
-        } catch (InstantiationException e) {
-            Debug.logError(e, "Could not pre-initialize dynamically loaded class: ", module);
-        }
-    }
-}
+/*******************************************************************************

+ * 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.content;

+

+import org.ofbiz.base.util.Debug;

+

+/**

+ * WidgetContentWorker Class

+ */

+public class WidgetContentWorker {

+    public static final String module = WidgetContentWorker.class.getName();

+    public static ContentWorkerInterface contentWorker = null;

+    static {

+        try {

+            ClassLoader loader = Thread.currentThread().getContextClassLoader();

+            // note: loadClass is necessary for these since this class doesn't know anything about them at compile time

+            contentWorker = (ContentWorkerInterface) loader.loadClass("org.ofbiz.content.content.ContentWorker").newInstance();

+        } catch (ClassNotFoundException e) {

+            Debug.logError(e, "Could not pre-initialize dynamically loaded class: ", module);

+        } catch (IllegalAccessException e) {

+            Debug.logError(e, "Could not pre-initialize dynamically loaded class: ", module);

+        } catch (InstantiationException e) {

+            Debug.logError(e, "Could not pre-initialize dynamically loaded class: ", module);

+        }

+    }

+}

diff --git a/framework/widget/src/org/ofbiz/widget/WidgetDataResourceWorker.java b/framework/widget/src/org/ofbiz/widget/content/WidgetDataResourceWorker.java
similarity index 98%
rename from framework/widget/src/org/ofbiz/widget/WidgetDataResourceWorker.java
rename to framework/widget/src/org/ofbiz/widget/content/WidgetDataResourceWorker.java
index d19f427..afe2418 100644
--- a/framework/widget/src/org/ofbiz/widget/WidgetDataResourceWorker.java
+++ b/framework/widget/src/org/ofbiz/widget/content/WidgetDataResourceWorker.java
@@ -1,42 +1,42 @@
-/*******************************************************************************
- * 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;
-
-import org.ofbiz.base.util.Debug;
-
-/**
- * WidgetContentWorker Class
- */
-public class WidgetDataResourceWorker {
-    public static final String module = WidgetDataResourceWorker.class.getName();
-    public static DataResourceWorkerInterface dataresourceWorker = null;
-    static {
-        try {
-            ClassLoader loader = Thread.currentThread().getContextClassLoader();
-            // note: loadClass is necessary for these since this class doesn't know anything about them at compile time
-            dataresourceWorker = (DataResourceWorkerInterface) loader.loadClass("org.ofbiz.content.data.DataResourceWorker").newInstance();
-        } catch (ClassNotFoundException e) {
-            Debug.logError(e, "Could not pre-initialize dynamically loaded class: ", module);
-        } catch (IllegalAccessException e) {
-            Debug.logError(e, "Could not pre-initialize dynamically loaded class: ", module);
-        } catch (InstantiationException e) {
-            Debug.logError(e, "Could not pre-initialize dynamically loaded class: ", module);
-        }
-    }
-}
+/*******************************************************************************

+ * 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.content;

+

+import org.ofbiz.base.util.Debug;

+

+/**

+ * WidgetContentWorker Class

+ */

+public class WidgetDataResourceWorker {

+    public static final String module = WidgetDataResourceWorker.class.getName();

+    public static DataResourceWorkerInterface dataresourceWorker = null;

+    static {

+        try {

+            ClassLoader loader = Thread.currentThread().getContextClassLoader();

+            // note: loadClass is necessary for these since this class doesn't know anything about them at compile time

+            dataresourceWorker = (DataResourceWorkerInterface) loader.loadClass("org.ofbiz.content.data.DataResourceWorker").newInstance();

+        } catch (ClassNotFoundException e) {

+            Debug.logError(e, "Could not pre-initialize dynamically loaded class: ", module);

+        } catch (IllegalAccessException e) {

+            Debug.logError(e, "Could not pre-initialize dynamically loaded class: ", module);

+        } catch (InstantiationException e) {

+            Debug.logError(e, "Could not pre-initialize dynamically loaded class: ", module);

+        }

+    }

+}

diff --git a/framework/widget/src/org/ofbiz/widget/AbstractModelAction.java b/framework/widget/src/org/ofbiz/widget/model/AbstractModelAction.java
similarity index 99%
rename from framework/widget/src/org/ofbiz/widget/AbstractModelAction.java
rename to framework/widget/src/org/ofbiz/widget/model/AbstractModelAction.java
index 0aacb3e..7ec655b 100644
--- a/framework/widget/src/org/ofbiz/widget/AbstractModelAction.java
+++ b/framework/widget/src/org/ofbiz/widget/model/AbstractModelAction.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations

  * under the License.

  *******************************************************************************/

-package org.ofbiz.widget;

+package org.ofbiz.widget.model;

 

 import java.io.Serializable;

 import java.text.MessageFormat;

@@ -58,7 +58,7 @@
 import org.ofbiz.service.DispatchContext;

 import org.ofbiz.service.GenericServiceException;

 import org.ofbiz.service.ModelService;

-import org.ofbiz.widget.xml.XmlWidgetActionVisitor;

+import org.ofbiz.widget.WidgetWorker;

 import org.w3c.dom.Element;

 

 /**

diff --git a/framework/widget/src/org/ofbiz/widget/AbstractModelCondition.java b/framework/widget/src/org/ofbiz/widget/model/AbstractModelCondition.java
similarity index 99%
rename from framework/widget/src/org/ofbiz/widget/AbstractModelCondition.java
rename to framework/widget/src/org/ofbiz/widget/model/AbstractModelCondition.java
index 7cb74b3..d752f0b 100644
--- a/framework/widget/src/org/ofbiz/widget/AbstractModelCondition.java
+++ b/framework/widget/src/org/ofbiz/widget/model/AbstractModelCondition.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations

  * under the License.

  *******************************************************************************/

-package org.ofbiz.widget;

+package org.ofbiz.widget.model;

 

 import java.io.Serializable;

 import java.lang.reflect.Method;

@@ -50,7 +50,6 @@
 import org.ofbiz.service.LocalDispatcher;

 import org.ofbiz.service.ModelService;

 import org.ofbiz.service.ServiceUtil;

-import org.ofbiz.widget.xml.*;

 import org.w3c.dom.Element;

 

 /**

diff --git a/framework/widget/src/org/ofbiz/widget/CommonWidgetModels.java b/framework/widget/src/org/ofbiz/widget/model/CommonWidgetModels.java
similarity index 99%
rename from framework/widget/src/org/ofbiz/widget/CommonWidgetModels.java
rename to framework/widget/src/org/ofbiz/widget/model/CommonWidgetModels.java
index dfd9f87..b538397 100644
--- a/framework/widget/src/org/ofbiz/widget/CommonWidgetModels.java
+++ b/framework/widget/src/org/ofbiz/widget/model/CommonWidgetModels.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations

  * under the License.

  *******************************************************************************/

-package org.ofbiz.widget;

+package org.ofbiz.widget.model;

 

 import java.math.BigDecimal;

 import java.text.DateFormat;

diff --git a/framework/widget/src/org/ofbiz/widget/form/FieldInfo.java b/framework/widget/src/org/ofbiz/widget/model/FieldInfo.java
similarity index 97%
rename from framework/widget/src/org/ofbiz/widget/form/FieldInfo.java
rename to framework/widget/src/org/ofbiz/widget/model/FieldInfo.java
index dcb8ea3..7bc47b3 100644
--- a/framework/widget/src/org/ofbiz/widget/form/FieldInfo.java
+++ b/framework/widget/src/org/ofbiz/widget/model/FieldInfo.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations

  * under the License.

  *******************************************************************************/

-package org.ofbiz.widget.form;

+package org.ofbiz.widget.model;

 

 import java.io.IOException;

 import java.util.Collections;

@@ -24,8 +24,7 @@
 import java.util.Map;

 

 import org.ofbiz.base.util.Debug;

-import org.ofbiz.widget.ModelFieldVisitor;

-import org.ofbiz.widget.xml.XmlWidgetFieldVisitor;

+import org.ofbiz.widget.renderer.FormStringRenderer;

 import org.w3c.dom.Element;

 

 /**

diff --git a/framework/widget/src/org/ofbiz/widget/form/FormFactory.java b/framework/widget/src/org/ofbiz/widget/model/FormFactory.java
similarity index 99%
rename from framework/widget/src/org/ofbiz/widget/form/FormFactory.java
rename to framework/widget/src/org/ofbiz/widget/model/FormFactory.java
index 0729275..a9ba4ad 100644
--- a/framework/widget/src/org/ofbiz/widget/form/FormFactory.java
+++ b/framework/widget/src/org/ofbiz/widget/model/FormFactory.java
@@ -1,131 +1,131 @@
-/*******************************************************************************
- * 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.net.URL;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import javax.servlet.ServletContext;
-import javax.servlet.http.HttpServletRequest;
-import javax.xml.parsers.ParserConfigurationException;
-
-import org.ofbiz.base.location.FlexibleLocation;
-import org.ofbiz.base.util.UtilHttp;
-import org.ofbiz.base.util.UtilXml;
-import org.ofbiz.base.util.cache.UtilCache;
-import org.ofbiz.entity.Delegator;
-import org.ofbiz.entity.model.ModelReader;
-import org.ofbiz.service.DispatchContext;
-import org.ofbiz.service.LocalDispatcher;
-
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-import org.xml.sax.SAXException;
-
-
-/**
- * Widget Library - Form factory class
- */
-public class FormFactory {
-
-    public static final String module = FormFactory.class.getName();
-    private static final UtilCache<String, ModelForm> formLocationCache = UtilCache.createUtilCache("widget.form.locationResource", 0, 0, false);
-    private static final UtilCache<String, ModelForm> formWebappCache = UtilCache.createUtilCache("widget.form.webappResource", 0, 0, false);
-
-    public static Map<String, ModelForm> getFormsFromLocation(String resourceName, ModelReader entityModelReader, DispatchContext dispatchContext)
-            throws IOException, SAXException, ParserConfigurationException {
-        URL formFileUrl = FlexibleLocation.resolveLocation(resourceName);
-        Document formFileDoc = UtilXml.readXmlDocument(formFileUrl, true, true);
-        return readFormDocument(formFileDoc, entityModelReader, dispatchContext, resourceName);
-    }
-
-    public static ModelForm getFormFromLocation(String resourceName, String formName, ModelReader entityModelReader, DispatchContext dispatchContext)
-            throws IOException, SAXException, ParserConfigurationException {
-        StringBuilder sb = new StringBuilder(dispatchContext.getDelegator().getDelegatorName());
-        sb.append(":").append(resourceName).append("#").append(formName);
-        String cacheKey = sb.toString();
-        ModelForm modelForm = formLocationCache.get(cacheKey);
-        if (modelForm == null) {
-            URL formFileUrl = FlexibleLocation.resolveLocation(resourceName);
-            Document formFileDoc = UtilXml.readXmlDocument(formFileUrl, true, true);
-            if (formFileDoc == null) {
-                throw new IllegalArgumentException("Could not find resource [" + resourceName + "]");
-            }
-            modelForm = createModelForm(formFileDoc, entityModelReader, dispatchContext, resourceName, formName);
-            modelForm = formLocationCache.putIfAbsentAndGet(cacheKey, modelForm);
-        }
-        if (modelForm == null) {
-            throw new IllegalArgumentException("Could not find form with name [" + formName + "] in class resource [" + resourceName + "]");
-        }
-        return modelForm;
-    }
-
-    public static ModelForm getFormFromWebappContext(String resourceName, String formName, HttpServletRequest request)
-            throws IOException, SAXException, ParserConfigurationException {
-        String webappName = UtilHttp.getApplicationName(request);
-        String cacheKey = webappName + "::" + resourceName + "::" + formName;
-        ModelForm modelForm = formWebappCache.get(cacheKey);
-        if (modelForm == null) {
-            ServletContext servletContext = (ServletContext) request.getAttribute("servletContext");
-            Delegator delegator = (Delegator) request.getAttribute("delegator");
-            LocalDispatcher dispatcher = (LocalDispatcher) request.getAttribute("dispatcher");
-            URL formFileUrl = servletContext.getResource(resourceName);
-            Document formFileDoc = UtilXml.readXmlDocument(formFileUrl, true, true);
-            Element formElement = UtilXml.firstChildElement(formFileDoc.getDocumentElement(), "form", "name", formName);
-            modelForm = new ModelForm(formElement, resourceName, delegator.getModelReader(), dispatcher.getDispatchContext());
-            modelForm = formWebappCache.putIfAbsentAndGet(cacheKey, modelForm);
-        }
-        if (modelForm == null) {
-            throw new IllegalArgumentException("Could not find form with name [" + formName + "] in webapp resource [" + resourceName + "] in the webapp [" + webappName + "]");
-        }
-        return modelForm;
-    }
-
-    public static Map<String, ModelForm> readFormDocument(Document formFileDoc, ModelReader entityModelReader, DispatchContext dispatchContext, String formLocation) {
-        Map<String, ModelForm> modelFormMap = new HashMap<String, ModelForm>();
-        if (formFileDoc != null) {
-            // read document and construct ModelForm for each form element
-            Element rootElement = formFileDoc.getDocumentElement();
-            List<? extends Element> formElements = UtilXml.childElementList(rootElement, "form");
-            for (Element formElement : formElements) {
-                String formName = formElement.getAttribute("name");
-                String cacheKey = formLocation + "#" + formName;
-                ModelForm modelForm = formLocationCache.get(cacheKey);
-                if (modelForm == null) {
-                    modelForm = createModelForm(formElement, entityModelReader, dispatchContext, formLocation, formName);
-                    modelForm = formLocationCache.putIfAbsentAndGet(cacheKey, modelForm);
-                }
-                modelFormMap.put(formName, modelForm);
-            }
-        }
-        return modelFormMap;
-    }
-
-    public static ModelForm createModelForm(Document formFileDoc, ModelReader entityModelReader, DispatchContext dispatchContext, String formLocation, String formName) {
-        Element formElement = UtilXml.firstChildElement(formFileDoc.getDocumentElement(), "form", "name", formName);
-        return createModelForm(formElement, entityModelReader, dispatchContext, formLocation, formName);
-    }
-
-    public static ModelForm createModelForm(Element formElement, ModelReader entityModelReader, DispatchContext dispatchContext, String formLocation, String formName) {
-        ModelForm modelForm = new ModelForm(formElement, formLocation, entityModelReader, dispatchContext);
-        return modelForm;
-    }
-}
+/*******************************************************************************

+ * Licensed to the Apache Software Foundation (ASF) under one

+ * or more contributor license agreements.  See the NOTICE file

+ * distributed with this work for additional information

+ * regarding copyright ownership.  The ASF licenses this file

+ * to you under the Apache License, Version 2.0 (the

+ * "License"); you may not use this file except in compliance

+ * with the License.  You may obtain a copy of the License at

+ *

+ * http://www.apache.org/licenses/LICENSE-2.0

+ *

+ * Unless required by applicable law or agreed to in writing,

+ * software distributed under the License is distributed on an

+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY

+ * KIND, either express or implied.  See the License for the

+ * specific language governing permissions and limitations

+ * under the License.

+ *******************************************************************************/

+package org.ofbiz.widget.model;

+

+import java.io.IOException;

+import java.net.URL;

+import java.util.HashMap;

+import java.util.List;

+import java.util.Map;

+

+import javax.servlet.ServletContext;

+import javax.servlet.http.HttpServletRequest;

+import javax.xml.parsers.ParserConfigurationException;

+

+import org.ofbiz.base.location.FlexibleLocation;

+import org.ofbiz.base.util.UtilHttp;

+import org.ofbiz.base.util.UtilXml;

+import org.ofbiz.base.util.cache.UtilCache;

+import org.ofbiz.entity.Delegator;

+import org.ofbiz.entity.model.ModelReader;

+import org.ofbiz.service.DispatchContext;

+import org.ofbiz.service.LocalDispatcher;

+import org.w3c.dom.Document;

+import org.w3c.dom.Element;

+import org.xml.sax.SAXException;

+

+

+/**

+ * Widget Library - Form factory class

+ */

+public class FormFactory {

+

+    public static final String module = FormFactory.class.getName();

+    private static final UtilCache<String, ModelForm> formLocationCache = UtilCache.createUtilCache("widget.form.locationResource", 0, 0, false);

+    private static final UtilCache<String, ModelForm> formWebappCache = UtilCache.createUtilCache("widget.form.webappResource", 0, 0, false);

+

+    public static Map<String, ModelForm> getFormsFromLocation(String resourceName, ModelReader entityModelReader, DispatchContext dispatchContext)

+            throws IOException, SAXException, ParserConfigurationException {

+        URL formFileUrl = FlexibleLocation.resolveLocation(resourceName);

+        Document formFileDoc = UtilXml.readXmlDocument(formFileUrl, true, true);

+        return readFormDocument(formFileDoc, entityModelReader, dispatchContext, resourceName);

+    }

+

+    public static ModelForm getFormFromLocation(String resourceName, String formName, ModelReader entityModelReader, DispatchContext dispatchContext)

+            throws IOException, SAXException, ParserConfigurationException {

+        StringBuilder sb = new StringBuilder(dispatchContext.getDelegator().getDelegatorName());

+        sb.append(":").append(resourceName).append("#").append(formName);

+        String cacheKey = sb.toString();

+        ModelForm modelForm = formLocationCache.get(cacheKey);

+        if (modelForm == null) {

+            URL formFileUrl = FlexibleLocation.resolveLocation(resourceName);

+            Document formFileDoc = UtilXml.readXmlDocument(formFileUrl, true, true);

+            if (formFileDoc == null) {

+                throw new IllegalArgumentException("Could not find resource [" + resourceName + "]");

+            }

+            modelForm = createModelForm(formFileDoc, entityModelReader, dispatchContext, resourceName, formName);

+            modelForm = formLocationCache.putIfAbsentAndGet(cacheKey, modelForm);

+        }

+        if (modelForm == null) {

+            throw new IllegalArgumentException("Could not find form with name [" + formName + "] in class resource [" + resourceName + "]");

+        }

+        return modelForm;

+    }

+

+    public static ModelForm getFormFromWebappContext(String resourceName, String formName, HttpServletRequest request)

+            throws IOException, SAXException, ParserConfigurationException {

+        String webappName = UtilHttp.getApplicationName(request);

+        String cacheKey = webappName + "::" + resourceName + "::" + formName;

+        ModelForm modelForm = formWebappCache.get(cacheKey);

+        if (modelForm == null) {

+            ServletContext servletContext = (ServletContext) request.getAttribute("servletContext");

+            Delegator delegator = (Delegator) request.getAttribute("delegator");

+            LocalDispatcher dispatcher = (LocalDispatcher) request.getAttribute("dispatcher");

+            URL formFileUrl = servletContext.getResource(resourceName);

+            Document formFileDoc = UtilXml.readXmlDocument(formFileUrl, true, true);

+            Element formElement = UtilXml.firstChildElement(formFileDoc.getDocumentElement(), "form", "name", formName);

+            modelForm = new ModelForm(formElement, resourceName, delegator.getModelReader(), dispatcher.getDispatchContext());

+            modelForm = formWebappCache.putIfAbsentAndGet(cacheKey, modelForm);

+        }

+        if (modelForm == null) {

+            throw new IllegalArgumentException("Could not find form with name [" + formName + "] in webapp resource [" + resourceName + "] in the webapp [" + webappName + "]");

+        }

+        return modelForm;

+    }

+

+    public static Map<String, ModelForm> readFormDocument(Document formFileDoc, ModelReader entityModelReader, DispatchContext dispatchContext, String formLocation) {

+        Map<String, ModelForm> modelFormMap = new HashMap<String, ModelForm>();

+        if (formFileDoc != null) {

+            // read document and construct ModelForm for each form element

+            Element rootElement = formFileDoc.getDocumentElement();

+            List<? extends Element> formElements = UtilXml.childElementList(rootElement, "form");

+            for (Element formElement : formElements) {

+                String formName = formElement.getAttribute("name");

+                String cacheKey = formLocation + "#" + formName;

+                ModelForm modelForm = formLocationCache.get(cacheKey);

+                if (modelForm == null) {

+                    modelForm = createModelForm(formElement, entityModelReader, dispatchContext, formLocation, formName);

+                    modelForm = formLocationCache.putIfAbsentAndGet(cacheKey, modelForm);

+                }

+                modelFormMap.put(formName, modelForm);

+            }

+        }

+        return modelFormMap;

+    }

+

+    public static ModelForm createModelForm(Document formFileDoc, ModelReader entityModelReader, DispatchContext dispatchContext, String formLocation, String formName) {

+        Element formElement = UtilXml.firstChildElement(formFileDoc.getDocumentElement(), "form", "name", formName);

+        return createModelForm(formElement, entityModelReader, dispatchContext, formLocation, formName);

+    }

+

+    public static ModelForm createModelForm(Element formElement, ModelReader entityModelReader, DispatchContext dispatchContext, String formLocation, String formName) {

+        ModelForm modelForm = new ModelForm(formElement, formLocation, entityModelReader, dispatchContext);

+        return modelForm;

+    }

+}

diff --git a/framework/widget/src/org/ofbiz/widget/screen/HtmlWidget.java b/framework/widget/src/org/ofbiz/widget/model/HtmlWidget.java
similarity index 98%
rename from framework/widget/src/org/ofbiz/widget/screen/HtmlWidget.java
rename to framework/widget/src/org/ofbiz/widget/model/HtmlWidget.java
index c74cb2b..66bb671 100644
--- a/framework/widget/src/org/ofbiz/widget/screen/HtmlWidget.java
+++ b/framework/widget/src/org/ofbiz/widget/model/HtmlWidget.java
@@ -1,312 +1,311 @@
-/*******************************************************************************
- * 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.screen;
-
-import java.io.IOException;
-import java.net.MalformedURLException;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import org.ofbiz.base.util.Debug;
-import org.ofbiz.base.util.GeneralException;
-import org.ofbiz.base.util.StringUtil;
-import org.ofbiz.base.util.UtilCodec;
-import org.ofbiz.base.util.UtilGenerics;
-import org.ofbiz.base.util.UtilValidate;
-import org.ofbiz.base.util.UtilXml;
-import org.ofbiz.base.util.cache.UtilCache;
-import org.ofbiz.base.util.collections.MapStack;
-import org.ofbiz.base.util.string.FlexibleStringExpander;
-import org.ofbiz.base.util.template.FreeMarkerWorker;
-import org.ofbiz.widget.ModelWidget;
-import org.ofbiz.widget.ModelWidgetVisitor;
-import org.ofbiz.widget.html.HtmlWidgetRenderer;
-import org.w3c.dom.Element;
-
-import freemarker.ext.beans.BeansWrapper;
-import freemarker.ext.beans.CollectionModel;
-import freemarker.ext.beans.StringModel;
-import freemarker.template.Configuration;
-import freemarker.template.Template;
-import freemarker.template.TemplateException;
-import freemarker.template.TemplateModel;
-import freemarker.template.TemplateModelException;
-import freemarker.template.Version;
-
-/**
- * Widget Library - Screen model HTML class.
- */
-@SuppressWarnings("serial")
-public class HtmlWidget extends ModelScreenWidget {
-    public static final String module = HtmlWidget.class.getName();
-
-    private static final UtilCache<String, Template> specialTemplateCache = UtilCache.createUtilCache("widget.screen.template.ftl.general", 0, 0, false);
-    protected static Configuration specialConfig = FreeMarkerWorker.makeConfiguration(new ExtendedWrapper(FreeMarkerWorker.version));
-
-    // not sure if this is the best way to get FTL to use my fancy MapModel derivative, but should work at least...
-    public static class ExtendedWrapper extends BeansWrapper {
-        public ExtendedWrapper(Version version) {
-            super(version);
-        }
-
-        @Override
-        public TemplateModel wrap(Object object) throws TemplateModelException {
-            // This StringHtmlWrapperForFtl option seems to be the best option
-            // and handles most things without causing too many problems
-            if (object instanceof String) {
-                return new StringHtmlWrapperForFtl((String) object, this);
-            } else if (object instanceof Collection && !(object instanceof Map)) {
-                // An additional wrapper to ensure ${aCollection} is properly encoded for html
-                return new CollectionHtmlWrapperForFtl((Collection<?>) object, this);
-            }
-            return super.wrap(object);
-        }
-    }
-
-    public static class StringHtmlWrapperForFtl extends StringModel {
-        public StringHtmlWrapperForFtl(String str, BeansWrapper wrapper) {
-            super(str, wrapper);
-        }
-        @Override
-        public String getAsString() {
-            return UtilCodec.getEncoder("html").encode(super.getAsString());
-        }
-    }
-
-    public static class CollectionHtmlWrapperForFtl extends CollectionModel {
-
-        public CollectionHtmlWrapperForFtl(Collection<?> collection, BeansWrapper wrapper) {
-            super(collection, wrapper);
-        }
-
-        @Override
-        public String getAsString() {
-            return UtilCodec.getEncoder("html").encode(super.getAsString());
-        }
-
-    }
-
-    // End Static, begin class section
-
-    private final List<ModelScreenWidget> subWidgets;
-
-    public HtmlWidget(ModelScreen modelScreen, Element htmlElement) {
-        super(modelScreen, htmlElement);
-        List<? extends Element> childElementList = UtilXml.childElementList(htmlElement);
-        if (childElementList.isEmpty()) {
-            this.subWidgets = Collections.emptyList();
-        } else {
-            List<ModelScreenWidget> subWidgets = new ArrayList<ModelScreenWidget>(childElementList.size());
-            for (Element childElement : childElementList) {
-                if ("html-template".equals(childElement.getNodeName())) {
-                    subWidgets.add(new HtmlTemplate(modelScreen, childElement));
-                } else if ("html-template-decorator".equals(childElement.getNodeName())) {
-                    subWidgets.add(new HtmlTemplateDecorator(modelScreen, childElement));
-                } else {
-                    throw new IllegalArgumentException("Tag not supported under the platform-specific -> html tag with name: "
-                            + childElement.getNodeName());
-                }
-            }
-            this.subWidgets = Collections.unmodifiableList(subWidgets);
-        }
-    }
-
-    public List<ModelScreenWidget> getSubWidgets() {
-        return subWidgets;
-    }
-
-    @Override
-    public void renderWidgetString(Appendable writer, Map<String, Object> context, ScreenStringRenderer screenStringRenderer) throws GeneralException, IOException {
-        for (ModelScreenWidget subWidget : subWidgets) {
-            subWidget.renderWidgetString(writer, context, screenStringRenderer);
-        }
-    }
-
-    public static void renderHtmlTemplate(Appendable writer, FlexibleStringExpander locationExdr, Map<String, Object> context) {
-        String location = locationExdr.expandString(context);
-        //Debug.logInfo("Rendering template at location [" + location + "] with context: \n" + context, module);
-
-        if (UtilValidate.isEmpty(location)) {
-            throw new IllegalArgumentException("Template location is empty");
-        }
-
-        if (location.endsWith(".ftl")) {
-            try {
-                Map<String, ? extends Object> parameters = UtilGenerics.checkMap(context.get("parameters"));
-                boolean insertWidgetBoundaryComments = ModelWidget.widgetBoundaryCommentsEnabled(parameters);
-                if (insertWidgetBoundaryComments) {
-                    writer.append(HtmlWidgetRenderer.formatBoundaryComment("Begin", "Template", location));
-                }
-
-                //FreeMarkerWorker.renderTemplateAtLocation(location, context, writer);
-                Template template = null;
-                if (location.endsWith(".fo.ftl")) { // FOP can't render correctly escaped characters
-                    template = FreeMarkerWorker.getTemplate(location);
-                } else {
-                    template = FreeMarkerWorker.getTemplate(location, specialTemplateCache, specialConfig);
-                }
-                FreeMarkerWorker.renderTemplate(template, context, writer);
-
-                if (insertWidgetBoundaryComments) {
-                    writer.append(HtmlWidgetRenderer.formatBoundaryComment("End", "Template", location));
-                }
-            } catch (IllegalArgumentException e) {
-                String errMsg = "Error rendering included template at location [" + location + "]: " + e.toString();
-                Debug.logError(e, errMsg, module);
-                writeError(writer, errMsg);
-            } catch (MalformedURLException e) {
-                String errMsg = "Error rendering included template at location [" + location + "]: " + e.toString();
-                Debug.logError(e, errMsg, module);
-                writeError(writer, errMsg);
-            } catch (TemplateException e) {
-                String errMsg = "Error rendering included template at location [" + location + "]: " + e.toString();
-                Debug.logError(e, errMsg, module);
-                writeError(writer, errMsg);
-            } catch (IOException e) {
-                String errMsg = "Error rendering included template at location [" + location + "]: " + e.toString();
-                Debug.logError(e, errMsg, module);
-                writeError(writer, errMsg);
-            }
-        } else {
-            throw new IllegalArgumentException("Rendering not yet supported for the template at location: " + location);
-        }
-    }
-
-    // TODO: We can make this more fancy, but for now this is very functional
-    public static void writeError(Appendable writer, String message) {
-        try {
-            writer.append(message);
-        } catch (IOException e) {
-        }
-    }
-
-    public static class HtmlTemplate extends ModelScreenWidget {
-        protected FlexibleStringExpander locationExdr;
-
-        public HtmlTemplate(ModelScreen modelScreen, Element htmlTemplateElement) {
-            super(modelScreen, htmlTemplateElement);
-            this.locationExdr = FlexibleStringExpander.getInstance(htmlTemplateElement.getAttribute("location"));
-        }
-
-        public String getLocation(Map<String, Object> context) {
-            return locationExdr.expandString(context);
-        }
-
-        @Override
-        public void renderWidgetString(Appendable writer, Map<String, Object> context, ScreenStringRenderer screenStringRenderer) {
-            renderHtmlTemplate(writer, this.locationExdr, context);
-        }
-
-        @Override
-        public void accept(ModelWidgetVisitor visitor) throws Exception {
-            visitor.visit(this);
-        }
-
-        public FlexibleStringExpander getLocationExdr() {
-            return locationExdr;
-        }
-    }
-
-    public static class HtmlTemplateDecorator extends ModelScreenWidget {
-        protected FlexibleStringExpander locationExdr;
-        protected Map<String, ModelScreenWidget> sectionMap = new HashMap<String, ModelScreenWidget>();
-
-        public HtmlTemplateDecorator(ModelScreen modelScreen, Element htmlTemplateDecoratorElement) {
-            super(modelScreen, htmlTemplateDecoratorElement);
-            this.locationExdr = FlexibleStringExpander.getInstance(htmlTemplateDecoratorElement.getAttribute("location"));
-
-            List<? extends Element> htmlTemplateDecoratorSectionElementList = UtilXml.childElementList(htmlTemplateDecoratorElement, "html-template-decorator-section");
-            for (Element htmlTemplateDecoratorSectionElement: htmlTemplateDecoratorSectionElementList) {
-                String name = htmlTemplateDecoratorSectionElement.getAttribute("name");
-                this.sectionMap.put(name, new HtmlTemplateDecoratorSection(modelScreen, htmlTemplateDecoratorSectionElement));
-            }
-        }
-
-        @Override
-        public void renderWidgetString(Appendable writer, Map<String, Object> context, ScreenStringRenderer screenStringRenderer) {
-            // isolate the scope
-            MapStack<String> contextMs;
-            if (!(context instanceof MapStack<?>)) {
-                contextMs = MapStack.create(context);
-                context = contextMs;
-            } else {
-                contextMs = UtilGenerics.cast(context);
-            }
-
-            // create a standAloneStack, basically a "save point" for this SectionsRenderer, and make a new "screens" object just for it so it is isolated and doesn't follow the stack down
-            MapStack<String> standAloneStack = contextMs.standAloneChildStack();
-            standAloneStack.put("screens", new ScreenRenderer(writer, standAloneStack, screenStringRenderer));
-            SectionsRenderer sections = new SectionsRenderer(this.sectionMap, standAloneStack, writer, screenStringRenderer);
-
-            // put the sectionMap in the context, make sure it is in the sub-scope, ie after calling push on the MapStack
-            contextMs.push();
-            context.put("sections", sections);
-
-            renderHtmlTemplate(writer, this.locationExdr, context);
-            contextMs.pop();
-        }
-
-        @Override
-        public void accept(ModelWidgetVisitor visitor) throws Exception {
-            visitor.visit(this);
-        }
-
-        public FlexibleStringExpander getLocationExdr() {
-            return locationExdr;
-        }
-
-        public Map<String, ModelScreenWidget> getSectionMap() {
-            return sectionMap;
-        }
-    }
-
-    public static class HtmlTemplateDecoratorSection extends ModelScreenWidget {
-        protected List<ModelScreenWidget> subWidgets;
-
-        public HtmlTemplateDecoratorSection(ModelScreen modelScreen, Element htmlTemplateDecoratorSectionElement) {
-            super(modelScreen, htmlTemplateDecoratorSectionElement);
-            List<? extends Element> subElementList = UtilXml.childElementList(htmlTemplateDecoratorSectionElement);
-            this.subWidgets = ModelScreenWidget.readSubWidgets(getModelScreen(), subElementList);
-        }
-
-        @Override
-        public void renderWidgetString(Appendable writer, Map<String, Object> context, ScreenStringRenderer screenStringRenderer) throws GeneralException, IOException {
-            // render sub-widgets
-            renderSubWidgetsString(this.subWidgets, writer, context, screenStringRenderer);
-        }
-
-        @Override
-        public void accept(ModelWidgetVisitor visitor) throws Exception {
-            visitor.visit(this);
-        }
-
-        public List<ModelScreenWidget> getSubWidgets() {
-            return subWidgets;
-        }
-    }
-
-    @Override
-    public void accept(ModelWidgetVisitor visitor) throws Exception {
-        visitor.visit(this);
-    }
-}
+/*******************************************************************************

+ * Licensed to the Apache Software Foundation (ASF) under one

+ * or more contributor license agreements.  See the NOTICE file

+ * distributed with this work for additional information

+ * regarding copyright ownership.  The ASF licenses this file

+ * to you under the Apache License, Version 2.0 (the

+ * "License"); you may not use this file except in compliance

+ * with the License.  You may obtain a copy of the License at

+ *

+ * http://www.apache.org/licenses/LICENSE-2.0

+ *

+ * Unless required by applicable law or agreed to in writing,

+ * software distributed under the License is distributed on an

+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY

+ * KIND, either express or implied.  See the License for the

+ * specific language governing permissions and limitations

+ * under the License.

+ *******************************************************************************/

+package org.ofbiz.widget.model;

+

+import java.io.IOException;

+import java.net.MalformedURLException;

+import java.util.ArrayList;

+import java.util.Collection;

+import java.util.Collections;

+import java.util.HashMap;

+import java.util.List;

+import java.util.Map;

+

+import org.ofbiz.base.util.Debug;

+import org.ofbiz.base.util.GeneralException;

+import org.ofbiz.base.util.UtilCodec;

+import org.ofbiz.base.util.UtilGenerics;

+import org.ofbiz.base.util.UtilValidate;

+import org.ofbiz.base.util.UtilXml;

+import org.ofbiz.base.util.cache.UtilCache;

+import org.ofbiz.base.util.collections.MapStack;

+import org.ofbiz.base.util.string.FlexibleStringExpander;

+import org.ofbiz.base.util.template.FreeMarkerWorker;

+import org.ofbiz.widget.renderer.ScreenRenderer;

+import org.ofbiz.widget.renderer.ScreenStringRenderer;

+import org.ofbiz.widget.renderer.html.HtmlWidgetRenderer;

+import org.w3c.dom.Element;

+

+import freemarker.ext.beans.BeansWrapper;

+import freemarker.ext.beans.CollectionModel;

+import freemarker.ext.beans.StringModel;

+import freemarker.template.Configuration;

+import freemarker.template.Template;

+import freemarker.template.TemplateException;

+import freemarker.template.TemplateModel;

+import freemarker.template.TemplateModelException;

+import freemarker.template.Version;

+

+/**

+ * Widget Library - Screen model HTML class.

+ */

+@SuppressWarnings("serial")

+public class HtmlWidget extends ModelScreenWidget {

+    public static final String module = HtmlWidget.class.getName();

+

+    private static final UtilCache<String, Template> specialTemplateCache = UtilCache.createUtilCache("widget.screen.template.ftl.general", 0, 0, false);

+    protected static Configuration specialConfig = FreeMarkerWorker.makeConfiguration(new ExtendedWrapper(FreeMarkerWorker.version));

+

+    // not sure if this is the best way to get FTL to use my fancy MapModel derivative, but should work at least...

+    public static class ExtendedWrapper extends BeansWrapper {

+        public ExtendedWrapper(Version version) {

+            super(version);

+        }

+

+        @Override

+        public TemplateModel wrap(Object object) throws TemplateModelException {

+            // This StringHtmlWrapperForFtl option seems to be the best option

+            // and handles most things without causing too many problems

+            if (object instanceof String) {

+                return new StringHtmlWrapperForFtl((String) object, this);

+            } else if (object instanceof Collection && !(object instanceof Map)) {

+                // An additional wrapper to ensure ${aCollection} is properly encoded for html

+                return new CollectionHtmlWrapperForFtl((Collection<?>) object, this);

+            }

+            return super.wrap(object);

+        }

+    }

+

+    public static class StringHtmlWrapperForFtl extends StringModel {

+        public StringHtmlWrapperForFtl(String str, BeansWrapper wrapper) {

+            super(str, wrapper);

+        }

+        @Override

+        public String getAsString() {

+            return UtilCodec.getEncoder("html").encode(super.getAsString());

+        }

+    }

+

+    public static class CollectionHtmlWrapperForFtl extends CollectionModel {

+

+        public CollectionHtmlWrapperForFtl(Collection<?> collection, BeansWrapper wrapper) {

+            super(collection, wrapper);

+        }

+

+        @Override

+        public String getAsString() {

+            return UtilCodec.getEncoder("html").encode(super.getAsString());

+        }

+

+    }

+

+    // End Static, begin class section

+

+    private final List<ModelScreenWidget> subWidgets;

+

+    public HtmlWidget(ModelScreen modelScreen, Element htmlElement) {

+        super(modelScreen, htmlElement);

+        List<? extends Element> childElementList = UtilXml.childElementList(htmlElement);

+        if (childElementList.isEmpty()) {

+            this.subWidgets = Collections.emptyList();

+        } else {

+            List<ModelScreenWidget> subWidgets = new ArrayList<ModelScreenWidget>(childElementList.size());

+            for (Element childElement : childElementList) {

+                if ("html-template".equals(childElement.getNodeName())) {

+                    subWidgets.add(new HtmlTemplate(modelScreen, childElement));

+                } else if ("html-template-decorator".equals(childElement.getNodeName())) {

+                    subWidgets.add(new HtmlTemplateDecorator(modelScreen, childElement));

+                } else {

+                    throw new IllegalArgumentException("Tag not supported under the platform-specific -> html tag with name: "

+                            + childElement.getNodeName());

+                }

+            }

+            this.subWidgets = Collections.unmodifiableList(subWidgets);

+        }

+    }

+

+    public List<ModelScreenWidget> getSubWidgets() {

+        return subWidgets;

+    }

+

+    @Override

+    public void renderWidgetString(Appendable writer, Map<String, Object> context, ScreenStringRenderer screenStringRenderer) throws GeneralException, IOException {

+        for (ModelScreenWidget subWidget : subWidgets) {

+            subWidget.renderWidgetString(writer, context, screenStringRenderer);

+        }

+    }

+

+    public static void renderHtmlTemplate(Appendable writer, FlexibleStringExpander locationExdr, Map<String, Object> context) {

+        String location = locationExdr.expandString(context);

+        //Debug.logInfo("Rendering template at location [" + location + "] with context: \n" + context, module);

+

+        if (UtilValidate.isEmpty(location)) {

+            throw new IllegalArgumentException("Template location is empty");

+        }

+

+        if (location.endsWith(".ftl")) {

+            try {

+                Map<String, ? extends Object> parameters = UtilGenerics.checkMap(context.get("parameters"));

+                boolean insertWidgetBoundaryComments = ModelWidget.widgetBoundaryCommentsEnabled(parameters);

+                if (insertWidgetBoundaryComments) {

+                    writer.append(HtmlWidgetRenderer.formatBoundaryComment("Begin", "Template", location));

+                }

+

+                //FreeMarkerWorker.renderTemplateAtLocation(location, context, writer);

+                Template template = null;

+                if (location.endsWith(".fo.ftl")) { // FOP can't render correctly escaped characters

+                    template = FreeMarkerWorker.getTemplate(location);

+                } else {

+                    template = FreeMarkerWorker.getTemplate(location, specialTemplateCache, specialConfig);

+                }

+                FreeMarkerWorker.renderTemplate(template, context, writer);

+

+                if (insertWidgetBoundaryComments) {

+                    writer.append(HtmlWidgetRenderer.formatBoundaryComment("End", "Template", location));

+                }

+            } catch (IllegalArgumentException e) {

+                String errMsg = "Error rendering included template at location [" + location + "]: " + e.toString();

+                Debug.logError(e, errMsg, module);

+                writeError(writer, errMsg);

+            } catch (MalformedURLException e) {

+                String errMsg = "Error rendering included template at location [" + location + "]: " + e.toString();

+                Debug.logError(e, errMsg, module);

+                writeError(writer, errMsg);

+            } catch (TemplateException e) {

+                String errMsg = "Error rendering included template at location [" + location + "]: " + e.toString();

+                Debug.logError(e, errMsg, module);

+                writeError(writer, errMsg);

+            } catch (IOException e) {

+                String errMsg = "Error rendering included template at location [" + location + "]: " + e.toString();

+                Debug.logError(e, errMsg, module);

+                writeError(writer, errMsg);

+            }

+        } else {

+            throw new IllegalArgumentException("Rendering not yet supported for the template at location: " + location);

+        }

+    }

+

+    // TODO: We can make this more fancy, but for now this is very functional

+    public static void writeError(Appendable writer, String message) {

+        try {

+            writer.append(message);

+        } catch (IOException e) {

+        }

+    }

+

+    public static class HtmlTemplate extends ModelScreenWidget {

+        protected FlexibleStringExpander locationExdr;

+

+        public HtmlTemplate(ModelScreen modelScreen, Element htmlTemplateElement) {

+            super(modelScreen, htmlTemplateElement);

+            this.locationExdr = FlexibleStringExpander.getInstance(htmlTemplateElement.getAttribute("location"));

+        }

+

+        public String getLocation(Map<String, Object> context) {

+            return locationExdr.expandString(context);

+        }

+

+        @Override

+        public void renderWidgetString(Appendable writer, Map<String, Object> context, ScreenStringRenderer screenStringRenderer) {

+            renderHtmlTemplate(writer, this.locationExdr, context);

+        }

+

+        @Override

+        public void accept(ModelWidgetVisitor visitor) throws Exception {

+            visitor.visit(this);

+        }

+

+        public FlexibleStringExpander getLocationExdr() {

+            return locationExdr;

+        }

+    }

+

+    public static class HtmlTemplateDecorator extends ModelScreenWidget {

+        protected FlexibleStringExpander locationExdr;

+        protected Map<String, ModelScreenWidget> sectionMap = new HashMap<String, ModelScreenWidget>();

+

+        public HtmlTemplateDecorator(ModelScreen modelScreen, Element htmlTemplateDecoratorElement) {

+            super(modelScreen, htmlTemplateDecoratorElement);

+            this.locationExdr = FlexibleStringExpander.getInstance(htmlTemplateDecoratorElement.getAttribute("location"));

+

+            List<? extends Element> htmlTemplateDecoratorSectionElementList = UtilXml.childElementList(htmlTemplateDecoratorElement, "html-template-decorator-section");

+            for (Element htmlTemplateDecoratorSectionElement: htmlTemplateDecoratorSectionElementList) {

+                String name = htmlTemplateDecoratorSectionElement.getAttribute("name");

+                this.sectionMap.put(name, new HtmlTemplateDecoratorSection(modelScreen, htmlTemplateDecoratorSectionElement));

+            }

+        }

+

+        @Override

+        public void renderWidgetString(Appendable writer, Map<String, Object> context, ScreenStringRenderer screenStringRenderer) {

+            // isolate the scope

+            MapStack<String> contextMs;

+            if (!(context instanceof MapStack<?>)) {

+                contextMs = MapStack.create(context);

+                context = contextMs;

+            } else {

+                contextMs = UtilGenerics.cast(context);

+            }

+

+            // create a standAloneStack, basically a "save point" for this SectionsRenderer, and make a new "screens" object just for it so it is isolated and doesn't follow the stack down

+            MapStack<String> standAloneStack = contextMs.standAloneChildStack();

+            standAloneStack.put("screens", new ScreenRenderer(writer, standAloneStack, screenStringRenderer));

+            SectionsRenderer sections = new SectionsRenderer(this.sectionMap, standAloneStack, writer, screenStringRenderer);

+

+            // put the sectionMap in the context, make sure it is in the sub-scope, ie after calling push on the MapStack

+            contextMs.push();

+            context.put("sections", sections);

+

+            renderHtmlTemplate(writer, this.locationExdr, context);

+            contextMs.pop();

+        }

+

+        @Override

+        public void accept(ModelWidgetVisitor visitor) throws Exception {

+            visitor.visit(this);

+        }

+

+        public FlexibleStringExpander getLocationExdr() {

+            return locationExdr;

+        }

+

+        public Map<String, ModelScreenWidget> getSectionMap() {

+            return sectionMap;

+        }

+    }

+

+    public static class HtmlTemplateDecoratorSection extends ModelScreenWidget {

+        protected List<ModelScreenWidget> subWidgets;

+

+        public HtmlTemplateDecoratorSection(ModelScreen modelScreen, Element htmlTemplateDecoratorSectionElement) {

+            super(modelScreen, htmlTemplateDecoratorSectionElement);

+            List<? extends Element> subElementList = UtilXml.childElementList(htmlTemplateDecoratorSectionElement);

+            this.subWidgets = ModelScreenWidget.readSubWidgets(getModelScreen(), subElementList);

+        }

+

+        @Override

+        public void renderWidgetString(Appendable writer, Map<String, Object> context, ScreenStringRenderer screenStringRenderer) throws GeneralException, IOException {

+            // render sub-widgets

+            renderSubWidgetsString(this.subWidgets, writer, context, screenStringRenderer);

+        }

+

+        @Override

+        public void accept(ModelWidgetVisitor visitor) throws Exception {

+            visitor.visit(this);

+        }

+

+        public List<ModelScreenWidget> getSubWidgets() {

+            return subWidgets;

+        }

+    }

+

+    @Override

+    public void accept(ModelWidgetVisitor visitor) throws Exception {

+        visitor.visit(this);

+    }

+}

diff --git a/framework/widget/src/org/ofbiz/widget/screen/IterateSectionWidget.java b/framework/widget/src/org/ofbiz/widget/model/IterateSectionWidget.java
similarity index 99%
rename from framework/widget/src/org/ofbiz/widget/screen/IterateSectionWidget.java
rename to framework/widget/src/org/ofbiz/widget/model/IterateSectionWidget.java
index 3ae2fce..670ca9b 100644
--- a/framework/widget/src/org/ofbiz/widget/screen/IterateSectionWidget.java
+++ b/framework/widget/src/org/ofbiz/widget/model/IterateSectionWidget.java
@@ -1,387 +1,387 @@
-/*******************************************************************************
- * 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.screen;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-import java.util.Set;
-
-import javax.servlet.ServletContext;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.ofbiz.base.util.Debug;
-import org.ofbiz.base.util.GeneralException;
-import org.ofbiz.base.util.UtilGenerics;
-import org.ofbiz.base.util.UtilHttp;
-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.webapp.control.RequestHandler;
-import org.ofbiz.widget.ModelWidgetVisitor;
-import org.ofbiz.widget.WidgetWorker;
-import org.w3c.dom.Element;
-
-
-/**
- * Widget Library - Screen model HTML class
- */
-@SuppressWarnings("serial")
-public class IterateSectionWidget extends ModelScreenWidget {
-
-    public static final String module = IterateSectionWidget.class.getName();
-    public static int DEFAULT_PAGE_SIZE = 5;
-    public static int MAX_PAGE_SIZE = 10000;
-
-    private final List<ModelScreenWidget.Section> sectionList;
-    private final FlexibleMapAccessor<Object> listNameExdr;
-    private final FlexibleStringExpander entryNameExdr;
-    private final FlexibleStringExpander keyNameExdr;
-    private final FlexibleStringExpander paginateTarget;
-    private final FlexibleStringExpander paginate;
-    private final int viewSize;
-
-    public IterateSectionWidget(ModelScreen modelScreen, Element iterateSectionElement) {
-        super(modelScreen, iterateSectionElement);
-        String listName = iterateSectionElement.getAttribute("list");
-        if (listName.isEmpty()) {
-            listName = iterateSectionElement.getAttribute("list-name");
-        }
-        this.listNameExdr = FlexibleMapAccessor.getInstance(listName);
-        String entryName = iterateSectionElement.getAttribute("entry");
-        if (entryName.isEmpty()) {
-            entryName = iterateSectionElement.getAttribute("entry-name");
-        }
-        this.entryNameExdr = FlexibleStringExpander.getInstance(entryName);
-        String keyName = iterateSectionElement.getAttribute("key");
-        if (keyName.isEmpty()) {
-            keyName = iterateSectionElement.getAttribute("key-name");
-        }
-        this.keyNameExdr = FlexibleStringExpander.getInstance(keyName);
-        this.paginateTarget = FlexibleStringExpander.getInstance(iterateSectionElement.getAttribute("paginate-target"));
-        this.paginate = FlexibleStringExpander.getInstance(iterateSectionElement.getAttribute("paginate"));
-        int viewSize = DEFAULT_PAGE_SIZE;
-        String viewSizeStr = iterateSectionElement.getAttribute("view-size");
-        if (!viewSizeStr.isEmpty()) {
-            viewSize = Integer.parseInt(viewSizeStr);
-        }
-        this.viewSize = viewSize;
-        List<? extends Element> childElementList = UtilXml.childElementList(iterateSectionElement);
-        if (childElementList.isEmpty()) {
-            this.sectionList = Collections.emptyList();
-        } else {
-            List<ModelScreenWidget.Section> sectionList = new ArrayList<ModelScreenWidget.Section>(childElementList.size());
-            for (Element sectionElement: childElementList) {
-                ModelScreenWidget.Section section = new ModelScreenWidget.Section(modelScreen, sectionElement, false);
-                sectionList.add(section);
-            }
-            this.sectionList = Collections.unmodifiableList(sectionList);
-        }
-    }
-
-    public List<ModelScreenWidget.Section> getSectionList() {
-        return sectionList;
-    }
-
-    @Override
-    public void renderWidgetString(Appendable writer, Map<String, Object> context, ScreenStringRenderer screenStringRenderer) throws GeneralException, IOException {
-        int viewIndex = 0;
-        int viewSize = this.viewSize;
-        int lowIndex = -1;
-        int highIndex = -1;
-        int listSize = 0;
-        int actualPageSize = 0;
-
-        boolean isEntrySet = false;
-        // create a standAloneStack, basically a "save point" for this SectionsRenderer, and make a new "screens" object just for it so it is isolated and doesn't follow the stack down
-        MapStack<String> contextMs = MapStack.create(context);
-
-        String entryName = this.entryNameExdr.expandString(context);
-        String keyName = this.keyNameExdr.expandString(context);
-        Object obj = listNameExdr.get(context);
-        if (obj == null) {
-            Debug.logError("No object found for listName:" + listNameExdr.toString(), module);
-            return;
-        }
-        List<?> theList = null;
-        if (obj instanceof Map<?, ?>) {
-            Set<Map.Entry<String, Object>> entrySet = UtilGenerics.<Map<String, Object>>cast(obj).entrySet();
-            Object [] a = entrySet.toArray();
-            theList = Arrays.asList(a);
-            isEntrySet = true;
-        } else if (obj instanceof List<?>) {
-            theList = (List<?>)obj;
-        } else {
-            Debug.logError("Object not list or map type", module);
-            return;
-        }
-        listSize = theList.size();
-        WidgetWorker.incrementPaginatorNumber(context);
-        int startPageNumber = WidgetWorker.getPaginatorNumber(context);
-
-        if (getPaginate(context)) {
-            try {
-                Map<String, String> params = UtilGenerics.cast(context.get("parameters"));
-                String viewIndexString = params.get("VIEW_INDEX" + "_" + WidgetWorker.getPaginatorNumber(context));
-                String viewSizeString = params.get("VIEW_SIZE" + "_" + WidgetWorker.getPaginatorNumber(context));
-                viewIndex = Integer.parseInt(viewIndexString);
-                viewSize = Integer.parseInt(viewSizeString);
-            } catch (Exception e) {
-                try {
-                    viewIndex = ((Integer) context.get("viewIndex")).intValue();
-                } catch (Exception e2) {
-                    viewIndex = 0;
-                }
-            }
-            context.put("viewIndex", Integer.valueOf(viewIndex));
-            lowIndex = viewIndex * viewSize;
-            highIndex = (viewIndex + 1) * viewSize;
-        } else {
-            viewIndex = 0;
-            viewSize = MAX_PAGE_SIZE;
-            lowIndex = 0;
-            highIndex = MAX_PAGE_SIZE;
-        }
-        Iterator<?> iter = theList.iterator();
-        int itemIndex = -1;
-        int iterateIndex = 0;
-        while (iter.hasNext()) {
-            itemIndex++;
-            if (itemIndex >= highIndex) {
-                break;
-            }
-            Object item = iter.next();
-            if (itemIndex < lowIndex) {
-                continue;
-            }
-            if (isEntrySet) {
-                Map.Entry<String, ?> entry = UtilGenerics.cast(item);
-                contextMs.put(entryName, entry.getValue());
-                contextMs.put(keyName, entry.getKey());
-            } else {
-                contextMs.put(entryName, item);
-            }
-            contextMs.put("itemIndex", Integer.valueOf(itemIndex));
-
-            if (iterateIndex < listSize) {
-                contextMs.put("iterateId",String.valueOf(entryName+iterateIndex));
-                iterateIndex++;
-            }
-            for (ModelScreenWidget.Section section: this.sectionList) {
-                section.renderWidgetString(writer, contextMs, screenStringRenderer);
-            }
-        }
-
-        if ((itemIndex + 1) < highIndex) {
-            highIndex = itemIndex + 1;
-        }
-        actualPageSize = highIndex - lowIndex;
-        if (getPaginate(context)) {
-            try {
-                Integer lastPageNumber = null;
-                Map<String, Object> globalCtx = UtilGenerics.checkMap(context.get("globalContext"));
-                if (globalCtx != null) {
-                    lastPageNumber = (Integer)globalCtx.get("PAGINATOR_NUMBER");
-                    globalCtx.put("PAGINATOR_NUMBER", Integer.valueOf(startPageNumber));
-                }
-                renderNextPrev(writer, context, listSize, actualPageSize);
-                if (globalCtx != null) {
-                    globalCtx.put("PAGINATOR_NUMBER", lastPageNumber);
-                }
-            } catch (IOException e) {
-                Debug.logError(e, module);
-                throw new RuntimeException(e.getMessage());
-            }
-        }
-
-    }
-    /*
-     * @return
-     */
-    public String getPaginateTarget(Map<String, Object> context) {
-        return this.paginateTarget.expandString(context);
-    }
-
-    public boolean getPaginate(Map<String, Object> context) {
-        if (!this.paginate.isEmpty() && UtilValidate.isNotEmpty(this.paginate.expandString(context))) {
-            return Boolean.valueOf(this.paginate.expandString(context)).booleanValue();
-        } else {
-            return true;
-        }
-    }
-
-    public int getViewSize() {
-        return viewSize;
-    }
-
-    public void renderNextPrev(Appendable writer, Map<String, Object> context, int listSize, int actualPageSize) throws IOException {
-        String targetService = this.getPaginateTarget(context);
-        if (targetService == null) {
-            targetService = "${targetService}";
-        }
-
-        Map<String, Object> inputFields = UtilGenerics.checkMap(context.get("requestParameters"));
-        Map<String, Object> queryStringMap = UtilGenerics.toMap(context.get("queryStringMap"));
-        if (UtilValidate.isNotEmpty(queryStringMap)) {
-            inputFields.putAll(queryStringMap);
-        }
-
-        String queryString = UtilHttp.urlEncodeArgs(inputFields);
-        int paginatorNumber = WidgetWorker.getPaginatorNumber(context);
-        queryString = UtilHttp.stripViewParamsFromQueryString(queryString, "" + paginatorNumber);
-
-
-
-
-        if (UtilValidate.isEmpty(targetService)) {
-            Debug.logWarning("TargetService is empty.", module);
-            return;
-        }
-
-        int viewIndex = -1;
-        try {
-            viewIndex = ((Integer) context.get("viewIndex")).intValue();
-        } catch (Exception e) {
-            viewIndex = 0;
-        }
-
-        int viewSize = -1;
-        try {
-            viewSize = ((Integer) context.get("viewSize")).intValue();
-        } catch (Exception e) {
-            viewSize = this.getViewSize();
-        }
-
-
-        /*
-        int highIndex = -1;
-        try {
-            highIndex = modelForm.getHighIndex();
-        } catch (Exception e) {
-            highIndex = 0;
-        }
-
-        int lowIndex = -1;
-        try {
-            lowIndex = modelForm.getLowIndex();
-        } catch (Exception e) {
-            lowIndex = 0;
-        }
-         */
-
-        int lowIndex = viewIndex * viewSize;
-        int highIndex = (viewIndex + 1) * viewSize;
-        // if this is all there seems to be (if listSize < 0, then size is unknown)
-        if (actualPageSize >= listSize && listSize > 0) {
-            return;
-        }
-
-        HttpServletRequest request = (HttpServletRequest) context.get("request");
-        HttpServletResponse response = (HttpServletResponse) context.get("response");
-
-        ServletContext ctx = (ServletContext) request.getAttribute("servletContext");
-        RequestHandler rh = (RequestHandler) ctx.getAttribute("_REQUEST_HANDLER_");
-
-        writer.append("<table border=\"0\" width=\"100%\" cellpadding=\"2\">\n");
-        writer.append("  <tr>\n");
-        writer.append("    <td align=\"right\">\n");
-        writer.append("      <b>\n");
-        if (viewIndex > 0) {
-            writer.append(" <a href=\"");
-            StringBuilder linkText = new StringBuilder(targetService);
-            if (linkText.indexOf("?") < 0)  linkText.append("?");
-            else linkText.append("&amp;");
-            //if (queryString != null && !queryString.equals("null")) linkText += queryString + "&";
-            if (UtilValidate.isNotEmpty(queryString)) {
-                linkText.append(queryString).append("&amp;");
-            }
-            linkText.append("VIEW_SIZE_"+ paginatorNumber + "=").append(viewSize).append("&amp;VIEW_INDEX_" + paginatorNumber + "=").append(viewIndex - 1).append("\"");
-
-            // make the link
-            writer.append(rh.makeLink(request, response, linkText.toString(), false, false, false));
-            String previous = UtilProperties.getMessage("CommonUiLabels", "CommonPrevious", (Locale) context.get("locale"));
-            writer.append(" class=\"buttontext\">[").append(previous).append("]</a>\n");
-
-        }
-        if (listSize > 0) {
-            Map<String, Integer> messageMap = UtilMisc.toMap("lowCount", Integer.valueOf(lowIndex + 1), "highCount", Integer.valueOf(lowIndex + actualPageSize), "total", Integer.valueOf(listSize));
-            String commonDisplaying = UtilProperties.getMessage("CommonUiLabels", "CommonDisplaying", messageMap, (Locale) context.get("locale"));
-            writer.append(" <span class=\"tabletext\">").append(commonDisplaying).append("</span> \n");
-        }
-        if (highIndex < listSize) {
-            writer.append(" <a href=\"");
-            StringBuilder linkText = new StringBuilder(targetService);
-            if (linkText.indexOf("?") < 0)  linkText.append("?");
-            else linkText.append("&amp;");
-            if (UtilValidate.isNotEmpty(queryString)) {
-                linkText.append(queryString).append("&amp;");
-            }
-            linkText.append("VIEW_SIZE_" + paginatorNumber + "=").append(viewSize).append("&amp;VIEW_INDEX_" + paginatorNumber + "=").append(viewIndex + 1).append("\"");
-
-            // make the link
-            writer.append(rh.makeLink(request, response, linkText.toString(), false, false, false));
-            String next = UtilProperties.getMessage("CommonUiLabels", "CommonNext", (Locale) context.get("locale"));
-            writer.append(" class=\"buttontext\">[").append(next).append("]</a>\n");
-
-        }
-        writer.append("      </b>\n");
-        writer.append("    </td>\n");
-        writer.append("  </tr>\n");
-        writer.append("</table>\n");
-
-    }
-
-    @Override
-    public void accept(ModelWidgetVisitor visitor) throws Exception {
-        visitor.visit(this);
-    }
-
-    public FlexibleMapAccessor<Object> getListNameExdr() {
-        return listNameExdr;
-    }
-
-    public FlexibleStringExpander getEntryNameExdr() {
-        return entryNameExdr;
-    }
-
-    public FlexibleStringExpander getKeyNameExdr() {
-        return keyNameExdr;
-    }
-
-    public FlexibleStringExpander getPaginateTarget() {
-        return paginateTarget;
-    }
-
-    public FlexibleStringExpander getPaginate() {
-        return paginate;
-    }
-
-}
-
-
+/*******************************************************************************

+ * Licensed to the Apache Software Foundation (ASF) under one

+ * or more contributor license agreements.  See the NOTICE file

+ * distributed with this work for additional information

+ * regarding copyright ownership.  The ASF licenses this file

+ * to you under the Apache License, Version 2.0 (the

+ * "License"); you may not use this file except in compliance

+ * with the License.  You may obtain a copy of the License at

+ *

+ * http://www.apache.org/licenses/LICENSE-2.0

+ *

+ * Unless required by applicable law or agreed to in writing,

+ * software distributed under the License is distributed on an

+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY

+ * KIND, either express or implied.  See the License for the

+ * specific language governing permissions and limitations

+ * under the License.

+ *******************************************************************************/

+package org.ofbiz.widget.model;

+

+import java.io.IOException;

+import java.util.ArrayList;

+import java.util.Arrays;

+import java.util.Collections;

+import java.util.Iterator;

+import java.util.List;

+import java.util.Locale;

+import java.util.Map;

+import java.util.Set;

+

+import javax.servlet.ServletContext;

+import javax.servlet.http.HttpServletRequest;

+import javax.servlet.http.HttpServletResponse;

+

+import org.ofbiz.base.util.Debug;

+import org.ofbiz.base.util.GeneralException;

+import org.ofbiz.base.util.UtilGenerics;

+import org.ofbiz.base.util.UtilHttp;

+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.webapp.control.RequestHandler;

+import org.ofbiz.widget.WidgetWorker;

+import org.ofbiz.widget.renderer.ScreenStringRenderer;

+import org.w3c.dom.Element;

+

+

+/**

+ * Widget Library - Screen model HTML class

+ */

+@SuppressWarnings("serial")

+public class IterateSectionWidget extends ModelScreenWidget {

+

+    public static final String module = IterateSectionWidget.class.getName();

+    public static int DEFAULT_PAGE_SIZE = 5;

+    public static int MAX_PAGE_SIZE = 10000;

+

+    private final List<ModelScreenWidget.Section> sectionList;

+    private final FlexibleMapAccessor<Object> listNameExdr;

+    private final FlexibleStringExpander entryNameExdr;

+    private final FlexibleStringExpander keyNameExdr;

+    private final FlexibleStringExpander paginateTarget;

+    private final FlexibleStringExpander paginate;

+    private final int viewSize;

+

+    public IterateSectionWidget(ModelScreen modelScreen, Element iterateSectionElement) {

+        super(modelScreen, iterateSectionElement);

+        String listName = iterateSectionElement.getAttribute("list");

+        if (listName.isEmpty()) {

+            listName = iterateSectionElement.getAttribute("list-name");

+        }

+        this.listNameExdr = FlexibleMapAccessor.getInstance(listName);

+        String entryName = iterateSectionElement.getAttribute("entry");

+        if (entryName.isEmpty()) {

+            entryName = iterateSectionElement.getAttribute("entry-name");

+        }

+        this.entryNameExdr = FlexibleStringExpander.getInstance(entryName);

+        String keyName = iterateSectionElement.getAttribute("key");

+        if (keyName.isEmpty()) {

+            keyName = iterateSectionElement.getAttribute("key-name");

+        }

+        this.keyNameExdr = FlexibleStringExpander.getInstance(keyName);

+        this.paginateTarget = FlexibleStringExpander.getInstance(iterateSectionElement.getAttribute("paginate-target"));

+        this.paginate = FlexibleStringExpander.getInstance(iterateSectionElement.getAttribute("paginate"));

+        int viewSize = DEFAULT_PAGE_SIZE;

+        String viewSizeStr = iterateSectionElement.getAttribute("view-size");

+        if (!viewSizeStr.isEmpty()) {

+            viewSize = Integer.parseInt(viewSizeStr);

+        }

+        this.viewSize = viewSize;

+        List<? extends Element> childElementList = UtilXml.childElementList(iterateSectionElement);

+        if (childElementList.isEmpty()) {

+            this.sectionList = Collections.emptyList();

+        } else {

+            List<ModelScreenWidget.Section> sectionList = new ArrayList<ModelScreenWidget.Section>(childElementList.size());

+            for (Element sectionElement: childElementList) {

+                ModelScreenWidget.Section section = new ModelScreenWidget.Section(modelScreen, sectionElement, false);

+                sectionList.add(section);

+            }

+            this.sectionList = Collections.unmodifiableList(sectionList);

+        }

+    }

+

+    public List<ModelScreenWidget.Section> getSectionList() {

+        return sectionList;

+    }

+

+    @Override

+    public void renderWidgetString(Appendable writer, Map<String, Object> context, ScreenStringRenderer screenStringRenderer) throws GeneralException, IOException {

+        int viewIndex = 0;

+        int viewSize = this.viewSize;

+        int lowIndex = -1;

+        int highIndex = -1;

+        int listSize = 0;

+        int actualPageSize = 0;

+

+        boolean isEntrySet = false;

+        // create a standAloneStack, basically a "save point" for this SectionsRenderer, and make a new "screens" object just for it so it is isolated and doesn't follow the stack down

+        MapStack<String> contextMs = MapStack.create(context);

+

+        String entryName = this.entryNameExdr.expandString(context);

+        String keyName = this.keyNameExdr.expandString(context);

+        Object obj = listNameExdr.get(context);

+        if (obj == null) {

+            Debug.logError("No object found for listName:" + listNameExdr.toString(), module);

+            return;

+        }

+        List<?> theList = null;

+        if (obj instanceof Map<?, ?>) {

+            Set<Map.Entry<String, Object>> entrySet = UtilGenerics.<Map<String, Object>>cast(obj).entrySet();

+            Object [] a = entrySet.toArray();

+            theList = Arrays.asList(a);

+            isEntrySet = true;

+        } else if (obj instanceof List<?>) {

+            theList = (List<?>)obj;

+        } else {

+            Debug.logError("Object not list or map type", module);

+            return;

+        }

+        listSize = theList.size();

+        WidgetWorker.incrementPaginatorNumber(context);

+        int startPageNumber = WidgetWorker.getPaginatorNumber(context);

+

+        if (getPaginate(context)) {

+            try {

+                Map<String, String> params = UtilGenerics.cast(context.get("parameters"));

+                String viewIndexString = params.get("VIEW_INDEX" + "_" + WidgetWorker.getPaginatorNumber(context));

+                String viewSizeString = params.get("VIEW_SIZE" + "_" + WidgetWorker.getPaginatorNumber(context));

+                viewIndex = Integer.parseInt(viewIndexString);

+                viewSize = Integer.parseInt(viewSizeString);

+            } catch (Exception e) {

+                try {

+                    viewIndex = ((Integer) context.get("viewIndex")).intValue();

+                } catch (Exception e2) {

+                    viewIndex = 0;

+                }

+            }

+            context.put("viewIndex", Integer.valueOf(viewIndex));

+            lowIndex = viewIndex * viewSize;

+            highIndex = (viewIndex + 1) * viewSize;

+        } else {

+            viewIndex = 0;

+            viewSize = MAX_PAGE_SIZE;

+            lowIndex = 0;

+            highIndex = MAX_PAGE_SIZE;

+        }

+        Iterator<?> iter = theList.iterator();

+        int itemIndex = -1;

+        int iterateIndex = 0;

+        while (iter.hasNext()) {

+            itemIndex++;

+            if (itemIndex >= highIndex) {

+                break;

+            }

+            Object item = iter.next();

+            if (itemIndex < lowIndex) {

+                continue;

+            }

+            if (isEntrySet) {

+                Map.Entry<String, ?> entry = UtilGenerics.cast(item);

+                contextMs.put(entryName, entry.getValue());

+                contextMs.put(keyName, entry.getKey());

+            } else {

+                contextMs.put(entryName, item);

+            }

+            contextMs.put("itemIndex", Integer.valueOf(itemIndex));

+

+            if (iterateIndex < listSize) {

+                contextMs.put("iterateId",String.valueOf(entryName+iterateIndex));

+                iterateIndex++;

+            }

+            for (ModelScreenWidget.Section section: this.sectionList) {

+                section.renderWidgetString(writer, contextMs, screenStringRenderer);

+            }

+        }

+

+        if ((itemIndex + 1) < highIndex) {

+            highIndex = itemIndex + 1;

+        }

+        actualPageSize = highIndex - lowIndex;

+        if (getPaginate(context)) {

+            try {

+                Integer lastPageNumber = null;

+                Map<String, Object> globalCtx = UtilGenerics.checkMap(context.get("globalContext"));

+                if (globalCtx != null) {

+                    lastPageNumber = (Integer)globalCtx.get("PAGINATOR_NUMBER");

+                    globalCtx.put("PAGINATOR_NUMBER", Integer.valueOf(startPageNumber));

+                }

+                renderNextPrev(writer, context, listSize, actualPageSize);

+                if (globalCtx != null) {

+                    globalCtx.put("PAGINATOR_NUMBER", lastPageNumber);

+                }

+            } catch (IOException e) {

+                Debug.logError(e, module);

+                throw new RuntimeException(e.getMessage());

+            }

+        }

+

+    }

+    /*

+     * @return

+     */

+    public String getPaginateTarget(Map<String, Object> context) {

+        return this.paginateTarget.expandString(context);

+    }

+

+    public boolean getPaginate(Map<String, Object> context) {

+        if (!this.paginate.isEmpty() && UtilValidate.isNotEmpty(this.paginate.expandString(context))) {

+            return Boolean.valueOf(this.paginate.expandString(context)).booleanValue();

+        } else {

+            return true;

+        }

+    }

+

+    public int getViewSize() {

+        return viewSize;

+    }

+

+    public void renderNextPrev(Appendable writer, Map<String, Object> context, int listSize, int actualPageSize) throws IOException {

+        String targetService = this.getPaginateTarget(context);

+        if (targetService == null) {

+            targetService = "${targetService}";

+        }

+

+        Map<String, Object> inputFields = UtilGenerics.checkMap(context.get("requestParameters"));

+        Map<String, Object> queryStringMap = UtilGenerics.toMap(context.get("queryStringMap"));

+        if (UtilValidate.isNotEmpty(queryStringMap)) {

+            inputFields.putAll(queryStringMap);

+        }

+

+        String queryString = UtilHttp.urlEncodeArgs(inputFields);

+        int paginatorNumber = WidgetWorker.getPaginatorNumber(context);

+        queryString = UtilHttp.stripViewParamsFromQueryString(queryString, "" + paginatorNumber);

+

+

+

+

+        if (UtilValidate.isEmpty(targetService)) {

+            Debug.logWarning("TargetService is empty.", module);

+            return;

+        }

+

+        int viewIndex = -1;

+        try {

+            viewIndex = ((Integer) context.get("viewIndex")).intValue();

+        } catch (Exception e) {

+            viewIndex = 0;

+        }

+

+        int viewSize = -1;

+        try {

+            viewSize = ((Integer) context.get("viewSize")).intValue();

+        } catch (Exception e) {

+            viewSize = this.getViewSize();

+        }

+

+

+        /*

+        int highIndex = -1;

+        try {

+            highIndex = modelForm.getHighIndex();

+        } catch (Exception e) {

+            highIndex = 0;

+        }

+

+        int lowIndex = -1;

+        try {

+            lowIndex = modelForm.getLowIndex();

+        } catch (Exception e) {

+            lowIndex = 0;

+        }

+         */

+

+        int lowIndex = viewIndex * viewSize;

+        int highIndex = (viewIndex + 1) * viewSize;

+        // if this is all there seems to be (if listSize < 0, then size is unknown)

+        if (actualPageSize >= listSize && listSize > 0) {

+            return;

+        }

+

+        HttpServletRequest request = (HttpServletRequest) context.get("request");

+        HttpServletResponse response = (HttpServletResponse) context.get("response");

+

+        ServletContext ctx = (ServletContext) request.getAttribute("servletContext");

+        RequestHandler rh = (RequestHandler) ctx.getAttribute("_REQUEST_HANDLER_");

+

+        writer.append("<table border=\"0\" width=\"100%\" cellpadding=\"2\">\n");

+        writer.append("  <tr>\n");

+        writer.append("    <td align=\"right\">\n");

+        writer.append("      <b>\n");

+        if (viewIndex > 0) {

+            writer.append(" <a href=\"");

+            StringBuilder linkText = new StringBuilder(targetService);

+            if (linkText.indexOf("?") < 0)  linkText.append("?");

+            else linkText.append("&amp;");

+            //if (queryString != null && !queryString.equals("null")) linkText += queryString + "&";

+            if (UtilValidate.isNotEmpty(queryString)) {

+                linkText.append(queryString).append("&amp;");

+            }

+            linkText.append("VIEW_SIZE_"+ paginatorNumber + "=").append(viewSize).append("&amp;VIEW_INDEX_" + paginatorNumber + "=").append(viewIndex - 1).append("\"");

+

+            // make the link

+            writer.append(rh.makeLink(request, response, linkText.toString(), false, false, false));

+            String previous = UtilProperties.getMessage("CommonUiLabels", "CommonPrevious", (Locale) context.get("locale"));

+            writer.append(" class=\"buttontext\">[").append(previous).append("]</a>\n");

+

+        }

+        if (listSize > 0) {

+            Map<String, Integer> messageMap = UtilMisc.toMap("lowCount", Integer.valueOf(lowIndex + 1), "highCount", Integer.valueOf(lowIndex + actualPageSize), "total", Integer.valueOf(listSize));

+            String commonDisplaying = UtilProperties.getMessage("CommonUiLabels", "CommonDisplaying", messageMap, (Locale) context.get("locale"));

+            writer.append(" <span class=\"tabletext\">").append(commonDisplaying).append("</span> \n");

+        }

+        if (highIndex < listSize) {

+            writer.append(" <a href=\"");

+            StringBuilder linkText = new StringBuilder(targetService);

+            if (linkText.indexOf("?") < 0)  linkText.append("?");

+            else linkText.append("&amp;");

+            if (UtilValidate.isNotEmpty(queryString)) {

+                linkText.append(queryString).append("&amp;");

+            }

+            linkText.append("VIEW_SIZE_" + paginatorNumber + "=").append(viewSize).append("&amp;VIEW_INDEX_" + paginatorNumber + "=").append(viewIndex + 1).append("\"");

+

+            // make the link

+            writer.append(rh.makeLink(request, response, linkText.toString(), false, false, false));

+            String next = UtilProperties.getMessage("CommonUiLabels", "CommonNext", (Locale) context.get("locale"));

+            writer.append(" class=\"buttontext\">[").append(next).append("]</a>\n");

+

+        }

+        writer.append("      </b>\n");

+        writer.append("    </td>\n");

+        writer.append("  </tr>\n");

+        writer.append("</table>\n");

+

+    }

+

+    @Override

+    public void accept(ModelWidgetVisitor visitor) throws Exception {

+        visitor.visit(this);

+    }

+

+    public FlexibleMapAccessor<Object> getListNameExdr() {

+        return listNameExdr;

+    }

+

+    public FlexibleStringExpander getEntryNameExdr() {

+        return entryNameExdr;

+    }

+

+    public FlexibleStringExpander getKeyNameExdr() {

+        return keyNameExdr;

+    }

+

+    public FlexibleStringExpander getPaginateTarget() {

+        return paginateTarget;

+    }

+

+    public FlexibleStringExpander getPaginate() {

+        return paginate;

+    }

+

+}

+

+

diff --git a/framework/widget/src/org/ofbiz/widget/menu/MenuFactory.java b/framework/widget/src/org/ofbiz/widget/model/MenuFactory.java
similarity index 99%
rename from framework/widget/src/org/ofbiz/widget/menu/MenuFactory.java
rename to framework/widget/src/org/ofbiz/widget/model/MenuFactory.java
index 472d688..c30ac37 100644
--- a/framework/widget/src/org/ofbiz/widget/menu/MenuFactory.java
+++ b/framework/widget/src/org/ofbiz/widget/model/MenuFactory.java
@@ -1,118 +1,118 @@
-/*******************************************************************************
- * 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.menu;
-
-import java.io.IOException;
-import java.net.URL;
-import java.util.HashMap;
-import java.util.Map;
-
-import javax.servlet.ServletContext;
-import javax.servlet.http.HttpServletRequest;
-import javax.xml.parsers.ParserConfigurationException;
-
-import org.ofbiz.base.location.FlexibleLocation;
-import org.ofbiz.base.util.UtilHttp;
-import org.ofbiz.base.util.UtilValidate;
-import org.ofbiz.base.util.UtilXml;
-import org.ofbiz.base.util.cache.UtilCache;
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-import org.xml.sax.SAXException;
-
-
-/**
- * Widget Library - Menu factory class
- */
-public class MenuFactory {
-
-    public static final String module = MenuFactory.class.getName();
-
-    public static final UtilCache<String, Map<String, ModelMenu>> menuWebappCache = UtilCache.createUtilCache("widget.menu.webappResource", 0, 0, false);
-    public static final UtilCache<String, Map<String, ModelMenu>> menuLocationCache = UtilCache.createUtilCache("widget.menu.locationResource", 0, 0, false);
-
-    public static ModelMenu getMenuFromWebappContext(String resourceName, String menuName, HttpServletRequest request)
-            throws IOException, SAXException, ParserConfigurationException {
-        String webappName = UtilHttp.getApplicationName(request);
-        String cacheKey = webappName + "::" + resourceName;
-
-        Map<String, ModelMenu> modelMenuMap = menuWebappCache.get(cacheKey);
-        if (modelMenuMap == null) {
-            synchronized (MenuFactory.class) {
-                modelMenuMap = menuWebappCache.get(cacheKey);
-                if (modelMenuMap == null) {
-                    ServletContext servletContext = (ServletContext) request.getAttribute("servletContext");
-
-                    URL menuFileUrl = servletContext.getResource(resourceName);
-                    Document menuFileDoc = UtilXml.readXmlDocument(menuFileUrl, true, true);
-                    modelMenuMap = readMenuDocument(menuFileDoc, cacheKey);
-                    menuWebappCache.put(cacheKey, modelMenuMap);
-                }
-            }
-        }
-
-        if (UtilValidate.isEmpty(modelMenuMap)) {
-            throw new IllegalArgumentException("Could not find menu file in webapp resource [" + resourceName + "] in the webapp [" + webappName + "]");
-        }
-
-        ModelMenu modelMenu = modelMenuMap.get(menuName);
-        if (modelMenu == null) {
-            throw new IllegalArgumentException("Could not find menu with name [" + menuName + "] in webapp resource [" + resourceName + "] in the webapp [" + webappName + "]");
-        }
-        return modelMenu;
-    }
-
-    public static Map<String, ModelMenu> readMenuDocument(Document menuFileDoc, String menuLocation) {
-        Map<String, ModelMenu> modelMenuMap = new HashMap<String, ModelMenu>();
-        if (menuFileDoc != null) {
-            // read document and construct ModelMenu for each menu element
-            Element rootElement = menuFileDoc.getDocumentElement();
-            for (Element menuElement: UtilXml.childElementList(rootElement, "menu")){
-                ModelMenu modelMenu = new ModelMenu(menuElement, menuLocation);
-                modelMenuMap.put(modelMenu.getName(), modelMenu);
-            }
-         }
-        return modelMenuMap;
-    }
-
-    public static ModelMenu getMenuFromLocation(String resourceName, String menuName) throws IOException, SAXException, ParserConfigurationException {
-        Map<String, ModelMenu> modelMenuMap = menuLocationCache.get(resourceName);
-        if (modelMenuMap == null) {
-            synchronized (MenuFactory.class) {
-                modelMenuMap = menuLocationCache.get(resourceName);
-                if (modelMenuMap == null) {
-                    URL menuFileUrl = FlexibleLocation.resolveLocation(resourceName);
-                    Document menuFileDoc = UtilXml.readXmlDocument(menuFileUrl, true, true);
-                    modelMenuMap = readMenuDocument(menuFileDoc, resourceName);
-                    menuLocationCache.put(resourceName, modelMenuMap);
-                }
-            }
-        }
-
-        if (UtilValidate.isEmpty(modelMenuMap)) {
-            throw new IllegalArgumentException("Could not find menu file in location [" + resourceName + "]");
-        }
-
-        ModelMenu modelMenu = modelMenuMap.get(menuName);
-        if (modelMenu == null) {
-            throw new IllegalArgumentException("Could not find menu with name [" + menuName + "] in location [" + resourceName + "]");
-        }
-        return modelMenu;
-    }
-}
+/*******************************************************************************

+ * Licensed to the Apache Software Foundation (ASF) under one

+ * or more contributor license agreements.  See the NOTICE file

+ * distributed with this work for additional information

+ * regarding copyright ownership.  The ASF licenses this file

+ * to you under the Apache License, Version 2.0 (the

+ * "License"); you may not use this file except in compliance

+ * with the License.  You may obtain a copy of the License at

+ *

+ * http://www.apache.org/licenses/LICENSE-2.0

+ *

+ * Unless required by applicable law or agreed to in writing,

+ * software distributed under the License is distributed on an

+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY

+ * KIND, either express or implied.  See the License for the

+ * specific language governing permissions and limitations

+ * under the License.

+ *******************************************************************************/

+package org.ofbiz.widget.model;

+

+import java.io.IOException;

+import java.net.URL;

+import java.util.HashMap;

+import java.util.Map;

+

+import javax.servlet.ServletContext;

+import javax.servlet.http.HttpServletRequest;

+import javax.xml.parsers.ParserConfigurationException;

+

+import org.ofbiz.base.location.FlexibleLocation;

+import org.ofbiz.base.util.UtilHttp;

+import org.ofbiz.base.util.UtilValidate;

+import org.ofbiz.base.util.UtilXml;

+import org.ofbiz.base.util.cache.UtilCache;

+import org.w3c.dom.Document;

+import org.w3c.dom.Element;

+import org.xml.sax.SAXException;

+

+

+/**

+ * Widget Library - Menu factory class

+ */

+public class MenuFactory {

+

+    public static final String module = MenuFactory.class.getName();

+

+    public static final UtilCache<String, Map<String, ModelMenu>> menuWebappCache = UtilCache.createUtilCache("widget.menu.webappResource", 0, 0, false);

+    public static final UtilCache<String, Map<String, ModelMenu>> menuLocationCache = UtilCache.createUtilCache("widget.menu.locationResource", 0, 0, false);

+

+    public static ModelMenu getMenuFromWebappContext(String resourceName, String menuName, HttpServletRequest request)

+            throws IOException, SAXException, ParserConfigurationException {

+        String webappName = UtilHttp.getApplicationName(request);

+        String cacheKey = webappName + "::" + resourceName;

+

+        Map<String, ModelMenu> modelMenuMap = menuWebappCache.get(cacheKey);

+        if (modelMenuMap == null) {

+            synchronized (MenuFactory.class) {

+                modelMenuMap = menuWebappCache.get(cacheKey);

+                if (modelMenuMap == null) {

+                    ServletContext servletContext = (ServletContext) request.getAttribute("servletContext");

+

+                    URL menuFileUrl = servletContext.getResource(resourceName);

+                    Document menuFileDoc = UtilXml.readXmlDocument(menuFileUrl, true, true);

+                    modelMenuMap = readMenuDocument(menuFileDoc, cacheKey);

+                    menuWebappCache.put(cacheKey, modelMenuMap);

+                }

+            }

+        }

+

+        if (UtilValidate.isEmpty(modelMenuMap)) {

+            throw new IllegalArgumentException("Could not find menu file in webapp resource [" + resourceName + "] in the webapp [" + webappName + "]");

+        }

+

+        ModelMenu modelMenu = modelMenuMap.get(menuName);

+        if (modelMenu == null) {

+            throw new IllegalArgumentException("Could not find menu with name [" + menuName + "] in webapp resource [" + resourceName + "] in the webapp [" + webappName + "]");

+        }

+        return modelMenu;

+    }

+

+    public static Map<String, ModelMenu> readMenuDocument(Document menuFileDoc, String menuLocation) {

+        Map<String, ModelMenu> modelMenuMap = new HashMap<String, ModelMenu>();

+        if (menuFileDoc != null) {

+            // read document and construct ModelMenu for each menu element

+            Element rootElement = menuFileDoc.getDocumentElement();

+            for (Element menuElement: UtilXml.childElementList(rootElement, "menu")){

+                ModelMenu modelMenu = new ModelMenu(menuElement, menuLocation);

+                modelMenuMap.put(modelMenu.getName(), modelMenu);

+            }

+         }

+        return modelMenuMap;

+    }

+

+    public static ModelMenu getMenuFromLocation(String resourceName, String menuName) throws IOException, SAXException, ParserConfigurationException {

+        Map<String, ModelMenu> modelMenuMap = menuLocationCache.get(resourceName);

+        if (modelMenuMap == null) {

+            synchronized (MenuFactory.class) {

+                modelMenuMap = menuLocationCache.get(resourceName);

+                if (modelMenuMap == null) {

+                    URL menuFileUrl = FlexibleLocation.resolveLocation(resourceName);

+                    Document menuFileDoc = UtilXml.readXmlDocument(menuFileUrl, true, true);

+                    modelMenuMap = readMenuDocument(menuFileDoc, resourceName);

+                    menuLocationCache.put(resourceName, modelMenuMap);

+                }

+            }

+        }

+

+        if (UtilValidate.isEmpty(modelMenuMap)) {

+            throw new IllegalArgumentException("Could not find menu file in location [" + resourceName + "]");

+        }

+

+        ModelMenu modelMenu = modelMenuMap.get(menuName);

+        if (modelMenu == null) {

+            throw new IllegalArgumentException("Could not find menu with name [" + menuName + "] in location [" + resourceName + "]");

+        }

+        return modelMenu;

+    }

+}

diff --git a/framework/widget/src/org/ofbiz/widget/ModelAction.java b/framework/widget/src/org/ofbiz/widget/model/ModelAction.java
similarity index 97%
rename from framework/widget/src/org/ofbiz/widget/ModelAction.java
rename to framework/widget/src/org/ofbiz/widget/model/ModelAction.java
index 19977a2..6503686 100644
--- a/framework/widget/src/org/ofbiz/widget/ModelAction.java
+++ b/framework/widget/src/org/ofbiz/widget/model/ModelAction.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations

  * under the License.

  *******************************************************************************/

-package org.ofbiz.widget;

+package org.ofbiz.widget.model;

 

 import java.util.Map;

 

diff --git a/framework/widget/src/org/ofbiz/widget/ModelActionVisitor.java b/framework/widget/src/org/ofbiz/widget/model/ModelActionVisitor.java
similarity index 93%
rename from framework/widget/src/org/ofbiz/widget/ModelActionVisitor.java
rename to framework/widget/src/org/ofbiz/widget/model/ModelActionVisitor.java
index 28c039c..84085a5 100644
--- a/framework/widget/src/org/ofbiz/widget/ModelActionVisitor.java
+++ b/framework/widget/src/org/ofbiz/widget/model/ModelActionVisitor.java
@@ -16,11 +16,7 @@
  * specific language governing permissions and limitations

  * under the License.

  *******************************************************************************/

-package org.ofbiz.widget;

-

-import org.ofbiz.widget.form.ModelFormAction;

-import org.ofbiz.widget.menu.ModelMenuAction;

-import org.ofbiz.widget.tree.ModelTreeAction;

+package org.ofbiz.widget.model;

 

 /**

  *  A <code>ModelAction</code> visitor.

diff --git a/framework/widget/src/org/ofbiz/widget/ModelCondition.java b/framework/widget/src/org/ofbiz/widget/model/ModelCondition.java
similarity index 97%
rename from framework/widget/src/org/ofbiz/widget/ModelCondition.java
rename to framework/widget/src/org/ofbiz/widget/model/ModelCondition.java
index b829fdb..b7f6ff9 100644
--- a/framework/widget/src/org/ofbiz/widget/ModelCondition.java
+++ b/framework/widget/src/org/ofbiz/widget/model/ModelCondition.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations

  * under the License.

  *******************************************************************************/

-package org.ofbiz.widget;

+package org.ofbiz.widget.model;

 

 import java.util.Map;

 

diff --git a/framework/widget/src/org/ofbiz/widget/ModelConditionFactory.java b/framework/widget/src/org/ofbiz/widget/model/ModelConditionFactory.java
similarity index 97%
rename from framework/widget/src/org/ofbiz/widget/ModelConditionFactory.java
rename to framework/widget/src/org/ofbiz/widget/model/ModelConditionFactory.java
index 0857f52..e47799d 100644
--- a/framework/widget/src/org/ofbiz/widget/ModelConditionFactory.java
+++ b/framework/widget/src/org/ofbiz/widget/model/ModelConditionFactory.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations

  * under the License.

  *******************************************************************************/

-package org.ofbiz.widget;

+package org.ofbiz.widget.model;

 

 import org.w3c.dom.Element;

 

diff --git a/framework/widget/src/org/ofbiz/widget/ModelConditionVisitor.java b/framework/widget/src/org/ofbiz/widget/model/ModelConditionVisitor.java
similarity index 68%
rename from framework/widget/src/org/ofbiz/widget/ModelConditionVisitor.java
rename to framework/widget/src/org/ofbiz/widget/model/ModelConditionVisitor.java
index 7bc9684..a60dd39 100644
--- a/framework/widget/src/org/ofbiz/widget/ModelConditionVisitor.java
+++ b/framework/widget/src/org/ofbiz/widget/model/ModelConditionVisitor.java
@@ -16,23 +16,21 @@
  * specific language governing permissions and limitations

  * under the License.

  *******************************************************************************/

-package org.ofbiz.widget;

+package org.ofbiz.widget.model;

 

-import org.ofbiz.widget.AbstractModelCondition.And;

-import org.ofbiz.widget.AbstractModelCondition.IfCompare;

-import org.ofbiz.widget.AbstractModelCondition.IfCompareField;

-import org.ofbiz.widget.AbstractModelCondition.IfEmpty;

-import org.ofbiz.widget.AbstractModelCondition.IfEntityPermission;

-import org.ofbiz.widget.AbstractModelCondition.IfHasPermission;

-import org.ofbiz.widget.AbstractModelCondition.IfRegexp;

-import org.ofbiz.widget.AbstractModelCondition.IfServicePermission;

-import org.ofbiz.widget.AbstractModelCondition.IfValidateMethod;

-import org.ofbiz.widget.AbstractModelCondition.Not;

-import org.ofbiz.widget.AbstractModelCondition.Or;

-import org.ofbiz.widget.AbstractModelCondition.Xor;

-import org.ofbiz.widget.menu.ModelMenuCondition;

-import org.ofbiz.widget.screen.ModelScreenCondition.IfEmptySection;

-import org.ofbiz.widget.tree.ModelTreeCondition;

+import org.ofbiz.widget.model.AbstractModelCondition.And;

+import org.ofbiz.widget.model.AbstractModelCondition.IfCompare;

+import org.ofbiz.widget.model.AbstractModelCondition.IfCompareField;

+import org.ofbiz.widget.model.AbstractModelCondition.IfEmpty;

+import org.ofbiz.widget.model.AbstractModelCondition.IfEntityPermission;

+import org.ofbiz.widget.model.AbstractModelCondition.IfHasPermission;

+import org.ofbiz.widget.model.AbstractModelCondition.IfRegexp;

+import org.ofbiz.widget.model.AbstractModelCondition.IfServicePermission;

+import org.ofbiz.widget.model.AbstractModelCondition.IfValidateMethod;

+import org.ofbiz.widget.model.AbstractModelCondition.Not;

+import org.ofbiz.widget.model.AbstractModelCondition.Or;

+import org.ofbiz.widget.model.AbstractModelCondition.Xor;

+import org.ofbiz.widget.model.ModelScreenCondition.IfEmptySection;

 

 /**

  *  A <code>ModelCondition</code> visitor.

diff --git a/framework/widget/src/org/ofbiz/widget/ModelFieldVisitor.java b/framework/widget/src/org/ofbiz/widget/model/ModelFieldVisitor.java
similarity index 65%
rename from framework/widget/src/org/ofbiz/widget/ModelFieldVisitor.java
rename to framework/widget/src/org/ofbiz/widget/model/ModelFieldVisitor.java
index bf06bf7..753971b 100644
--- a/framework/widget/src/org/ofbiz/widget/ModelFieldVisitor.java
+++ b/framework/widget/src/org/ofbiz/widget/model/ModelFieldVisitor.java
@@ -16,29 +16,29 @@
  * specific language governing permissions and limitations

  * under the License.

  *******************************************************************************/

-package org.ofbiz.widget;

+package org.ofbiz.widget.model;

 

-import org.ofbiz.widget.form.ModelFormField.CheckField;

-import org.ofbiz.widget.form.ModelFormField.ContainerField;

-import org.ofbiz.widget.form.ModelFormField.DateFindField;

-import org.ofbiz.widget.form.ModelFormField.DateTimeField;

-import org.ofbiz.widget.form.ModelFormField.DisplayEntityField;

-import org.ofbiz.widget.form.ModelFormField.DisplayField;

-import org.ofbiz.widget.form.ModelFormField.DropDownField;

-import org.ofbiz.widget.form.ModelFormField.FileField;

-import org.ofbiz.widget.form.ModelFormField.HiddenField;

-import org.ofbiz.widget.form.ModelFormField.HyperlinkField;

-import org.ofbiz.widget.form.ModelFormField.IgnoredField;

-import org.ofbiz.widget.form.ModelFormField.ImageField;

-import org.ofbiz.widget.form.ModelFormField.LookupField;

-import org.ofbiz.widget.form.ModelFormField.PasswordField;

-import org.ofbiz.widget.form.ModelFormField.RadioField;

-import org.ofbiz.widget.form.ModelFormField.RangeFindField;

-import org.ofbiz.widget.form.ModelFormField.ResetField;

-import org.ofbiz.widget.form.ModelFormField.SubmitField;

-import org.ofbiz.widget.form.ModelFormField.TextField;

-import org.ofbiz.widget.form.ModelFormField.TextFindField;

-import org.ofbiz.widget.form.ModelFormField.TextareaField;

+import org.ofbiz.widget.model.ModelFormField.CheckField;

+import org.ofbiz.widget.model.ModelFormField.ContainerField;

+import org.ofbiz.widget.model.ModelFormField.DateFindField;

+import org.ofbiz.widget.model.ModelFormField.DateTimeField;

+import org.ofbiz.widget.model.ModelFormField.DisplayEntityField;

+import org.ofbiz.widget.model.ModelFormField.DisplayField;

+import org.ofbiz.widget.model.ModelFormField.DropDownField;

+import org.ofbiz.widget.model.ModelFormField.FileField;

+import org.ofbiz.widget.model.ModelFormField.HiddenField;

+import org.ofbiz.widget.model.ModelFormField.HyperlinkField;

+import org.ofbiz.widget.model.ModelFormField.IgnoredField;

+import org.ofbiz.widget.model.ModelFormField.ImageField;

+import org.ofbiz.widget.model.ModelFormField.LookupField;

+import org.ofbiz.widget.model.ModelFormField.PasswordField;

+import org.ofbiz.widget.model.ModelFormField.RadioField;

+import org.ofbiz.widget.model.ModelFormField.RangeFindField;

+import org.ofbiz.widget.model.ModelFormField.ResetField;

+import org.ofbiz.widget.model.ModelFormField.SubmitField;

+import org.ofbiz.widget.model.ModelFormField.TextField;

+import org.ofbiz.widget.model.ModelFormField.TextFindField;

+import org.ofbiz.widget.model.ModelFormField.TextareaField;

 

 /**

  *  A <code>ModelFormField</code> visitor.

diff --git a/framework/widget/src/org/ofbiz/widget/form/ModelForm.java b/framework/widget/src/org/ofbiz/widget/model/ModelForm.java
similarity index 99%
rename from framework/widget/src/org/ofbiz/widget/form/ModelForm.java
rename to framework/widget/src/org/ofbiz/widget/model/ModelForm.java
index 41f981d..73b87bb 100644
--- a/framework/widget/src/org/ofbiz/widget/form/ModelForm.java
+++ b/framework/widget/src/org/ofbiz/widget/model/ModelForm.java
@@ -1,1858 +1,1854 @@
-/*******************************************************************************
- * 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.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-import java.util.Set;
-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.UtilCodec;
-import org.ofbiz.base.util.UtilGenerics;
-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.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.service.DispatchContext;
-import org.ofbiz.service.GenericServiceException;
-import org.ofbiz.service.ModelParam;
-import org.ofbiz.service.ModelService;
-import org.ofbiz.widget.AbstractModelAction;
-import org.ofbiz.widget.CommonWidgetModels;
-import org.ofbiz.widget.ModelAction;
-import org.ofbiz.widget.ModelWidget;
-import org.ofbiz.widget.ModelWidgetVisitor;
-import org.ofbiz.widget.WidgetWorker;
-import org.w3c.dom.Element;
-
-import bsh.EvalError;
-import bsh.Interpreter;
-
-/**
- * Models the &lt;form&gt; element.
- * 
- * @see <code>widget-form.xsd</code>
- */
-@SuppressWarnings("serial")
-public class ModelForm extends ModelWidget {
-
-    /*
-     * ----------------------------------------------------------------------- *
-     *                     DEVELOPERS PLEASE READ
-     * ----------------------------------------------------------------------- *
-     * 
-     * This model is intended to be a read-only data structure that represents
-     * an XML element. Outside of object construction, the class should not
-     * have any behaviors. All behavior should be contained in model visitors.
-     * 
-     * Instances of this class will be shared by multiple threads - therefore
-     * it is immutable. DO NOT CHANGE THE OBJECT'S STATE AT RUN TIME!
-     * 
-     * BE VERY CAREFUL when implementing "extends" - parent form collections
-     * must be added to child collections, not replace them. In other words,
-     * do not assign parent collection fields to child collection fields.
-     * 
-     */
-
-    public static final String module = ModelForm.class.getName();
-    public static final String DEFAULT_FORM_RESULT_LIST_NAME = "defaultFormResultList";
-    /** Pagination settings and defaults. */
-    public static int DEFAULT_PAGE_SIZE = 10;
-    public static int MAX_PAGE_SIZE = 10000;
-    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";
-    private final List<ModelAction> actions;
-    private final List<AltRowStyle> altRowStyles;
-    private final List<AltTarget> altTargets;
-    private final List<AutoFieldsEntity> autoFieldsEntities;
-    private final List<AutoFieldsService> autoFieldsServices;
-    private final boolean clientAutocompleteFields;
-    private final String containerId;
-    private final String containerStyle;
-    private final String defaultEntityName;
-    /** This field group will be the "catch-all" group for fields that are not
-     *  included in an explicit field-group.
-     */
-    private final FieldGroup defaultFieldGroup;
-    private final FlexibleMapAccessor<Map<String, ? extends Object>> defaultMapName;
-    private final String defaultRequiredFieldStyle;
-    private final String defaultServiceName;
-    private final String defaultSortFieldAscStyle;
-    private final String defaultSortFieldDescStyle;
-    private final String defaultSortFieldStyle;
-    private final String defaultTableStyle;
-    private final String defaultTitleAreaStyle;
-    private final String defaultTitleStyle;
-    private final String defaultTooltipStyle;
-    private final int defaultViewSize;
-    private final String defaultWidgetAreaStyle;
-    private final String defaultWidgetStyle;
-    private final String evenRowStyle;
-    /** This is a list of FieldGroups in the order they were created.
-     * Can also include Banner objects.
-     */
-    private final List<FieldGroupBase> fieldGroupList;
-    /** This Map is keyed with the field name and has a FieldGroup for the value.
-     * Can also include Banner objects.
-     */
-    private final Map<String, FieldGroupBase> fieldGroupMap;
-    /** 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.
-     */
-    private final List<ModelFormField> fieldList;
-    private final String focusFieldName;
-    private final String formLocation;
-    private final String formTitleAreaStyle;
-    private final String formWidgetAreaStyle;
-    private final boolean groupColumns;
-    private final String headerRowStyle;
-    private final boolean hideHeader;
-    private final String itemIndexSeparator;
-    private final List<String> lastOrderFields;
-    private final String listEntryName;
-    private final String listName;
-    private final List<ModelFormField> multiSubmitFields;
-    private final String oddRowStyle;
-    /** On Paginate areas to be updated. */
-    private final List<UpdateArea> onPaginateUpdateAreas;
-    /** On Sort Column areas to be updated. */
-    private final List<UpdateArea> onSortColumnUpdateAreas;
-    /** On Submit areas to be updated. */
-    private final List<UpdateArea> onSubmitUpdateAreas;
-    private final FlexibleStringExpander overrideListSize;
-    private final FlexibleStringExpander paginate;
-    private final FlexibleStringExpander paginateFirstLabel;
-    private final FlexibleStringExpander paginateIndexField;
-    private final FlexibleStringExpander paginateLastLabel;
-    private final FlexibleStringExpander paginateNextLabel;
-    private final FlexibleStringExpander paginatePreviousLabel;
-    private final FlexibleStringExpander paginateSizeField;
-    private final String paginateStyle;
-    private final FlexibleStringExpander paginateTarget;
-    private final String paginateTargetAnchor;
-    private final FlexibleStringExpander paginateViewSizeLabel;
-    private final ModelForm parentModelForm;
-    private final List<ModelAction> rowActions;
-    private final FlexibleStringExpander rowCountExdr;
-    private final boolean separateColumns;
-    private final boolean skipEnd;
-    private final boolean skipStart;
-    private final String sortFieldParameterName;
-    private final List<SortField> sortOrderFields;
-    private final FlexibleStringExpander target;
-    private final String targetType;
-    private final FlexibleStringExpander targetWindowExdr;
-    private final String title;
-    private final String tooltip;
-    private final String type;
-    private final boolean useRowSubmit;
-    /** Keeps track of conditional fields to help ensure that only one is rendered
-     */
-    private final Set<String> useWhenFields;
-
-    /** XML Constructor */
-    public ModelForm(Element formElement, String formLocation, ModelReader entityModelReader, DispatchContext dispatchContext) {
-        super(formElement);
-        this.formLocation = formLocation;
-        parentModelForm = getParentForm(formElement, entityModelReader, dispatchContext);
-        int defaultViewSizeInt = DEFAULT_PAGE_SIZE;
-        String viewSize = formElement.getAttribute("view-size");
-        if (viewSize.isEmpty()) {
-            if (parentModelForm != null) {
-                defaultViewSizeInt = parentModelForm.defaultViewSize;
-            } else {
-                defaultViewSizeInt = UtilProperties.getPropertyAsInteger("widget.properties", "widget.form.defaultViewSize",
-                        defaultViewSizeInt);
-            }
-        } else {
-            try {
-                defaultViewSizeInt = Integer.valueOf(viewSize);
-            } catch (NumberFormatException e) {
-            }
-        }
-        this.defaultViewSize = defaultViewSizeInt;
-        String type = formElement.getAttribute("type");
-        if (type.isEmpty() && parentModelForm != null) {
-            type = parentModelForm.type;
-        }
-        this.type = type;
-        FlexibleStringExpander target = FlexibleStringExpander.getInstance(formElement.getAttribute("target"));
-        if (target.isEmpty() && parentModelForm != null) {
-            target = parentModelForm.target;
-        }
-        this.target = target;
-        String containerId = formElement.getAttribute("id");
-        if (containerId.isEmpty() && parentModelForm != null) {
-            containerId = parentModelForm.containerId;
-        }
-        this.containerId = containerId;
-        String containerStyle = formElement.getAttribute("style");
-        if (containerStyle.isEmpty() && parentModelForm != null) {
-            containerStyle = parentModelForm.containerStyle;
-        }
-        this.containerStyle = containerStyle;
-        String title = formElement.getAttribute("title");
-        if (title.isEmpty() && parentModelForm != null) {
-            title = parentModelForm.title;
-        }
-        this.title = title;
-        String tooltip = formElement.getAttribute("tooltip");
-        if (tooltip.isEmpty() && parentModelForm != null) {
-            tooltip = parentModelForm.tooltip;
-        }
-        this.tooltip = tooltip;
-        String listName = formElement.getAttribute("list-name");
-        if (listName.isEmpty()) {
-            if (parentModelForm != null) {
-                listName = parentModelForm.listName;
-            } else {
-                listName = DEFAULT_FORM_RESULT_LIST_NAME;
-            }
-        }
-        this.listName = listName;
-        String listEntryName = formElement.getAttribute("list-entry-name");
-        if (listEntryName.isEmpty() && parentModelForm != null) {
-            listEntryName = parentModelForm.listEntryName;
-        }
-        this.listEntryName = listEntryName;
-        String defaultEntityName = formElement.getAttribute("default-entity-name");
-        if (defaultEntityName.isEmpty() && parentModelForm != null) {
-            defaultEntityName = parentModelForm.defaultEntityName;
-        }
-        this.defaultEntityName = defaultEntityName;
-        String defaultServiceName = formElement.getAttribute("default-service-name");
-        if (defaultServiceName.isEmpty() && parentModelForm != null) {
-            defaultServiceName = parentModelForm.defaultServiceName;
-        }
-        this.defaultServiceName = defaultServiceName;
-        String formTitleAreaStyle = formElement.getAttribute("form-title-area-style");
-        if (formTitleAreaStyle.isEmpty() && parentModelForm != null) {
-            formTitleAreaStyle = parentModelForm.formTitleAreaStyle;
-        }
-        this.formTitleAreaStyle = formTitleAreaStyle;
-        String formWidgetAreaStyle = formElement.getAttribute("form-widget-area-style");
-        if (formWidgetAreaStyle.isEmpty() && parentModelForm != null) {
-            formWidgetAreaStyle = parentModelForm.formWidgetAreaStyle;
-        }
-        this.formWidgetAreaStyle = formWidgetAreaStyle;
-        String defaultTitleAreaStyle = formElement.getAttribute("default-title-area-style");
-        if (defaultTitleAreaStyle.isEmpty() && parentModelForm != null) {
-            defaultTitleAreaStyle = parentModelForm.defaultTitleAreaStyle;
-        }
-        this.defaultTitleAreaStyle = defaultTitleAreaStyle;
-        String defaultWidgetAreaStyle = formElement.getAttribute("default-widget-area-style");
-        if (defaultWidgetAreaStyle.isEmpty() && parentModelForm != null) {
-            defaultWidgetAreaStyle = parentModelForm.defaultWidgetAreaStyle;
-        }
-        this.defaultWidgetAreaStyle = defaultWidgetAreaStyle;
-        String oddRowStyle = formElement.getAttribute("odd-row-style");
-        if (oddRowStyle.isEmpty() && parentModelForm != null) {
-            oddRowStyle = parentModelForm.oddRowStyle;
-        }
-        this.oddRowStyle = oddRowStyle;
-        String evenRowStyle = formElement.getAttribute("even-row-style");
-        if (evenRowStyle.isEmpty() && parentModelForm != null) {
-            evenRowStyle = parentModelForm.evenRowStyle;
-        }
-        this.evenRowStyle = evenRowStyle;
-        String defaultTableStyle = formElement.getAttribute("default-table-style");
-        if (defaultTableStyle.isEmpty() && parentModelForm != null) {
-            defaultTableStyle = parentModelForm.defaultTableStyle;
-        }
-        this.defaultTableStyle = defaultTableStyle;
-        String headerRowStyle = formElement.getAttribute("header-row-style");
-        if (headerRowStyle.isEmpty() && parentModelForm != null) {
-            headerRowStyle = parentModelForm.headerRowStyle;
-        }
-        this.headerRowStyle = headerRowStyle;
-        String defaultTitleStyle = formElement.getAttribute("default-title-style");
-        if (defaultTitleStyle.isEmpty() && parentModelForm != null) {
-            defaultTitleStyle = parentModelForm.defaultTitleStyle;
-        }
-        this.defaultTitleStyle = defaultTitleStyle;
-        String defaultWidgetStyle = formElement.getAttribute("default-widget-style");
-        if (defaultWidgetStyle.isEmpty() && parentModelForm != null) {
-            defaultWidgetStyle = parentModelForm.defaultWidgetStyle;
-        }
-        this.defaultWidgetStyle = defaultWidgetStyle;
-        String defaultTooltipStyle = formElement.getAttribute("default-tooltip-style");
-        if (defaultTooltipStyle.isEmpty() && parentModelForm != null) {
-            defaultTooltipStyle = parentModelForm.defaultTooltipStyle;
-        }
-        this.defaultTooltipStyle = defaultTooltipStyle;
-        String itemIndexSeparator = formElement.getAttribute("item-index-separator");
-        if (itemIndexSeparator.isEmpty() && parentModelForm != null) {
-            itemIndexSeparator = parentModelForm.itemIndexSeparator;
-        }
-        this.itemIndexSeparator = itemIndexSeparator;
-        String separateColumns = formElement.getAttribute("separate-columns");
-        if (separateColumns.isEmpty() && parentModelForm != null) {
-            this.separateColumns = parentModelForm.separateColumns;
-        } else {
-            this.separateColumns = "true".equals(separateColumns);
-        }
-        String groupColumns = formElement.getAttribute("group-columns");
-        if (groupColumns.isEmpty() && parentModelForm != null) {
-            this.groupColumns = parentModelForm.groupColumns;
-        } else {
-            this.groupColumns = !"false".equals(groupColumns);
-        }
-        String targetType = formElement.getAttribute("target-type");
-        if (targetType.isEmpty() && parentModelForm != null) {
-            targetType = parentModelForm.targetType;
-        }
-        this.targetType = targetType;
-        FlexibleMapAccessor<Map<String, ? extends Object>> defaultMapName = FlexibleMapAccessor.getInstance(formElement
-                .getAttribute("default-map-name"));
-        if (defaultMapName.isEmpty() && parentModelForm != null) {
-            defaultMapName = parentModelForm.defaultMapName;
-        }
-        this.defaultMapName = defaultMapName;
-        FlexibleStringExpander targetWindowExdr = FlexibleStringExpander.getInstance(formElement.getAttribute("target-window"));
-        if (targetWindowExdr.isEmpty() && parentModelForm != null) {
-            targetWindowExdr = parentModelForm.targetWindowExdr;
-        }
-        this.targetWindowExdr = targetWindowExdr;
-        String hideHeader = formElement.getAttribute("hide-header");
-        if (hideHeader.isEmpty() && parentModelForm != null) {
-            this.hideHeader = parentModelForm.hideHeader;
-        } else {
-            this.hideHeader = "true".equals(hideHeader);
-        }
-        String clientAutocompleteFields = formElement.getAttribute("client-autocomplete-fields");
-        if (clientAutocompleteFields.isEmpty() && parentModelForm != null) {
-            this.clientAutocompleteFields = parentModelForm.clientAutocompleteFields;
-        } else {
-            this.clientAutocompleteFields = !"false".equals(formElement.getAttribute("client-autocomplete-fields"));
-        }
-        FlexibleStringExpander paginateTarget = FlexibleStringExpander.getInstance(formElement.getAttribute("paginate-target"));
-        if (paginateTarget.isEmpty() && parentModelForm != null) {
-            paginateTarget = parentModelForm.paginateTarget;
-        }
-        this.paginateTarget = paginateTarget;
-        ArrayList<AltTarget> altTargets = new ArrayList<AltTarget>();
-        if (parentModelForm != null) {
-            altTargets.addAll(parentModelForm.altTargets);
-        }
-        for (Element altTargetElement : UtilXml.childElementList(formElement, "alt-target")) {
-            altTargets.add(new AltTarget(altTargetElement));
-        }
-        altTargets.trimToSize();
-        this.altTargets = Collections.unmodifiableList(altTargets);
-        ArrayList<ModelAction> actions = new ArrayList<ModelAction>();
-        if (parentModelForm != null) {
-            actions.addAll(parentModelForm.actions);
-        }
-        Element actionsElement = UtilXml.firstChildElement(formElement, "actions");
-        if (actionsElement != null) {
-            actions.addAll(ModelFormAction.readSubActions(this, actionsElement));
-        }
-        actions.trimToSize();
-        this.actions = Collections.unmodifiableList(actions);
-        ArrayList<ModelAction> rowActions = new ArrayList<ModelAction>();
-        if (parentModelForm != null) {
-            rowActions.addAll(parentModelForm.rowActions);
-        }
-        Element rowActionsElement = UtilXml.firstChildElement(formElement, "row-actions");
-        if (rowActionsElement != null) {
-            rowActions.addAll(ModelFormAction.readSubActions(this, rowActionsElement));
-        }
-        rowActions.trimToSize();
-        this.rowActions = Collections.unmodifiableList(rowActions);
-        ArrayList<UpdateArea> onPaginateUpdateAreas = new ArrayList<UpdateArea>();
-        ArrayList<UpdateArea> onSubmitUpdateAreas = new ArrayList<UpdateArea>();
-        ArrayList<UpdateArea> onSortColumnUpdateAreas = new ArrayList<UpdateArea>();
-        if (parentModelForm != null) {
-            onPaginateUpdateAreas.addAll(parentModelForm.onPaginateUpdateAreas);
-            onSubmitUpdateAreas.addAll(parentModelForm.onSubmitUpdateAreas);
-            onSortColumnUpdateAreas.addAll(parentModelForm.onSortColumnUpdateAreas);
-        }
-        for (Element updateAreaElement : UtilXml.childElementList(formElement, "on-event-update-area")) {
-            UpdateArea updateArea = new UpdateArea(updateAreaElement, defaultServiceName, defaultEntityName);
-            if ("paginate".equals(updateArea.getEventType())) {
-                int index = onPaginateUpdateAreas.indexOf(updateArea);
-                if (index != -1) {
-                    if (!updateArea.areaTarget.isEmpty()) {
-                        onPaginateUpdateAreas.set(index, updateArea);
-                    } else {
-                        // blank target indicates a removing override
-                        onPaginateUpdateAreas.remove(index);
-                    }
-                } else {
-                    onPaginateUpdateAreas.add(updateArea);
-                }
-            } else if ("submit".equals(updateArea.getEventType())) {
-                int index = onSubmitUpdateAreas.indexOf(updateArea);
-                if (index != -1) {
-                    onSubmitUpdateAreas.set(index, updateArea);
-                } else {
-                    onSubmitUpdateAreas.add(updateArea);
-                }
-            } else if ("sort-column".equals(updateArea.getEventType())) {
-                int index = onSortColumnUpdateAreas.indexOf(updateArea);
-                if (index != -1) {
-                    if (!updateArea.areaTarget.isEmpty()) {
-                        onSortColumnUpdateAreas.set(index, updateArea);
-                    } else {
-                        // blank target indicates a removing override
-                        onSortColumnUpdateAreas.remove(index);
-                    }
-                } else {
-                    onSortColumnUpdateAreas.add(updateArea);
-                }
-            }
-        }
-        onPaginateUpdateAreas.trimToSize();
-        this.onPaginateUpdateAreas = Collections.unmodifiableList(onPaginateUpdateAreas);
-        onSubmitUpdateAreas.trimToSize();
-        this.onSubmitUpdateAreas = Collections.unmodifiableList(onSubmitUpdateAreas);
-        onSortColumnUpdateAreas.trimToSize();
-        this.onSortColumnUpdateAreas = Collections.unmodifiableList(onSortColumnUpdateAreas);
-        ArrayList<AltRowStyle> altRowStyles = new ArrayList<AltRowStyle>();
-        if (parentModelForm != null) {
-            altRowStyles.addAll(parentModelForm.altRowStyles);
-        }
-        for (Element altRowStyleElement : UtilXml.childElementList(formElement, "alt-row-style")) {
-            AltRowStyle altRowStyle = new AltRowStyle(altRowStyleElement);
-            altRowStyles.add(altRowStyle);
-        }
-        altRowStyles.trimToSize();
-        this.altRowStyles = Collections.unmodifiableList(altRowStyles);
-        Set<String> useWhenFields = new HashSet<String>();
-        if (parentModelForm != null) {
-            useWhenFields.addAll(parentModelForm.useWhenFields);
-        }
-        ArrayList<ModelFormFieldBuilder> fieldBuilderList = new ArrayList<ModelFormFieldBuilder>();
-        Map<String, ModelFormFieldBuilder> fieldBuilderMap = new HashMap<String, ModelFormFieldBuilder>();
-        if (parentModelForm != null) {
-            // Create this fieldList/Map from clones of parentModelForm's
-            for (ModelFormField parentChildField : parentModelForm.fieldList) {
-                ModelFormFieldBuilder builder = new ModelFormFieldBuilder(parentChildField);
-                builder.setModelForm(this);
-                fieldBuilderList.add(builder);
-                fieldBuilderMap.put(builder.getName(), builder);
-            }
-        }
-        Map<String, FieldGroupBase> fieldGroupMap = new HashMap<String, FieldGroupBase>();
-        if (parentModelForm != null) {
-            fieldGroupMap.putAll(parentModelForm.fieldGroupMap);
-        }
-        ArrayList<FieldGroupBase> fieldGroupList = new ArrayList<FieldGroupBase>();
-        if (parentModelForm != null) {
-            fieldGroupList.addAll(parentModelForm.fieldGroupList);
-        }
-        ArrayList<String> lastOrderFields = new ArrayList<String>();
-        if (parentModelForm != null) {
-            lastOrderFields.addAll(parentModelForm.lastOrderFields);
-        }
-        String sortFieldParameterName = formElement.getAttribute("sort-field-parameter-name");
-        if (sortFieldParameterName.isEmpty() && parentModelForm != null) {
-            this.sortFieldParameterName = parentModelForm.targetType;
-        } else {
-            this.sortFieldParameterName = "sortField";
-        }
-        String defaultRequiredFieldStyle = formElement.getAttribute("default-required-field-style");
-        if (defaultRequiredFieldStyle.isEmpty() && parentModelForm != null) {
-            defaultRequiredFieldStyle = parentModelForm.defaultRequiredFieldStyle;
-        }
-        this.defaultRequiredFieldStyle = defaultRequiredFieldStyle;
-        String defaultSortFieldStyle = formElement.getAttribute("default-sort-field-style");
-        if (defaultSortFieldStyle.isEmpty() && parentModelForm != null) {
-            this.defaultSortFieldStyle = parentModelForm.defaultSortFieldStyle;
-        } else {
-            this.defaultSortFieldStyle = DEFAULT_SORT_FIELD_STYLE;
-        }
-        String defaultSortFieldAscStyle = formElement.getAttribute("default-sort-field-asc-style");
-        if (defaultSortFieldAscStyle.isEmpty() && parentModelForm != null) {
-            this.defaultSortFieldAscStyle = parentModelForm.defaultSortFieldAscStyle;
-        } else {
-            this.defaultSortFieldAscStyle = DEFAULT_SORT_FIELD_ASC_STYLE;
-        }
-        String defaultSortFieldDescStyle = formElement.getAttribute("default-sort-field-desc-style");
-        if (defaultSortFieldDescStyle.isEmpty() && parentModelForm != null) {
-            this.defaultSortFieldDescStyle = parentModelForm.defaultSortFieldDescStyle;
-        } else {
-            this.defaultSortFieldDescStyle = DEFAULT_SORT_FIELD_DESC_STYLE;
-        }
-        String paginateTargetAnchor = formElement.getAttribute("paginate-target-anchor");
-        if (paginateTargetAnchor.isEmpty() && parentModelForm != null) {
-            paginateTargetAnchor = parentModelForm.paginateTargetAnchor;
-        }
-        this.paginateTargetAnchor = paginateTargetAnchor;
-        FlexibleStringExpander paginateIndexField = FlexibleStringExpander.getInstance(formElement
-                .getAttribute("paginate-index-field"));
-        if (paginateIndexField.isEmpty() && parentModelForm != null) {
-            paginateIndexField = parentModelForm.paginateIndexField;
-        }
-        this.paginateIndexField = paginateIndexField;
-        FlexibleStringExpander paginateSizeField = FlexibleStringExpander.getInstance(formElement
-                .getAttribute("paginate-size-field"));
-        if (paginateSizeField.isEmpty() && parentModelForm != null) {
-            paginateSizeField = parentModelForm.paginateSizeField;
-        }
-        this.paginateSizeField = paginateSizeField;
-        FlexibleStringExpander overrideListSize = FlexibleStringExpander.getInstance(formElement
-                .getAttribute("override-list-size"));
-        if (overrideListSize.isEmpty() && parentModelForm != null) {
-            overrideListSize = parentModelForm.overrideListSize;
-        }
-        this.overrideListSize = overrideListSize;
-        FlexibleStringExpander paginateFirstLabel = FlexibleStringExpander.getInstance(formElement
-                .getAttribute("paginate-first-label"));
-        if (paginateFirstLabel.isEmpty() && parentModelForm != null) {
-            paginateFirstLabel = parentModelForm.paginateFirstLabel;
-        }
-        this.paginateFirstLabel = paginateFirstLabel;
-        FlexibleStringExpander paginatePreviousLabel = FlexibleStringExpander.getInstance(formElement
-                .getAttribute("paginate-previous-label"));
-        if (paginatePreviousLabel.isEmpty() && parentModelForm != null) {
-            paginatePreviousLabel = parentModelForm.paginatePreviousLabel;
-        }
-        this.paginatePreviousLabel = paginatePreviousLabel;
-        FlexibleStringExpander paginateNextLabel = FlexibleStringExpander.getInstance(formElement
-                .getAttribute("paginate-next-label"));
-        if (paginateNextLabel.isEmpty() && parentModelForm != null) {
-            paginateNextLabel = parentModelForm.paginateNextLabel;
-        }
-        this.paginateNextLabel = paginateNextLabel;
-        FlexibleStringExpander paginateLastLabel = FlexibleStringExpander.getInstance(formElement
-                .getAttribute("paginate-last-label"));
-        if (paginateLastLabel.isEmpty() && parentModelForm != null) {
-            paginateLastLabel = parentModelForm.paginateLastLabel;
-        }
-        this.paginateLastLabel = paginateLastLabel;
-        FlexibleStringExpander paginateViewSizeLabel = FlexibleStringExpander.getInstance(formElement
-                .getAttribute("paginate-viewsize-label"));
-        if (paginateViewSizeLabel.isEmpty() && parentModelForm != null) {
-            paginateViewSizeLabel = parentModelForm.paginateViewSizeLabel;
-        }
-        this.paginateViewSizeLabel = paginateViewSizeLabel;
-        String paginateStyle = formElement.getAttribute("paginate-style");
-        if (paginateStyle.isEmpty() && parentModelForm != null) {
-            this.paginateStyle = parentModelForm.paginateStyle;
-        } else {
-            this.paginateStyle = DEFAULT_PAG_STYLE;
-        }
-        FlexibleStringExpander paginate = FlexibleStringExpander.getInstance(formElement.getAttribute("paginate"));
-        if (paginate.isEmpty() && parentModelForm != null) {
-            paginate = parentModelForm.paginate;
-        }
-        this.paginate = paginate;
-        String skipStart = formElement.getAttribute("skip-start");
-        if (skipStart.isEmpty() && parentModelForm != null) {
-            this.skipStart = parentModelForm.skipStart;
-        } else {
-            this.skipStart = "true".equals(skipStart);
-        }
-        String skipEnd = formElement.getAttribute("skip-end");
-        if (skipEnd.isEmpty() && parentModelForm != null) {
-            this.skipEnd = parentModelForm.skipEnd;
-        } else {
-            this.skipEnd = "true".equals(skipEnd);
-        }
-        String useRowSubmit = formElement.getAttribute("use-row-submit");
-        if (useRowSubmit.isEmpty() && parentModelForm != null) {
-            this.useRowSubmit = parentModelForm.useRowSubmit;
-        } else {
-            this.useRowSubmit = "true".equals(useRowSubmit);
-        }
-        FlexibleStringExpander rowCountExdr = FlexibleStringExpander.getInstance(formElement.getAttribute("row-count"));
-        if (rowCountExdr.isEmpty() && parentModelForm != null) {
-            rowCountExdr = parentModelForm.rowCountExdr;
-        }
-        this.rowCountExdr = paginate;
-        ArrayList<ModelFormFieldBuilder> multiSubmitBuilders = new ArrayList<ModelFormFieldBuilder>();
-        ArrayList<AutoFieldsService> autoFieldsServices = new ArrayList<AutoFieldsService>();
-        ArrayList<AutoFieldsEntity> autoFieldsEntities = new ArrayList<AutoFieldsEntity>();
-        ArrayList<SortField> sortOrderFields = new ArrayList<SortField>();
-        this.defaultFieldGroup = new FieldGroup(null, this, sortOrderFields, fieldGroupMap);
-        for (Element autoFieldsServiceElement : UtilXml.childElementList(formElement, "auto-fields-service")) {
-            AutoFieldsService autoFieldsService = new AutoFieldsService(autoFieldsServiceElement);
-            autoFieldsServices.add(autoFieldsService);
-            addAutoFieldsFromService(autoFieldsService, entityModelReader, dispatchContext, useWhenFields, fieldBuilderList, fieldBuilderMap);
-        }
-        for (Element autoFieldsEntityElement : UtilXml.childElementList(formElement, "auto-fields-entity")) {
-            AutoFieldsEntity autoFieldsEntity = new AutoFieldsEntity(autoFieldsEntityElement);
-            autoFieldsEntities.add(autoFieldsEntity);
-            addAutoFieldsFromEntity(autoFieldsEntity, entityModelReader, useWhenFields, fieldBuilderList, fieldBuilderMap);
-        }
-        String thisType = this.getType();
-        for (Element fieldElement : UtilXml.childElementList(formElement, "field")) {
-            ModelFormFieldBuilder builder = new ModelFormFieldBuilder(fieldElement, this, entityModelReader, dispatchContext);
-            FieldInfo fieldInfo = builder.getFieldInfo();
-            if (thisType.equals("multi") && fieldInfo instanceof ModelFormField.SubmitField) {
-                multiSubmitBuilders.add(builder);
-            } else {
-                addUpdateField(builder, useWhenFields, fieldBuilderList, fieldBuilderMap);
-            }
-        }
-        // get the sort-order
-        Element sortOrderElement = UtilXml.firstChildElement(formElement, "sort-order");
-        if (sortOrderElement != null) {
-            FieldGroup lastFieldGroup = new FieldGroup(null, this, sortOrderFields, fieldGroupMap);
-            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");
-                    sortOrderFields.add(new SortField(fieldName, position));
-                    fieldGroupMap.put(fieldName, lastFieldGroup);
-                } else if (tagName.equals("last-field")) {
-                    String fieldName = sortFieldElement.getAttribute("name");
-                    fieldGroupMap.put(fieldName, lastFieldGroup);
-                    lastOrderFields.add(fieldName);
-                } else if (tagName.equals("banner")) {
-                    Banner thisBanner = new Banner(sortFieldElement);
-                    fieldGroupList.add(thisBanner);
-                    lastFieldGroup = new FieldGroup(null, this, sortOrderFields, fieldGroupMap);
-                    fieldGroupList.add(lastFieldGroup);
-                } else if (tagName.equals("field-group")) {
-                    FieldGroup thisFieldGroup = new FieldGroup(sortFieldElement, this, sortOrderFields, fieldGroupMap);
-                    fieldGroupList.add(thisFieldGroup);
-                    lastFieldGroup = new FieldGroup(null, this, sortOrderFields, fieldGroupMap);
-                    fieldGroupList.add(lastFieldGroup);
-                }
-            }
-        }
-        if (sortOrderFields.size() > 0) {
-            ArrayList<ModelFormFieldBuilder> sortedFields = new ArrayList<ModelFormFieldBuilder>();
-            for (SortField sortField : 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<ModelFormFieldBuilder> fieldIter = fieldBuilderList.iterator();
-                while (fieldIter.hasNext()) {
-                    ModelFormFieldBuilder builder = fieldIter.next();
-                    if (fieldName.equals(builder.getName())) {
-                        // matched the name; remove from the original last and add to the sorted list
-                        if (UtilValidate.isNotEmpty(sortField.getPosition())) {
-                            builder.setPosition(sortField.getPosition());
-                        }
-                        fieldIter.remove();
-                        sortedFields.add(builder);
-                    }
-                }
-            }
-            // now add all of the rest of the fields from fieldList, ie those that were not explicitly listed in the sort order
-            sortedFields.addAll(fieldBuilderList);
-            // sortedFields all done, set fieldList
-            fieldBuilderList = sortedFields;
-        }
-        if (UtilValidate.isNotEmpty(lastOrderFields)) {
-            List<ModelFormFieldBuilder> lastedFields = new LinkedList<ModelFormFieldBuilder>();
-            for (String fieldName : lastOrderFields) {
-                if (UtilValidate.isEmpty(fieldName)) {
-                    continue;
-                }
-                // get all fields with the given name from the existing list and put them in the lasted list
-                Iterator<ModelFormFieldBuilder> fieldIter = fieldBuilderList.iterator();
-                while (fieldIter.hasNext()) {
-                    ModelFormFieldBuilder builder = fieldIter.next();
-                    if (fieldName.equals(builder.getName())) {
-                        // matched the name; remove from the original last and add to the lasted list
-                        fieldIter.remove();
-                        lastedFields.add(builder);
-                    }
-                }
-            }
-            //now put all lastedFields at the field list end
-            fieldBuilderList.addAll(lastedFields);
-        }
-        List<ModelFormField> fieldList = new ArrayList<ModelFormField>(fieldBuilderList.size());
-        for (ModelFormFieldBuilder builder : fieldBuilderList) {
-            fieldList.add(builder.build());
-        }
-        this.fieldList = Collections.unmodifiableList(fieldList);
-        List<ModelFormField> multiSubmitFields = new ArrayList<ModelFormField>(multiSubmitBuilders.size());
-        for (ModelFormFieldBuilder builder : multiSubmitBuilders) {
-            multiSubmitFields.add(builder.build());
-        }
-        this.multiSubmitFields = Collections.unmodifiableList(multiSubmitFields);
-        this.useWhenFields = Collections.unmodifiableSet(useWhenFields);
-        this.fieldGroupMap = Collections.unmodifiableMap(fieldGroupMap);
-        fieldGroupList.trimToSize();
-        this.fieldGroupList = Collections.unmodifiableList(fieldGroupList);
-        lastOrderFields.trimToSize();
-        this.lastOrderFields = Collections.unmodifiableList(lastOrderFields);
-        autoFieldsServices.trimToSize();
-        this.autoFieldsServices = Collections.unmodifiableList(autoFieldsServices);
-        autoFieldsEntities.trimToSize();
-        this.autoFieldsEntities = Collections.unmodifiableList(autoFieldsEntities);
-        sortOrderFields.trimToSize();
-        this.sortOrderFields = Collections.unmodifiableList(sortOrderFields);
-        String focusFieldName = formElement.getAttribute("focus-field-name");
-        if (focusFieldName.isEmpty() && parentModelForm != null) {
-            focusFieldName = parentModelForm.focusFieldName;
-        }
-        this.focusFieldName = focusFieldName;
-    }
-
-    @Override
-    public void accept(ModelWidgetVisitor visitor) throws Exception {
-        visitor.visit(this);
-    }
-
-    private void addAutoFieldsFromEntity(AutoFieldsEntity autoFieldsEntity, ModelReader entityModelReader,
-            Set<String> useWhenFields, List<ModelFormFieldBuilder> fieldBuilderList, Map<String, ModelFormFieldBuilder> fieldBuilderMap) {
-        // read entity def and auto-create fields
-        ModelEntity modelEntity = null;
-        try {
-            modelEntity = 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;
-            }
-            ModelFormFieldBuilder builder = new ModelFormFieldBuilder();
-            builder.setModelForm(this);
-            builder.setName(modelField.getName());
-            builder.setEntityName(modelEntity.getEntityName());
-            builder.setFieldName(modelField.getName());
-            builder.induceFieldInfoFromEntityField(modelEntity, modelField, autoFieldsEntity.defaultFieldType);
-            builder.setPosition(autoFieldsEntity.defaultPosition);
-            if (UtilValidate.isNotEmpty(autoFieldsEntity.mapName)) {
-                builder.setMapName(autoFieldsEntity.mapName);
-            }
-            addUpdateField(builder, useWhenFields, fieldBuilderList, fieldBuilderMap);
-        }
-    }
-
-    private void addAutoFieldsFromService(AutoFieldsService autoFieldsService, ModelReader entityModelReader,
-            DispatchContext dispatchContext, Set<String> useWhenFields, List<ModelFormFieldBuilder> fieldBuilderList,
-            Map<String, ModelFormFieldBuilder> fieldBuilderMap) {
-        // read service def and auto-create fields
-        ModelService modelService = null;
-        try {
-            modelService = 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()) {
-            if (modelParam.internal) {
-                // skip auto params that the service engine populates...
-                continue;
-            }
-            if (modelParam.formDisplay) {
-                if (UtilValidate.isNotEmpty(modelParam.entityName) && UtilValidate.isNotEmpty(modelParam.fieldName)) {
-                    ModelEntity modelEntity;
-                    try {
-                        modelEntity = entityModelReader.getModelEntity(modelParam.entityName);
-                        if (modelEntity != null) {
-                            ModelField modelField = modelEntity.getField(modelParam.fieldName);
-                            if (modelField != null) {
-                                // okay, populate using the entity field info...
-                                ModelFormFieldBuilder builder = new ModelFormFieldBuilder();
-                                builder.setModelForm(this);
-                                builder.setName(modelField.getName());
-                                builder.setEntityName(modelEntity.getEntityName());
-                                builder.setFieldName(modelField.getName());
-                                builder.induceFieldInfoFromEntityField(modelEntity, modelField, autoFieldsService.defaultFieldType);
-                                if (UtilValidate.isNotEmpty(autoFieldsService.mapName)) {
-                                    builder.setMapName(autoFieldsService.mapName);
-                                }
-                                builder.setRequiredField(!modelParam.optional);
-                                addUpdateField(builder, useWhenFields, fieldBuilderList, fieldBuilderMap);
-                                // continue to skip creating based on service param
-                                continue;
-                            }
-                        }
-                    } catch (GenericEntityException e) {
-                        Debug.logError(e, module);
-                    }
-                }
-                ModelFormFieldBuilder builder = new ModelFormFieldBuilder();
-                builder.setModelForm(this);
-                builder.setName(modelParam.name);
-                builder.setServiceName(modelService.name);
-                builder.setAttributeName(modelParam.name);
-                builder.setTitle(modelParam.formLabel);
-                builder.setRequiredField(!modelParam.optional);
-                builder.induceFieldInfoFromServiceParam(modelService, modelParam, autoFieldsService.defaultFieldType);
-                builder.setPosition(autoFieldsService.defaultPosition);
-                if (UtilValidate.isNotEmpty(autoFieldsService.mapName)) {
-                    builder.setMapName(autoFieldsService.mapName);
-                }
-                addUpdateField(builder, useWhenFields, fieldBuilderList, fieldBuilderMap);
-            }
-        }
-    }
-
-    private void addUpdateField(ModelFormFieldBuilder builder, Set<String> useWhenFields,
-            List<ModelFormFieldBuilder> fieldBuilderList, Map<String, ModelFormFieldBuilder> fieldBuilderMap) {
-        if (!builder.getUseWhen().isEmpty() || useWhenFields.contains(builder.getName())) {
-            useWhenFields.add(builder.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 < fieldBuilderList.size(); i++) {
-                ModelFormFieldBuilder curField = fieldBuilderList.get(i);
-                if (curField.getName() != null && curField.getName().equals(builder.getName())) {
-                    fieldBuilderList.add(i, builder);
-                    inserted = true;
-                    break;
-                }
-            }
-            if (!inserted) {
-                fieldBuilderList.add(builder);
-            }
-            return;
-        } else {
-            // not a conditional field, see if a named field exists in Map
-            ModelFormFieldBuilder existingField = fieldBuilderMap.get(builder.getName());
-            if (existingField != null) {
-                // does exist, update the field by doing a merge/override
-                existingField.mergeOverrideModelFormField(builder);
-            } else {
-                // does not exist, add to List and Map
-                fieldBuilderList.add(builder);
-                fieldBuilderMap.put(builder.getName(), builder);
-            }
-        }
-    }
-
-    public List<ModelAction> getActions() {
-        return actions;
-    }
-
-    public List<AltRowStyle> getAltRowStyles() {
-        return altRowStyles;
-    }
-
-    public List<AltTarget> getAltTargets() {
-        return altTargets;
-    }
-
-    public List<AutoFieldsEntity> getAutoFieldsEntities() {
-        return autoFieldsEntities;
-    }
-
-    public List<AutoFieldsService> getAutoFieldsServices() {
-        return autoFieldsServices;
-    }
-
-    public Interpreter getBshInterpreter(Map<String, Object> context) throws EvalError {
-        Interpreter bsh = (Interpreter) context.get("bshInterpreter");
-        if (bsh == null) {
-            bsh = BshUtil.makeInterpreter(context);
-            context.put("bshInterpreter", bsh);
-        }
-        return bsh;
-    }
-
-    @Override
-    public String getBoundaryCommentName() {
-        return formLocation + "#" + getName();
-    }
-
-    public boolean getClientAutocompleteFields() {
-        return this.clientAutocompleteFields;
-    }
-
-    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 getContainerStyle() {
-        return this.containerStyle;
-    }
-
-    public String getDefaultEntityName() {
-        return this.defaultEntityName;
-    }
-
-    public FieldGroup getDefaultFieldGroup() {
-        return defaultFieldGroup;
-    }
-
-    public Map<String, ? extends Object> getDefaultMap(Map<String, ? extends Object> context) {
-        return this.defaultMapName.get(context);
-    }
-
-    public String getDefaultMapName() {
-        return this.defaultMapName.getOriginalName();
-    }
-
-    public String getDefaultRequiredFieldStyle() {
-        return this.defaultRequiredFieldStyle;
-    }
-
-    public String getDefaultServiceName() {
-        return this.defaultServiceName;
-    }
-
-    public String getDefaultSortFieldAscStyle() {
-        return this.defaultSortFieldAscStyle;
-    }
-
-    public String getDefaultSortFieldDescStyle() {
-        return this.defaultSortFieldDescStyle;
-    }
-
-    public String getDefaultSortFieldStyle() {
-        return this.defaultSortFieldStyle;
-    }
-
-    public String getDefaultTableStyle() {
-        return this.defaultTableStyle;
-    }
-
-    public String getDefaultTitleAreaStyle() {
-        return this.defaultTitleAreaStyle;
-    }
-
-    public String getDefaultTitleStyle() {
-        return this.defaultTitleStyle;
-    }
-
-    public String getDefaultTooltipStyle() {
-        return this.defaultTooltipStyle;
-    }
-
-    public int getDefaultViewSize() {
-        return defaultViewSize;
-    }
-
-    public String getDefaultWidgetAreaStyle() {
-        return this.defaultWidgetAreaStyle;
-    }
-
-    public String getDefaultWidgetStyle() {
-        return this.defaultWidgetStyle;
-    }
-
-    public String getEvenRowStyle() {
-        return this.evenRowStyle;
-    }
-
-    public List<FieldGroupBase> getFieldGroupList() {
-        return fieldGroupList;
-    }
-
-    public Map<String, FieldGroupBase> getFieldGroupMap() {
-        return fieldGroupMap;
-    }
-
-    public List<ModelFormField> getFieldList() {
-        return fieldList;
-    }
-
-    public String getFocusFieldName() {
-        return focusFieldName;
-    }
-
-    public String getFormLocation() {
-        return this.formLocation;
-    }
-
-    public String getFormTitleAreaStyle() {
-        return this.formTitleAreaStyle;
-    }
-
-    public String getFormWidgetAreaStyle() {
-        return this.formWidgetAreaStyle;
-    }
-
-    public String getHeaderRowStyle() {
-        return this.headerRowStyle;
-    }
-
-    public boolean getHideHeader() {
-        return this.hideHeader;
-    }
-
-    public String getItemIndexSeparator() {
-        if (UtilValidate.isNotEmpty(this.itemIndexSeparator)) {
-            return this.itemIndexSeparator;
-        } else {
-            return "_o_";
-        }
-    }
-
-    public List<String> getLastOrderFields() {
-        return lastOrderFields;
-    }
-
-    public String getListEntryName() {
-        return this.listEntryName;
-    }
-
-    public String getListName() {
-        return this.listName;
-    }
-
-    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 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 List<ModelFormField> getMultiSubmitFields() {
-        return this.multiSubmitFields;
-    }
-
-    public String getOddRowStyle() {
-        return this.oddRowStyle;
-    }
-
-    public List<UpdateArea> getOnPaginateUpdateAreas() {
-        return this.onPaginateUpdateAreas;
-    }
-
-    public List<UpdateArea> getOnSortColumnUpdateAreas() {
-        return this.onSortColumnUpdateAreas;
-    }
-
-    /* Returns the list of ModelForm.UpdateArea objects.
-     */
-    public List<UpdateArea> getOnSubmitUpdateAreas() {
-        return this.onSubmitUpdateAreas;
-    }
-
-    public String getOverrideListSize() {
-        return overrideListSize.getOriginal();
-    }
-
-    public int getOverrideListSize(Map<String, Object> context) {
-        int listSize = 0;
-        if (!this.overrideListSize.isEmpty()) {
-            String size = this.overrideListSize.expandString(context);
-            try {
-                size = size.replaceAll("[^0-9.]", "");
-                listSize = Integer.parseInt(size);
-            } catch (NumberFormatException e) {
-                Debug.logError(e, "Error getting override list size from value " + size, module);
-            }
-        }
-        return listSize;
-    }
-
-    public String getPaginate() {
-        return paginate.getOriginal();
-    }
-
-    public boolean getPaginate(Map<String, Object> context) {
-        String paginate = this.paginate.expandString(context);
-        if (!paginate.isEmpty()) {
-            return Boolean.valueOf(paginate).booleanValue();
-        } else {
-            return true;
-        }
-    }
-
-    public String getPaginateFirstLabel() {
-        return paginateFirstLabel.getOriginal();
-    }
-
-    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 getPaginateFirstStyle() {
-        return DEFAULT_PAG_FIRST_STYLE;
-    }
-
-    public String getPaginateIndexField() {
-        return paginateIndexField.getOriginal();
-    }
-
-    public String getPaginateIndexField(Map<String, Object> context) {
-        String field = this.paginateIndexField.expandString(context);
-        if (field.isEmpty()) {
-            return DEFAULT_PAG_INDEX_FIELD;
-        }
-        return field;
-    }
-
-    public String getPaginateLastLabel() {
-        return paginateLastLabel.getOriginal();
-    }
-
-    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 getPaginateLastStyle() {
-        return DEFAULT_PAG_LAST_STYLE;
-    }
-
-    public String getPaginateNextLabel() {
-        return paginateNextLabel.getOriginal();
-    }
-
-    public String getPaginateNextLabel(Map<String, Object> context) {
-        String field = this.paginateNextLabel.expandString(context);
-        if (field.isEmpty()) {
-            Locale locale = (Locale) context.get("locale");
-            return UtilProperties.getMessage("CommonUiLabels", "CommonNext", locale);
-        }
-        return field;
-    }
-
-    public String getPaginateNextStyle() {
-        return DEFAULT_PAG_NEXT_STYLE;
-    }
-
-    public String getPaginatePreviousLabel() {
-        return paginatePreviousLabel.getOriginal();
-    }
-
-    public String getPaginatePreviousLabel(Map<String, Object> context) {
-        String field = this.paginatePreviousLabel.expandString(context);
-        if (field.isEmpty()) {
-            Locale locale = (Locale) context.get("locale");
-            field = UtilProperties.getMessage("CommonUiLabels", "CommonPrevious", locale);
-        }
-        return field;
-    }
-
-    public String getPaginatePreviousStyle() {
-        return DEFAULT_PAG_PREV_STYLE;
-    }
-
-    public String getPaginateSizeField() {
-        return paginateSizeField.getOriginal();
-    }
-
-    public String getPaginateSizeField(Map<String, Object> context) {
-        String field = this.paginateSizeField.expandString(context);
-        if (field.isEmpty()) {
-            return DEFAULT_PAG_SIZE_FIELD;
-        }
-        return field;
-    }
-
-    public String getPaginateStyle() {
-        return this.paginateStyle;
-    }
-
-    public String getPaginateTarget() {
-        return paginateTarget.getOriginal();
-    }
-
-    public String getPaginateTarget(Map<String, Object> context) {
-        String targ = this.paginateTarget.expandString(context);
-        if (targ.isEmpty()) {
-            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 getPaginateViewSizeLabel() {
-        return paginateViewSizeLabel.getOriginal();
-    }
-
-    public String getPaginateViewSizeLabel(Map<String, Object> context) {
-        String field = this.paginateViewSizeLabel.expandString(context);
-        if (field.isEmpty()) {
-            Locale locale = (Locale) context.get("locale");
-            return UtilProperties.getMessage("CommonUiLabels", "CommonItemsPerPage", locale);
-        }
-        return field;
-    }
-
-    private ModelForm getParentForm(Element formElement, ModelReader entityModelReader, DispatchContext dispatchContext) {
-        ModelForm parent = null;
-        String parentResource = formElement.getAttribute("extends-resource");
-        String parentForm = formElement.getAttribute("extends");
-        if (parentForm.length() > 0) {
-            // 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);
-                } 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, parentResource, entityModelReader, dispatchContext);
-                        break;
-                    }
-                }
-                if (parent == null) {
-                    Debug.logError("Failed to find parent form definition '" + parentForm + "' in same document.", module);
-                }
-            } else {
-                Debug.logError("Recursive form definition found for '" + formElement.getAttribute("name") + ".'", module);
-            }
-        }
-        return parent;
-    }
-
-    public String getParentFormLocation() {
-        return this.parentModelForm == null ? null : this.parentModelForm.getFormLocation();
-    }
-
-    public String getParentFormName() {
-        return this.parentModelForm == null ? null : this.parentModelForm.getName();
-    }
-
-    public ModelForm getParentModelForm() {
-        return parentModelForm;
-    }
-
-    public String getPassedRowCount(Map<String, Object> context) {
-        return rowCountExdr.expandString(context);
-    }
-
-    public List<ModelAction> getRowActions() {
-        return rowActions;
-    }
-
-    public String getRowCount() {
-        return rowCountExdr.getOriginal();
-    }
-
-    public boolean getSeparateColumns() {
-        return this.separateColumns;
-    }
-
-    public boolean getSkipEnd() {
-        return this.skipEnd;
-    }
-
-    public boolean getSkipStart() {
-        return this.skipStart;
-    }
-
-    public String getSortField(Map<String, Object> context) {
-        String value = null;
-        try {
-            value = (String) context.get(this.sortFieldParameterName);
-            if (value == null) {
-                Map<String, String> parameters = UtilGenerics.cast(context.get("parameters"));
-                if (parameters != null) {
-                    value = parameters.get(this.sortFieldParameterName);
-                }
-            }
-        } catch (Exception e) {
-            Debug.logWarning(e, "Error getting sortField: " + e.toString(), module);
-        }
-        return value;
-    }
-
-    public String getSortFieldParameterName() {
-        return this.sortFieldParameterName;
-    }
-
-    public List<SortField> getSortOrderFields() {
-        return sortOrderFields;
-    }
-
-    /**
-     * 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
-            Interpreter bsh = this.getBshInterpreter(context);
-            for (AltRowStyle altRowStyle : this.altRowStyles) {
-                Object retVal = bsh.eval(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 " + getName());
-                }
-            }
-        } catch (EvalError e) {
-            String errmsg = "Error evaluating BeanShell style conditions on form " + getName();
-            Debug.logError(e, errmsg, module);
-            throw new IllegalArgumentException(errmsg);
-        }
-        return styles;
-    }
-
-    public String getTarget() {
-        return target.getOriginal();
-    }
-
-    /** 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;
-        UtilCodec.SimpleEncoder simpleEncoder = (UtilCodec.SimpleEncoder) context.get("simpleEncoder");
-        if (simpleEncoder != null) {
-            expanderContext = UtilCodec.HtmlEncodingMapWrapper.getHtmlEncodingMapWrapper(context, simpleEncoder);
-        }
-        try {
-            // use the same Interpreter (ie with the same context setup) for all evals
-            Interpreter bsh = this.getBshInterpreter(context);
-            for (AltTarget altTarget : this.altTargets) {
-                String useWhen = FlexibleStringExpander.expandString(altTarget.useWhen, context);
-                Object retVal = bsh.eval(StringUtil.convertOperatorSubstitutions(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 " + getName());
-                }
-
-                if (condTrue && !targetType.equals("inter-app")) {
-                    return altTarget.targetExdr.expandString(expanderContext);
-                }
-            }
-        } catch (EvalError e) {
-            String errmsg = "Error evaluating BeanShell target conditions on form " + getName();
-            Debug.logError(e, errmsg, module);
-            throw new IllegalArgumentException(errmsg);
-        }
-        return target.expandString(expanderContext);
-    }
-
-    public String getTargetType() {
-        return this.targetType;
-    }
-
-    public String getTargetWindow() {
-        return targetWindowExdr.getOriginal();
-    }
-
-    public String getTargetWindow(Map<String, Object> context) {
-        return this.targetWindowExdr.expandString(context);
-    }
-
-    public String getTitle() {
-        return this.title;
-    }
-
-    public String getTooltip() {
-        return this.tooltip;
-    }
-
-    public String getType() {
-        return this.type;
-    }
-
-    public boolean getUseRowSubmit() {
-        return this.useRowSubmit;
-    }
-
-    public Set<String> getUseWhenFields() {
-        return useWhenFields;
-    }
-    public boolean getGroupColumns() {
-        return groupColumns;
-    }
-
-    public boolean isOverridenListSize() {
-        return !this.overrideListSize.isEmpty();
-    }
-
-    public void runFormActions(Map<String, Object> context) {
-        AbstractModelAction.runSubActions(this.actions, context);
-    }
-
-    public static class AltRowStyle {
-        public final String useWhen;
-        public final String style;
-
-        public AltRowStyle(Element altRowStyleElement) {
-            this.useWhen = altRowStyleElement.getAttribute("use-when");
-            this.style = altRowStyleElement.getAttribute("style");
-        }
-    }
-
-    public static class AltTarget {
-        public final String useWhen;
-        public final FlexibleStringExpander targetExdr;
-
-        public AltTarget(Element altTargetElement) {
-            this.useWhen = altTargetElement.getAttribute("use-when");
-            this.targetExdr = FlexibleStringExpander.getInstance(altTargetElement.getAttribute("target"));
-        }
-
-        @Override
-        public boolean equals(Object obj) {
-            return obj instanceof AltTarget && obj.hashCode() == this.hashCode();
-        }
-
-        @Override
-        public int hashCode() {
-            return useWhen.hashCode();
-        }
-    }
-
-    public static class AutoFieldsEntity {
-        public final String entityName;
-        public final String mapName;
-        public final String defaultFieldType;
-        public final 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 AutoFieldsService {
-        public final String serviceName;
-        public final String mapName;
-        public final String defaultFieldType;
-        public final 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 Banner implements FieldGroupBase {
-        public final FlexibleStringExpander style;
-        public final FlexibleStringExpander text;
-        public final FlexibleStringExpander textStyle;
-        public final FlexibleStringExpander leftText;
-        public final FlexibleStringExpander leftTextStyle;
-        public final FlexibleStringExpander rightText;
-        public final FlexibleStringExpander rightTextStyle;
-
-        public Banner(Element sortOrderElement) {
-            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 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 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 void renderString(Appendable writer, Map<String, Object> context, FormStringRenderer formStringRenderer)
-                throws IOException {
-            formStringRenderer.renderBanner(writer, context, this);
-        }
-    }
-
-    public static class FieldGroup implements FieldGroupBase {
-        private static AtomicInteger baseSeqNo = new AtomicInteger(0);
-        private static final String baseId = "_G";
-        private final String id;
-        private final String style;
-        private final String title;
-        private final boolean collapsible;
-        private final boolean initiallyCollapsed;
-        private final ModelForm modelForm;
-
-        public FieldGroup(Element sortOrderElement, ModelForm modelForm, List<SortField> sortOrderFields,
-                Map<String, FieldGroupBase> fieldGroupMap) {
-            this.modelForm = modelForm;
-            String id;
-            String style = "";
-            String title = "";
-            boolean collapsible = false;
-            boolean initiallyCollapsed = false;
-            if (sortOrderElement != null) {
-                id = sortOrderElement.getAttribute("id");
-                if (id.isEmpty()) {
-                    String lastGroupId = baseId + baseSeqNo.getAndIncrement() + "_";
-                    id = lastGroupId;
-                }
-                style = sortOrderElement.getAttribute("style");
-                title = sortOrderElement.getAttribute("title");
-                collapsible = "true".equals(sortOrderElement.getAttribute("collapsible"));
-                initiallyCollapsed = "true".equals(sortOrderElement.getAttribute("initially-collapsed"));
-                if (initiallyCollapsed) {
-                    collapsible = true;
-                }
-                for (Element sortFieldElement : UtilXml.childElementList(sortOrderElement, "sort-field")) {
-                    sortOrderFields.add(new SortField(sortFieldElement.getAttribute("name"), sortFieldElement
-                            .getAttribute("position")));
-                    fieldGroupMap.put(sortFieldElement.getAttribute("name"), this);
-                }
-            } else {
-                String lastGroupId = baseId + baseSeqNo.getAndIncrement() + "_";
-                id = lastGroupId;
-            }
-            this.id = id;
-            this.style = style;
-            this.title = title;
-            this.collapsible = collapsible;
-            this.initiallyCollapsed = initiallyCollapsed;
-        }
-
-        public Boolean collapsible() {
-            return this.collapsible;
-        }
-
-        public String getId() {
-            return this.id;
-        }
-
-        public String getStyle() {
-            return this.style;
-        }
-
-        public String getTitle() {
-            return this.title;
-        }
-
-        public Boolean initiallyCollapsed() {
-            return this.initiallyCollapsed;
-        }
-
-        public void renderEndString(Appendable writer, Map<String, Object> context, FormStringRenderer formStringRenderer)
-                throws IOException {
-            formStringRenderer.renderFormatSingleWrapperClose(writer, context, modelForm);
-            if (!modelForm.fieldGroupList.isEmpty()) {
-                if (shouldUse(context)) {
-                    formStringRenderer.renderFieldGroupClose(writer, context, this);
-                }
-            }
-        }
-
-        public void renderStartString(Appendable writer, Map<String, Object> context, FormStringRenderer formStringRenderer)
-                throws IOException {
-            if (!modelForm.fieldGroupList.isEmpty()) {
-                if (shouldUse(context)) {
-                    formStringRenderer.renderFieldGroupOpen(writer, context, this);
-                }
-            }
-            formStringRenderer.renderFormatSingleWrapperOpen(writer, context, modelForm);
-        }
-
-        public boolean shouldUse(Map<String, Object> context) {
-            for (String fieldName : modelForm.fieldGroupMap.keySet()) {
-                FieldGroupBase group = modelForm.fieldGroupMap.get(fieldName);
-                if (group instanceof FieldGroup) {
-                    FieldGroup fieldgroup = (FieldGroup) group;
-                    if (this.id.equals(fieldgroup.getId())) {
-                        for (ModelFormField modelField : modelForm.fieldList) {
-                            if (fieldName.equals(modelField.getName()) && modelField.shouldUse(context)) {
-                                return true;
-                            }
-                        }
-                    }
-                }
-            }
-            return false;
-        }
-    }
-
-    public static interface FieldGroupBase {
-    }
-
-    public static class SortField {
-        private final String fieldName;
-        private final Integer position;
-
-        public SortField(String name) {
-            this(name, 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;
-            } else {
-                this.position = null;
-            }
-        }
-
-        public String getFieldName() {
-            return this.fieldName;
-        }
-
-        public Integer getPosition() {
-            return this.position;
-        }
-    }
-
-    /** The UpdateArea class implements the <code>&lt;on-event-update-area&gt;</code>
-     * elements used in form widgets.
-     */
-    public static class UpdateArea {
-        private final String eventType;
-        private final String areaId;
-        private final String areaTarget;
-        private final String defaultServiceName;
-        private final String defaultEntityName;
-        private final CommonWidgetModels.AutoEntityParameters autoEntityParameters;
-        private final CommonWidgetModels.AutoServiceParameters autoServiceParameters;
-        private final List<CommonWidgetModels.Parameter> parameterList;
-
-        public UpdateArea(Element updateAreaElement) {
-            this(updateAreaElement, null, null);
-        }
-
-        /** XML constructor.
-         * @param updateAreaElement The <code>&lt;on-xxx-update-area&gt;</code>
-         * XML element.
-         */
-        public UpdateArea(Element updateAreaElement, String defaultServiceName, String defaultEntityName) {
-            this.eventType = updateAreaElement.getAttribute("event-type");
-            this.areaId = updateAreaElement.getAttribute("area-id");
-            this.areaTarget = updateAreaElement.getAttribute("area-target");
-            this.defaultServiceName = defaultServiceName;
-            this.defaultEntityName = defaultEntityName;
-            List<? extends Element> parameterElementList = UtilXml.childElementList(updateAreaElement, "parameter");
-            if (parameterElementList.isEmpty()) {
-                this.parameterList = Collections.emptyList();
-            } else {
-                List<CommonWidgetModels.Parameter> parameterList = new ArrayList<CommonWidgetModels.Parameter>(parameterElementList.size());
-                for (Element parameterElement : parameterElementList) {
-                    parameterList.add(new CommonWidgetModels.Parameter(parameterElement));
-                }
-                this.parameterList = Collections.unmodifiableList(parameterList);
-            }
-            Element autoServiceParamsElement = UtilXml.firstChildElement(updateAreaElement, "auto-parameters-service");
-            if (autoServiceParamsElement != null) {
-                this.autoServiceParameters = new CommonWidgetModels.AutoServiceParameters(autoServiceParamsElement);
-            } else {
-                this.autoServiceParameters = null;
-            }
-            Element autoEntityParamsElement = UtilXml.firstChildElement(updateAreaElement, "auto-parameters-entity");
-            if (autoEntityParamsElement != null) {
-                this.autoEntityParameters = new CommonWidgetModels.AutoEntityParameters(autoEntityParamsElement);
-            } else {
-                this.autoEntityParameters = null;
-            }
-        }
-
-        /** 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;
-            this.defaultServiceName = null;
-            this.defaultEntityName = null;
-            this.parameterList = Collections.emptyList();
-            this.autoServiceParameters = null;
-            this.autoEntityParameters = null;
-        }
-
-        @Override
-        public boolean equals(Object obj) {
-            return obj instanceof UpdateArea && obj.hashCode() == this.hashCode();
-        }
-
-        public String getAreaId() {
-            return areaId;
-        }
-
-        public String getAreaTarget(Map<String, ? extends Object> context) {
-            return FlexibleStringExpander.expandString(areaTarget, context);
-        }
-
-        public String getEventType() {
-            return eventType;
-        }
-
-        public Map<String, String> getParameterMap(Map<String, Object> context) {
-            Map<String, String> fullParameterMap = new HashMap<String, String>();
-            if (autoServiceParameters != null) {
-                fullParameterMap.putAll(autoServiceParameters.getParametersMap(context, defaultServiceName));
-            }
-            if (autoEntityParameters != null) {
-                fullParameterMap.putAll(autoEntityParameters.getParametersMap(context, defaultEntityName));
-            }
-            for (CommonWidgetModels.Parameter parameter : this.parameterList) {
-                fullParameterMap.put(parameter.getName(), parameter.getValue(context));
-            }
-
-            return fullParameterMap;
-        }
-
-        @Override
-        public int hashCode() {
-            return areaId.hashCode();
-        }
-
-        public String getAreaTarget() {
-            return areaTarget;
-        }
-
-        public String getDefaultServiceName() {
-            return defaultServiceName;
-        }
-
-        public String getDefaultEntityName() {
-            return defaultEntityName;
-        }
-
-        public CommonWidgetModels.AutoEntityParameters getAutoEntityParameters() {
-            return autoEntityParameters;
-        }
-
-        public CommonWidgetModels.AutoServiceParameters getAutoServiceParameters() {
-            return autoServiceParameters;
-        }
-
-        public List<CommonWidgetModels.Parameter> getParameterList() {
-            return parameterList;
-        }
-    }
-}
+/*******************************************************************************

+ * Licensed to the Apache Software Foundation (ASF) under one

+ * or more contributor license agreements.  See the NOTICE file

+ * distributed with this work for additional information

+ * regarding copyright ownership.  The ASF licenses this file

+ * to you under the Apache License, Version 2.0 (the

+ * "License"); you may not use this file except in compliance

+ * with the License.  You may obtain a copy of the License at

+ *

+ * http://www.apache.org/licenses/LICENSE-2.0

+ *

+ * Unless required by applicable law or agreed to in writing,

+ * software distributed under the License is distributed on an

+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY

+ * KIND, either express or implied.  See the License for the

+ * specific language governing permissions and limitations

+ * under the License.

+ *******************************************************************************/

+package org.ofbiz.widget.model;

+

+import java.io.IOException;

+import java.util.ArrayList;

+import java.util.Collections;

+import java.util.HashMap;

+import java.util.HashSet;

+import java.util.Iterator;

+import java.util.LinkedList;

+import java.util.List;

+import java.util.Locale;

+import java.util.Map;

+import java.util.Set;

+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.UtilCodec;

+import org.ofbiz.base.util.UtilGenerics;

+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.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.service.DispatchContext;

+import org.ofbiz.service.GenericServiceException;

+import org.ofbiz.service.ModelParam;

+import org.ofbiz.service.ModelService;

+import org.ofbiz.widget.WidgetWorker;

+import org.ofbiz.widget.renderer.FormStringRenderer;

+import org.w3c.dom.Element;

+

+import bsh.EvalError;

+import bsh.Interpreter;

+

+/**

+ * Models the &lt;form&gt; element.

+ * 

+ * @see <code>widget-form.xsd</code>

+ */

+@SuppressWarnings("serial")

+public class ModelForm extends ModelWidget {

+

+    /*

+     * ----------------------------------------------------------------------- *

+     *                     DEVELOPERS PLEASE READ

+     * ----------------------------------------------------------------------- *

+     * 

+     * This model is intended to be a read-only data structure that represents

+     * an XML element. Outside of object construction, the class should not

+     * have any behaviors. All behavior should be contained in model visitors.

+     * 

+     * Instances of this class will be shared by multiple threads - therefore

+     * it is immutable. DO NOT CHANGE THE OBJECT'S STATE AT RUN TIME!

+     * 

+     * BE VERY CAREFUL when implementing "extends" - parent form collections

+     * must be added to child collections, not replace them. In other words,

+     * do not assign parent collection fields to child collection fields.

+     * 

+     */

+

+    public static final String module = ModelForm.class.getName();

+    public static final String DEFAULT_FORM_RESULT_LIST_NAME = "defaultFormResultList";

+    /** Pagination settings and defaults. */

+    public static int DEFAULT_PAGE_SIZE = 10;

+    public static int MAX_PAGE_SIZE = 10000;

+    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";

+    private final List<ModelAction> actions;

+    private final List<AltRowStyle> altRowStyles;

+    private final List<AltTarget> altTargets;

+    private final List<AutoFieldsEntity> autoFieldsEntities;

+    private final List<AutoFieldsService> autoFieldsServices;

+    private final boolean clientAutocompleteFields;

+    private final String containerId;

+    private final String containerStyle;

+    private final String defaultEntityName;

+    /** This field group will be the "catch-all" group for fields that are not

+     *  included in an explicit field-group.

+     */

+    private final FieldGroup defaultFieldGroup;

+    private final FlexibleMapAccessor<Map<String, ? extends Object>> defaultMapName;

+    private final String defaultRequiredFieldStyle;

+    private final String defaultServiceName;

+    private final String defaultSortFieldAscStyle;

+    private final String defaultSortFieldDescStyle;

+    private final String defaultSortFieldStyle;

+    private final String defaultTableStyle;

+    private final String defaultTitleAreaStyle;

+    private final String defaultTitleStyle;

+    private final String defaultTooltipStyle;

+    private final int defaultViewSize;

+    private final String defaultWidgetAreaStyle;

+    private final String defaultWidgetStyle;

+    private final String evenRowStyle;

+    /** This is a list of FieldGroups in the order they were created.

+     * Can also include Banner objects.

+     */

+    private final List<FieldGroupBase> fieldGroupList;

+    /** This Map is keyed with the field name and has a FieldGroup for the value.

+     * Can also include Banner objects.

+     */

+    private final Map<String, FieldGroupBase> fieldGroupMap;

+    /** 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.

+     */

+    private final List<ModelFormField> fieldList;

+    private final String focusFieldName;

+    private final String formLocation;

+    private final String formTitleAreaStyle;

+    private final String formWidgetAreaStyle;

+    private final boolean groupColumns;

+    private final String headerRowStyle;

+    private final boolean hideHeader;

+    private final String itemIndexSeparator;

+    private final List<String> lastOrderFields;

+    private final String listEntryName;

+    private final String listName;

+    private final List<ModelFormField> multiSubmitFields;

+    private final String oddRowStyle;

+    /** On Paginate areas to be updated. */

+    private final List<UpdateArea> onPaginateUpdateAreas;

+    /** On Sort Column areas to be updated. */

+    private final List<UpdateArea> onSortColumnUpdateAreas;

+    /** On Submit areas to be updated. */

+    private final List<UpdateArea> onSubmitUpdateAreas;

+    private final FlexibleStringExpander overrideListSize;

+    private final FlexibleStringExpander paginate;

+    private final FlexibleStringExpander paginateFirstLabel;

+    private final FlexibleStringExpander paginateIndexField;

+    private final FlexibleStringExpander paginateLastLabel;

+    private final FlexibleStringExpander paginateNextLabel;

+    private final FlexibleStringExpander paginatePreviousLabel;

+    private final FlexibleStringExpander paginateSizeField;

+    private final String paginateStyle;

+    private final FlexibleStringExpander paginateTarget;

+    private final String paginateTargetAnchor;

+    private final FlexibleStringExpander paginateViewSizeLabel;

+    private final ModelForm parentModelForm;

+    private final List<ModelAction> rowActions;

+    private final FlexibleStringExpander rowCountExdr;

+    private final boolean separateColumns;

+    private final boolean skipEnd;

+    private final boolean skipStart;

+    private final String sortFieldParameterName;

+    private final List<SortField> sortOrderFields;

+    private final FlexibleStringExpander target;

+    private final String targetType;

+    private final FlexibleStringExpander targetWindowExdr;

+    private final String title;

+    private final String tooltip;

+    private final String type;

+    private final boolean useRowSubmit;

+    /** Keeps track of conditional fields to help ensure that only one is rendered

+     */

+    private final Set<String> useWhenFields;

+

+    /** XML Constructor */

+    public ModelForm(Element formElement, String formLocation, ModelReader entityModelReader, DispatchContext dispatchContext) {

+        super(formElement);

+        this.formLocation = formLocation;

+        parentModelForm = getParentForm(formElement, entityModelReader, dispatchContext);

+        int defaultViewSizeInt = DEFAULT_PAGE_SIZE;

+        String viewSize = formElement.getAttribute("view-size");

+        if (viewSize.isEmpty()) {

+            if (parentModelForm != null) {

+                defaultViewSizeInt = parentModelForm.defaultViewSize;

+            } else {

+                defaultViewSizeInt = UtilProperties.getPropertyAsInteger("widget.properties", "widget.form.defaultViewSize",

+                        defaultViewSizeInt);

+            }

+        } else {

+            try {

+                defaultViewSizeInt = Integer.valueOf(viewSize);

+            } catch (NumberFormatException e) {

+            }

+        }

+        this.defaultViewSize = defaultViewSizeInt;

+        String type = formElement.getAttribute("type");

+        if (type.isEmpty() && parentModelForm != null) {

+            type = parentModelForm.type;

+        }

+        this.type = type;

+        FlexibleStringExpander target = FlexibleStringExpander.getInstance(formElement.getAttribute("target"));

+        if (target.isEmpty() && parentModelForm != null) {

+            target = parentModelForm.target;

+        }

+        this.target = target;

+        String containerId = formElement.getAttribute("id");

+        if (containerId.isEmpty() && parentModelForm != null) {

+            containerId = parentModelForm.containerId;

+        }

+        this.containerId = containerId;

+        String containerStyle = formElement.getAttribute("style");

+        if (containerStyle.isEmpty() && parentModelForm != null) {

+            containerStyle = parentModelForm.containerStyle;

+        }

+        this.containerStyle = containerStyle;

+        String title = formElement.getAttribute("title");

+        if (title.isEmpty() && parentModelForm != null) {

+            title = parentModelForm.title;

+        }

+        this.title = title;

+        String tooltip = formElement.getAttribute("tooltip");

+        if (tooltip.isEmpty() && parentModelForm != null) {

+            tooltip = parentModelForm.tooltip;

+        }

+        this.tooltip = tooltip;

+        String listName = formElement.getAttribute("list-name");

+        if (listName.isEmpty()) {

+            if (parentModelForm != null) {

+                listName = parentModelForm.listName;

+            } else {

+                listName = DEFAULT_FORM_RESULT_LIST_NAME;

+            }

+        }

+        this.listName = listName;

+        String listEntryName = formElement.getAttribute("list-entry-name");

+        if (listEntryName.isEmpty() && parentModelForm != null) {

+            listEntryName = parentModelForm.listEntryName;

+        }

+        this.listEntryName = listEntryName;

+        String defaultEntityName = formElement.getAttribute("default-entity-name");

+        if (defaultEntityName.isEmpty() && parentModelForm != null) {

+            defaultEntityName = parentModelForm.defaultEntityName;

+        }

+        this.defaultEntityName = defaultEntityName;

+        String defaultServiceName = formElement.getAttribute("default-service-name");

+        if (defaultServiceName.isEmpty() && parentModelForm != null) {

+            defaultServiceName = parentModelForm.defaultServiceName;

+        }

+        this.defaultServiceName = defaultServiceName;

+        String formTitleAreaStyle = formElement.getAttribute("form-title-area-style");

+        if (formTitleAreaStyle.isEmpty() && parentModelForm != null) {

+            formTitleAreaStyle = parentModelForm.formTitleAreaStyle;

+        }

+        this.formTitleAreaStyle = formTitleAreaStyle;

+        String formWidgetAreaStyle = formElement.getAttribute("form-widget-area-style");

+        if (formWidgetAreaStyle.isEmpty() && parentModelForm != null) {

+            formWidgetAreaStyle = parentModelForm.formWidgetAreaStyle;

+        }

+        this.formWidgetAreaStyle = formWidgetAreaStyle;

+        String defaultTitleAreaStyle = formElement.getAttribute("default-title-area-style");

+        if (defaultTitleAreaStyle.isEmpty() && parentModelForm != null) {

+            defaultTitleAreaStyle = parentModelForm.defaultTitleAreaStyle;

+        }

+        this.defaultTitleAreaStyle = defaultTitleAreaStyle;

+        String defaultWidgetAreaStyle = formElement.getAttribute("default-widget-area-style");

+        if (defaultWidgetAreaStyle.isEmpty() && parentModelForm != null) {

+            defaultWidgetAreaStyle = parentModelForm.defaultWidgetAreaStyle;

+        }

+        this.defaultWidgetAreaStyle = defaultWidgetAreaStyle;

+        String oddRowStyle = formElement.getAttribute("odd-row-style");

+        if (oddRowStyle.isEmpty() && parentModelForm != null) {

+            oddRowStyle = parentModelForm.oddRowStyle;

+        }

+        this.oddRowStyle = oddRowStyle;

+        String evenRowStyle = formElement.getAttribute("even-row-style");

+        if (evenRowStyle.isEmpty() && parentModelForm != null) {

+            evenRowStyle = parentModelForm.evenRowStyle;

+        }

+        this.evenRowStyle = evenRowStyle;

+        String defaultTableStyle = formElement.getAttribute("default-table-style");

+        if (defaultTableStyle.isEmpty() && parentModelForm != null) {

+            defaultTableStyle = parentModelForm.defaultTableStyle;

+        }

+        this.defaultTableStyle = defaultTableStyle;

+        String headerRowStyle = formElement.getAttribute("header-row-style");

+        if (headerRowStyle.isEmpty() && parentModelForm != null) {

+            headerRowStyle = parentModelForm.headerRowStyle;

+        }

+        this.headerRowStyle = headerRowStyle;

+        String defaultTitleStyle = formElement.getAttribute("default-title-style");

+        if (defaultTitleStyle.isEmpty() && parentModelForm != null) {

+            defaultTitleStyle = parentModelForm.defaultTitleStyle;

+        }

+        this.defaultTitleStyle = defaultTitleStyle;

+        String defaultWidgetStyle = formElement.getAttribute("default-widget-style");

+        if (defaultWidgetStyle.isEmpty() && parentModelForm != null) {

+            defaultWidgetStyle = parentModelForm.defaultWidgetStyle;

+        }

+        this.defaultWidgetStyle = defaultWidgetStyle;

+        String defaultTooltipStyle = formElement.getAttribute("default-tooltip-style");

+        if (defaultTooltipStyle.isEmpty() && parentModelForm != null) {

+            defaultTooltipStyle = parentModelForm.defaultTooltipStyle;

+        }

+        this.defaultTooltipStyle = defaultTooltipStyle;

+        String itemIndexSeparator = formElement.getAttribute("item-index-separator");

+        if (itemIndexSeparator.isEmpty() && parentModelForm != null) {

+            itemIndexSeparator = parentModelForm.itemIndexSeparator;

+        }

+        this.itemIndexSeparator = itemIndexSeparator;

+        String separateColumns = formElement.getAttribute("separate-columns");

+        if (separateColumns.isEmpty() && parentModelForm != null) {

+            this.separateColumns = parentModelForm.separateColumns;

+        } else {

+            this.separateColumns = "true".equals(separateColumns);

+        }

+        String groupColumns = formElement.getAttribute("group-columns");

+        if (groupColumns.isEmpty() && parentModelForm != null) {

+            this.groupColumns = parentModelForm.groupColumns;

+        } else {

+            this.groupColumns = !"false".equals(groupColumns);

+        }

+        String targetType = formElement.getAttribute("target-type");

+        if (targetType.isEmpty() && parentModelForm != null) {

+            targetType = parentModelForm.targetType;

+        }

+        this.targetType = targetType;

+        FlexibleMapAccessor<Map<String, ? extends Object>> defaultMapName = FlexibleMapAccessor.getInstance(formElement

+                .getAttribute("default-map-name"));

+        if (defaultMapName.isEmpty() && parentModelForm != null) {

+            defaultMapName = parentModelForm.defaultMapName;

+        }

+        this.defaultMapName = defaultMapName;

+        FlexibleStringExpander targetWindowExdr = FlexibleStringExpander.getInstance(formElement.getAttribute("target-window"));

+        if (targetWindowExdr.isEmpty() && parentModelForm != null) {

+            targetWindowExdr = parentModelForm.targetWindowExdr;

+        }

+        this.targetWindowExdr = targetWindowExdr;

+        String hideHeader = formElement.getAttribute("hide-header");

+        if (hideHeader.isEmpty() && parentModelForm != null) {

+            this.hideHeader = parentModelForm.hideHeader;

+        } else {

+            this.hideHeader = "true".equals(hideHeader);

+        }

+        String clientAutocompleteFields = formElement.getAttribute("client-autocomplete-fields");

+        if (clientAutocompleteFields.isEmpty() && parentModelForm != null) {

+            this.clientAutocompleteFields = parentModelForm.clientAutocompleteFields;

+        } else {

+            this.clientAutocompleteFields = !"false".equals(formElement.getAttribute("client-autocomplete-fields"));

+        }

+        FlexibleStringExpander paginateTarget = FlexibleStringExpander.getInstance(formElement.getAttribute("paginate-target"));

+        if (paginateTarget.isEmpty() && parentModelForm != null) {

+            paginateTarget = parentModelForm.paginateTarget;

+        }

+        this.paginateTarget = paginateTarget;

+        ArrayList<AltTarget> altTargets = new ArrayList<AltTarget>();

+        if (parentModelForm != null) {

+            altTargets.addAll(parentModelForm.altTargets);

+        }

+        for (Element altTargetElement : UtilXml.childElementList(formElement, "alt-target")) {

+            altTargets.add(new AltTarget(altTargetElement));

+        }

+        altTargets.trimToSize();

+        this.altTargets = Collections.unmodifiableList(altTargets);

+        ArrayList<ModelAction> actions = new ArrayList<ModelAction>();

+        if (parentModelForm != null) {

+            actions.addAll(parentModelForm.actions);

+        }

+        Element actionsElement = UtilXml.firstChildElement(formElement, "actions");

+        if (actionsElement != null) {

+            actions.addAll(ModelFormAction.readSubActions(this, actionsElement));

+        }

+        actions.trimToSize();

+        this.actions = Collections.unmodifiableList(actions);

+        ArrayList<ModelAction> rowActions = new ArrayList<ModelAction>();

+        if (parentModelForm != null) {

+            rowActions.addAll(parentModelForm.rowActions);

+        }

+        Element rowActionsElement = UtilXml.firstChildElement(formElement, "row-actions");

+        if (rowActionsElement != null) {

+            rowActions.addAll(ModelFormAction.readSubActions(this, rowActionsElement));

+        }

+        rowActions.trimToSize();

+        this.rowActions = Collections.unmodifiableList(rowActions);

+        ArrayList<UpdateArea> onPaginateUpdateAreas = new ArrayList<UpdateArea>();

+        ArrayList<UpdateArea> onSubmitUpdateAreas = new ArrayList<UpdateArea>();

+        ArrayList<UpdateArea> onSortColumnUpdateAreas = new ArrayList<UpdateArea>();

+        if (parentModelForm != null) {

+            onPaginateUpdateAreas.addAll(parentModelForm.onPaginateUpdateAreas);

+            onSubmitUpdateAreas.addAll(parentModelForm.onSubmitUpdateAreas);

+            onSortColumnUpdateAreas.addAll(parentModelForm.onSortColumnUpdateAreas);

+        }

+        for (Element updateAreaElement : UtilXml.childElementList(formElement, "on-event-update-area")) {

+            UpdateArea updateArea = new UpdateArea(updateAreaElement, defaultServiceName, defaultEntityName);

+            if ("paginate".equals(updateArea.getEventType())) {

+                int index = onPaginateUpdateAreas.indexOf(updateArea);

+                if (index != -1) {

+                    if (!updateArea.areaTarget.isEmpty()) {

+                        onPaginateUpdateAreas.set(index, updateArea);

+                    } else {

+                        // blank target indicates a removing override

+                        onPaginateUpdateAreas.remove(index);

+                    }

+                } else {

+                    onPaginateUpdateAreas.add(updateArea);

+                }

+            } else if ("submit".equals(updateArea.getEventType())) {

+                int index = onSubmitUpdateAreas.indexOf(updateArea);

+                if (index != -1) {

+                    onSubmitUpdateAreas.set(index, updateArea);

+                } else {

+                    onSubmitUpdateAreas.add(updateArea);

+                }

+            } else if ("sort-column".equals(updateArea.getEventType())) {

+                int index = onSortColumnUpdateAreas.indexOf(updateArea);

+                if (index != -1) {

+                    if (!updateArea.areaTarget.isEmpty()) {

+                        onSortColumnUpdateAreas.set(index, updateArea);

+                    } else {

+                        // blank target indicates a removing override

+                        onSortColumnUpdateAreas.remove(index);

+                    }

+                } else {

+                    onSortColumnUpdateAreas.add(updateArea);

+                }

+            }

+        }

+        onPaginateUpdateAreas.trimToSize();

+        this.onPaginateUpdateAreas = Collections.unmodifiableList(onPaginateUpdateAreas);

+        onSubmitUpdateAreas.trimToSize();

+        this.onSubmitUpdateAreas = Collections.unmodifiableList(onSubmitUpdateAreas);

+        onSortColumnUpdateAreas.trimToSize();

+        this.onSortColumnUpdateAreas = Collections.unmodifiableList(onSortColumnUpdateAreas);

+        ArrayList<AltRowStyle> altRowStyles = new ArrayList<AltRowStyle>();

+        if (parentModelForm != null) {

+            altRowStyles.addAll(parentModelForm.altRowStyles);

+        }

+        for (Element altRowStyleElement : UtilXml.childElementList(formElement, "alt-row-style")) {

+            AltRowStyle altRowStyle = new AltRowStyle(altRowStyleElement);

+            altRowStyles.add(altRowStyle);

+        }

+        altRowStyles.trimToSize();

+        this.altRowStyles = Collections.unmodifiableList(altRowStyles);

+        Set<String> useWhenFields = new HashSet<String>();

+        if (parentModelForm != null) {

+            useWhenFields.addAll(parentModelForm.useWhenFields);

+        }

+        ArrayList<ModelFormFieldBuilder> fieldBuilderList = new ArrayList<ModelFormFieldBuilder>();

+        Map<String, ModelFormFieldBuilder> fieldBuilderMap = new HashMap<String, ModelFormFieldBuilder>();

+        if (parentModelForm != null) {

+            // Create this fieldList/Map from clones of parentModelForm's

+            for (ModelFormField parentChildField : parentModelForm.fieldList) {

+                ModelFormFieldBuilder builder = new ModelFormFieldBuilder(parentChildField);

+                builder.setModelForm(this);

+                fieldBuilderList.add(builder);

+                fieldBuilderMap.put(builder.getName(), builder);

+            }

+        }

+        Map<String, FieldGroupBase> fieldGroupMap = new HashMap<String, FieldGroupBase>();

+        if (parentModelForm != null) {

+            fieldGroupMap.putAll(parentModelForm.fieldGroupMap);

+        }

+        ArrayList<FieldGroupBase> fieldGroupList = new ArrayList<FieldGroupBase>();

+        if (parentModelForm != null) {

+            fieldGroupList.addAll(parentModelForm.fieldGroupList);

+        }

+        ArrayList<String> lastOrderFields = new ArrayList<String>();

+        if (parentModelForm != null) {

+            lastOrderFields.addAll(parentModelForm.lastOrderFields);

+        }

+        String sortFieldParameterName = formElement.getAttribute("sort-field-parameter-name");

+        if (sortFieldParameterName.isEmpty() && parentModelForm != null) {

+            this.sortFieldParameterName = parentModelForm.targetType;

+        } else {

+            this.sortFieldParameterName = "sortField";

+        }

+        String defaultRequiredFieldStyle = formElement.getAttribute("default-required-field-style");

+        if (defaultRequiredFieldStyle.isEmpty() && parentModelForm != null) {

+            defaultRequiredFieldStyle = parentModelForm.defaultRequiredFieldStyle;

+        }

+        this.defaultRequiredFieldStyle = defaultRequiredFieldStyle;

+        String defaultSortFieldStyle = formElement.getAttribute("default-sort-field-style");

+        if (defaultSortFieldStyle.isEmpty() && parentModelForm != null) {

+            this.defaultSortFieldStyle = parentModelForm.defaultSortFieldStyle;

+        } else {

+            this.defaultSortFieldStyle = DEFAULT_SORT_FIELD_STYLE;

+        }

+        String defaultSortFieldAscStyle = formElement.getAttribute("default-sort-field-asc-style");

+        if (defaultSortFieldAscStyle.isEmpty() && parentModelForm != null) {

+            this.defaultSortFieldAscStyle = parentModelForm.defaultSortFieldAscStyle;

+        } else {

+            this.defaultSortFieldAscStyle = DEFAULT_SORT_FIELD_ASC_STYLE;

+        }

+        String defaultSortFieldDescStyle = formElement.getAttribute("default-sort-field-desc-style");

+        if (defaultSortFieldDescStyle.isEmpty() && parentModelForm != null) {

+            this.defaultSortFieldDescStyle = parentModelForm.defaultSortFieldDescStyle;

+        } else {

+            this.defaultSortFieldDescStyle = DEFAULT_SORT_FIELD_DESC_STYLE;

+        }

+        String paginateTargetAnchor = formElement.getAttribute("paginate-target-anchor");

+        if (paginateTargetAnchor.isEmpty() && parentModelForm != null) {

+            paginateTargetAnchor = parentModelForm.paginateTargetAnchor;

+        }

+        this.paginateTargetAnchor = paginateTargetAnchor;

+        FlexibleStringExpander paginateIndexField = FlexibleStringExpander.getInstance(formElement

+                .getAttribute("paginate-index-field"));

+        if (paginateIndexField.isEmpty() && parentModelForm != null) {

+            paginateIndexField = parentModelForm.paginateIndexField;

+        }

+        this.paginateIndexField = paginateIndexField;

+        FlexibleStringExpander paginateSizeField = FlexibleStringExpander.getInstance(formElement

+                .getAttribute("paginate-size-field"));

+        if (paginateSizeField.isEmpty() && parentModelForm != null) {

+            paginateSizeField = parentModelForm.paginateSizeField;

+        }

+        this.paginateSizeField = paginateSizeField;

+        FlexibleStringExpander overrideListSize = FlexibleStringExpander.getInstance(formElement

+                .getAttribute("override-list-size"));

+        if (overrideListSize.isEmpty() && parentModelForm != null) {

+            overrideListSize = parentModelForm.overrideListSize;

+        }

+        this.overrideListSize = overrideListSize;

+        FlexibleStringExpander paginateFirstLabel = FlexibleStringExpander.getInstance(formElement

+                .getAttribute("paginate-first-label"));

+        if (paginateFirstLabel.isEmpty() && parentModelForm != null) {

+            paginateFirstLabel = parentModelForm.paginateFirstLabel;

+        }

+        this.paginateFirstLabel = paginateFirstLabel;

+        FlexibleStringExpander paginatePreviousLabel = FlexibleStringExpander.getInstance(formElement

+                .getAttribute("paginate-previous-label"));

+        if (paginatePreviousLabel.isEmpty() && parentModelForm != null) {

+            paginatePreviousLabel = parentModelForm.paginatePreviousLabel;

+        }

+        this.paginatePreviousLabel = paginatePreviousLabel;

+        FlexibleStringExpander paginateNextLabel = FlexibleStringExpander.getInstance(formElement

+                .getAttribute("paginate-next-label"));

+        if (paginateNextLabel.isEmpty() && parentModelForm != null) {

+            paginateNextLabel = parentModelForm.paginateNextLabel;

+        }

+        this.paginateNextLabel = paginateNextLabel;

+        FlexibleStringExpander paginateLastLabel = FlexibleStringExpander.getInstance(formElement

+                .getAttribute("paginate-last-label"));

+        if (paginateLastLabel.isEmpty() && parentModelForm != null) {

+            paginateLastLabel = parentModelForm.paginateLastLabel;

+        }

+        this.paginateLastLabel = paginateLastLabel;

+        FlexibleStringExpander paginateViewSizeLabel = FlexibleStringExpander.getInstance(formElement

+                .getAttribute("paginate-viewsize-label"));

+        if (paginateViewSizeLabel.isEmpty() && parentModelForm != null) {

+            paginateViewSizeLabel = parentModelForm.paginateViewSizeLabel;

+        }

+        this.paginateViewSizeLabel = paginateViewSizeLabel;

+        String paginateStyle = formElement.getAttribute("paginate-style");

+        if (paginateStyle.isEmpty() && parentModelForm != null) {

+            this.paginateStyle = parentModelForm.paginateStyle;

+        } else {

+            this.paginateStyle = DEFAULT_PAG_STYLE;

+        }

+        FlexibleStringExpander paginate = FlexibleStringExpander.getInstance(formElement.getAttribute("paginate"));

+        if (paginate.isEmpty() && parentModelForm != null) {

+            paginate = parentModelForm.paginate;

+        }

+        this.paginate = paginate;

+        String skipStart = formElement.getAttribute("skip-start");

+        if (skipStart.isEmpty() && parentModelForm != null) {

+            this.skipStart = parentModelForm.skipStart;

+        } else {

+            this.skipStart = "true".equals(skipStart);

+        }

+        String skipEnd = formElement.getAttribute("skip-end");

+        if (skipEnd.isEmpty() && parentModelForm != null) {

+            this.skipEnd = parentModelForm.skipEnd;

+        } else {

+            this.skipEnd = "true".equals(skipEnd);

+        }

+        String useRowSubmit = formElement.getAttribute("use-row-submit");

+        if (useRowSubmit.isEmpty() && parentModelForm != null) {

+            this.useRowSubmit = parentModelForm.useRowSubmit;

+        } else {

+            this.useRowSubmit = "true".equals(useRowSubmit);

+        }

+        FlexibleStringExpander rowCountExdr = FlexibleStringExpander.getInstance(formElement.getAttribute("row-count"));

+        if (rowCountExdr.isEmpty() && parentModelForm != null) {

+            rowCountExdr = parentModelForm.rowCountExdr;

+        }

+        this.rowCountExdr = paginate;

+        ArrayList<ModelFormFieldBuilder> multiSubmitBuilders = new ArrayList<ModelFormFieldBuilder>();

+        ArrayList<AutoFieldsService> autoFieldsServices = new ArrayList<AutoFieldsService>();

+        ArrayList<AutoFieldsEntity> autoFieldsEntities = new ArrayList<AutoFieldsEntity>();

+        ArrayList<SortField> sortOrderFields = new ArrayList<SortField>();

+        this.defaultFieldGroup = new FieldGroup(null, this, sortOrderFields, fieldGroupMap);

+        for (Element autoFieldsServiceElement : UtilXml.childElementList(formElement, "auto-fields-service")) {

+            AutoFieldsService autoFieldsService = new AutoFieldsService(autoFieldsServiceElement);

+            autoFieldsServices.add(autoFieldsService);

+            addAutoFieldsFromService(autoFieldsService, entityModelReader, dispatchContext, useWhenFields, fieldBuilderList, fieldBuilderMap);

+        }

+        for (Element autoFieldsEntityElement : UtilXml.childElementList(formElement, "auto-fields-entity")) {

+            AutoFieldsEntity autoFieldsEntity = new AutoFieldsEntity(autoFieldsEntityElement);

+            autoFieldsEntities.add(autoFieldsEntity);

+            addAutoFieldsFromEntity(autoFieldsEntity, entityModelReader, useWhenFields, fieldBuilderList, fieldBuilderMap);

+        }

+        String thisType = this.getType();

+        for (Element fieldElement : UtilXml.childElementList(formElement, "field")) {

+            ModelFormFieldBuilder builder = new ModelFormFieldBuilder(fieldElement, this, entityModelReader, dispatchContext);

+            FieldInfo fieldInfo = builder.getFieldInfo();

+            if (thisType.equals("multi") && fieldInfo instanceof ModelFormField.SubmitField) {

+                multiSubmitBuilders.add(builder);

+            } else {

+                addUpdateField(builder, useWhenFields, fieldBuilderList, fieldBuilderMap);

+            }

+        }

+        // get the sort-order

+        Element sortOrderElement = UtilXml.firstChildElement(formElement, "sort-order");

+        if (sortOrderElement != null) {

+            FieldGroup lastFieldGroup = new FieldGroup(null, this, sortOrderFields, fieldGroupMap);

+            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");

+                    sortOrderFields.add(new SortField(fieldName, position));

+                    fieldGroupMap.put(fieldName, lastFieldGroup);

+                } else if (tagName.equals("last-field")) {

+                    String fieldName = sortFieldElement.getAttribute("name");

+                    fieldGroupMap.put(fieldName, lastFieldGroup);

+                    lastOrderFields.add(fieldName);

+                } else if (tagName.equals("banner")) {

+                    Banner thisBanner = new Banner(sortFieldElement);

+                    fieldGroupList.add(thisBanner);

+                    lastFieldGroup = new FieldGroup(null, this, sortOrderFields, fieldGroupMap);

+                    fieldGroupList.add(lastFieldGroup);

+                } else if (tagName.equals("field-group")) {

+                    FieldGroup thisFieldGroup = new FieldGroup(sortFieldElement, this, sortOrderFields, fieldGroupMap);

+                    fieldGroupList.add(thisFieldGroup);

+                    lastFieldGroup = new FieldGroup(null, this, sortOrderFields, fieldGroupMap);

+                    fieldGroupList.add(lastFieldGroup);

+                }

+            }

+        }

+        if (sortOrderFields.size() > 0) {

+            ArrayList<ModelFormFieldBuilder> sortedFields = new ArrayList<ModelFormFieldBuilder>();

+            for (SortField sortField : 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<ModelFormFieldBuilder> fieldIter = fieldBuilderList.iterator();

+                while (fieldIter.hasNext()) {

+                    ModelFormFieldBuilder builder = fieldIter.next();

+                    if (fieldName.equals(builder.getName())) {

+                        // matched the name; remove from the original last and add to the sorted list

+                        if (UtilValidate.isNotEmpty(sortField.getPosition())) {

+                            builder.setPosition(sortField.getPosition());

+                        }

+                        fieldIter.remove();

+                        sortedFields.add(builder);

+                    }

+                }

+            }

+            // now add all of the rest of the fields from fieldList, ie those that were not explicitly listed in the sort order

+            sortedFields.addAll(fieldBuilderList);

+            // sortedFields all done, set fieldList

+            fieldBuilderList = sortedFields;

+        }

+        if (UtilValidate.isNotEmpty(lastOrderFields)) {

+            List<ModelFormFieldBuilder> lastedFields = new LinkedList<ModelFormFieldBuilder>();

+            for (String fieldName : lastOrderFields) {

+                if (UtilValidate.isEmpty(fieldName)) {

+                    continue;

+                }

+                // get all fields with the given name from the existing list and put them in the lasted list

+                Iterator<ModelFormFieldBuilder> fieldIter = fieldBuilderList.iterator();

+                while (fieldIter.hasNext()) {

+                    ModelFormFieldBuilder builder = fieldIter.next();

+                    if (fieldName.equals(builder.getName())) {

+                        // matched the name; remove from the original last and add to the lasted list

+                        fieldIter.remove();

+                        lastedFields.add(builder);

+                    }

+                }

+            }

+            //now put all lastedFields at the field list end

+            fieldBuilderList.addAll(lastedFields);

+        }

+        List<ModelFormField> fieldList = new ArrayList<ModelFormField>(fieldBuilderList.size());

+        for (ModelFormFieldBuilder builder : fieldBuilderList) {

+            fieldList.add(builder.build());

+        }

+        this.fieldList = Collections.unmodifiableList(fieldList);

+        List<ModelFormField> multiSubmitFields = new ArrayList<ModelFormField>(multiSubmitBuilders.size());

+        for (ModelFormFieldBuilder builder : multiSubmitBuilders) {

+            multiSubmitFields.add(builder.build());

+        }

+        this.multiSubmitFields = Collections.unmodifiableList(multiSubmitFields);

+        this.useWhenFields = Collections.unmodifiableSet(useWhenFields);

+        this.fieldGroupMap = Collections.unmodifiableMap(fieldGroupMap);

+        fieldGroupList.trimToSize();

+        this.fieldGroupList = Collections.unmodifiableList(fieldGroupList);

+        lastOrderFields.trimToSize();

+        this.lastOrderFields = Collections.unmodifiableList(lastOrderFields);

+        autoFieldsServices.trimToSize();

+        this.autoFieldsServices = Collections.unmodifiableList(autoFieldsServices);

+        autoFieldsEntities.trimToSize();

+        this.autoFieldsEntities = Collections.unmodifiableList(autoFieldsEntities);

+        sortOrderFields.trimToSize();

+        this.sortOrderFields = Collections.unmodifiableList(sortOrderFields);

+        String focusFieldName = formElement.getAttribute("focus-field-name");

+        if (focusFieldName.isEmpty() && parentModelForm != null) {

+            focusFieldName = parentModelForm.focusFieldName;

+        }

+        this.focusFieldName = focusFieldName;

+    }

+

+    @Override

+    public void accept(ModelWidgetVisitor visitor) throws Exception {

+        visitor.visit(this);

+    }

+

+    private void addAutoFieldsFromEntity(AutoFieldsEntity autoFieldsEntity, ModelReader entityModelReader,

+            Set<String> useWhenFields, List<ModelFormFieldBuilder> fieldBuilderList, Map<String, ModelFormFieldBuilder> fieldBuilderMap) {

+        // read entity def and auto-create fields

+        ModelEntity modelEntity = null;

+        try {

+            modelEntity = 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;

+            }

+            ModelFormFieldBuilder builder = new ModelFormFieldBuilder();

+            builder.setModelForm(this);

+            builder.setName(modelField.getName());

+            builder.setEntityName(modelEntity.getEntityName());

+            builder.setFieldName(modelField.getName());

+            builder.induceFieldInfoFromEntityField(modelEntity, modelField, autoFieldsEntity.defaultFieldType);

+            builder.setPosition(autoFieldsEntity.defaultPosition);

+            if (UtilValidate.isNotEmpty(autoFieldsEntity.mapName)) {

+                builder.setMapName(autoFieldsEntity.mapName);

+            }

+            addUpdateField(builder, useWhenFields, fieldBuilderList, fieldBuilderMap);

+        }

+    }

+

+    private void addAutoFieldsFromService(AutoFieldsService autoFieldsService, ModelReader entityModelReader,

+            DispatchContext dispatchContext, Set<String> useWhenFields, List<ModelFormFieldBuilder> fieldBuilderList,

+            Map<String, ModelFormFieldBuilder> fieldBuilderMap) {

+        // read service def and auto-create fields

+        ModelService modelService = null;

+        try {

+            modelService = 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()) {

+            if (modelParam.internal) {

+                // skip auto params that the service engine populates...

+                continue;

+            }

+            if (modelParam.formDisplay) {

+                if (UtilValidate.isNotEmpty(modelParam.entityName) && UtilValidate.isNotEmpty(modelParam.fieldName)) {

+                    ModelEntity modelEntity;

+                    try {

+                        modelEntity = entityModelReader.getModelEntity(modelParam.entityName);

+                        if (modelEntity != null) {

+                            ModelField modelField = modelEntity.getField(modelParam.fieldName);

+                            if (modelField != null) {

+                                // okay, populate using the entity field info...

+                                ModelFormFieldBuilder builder = new ModelFormFieldBuilder();

+                                builder.setModelForm(this);

+                                builder.setName(modelField.getName());

+                                builder.setEntityName(modelEntity.getEntityName());

+                                builder.setFieldName(modelField.getName());

+                                builder.induceFieldInfoFromEntityField(modelEntity, modelField, autoFieldsService.defaultFieldType);

+                                if (UtilValidate.isNotEmpty(autoFieldsService.mapName)) {

+                                    builder.setMapName(autoFieldsService.mapName);

+                                }

+                                builder.setRequiredField(!modelParam.optional);

+                                addUpdateField(builder, useWhenFields, fieldBuilderList, fieldBuilderMap);

+                                // continue to skip creating based on service param

+                                continue;

+                            }

+                        }

+                    } catch (GenericEntityException e) {

+                        Debug.logError(e, module);

+                    }

+                }

+                ModelFormFieldBuilder builder = new ModelFormFieldBuilder();

+                builder.setModelForm(this);

+                builder.setName(modelParam.name);

+                builder.setServiceName(modelService.name);

+                builder.setAttributeName(modelParam.name);

+                builder.setTitle(modelParam.formLabel);

+                builder.setRequiredField(!modelParam.optional);

+                builder.induceFieldInfoFromServiceParam(modelService, modelParam, autoFieldsService.defaultFieldType);

+                builder.setPosition(autoFieldsService.defaultPosition);

+                if (UtilValidate.isNotEmpty(autoFieldsService.mapName)) {

+                    builder.setMapName(autoFieldsService.mapName);

+                }

+                addUpdateField(builder, useWhenFields, fieldBuilderList, fieldBuilderMap);

+            }

+        }

+    }

+

+    private void addUpdateField(ModelFormFieldBuilder builder, Set<String> useWhenFields,

+            List<ModelFormFieldBuilder> fieldBuilderList, Map<String, ModelFormFieldBuilder> fieldBuilderMap) {

+        if (!builder.getUseWhen().isEmpty() || useWhenFields.contains(builder.getName())) {

+            useWhenFields.add(builder.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 < fieldBuilderList.size(); i++) {

+                ModelFormFieldBuilder curField = fieldBuilderList.get(i);

+                if (curField.getName() != null && curField.getName().equals(builder.getName())) {

+                    fieldBuilderList.add(i, builder);

+                    inserted = true;

+                    break;

+                }

+            }

+            if (!inserted) {

+                fieldBuilderList.add(builder);

+            }

+            return;

+        } else {

+            // not a conditional field, see if a named field exists in Map

+            ModelFormFieldBuilder existingField = fieldBuilderMap.get(builder.getName());

+            if (existingField != null) {

+                // does exist, update the field by doing a merge/override

+                existingField.mergeOverrideModelFormField(builder);

+            } else {

+                // does not exist, add to List and Map

+                fieldBuilderList.add(builder);

+                fieldBuilderMap.put(builder.getName(), builder);

+            }

+        }

+    }

+

+    public List<ModelAction> getActions() {

+        return actions;

+    }

+

+    public List<AltRowStyle> getAltRowStyles() {

+        return altRowStyles;

+    }

+

+    public List<AltTarget> getAltTargets() {

+        return altTargets;

+    }

+

+    public List<AutoFieldsEntity> getAutoFieldsEntities() {

+        return autoFieldsEntities;

+    }

+

+    public List<AutoFieldsService> getAutoFieldsServices() {

+        return autoFieldsServices;

+    }

+

+    public Interpreter getBshInterpreter(Map<String, Object> context) throws EvalError {

+        Interpreter bsh = (Interpreter) context.get("bshInterpreter");

+        if (bsh == null) {

+            bsh = BshUtil.makeInterpreter(context);

+            context.put("bshInterpreter", bsh);

+        }

+        return bsh;

+    }

+

+    @Override

+    public String getBoundaryCommentName() {

+        return formLocation + "#" + getName();

+    }

+

+    public boolean getClientAutocompleteFields() {

+        return this.clientAutocompleteFields;

+    }

+

+    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 getContainerStyle() {

+        return this.containerStyle;

+    }

+

+    public String getDefaultEntityName() {

+        return this.defaultEntityName;

+    }

+

+    public FieldGroup getDefaultFieldGroup() {

+        return defaultFieldGroup;

+    }

+

+    public Map<String, ? extends Object> getDefaultMap(Map<String, ? extends Object> context) {

+        return this.defaultMapName.get(context);

+    }

+

+    public String getDefaultMapName() {

+        return this.defaultMapName.getOriginalName();

+    }

+

+    public String getDefaultRequiredFieldStyle() {

+        return this.defaultRequiredFieldStyle;

+    }

+

+    public String getDefaultServiceName() {

+        return this.defaultServiceName;

+    }

+

+    public String getDefaultSortFieldAscStyle() {

+        return this.defaultSortFieldAscStyle;

+    }

+

+    public String getDefaultSortFieldDescStyle() {

+        return this.defaultSortFieldDescStyle;

+    }

+

+    public String getDefaultSortFieldStyle() {

+        return this.defaultSortFieldStyle;

+    }

+

+    public String getDefaultTableStyle() {

+        return this.defaultTableStyle;

+    }

+

+    public String getDefaultTitleAreaStyle() {

+        return this.defaultTitleAreaStyle;

+    }

+

+    public String getDefaultTitleStyle() {

+        return this.defaultTitleStyle;

+    }

+

+    public String getDefaultTooltipStyle() {

+        return this.defaultTooltipStyle;

+    }

+

+    public int getDefaultViewSize() {

+        return defaultViewSize;

+    }

+

+    public String getDefaultWidgetAreaStyle() {

+        return this.defaultWidgetAreaStyle;

+    }

+

+    public String getDefaultWidgetStyle() {

+        return this.defaultWidgetStyle;

+    }

+

+    public String getEvenRowStyle() {

+        return this.evenRowStyle;

+    }

+

+    public List<FieldGroupBase> getFieldGroupList() {

+        return fieldGroupList;

+    }

+

+    public Map<String, FieldGroupBase> getFieldGroupMap() {

+        return fieldGroupMap;

+    }

+

+    public List<ModelFormField> getFieldList() {

+        return fieldList;

+    }

+

+    public String getFocusFieldName() {

+        return focusFieldName;

+    }

+

+    public String getFormLocation() {

+        return this.formLocation;

+    }

+

+    public String getFormTitleAreaStyle() {

+        return this.formTitleAreaStyle;

+    }

+

+    public String getFormWidgetAreaStyle() {

+        return this.formWidgetAreaStyle;

+    }

+

+    public String getHeaderRowStyle() {

+        return this.headerRowStyle;

+    }

+

+    public boolean getHideHeader() {

+        return this.hideHeader;

+    }

+

+    public String getItemIndexSeparator() {

+        if (UtilValidate.isNotEmpty(this.itemIndexSeparator)) {

+            return this.itemIndexSeparator;

+        } else {

+            return "_o_";

+        }

+    }

+

+    public List<String> getLastOrderFields() {

+        return lastOrderFields;

+    }

+

+    public String getListEntryName() {

+        return this.listEntryName;

+    }

+

+    public String getListName() {

+        return this.listName;

+    }

+

+    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 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 List<ModelFormField> getMultiSubmitFields() {

+        return this.multiSubmitFields;

+    }

+

+    public String getOddRowStyle() {

+        return this.oddRowStyle;

+    }

+

+    public List<UpdateArea> getOnPaginateUpdateAreas() {

+        return this.onPaginateUpdateAreas;

+    }

+

+    public List<UpdateArea> getOnSortColumnUpdateAreas() {

+        return this.onSortColumnUpdateAreas;

+    }

+

+    /* Returns the list of ModelForm.UpdateArea objects.

+     */

+    public List<UpdateArea> getOnSubmitUpdateAreas() {

+        return this.onSubmitUpdateAreas;

+    }

+

+    public String getOverrideListSize() {

+        return overrideListSize.getOriginal();

+    }

+

+    public int getOverrideListSize(Map<String, Object> context) {

+        int listSize = 0;

+        if (!this.overrideListSize.isEmpty()) {

+            String size = this.overrideListSize.expandString(context);

+            try {

+                size = size.replaceAll("[^0-9.]", "");

+                listSize = Integer.parseInt(size);

+            } catch (NumberFormatException e) {

+                Debug.logError(e, "Error getting override list size from value " + size, module);

+            }

+        }

+        return listSize;

+    }

+

+    public String getPaginate() {

+        return paginate.getOriginal();

+    }

+

+    public boolean getPaginate(Map<String, Object> context) {

+        String paginate = this.paginate.expandString(context);

+        if (!paginate.isEmpty()) {

+            return Boolean.valueOf(paginate).booleanValue();

+        } else {

+            return true;

+        }

+    }

+

+    public String getPaginateFirstLabel() {

+        return paginateFirstLabel.getOriginal();

+    }

+

+    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 getPaginateFirstStyle() {

+        return DEFAULT_PAG_FIRST_STYLE;

+    }

+

+    public String getPaginateIndexField() {

+        return paginateIndexField.getOriginal();

+    }

+

+    public String getPaginateIndexField(Map<String, Object> context) {

+        String field = this.paginateIndexField.expandString(context);

+        if (field.isEmpty()) {

+            return DEFAULT_PAG_INDEX_FIELD;

+        }

+        return field;

+    }

+

+    public String getPaginateLastLabel() {

+        return paginateLastLabel.getOriginal();

+    }

+

+    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 getPaginateLastStyle() {

+        return DEFAULT_PAG_LAST_STYLE;

+    }

+

+    public String getPaginateNextLabel() {

+        return paginateNextLabel.getOriginal();

+    }

+

+    public String getPaginateNextLabel(Map<String, Object> context) {

+        String field = this.paginateNextLabel.expandString(context);

+        if (field.isEmpty()) {

+            Locale locale = (Locale) context.get("locale");

+            return UtilProperties.getMessage("CommonUiLabels", "CommonNext", locale);

+        }

+        return field;

+    }

+

+    public String getPaginateNextStyle() {

+        return DEFAULT_PAG_NEXT_STYLE;

+    }

+

+    public String getPaginatePreviousLabel() {

+        return paginatePreviousLabel.getOriginal();

+    }

+

+    public String getPaginatePreviousLabel(Map<String, Object> context) {

+        String field = this.paginatePreviousLabel.expandString(context);

+        if (field.isEmpty()) {

+            Locale locale = (Locale) context.get("locale");

+            field = UtilProperties.getMessage("CommonUiLabels", "CommonPrevious", locale);

+        }

+        return field;

+    }

+

+    public String getPaginatePreviousStyle() {

+        return DEFAULT_PAG_PREV_STYLE;

+    }

+

+    public String getPaginateSizeField() {

+        return paginateSizeField.getOriginal();

+    }

+

+    public String getPaginateSizeField(Map<String, Object> context) {

+        String field = this.paginateSizeField.expandString(context);

+        if (field.isEmpty()) {

+            return DEFAULT_PAG_SIZE_FIELD;

+        }

+        return field;

+    }

+

+    public String getPaginateStyle() {

+        return this.paginateStyle;

+    }

+

+    public String getPaginateTarget() {

+        return paginateTarget.getOriginal();

+    }

+

+    public String getPaginateTarget(Map<String, Object> context) {

+        String targ = this.paginateTarget.expandString(context);

+        if (targ.isEmpty()) {

+            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 getPaginateViewSizeLabel() {

+        return paginateViewSizeLabel.getOriginal();

+    }

+

+    public String getPaginateViewSizeLabel(Map<String, Object> context) {

+        String field = this.paginateViewSizeLabel.expandString(context);

+        if (field.isEmpty()) {

+            Locale locale = (Locale) context.get("locale");

+            return UtilProperties.getMessage("CommonUiLabels", "CommonItemsPerPage", locale);

+        }

+        return field;

+    }

+

+    private ModelForm getParentForm(Element formElement, ModelReader entityModelReader, DispatchContext dispatchContext) {

+        ModelForm parent = null;

+        String parentResource = formElement.getAttribute("extends-resource");

+        String parentForm = formElement.getAttribute("extends");

+        if (parentForm.length() > 0) {

+            // 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);

+                } 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, parentResource, entityModelReader, dispatchContext);

+                        break;

+                    }

+                }

+                if (parent == null) {

+                    Debug.logError("Failed to find parent form definition '" + parentForm + "' in same document.", module);

+                }

+            } else {

+                Debug.logError("Recursive form definition found for '" + formElement.getAttribute("name") + ".'", module);

+            }

+        }

+        return parent;

+    }

+

+    public String getParentFormLocation() {

+        return this.parentModelForm == null ? null : this.parentModelForm.getFormLocation();

+    }

+

+    public String getParentFormName() {

+        return this.parentModelForm == null ? null : this.parentModelForm.getName();

+    }

+

+    public ModelForm getParentModelForm() {

+        return parentModelForm;

+    }

+

+    public String getPassedRowCount(Map<String, Object> context) {

+        return rowCountExdr.expandString(context);

+    }

+

+    public List<ModelAction> getRowActions() {

+        return rowActions;

+    }

+

+    public String getRowCount() {

+        return rowCountExdr.getOriginal();

+    }

+

+    public boolean getSeparateColumns() {

+        return this.separateColumns;

+    }

+

+    public boolean getSkipEnd() {

+        return this.skipEnd;

+    }

+

+    public boolean getSkipStart() {

+        return this.skipStart;

+    }

+

+    public String getSortField(Map<String, Object> context) {

+        String value = null;

+        try {

+            value = (String) context.get(this.sortFieldParameterName);

+            if (value == null) {

+                Map<String, String> parameters = UtilGenerics.cast(context.get("parameters"));

+                if (parameters != null) {

+                    value = parameters.get(this.sortFieldParameterName);

+                }

+            }

+        } catch (Exception e) {

+            Debug.logWarning(e, "Error getting sortField: " + e.toString(), module);

+        }

+        return value;

+    }

+

+    public String getSortFieldParameterName() {

+        return this.sortFieldParameterName;

+    }

+

+    public List<SortField> getSortOrderFields() {

+        return sortOrderFields;

+    }

+

+    /**

+     * 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

+            Interpreter bsh = this.getBshInterpreter(context);

+            for (AltRowStyle altRowStyle : this.altRowStyles) {

+                Object retVal = bsh.eval(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 " + getName());

+                }

+            }

+        } catch (EvalError e) {

+            String errmsg = "Error evaluating BeanShell style conditions on form " + getName();

+            Debug.logError(e, errmsg, module);

+            throw new IllegalArgumentException(errmsg);

+        }

+        return styles;

+    }

+

+    public String getTarget() {

+        return target.getOriginal();

+    }

+

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

+        UtilCodec.SimpleEncoder simpleEncoder = (UtilCodec.SimpleEncoder) context.get("simpleEncoder");

+        if (simpleEncoder != null) {

+            expanderContext = UtilCodec.HtmlEncodingMapWrapper.getHtmlEncodingMapWrapper(context, simpleEncoder);

+        }

+        try {

+            // use the same Interpreter (ie with the same context setup) for all evals

+            Interpreter bsh = this.getBshInterpreter(context);

+            for (AltTarget altTarget : this.altTargets) {

+                String useWhen = FlexibleStringExpander.expandString(altTarget.useWhen, context);

+                Object retVal = bsh.eval(StringUtil.convertOperatorSubstitutions(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 " + getName());

+                }

+

+                if (condTrue && !targetType.equals("inter-app")) {

+                    return altTarget.targetExdr.expandString(expanderContext);

+                }

+            }

+        } catch (EvalError e) {

+            String errmsg = "Error evaluating BeanShell target conditions on form " + getName();

+            Debug.logError(e, errmsg, module);

+            throw new IllegalArgumentException(errmsg);

+        }

+        return target.expandString(expanderContext);

+    }

+

+    public String getTargetType() {

+        return this.targetType;

+    }

+

+    public String getTargetWindow() {

+        return targetWindowExdr.getOriginal();

+    }

+

+    public String getTargetWindow(Map<String, Object> context) {

+        return this.targetWindowExdr.expandString(context);

+    }

+

+    public String getTitle() {

+        return this.title;

+    }

+

+    public String getTooltip() {

+        return this.tooltip;

+    }

+

+    public String getType() {

+        return this.type;

+    }

+

+    public boolean getUseRowSubmit() {

+        return this.useRowSubmit;

+    }

+

+    public Set<String> getUseWhenFields() {

+        return useWhenFields;

+    }

+    public boolean getGroupColumns() {

+        return groupColumns;

+    }

+

+    public boolean isOverridenListSize() {

+        return !this.overrideListSize.isEmpty();

+    }

+

+    public void runFormActions(Map<String, Object> context) {

+        AbstractModelAction.runSubActions(this.actions, context);

+    }

+

+    public static class AltRowStyle {

+        public final String useWhen;

+        public final String style;

+

+        public AltRowStyle(Element altRowStyleElement) {

+            this.useWhen = altRowStyleElement.getAttribute("use-when");

+            this.style = altRowStyleElement.getAttribute("style");

+        }

+    }

+

+    public static class AltTarget {

+        public final String useWhen;

+        public final FlexibleStringExpander targetExdr;

+

+        public AltTarget(Element altTargetElement) {

+            this.useWhen = altTargetElement.getAttribute("use-when");

+            this.targetExdr = FlexibleStringExpander.getInstance(altTargetElement.getAttribute("target"));

+        }

+

+        @Override

+        public boolean equals(Object obj) {

+            return obj instanceof AltTarget && obj.hashCode() == this.hashCode();

+        }

+

+        @Override

+        public int hashCode() {

+            return useWhen.hashCode();

+        }

+    }

+

+    public static class AutoFieldsEntity {

+        public final String entityName;

+        public final String mapName;

+        public final String defaultFieldType;

+        public final 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 AutoFieldsService {

+        public final String serviceName;

+        public final String mapName;

+        public final String defaultFieldType;

+        public final 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 Banner implements FieldGroupBase {

+        public final FlexibleStringExpander style;

+        public final FlexibleStringExpander text;

+        public final FlexibleStringExpander textStyle;

+        public final FlexibleStringExpander leftText;

+        public final FlexibleStringExpander leftTextStyle;

+        public final FlexibleStringExpander rightText;

+        public final FlexibleStringExpander rightTextStyle;

+

+        public Banner(Element sortOrderElement) {

+            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 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 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 void renderString(Appendable writer, Map<String, Object> context, FormStringRenderer formStringRenderer)

+                throws IOException {

+            formStringRenderer.renderBanner(writer, context, this);

+        }

+    }

+

+    public static class FieldGroup implements FieldGroupBase {

+        private static AtomicInteger baseSeqNo = new AtomicInteger(0);

+        private static final String baseId = "_G";

+        private final String id;

+        private final String style;

+        private final String title;

+        private final boolean collapsible;

+        private final boolean initiallyCollapsed;

+        private final ModelForm modelForm;

+

+        public FieldGroup(Element sortOrderElement, ModelForm modelForm, List<SortField> sortOrderFields,

+                Map<String, FieldGroupBase> fieldGroupMap) {

+            this.modelForm = modelForm;

+            String id;

+            String style = "";

+            String title = "";

+            boolean collapsible = false;

+            boolean initiallyCollapsed = false;

+            if (sortOrderElement != null) {

+                id = sortOrderElement.getAttribute("id");

+                if (id.isEmpty()) {

+                    String lastGroupId = baseId + baseSeqNo.getAndIncrement() + "_";

+                    id = lastGroupId;

+                }

+                style = sortOrderElement.getAttribute("style");

+                title = sortOrderElement.getAttribute("title");

+                collapsible = "true".equals(sortOrderElement.getAttribute("collapsible"));

+                initiallyCollapsed = "true".equals(sortOrderElement.getAttribute("initially-collapsed"));

+                if (initiallyCollapsed) {

+                    collapsible = true;

+                }

+                for (Element sortFieldElement : UtilXml.childElementList(sortOrderElement, "sort-field")) {

+                    sortOrderFields.add(new SortField(sortFieldElement.getAttribute("name"), sortFieldElement

+                            .getAttribute("position")));

+                    fieldGroupMap.put(sortFieldElement.getAttribute("name"), this);

+                }

+            } else {

+                String lastGroupId = baseId + baseSeqNo.getAndIncrement() + "_";

+                id = lastGroupId;

+            }

+            this.id = id;

+            this.style = style;

+            this.title = title;

+            this.collapsible = collapsible;

+            this.initiallyCollapsed = initiallyCollapsed;

+        }

+

+        public Boolean collapsible() {

+            return this.collapsible;

+        }

+

+        public String getId() {

+            return this.id;

+        }

+

+        public String getStyle() {

+            return this.style;

+        }

+

+        public String getTitle() {

+            return this.title;

+        }

+

+        public Boolean initiallyCollapsed() {

+            return this.initiallyCollapsed;

+        }

+

+        public void renderEndString(Appendable writer, Map<String, Object> context, FormStringRenderer formStringRenderer)

+                throws IOException {

+            formStringRenderer.renderFormatSingleWrapperClose(writer, context, modelForm);

+            if (!modelForm.fieldGroupList.isEmpty()) {

+                if (shouldUse(context)) {

+                    formStringRenderer.renderFieldGroupClose(writer, context, this);

+                }

+            }

+        }

+

+        public void renderStartString(Appendable writer, Map<String, Object> context, FormStringRenderer formStringRenderer)

+                throws IOException {

+            if (!modelForm.fieldGroupList.isEmpty()) {

+                if (shouldUse(context)) {

+                    formStringRenderer.renderFieldGroupOpen(writer, context, this);

+                }

+            }

+            formStringRenderer.renderFormatSingleWrapperOpen(writer, context, modelForm);

+        }

+

+        public boolean shouldUse(Map<String, Object> context) {

+            for (String fieldName : modelForm.fieldGroupMap.keySet()) {

+                FieldGroupBase group = modelForm.fieldGroupMap.get(fieldName);

+                if (group instanceof FieldGroup) {

+                    FieldGroup fieldgroup = (FieldGroup) group;

+                    if (this.id.equals(fieldgroup.getId())) {

+                        for (ModelFormField modelField : modelForm.fieldList) {

+                            if (fieldName.equals(modelField.getName()) && modelField.shouldUse(context)) {

+                                return true;

+                            }

+                        }

+                    }

+                }

+            }

+            return false;

+        }

+    }

+

+    public static interface FieldGroupBase {

+    }

+

+    public static class SortField {

+        private final String fieldName;

+        private final Integer position;

+

+        public SortField(String name) {

+            this(name, 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;

+            } else {

+                this.position = null;

+            }

+        }

+

+        public String getFieldName() {

+            return this.fieldName;

+        }

+

+        public Integer getPosition() {

+            return this.position;

+        }

+    }

+

+    /** The UpdateArea class implements the <code>&lt;on-event-update-area&gt;</code>

+     * elements used in form widgets.

+     */

+    public static class UpdateArea {

+        private final String eventType;

+        private final String areaId;

+        private final String areaTarget;

+        private final String defaultServiceName;

+        private final String defaultEntityName;

+        private final CommonWidgetModels.AutoEntityParameters autoEntityParameters;

+        private final CommonWidgetModels.AutoServiceParameters autoServiceParameters;

+        private final List<CommonWidgetModels.Parameter> parameterList;

+

+        public UpdateArea(Element updateAreaElement) {

+            this(updateAreaElement, null, null);

+        }

+

+        /** XML constructor.

+         * @param updateAreaElement The <code>&lt;on-xxx-update-area&gt;</code>

+         * XML element.

+         */

+        public UpdateArea(Element updateAreaElement, String defaultServiceName, String defaultEntityName) {

+            this.eventType = updateAreaElement.getAttribute("event-type");

+            this.areaId = updateAreaElement.getAttribute("area-id");

+            this.areaTarget = updateAreaElement.getAttribute("area-target");

+            this.defaultServiceName = defaultServiceName;

+            this.defaultEntityName = defaultEntityName;

+            List<? extends Element> parameterElementList = UtilXml.childElementList(updateAreaElement, "parameter");

+            if (parameterElementList.isEmpty()) {

+                this.parameterList = Collections.emptyList();

+            } else {

+                List<CommonWidgetModels.Parameter> parameterList = new ArrayList<CommonWidgetModels.Parameter>(parameterElementList.size());

+                for (Element parameterElement : parameterElementList) {

+                    parameterList.add(new CommonWidgetModels.Parameter(parameterElement));

+                }

+                this.parameterList = Collections.unmodifiableList(parameterList);

+            }

+            Element autoServiceParamsElement = UtilXml.firstChildElement(updateAreaElement, "auto-parameters-service");

+            if (autoServiceParamsElement != null) {

+                this.autoServiceParameters = new CommonWidgetModels.AutoServiceParameters(autoServiceParamsElement);

+            } else {

+                this.autoServiceParameters = null;

+            }

+            Element autoEntityParamsElement = UtilXml.firstChildElement(updateAreaElement, "auto-parameters-entity");

+            if (autoEntityParamsElement != null) {

+                this.autoEntityParameters = new CommonWidgetModels.AutoEntityParameters(autoEntityParamsElement);

+            } else {

+                this.autoEntityParameters = null;

+            }

+        }

+

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

+            this.defaultServiceName = null;

+            this.defaultEntityName = null;

+            this.parameterList = Collections.emptyList();

+            this.autoServiceParameters = null;

+            this.autoEntityParameters = null;

+        }

+

+        @Override

+        public boolean equals(Object obj) {

+            return obj instanceof UpdateArea && obj.hashCode() == this.hashCode();

+        }

+

+        public String getAreaId() {

+            return areaId;

+        }

+

+        public String getAreaTarget(Map<String, ? extends Object> context) {

+            return FlexibleStringExpander.expandString(areaTarget, context);

+        }

+

+        public String getEventType() {

+            return eventType;

+        }

+

+        public Map<String, String> getParameterMap(Map<String, Object> context) {

+            Map<String, String> fullParameterMap = new HashMap<String, String>();

+            if (autoServiceParameters != null) {

+                fullParameterMap.putAll(autoServiceParameters.getParametersMap(context, defaultServiceName));

+            }

+            if (autoEntityParameters != null) {

+                fullParameterMap.putAll(autoEntityParameters.getParametersMap(context, defaultEntityName));

+            }

+            for (CommonWidgetModels.Parameter parameter : this.parameterList) {

+                fullParameterMap.put(parameter.getName(), parameter.getValue(context));

+            }

+

+            return fullParameterMap;

+        }

+

+        @Override

+        public int hashCode() {

+            return areaId.hashCode();

+        }

+

+        public String getAreaTarget() {

+            return areaTarget;

+        }

+

+        public String getDefaultServiceName() {

+            return defaultServiceName;

+        }

+

+        public String getDefaultEntityName() {

+            return defaultEntityName;

+        }

+

+        public CommonWidgetModels.AutoEntityParameters getAutoEntityParameters() {

+            return autoEntityParameters;

+        }

+

+        public CommonWidgetModels.AutoServiceParameters getAutoServiceParameters() {

+            return autoServiceParameters;

+        }

+

+        public List<CommonWidgetModels.Parameter> getParameterList() {

+            return parameterList;

+        }

+    }

+}

diff --git a/framework/widget/src/org/ofbiz/widget/form/ModelFormAction.java b/framework/widget/src/org/ofbiz/widget/model/ModelFormAction.java
similarity index 98%
rename from framework/widget/src/org/ofbiz/widget/form/ModelFormAction.java
rename to framework/widget/src/org/ofbiz/widget/model/ModelFormAction.java
index 29a0879..46c60c5 100644
--- a/framework/widget/src/org/ofbiz/widget/form/ModelFormAction.java
+++ b/framework/widget/src/org/ofbiz/widget/model/ModelFormAction.java
@@ -1,275 +1,272 @@
-/*******************************************************************************
- * 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.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.ListIterator;
-import java.util.Map;
-import java.util.regex.PatternSyntaxException;
-
-import org.ofbiz.base.util.Debug;
-import org.ofbiz.base.util.UtilGenerics;
-import org.ofbiz.base.util.UtilValidate;
-import org.ofbiz.base.util.UtilXml;
-import org.ofbiz.base.util.collections.FlexibleMapAccessor;
-import org.ofbiz.base.util.string.FlexibleStringExpander;
-import org.ofbiz.entity.finder.EntityFinderUtil;
-import org.ofbiz.service.GenericServiceException;
-import org.ofbiz.service.ModelService;
-import org.ofbiz.widget.AbstractModelAction;
-import org.ofbiz.widget.ModelAction;
-import org.ofbiz.widget.ModelActionVisitor;
-import org.ofbiz.widget.WidgetWorker;
-import org.w3c.dom.Element;
-
-/**
- * Abstract form action.
- */
-public abstract class ModelFormAction {
-
-    public static final String module = ModelFormAction.class.getName();
-
-    public static List<ModelAction> readSubActions(ModelForm modelForm, Element parentElement) {
-        List<? extends Element> actionElementList = UtilXml.childElementList(parentElement);
-        List<ModelAction> actions = new ArrayList<ModelAction>(actionElementList.size());
-        for (Element actionElement : UtilXml.childElementList(parentElement)) {
-            if ("service".equals(actionElement.getNodeName())) {
-                actions.add(new Service(modelForm, actionElement));
-            } else if ("entity-and".equals(actionElement.getNodeName()) || "entity-condition".equals(actionElement.getNodeName())
-                    || "get-related".equals(actionElement.getNodeName())) {
-                if (!actionElement.hasAttribute("list")) {
-                    String listName = modelForm.getListName();
-                    if (UtilValidate.isEmpty(listName)) {
-                        listName = ModelForm.DEFAULT_FORM_RESULT_LIST_NAME;
-                    }
-                    actionElement.setAttribute("list", listName);
-                }
-                actions.add(AbstractModelAction.newInstance(modelForm, actionElement));
-            } else if ("call-parent-actions".equals(actionElement.getNodeName())) {
-                actions.add(new CallParentActions(modelForm, actionElement));
-            } else {
-                actions.add(AbstractModelAction.newInstance(modelForm, actionElement));
-            }
-        }
-        return Collections.unmodifiableList(actions);
-    }
-
-    /**
-     * Models the &lt;call-parent-actions&gt; element.
-     * 
-     * @see <code>widget-form.xsd</code>
-     */
-    @SuppressWarnings("serial")
-    public static class CallParentActions extends AbstractModelAction {
-        private final ActionsKind kind;;
-        private final ModelForm modelForm;
-
-        public CallParentActions(ModelForm modelForm, Element callParentActionsElement) {
-            super(modelForm, callParentActionsElement);
-            String parentName = callParentActionsElement.getParentNode().getNodeName();
-            if ("actions".equals(parentName)) {
-                kind = ActionsKind.ACTIONS;
-            } else if ("row-actions".equals(parentName)) {
-                kind = ActionsKind.ROW_ACTIONS;
-            } else {
-                throw new IllegalArgumentException("Action element not supported for call-parent-actions : " + parentName);
-            }
-            ModelForm parentModel = modelForm.getParentModelForm();
-            if (parentModel == null) {
-                throw new IllegalArgumentException("call-parent-actions can only be used with form extending another form");
-            }
-            this.modelForm = modelForm;
-        }
-
-        @Override
-        public void accept(ModelActionVisitor visitor) throws Exception {
-            visitor.visit(this);
-        }
-
-        @Override
-        public void runAction(Map<String, Object> context) {
-            ModelForm parentModel = modelForm.getParentModelForm();
-            switch (kind) {
-            case ACTIONS:
-                parentModel.runFormActions(context);
-                break;
-            case ROW_ACTIONS:
-                AbstractModelAction.runSubActions(parentModel.getRowActions(), context);
-                break;
-            }
-        }
-
-        protected static enum ActionsKind {
-            ACTIONS, ROW_ACTIONS
-        }
-    }
-
-    /**
-     * Models the &lt;service&gt; element.
-     * 
-     * @see <code>widget-form.xsd</code>
-     */
-    @SuppressWarnings("serial")
-    public static class Service extends AbstractModelAction {
-        private final FlexibleStringExpander autoFieldMapExdr;
-        private final Map<FlexibleMapAccessor<Object>, Object> fieldMap;
-        private final boolean ignoreError;
-        private final FlexibleStringExpander resultMapListNameExdr;
-        private final FlexibleMapAccessor<Map<String, Object>> resultMapNameAcsr;
-        private final FlexibleStringExpander serviceNameExdr;
-
-        public Service(ModelForm modelForm, Element serviceElement) {
-            super(modelForm, serviceElement);
-            this.serviceNameExdr = FlexibleStringExpander.getInstance(serviceElement.getAttribute("service-name"));
-            this.resultMapNameAcsr = FlexibleMapAccessor.getInstance(serviceElement.getAttribute("result-map"));
-            this.autoFieldMapExdr = FlexibleStringExpander.getInstance(serviceElement.getAttribute("auto-field-map"));
-            FlexibleStringExpander resultMapListNameExdr = FlexibleStringExpander.getInstance("");
-            if (UtilValidate.isEmpty(serviceElement.getAttribute("result-map-list"))
-                    && UtilValidate.isEmpty(serviceElement.getAttribute("result-map-list-name"))) {
-                if (UtilValidate.isEmpty(serviceElement.getAttribute("result-map-list-iterator"))
-                        && UtilValidate.isEmpty(serviceElement.getAttribute("result-map-list-iterator-name"))) {
-                    String lstNm = modelForm.getListName();
-                    if (UtilValidate.isEmpty(lstNm)) {
-                        lstNm = ModelForm.DEFAULT_FORM_RESULT_LIST_NAME;
-                    }
-                    resultMapListNameExdr = FlexibleStringExpander.getInstance(lstNm);
-                } else {
-                    // this is deprecated, but support it for now anyway
-                    resultMapListNameExdr = FlexibleStringExpander.getInstance(serviceElement
-                            .getAttribute("result-map-list-iterator"));
-                    if (resultMapListNameExdr.isEmpty())
-                        resultMapListNameExdr = FlexibleStringExpander.getInstance(serviceElement
-                                .getAttribute("result-map-list-iterator-name"));
-                }
-            } else {
-                resultMapListNameExdr = FlexibleStringExpander.getInstance(serviceElement.getAttribute("result-map-list"));
-                if (resultMapListNameExdr.isEmpty())
-                    resultMapListNameExdr = FlexibleStringExpander.getInstance(serviceElement
-                            .getAttribute("result-map-list-name"));
-            }
-            this.resultMapListNameExdr = resultMapListNameExdr;
-            this.fieldMap = EntityFinderUtil.makeFieldMap(serviceElement);
-            this.ignoreError = "true".equals(serviceElement.getAttribute("ignore-error"));
-        }
-
-        @Override
-        public void accept(ModelActionVisitor visitor) throws Exception {
-            visitor.visit(this);
-        }
-
-        public String getServiceName() {
-            return serviceNameExdr.getOriginal();
-        }
-
-        @Override
-        public void runAction(Map<String, Object> context) {
-            String serviceNameExpanded = this.serviceNameExdr.expandString(context);
-            if (UtilValidate.isEmpty(serviceNameExpanded)) {
-                throw new IllegalArgumentException("Service name was empty, expanded from: " + this.serviceNameExdr.getOriginal());
-            }
-            String autoFieldMapString = this.autoFieldMapExdr.expandString(context);
-            boolean autoFieldMapBool = !"false".equals(autoFieldMapString);
-            try {
-                Map<String, Object> serviceContext = null;
-                if (autoFieldMapBool) {
-                    if (!"true".equals(autoFieldMapString)) {
-                        Map<String, Object> autoFieldMap = UtilGenerics.checkMap(context.get(autoFieldMapString));
-                        serviceContext = WidgetWorker.getDispatcher(context).getDispatchContext()
-                                .makeValidContext(serviceNameExpanded, ModelService.IN_PARAM, autoFieldMap);
-                    } else {
-                        serviceContext = WidgetWorker.getDispatcher(context).getDispatchContext()
-                                .makeValidContext(serviceNameExpanded, ModelService.IN_PARAM, context);
-                    }
-                } else {
-                    serviceContext = new HashMap<String, Object>();
-                }
-                if (this.fieldMap != null) {
-                    EntityFinderUtil.expandFieldMapToContext(this.fieldMap, context, serviceContext);
-                }
-                Map<String, Object> result = null;
-                if (this.ignoreError) {
-                    result = WidgetWorker.getDispatcher(context).runSync(serviceNameExpanded, serviceContext, -1, true);
-                } else {
-                    result = WidgetWorker.getDispatcher(context).runSync(serviceNameExpanded, serviceContext);
-                }
-                if (!this.resultMapNameAcsr.isEmpty()) {
-                    this.resultMapNameAcsr.put(context, result);
-                    String queryString = (String) result.get("queryString");
-                    context.put("queryString", queryString);
-                    context.put("queryStringMap", result.get("queryStringMap"));
-                    if (UtilValidate.isNotEmpty(queryString)) {
-                        try {
-                            String queryStringEncoded = queryString.replaceAll("&", "%26");
-                            context.put("queryStringEncoded", queryStringEncoded);
-                        } catch (PatternSyntaxException e) {
-
-                        }
-                    }
-                } else {
-                    context.putAll(result);
-                }
-                String listName = resultMapListNameExdr.expandString(context);
-                Object listObj = result.get(listName);
-                if (listObj != null) {
-                    if (!(listObj instanceof List<?>) && !(listObj instanceof ListIterator<?>)) {
-                        throw new IllegalArgumentException("Error in form [" + this.getModelWidget().getName()
-                                + "] calling service with name [" + serviceNameExpanded
-                                + "]: the result that is supposed to be a List or ListIterator and is not.");
-                    }
-                    context.put("listName", listName);
-                    context.put(listName, listObj);
-                }
-            } catch (GenericServiceException e) {
-                String errMsg = "Error in form [" + this.getModelWidget().getName() + "] calling service with name ["
-                        + serviceNameExpanded + "]: " + e.toString();
-                Debug.logError(e, errMsg, module);
-                if (!this.ignoreError) {
-                    throw new IllegalArgumentException(errMsg);
-                }
-            }
-        }
-
-        public FlexibleStringExpander getAutoFieldMapExdr() {
-            return autoFieldMapExdr;
-        }
-
-        public Map<FlexibleMapAccessor<Object>, Object> getFieldMap() {
-            return fieldMap;
-        }
-
-        public boolean getIgnoreError() {
-            return ignoreError;
-        }
-
-        public FlexibleStringExpander getResultMapListNameExdr() {
-            return resultMapListNameExdr;
-        }
-
-        public FlexibleMapAccessor<Map<String, Object>> getResultMapNameAcsr() {
-            return resultMapNameAcsr;
-        }
-
-        public FlexibleStringExpander getServiceNameExdr() {
-            return serviceNameExdr;
-        }
-    }
-}
+/*******************************************************************************

+ * Licensed to the Apache Software Foundation (ASF) under one

+ * or more contributor license agreements.  See the NOTICE file

+ * distributed with this work for additional information

+ * regarding copyright ownership.  The ASF licenses this file

+ * to you under the Apache License, Version 2.0 (the

+ * "License"); you may not use this file except in compliance

+ * with the License.  You may obtain a copy of the License at

+ *

+ * http://www.apache.org/licenses/LICENSE-2.0

+ *

+ * Unless required by applicable law or agreed to in writing,

+ * software distributed under the License is distributed on an

+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY

+ * KIND, either express or implied.  See the License for the

+ * specific language governing permissions and limitations

+ * under the License.

+ *******************************************************************************/

+package org.ofbiz.widget.model;

+

+import java.util.ArrayList;

+import java.util.Collections;

+import java.util.HashMap;

+import java.util.List;

+import java.util.ListIterator;

+import java.util.Map;

+import java.util.regex.PatternSyntaxException;

+

+import org.ofbiz.base.util.Debug;

+import org.ofbiz.base.util.UtilGenerics;

+import org.ofbiz.base.util.UtilValidate;

+import org.ofbiz.base.util.UtilXml;

+import org.ofbiz.base.util.collections.FlexibleMapAccessor;

+import org.ofbiz.base.util.string.FlexibleStringExpander;

+import org.ofbiz.entity.finder.EntityFinderUtil;

+import org.ofbiz.service.GenericServiceException;

+import org.ofbiz.service.ModelService;

+import org.ofbiz.widget.WidgetWorker;

+import org.w3c.dom.Element;

+

+/**

+ * Abstract form action.

+ */

+public abstract class ModelFormAction {

+

+    public static final String module = ModelFormAction.class.getName();

+

+    public static List<ModelAction> readSubActions(ModelForm modelForm, Element parentElement) {

+        List<? extends Element> actionElementList = UtilXml.childElementList(parentElement);

+        List<ModelAction> actions = new ArrayList<ModelAction>(actionElementList.size());

+        for (Element actionElement : UtilXml.childElementList(parentElement)) {

+            if ("service".equals(actionElement.getNodeName())) {

+                actions.add(new Service(modelForm, actionElement));

+            } else if ("entity-and".equals(actionElement.getNodeName()) || "entity-condition".equals(actionElement.getNodeName())

+                    || "get-related".equals(actionElement.getNodeName())) {

+                if (!actionElement.hasAttribute("list")) {

+                    String listName = modelForm.getListName();

+                    if (UtilValidate.isEmpty(listName)) {

+                        listName = ModelForm.DEFAULT_FORM_RESULT_LIST_NAME;

+                    }

+                    actionElement.setAttribute("list", listName);

+                }

+                actions.add(AbstractModelAction.newInstance(modelForm, actionElement));

+            } else if ("call-parent-actions".equals(actionElement.getNodeName())) {

+                actions.add(new CallParentActions(modelForm, actionElement));

+            } else {

+                actions.add(AbstractModelAction.newInstance(modelForm, actionElement));

+            }

+        }

+        return Collections.unmodifiableList(actions);

+    }

+

+    /**

+     * Models the &lt;call-parent-actions&gt; element.

+     * 

+     * @see <code>widget-form.xsd</code>

+     */

+    @SuppressWarnings("serial")

+    public static class CallParentActions extends AbstractModelAction {

+        private final ActionsKind kind;;

+        private final ModelForm modelForm;

+

+        public CallParentActions(ModelForm modelForm, Element callParentActionsElement) {

+            super(modelForm, callParentActionsElement);

+            String parentName = callParentActionsElement.getParentNode().getNodeName();

+            if ("actions".equals(parentName)) {

+                kind = ActionsKind.ACTIONS;

+            } else if ("row-actions".equals(parentName)) {

+                kind = ActionsKind.ROW_ACTIONS;

+            } else {

+                throw new IllegalArgumentException("Action element not supported for call-parent-actions : " + parentName);

+            }

+            ModelForm parentModel = modelForm.getParentModelForm();

+            if (parentModel == null) {

+                throw new IllegalArgumentException("call-parent-actions can only be used with form extending another form");

+            }

+            this.modelForm = modelForm;

+        }

+

+        @Override

+        public void accept(ModelActionVisitor visitor) throws Exception {

+            visitor.visit(this);

+        }

+

+        @Override

+        public void runAction(Map<String, Object> context) {

+            ModelForm parentModel = modelForm.getParentModelForm();

+            switch (kind) {

+            case ACTIONS:

+                parentModel.runFormActions(context);

+                break;

+            case ROW_ACTIONS:

+                AbstractModelAction.runSubActions(parentModel.getRowActions(), context);

+                break;

+            }

+        }

+

+        protected static enum ActionsKind {

+            ACTIONS, ROW_ACTIONS

+        }

+    }

+

+    /**

+     * Models the &lt;service&gt; element.

+     * 

+     * @see <code>widget-form.xsd</code>

+     */

+    @SuppressWarnings("serial")

+    public static class Service extends AbstractModelAction {

+        private final FlexibleStringExpander autoFieldMapExdr;

+        private final Map<FlexibleMapAccessor<Object>, Object> fieldMap;

+        private final boolean ignoreError;

+        private final FlexibleStringExpander resultMapListNameExdr;

+        private final FlexibleMapAccessor<Map<String, Object>> resultMapNameAcsr;

+        private final FlexibleStringExpander serviceNameExdr;

+

+        public Service(ModelForm modelForm, Element serviceElement) {

+            super(modelForm, serviceElement);

+            this.serviceNameExdr = FlexibleStringExpander.getInstance(serviceElement.getAttribute("service-name"));

+            this.resultMapNameAcsr = FlexibleMapAccessor.getInstance(serviceElement.getAttribute("result-map"));

+            this.autoFieldMapExdr = FlexibleStringExpander.getInstance(serviceElement.getAttribute("auto-field-map"));

+            FlexibleStringExpander resultMapListNameExdr = FlexibleStringExpander.getInstance("");

+            if (UtilValidate.isEmpty(serviceElement.getAttribute("result-map-list"))

+                    && UtilValidate.isEmpty(serviceElement.getAttribute("result-map-list-name"))) {

+                if (UtilValidate.isEmpty(serviceElement.getAttribute("result-map-list-iterator"))

+                        && UtilValidate.isEmpty(serviceElement.getAttribute("result-map-list-iterator-name"))) {

+                    String lstNm = modelForm.getListName();

+                    if (UtilValidate.isEmpty(lstNm)) {

+                        lstNm = ModelForm.DEFAULT_FORM_RESULT_LIST_NAME;

+                    }

+                    resultMapListNameExdr = FlexibleStringExpander.getInstance(lstNm);

+                } else {

+                    // this is deprecated, but support it for now anyway

+                    resultMapListNameExdr = FlexibleStringExpander.getInstance(serviceElement

+                            .getAttribute("result-map-list-iterator"));

+                    if (resultMapListNameExdr.isEmpty())

+                        resultMapListNameExdr = FlexibleStringExpander.getInstance(serviceElement

+                                .getAttribute("result-map-list-iterator-name"));

+                }

+            } else {

+                resultMapListNameExdr = FlexibleStringExpander.getInstance(serviceElement.getAttribute("result-map-list"));

+                if (resultMapListNameExdr.isEmpty())

+                    resultMapListNameExdr = FlexibleStringExpander.getInstance(serviceElement

+                            .getAttribute("result-map-list-name"));

+            }

+            this.resultMapListNameExdr = resultMapListNameExdr;

+            this.fieldMap = EntityFinderUtil.makeFieldMap(serviceElement);

+            this.ignoreError = "true".equals(serviceElement.getAttribute("ignore-error"));

+        }

+

+        @Override

+        public void accept(ModelActionVisitor visitor) throws Exception {

+            visitor.visit(this);

+        }

+

+        public String getServiceName() {

+            return serviceNameExdr.getOriginal();

+        }

+

+        @Override

+        public void runAction(Map<String, Object> context) {

+            String serviceNameExpanded = this.serviceNameExdr.expandString(context);

+            if (UtilValidate.isEmpty(serviceNameExpanded)) {

+                throw new IllegalArgumentException("Service name was empty, expanded from: " + this.serviceNameExdr.getOriginal());

+            }

+            String autoFieldMapString = this.autoFieldMapExdr.expandString(context);

+            boolean autoFieldMapBool = !"false".equals(autoFieldMapString);

+            try {

+                Map<String, Object> serviceContext = null;

+                if (autoFieldMapBool) {

+                    if (!"true".equals(autoFieldMapString)) {

+                        Map<String, Object> autoFieldMap = UtilGenerics.checkMap(context.get(autoFieldMapString));

+                        serviceContext = WidgetWorker.getDispatcher(context).getDispatchContext()

+                                .makeValidContext(serviceNameExpanded, ModelService.IN_PARAM, autoFieldMap);

+                    } else {

+                        serviceContext = WidgetWorker.getDispatcher(context).getDispatchContext()

+                                .makeValidContext(serviceNameExpanded, ModelService.IN_PARAM, context);

+                    }

+                } else {

+                    serviceContext = new HashMap<String, Object>();

+                }

+                if (this.fieldMap != null) {

+                    EntityFinderUtil.expandFieldMapToContext(this.fieldMap, context, serviceContext);

+                }

+                Map<String, Object> result = null;

+                if (this.ignoreError) {

+                    result = WidgetWorker.getDispatcher(context).runSync(serviceNameExpanded, serviceContext, -1, true);

+                } else {

+                    result = WidgetWorker.getDispatcher(context).runSync(serviceNameExpanded, serviceContext);

+                }

+                if (!this.resultMapNameAcsr.isEmpty()) {

+                    this.resultMapNameAcsr.put(context, result);

+                    String queryString = (String) result.get("queryString");

+                    context.put("queryString", queryString);

+                    context.put("queryStringMap", result.get("queryStringMap"));

+                    if (UtilValidate.isNotEmpty(queryString)) {

+                        try {

+                            String queryStringEncoded = queryString.replaceAll("&", "%26");

+                            context.put("queryStringEncoded", queryStringEncoded);

+                        } catch (PatternSyntaxException e) {

+

+                        }

+                    }

+                } else {

+                    context.putAll(result);

+                }

+                String listName = resultMapListNameExdr.expandString(context);

+                Object listObj = result.get(listName);

+                if (listObj != null) {

+                    if (!(listObj instanceof List<?>) && !(listObj instanceof ListIterator<?>)) {

+                        throw new IllegalArgumentException("Error in form [" + this.getModelWidget().getName()

+                                + "] calling service with name [" + serviceNameExpanded

+                                + "]: the result that is supposed to be a List or ListIterator and is not.");

+                    }

+                    context.put("listName", listName);

+                    context.put(listName, listObj);

+                }

+            } catch (GenericServiceException e) {

+                String errMsg = "Error in form [" + this.getModelWidget().getName() + "] calling service with name ["

+                        + serviceNameExpanded + "]: " + e.toString();

+                Debug.logError(e, errMsg, module);

+                if (!this.ignoreError) {

+                    throw new IllegalArgumentException(errMsg);

+                }

+            }

+        }

+

+        public FlexibleStringExpander getAutoFieldMapExdr() {

+            return autoFieldMapExdr;

+        }

+

+        public Map<FlexibleMapAccessor<Object>, Object> getFieldMap() {

+            return fieldMap;

+        }

+

+        public boolean getIgnoreError() {

+            return ignoreError;

+        }

+

+        public FlexibleStringExpander getResultMapListNameExdr() {

+            return resultMapListNameExdr;

+        }

+

+        public FlexibleMapAccessor<Map<String, Object>> getResultMapNameAcsr() {

+            return resultMapNameAcsr;

+        }

+

+        public FlexibleStringExpander getServiceNameExdr() {

+            return serviceNameExdr;

+        }

+    }

+}

diff --git a/framework/widget/src/org/ofbiz/widget/form/ModelFormField.java b/framework/widget/src/org/ofbiz/widget/model/ModelFormField.java
similarity index 99%
rename from framework/widget/src/org/ofbiz/widget/form/ModelFormField.java
rename to framework/widget/src/org/ofbiz/widget/model/ModelFormField.java
index f9d3ddd..4e6f3c6 100644
--- a/framework/widget/src/org/ofbiz/widget/form/ModelFormField.java
+++ b/framework/widget/src/org/ofbiz/widget/model/ModelFormField.java
@@ -1,3802 +1,3806 @@
-/*******************************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *******************************************************************************/
-package org.ofbiz.widget.form;
-
-import java.io.IOException;
-import java.math.BigDecimal;
-import java.sql.Timestamp;
-import java.text.DateFormat;
-import java.text.NumberFormat;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-import java.util.StringTokenizer;
-import java.util.TimeZone;
-
-import org.ofbiz.base.conversion.ConversionException;
-import org.ofbiz.base.conversion.DateTimeConverters;
-import org.ofbiz.base.conversion.DateTimeConverters.StringToTimestamp;
-import org.ofbiz.base.util.BshUtil;
-import org.ofbiz.base.util.Debug;
-import org.ofbiz.base.util.GeneralException;
-import org.ofbiz.base.util.ObjectType;
-import org.ofbiz.base.util.StringUtil;
-import org.ofbiz.base.util.UtilCodec;
-import org.ofbiz.base.util.UtilDateTime;
-import org.ofbiz.base.util.UtilFormatOut;
-import org.ofbiz.base.util.UtilGenerics;
-import org.ofbiz.base.util.UtilMisc;
-import org.ofbiz.base.util.UtilProperties;
-import org.ofbiz.base.util.UtilValidate;
-import org.ofbiz.base.util.UtilXml;
-import org.ofbiz.base.util.collections.FlexibleMapAccessor;
-import org.ofbiz.base.util.collections.MapStack;
-import org.ofbiz.base.util.string.FlexibleStringExpander;
-import org.ofbiz.entity.Delegator;
-import org.ofbiz.entity.GenericEntity;
-import org.ofbiz.entity.GenericEntityException;
-import org.ofbiz.entity.GenericValue;
-import org.ofbiz.entity.condition.EntityCondition;
-import org.ofbiz.entity.finder.EntityFinderUtil;
-import org.ofbiz.entity.model.ModelEntity;
-import org.ofbiz.entity.util.EntityUtil;
-import org.ofbiz.widget.CommonWidgetModels.*;
-import org.ofbiz.widget.ModelFieldVisitor;
-import org.ofbiz.widget.WidgetWorker;
-import org.ofbiz.widget.form.ModelForm.UpdateArea;
-import org.w3c.dom.Element;
-
-import bsh.EvalError;
-import bsh.Interpreter;
-
-/**
- * Models the &lt;field&gt; element.
- * 
- * @see <code>widget-form.xsd</code>
- */
-public class ModelFormField {
-
-    /*
-     * ----------------------------------------------------------------------- *
-     *                     DEVELOPERS PLEASE READ
-     * ----------------------------------------------------------------------- *
-     * 
-     * This model is intended to be a read-only data structure that represents
-     * an XML element. Outside of object construction, the class should not
-     * have any behaviors. All behavior should be contained in model visitors.
-     * 
-     * Instances of this class will be shared by multiple threads - therefore
-     * it is immutable. DO NOT CHANGE THE OBJECT'S STATE AT RUN TIME!
-     * 
-     */
-
-    public static final String module = ModelFormField.class.getName();
-
-    public static ModelFormField from(ModelFormFieldBuilder builder) {
-        return new ModelFormField(builder);
-    }
-
-    private final FlexibleStringExpander action;
-    private final String attributeName;
-    private final boolean encodeOutput;
-    private final String entityName;
-    private final FlexibleMapAccessor<Object> entryAcsr;
-    private final String event;
-    private final FieldInfo fieldInfo;
-    private final String fieldName;
-    private final String headerLink;
-    private final String headerLinkStyle;
-    private final String idName;
-    private final FlexibleMapAccessor<Map<String, ? extends Object>> mapAcsr;
-    private final ModelForm modelForm;
-    private final String name;
-    private final List<UpdateArea> onChangeUpdateAreas;
-    private final List<UpdateArea> onClickUpdateAreas;
-    private final String parameterName;
-    private final Integer position;
-    private final String redWhen;
-    private final Boolean requiredField;
-    private final String requiredFieldStyle;
-    private final boolean separateColumn;
-    private final String serviceName;
-    private final Boolean sortField;
-    private final String sortFieldAscStyle;
-    private final String sortFieldDescStyle;
-    private final String sortFieldHelpText;
-    private final String sortFieldStyle;
-    private final FlexibleStringExpander title;
-    private final String titleAreaStyle;
-    private final String titleStyle;
-    private final FlexibleStringExpander tooltip;
-    private final String tooltipStyle;
-    private final FlexibleStringExpander useWhen;
-    private final String widgetAreaStyle;
-    private final String widgetStyle;
-
-    private ModelFormField(ModelFormFieldBuilder builder) {
-        this.action = builder.getAction();
-        this.attributeName = builder.getAttributeName();
-        this.encodeOutput = builder.getEncodeOutput();
-        this.entityName = builder.getEntityName();
-        this.entryAcsr = builder.getEntryAcsr();
-        this.event = builder.getEvent();
-        if (builder.getFieldInfo() != null) {
-            this.fieldInfo = builder.getFieldInfo().copy(this);
-        } else {
-            this.fieldInfo = null;
-        }
-        this.fieldName = builder.getFieldName();
-        this.headerLink = builder.getHeaderLink();
-        this.headerLinkStyle = builder.getHeaderLinkStyle();
-        this.idName = builder.getIdName();
-        this.mapAcsr = builder.getMapAcsr();
-        this.modelForm = builder.getModelForm();
-        this.name = builder.getName();
-        if (builder.getOnChangeUpdateAreas().isEmpty()) {
-            this.onChangeUpdateAreas = Collections.emptyList();
-        } else {
-            this.onChangeUpdateAreas = Collections.unmodifiableList(new ArrayList<UpdateArea>(builder.getOnChangeUpdateAreas()));
-        }
-        if (builder.getOnClickUpdateAreas().isEmpty()) {
-            this.onClickUpdateAreas = Collections.emptyList();
-        } else {
-            this.onClickUpdateAreas = Collections.unmodifiableList(new ArrayList<UpdateArea>(builder.getOnClickUpdateAreas()));
-        }
-        this.parameterName = builder.getParameterName();
-        this.position = builder.getPosition();
-        this.redWhen = builder.getRedWhen();
-        this.requiredField = builder.getRequiredField();
-        this.requiredFieldStyle = builder.getRequiredFieldStyle();
-        this.separateColumn = builder.getSeparateColumn();
-        this.serviceName = builder.getServiceName();
-        this.sortField = builder.getSortField();
-        this.sortFieldAscStyle = builder.getSortFieldAscStyle();
-        this.sortFieldDescStyle = builder.getSortFieldDescStyle();
-        this.sortFieldHelpText = builder.getSortFieldHelpText();
-        this.sortFieldStyle = builder.getSortFieldStyle();
-        this.title = builder.getTitle();
-        this.titleAreaStyle = builder.getTitleAreaStyle();
-        this.titleStyle = builder.getTitleStyle();
-        this.tooltip = builder.getTooltip();
-        this.tooltipStyle = builder.getTooltipStyle();
-        this.useWhen = builder.getUseWhen();
-        this.widgetAreaStyle = builder.getWidgetAreaStyle();
-        this.widgetStyle = builder.getWidgetStyle();
-    }
-
-    public FlexibleStringExpander getAction() {
-        return action;
-    }
-
-    public String getAction(Map<String, ? extends Object> context) {
-        if (UtilValidate.isNotEmpty(this.action))
-            return action.expandString(context);
-        return null;
-    }
-
-    /**
-     * Gets the name of the Service Attribute (aka Parameter) that corresponds
-     * with this field. This can be used to get additional information about the field.
-     * Use the getServiceName() method to get the Entity name that the field is in.
-     *
-     * @return returns the name of the Service Attribute 
-     */
-    public String getAttributeName() {
-        if (UtilValidate.isNotEmpty(this.attributeName))
-            return this.attributeName;
-        return this.name;
-    }
-
-    public String getCurrentContainerId(Map<String, Object> context) {
-        ModelForm modelForm = this.getModelForm();
-        String idName = FlexibleStringExpander.expandString(this.getIdName(), context);
-
-        if (modelForm != null) {
-            Integer itemIndex = (Integer) context.get("itemIndex");
-            if ("list".equals(modelForm.getType()) || "multi".equals(modelForm.getType())) {
-                if (itemIndex != null) {
-                    return idName + modelForm.getItemIndexSeparator() + itemIndex.intValue();
-                }
-            }
-        }
-        return idName;
-    }
-
-    public boolean getEncodeOutput() {
-        return this.encodeOutput;
-    }
-
-    public String getEntityName() {
-        if (UtilValidate.isNotEmpty(this.entityName))
-            return this.entityName;
-        return this.modelForm.getDefaultEntityName();
-    }
-
-    /**
-     * Gets the entry from the context that corresponds to this field; if this
-     * form is being rendered in an error condition (ie isError in the context
-     * is true) then the value will be retrieved from the parameters Map in
-     * the context.
-     *
-     * @param context the context
-     * @return returns the entry from the context that corresponds to this field
-     */
-    public String getEntry(Map<String, ? extends Object> context) {
-        return this.getEntry(context, "");
-    }
-
-    public String getEntry(Map<String, ? extends Object> context, String defaultValue) {
-        Boolean isError = (Boolean) context.get("isError");
-        Boolean useRequestParameters = (Boolean) context.get("useRequestParameters");
-
-        Locale locale = (Locale) context.get("locale");
-        if (locale == null)
-            locale = Locale.getDefault();
-        TimeZone timeZone = (TimeZone) context.get("timeZone");
-        if (timeZone == null)
-            timeZone = TimeZone.getDefault();
-
-        String returnValue;
-
-        // if useRequestParameters is TRUE then parameters will always be used, if FALSE then parameters will never be used
-        // if isError is TRUE and useRequestParameters is not FALSE (ie is null or TRUE) then parameters will be used
-        if ((Boolean.TRUE.equals(isError) && !Boolean.FALSE.equals(useRequestParameters))
-                || (Boolean.TRUE.equals(useRequestParameters))) {
-            //Debug.logInfo("Getting entry, isError true so getting from parameters for field " + this.getName() + " of form " + this.modelForm.getName(), module);
-            Map<String, Object> parameters = UtilGenerics.checkMap(context.get("parameters"), String.class, Object.class);
-            String parameterName = this.getParameterName(context);
-            if (parameters != null && parameters.get(parameterName) != null) {
-                Object parameterValue = parameters.get(parameterName);
-                if (parameterValue instanceof String) {
-                    returnValue = (String) parameterValue;
-                } else {
-                    // we might want to do something else here in the future, but for now this is probably best
-                    Debug.logWarning("Found a non-String parameter value for field [" + this.getModelForm().getName() + "."
-                            + this.getFieldName() + "]", module);
-                    returnValue = defaultValue;
-                }
-            } else {
-                returnValue = defaultValue;
-            }
-        } else {
-            //Debug.logInfo("Getting entry, isError false so getting from Map in context for field " + this.getName() + " of form " + this.modelForm.getName(), module);
-            Map<String, ? extends Object> dataMap = this.getMap(context);
-            boolean dataMapIsContext = false;
-            if (dataMap == null) {
-                //Debug.logInfo("Getting entry, no Map found with name " + this.getMapName() + ", using context for field " + this.getName() + " of form " + this.modelForm.getName(), module);
-                dataMap = context;
-                dataMapIsContext = true;
-            }
-            Object retVal = null;
-            if (UtilValidate.isNotEmpty(this.entryAcsr)) {
-                if (dataMap instanceof GenericEntity) {
-                    GenericEntity genEnt = (GenericEntity) dataMap;
-                    if (genEnt.getModelEntity().isField(this.entryAcsr.getOriginalName())) {
-                        retVal = genEnt.get(this.entryAcsr.getOriginalName(), locale);
-                    } else {
-                        //TODO: this may never come up, but if necessary use the FlexibleStringExander to eval the name first: String evaled = this.entryAcsr
-                    }
-                } else {
-                    retVal = this.entryAcsr.get(dataMap, locale);
-                }
-            } else {
-                // if no entry name was specified, use the field's name
-                if (dataMap.containsKey(this.name)) {
-                    retVal = dataMap.get(this.name);
-                }
-            }
-
-            // this is a special case to fill in fields during a create by default from parameters passed in
-            if (dataMapIsContext && retVal == null && !Boolean.FALSE.equals(useRequestParameters)) {
-                Map<String, ? extends Object> parameters = UtilGenerics.checkMap(context.get("parameters"));
-                if (parameters != null) {
-                    if (UtilValidate.isNotEmpty(this.entryAcsr))
-                        retVal = this.entryAcsr.get(parameters);
-                    else
-                        retVal = parameters.get(this.name);
-                }
-            }
-
-            if (retVal != null) {
-                // format string based on the user's locale and time zone
-                if (retVal instanceof Double || retVal instanceof Float || retVal instanceof BigDecimal) {
-                    NumberFormat nf = NumberFormat.getInstance(locale);
-                    nf.setMaximumFractionDigits(10);
-                    return nf.format(retVal);
-                } else if (retVal instanceof java.sql.Date) {
-                    DateFormat df = UtilDateTime.toDateFormat(UtilDateTime.DATE_FORMAT, timeZone, null);
-                    return df.format((java.util.Date) retVal);
-                } else if (retVal instanceof java.sql.Time) {
-                    DateFormat df = UtilDateTime.toTimeFormat(UtilDateTime.TIME_FORMAT, timeZone, null);
-                    return df.format((java.util.Date) retVal);
-                } else if (retVal instanceof java.sql.Timestamp) {
-                    DateFormat df = UtilDateTime.toDateTimeFormat(UtilDateTime.DATE_TIME_FORMAT, timeZone, null);
-                    return df.format((java.util.Date) retVal);
-                } else if (retVal instanceof java.util.Date) {
-                    DateFormat df = UtilDateTime.toDateTimeFormat("EEE MMM dd hh:mm:ss z yyyy", timeZone, null);
-                    return df.format((java.util.Date) retVal);
-                } else {
-                    returnValue = retVal.toString();
-                }
-            } else {
-                returnValue = defaultValue;
-            }
-        }
-
-        if (this.getEncodeOutput() && returnValue != null) {
-            UtilCodec.SimpleEncoder simpleEncoder = (UtilCodec.SimpleEncoder) context.get("simpleEncoder");
-            if (simpleEncoder != null)
-                returnValue = simpleEncoder.encode(returnValue);
-        }
-        return returnValue;
-    }
-
-    public FlexibleMapAccessor<Object> getEntryAcsr() {
-        return entryAcsr;
-    }
-
-    public String getEntryName() {
-        if (UtilValidate.isNotEmpty(this.entryAcsr))
-            return this.entryAcsr.getOriginalName();
-        return this.name;
-    }
-
-    public String getEvent() {
-        return event;
-    }
-
-    public FieldInfo getFieldInfo() {
-        return fieldInfo;
-    }
-
-    /**
-     * Gets the name of the Entity Field that corresponds
-     * with this field. This can be used to get additional information about the field.
-     * Use the getEntityName() method to get the Entity name that the field is in.
-     *
-     * @return return the name of the Entity Field that corresponds with this field
-     */
-    public String getFieldName() {
-        if (UtilValidate.isNotEmpty(this.fieldName))
-            return this.fieldName;
-        return this.name;
-    }
-
-    public String getHeaderLink() {
-        return headerLink;
-    }
-
-    public String getHeaderLinkStyle() {
-        return headerLinkStyle;
-    }
-
-    public String getIdName() {
-        if (UtilValidate.isNotEmpty(idName))
-            return idName;
-        return this.modelForm.getName() + "_" + this.getFieldName();
-    }
-
-    public Map<String, ? extends Object> getMap(Map<String, ? extends Object> context) {
-        if (UtilValidate.isEmpty(this.mapAcsr))
-            return this.modelForm.getDefaultMap(context); //Debug.logInfo("Getting Map from default of the form because of no mapAcsr for field " + this.getName(), module);
-
-        // Debug.logInfo("Getting Map from mapAcsr for field " + this.getName() + ", map-name=" + mapAcsr.getOriginalName() + ", context type=" + context.getClass().toString(), module);
-        Map<String, ? extends Object> result = null;
-        try {
-            result = mapAcsr.get(context);
-        } catch (java.lang.ClassCastException e) {
-            String errMsg = "Got an unexpected object type (not a Map) for map-name [" + mapAcsr.getOriginalName()
-                    + "] in field with name [" + this.getName() + "]: " + e.getMessage();
-            Debug.logError(errMsg, module);
-            throw new ClassCastException(errMsg);
-        }
-        return result;
-    }
-
-    public FlexibleMapAccessor<Map<String, ? extends Object>> getMapAcsr() {
-        return mapAcsr;
-    }
-
-    /** Get the name of the Map in the form context that contains the entry,
-     * available from the getEntryName() method. This entry is used to
-     * pre-populate the field widget when not in an error condition. In an
-     * error condition the parameter name is used to get the value from the
-     * parameters Map.
-     *
-     * @return returns the name of the Map in the form context that contains the entry
-     */
-    public String getMapName() {
-        if (UtilValidate.isNotEmpty(this.mapAcsr))
-            return this.mapAcsr.getOriginalName();
-        return this.modelForm.getDefaultMapName();
-    }
-
-    public ModelForm getModelForm() {
-        return modelForm;
-    }
-
-    public String getName() {
-        return name;
-    }
-
-    public List<UpdateArea> getOnChangeUpdateAreas() {
-        return onChangeUpdateAreas;
-    }
-
-    public List<UpdateArea> getOnClickUpdateAreas() {
-        return onClickUpdateAreas;
-    }
-
-    public String getParameterName() {
-        return parameterName;
-    }
-
-    /**
-     * Get the name to use for the parameter for this field in the form interpreter.
-     * For HTML forms this is the request parameter name.
-     *
-     * @return returns the name to use for the parameter for this field in the form interpreter
-     */
-    public String getParameterName(Map<String, ? extends Object> context) {
-        String baseName;
-        if (UtilValidate.isNotEmpty(this.parameterName))
-            baseName = this.parameterName;
-        else
-            baseName = this.name;
-
-        Integer itemIndex = (Integer) context.get("itemIndex");
-        if (itemIndex != null && "multi".equals(this.modelForm.getType())) {
-            return baseName + this.modelForm.getItemIndexSeparator() + itemIndex.intValue();
-        } else {
-            return baseName;
-        }
-    }
-
-    public int getPosition() {
-        if (this.position == null)
-            return 1;
-        return position.intValue();
-    }
-
-    public String getRedWhen() {
-        return redWhen;
-    }
-
-    public boolean getRequiredField() {
-        return this.requiredField != null ? this.requiredField : false;
-    }
-
-    public String getRequiredFieldStyle() {
-        if (UtilValidate.isNotEmpty(this.requiredFieldStyle))
-            return this.requiredFieldStyle;
-        return this.modelForm.getDefaultRequiredFieldStyle();
-    }
-
-    public boolean getSeparateColumn() {
-        return this.separateColumn;
-    }
-
-    public String getServiceName() {
-        if (UtilValidate.isNotEmpty(this.serviceName))
-            return this.serviceName;
-        return this.modelForm.getDefaultServiceName();
-    }
-
-    public Boolean getSortField() {
-        return sortField;
-    }
-
-    public String getSortFieldAscStyle() {
-        return sortFieldAscStyle;
-    }
-
-    public String getSortFieldDescStyle() {
-        return sortFieldDescStyle;
-    }
-
-    public String getSortFieldHelpText() {
-        return sortFieldHelpText;
-    }
-
-    public String getSortFieldHelpText(Map<String, Object> context) {
-        return FlexibleStringExpander.expandString(this.sortFieldHelpText, context);
-    }
-
-    public String getSortFieldStyle() {
-        if (UtilValidate.isNotEmpty(this.sortFieldStyle))
-            return this.sortFieldStyle;
-        return this.modelForm.getDefaultSortFieldStyle();
-    }
-
-    public String getSortFieldStyleAsc() {
-        if (UtilValidate.isNotEmpty(this.sortFieldAscStyle))
-            return this.sortFieldAscStyle;
-        return this.modelForm.getDefaultSortFieldAscStyle();
-    }
-
-    public String getSortFieldStyleDesc() {
-        if (UtilValidate.isNotEmpty(this.sortFieldDescStyle))
-            return this.sortFieldDescStyle;
-        return this.modelForm.getDefaultSortFieldDescStyle();
-    }
-
-    public FlexibleStringExpander getTitle() {
-        return title;
-    }
-
-    public String getTitle(Map<String, Object> context) {
-        if (UtilValidate.isNotEmpty(this.title))
-            return title.expandString(context);
-
-        // create a title from the name of this field; expecting a Java method/field style name, ie productName or productCategoryId
-        if (UtilValidate.isEmpty(this.name))
-            return ""; // this should never happen, ie name is required
-
-        // search for a localized label for the field's name
-        Map<String, String> uiLabelMap = UtilGenerics.checkMap(context.get("uiLabelMap"));
-        if (uiLabelMap != null) {
-            String titleFieldName = "FormFieldTitle_" + this.name;
-            String localizedName = uiLabelMap.get(titleFieldName);
-            if (!localizedName.equals(titleFieldName)) {
-                return localizedName;
-            }
-        } else {
-            Debug.logWarning("Could not find uiLabelMap in context while rendering form " + this.modelForm.getName(), module);
-        }
-
-        // create a title from the name of this field; expecting a Java method/field style name, ie productName or productCategoryId
-        StringBuilder autoTitlewriter = new StringBuilder();
-
-        // always use upper case first letter...
-        autoTitlewriter.append(Character.toUpperCase(this.name.charAt(0)));
-
-        // just put spaces before the upper case letters
-        for (int i = 1; i < this.name.length(); i++) {
-            char curChar = this.name.charAt(i);
-            if (Character.isUpperCase(curChar)) {
-                autoTitlewriter.append(' ');
-            }
-            autoTitlewriter.append(curChar);
-        }
-
-        return autoTitlewriter.toString();
-    }
-
-    public String getTitleAreaStyle() {
-        if (UtilValidate.isNotEmpty(this.titleAreaStyle))
-            return this.titleAreaStyle;
-        return this.modelForm.getDefaultTitleAreaStyle();
-    }
-
-    public String getTitleStyle() {
-        if (UtilValidate.isNotEmpty(this.titleStyle))
-            return this.titleStyle;
-        return this.modelForm.getDefaultTitleStyle();
-    }
-
-    public FlexibleStringExpander getTooltip() {
-        return tooltip;
-    }
-
-    public String getTooltip(Map<String, Object> context) {
-        String tooltipString = "";
-        if (UtilValidate.isNotEmpty(tooltip))
-            tooltipString = tooltip.expandString(context);
-        if (this.getEncodeOutput()) {
-            UtilCodec.SimpleEncoder simpleEncoder = (UtilCodec.SimpleEncoder) context.get("simpleEncoder");
-            if (simpleEncoder != null)
-                tooltipString = simpleEncoder.encode(tooltipString);
-        }
-        return tooltipString;
-    }
-
-    public String getTooltipStyle() {
-        if (UtilValidate.isNotEmpty(this.tooltipStyle))
-            return this.tooltipStyle;
-        return this.modelForm.getDefaultTooltipStyle();
-    }
-
-    public FlexibleStringExpander getUseWhen() {
-        return useWhen;
-    }
-
-    public String getUseWhen(Map<String, Object> context) {
-        if (UtilValidate.isNotEmpty(this.useWhen))
-            return this.useWhen.expandString(context);
-        return "";
-    }
-
-    public String getWidgetAreaStyle() {
-        if (UtilValidate.isNotEmpty(this.widgetAreaStyle))
-            return this.widgetAreaStyle;
-        return this.modelForm.getDefaultWidgetAreaStyle();
-    }
-
-    public String getWidgetStyle() {
-        if (UtilValidate.isNotEmpty(this.widgetStyle))
-            return this.widgetStyle;
-        return this.modelForm.getDefaultWidgetStyle();
-    }
-
-    /**
-     * Checks if field is a row submit field.
-     */
-    public boolean isRowSubmit() {
-        if (!"multi".equals(getModelForm().getType()))
-            return false;
-        if (getFieldInfo().getFieldType() != FieldInfo.CHECK)
-            return false;
-        if (!CheckField.ROW_SUBMIT_FIELD_NAME.equals(getName()))
-            return false;
-        return true;
-    }
-
-    public boolean isSortField() {
-        return this.sortField != null && this.sortField.booleanValue();
-    }
-
-    public boolean isUseWhenEmpty() {
-        if (this.useWhen == null) {
-            return true;
-        }
-
-        return this.useWhen.isEmpty();
-    }
-
-    public void renderFieldString(Appendable writer, Map<String, Object> context, FormStringRenderer formStringRenderer)
-            throws IOException {
-        this.fieldInfo.renderFieldString(writer, context, formStringRenderer);
-    }
-
-    /**
-     * the widget/interaction part will be red if the date value is
-     *  before-now (for ex. thruDate), after-now (for ex. fromDate), or by-name (if the
-     *  field's name or entry-name or fromDate or thruDate the corresponding
-     *  action will be done); only applicable when the field is a timestamp
-     *
-     * @param context the context
-     * @return true if the field should be read otherwise false
-     */
-    public boolean shouldBeRed(Map<String, Object> context) {
-        // red-when (never | before-now | after-now | by-name) "by-name"
-
-        String redCondition = this.redWhen;
-
-        if ("never".equals(redCondition))
-            return false;
-
-        // for performance resaons we check this first, most fields will be eliminated here and the valueOfs will not be necessary
-        if (UtilValidate.isEmpty(redCondition) || "by-name".equals(redCondition)) {
-            if ("fromDate".equals(this.name) || (this.entryAcsr != null && "fromDate".equals(this.entryAcsr.getOriginalName()))) {
-                redCondition = "after-now";
-            } else if ("thruDate".equals(this.name)
-                    || (this.entryAcsr != null && "thruDate".equals(this.entryAcsr.getOriginalName()))) {
-                redCondition = "before-now";
-            } else {
-                return false;
-            }
-        }
-
-        boolean isBeforeNow = false;
-        if ("before-now".equals(redCondition)) {
-            isBeforeNow = true;
-        } else if ("after-now".equals(redCondition)) {
-            isBeforeNow = false;
-        } else {
-            return false;
-        }
-
-        java.sql.Date dateVal = null;
-        java.sql.Time timeVal = null;
-        java.sql.Timestamp timestampVal = null;
-
-        //now before going on, check to see if the current entry is a valid date and/or time and get the value
-        String value = this.getEntry(context, null);
-        try {
-            timestampVal = java.sql.Timestamp.valueOf(value);
-        } catch (Exception e) {
-            // okay, not a timestamp...
-        }
-
-        if (timestampVal == null) {
-            try {
-                dateVal = java.sql.Date.valueOf(value);
-            } catch (Exception e) {
-                // okay, not a date...
-            }
-        }
-
-        if (timestampVal == null && dateVal == null) {
-            try {
-                timeVal = java.sql.Time.valueOf(value);
-            } catch (Exception e) {
-                // okay, not a time...
-            }
-        }
-
-        if (timestampVal == null && dateVal == null && timeVal == null) {
-            return false;
-        }
-
-        long nowMillis = System.currentTimeMillis();
-        if (timestampVal != null) {
-            java.sql.Timestamp nowStamp = new java.sql.Timestamp(nowMillis);
-            if (!timestampVal.equals(nowStamp)) {
-                if (isBeforeNow) {
-                    if (timestampVal.before(nowStamp)) {
-                        return true;
-                    }
-                } else {
-                    if (timestampVal.after(nowStamp)) {
-                        return true;
-                    }
-                }
-            }
-        } else if (dateVal != null) {
-            java.sql.Date nowDate = new java.sql.Date(nowMillis);
-            if (!dateVal.equals(nowDate)) {
-                if (isBeforeNow) {
-                    if (dateVal.before(nowDate)) {
-                        return true;
-                    }
-                } else {
-                    if (dateVal.after(nowDate)) {
-                        return true;
-                    }
-                }
-            }
-        } else if (timeVal != null) {
-            java.sql.Time nowTime = new java.sql.Time(nowMillis);
-            if (!timeVal.equals(nowTime)) {
-                if (isBeforeNow) {
-                    if (timeVal.before(nowTime)) {
-                        return true;
-                    }
-                } else {
-                    if (timeVal.after(nowTime)) {
-                        return true;
-                    }
-                }
-            }
-        }
-
-        return false;
-    }
-
-    public boolean shouldUse(Map<String, Object> context) {
-        String useWhenStr = this.getUseWhen(context);
-        if (UtilValidate.isEmpty(useWhenStr))
-            return true;
-
-        try {
-            Interpreter bsh = this.modelForm.getBshInterpreter(context);
-            Object retVal = bsh.eval(StringUtil.convertOperatorSubstitutions(useWhenStr));
-            boolean condTrue = false;
-            // retVal should be a Boolean, if not something weird is up...
-            if (retVal instanceof Boolean) {
-                Boolean boolVal = (Boolean) retVal;
-                condTrue = boolVal.booleanValue();
-            } else {
-                throw new IllegalArgumentException("Return value from use-when condition eval was not a Boolean: "
-                        + (retVal != null ? retVal.getClass().getName() : "null") + " [" + retVal + "] on the field " + this.name
-                        + " of form " + this.modelForm.getName());
-            }
-
-            return condTrue;
-        } catch (EvalError e) {
-            String errMsg = "Error evaluating BeanShell use-when condition [" + useWhenStr + "] on the field " + this.name
-                    + " of form " + this.modelForm.getName() + ": " + e.toString();
-            Debug.logError(e, errMsg, module);
-            //Debug.logError("For use-when eval error context is: " + context, module);
-            throw new IllegalArgumentException(errMsg);
-        }
-    }
-
-    /**
-     * Models the &lt;auto-complete&gt; element.
-     * 
-     * @see <code>widget-form.xsd</code>
-     */
-    public static class AutoComplete {
-        private final String autoSelect;
-        private final String choices;
-        private final String frequency;
-        private final String fullSearch;
-        private final String ignoreCase;
-        private final String minChars;
-        private final String partialChars;
-        private final String partialSearch;
-
-        public AutoComplete(Element element) {
-            this.autoSelect = element.getAttribute("auto-select");
-            this.frequency = element.getAttribute("frequency");
-            this.minChars = element.getAttribute("min-chars");
-            this.choices = element.getAttribute("choices");
-            this.partialSearch = element.getAttribute("partial-search");
-            this.partialChars = element.getAttribute("partial-chars");
-            this.ignoreCase = element.getAttribute("ignore-case");
-            this.fullSearch = element.getAttribute("full-search");
-        }
-
-        public String getAutoSelect() {
-            return this.autoSelect;
-        }
-
-        public String getChoices() {
-            return this.choices;
-        }
-
-        public String getFrequency() {
-            return this.frequency;
-        }
-
-        public String getFullSearch() {
-            return this.fullSearch;
-        }
-
-        public String getIgnoreCase() {
-            return this.ignoreCase;
-        }
-
-        public String getMinChars() {
-            return this.minChars;
-        }
-
-        public String getPartialChars() {
-            return this.partialChars;
-        }
-
-        public String getPartialSearch() {
-            return this.partialSearch;
-        }
-    }
-
-    /**
-     * Models the &lt;check&gt; element.
-     * 
-     * @see <code>widget-form.xsd</code>
-     */
-    public static class CheckField extends FieldInfoWithOptions {
-        public final static String ROW_SUBMIT_FIELD_NAME = "_rowSubmit";
-        private final FlexibleStringExpander allChecked;
-
-        private CheckField(CheckField original, ModelFormField modelFormField) {
-            super(original, modelFormField);
-            this.allChecked = original.allChecked;
-        }
-
-        public CheckField(Element element, ModelFormField modelFormField) {
-            super(element, modelFormField);
-            allChecked = FlexibleStringExpander.getInstance(element.getAttribute("all-checked"));
-        }
-
-        public CheckField(int fieldSource, ModelFormField modelFormField) {
-            super(fieldSource, FieldInfo.CHECK, modelFormField);
-            this.allChecked = FlexibleStringExpander.getInstance("");
-        }
-
-        public CheckField(ModelFormField modelFormField) {
-            super(FieldInfo.SOURCE_EXPLICIT, FieldInfo.CHECK, modelFormField);
-            this.allChecked = FlexibleStringExpander.getInstance("");
-        }
-
-        @Override
-        public void accept(ModelFieldVisitor visitor) throws Exception {
-            visitor.visit(this);
-        }
-
-        @Override
-        public FieldInfo copy(ModelFormField modelFormField) {
-            return new CheckField(this, modelFormField);
-        }
-
-        public FlexibleStringExpander getAllChecked() {
-            return allChecked;
-        }
-
-        public Boolean isAllChecked(Map<String, Object> context) {
-            String allCheckedStr = this.allChecked.expandString(context);
-            if (!allCheckedStr.isEmpty())
-                return Boolean.valueOf("true".equals(allCheckedStr));
-            else
-                return null;
-        }
-
-        @Override
-        public void renderFieldString(Appendable writer, Map<String, Object> context, FormStringRenderer formStringRenderer)
-                throws IOException {
-            formStringRenderer.renderCheckField(writer, context, this);
-        }
-    }
-
-    /**
-     * Models the &lt;container&gt; element.
-     * 
-     * @see <code>widget-form.xsd</code>
-     */
-    public static class ContainerField extends FieldInfo {
-
-        private ContainerField(ContainerField original, ModelFormField modelFormField) {
-            super(original.getFieldSource(), original.getFieldType(), modelFormField);
-        }
-
-        public ContainerField(Element element, ModelFormField modelFormField) {
-            super(element, modelFormField);
-        }
-
-        public ContainerField(int fieldSource, int fieldType, ModelFormField modelFormField) {
-            super(fieldSource, fieldType, modelFormField);
-        }
-
-        @Override
-        public void accept(ModelFieldVisitor visitor) throws Exception {
-            visitor.visit(this);
-        }
-
-        @Override
-        public FieldInfo copy(ModelFormField modelFormField) {
-            return new ContainerField(this, modelFormField);
-        }
-
-        @Override
-        public void renderFieldString(Appendable writer, Map<String, Object> context, FormStringRenderer formStringRenderer)
-                throws IOException {
-            formStringRenderer.renderContainerFindField(writer, context, this);
-        }
-    }
-
-    /**
-     * Models the &lt;date-find&gt; element.
-     * 
-     * @see <code>widget-form.xsd</code>
-     */
-    public static class DateFindField extends DateTimeField {
-        private final String defaultOptionFrom;
-        private final String defaultOptionThru;
-
-        private DateFindField(DateFindField original, ModelFormField modelFormField) {
-            super(original, modelFormField);
-            this.defaultOptionFrom = original.defaultOptionFrom;
-            this.defaultOptionThru = original.defaultOptionThru;
-        }
-
-        public DateFindField(Element element, ModelFormField modelFormField) {
-            super(element, modelFormField);
-            this.defaultOptionFrom = element.getAttribute("default-option-from");
-            this.defaultOptionThru = element.getAttribute("default-option-thru");
-        }
-
-        public DateFindField(int fieldSource, ModelFormField modelFormField) {
-            super(fieldSource, modelFormField);
-            this.defaultOptionFrom = "greaterThanEqualTo";
-            this.defaultOptionThru = "lessThanEqualTo";
-        }
-
-        public DateFindField(int fieldSource, String type) {
-            super(fieldSource, type);
-            this.defaultOptionFrom = "greaterThanEqualTo";
-            this.defaultOptionThru = "lessThanEqualTo";
-        }
-
-        @Override
-        public void accept(ModelFieldVisitor visitor) throws Exception {
-            visitor.visit(this);
-        }
-
-        @Override
-        public FieldInfo copy(ModelFormField modelFormField) {
-            return new DateFindField(this, modelFormField);
-        }
-
-        public String getDefaultOptionFrom() {
-            return this.defaultOptionFrom;
-        }
-
-        public String getDefaultOptionThru() {
-            return this.defaultOptionThru;
-        }
-
-        @Override
-        public void renderFieldString(Appendable writer, Map<String, Object> context, FormStringRenderer formStringRenderer)
-                throws IOException {
-            formStringRenderer.renderDateFindField(writer, context, this);
-        }
-    }
-
-    /**
-     * Models the &lt;date-time&gt; element.
-     * 
-     * @see <code>widget-form.xsd</code>
-     */
-    public static class DateTimeField extends FieldInfo {
-        private final String clock;
-        private final FlexibleStringExpander defaultValue;
-        private final String inputMethod;
-        private final String mask;
-        private final String step;
-        private final String type;
-
-        protected DateTimeField(DateTimeField original, ModelFormField modelFormField) {
-            super(original.getFieldSource(), original.getFieldType(), modelFormField);
-            this.defaultValue = original.defaultValue;
-            this.type = original.type;
-            this.inputMethod = original.inputMethod;
-            this.clock = original.clock;
-            this.mask = original.mask;
-            this.step = original.step;
-        }
-
-        public DateTimeField(Element element, ModelFormField modelFormField) {
-            super(element, modelFormField);
-            this.defaultValue = FlexibleStringExpander.getInstance(element.getAttribute("default-value"));
-            this.type = element.getAttribute("type");
-            this.inputMethod = element.getAttribute("input-method");
-            this.clock = element.getAttribute("clock");
-            this.mask = element.getAttribute("mask");
-            String step = element.getAttribute("step");
-            if (step.isEmpty()) {
-                step = "1";
-            }
-            this.step = step;
-        }
-
-        public DateTimeField(int fieldSource, ModelFormField modelFormField) {
-            super(fieldSource, FieldInfo.DATE_TIME, modelFormField);
-            this.defaultValue = FlexibleStringExpander.getInstance("");
-            this.type = "";
-            this.inputMethod = "";
-            this.clock = "";
-            this.mask = "";
-            this.step = "1";
-        }
-
-        public DateTimeField(int fieldSource, String type) {
-            super(fieldSource, FieldInfo.DATE_TIME, null);
-            this.defaultValue = FlexibleStringExpander.getInstance("");
-            this.type = type;
-            this.inputMethod = "";
-            this.clock = "";
-            this.mask = "";
-            this.step = "1";
-        }
-
-        public DateTimeField(ModelFormField modelFormField) {
-            super(FieldInfo.SOURCE_EXPLICIT, FieldInfo.DATE_TIME, modelFormField);
-            this.defaultValue = FlexibleStringExpander.getInstance("");
-            this.type = "";
-            this.inputMethod = "";
-            this.clock = "";
-            this.mask = "";
-            this.step = "1";
-        }
-
-        @Override
-        public void accept(ModelFieldVisitor visitor) throws Exception {
-            visitor.visit(this);
-        }
-
-        @Override
-        public FieldInfo copy(ModelFormField modelFormField) {
-            return new DateTimeField(this, modelFormField);
-        }
-
-        public String getClock() {
-            return this.clock;
-        }
-
-        /**
-         * Returns the default-value if specified, otherwise the current date, time or timestamp
-         *
-         * @param context Context Map
-         * @return Default value string for date-time
-         */
-        public String getDefaultDateTimeString(Map<String, Object> context) {
-            if (UtilValidate.isNotEmpty(this.defaultValue))
-                return this.getDefaultValue(context);
-
-            if ("date".equals(this.type))
-                return (new java.sql.Date(System.currentTimeMillis())).toString();
-            else if ("time".equals(this.type))
-                return (new java.sql.Time(System.currentTimeMillis())).toString();
-            else
-                return UtilDateTime.nowTimestamp().toString();
-        }
-
-        public FlexibleStringExpander getDefaultValue() {
-            return defaultValue;
-        }
-
-        public String getDefaultValue(Map<String, Object> context) {
-            if (this.defaultValue != null) {
-                return this.defaultValue.expandString(context);
-            } else {
-                return "";
-            }
-        }
-
-        public String getInputMethod() {
-            return this.inputMethod;
-        }
-
-        public String getMask() {
-            return this.mask;
-        }
-
-        public String getStep() {
-            return this.step;
-        }
-
-        public String getType() {
-            return type;
-        }
-
-        @Override
-        public void renderFieldString(Appendable writer, Map<String, Object> context, FormStringRenderer formStringRenderer)
-                throws IOException {
-            formStringRenderer.renderDateTimeField(writer, context, this);
-        }
-    }
-
-    /**
-     * Models the &lt;display-entity&gt; element.
-     * 
-     * @see <code>widget-form.xsd</code>
-     */
-    public static class DisplayEntityField extends DisplayField {
-        private final boolean cache;
-        private final String entityName;
-        private final String keyFieldName;
-        private final SubHyperlink subHyperlink;
-
-        private DisplayEntityField(DisplayEntityField original, ModelFormField modelFormField) {
-            super(original, modelFormField);
-            this.cache = original.cache;
-            this.entityName = original.entityName;
-            this.keyFieldName = original.keyFieldName;
-            if (original.subHyperlink != null) {
-                this.subHyperlink = new SubHyperlink(original.subHyperlink, modelFormField);
-            } else {
-                this.subHyperlink = null;
-            }
-        }
-
-        public DisplayEntityField(Element element, ModelFormField modelFormField) {
-            super(element, modelFormField);
-            this.cache = !"false".equals(element.getAttribute("cache"));
-            this.entityName = element.getAttribute("entity-name");
-            this.keyFieldName = element.getAttribute("key-field-name");
-            Element subHyperlinkElement = UtilXml.firstChildElement(element, "sub-hyperlink");
-            if (subHyperlinkElement != null) {
-                this.subHyperlink = new SubHyperlink(subHyperlinkElement, modelFormField);
-            } else {
-                this.subHyperlink = null;
-            }
-        }
-
-        public DisplayEntityField(int fieldSource, ModelFormField modelFormField) {
-            super(fieldSource, FieldInfo.DISPLAY_ENTITY, modelFormField);
-            this.cache = true;
-            this.entityName = "";
-            this.keyFieldName = "";
-            this.subHyperlink = null;
-        }
-
-        public DisplayEntityField(ModelFormField modelFormField) {
-            super(FieldInfo.SOURCE_EXPLICIT, FieldInfo.DISPLAY_ENTITY, modelFormField);
-            this.cache = true;
-            this.entityName = "";
-            this.keyFieldName = "";
-            this.subHyperlink = null;
-        }
-
-        @Override
-        public void accept(ModelFieldVisitor visitor) throws Exception {
-            visitor.visit(this);
-        }
-
-        @Override
-        public FieldInfo copy(ModelFormField modelFormField) {
-            return new DisplayEntityField(this, modelFormField);
-        }
-
-        public boolean getCache() {
-            return cache;
-        }
-
-        @Override
-        public String getDescription(Map<String, Object> context) {
-            Locale locale = UtilMisc.ensureLocale(context.get("locale"));
-
-            // rather than using the context to expand the string, lookup the given entity and use it to expand the string
-            GenericValue value = null;
-            String fieldKey = this.keyFieldName;
-            if (UtilValidate.isEmpty(fieldKey))
-                fieldKey = getModelFormField().fieldName;
-
-            Delegator delegator = WidgetWorker.getDelegator(context);
-            String fieldValue = getModelFormField().getEntry(context);
-            try {
-                value = delegator.findOne(this.entityName, this.cache, fieldKey, fieldValue);
-            } catch (GenericEntityException e) {
-                String errMsg = "Error getting value from the database for display of field [" + getModelFormField().getName()
-                        + "] on form [" + getModelFormField().modelForm.getName() + "]: " + e.toString();
-                Debug.logError(e, errMsg, module);
-                throw new IllegalArgumentException(errMsg);
-            }
-
-            String retVal = null;
-            if (value != null) {
-                // expanding ${} stuff, passing locale explicitly to expand value string because it won't be found in the Entity
-                MapStack<String> localContext = MapStack.create(context);
-                // Rendering code might try to modify the GenericEntity instance,
-                // so we make a copy of it.
-                Map<String, Object> genericEntityClone = UtilGenerics.cast(value.clone());
-                localContext.push(genericEntityClone);
-
-                // expand with the new localContext, which is locale aware
-                retVal = this.getDescription().expandString(localContext, locale);
-            }
-            // try to get the entry for the field if description doesn't expand to anything
-            if (UtilValidate.isEmpty(retVal))
-                retVal = fieldValue;
-            if (UtilValidate.isEmpty(retVal))
-                retVal = "";
-            return retVal;
-        }
-
-        public String getEntityName() {
-            return entityName;
-        }
-
-        public String getKeyFieldName() {
-            return keyFieldName;
-        }
-
-        public SubHyperlink getSubHyperlink() {
-            return this.subHyperlink;
-        }
-    }
-
-    /**
-     * Models the &lt;display&gt; element.
-     * 
-     * @see <code>widget-form.xsd</code>
-     */
-    public static class DisplayField extends FieldInfo {
-        private final boolean alsoHidden;
-        private final FlexibleStringExpander currency;
-        private final FlexibleStringExpander date;
-        private final FlexibleStringExpander defaultValue;
-        private final FlexibleStringExpander description;
-        private final FlexibleStringExpander imageLocation;
-        private final InPlaceEditor inPlaceEditor;
-        private final String size; // maximum number of characters to display
-        private final String type; // matches type of field, currently text or currency
-
-        protected DisplayField(DisplayField original, ModelFormField modelFormField) {
-            super(original.getFieldSource(), original.getFieldType(), modelFormField);
-            this.alsoHidden = original.alsoHidden;
-            this.currency = original.currency;
-            this.date = original.date;
-            this.defaultValue = original.defaultValue;
-            this.description = original.description;
-            this.imageLocation = original.imageLocation;
-            this.inPlaceEditor = original.inPlaceEditor;
-            this.size = original.size;
-            this.type = original.type;
-        }
-
-        public DisplayField(Element element, ModelFormField modelFormField) {
-            super(element, modelFormField);
-            this.alsoHidden = !"false".equals(element.getAttribute("also-hidden"));
-            this.currency = FlexibleStringExpander.getInstance(element.getAttribute("currency"));
-            this.date = FlexibleStringExpander.getInstance(element.getAttribute("date"));
-            this.defaultValue = FlexibleStringExpander.getInstance(element.getAttribute("default-value"));
-            this.description = FlexibleStringExpander.getInstance(element.getAttribute("description"));
-            this.imageLocation = FlexibleStringExpander.getInstance(element.getAttribute("image-location"));
-            Element inPlaceEditorElement = UtilXml.firstChildElement(element, "in-place-editor");
-            if (inPlaceEditorElement != null) {
-                this.inPlaceEditor = new InPlaceEditor(inPlaceEditorElement);
-            } else {
-                this.inPlaceEditor = null;
-            }
-            this.size = element.getAttribute("size");
-            this.type = element.getAttribute("type");
-        }
-
-        public DisplayField(int fieldSource, int fieldType, ModelFormField modelFormField) {
-            super(fieldSource, fieldType, modelFormField);
-            this.alsoHidden = true;
-            this.currency = FlexibleStringExpander.getInstance("");
-            this.date = FlexibleStringExpander.getInstance("");
-            this.defaultValue = FlexibleStringExpander.getInstance("");
-            this.description = FlexibleStringExpander.getInstance("");
-            this.imageLocation = FlexibleStringExpander.getInstance("");
-            this.inPlaceEditor = null;
-            this.size = "";
-            this.type = "";
-        }
-
-        public DisplayField(int fieldSource, ModelFormField modelFormField) {
-            super(fieldSource, FieldInfo.DISPLAY, modelFormField);
-            this.alsoHidden = true;
-            this.currency = FlexibleStringExpander.getInstance("");
-            this.date = FlexibleStringExpander.getInstance("");
-            this.defaultValue = FlexibleStringExpander.getInstance("");
-            this.description = FlexibleStringExpander.getInstance("");
-            this.imageLocation = FlexibleStringExpander.getInstance("");
-            this.inPlaceEditor = null;
-            this.size = "";
-            this.type = "";
-        }
-
-        public DisplayField(ModelFormField modelFormField) {
-            super(FieldInfo.SOURCE_EXPLICIT, FieldInfo.DISPLAY, modelFormField);
-            this.alsoHidden = true;
-            this.currency = FlexibleStringExpander.getInstance("");
-            this.date = FlexibleStringExpander.getInstance("");
-            this.defaultValue = FlexibleStringExpander.getInstance("");
-            this.description = FlexibleStringExpander.getInstance("");
-            this.imageLocation = FlexibleStringExpander.getInstance("");
-            this.inPlaceEditor = null;
-            this.size = "";
-            this.type = "";
-        }
-
-        @Override
-        public void accept(ModelFieldVisitor visitor) throws Exception {
-            visitor.visit(this);
-        }
-
-        @Override
-        public FieldInfo copy(ModelFormField modelFormField) {
-            return new DisplayField(this, modelFormField);
-        }
-
-        public boolean getAlsoHidden() {
-            return alsoHidden;
-        }
-
-        public FlexibleStringExpander getCurrency() {
-            return currency;
-        }
-
-        public FlexibleStringExpander getDate() {
-            return date;
-        }
-
-        public FlexibleStringExpander getDefaultValue() {
-            return defaultValue;
-        }
-
-        public String getDefaultValue(Map<String, Object> context) {
-            if (this.defaultValue != null) {
-                return this.defaultValue.expandString(context);
-            } else {
-                return "";
-            }
-        }
-
-        public FlexibleStringExpander getDescription() {
-            return description;
-        }
-
-        public String getDescription(Map<String, Object> context) {
-            String retVal = null;
-            if (UtilValidate.isNotEmpty(this.description))
-                retVal = this.description.expandString(context);
-            else
-                retVal = getModelFormField().getEntry(context);
-
-            if (UtilValidate.isEmpty(retVal)) {
-                retVal = this.getDefaultValue(context);
-            } else if ("currency".equals(type)) {
-                retVal = retVal.replaceAll("&nbsp;", " "); // FIXME : encoding currency is a problem for some locale, we should not have any &nbsp; in retVal other case may arise in future...
-                Locale locale = (Locale) context.get("locale");
-                if (locale == null)
-                    locale = Locale.getDefault();
-                String isoCode = null;
-                if (UtilValidate.isNotEmpty(this.currency))
-                    isoCode = this.currency.expandString(context);
-
-                try {
-                    BigDecimal parsedRetVal = (BigDecimal) ObjectType.simpleTypeConvert(retVal, "BigDecimal", null, null, locale,
-                            true);
-                    retVal = UtilFormatOut.formatCurrency(parsedRetVal, isoCode, locale, 10); // we set the max to 10 digits as an hack to not round numbers in the ui
-                } catch (GeneralException e) {
-                    String errMsg = "Error formatting currency value [" + retVal + "]: " + e.toString();
-                    Debug.logError(e, errMsg, module);
-                    throw new IllegalArgumentException(errMsg);
-                }
-            } else if ("date".equals(this.type) && retVal.length() > 10) {
-                Locale locale = (Locale) context.get("locale");
-                if (locale == null) {
-                    locale = Locale.getDefault();
-                }
-
-                StringToTimestamp stringToTimestamp = new DateTimeConverters.StringToTimestamp();
-                Timestamp timestamp = null;
-                try {
-                    timestamp = stringToTimestamp.convert(retVal);
-                    Date date = new Date(timestamp.getTime());
-
-                    DateFormat dateFormatter = DateFormat.getDateInstance(DateFormat.SHORT, locale);
-                    retVal = dateFormatter.format(date);
-                } catch (ConversionException e) {
-                    String errMsg = "Error formatting date using default instead [" + retVal + "]: " + e.toString();
-                    Debug.logError(e, errMsg, module);
-                    // create default date value from timestamp string
-                    retVal = retVal.substring(0, 10);
-                }
-
-            } else if ("date-time".equals(this.type) && retVal.length() > 16) {
-                Locale locale = (Locale) context.get("locale");
-                TimeZone timeZone = (TimeZone) context.get("timeZone");
-                if (locale == null) {
-                    locale = Locale.getDefault();
-                }
-                if (timeZone == null) {
-                    timeZone = TimeZone.getDefault();
-                }
-
-                StringToTimestamp stringToTimestamp = new DateTimeConverters.StringToTimestamp();
-                Timestamp timestamp = null;
-                try {
-                    timestamp = stringToTimestamp.convert(retVal);
-                    Date date = new Date(timestamp.getTime());
-
-                    DateFormat dateFormatter = UtilDateTime.toDateTimeFormat(null, timeZone, locale);
-                    retVal = dateFormatter.format(date);
-                } catch (ConversionException e) {
-                    String errMsg = "Error formatting date/time using default instead [" + retVal + "]: " + e.toString();
-                    Debug.logError(e, errMsg, module);
-                    // create default date/time value from timestamp string
-                    retVal = retVal.substring(0, 16);
-                }
-            } else if ("accounting-number".equals(this.type)) {
-                Locale locale = (Locale) context.get("locale");
-                if (locale == null) {
-                    locale = Locale.getDefault();
-                }
-                try {
-                    Double parsedRetVal = (Double) ObjectType.simpleTypeConvert(retVal, "Double", null, locale, false);
-                    String template = UtilProperties.getPropertyValue("arithmetic", "accounting-number.format",
-                            "#,##0.00;(#,##0.00)");
-                    retVal = UtilFormatOut.formatDecimalNumber(parsedRetVal.doubleValue(), template, locale);
-                } catch (GeneralException e) {
-                    String errMsg = "Error formatting number [" + retVal + "]: " + e.toString();
-                    Debug.logError(e, errMsg, module);
-                    throw new IllegalArgumentException(errMsg);
-                }
-            }
-            if (UtilValidate.isNotEmpty(this.description) && retVal != null && this.getModelFormField().getEncodeOutput()) {
-                UtilCodec.SimpleEncoder simpleEncoder = (UtilCodec.SimpleEncoder) context.get("simpleEncoder");
-                if (simpleEncoder != null) {
-                    retVal = simpleEncoder.encode(retVal);
-                }
-            }
-            return retVal;
-        }
-
-        public FlexibleStringExpander getImageLocation() {
-            return imageLocation;
-        }
-
-        public String getImageLocation(Map<String, Object> context) {
-            if (this.imageLocation != null)
-                return this.imageLocation.expandString(context);
-            return "";
-        }
-
-        public InPlaceEditor getInPlaceEditor() {
-            return this.inPlaceEditor;
-        }
-
-        public String getSize() {
-            return this.size;
-        }
-
-        public String getType() {
-            return this.type;
-        }
-
-        @Override
-        public void renderFieldString(Appendable writer, Map<String, Object> context, FormStringRenderer formStringRenderer)
-                throws IOException {
-            formStringRenderer.renderDisplayField(writer, context, this);
-        }
-    }
-
-    /**
-     * Models the &lt;drop-down&gt; element.
-     * 
-     * @see <code>widget-form.xsd</code>
-     */
-    public static class DropDownField extends FieldInfoWithOptions {
-        private final boolean allowEmpty;
-        private final boolean allowMulti;
-        private final AutoComplete autoComplete;
-        private final String current;
-        private final FlexibleStringExpander currentDescription;
-        private final int otherFieldSize;
-        private final String size;
-        private final SubHyperlink subHyperlink;
-        private final String textSize;
-
-        private DropDownField(DropDownField original, ModelFormField modelFormField) {
-            super(original, modelFormField);
-            this.allowEmpty = original.allowEmpty;
-            this.allowMulti = original.allowMulti;
-            this.autoComplete = original.autoComplete;
-            this.current = original.current;
-            this.currentDescription = original.currentDescription;
-            this.otherFieldSize = original.otherFieldSize;
-            this.size = original.size;
-            if (original.subHyperlink != null) {
-                this.subHyperlink = new SubHyperlink(original.subHyperlink, modelFormField);
-            } else {
-                this.subHyperlink = null;
-            }
-            this.textSize = original.textSize;
-        }
-
-        public DropDownField(Element element, ModelFormField modelFormField) {
-            super(element, modelFormField);
-            this.allowEmpty = "true".equals(element.getAttribute("allow-empty"));
-            this.allowMulti = "true".equals(element.getAttribute("allow-multiple"));
-            Element autoCompleteElement = UtilXml.firstChildElement(element, "auto-complete");
-            if (autoCompleteElement != null) {
-                this.autoComplete = new AutoComplete(autoCompleteElement);
-            } else {
-                this.autoComplete = null;
-            }
-            this.current = element.getAttribute("current");
-            this.currentDescription = FlexibleStringExpander.getInstance(element.getAttribute("current-description"));
-            int otherFieldSize = 0;
-            String sizeStr = element.getAttribute("other-field-size");
-            if (!sizeStr.isEmpty()) {
-                try {
-                    otherFieldSize = Integer.parseInt(sizeStr);
-                } catch (Exception e) {
-                    Debug.logError("Could not parse the size value of the text element: [" + sizeStr
-                            + "], setting to the default of 0", module);
-                }
-            }
-            this.otherFieldSize = otherFieldSize;
-            String size = element.getAttribute("size");
-            if (size.isEmpty()) {
-                size = "1";
-            }
-            this.size = size;
-            Element subHyperlinkElement = UtilXml.firstChildElement(element, "sub-hyperlink");
-            if (subHyperlinkElement != null) {
-                this.subHyperlink = new SubHyperlink(subHyperlinkElement, this.getModelFormField());
-            } else {
-                this.subHyperlink = null;
-            }
-            String textSize = element.getAttribute("text-size");
-            if (textSize.isEmpty()) {
-                textSize = "0";
-            }
-            this.textSize = textSize;
-        }
-
-        public DropDownField(int fieldSource, List<OptionSource> optionSources) {
-            super(fieldSource, FieldInfo.DROP_DOWN, optionSources);
-            this.allowEmpty = false;
-            this.allowMulti = false;
-            this.autoComplete = null;
-            this.current = "";
-            this.currentDescription = FlexibleStringExpander.getInstance("");
-            this.otherFieldSize = 0;
-            this.size = "1";
-            this.subHyperlink = null;
-            this.textSize = "0";
-        }
-
-        public DropDownField(int fieldSource, ModelFormField modelFormField) {
-            super(fieldSource, FieldInfo.DROP_DOWN, modelFormField);
-            this.allowEmpty = false;
-            this.allowMulti = false;
-            this.autoComplete = null;
-            this.current = "";
-            this.currentDescription = FlexibleStringExpander.getInstance("");
-            this.otherFieldSize = 0;
-            this.size = "1";
-            this.subHyperlink = null;
-            this.textSize = "0";
-        }
-
-        public DropDownField(ModelFormField modelFormField) {
-            super(FieldInfo.SOURCE_EXPLICIT, FieldInfo.DROP_DOWN, modelFormField);
-            this.allowEmpty = false;
-            this.allowMulti = false;
-            this.autoComplete = null;
-            this.current = "";
-            this.currentDescription = FlexibleStringExpander.getInstance("");
-            this.otherFieldSize = 0;
-            this.size = "1";
-            this.subHyperlink = null;
-            this.textSize = "0";
-        }
-
-        @Override
-        public void accept(ModelFieldVisitor visitor) throws Exception {
-            visitor.visit(this);
-        }
-
-        @Override
-        public FieldInfo copy(ModelFormField modelFormField) {
-            return new DropDownField(this, modelFormField);
-        }
-
-        public boolean getAllowMulti() {
-            return allowMulti;
-        }
-
-        public AutoComplete getAutoComplete() {
-            return this.autoComplete;
-        }
-
-        public String getCurrent() {
-            if (UtilValidate.isEmpty(this.current))
-                return "first-in-list";
-            return this.current;
-        }
-
-        public FlexibleStringExpander getCurrentDescription() {
-            return currentDescription;
-        }
-
-        public String getCurrentDescription(Map<String, Object> context) {
-            if (this.currentDescription == null)
-                return null;
-            return this.currentDescription.expandString(context);
-        }
-
-        public int getOtherFieldSize() {
-            return this.otherFieldSize;
-        }
-
-        /**
-         * Get the name to use for the parameter for this field in the form interpreter.
-         * For HTML forms this is the request parameter name.
-         * @param context the context
-         * @return returns the name to use for the parameter for this field in the form interpreter.
-         */
-        public String getParameterNameOther(Map<String, Object> context) {
-            String baseName;
-            if (UtilValidate.isNotEmpty(getModelFormField().parameterName))
-                baseName = getModelFormField().parameterName;
-            else
-                baseName = getModelFormField().name;
-
-            baseName += "_OTHER";
-            Integer itemIndex = (Integer) context.get("itemIndex");
-            if (itemIndex != null && "multi".equals(getModelFormField().modelForm.getType())) {
-                return baseName + getModelFormField().modelForm.getItemIndexSeparator() + itemIndex.intValue();
-            } else {
-                return baseName;
-            }
-        }
-
-        public String getSize() {
-            return this.size;
-        }
-
-        public SubHyperlink getSubHyperlink() {
-            return this.subHyperlink;
-        }
-
-        public String getTextSize() {
-            return this.textSize;
-        }
-
-        public boolean getAllowEmpty() {
-            return this.allowEmpty;
-        }
-
-        public boolean getAllowMultiple() {
-            return this.allowMulti;
-        }
-
-        @Override
-        public void renderFieldString(Appendable writer, Map<String, Object> context, FormStringRenderer formStringRenderer)
-                throws IOException {
-            formStringRenderer.renderDropDownField(writer, context, this);
-        }
-    }
-
-    /**
-     * Models the &lt;entity-options&gt; element.
-     * 
-     * @see <code>widget-form.xsd</code>
-     */
-    public static class EntityOptions extends OptionSource {
-        private final boolean cache;
-        private final List<EntityFinderUtil.ConditionExpr> constraintList;
-        private final FlexibleStringExpander description;
-        private final String entityName;
-        private final String filterByDate;
-        private final String keyFieldName;
-        private final List<String> orderByList;
-
-        public EntityOptions(Element entityOptionsElement, ModelFormField modelFormField) {
-            super(modelFormField);
-            this.cache = !"false".equals(entityOptionsElement.getAttribute("cache"));
-            List<? extends Element> constraintElements = UtilXml.childElementList(entityOptionsElement, "entity-constraint");
-            if (!constraintElements.isEmpty()) {
-                List<EntityFinderUtil.ConditionExpr> constraintList = new ArrayList<EntityFinderUtil.ConditionExpr>(
-                        constraintElements.size());
-                for (Element constraintElement : constraintElements) {
-                    constraintList.add(new EntityFinderUtil.ConditionExpr(constraintElement));
-                }
-                this.constraintList = Collections.unmodifiableList(constraintList);
-            } else {
-                this.constraintList = Collections.emptyList();
-            }
-            this.description = FlexibleStringExpander.getInstance(entityOptionsElement.getAttribute("description"));
-            this.entityName = entityOptionsElement.getAttribute("entity-name");
-            this.filterByDate = entityOptionsElement.getAttribute("filter-by-date");
-            this.keyFieldName = entityOptionsElement.getAttribute("key-field-name");
-            List<? extends Element> orderByElements = UtilXml.childElementList(entityOptionsElement, "entity-order-by");
-            if (!orderByElements.isEmpty()) {
-                List<String> orderByList = new ArrayList<String>(orderByElements.size());
-                for (Element orderByElement : orderByElements) {
-                    orderByList.add(orderByElement.getAttribute("field-name"));
-                }
-                this.orderByList = Collections.unmodifiableList(orderByList);
-            } else {
-                this.orderByList = Collections.emptyList();
-            }
-        }
-
-        private EntityOptions(EntityOptions original, ModelFormField modelFormField) {
-            super(modelFormField);
-            this.cache = original.cache;
-            this.constraintList = original.constraintList;
-            this.description = original.description;
-            this.entityName = original.entityName;
-            this.filterByDate = original.filterByDate;
-            this.keyFieldName = original.keyFieldName;
-            this.orderByList = original.orderByList;
-        }
-
-        public EntityOptions(ModelFormField modelFormField) {
-            super(modelFormField);
-            this.cache = true;
-            this.constraintList = Collections.emptyList();
-            this.description = FlexibleStringExpander.getInstance("");
-            this.entityName = "";
-            this.filterByDate = "";
-            this.keyFieldName = "";
-            this.orderByList = Collections.emptyList();
-        }
-
-        @Override
-        public void addOptionValues(List<OptionValue> optionValues, Map<String, Object> context, Delegator delegator) {
-            // first expand any conditions that need expanding based on the current context
-            EntityCondition findCondition = null;
-            if (UtilValidate.isNotEmpty(this.constraintList)) {
-                List<EntityCondition> expandedConditionList = new LinkedList<EntityCondition>();
-                for (EntityFinderUtil.Condition condition : constraintList) {
-                    ModelEntity modelEntity = delegator.getModelEntity(this.entityName);
-                    if (modelEntity == null) {
-                        throw new IllegalArgumentException("Error in entity-options: could not find entity [" + this.entityName
-                                + "]");
-                    }
-                    EntityCondition createdCondition = condition.createCondition(context, modelEntity,
-                            delegator.getModelFieldTypeReader(modelEntity));
-                    if (createdCondition != null) {
-                        expandedConditionList.add(createdCondition);
-                    }
-                }
-                findCondition = EntityCondition.makeCondition(expandedConditionList);
-            }
-
-            try {
-                Locale locale = UtilMisc.ensureLocale(context.get("locale"));
-
-                List<GenericValue> values = null;
-                values = delegator.findList(this.entityName, findCondition, null, this.orderByList, null, this.cache);
-
-                // filter-by-date if requested
-                if ("true".equals(this.filterByDate)) {
-                    values = EntityUtil.filterByDate(values, true);
-                } else if (!"false".equals(this.filterByDate)) {
-                    // not explicitly true or false, check to see if has fromDate and thruDate, if so do the filter
-                    ModelEntity modelEntity = delegator.getModelEntity(this.entityName);
-                    if (modelEntity != null && modelEntity.isField("fromDate") && modelEntity.isField("thruDate")) {
-                        values = EntityUtil.filterByDate(values, true);
-                    }
-                }
-
-                for (GenericValue value : values) {
-                    // add key and description with string expansion, ie expanding ${} stuff, passing locale explicitly to expand value string because it won't be found in the Entity
-                    MapStack<String> localContext = MapStack.create(context);
-                    // Rendering code might try to modify the GenericEntity instance,
-                    // so we make a copy of it.
-                    Map<String, Object> genericEntityClone = UtilGenerics.cast(value.clone());
-                    localContext.push(genericEntityClone);
-
-                    // expand with the new localContext, which is locale aware
-                    String optionDesc = this.description.expandString(localContext, locale);
-
-                    Object keyFieldObject = value.get(this.getKeyFieldName());
-                    if (keyFieldObject == null) {
-                        throw new IllegalArgumentException(
-                                "The entity-options identifier (from key-name attribute, or default to the field name) ["
-                                        + this.getKeyFieldName() + "], may not be a valid key field name for the entity ["
-                                        + this.entityName + "].");
-                    }
-                    String keyFieldValue = keyFieldObject.toString();
-                    optionValues.add(new OptionValue(keyFieldValue, optionDesc));
-                }
-            } catch (GenericEntityException e) {
-                Debug.logError(e, "Error getting entity options in form", module);
-            }
-        }
-
-        @Override
-        public OptionSource copy(ModelFormField modelFormField) {
-            return new EntityOptions(this, modelFormField);
-        }
-
-        public boolean getCache() {
-            return cache;
-        }
-
-        public List<EntityFinderUtil.ConditionExpr> getConstraintList() {
-            return constraintList;
-        }
-
-        public FlexibleStringExpander getDescription() {
-            return description;
-        }
-
-        public String getEntityName() {
-            return entityName;
-        }
-
-        public String getFilterByDate() {
-            return filterByDate;
-        }
-
-        public String getKeyFieldName() {
-            if (UtilValidate.isNotEmpty(this.keyFieldName))
-                return this.keyFieldName;
-            return getModelFormField().getFieldName(); // get the modelFormField fieldName
-        }
-
-        public List<String> getOrderByList() {
-            return orderByList;
-        }
-    }
-
-    public static abstract class FieldInfoWithOptions extends FieldInfo {
-
-        public static String getDescriptionForOptionKey(String key, List<OptionValue> allOptionValues) {
-            if (UtilValidate.isEmpty(key))
-                return "";
-
-            if (UtilValidate.isEmpty(allOptionValues))
-                return key;
-
-            for (OptionValue optionValue : allOptionValues) {
-                if (key.equals(optionValue.getKey())) {
-                    return optionValue.getDescription();
-                }
-            }
-
-            // if we get here we didn't find a match, just return the key
-            return key;
-        }
-
-        private final FlexibleStringExpander noCurrentSelectedKey;
-        private final List<OptionSource> optionSources;
-
-        public FieldInfoWithOptions(Element element, ModelFormField modelFormField) {
-            super(element, modelFormField);
-            this.noCurrentSelectedKey = FlexibleStringExpander.getInstance(element.getAttribute("no-current-selected-key"));
-            // read all option and entity-options sub-elements, maintaining order
-            ArrayList<OptionSource> optionSources = new ArrayList<OptionSource>();
-            List<? extends Element> childElements = UtilXml.childElementList(element);
-            if (childElements.size() > 0) {
-                for (Element childElement : childElements) {
-                    if ("option".equals(childElement.getTagName())) {
-                        optionSources.add(new SingleOption(childElement, modelFormField));
-                    } else if ("list-options".equals(childElement.getTagName())) {
-                        optionSources.add(new ListOptions(childElement, modelFormField));
-                    } else if ("entity-options".equals(childElement.getTagName())) {
-                        optionSources.add(new EntityOptions(childElement, modelFormField));
-                    }
-                }
-            } else {
-                // this must be added or the multi-form select box options would not show up
-                optionSources.add(new SingleOption("Y", " ", modelFormField));
-            }
-            optionSources.trimToSize();
-            this.optionSources = Collections.unmodifiableList(optionSources);
-        }
-
-        // Copy constructor.
-        protected FieldInfoWithOptions(FieldInfoWithOptions original, ModelFormField modelFormField) {
-            super(original.getFieldSource(), original.getFieldType(), modelFormField);
-            this.noCurrentSelectedKey = original.noCurrentSelectedKey;
-            if (original.optionSources.isEmpty()) {
-                this.optionSources = original.optionSources;
-            } else {
-                List<OptionSource> optionSources = new ArrayList<OptionSource>(original.optionSources.size());
-                for (OptionSource source : original.optionSources) {
-                    optionSources.add(source.copy(modelFormField));
-                }
-                this.optionSources = Collections.unmodifiableList(optionSources);
-            }
-        }
-
-        protected FieldInfoWithOptions(int fieldSource, int fieldType, List<OptionSource> optionSources) {
-            super(fieldSource, fieldType, null);
-            this.noCurrentSelectedKey = FlexibleStringExpander.getInstance("");
-            this.optionSources = Collections.unmodifiableList(new ArrayList<OptionSource>(optionSources));
-        }
-
-        public FieldInfoWithOptions(int fieldSource, int fieldType, ModelFormField modelFormField) {
-            super(fieldSource, fieldType, modelFormField);
-            this.noCurrentSelectedKey = FlexibleStringExpander.getInstance("");
-            this.optionSources = Collections.emptyList();
-        }
-
-        public List<OptionValue> getAllOptionValues(Map<String, Object> context, Delegator delegator) {
-            List<OptionValue> optionValues = new LinkedList<OptionValue>();
-            for (OptionSource optionSource : this.optionSources) {
-                optionSource.addOptionValues(optionValues, context, delegator);
-            }
-            return optionValues;
-        }
-
-        public FlexibleStringExpander getNoCurrentSelectedKey() {
-            return noCurrentSelectedKey;
-        }
-
-        public String getNoCurrentSelectedKey(Map<String, Object> context) {
-            return this.noCurrentSelectedKey.expandString(context);
-        }
-
-        public List<OptionSource> getOptionSources() {
-            return optionSources;
-        }
-    }
-
-    /**
-     * Models the &lt;file&gt; element.
-     * 
-     * @see <code>widget-form.xsd</code>
-     */
-    public static class FileField extends TextField {
-
-        public FileField(Element element, ModelFormField modelFormField) {
-            super(element, modelFormField);
-        }
-
-        private FileField(FileField original, ModelFormField modelFormField) {
-            super(original, modelFormField);
-        }
-
-        public FileField(int fieldSource, ModelFormField modelFormField) {
-            super(fieldSource, modelFormField);
-        }
-
-        @Override
-        public void accept(ModelFieldVisitor visitor) throws Exception {
-            visitor.visit(this);
-        }
-
-        @Override
-        public FieldInfo copy(ModelFormField modelFormField) {
-            return new FileField(this, modelFormField);
-        }
-
-        @Override
-        public void renderFieldString(Appendable writer, Map<String, Object> context, FormStringRenderer formStringRenderer)
-                throws IOException {
-            formStringRenderer.renderFileField(writer, context, this);
-        }
-    }
-
-    /**
-     * Models the &lt;hidden&gt; element.
-     * 
-     * @see <code>widget-form.xsd</code>
-     */
-    public static class HiddenField extends FieldInfo {
-        private final FlexibleStringExpander value;
-
-        public HiddenField(Element element, ModelFormField modelFormField) {
-            super(element, modelFormField);
-            this.value = FlexibleStringExpander.getInstance(element.getAttribute("value"));
-        }
-
-        private HiddenField(HiddenField original, ModelFormField modelFormField) {
-            super(original.getFieldSource(), original.getFieldType(), modelFormField);
-            this.value = original.value;
-        }
-
-        public HiddenField(int fieldSource, ModelFormField modelFormField) {
-            super(fieldSource, FieldInfo.HIDDEN, modelFormField);
-            this.value = FlexibleStringExpander.getInstance("");
-        }
-
-        public HiddenField(ModelFormField modelFormField) {
-            super(FieldInfo.SOURCE_EXPLICIT, FieldInfo.HIDDEN, modelFormField);
-            this.value = FlexibleStringExpander.getInstance("");
-        }
-
-        @Override
-        public void accept(ModelFieldVisitor visitor) throws Exception {
-            visitor.visit(this);
-        }
-
-        @Override
-        public FieldInfo copy(ModelFormField modelFormField) {
-            return new HiddenField(this, modelFormField);
-        }
-
-        public FlexibleStringExpander getValue() {
-            return value;
-        }
-
-        public String getValue(Map<String, Object> context) {
-            if (UtilValidate.isNotEmpty(this.value)) {
-                String valueEnc = this.value.expandString(context);
-                UtilCodec.SimpleEncoder simpleEncoder = (UtilCodec.SimpleEncoder) context.get("simpleEncoder");
-                if (simpleEncoder != null) {
-                    valueEnc = simpleEncoder.encode(valueEnc);
-                }
-                return valueEnc;
-            } else {
-                return getModelFormField().getEntry(context);
-            }
-        }
-
-        @Override
-        public void renderFieldString(Appendable writer, Map<String, Object> context, FormStringRenderer formStringRenderer)
-                throws IOException {
-            formStringRenderer.renderHiddenField(writer, context, this);
-        }
-    }
-
-    /**
-     * Models the &lt;hyperlink&gt; element.
-     * 
-     * @see <code>widget-form.xsd</code>
-     */
-    public static class HyperlinkField extends FieldInfo {
-
-        private final boolean alsoHidden;
-        private final FlexibleStringExpander confirmationMsgExdr;
-        private final FlexibleStringExpander description;
-        private final boolean requestConfirmation;
-        private final Link link;
-        public HyperlinkField(Element element, ModelFormField modelFormField) {
-            super(element, modelFormField);
-            this.alsoHidden = !"false".equals(element.getAttribute("also-hidden"));
-            this.confirmationMsgExdr = FlexibleStringExpander.getInstance(element.getAttribute("confirmation-message"));
-            this.description = FlexibleStringExpander.getInstance(element.getAttribute("description"));
-            this.requestConfirmation = "true".equals(element.getAttribute("request-confirmation"));
-            this.link = new Link(element);
-        }
-
-        private HyperlinkField(HyperlinkField original, ModelFormField modelFormField) {
-            super(original.getFieldSource(), original.getFieldType(), modelFormField);
-            this.alsoHidden = original.alsoHidden;
-            this.confirmationMsgExdr = original.confirmationMsgExdr;
-            this.description = original.description;
-            this.requestConfirmation = original.requestConfirmation;
-            this.link = original.link;
-        }
-
-        @Override
-        public void accept(ModelFieldVisitor visitor) throws Exception {
-            visitor.visit(this);
-        }
-
-        @Override
-        public FieldInfo copy(ModelFormField modelFormField) {
-            return new HyperlinkField(this, modelFormField);
-        }
-
-        public boolean getAlsoHidden() {
-            return this.alsoHidden;
-        }
-
-        public String getConfirmation(Map<String, Object> context) {
-            String message = getConfirmationMsg(context);
-            if (UtilValidate.isNotEmpty(message))
-                return message;
-            if (getRequestConfirmation()) {
-                String defaultMessage = UtilProperties.getPropertyValue("general", "default.confirmation.message",
-                        "${uiLabelMap.CommonConfirm}");
-                return FlexibleStringExpander.expandString(defaultMessage, context);
-            }
-            return "";
-        }
-
-        public String getAlternate(Map<String, Object> context) {
-            if (link.getImage() != null) {
-                return link.getImage().getAlt(context);
-            }
-            return "";
-        }
-
-        public String getImageTitle(Map<String, Object> context) {
-            if (link.getImage() != null) {
-                return link.getImage().getTitleExdr().expandString(context);
-            }
-            return "";
-        }
-
-        public String getImageLocation(Map<String, Object> context) {
-            if (link.getImage() != null) {
-                return link.getImage().getSrc(context);
-            }
-            return "";
-        }
-
-        public String getConfirmationMsg(Map<String, Object> context) {
-            return this.confirmationMsgExdr.expandString(context);
-        }
-
-        public FlexibleStringExpander getConfirmationMsgExdr() {
-            return confirmationMsgExdr;
-        }
-
-        public FlexibleStringExpander getDescription() {
-            return description;
-        }
-
-        public String getDescription(Map<String, Object> context) {
-            return this.description.expandString(context);
-        }
-
-        public boolean getRequestConfirmation() {
-            return this.requestConfirmation;
-        }
-
-        public Link getLink() {
-            return link;
-        }
-
-        public AutoEntityParameters getAutoEntityParameters() {
-            return link.getAutoEntityParameters();
-        }
-
-        public AutoServiceParameters getAutoServiceParameters() {
-            return link.getAutoServiceParameters();
-        }
-
-        public boolean getEncode() {
-            return link.getEncode();
-        }
-
-        public boolean getFullPath() {
-            return link.getFullPath();
-        }
-
-        public String getHeight() {
-            return link.getHeight();
-        }
-
-        public String getId(Map<String, Object> context) {
-            return link.getId(context);
-        }
-
-        public FlexibleStringExpander getIdExdr() {
-            return link.getIdExdr();
-        }
-
-        public Image getImage() {
-            return link.getImage();
-        }
-
-        public String getLinkType() {
-            return link.getLinkType();
-        }
-
-        public String getName() {
-            return link.getName();
-        }
-
-        public String getName(Map<String, Object> context) {
-            return link.getName(context);
-        }
-
-        public FlexibleStringExpander getNameExdr() {
-            return link.getNameExdr();
-        }
-
-        public List<Parameter> getParameterList() {
-            return link.getParameterList();
-        }
-
-        public Map<String, String> getParameterMap(Map<String, Object> context) {
-            return link.getParameterMap(context);
-        }
-
-        public String getPrefix(Map<String, Object> context) {
-            return link.getPrefix(context);
-        }
-
-        public FlexibleStringExpander getPrefixExdr() {
-            return link.getPrefixExdr();
-        }
-
-        public boolean getSecure() {
-            return link.getSecure();
-        }
-
-        public Integer getSize() {
-            return link.getSize();
-        }
-
-        public String getStyle(Map<String, Object> context) {
-            return link.getStyle(context);
-        }
-
-        public FlexibleStringExpander getStyleExdr() {
-            return link.getStyleExdr();
-        }
-
-        public String getTarget(Map<String, Object> context) {
-            return link.getTarget(context);
-        }
-
-        public FlexibleStringExpander getTargetExdr() {
-            return link.getTargetExdr();
-        }
-
-        public String getTargetWindow(Map<String, Object> context) {
-            return link.getTargetWindow(context);
-        }
-
-        public FlexibleStringExpander getTargetWindowExdr() {
-            return link.getTargetWindowExdr();
-        }
-
-        public String getText(Map<String, Object> context) {
-            return link.getText(context);
-        }
-
-        public FlexibleStringExpander getTextExdr() {
-            return link.getTextExdr();
-        }
-
-        public String getUrlMode() {
-            return link.getUrlMode();
-        }
-
-        public String getWidth() {
-            return link.getWidth();
-        }
-
-        @Override
-        public void renderFieldString(Appendable writer, Map<String, Object> context, FormStringRenderer formStringRenderer)
-                throws IOException {
-            formStringRenderer.renderHyperlinkField(writer, context, this);
-        }
-    }
-
-    /**
-     * Models the &lt;ignored&gt; element.
-     * 
-     * @see <code>widget-form.xsd</code>
-     */
-    public static class IgnoredField extends FieldInfo {
-
-        public IgnoredField(Element element, ModelFormField modelFormField) {
-            super(element, modelFormField);
-        }
-
-        private IgnoredField(IgnoredField original, ModelFormField modelFormField) {
-            super(original.getFieldSource(), original.getFieldType(), modelFormField);
-        }
-
-        public IgnoredField(int fieldSource, ModelFormField modelFormField) {
-            super(fieldSource, FieldInfo.IGNORED, modelFormField);
-        }
-
-        public IgnoredField(ModelFormField modelFormField) {
-            super(FieldInfo.SOURCE_EXPLICIT, FieldInfo.IGNORED, modelFormField);
-        }
-
-        @Override
-        public void accept(ModelFieldVisitor visitor) throws Exception {
-            visitor.visit(this);
-        }
-
-        @Override
-        public FieldInfo copy(ModelFormField modelFormField) {
-            return new IgnoredField(this, modelFormField);
-        }
-
-        @Override
-        public void renderFieldString(Appendable writer, Map<String, Object> context, FormStringRenderer formStringRenderer)
-                throws IOException {
-            formStringRenderer.renderIgnoredField(writer, context, this);
-        }
-    }
-
-    /**
-     * Models the &lt;image&gt; element.
-     * 
-     * @see <code>widget-form.xsd</code>
-     */
-    public static class ImageField extends FieldInfo {
-        private final FlexibleStringExpander alternate;
-        private final FlexibleStringExpander defaultValue;
-        private final FlexibleStringExpander description;
-        private final FlexibleStringExpander style;
-        private final SubHyperlink subHyperlink;
-        private final FlexibleStringExpander value;
-
-        public ImageField(Element element, ModelFormField modelFormField) {
-            super(element, modelFormField);
-            this.alternate = FlexibleStringExpander.getInstance(element.getAttribute("alternate"));
-            this.defaultValue = FlexibleStringExpander.getInstance(element.getAttribute("default-value"));
-            this.description = FlexibleStringExpander.getInstance(element.getAttribute("description"));
-            this.style = FlexibleStringExpander.getInstance(element.getAttribute("style"));
-            Element subHyperlinkElement = UtilXml.firstChildElement(element, "sub-hyperlink");
-            if (subHyperlinkElement != null) {
-                this.subHyperlink = new SubHyperlink(subHyperlinkElement, modelFormField);
-            } else {
-                this.subHyperlink = null;
-            }
-            this.value = FlexibleStringExpander.getInstance(element.getAttribute("value"));
-        }
-
-        public ImageField(ImageField original, ModelFormField modelFormField) {
-            super(original.getFieldSource(), original.getFieldType(), modelFormField);
-            this.alternate = original.alternate;
-            this.defaultValue = original.defaultValue;
-            this.description = original.description;
-            this.style = original.style;
-            if (original.subHyperlink != null) {
-                this.subHyperlink = new SubHyperlink(original.subHyperlink, modelFormField);
-            } else {
-                this.subHyperlink = null;
-            }
-            this.value = original.value;
-        }
-
-        public ImageField(int fieldSource, ModelFormField modelFormField) {
-            super(fieldSource, FieldInfo.IMAGE, modelFormField);
-            this.alternate = FlexibleStringExpander.getInstance("");
-            this.defaultValue = FlexibleStringExpander.getInstance("");
-            this.description = FlexibleStringExpander.getInstance("");
-            this.style = FlexibleStringExpander.getInstance("");
-            this.subHyperlink = null;
-            this.value = FlexibleStringExpander.getInstance("");
-        }
-
-        public ImageField(ModelFormField modelFormField) {
-            this(FieldInfo.SOURCE_EXPLICIT, modelFormField);
-        }
-
-        @Override
-        public void accept(ModelFieldVisitor visitor) throws Exception {
-            visitor.visit(this);
-        }
-
-        @Override
-        public FieldInfo copy(ModelFormField modelFormField) {
-            return new ImageField(this, modelFormField);
-        }
-
-        public FlexibleStringExpander getAlternate() {
-            return alternate;
-        }
-
-        public String getAlternate(Map<String, Object> context) {
-            if (UtilValidate.isNotEmpty(this.alternate))
-                return this.alternate.expandString(context);
-            return "";
-        }
-
-        public FlexibleStringExpander getDefaultValue() {
-            return defaultValue;
-        }
-
-        public String getDefaultValue(Map<String, Object> context) {
-            if (this.defaultValue != null) {
-                return this.defaultValue.expandString(context);
-            } else {
-                return "";
-            }
-        }
-
-        public FlexibleStringExpander getDescription() {
-            return description;
-        }
-
-        public String getDescription(Map<String, Object> context) {
-            if (UtilValidate.isNotEmpty(this.description))
-                return this.description.expandString(context);
-            return "";
-        }
-
-        public FlexibleStringExpander getStyle() {
-            return style;
-        }
-
-        public String getStyle(Map<String, Object> context) {
-            if (UtilValidate.isNotEmpty(this.style))
-                return this.style.expandString(context);
-            return "";
-        }
-
-        public SubHyperlink getSubHyperlink() {
-            return this.subHyperlink;
-        }
-
-        public FlexibleStringExpander getValue() {
-            return value;
-        }
-
-        public String getValue(Map<String, Object> context) {
-            if (UtilValidate.isNotEmpty(this.value))
-                return this.value.expandString(context);
-            return getModelFormField().getEntry(context);
-        }
-
-        @Override
-        public void renderFieldString(Appendable writer, Map<String, Object> context, FormStringRenderer formStringRenderer)
-                throws IOException {
-            formStringRenderer.renderImageField(writer, context, this);
-        }
-    }
-
-    /**
-     * Models the &lt;in-place-editor&gt; element.
-     * 
-     * @see <code>widget-form.xsd</code>
-     */
-    public static class InPlaceEditor {
-        private final String cancelControl;
-        private final String cancelText;
-        private final String clickToEditText;
-        private final String cols;
-        private final Map<FlexibleMapAccessor<Object>, Object> fieldMap;
-        private final String fieldPostCreation;
-        private final String formClassName;
-        private final String highlightColor;
-        private final String highlightEndColor;
-        private final String hoverClassName;
-        private final String htmlResponse;
-        private final String loadingClassName;
-        private final String loadingText;
-        private final String okControl;
-        private final String okText;
-        private final String paramName;
-        private final String rows;
-        private final String savingClassName;
-        private final String savingText;
-        private final String submitOnBlur;
-        private final String textAfterControls;
-        private final String textBeforeControls;
-        private final String textBetweenControls;
-        private final String updateAfterRequestCall;
-        private final FlexibleStringExpander url;
-
-        public InPlaceEditor(Element element) {
-            this.cancelControl = element.getAttribute("cancel-control");
-            this.cancelText = element.getAttribute("cancel-text");
-            this.clickToEditText = element.getAttribute("click-to-edit-text");
-            this.fieldPostCreation = element.getAttribute("field-post-creation");
-            this.formClassName = element.getAttribute("form-class-name");
-            this.highlightColor = element.getAttribute("highlight-color");
-            this.highlightEndColor = element.getAttribute("highlight-end-color");
-            this.hoverClassName = element.getAttribute("hover-class-name");
-            this.htmlResponse = element.getAttribute("html-response");
-            this.loadingClassName = element.getAttribute("loading-class-name");
-            this.loadingText = element.getAttribute("loading-text");
-            this.okControl = element.getAttribute("ok-control");
-            this.okText = element.getAttribute("ok-text");
-            this.paramName = element.getAttribute("param-name");
-            this.savingClassName = element.getAttribute("saving-class-name");
-            this.savingText = element.getAttribute("saving-text");
-            this.submitOnBlur = element.getAttribute("submit-on-blur");
-            this.textBeforeControls = element.getAttribute("text-before-controls");
-            this.textAfterControls = element.getAttribute("text-after-controls");
-            this.textBetweenControls = element.getAttribute("text-between-controls");
-            this.updateAfterRequestCall = element.getAttribute("update-after-request-call");
-            Element simpleElement = UtilXml.firstChildElement(element, "simple-editor");
-            if (simpleElement != null) {
-                this.rows = simpleElement.getAttribute("rows");
-                this.cols = simpleElement.getAttribute("cols");
-            } else {
-                this.rows = "";
-                this.cols = "";
-            }
-            this.fieldMap = EntityFinderUtil.makeFieldMap(element);
-            this.url = FlexibleStringExpander.getInstance(element.getAttribute("url"));
-        }
-
-        public String getCancelControl() {
-            return this.cancelControl;
-        }
-
-        public String getCancelText() {
-            return this.cancelText;
-        }
-
-        public String getClickToEditText() {
-            return this.clickToEditText;
-        }
-
-        public String getCols() {
-            return this.cols;
-        }
-
-        public Map<FlexibleMapAccessor<Object>, Object> getFieldMap() {
-            return fieldMap;
-        }
-
-        public Map<String, Object> getFieldMap(Map<String, Object> context) {
-            Map<String, Object> inPlaceEditorContext = new HashMap<String, Object>();
-            EntityFinderUtil.expandFieldMapToContext(this.fieldMap, context, inPlaceEditorContext);
-            return inPlaceEditorContext;
-        }
-
-        public String getFieldPostCreation() {
-            return this.fieldPostCreation;
-        }
-
-        public String getFormClassName() {
-            return this.formClassName;
-        }
-
-        public String getHighlightColor() {
-            return this.highlightColor;
-        }
-
-        public String getHighlightEndColor() {
-            return this.highlightEndColor;
-        }
-
-        public String getHoverClassName() {
-            return this.hoverClassName;
-        }
-
-        public String getHtmlResponse() {
-            return this.htmlResponse;
-        }
-
-        public String getLoadingClassName() {
-            return this.loadingClassName;
-        }
-
-        public String getLoadingText() {
-            return this.loadingText;
-        }
-
-        public String getOkControl() {
-            return this.okControl;
-        }
-
-        public String getOkText() {
-            return this.okText;
-        }
-
-        public String getParamName() {
-            return this.paramName;
-        }
-
-        public String getRows() {
-            return this.rows;
-        }
-
-        public String getSavingClassName() {
-            return this.savingClassName;
-        }
-
-        public String getSavingText() {
-            return this.savingText;
-        }
-
-        public String getSubmitOnBlur() {
-            return this.submitOnBlur;
-        }
-
-        public String getTextAfterControls() {
-            return this.textAfterControls;
-        }
-
-        public String getTextBeforeControls() {
-            return this.textBeforeControls;
-        }
-
-        public String getTextBetweenControls() {
-            return this.textBetweenControls;
-        }
-
-        public String getUpdateAfterRequestCall() {
-            return this.updateAfterRequestCall;
-        }
-
-        public FlexibleStringExpander getUrl() {
-            return url;
-        }
-
-        public String getUrl(Map<String, Object> context) {
-            if (this.url != null) {
-                return this.url.expandString(context);
-            } else {
-                return "";
-            }
-        }
-    }
-
-    /**
-     * Models the &lt;list-options&gt; element.
-     * 
-     * @see <code>widget-form.xsd</code>
-     */
-    public static class ListOptions extends OptionSource {
-        private final FlexibleStringExpander description;
-        private final FlexibleMapAccessor<Object> keyAcsr;
-        private final FlexibleMapAccessor<List<? extends Object>> listAcsr;
-        private final String listEntryName;
-
-        public ListOptions(Element optionElement, ModelFormField modelFormField) {
-            super(modelFormField);
-            this.listEntryName = optionElement.getAttribute("list-entry-name");
-            this.keyAcsr = FlexibleMapAccessor.getInstance(optionElement.getAttribute("key-name"));
-            this.listAcsr = FlexibleMapAccessor.getInstance(optionElement.getAttribute("list-name"));
-            this.description = FlexibleStringExpander.getInstance(optionElement.getAttribute("description"));
-        }
-
-        private ListOptions(ListOptions original, ModelFormField modelFormField) {
-            super(modelFormField);
-            this.listAcsr = original.listAcsr;
-            this.listEntryName = original.listEntryName;
-            this.keyAcsr = original.keyAcsr;
-            this.description = original.description;
-        }
-
-        public ListOptions(String listName, String listEntryName, String keyName, String description,
-                ModelFormField modelFormField) {
-            super(modelFormField);
-            this.listAcsr = FlexibleMapAccessor.getInstance(listName);
-            this.listEntryName = listEntryName;
-            this.keyAcsr = FlexibleMapAccessor.getInstance(keyName);
-            this.description = FlexibleStringExpander.getInstance(description);
-        }
-
-        @Override
-        public void addOptionValues(List<OptionValue> optionValues, Map<String, Object> context, Delegator delegator) {
-            List<? extends Object> dataList = UtilGenerics.checkList(this.listAcsr.get(context));
-            if (dataList != null && dataList.size() != 0) {
-                for (Object data : dataList) {
-                    Map<String, Object> localContext = new HashMap<String, Object>();
-                    localContext.putAll(context);
-                    if (UtilValidate.isNotEmpty(this.listEntryName)) {
-                        localContext.put(this.listEntryName, data);
-                    } else {
-                        Map<String, Object> dataMap = UtilGenerics.checkMap(data);
-                        localContext.putAll(dataMap);
-                    }
-                    Object keyObj = keyAcsr.get(localContext);
-                    String key = null;
-                    if (keyObj instanceof String) {
-                        key = (String) keyObj;
-                    } else {
-                        try {
-                            key = (String) ObjectType.simpleTypeConvert(keyObj, "String", null, null);
-                        } catch (GeneralException e) {
-                            String errMsg = "Could not convert field value for the field: [" + this.keyAcsr.toString()
-                                    + "] to String for the value [" + keyObj + "]: " + e.toString();
-                            Debug.logError(e, errMsg, module);
-                        }
-                    }
-                    optionValues.add(new OptionValue(key, description.expandString(localContext)));
-                }
-            }
-        }
-
-        @Override
-        public OptionSource copy(ModelFormField modelFormField) {
-            return new ListOptions(this, modelFormField);
-        }
-
-        public FlexibleStringExpander getDescription() {
-            return description;
-        }
-
-        public FlexibleMapAccessor<Object> getKeyAcsr() {
-            return keyAcsr;
-        }
-
-        public FlexibleMapAccessor<List<? extends Object>> getListAcsr() {
-            return listAcsr;
-        }
-
-        public String getListEntryName() {
-            return listEntryName;
-        }
-    }
-
-    /**
-     * Models the &lt;lookup&gt; element.
-     * 
-     * @see <code>widget-form.xsd</code>
-     */
-    public static class LookupField extends TextField {
-        private final String descriptionFieldName;
-        private final String fadeBackground;
-        private final FlexibleStringExpander formName;
-        private final String initiallyCollapsed;
-        private final String lookupHeight;
-        private final String lookupPosition;
-        private final String lookupPresentation;
-        private final String lookupWidth;
-        private final String showDescription;
-        private final String targetParameter;
-
-        public LookupField(Element element, ModelFormField modelFormField) {
-            super(element, modelFormField);
-            this.descriptionFieldName = element.getAttribute("description-field-name");
-            this.fadeBackground = element.getAttribute("fade-background");
-            this.formName = FlexibleStringExpander.getInstance(element.getAttribute("target-form-name"));
-            this.initiallyCollapsed = element.getAttribute("initially-collapsed");
-            this.lookupHeight = element.getAttribute("height");
-            this.lookupPosition = element.getAttribute("position");
-            this.lookupPresentation = element.getAttribute("presentation");
-            this.lookupWidth = element.getAttribute("width");
-            this.showDescription = element.getAttribute("show-description");
-            this.targetParameter = element.getAttribute("target-parameter");
-        }
-
-        public LookupField(int fieldSource, ModelFormField modelFormField) {
-            super(fieldSource, modelFormField);
-            this.descriptionFieldName = "";
-            this.fadeBackground = "";
-            this.formName = FlexibleStringExpander.getInstance("");
-            this.initiallyCollapsed = "";
-            this.lookupHeight = "";
-            this.lookupPosition = "";
-            this.lookupPresentation = "";
-            this.lookupWidth = "";
-            this.showDescription = "";
-            this.targetParameter = "";
-        }
-
-        public LookupField(LookupField original, ModelFormField modelFormField) {
-            super(original, modelFormField);
-            this.descriptionFieldName = original.descriptionFieldName;
-            this.fadeBackground = original.fadeBackground;
-            this.formName = original.formName;
-            this.initiallyCollapsed = original.initiallyCollapsed;
-            this.lookupHeight = original.lookupHeight;
-            this.lookupPosition = original.lookupPosition;
-            this.lookupPresentation = original.lookupPresentation;
-            this.lookupWidth = original.lookupWidth;
-            this.showDescription = original.showDescription;
-            this.targetParameter = original.targetParameter;
-        }
-
-        @Override
-        public void accept(ModelFieldVisitor visitor) throws Exception {
-            visitor.visit(this);
-        }
-
-        @Override
-        public FieldInfo copy(ModelFormField modelFormField) {
-            return new LookupField(this, modelFormField);
-        }
-
-        public String getDescriptionFieldName() {
-            return this.descriptionFieldName;
-        }
-
-        public String getFadeBackground() {
-            return this.fadeBackground;
-        }
-
-        public FlexibleStringExpander getFormName() {
-            return formName;
-        }
-
-        public String getFormName(Map<String, Object> context) {
-            return this.formName.expandString(context);
-        }
-
-        //initially-collapsed status
-        public boolean getInitiallyCollapsed() {
-            return "true".equals(this.initiallyCollapsed);
-        }
-
-        public String getLookupHeight() {
-            return this.lookupHeight;
-        }
-
-        public String getLookupPosition() {
-            return this.lookupPosition;
-        }
-
-        public String getLookupPresentation() {
-            return this.lookupPresentation;
-        }
-
-        public String getLookupWidth() {
-            return this.lookupWidth;
-        }
-
-        public Boolean getShowDescription() {
-            return UtilValidate.isEmpty(this.showDescription) ? null : "true".equals(this.showDescription);
-        }
-
-        public String getTargetParameter() {
-            return targetParameter;
-        }
-
-        public List<String> getTargetParameterList() {
-            List<String> paramList = new LinkedList<String>();
-            if (UtilValidate.isNotEmpty(this.targetParameter)) {
-                StringTokenizer stk = new StringTokenizer(this.targetParameter, ", ");
-                while (stk.hasMoreTokens()) {
-                    paramList.add(stk.nextToken());
-                }
-            }
-            return paramList;
-        }
-
-        @Override
-        public void renderFieldString(Appendable writer, Map<String, Object> context, FormStringRenderer formStringRenderer)
-                throws IOException {
-            formStringRenderer.renderLookupField(writer, context, this);
-        }
-    }
-
-    public static abstract class OptionSource {
-
-        private final ModelFormField modelFormField;
-
-        protected OptionSource(ModelFormField modelFormField) {
-            this.modelFormField = modelFormField;
-        }
-
-        public abstract void addOptionValues(List<OptionValue> optionValues, Map<String, Object> context, Delegator delegator);
-
-        public abstract OptionSource copy(ModelFormField modelFormField);
-
-        public ModelFormField getModelFormField() {
-            return modelFormField;
-        }
-    }
-
-    public static class OptionValue {
-        private final String description;
-        private final String key;
-
-        public OptionValue(String key, String description) {
-            this.key = key;
-            this.description = description;
-        }
-
-        public String getDescription() {
-            return description;
-        }
-
-        public String getKey() {
-            return key;
-        }
-    }
-
-    /**
-     * Models the &lt;password&gt; element.
-     * 
-     * @see <code>widget-form.xsd</code>
-     */
-    public static class PasswordField extends TextField {
-
-        public PasswordField(Element element, ModelFormField modelFormField) {
-            super(element, modelFormField);
-        }
-
-        public PasswordField(int fieldSource, ModelFormField modelFormField) {
-            super(fieldSource, modelFormField);
-        }
-
-        private PasswordField(PasswordField original, ModelFormField modelFormField) {
-            super(original, modelFormField);
-        }
-
-        @Override
-        public void accept(ModelFieldVisitor visitor) throws Exception {
-            visitor.visit(this);
-        }
-
-        @Override
-        public FieldInfo copy(ModelFormField modelFormField) {
-            return new PasswordField(this, modelFormField);
-        }
-
-        @Override
-        public void renderFieldString(Appendable writer, Map<String, Object> context, FormStringRenderer formStringRenderer)
-                throws IOException {
-            formStringRenderer.renderPasswordField(writer, context, this);
-        }
-    }
-
-    /**
-     * Models the &lt;radio&gt; element.
-     * 
-     * @see <code>widget-form.xsd</code>
-     */
-    public static class RadioField extends FieldInfoWithOptions {
-
-        public RadioField(Element element, ModelFormField modelFormField) {
-            super(element, modelFormField);
-        }
-
-        public RadioField(int fieldSource, ModelFormField modelFormField) {
-            super(fieldSource, FieldInfo.RADIO, modelFormField);
-        }
-
-        public RadioField(ModelFormField modelFormField) {
-            super(FieldInfo.SOURCE_EXPLICIT, FieldInfo.RADIO, modelFormField);
-        }
-
-        private RadioField(RadioField original, ModelFormField modelFormField) {
-            super(original, modelFormField);
-        }
-
-        @Override
-        public void accept(ModelFieldVisitor visitor) throws Exception {
-            visitor.visit(this);
-        }
-
-        @Override
-        public FieldInfo copy(ModelFormField modelFormField) {
-            return new RadioField(this, modelFormField);
-        }
-
-        @Override
-        public void renderFieldString(Appendable writer, Map<String, Object> context, FormStringRenderer formStringRenderer)
-                throws IOException {
-            formStringRenderer.renderRadioField(writer, context, this);
-        }
-    }
-
-    /**
-     * Models the &lt;range-find&gt; element.
-     * 
-     * @see <code>widget-form.xsd</code>
-     */
-    public static class RangeFindField extends TextField {
-        private final String defaultOptionFrom;
-        private final String defaultOptionThru;
-
-        public RangeFindField(Element element, ModelFormField modelFormField) {
-            super(element, modelFormField);
-            this.defaultOptionFrom = element.getAttribute("default-option-from");
-            this.defaultOptionThru = element.getAttribute("default-option-thru");
-        }
-
-        public RangeFindField(int fieldSource, int size, ModelFormField modelFormField) {
-            super(fieldSource, size, null, modelFormField);
-            this.defaultOptionFrom = "greaterThanEqualTo";
-            this.defaultOptionThru = "lessThanEqualTo";
-        }
-
-        private RangeFindField(RangeFindField original, ModelFormField modelFormField) {
-            super(original, modelFormField);
-            this.defaultOptionFrom = original.defaultOptionFrom;
-            this.defaultOptionThru = original.defaultOptionThru;
-        }
-
-        @Override
-        public void accept(ModelFieldVisitor visitor) throws Exception {
-            visitor.visit(this);
-        }
-
-        @Override
-        public FieldInfo copy(ModelFormField modelFormField) {
-            return new RangeFindField(this, modelFormField);
-        }
-
-        public String getDefaultOptionFrom() {
-            return this.defaultOptionFrom;
-        }
-
-        public String getDefaultOptionThru() {
-            return this.defaultOptionThru;
-        }
-
-        @Override
-        public void renderFieldString(Appendable writer, Map<String, Object> context, FormStringRenderer formStringRenderer)
-                throws IOException {
-            formStringRenderer.renderRangeFindField(writer, context, this);
-        }
-    }
-
-    /**
-     * Models the &lt;reset&gt; element.
-     * 
-     * @see <code>widget-form.xsd</code>
-     */
-    public static class ResetField extends FieldInfo {
-
-        public ResetField(Element element, ModelFormField modelFormField) {
-            super(element, modelFormField);
-        }
-
-        public ResetField(int fieldSource, ModelFormField modelFormField) {
-            super(fieldSource, FieldInfo.RESET, modelFormField);
-        }
-
-        public ResetField(ModelFormField modelFormField) {
-            super(FieldInfo.SOURCE_EXPLICIT, FieldInfo.RESET, modelFormField);
-        }
-
-        private ResetField(ResetField original, ModelFormField modelFormField) {
-            super(original.getFieldSource(), original.getFieldType(), modelFormField);
-        }
-
-        @Override
-        public void accept(ModelFieldVisitor visitor) throws Exception {
-            visitor.visit(this);
-        }
-
-        @Override
-        public FieldInfo copy(ModelFormField modelFormField) {
-            return new ResetField(this, modelFormField);
-        }
-
-        @Override
-        public void renderFieldString(Appendable writer, Map<String, Object> context, FormStringRenderer formStringRenderer)
-                throws IOException {
-            formStringRenderer.renderResetField(writer, context, this);
-        }
-    }
-
-    /**
-     * Models the &lt;option&gt; element.
-     * 
-     * @see <code>widget-form.xsd</code>
-     */
-    public static class SingleOption extends OptionSource {
-        private final FlexibleStringExpander description;
-        private final FlexibleStringExpander key;
-
-        public SingleOption(Element optionElement, ModelFormField modelFormField) {
-            super(modelFormField);
-            this.key = FlexibleStringExpander.getInstance(optionElement.getAttribute("key"));
-            this.description = FlexibleStringExpander.getInstance(UtilXml.checkEmpty(optionElement.getAttribute("description"),
-                    optionElement.getAttribute("key")));
-        }
-
-        private SingleOption(SingleOption original, ModelFormField modelFormField) {
-            super(modelFormField);
-            this.key = original.key;
-            this.description = original.description;
-        }
-
-        public SingleOption(String key, String description, ModelFormField modelFormField) {
-            super(modelFormField);
-            this.key = FlexibleStringExpander.getInstance(key);
-            this.description = FlexibleStringExpander.getInstance(UtilXml.checkEmpty(description, key));
-        }
-
-        @Override
-        public void addOptionValues(List<OptionValue> optionValues, Map<String, Object> context, Delegator delegator) {
-            optionValues.add(new OptionValue(key.expandString(context), description.expandString(context)));
-        }
-
-        @Override
-        public OptionSource copy(ModelFormField modelFormField) {
-            return new SingleOption(this, modelFormField);
-        }
-
-        public FlexibleStringExpander getDescription() {
-            return description;
-        }
-
-        public FlexibleStringExpander getKey() {
-            return key;
-        }
-    }
-
-    /**
-     * Models the &lt;sub-hyperlink&gt; element.
-     * 
-     * @see <code>widget-form.xsd</code>
-     */
-    public static class SubHyperlink {
-        private final FlexibleStringExpander description;
-        private final FlexibleStringExpander useWhen;
-        private final Link link;
-        private final ModelFormField modelFormField;
-
-        public SubHyperlink(Element element, ModelFormField modelFormField) {
-            this.description = FlexibleStringExpander.getInstance(element.getAttribute("description"));
-            this.useWhen = FlexibleStringExpander.getInstance(element.getAttribute("use-when"));
-            this.link = new Link(element);
-            this.modelFormField = modelFormField;
-        }
-
-        public SubHyperlink(SubHyperlink original, ModelFormField modelFormField) {
-            this.description = original.description;
-            this.useWhen = original.useWhen;
-            this.link = original.link;
-            this.modelFormField = modelFormField;
-        }
-
-        public AutoEntityParameters getAutoEntityParameters() {
-            return link.getAutoEntityParameters();
-        }
-
-        public AutoServiceParameters getAutoServiceParameters() {
-            return link.getAutoServiceParameters();
-        }
-
-        public boolean getEncode() {
-            return link.getEncode();
-        }
-
-        public boolean getFullPath() {
-            return link.getFullPath();
-        }
-
-        public String getHeight() {
-            return link.getHeight();
-        }
-
-        public String getId(Map<String, Object> context) {
-            return link.getId(context);
-        }
-
-        public FlexibleStringExpander getIdExdr() {
-            return link.getIdExdr();
-        }
-
-        public Image getImage() {
-            return link.getImage();
-        }
-
-        public String getLinkType() {
-            return link.getLinkType();
-        }
-
-        public String getName() {
-            return link.getName();
-        }
-
-        public String getName(Map<String, Object> context) {
-            return link.getName(context);
-        }
-
-        public FlexibleStringExpander getNameExdr() {
-            return link.getNameExdr();
-        }
-
-        public List<Parameter> getParameterList() {
-            return link.getParameterList();
-        }
-
-        public Map<String, String> getParameterMap(Map<String, Object> context) {
-            return link.getParameterMap(context);
-        }
-
-        public String getPrefix(Map<String, Object> context) {
-            return link.getPrefix(context);
-        }
-
-        public FlexibleStringExpander getPrefixExdr() {
-            return link.getPrefixExdr();
-        }
-
-        public boolean getSecure() {
-            return link.getSecure();
-        }
-
-        public Integer getSize() {
-            return link.getSize();
-        }
-
-        public String getStyle(Map<String, Object> context) {
-            return link.getStyle(context);
-        }
-
-        public FlexibleStringExpander getStyleExdr() {
-            return link.getStyleExdr();
-        }
-
-        public String getTarget(Map<String, Object> context) {
-            return link.getTarget(context);
-        }
-
-        public FlexibleStringExpander getTargetExdr() {
-            return link.getTargetExdr();
-        }
-
-        public String getTargetWindow(Map<String, Object> context) {
-            return link.getTargetWindow(context);
-        }
-
-        public FlexibleStringExpander getTargetWindowExdr() {
-            return link.getTargetWindowExdr();
-        }
-
-        public String getText(Map<String, Object> context) {
-            return link.getText(context);
-        }
-
-        public FlexibleStringExpander getTextExdr() {
-            return link.getTextExdr();
-        }
-
-        public String getUrlMode() {
-            return link.getUrlMode();
-        }
-
-        public String getWidth() {
-            return link.getWidth();
-        }
-
-        public FlexibleStringExpander getDescription() {
-            return description;
-        }
-
-        public String getDescription(Map<String, Object> context) {
-            return description.expandString(context);
-        }
-
-        public FlexibleStringExpander getUseWhen() {
-            return useWhen;
-        }
-
-        public Link getLink() {
-            return link;
-        }
-
-        public String getUseWhen(Map<String, Object> context) {
-            return this.useWhen.expandString(context);
-        }
-
-        public ModelFormField getModelFormField() {
-            return modelFormField;
-        }
-
-        public boolean shouldUse(Map<String, Object> context) {
-            boolean shouldUse = true;
-            String useWhen = this.getUseWhen(context);
-            if (UtilValidate.isNotEmpty(useWhen)) {
-                try {
-                    Interpreter bsh = (Interpreter) context.get("bshInterpreter");
-                    if (bsh == null) {
-                        bsh = BshUtil.makeInterpreter(context);
-                        context.put("bshInterpreter", bsh);
-                    }
-
-                    Object retVal = bsh.eval(StringUtil.convertOperatorSubstitutions(useWhen));
-
-                    // retVal should be a Boolean, if not something weird is up...
-                    if (retVal instanceof Boolean) {
-                        Boolean boolVal = (Boolean) retVal;
-                        shouldUse = boolVal.booleanValue();
-                    } else {
-                        throw new IllegalArgumentException("Return value from target condition eval was not a Boolean: "
-                                + retVal.getClass().getName() + " [" + retVal + "]");
-                    }
-                } catch (EvalError e) {
-                    String errmsg = "Error evaluating BeanShell target conditions";
-                    Debug.logError(e, errmsg, module);
-                    throw new IllegalArgumentException(errmsg);
-                }
-            }
-            return shouldUse;
-        }
-    }
-
-    /**
-     * Models the &lt;submit&gt; element.
-     * 
-     * @see <code>widget-form.xsd</code>
-     */
-    public static class SubmitField extends FieldInfo {
-        private final FlexibleStringExpander backgroundSubmitRefreshTargetExdr;
-        private final String buttonType;
-        private final FlexibleStringExpander confirmationMsgExdr;
-        private final FlexibleStringExpander imageLocation;
-        private final boolean requestConfirmation;
-
-        public SubmitField(Element element, ModelFormField modelFormField) {
-            super(element, modelFormField);
-            this.backgroundSubmitRefreshTargetExdr = FlexibleStringExpander.getInstance(element
-                    .getAttribute("background-submit-refresh-target"));
-            this.buttonType = element.getAttribute("button-type");
-            this.confirmationMsgExdr = FlexibleStringExpander.getInstance(element.getAttribute("confirmation-message"));
-            this.imageLocation = FlexibleStringExpander.getInstance(element.getAttribute("image-location"));
-            this.requestConfirmation = "true".equals(element.getAttribute("request-confirmation"));
-        }
-
-        public SubmitField(int fieldInfo, ModelFormField modelFormField) {
-            super(fieldInfo, FieldInfo.SUBMIT, modelFormField);
-            this.backgroundSubmitRefreshTargetExdr = FlexibleStringExpander.getInstance("");
-            this.buttonType = "";
-            this.confirmationMsgExdr = FlexibleStringExpander.getInstance("");
-            this.imageLocation = FlexibleStringExpander.getInstance("");
-            this.requestConfirmation = false;
-        }
-
-        public SubmitField(ModelFormField modelFormField) {
-            this(FieldInfo.SOURCE_EXPLICIT, modelFormField);
-        }
-
-        private SubmitField(SubmitField original, ModelFormField modelFormField) {
-            super(original.getFieldSource(), original.getFieldType(), modelFormField);
-            this.buttonType = original.buttonType;
-            this.imageLocation = original.imageLocation;
-            this.backgroundSubmitRefreshTargetExdr = original.backgroundSubmitRefreshTargetExdr;
-            this.requestConfirmation = original.requestConfirmation;
-            this.confirmationMsgExdr = original.confirmationMsgExdr;
-        }
-
-        @Override
-        public void accept(ModelFieldVisitor visitor) throws Exception {
-            visitor.visit(this);
-        }
-
-        @Override
-        public FieldInfo copy(ModelFormField modelFormField) {
-            return new SubmitField(this, modelFormField);
-        }
-
-        public String getBackgroundSubmitRefreshTarget(Map<String, Object> context) {
-            return this.backgroundSubmitRefreshTargetExdr.expandString(context);
-        }
-
-        public FlexibleStringExpander getBackgroundSubmitRefreshTargetExdr() {
-            return backgroundSubmitRefreshTargetExdr;
-        }
-
-        public String getButtonType() {
-            return buttonType;
-        }
-
-        public String getConfirmation(Map<String, Object> context) {
-            String message = getConfirmationMsg(context);
-            if (UtilValidate.isNotEmpty(message))
-                return message;
-            else if (getRequestConfirmation()) {
-                String defaultMessage = UtilProperties.getPropertyValue("general", "default.confirmation.message",
-                        "${uiLabelMap.CommonConfirm}");
-                return FlexibleStringExpander.expandString(defaultMessage, context);
-            }
-            return "";
-        }
-
-        public String getConfirmationMsg(Map<String, Object> context) {
-            return this.confirmationMsgExdr.expandString(context);
-        }
-
-        public FlexibleStringExpander getConfirmationMsgExdr() {
-            return confirmationMsgExdr;
-        }
-
-        public FlexibleStringExpander getImageLocation() {
-            return imageLocation;
-        }
-
-        public String getImageLocation(Map<String, Object> context) {
-            return this.imageLocation.expandString(context);
-        }
-
-        public boolean getRequestConfirmation() {
-            return this.requestConfirmation;
-        }
-
-        @Override
-        public void renderFieldString(Appendable writer, Map<String, Object> context, FormStringRenderer formStringRenderer)
-                throws IOException {
-            formStringRenderer.renderSubmitField(writer, context, this);
-        }
-    }
-
-    /**
-     * Models the &lt;textarea&gt; element.
-     * 
-     * @see <code>widget-form.xsd</code>
-     */
-    public static class TextareaField extends FieldInfo {
-        private final int cols;
-        private final FlexibleStringExpander defaultValue;
-        private final boolean readOnly;
-        private final int rows;
-        private final FlexibleStringExpander visualEditorButtons;
-        private final boolean visualEditorEnable;
-
-        public TextareaField(Element element, ModelFormField modelFormField) {
-            super(element, modelFormField);
-            int cols = 60;
-            String colsStr = element.getAttribute("cols");
-            if (!colsStr.isEmpty()) {
-                try {
-                    cols = Integer.parseInt(colsStr);
-                } catch (Exception e) {
-                    if (UtilValidate.isNotEmpty(colsStr)) {
-                        Debug.logError("Could not parse the size value of the text element: [" + colsStr
-                                + "], setting to default of " + cols, module);
-                    }
-                }
-            }
-            this.cols = cols;
-            this.defaultValue = FlexibleStringExpander.getInstance(element.getAttribute("default-value"));
-            this.readOnly = "true".equals(element.getAttribute("read-only"));
-            int rows = 2;
-            String rowsStr = element.getAttribute("rows");
-            if (!rowsStr.isEmpty()) {
-                try {
-                    rows = Integer.parseInt(rowsStr);
-                } catch (Exception e) {
-                    if (UtilValidate.isNotEmpty(rowsStr)) {
-                        Debug.logError("Could not parse the size value of the text element: [" + rowsStr
-                                + "], setting to default of " + rows, module);
-                    }
-                }
-            }
-            this.rows = rows;
-            this.visualEditorButtons = FlexibleStringExpander.getInstance(element.getAttribute("visual-editor-buttons"));
-            this.visualEditorEnable = "true".equals(element.getAttribute("visual-editor-enable"));
-        }
-
-        public TextareaField(int fieldSource, ModelFormField modelFormField) {
-            super(fieldSource, FieldInfo.TEXTAREA, modelFormField);
-            this.cols = 60;
-            this.defaultValue = FlexibleStringExpander.getInstance("");
-            this.readOnly = false;
-            this.rows = 2;
-            this.visualEditorButtons = FlexibleStringExpander.getInstance("");
-            this.visualEditorEnable = false;
-        }
-
-        public TextareaField(ModelFormField modelFormField) {
-            this(FieldInfo.SOURCE_EXPLICIT, modelFormField);
-        }
-
-        private TextareaField(TextareaField original, ModelFormField modelFormField) {
-            super(original.getFieldSource(), original.getFieldType(), modelFormField);
-            this.defaultValue = original.defaultValue;
-            this.visualEditorEnable = original.visualEditorEnable;
-            this.visualEditorButtons = original.visualEditorButtons;
-            this.readOnly = original.readOnly;
-            this.cols = original.cols;
-            this.rows = original.rows;
-        }
-
-        @Override
-        public void accept(ModelFieldVisitor visitor) throws Exception {
-            visitor.visit(this);
-        }
-
-        @Override
-        public FieldInfo copy(ModelFormField modelFormField) {
-            return new TextareaField(this, modelFormField);
-        }
-
-        public int getCols() {
-            return cols;
-        }
-
-        public FlexibleStringExpander getDefaultValue() {
-            return defaultValue;
-        }
-
-        public String getDefaultValue(Map<String, Object> context) {
-            if (this.defaultValue != null) {
-                return this.defaultValue.expandString(context);
-            } else {
-                return "";
-            }
-        }
-
-        public int getRows() {
-            return rows;
-        }
-
-        public FlexibleStringExpander getVisualEditorButtons() {
-            return visualEditorButtons;
-        }
-
-        public String getVisualEditorButtons(Map<String, Object> context) {
-            return this.visualEditorButtons.expandString(context);
-        }
-
-        public boolean getVisualEditorEnable() {
-            return this.visualEditorEnable;
-        }
-
-        public boolean isReadOnly() {
-            return readOnly;
-        }
-
-        @Override
-        public void renderFieldString(Appendable writer, Map<String, Object> context, FormStringRenderer formStringRenderer)
-                throws IOException {
-            formStringRenderer.renderTextareaField(writer, context, this);
-        }
-    }
-
-    /**
-     * Models the &lt;text&gt; element.
-     * 
-     * @see <code>widget-form.xsd</code>
-     */
-    public static class TextField extends FieldInfo {
-        private final boolean clientAutocompleteField;
-        private final FlexibleStringExpander defaultValue;
-        private final boolean disabled;
-        private final String mask;
-        private final Integer maxlength;
-        private final FlexibleStringExpander placeholder;
-        private final boolean readonly;
-        private final int size;
-        private final SubHyperlink subHyperlink;
-
-        public TextField(Element element, ModelFormField modelFormField) {
-            super(element, modelFormField);
-            this.clientAutocompleteField = !"false".equals(element.getAttribute("client-autocomplete-field"));
-            this.defaultValue = FlexibleStringExpander.getInstance(element.getAttribute("default-value"));
-            this.disabled = "true".equals(element.getAttribute("disabled"));
-            this.mask = element.getAttribute("mask");
-            Integer maxlength = null;
-            String maxlengthStr = element.getAttribute("maxlength");
-            if (!maxlengthStr.isEmpty()) {
-                try {
-                    maxlength = Integer.valueOf(maxlengthStr);
-                } catch (Exception e) {
-                    Debug.logError("Could not parse the max-length value of the text element: [" + maxlengthStr
-                            + "], setting to null; default of no maxlength will be used", module);
-                }
-            }
-            this.maxlength = maxlength;
-            this.placeholder = FlexibleStringExpander.getInstance(element.getAttribute("placeholder"));
-            this.readonly = "true".equals(element.getAttribute("read-only"));
-            int size = 25;
-            String sizeStr = element.getAttribute("size");
-            if (!sizeStr.isEmpty()) {
-                try {
-                    size = Integer.parseInt(sizeStr);
-                } catch (Exception e) {
-                    Debug.logError("Could not parse the size value of the text element: [" + sizeStr
-                            + "], setting to the default of " + size, module);
-                }
-            }
-            this.size = size;
-            Element subHyperlinkElement = UtilXml.firstChildElement(element, "sub-hyperlink");
-            if (subHyperlinkElement != null) {
-                this.subHyperlink = new SubHyperlink(subHyperlinkElement, this.getModelFormField());
-            } else {
-                this.subHyperlink = null;
-            }
-        }
-
-        protected TextField(int fieldSource, int size, Integer maxlength, ModelFormField modelFormField) {
-            super(fieldSource, FieldInfo.TEXT, modelFormField);
-            this.clientAutocompleteField = true;
-            this.defaultValue = FlexibleStringExpander.getInstance("");
-            this.disabled = false;
-            this.mask = "";
-            this.maxlength = maxlength;
-            this.placeholder = FlexibleStringExpander.getInstance("");
-            this.readonly = false;
-            this.size = size;
-            this.subHyperlink = null;
-        }
-
-        private TextField(int fieldSource, int fieldType, ModelFormField modelFormField) {
-            super(fieldSource, fieldType, modelFormField);
-            this.clientAutocompleteField = true;
-            this.defaultValue = FlexibleStringExpander.getInstance("");
-            this.disabled = false;
-            this.mask = "";
-            this.maxlength = null;
-            this.placeholder = FlexibleStringExpander.getInstance("");
-            this.readonly = false;
-            this.size = 25;
-            this.subHyperlink = null;
-        }
-
-        public TextField(int fieldSource, ModelFormField modelFormField) {
-            this(fieldSource, FieldInfo.TEXT, modelFormField);
-        }
-
-        public TextField(ModelFormField modelFormField) {
-            this(FieldInfo.SOURCE_EXPLICIT, FieldInfo.TEXT, modelFormField);
-        }
-
-        protected TextField(TextField original, ModelFormField modelFormField) {
-            super(original.getFieldSource(), original.getFieldType(), modelFormField);
-            this.clientAutocompleteField = original.clientAutocompleteField;
-            this.defaultValue = original.defaultValue;
-            this.mask = original.mask;
-            this.placeholder = original.placeholder;
-            this.size = original.size;
-            this.maxlength = original.maxlength;
-            this.disabled = original.disabled;
-            this.readonly = original.readonly;
-            if (original.subHyperlink != null) {
-                this.subHyperlink = new SubHyperlink(original.subHyperlink, modelFormField);
-            } else {
-                this.subHyperlink = null;
-            }
-        }
-
-        @Override
-        public void accept(ModelFieldVisitor visitor) throws Exception {
-            visitor.visit(this);
-        }
-
-        @Override
-        public FieldInfo copy(ModelFormField modelFormField) {
-            return new TextField(this, modelFormField);
-        }
-
-        public boolean getClientAutocompleteField() {
-            return this.clientAutocompleteField;
-        }
-
-        public FlexibleStringExpander getDefaultValue() {
-            return defaultValue;
-        }
-
-        public String getDefaultValue(Map<String, Object> context) {
-            if (this.defaultValue != null) {
-                return this.defaultValue.expandString(context);
-            } else {
-                return "";
-            }
-        }
-
-        public boolean getDisabled() {
-            return this.disabled;
-        }
-
-        public String getMask() {
-            return this.mask;
-        }
-
-        public Integer getMaxlength() {
-            return maxlength;
-        }
-
-        public FlexibleStringExpander getPlaceholder() {
-            return placeholder;
-        }
-
-        public String getPlaceholder(Map<String, Object> context) {
-            return this.placeholder.expandString(context);
-        }
-
-        public boolean getReadonly() {
-            return this.readonly;
-        }
-
-        public int getSize() {
-            return size;
-        }
-
-        public SubHyperlink getSubHyperlink() {
-            return this.subHyperlink;
-        }
-
-        @Override
-        public void renderFieldString(Appendable writer, Map<String, Object> context, FormStringRenderer formStringRenderer)
-                throws IOException {
-            formStringRenderer.renderTextField(writer, context, this);
-        }
-    }
-
-    /**
-     * Models the &lt;text-find&gt; element.
-     * 
-     * @see <code>widget-form.xsd</code>
-     */
-    public static class TextFindField extends TextField {
-        private final String defaultOption;
-        private final boolean hideIgnoreCase;
-        private final boolean hideOptions;
-        private final boolean ignoreCase;
-
-        public TextFindField(Element element, ModelFormField modelFormField) {
-            super(element, modelFormField);
-            if (element.hasAttribute("default-option")) {
-                this.defaultOption = element.getAttribute("default-option");
-            } else {
-                this.defaultOption = UtilProperties.getPropertyValue("widget", "widget.form.defaultTextFindOption", "contains");
-            }
-            this.hideIgnoreCase = "true".equals(element.getAttribute("hide-options"))
-                    || "ignore-case".equals(element.getAttribute("hide-options")) ? true : false;
-            this.hideOptions = "true".equals(element.getAttribute("hide-options"))
-                    || "options".equals(element.getAttribute("hide-options")) ? true : false;
-            this.ignoreCase = "true".equals(element.getAttribute("ignore-case"));
-        }
-
-        public TextFindField(int fieldSource, int size, Integer maxlength, ModelFormField modelFormField) {
-            super(fieldSource, size, maxlength, modelFormField);
-            this.defaultOption = UtilProperties.getPropertyValue("widget", "widget.form.defaultTextFindOption", "contains");
-            this.hideIgnoreCase = false;
-            this.hideOptions = false;
-            this.ignoreCase = true;
-        }
-
-        public TextFindField(int fieldSource, ModelFormField modelFormField) {
-            super(fieldSource, modelFormField);
-            this.defaultOption = UtilProperties.getPropertyValue("widget", "widget.form.defaultTextFindOption", "contains");
-            this.hideIgnoreCase = false;
-            this.hideOptions = false;
-            this.ignoreCase = true;
-        }
-
-        private TextFindField(TextFindField original, ModelFormField modelFormField) {
-            super(original, modelFormField);
-            this.ignoreCase = original.ignoreCase;
-            this.hideIgnoreCase = original.hideIgnoreCase;
-            this.defaultOption = original.defaultOption;
-            this.hideOptions = original.hideOptions;
-        }
-
-        @Override
-        public void accept(ModelFieldVisitor visitor) throws Exception {
-            visitor.visit(this);
-        }
-
-        @Override
-        public FieldInfo copy(ModelFormField modelFormField) {
-            return new TextFindField(this, modelFormField);
-        }
-
-        public String getDefaultOption() {
-            return this.defaultOption;
-        }
-
-        public boolean getHideIgnoreCase() {
-            return this.hideIgnoreCase;
-        }
-
-        public boolean getHideOptions() {
-            return this.hideOptions;
-        }
-
-        public boolean getIgnoreCase() {
-            return this.ignoreCase;
-        }
-
-        @Override
-        public void renderFieldString(Appendable writer, Map<String, Object> context, FormStringRenderer formStringRenderer)
-                throws IOException {
-            formStringRenderer.renderTextFindField(writer, context, this);
-        }
-    }
-}
+/*******************************************************************************

+ * Licensed to the Apache Software Foundation (ASF) under one

+ * or more contributor license agreements.  See the NOTICE file

+ * distributed with this work for additional information

+ * regarding copyright ownership.  The ASF licenses this file

+ * to you under the Apache License, Version 2.0 (the

+ * "License"); you may not use this file except in compliance

+ * with the License.  You may obtain a copy of the License at

+ *

+ * http://www.apache.org/licenses/LICENSE-2.0

+ *

+ * Unless required by applicable law or agreed to in writing,

+ * software distributed under the License is distributed on an

+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY

+ * KIND, either express or implied.  See the License for the

+ * specific language governing permissions and limitations

+ * under the License.

+ *******************************************************************************/

+package org.ofbiz.widget.model;

+

+import java.io.IOException;

+import java.math.BigDecimal;

+import java.sql.Timestamp;

+import java.text.DateFormat;

+import java.text.NumberFormat;

+import java.util.ArrayList;

+import java.util.Collections;

+import java.util.Date;

+import java.util.HashMap;

+import java.util.LinkedList;

+import java.util.List;

+import java.util.Locale;

+import java.util.Map;

+import java.util.StringTokenizer;

+import java.util.TimeZone;

+

+import org.ofbiz.base.conversion.ConversionException;

+import org.ofbiz.base.conversion.DateTimeConverters;

+import org.ofbiz.base.conversion.DateTimeConverters.StringToTimestamp;

+import org.ofbiz.base.util.BshUtil;

+import org.ofbiz.base.util.Debug;

+import org.ofbiz.base.util.GeneralException;

+import org.ofbiz.base.util.ObjectType;

+import org.ofbiz.base.util.StringUtil;

+import org.ofbiz.base.util.UtilCodec;

+import org.ofbiz.base.util.UtilDateTime;

+import org.ofbiz.base.util.UtilFormatOut;

+import org.ofbiz.base.util.UtilGenerics;

+import org.ofbiz.base.util.UtilMisc;

+import org.ofbiz.base.util.UtilProperties;

+import org.ofbiz.base.util.UtilValidate;

+import org.ofbiz.base.util.UtilXml;

+import org.ofbiz.base.util.collections.FlexibleMapAccessor;

+import org.ofbiz.base.util.collections.MapStack;

+import org.ofbiz.base.util.string.FlexibleStringExpander;

+import org.ofbiz.entity.Delegator;

+import org.ofbiz.entity.GenericEntity;

+import org.ofbiz.entity.GenericEntityException;

+import org.ofbiz.entity.GenericValue;

+import org.ofbiz.entity.condition.EntityCondition;

+import org.ofbiz.entity.finder.EntityFinderUtil;

+import org.ofbiz.entity.model.ModelEntity;

+import org.ofbiz.entity.util.EntityUtil;

+import org.ofbiz.widget.WidgetWorker;

+import org.ofbiz.widget.model.CommonWidgetModels.AutoEntityParameters;

+import org.ofbiz.widget.model.CommonWidgetModels.AutoServiceParameters;

+import org.ofbiz.widget.model.CommonWidgetModels.Image;

+import org.ofbiz.widget.model.CommonWidgetModels.Link;

+import org.ofbiz.widget.model.CommonWidgetModels.Parameter;

+import org.ofbiz.widget.model.ModelForm.UpdateArea;

+import org.ofbiz.widget.renderer.FormStringRenderer;

+import org.w3c.dom.Element;

+

+import bsh.EvalError;

+import bsh.Interpreter;

+

+/**

+ * Models the &lt;field&gt; element.

+ * 

+ * @see <code>widget-form.xsd</code>

+ */

+public class ModelFormField {

+

+    /*

+     * ----------------------------------------------------------------------- *

+     *                     DEVELOPERS PLEASE READ

+     * ----------------------------------------------------------------------- *

+     * 

+     * This model is intended to be a read-only data structure that represents

+     * an XML element. Outside of object construction, the class should not

+     * have any behaviors. All behavior should be contained in model visitors.

+     * 

+     * Instances of this class will be shared by multiple threads - therefore

+     * it is immutable. DO NOT CHANGE THE OBJECT'S STATE AT RUN TIME!

+     * 

+     */

+

+    public static final String module = ModelFormField.class.getName();

+

+    public static ModelFormField from(ModelFormFieldBuilder builder) {

+        return new ModelFormField(builder);

+    }

+

+    private final FlexibleStringExpander action;

+    private final String attributeName;

+    private final boolean encodeOutput;

+    private final String entityName;

+    private final FlexibleMapAccessor<Object> entryAcsr;

+    private final String event;

+    private final FieldInfo fieldInfo;

+    private final String fieldName;

+    private final String headerLink;

+    private final String headerLinkStyle;

+    private final String idName;

+    private final FlexibleMapAccessor<Map<String, ? extends Object>> mapAcsr;

+    private final ModelForm modelForm;

+    private final String name;

+    private final List<UpdateArea> onChangeUpdateAreas;

+    private final List<UpdateArea> onClickUpdateAreas;

+    private final String parameterName;

+    private final Integer position;

+    private final String redWhen;

+    private final Boolean requiredField;

+    private final String requiredFieldStyle;

+    private final boolean separateColumn;

+    private final String serviceName;

+    private final Boolean sortField;

+    private final String sortFieldAscStyle;

+    private final String sortFieldDescStyle;

+    private final String sortFieldHelpText;

+    private final String sortFieldStyle;

+    private final FlexibleStringExpander title;

+    private final String titleAreaStyle;

+    private final String titleStyle;

+    private final FlexibleStringExpander tooltip;

+    private final String tooltipStyle;

+    private final FlexibleStringExpander useWhen;

+    private final String widgetAreaStyle;

+    private final String widgetStyle;

+

+    private ModelFormField(ModelFormFieldBuilder builder) {

+        this.action = builder.getAction();

+        this.attributeName = builder.getAttributeName();

+        this.encodeOutput = builder.getEncodeOutput();

+        this.entityName = builder.getEntityName();

+        this.entryAcsr = builder.getEntryAcsr();

+        this.event = builder.getEvent();

+        if (builder.getFieldInfo() != null) {

+            this.fieldInfo = builder.getFieldInfo().copy(this);

+        } else {

+            this.fieldInfo = null;

+        }

+        this.fieldName = builder.getFieldName();

+        this.headerLink = builder.getHeaderLink();

+        this.headerLinkStyle = builder.getHeaderLinkStyle();

+        this.idName = builder.getIdName();

+        this.mapAcsr = builder.getMapAcsr();

+        this.modelForm = builder.getModelForm();

+        this.name = builder.getName();

+        if (builder.getOnChangeUpdateAreas().isEmpty()) {

+            this.onChangeUpdateAreas = Collections.emptyList();

+        } else {

+            this.onChangeUpdateAreas = Collections.unmodifiableList(new ArrayList<UpdateArea>(builder.getOnChangeUpdateAreas()));

+        }

+        if (builder.getOnClickUpdateAreas().isEmpty()) {

+            this.onClickUpdateAreas = Collections.emptyList();

+        } else {

+            this.onClickUpdateAreas = Collections.unmodifiableList(new ArrayList<UpdateArea>(builder.getOnClickUpdateAreas()));

+        }

+        this.parameterName = builder.getParameterName();

+        this.position = builder.getPosition();

+        this.redWhen = builder.getRedWhen();

+        this.requiredField = builder.getRequiredField();

+        this.requiredFieldStyle = builder.getRequiredFieldStyle();

+        this.separateColumn = builder.getSeparateColumn();

+        this.serviceName = builder.getServiceName();

+        this.sortField = builder.getSortField();

+        this.sortFieldAscStyle = builder.getSortFieldAscStyle();

+        this.sortFieldDescStyle = builder.getSortFieldDescStyle();

+        this.sortFieldHelpText = builder.getSortFieldHelpText();

+        this.sortFieldStyle = builder.getSortFieldStyle();

+        this.title = builder.getTitle();

+        this.titleAreaStyle = builder.getTitleAreaStyle();

+        this.titleStyle = builder.getTitleStyle();

+        this.tooltip = builder.getTooltip();

+        this.tooltipStyle = builder.getTooltipStyle();

+        this.useWhen = builder.getUseWhen();

+        this.widgetAreaStyle = builder.getWidgetAreaStyle();

+        this.widgetStyle = builder.getWidgetStyle();

+    }

+

+    public FlexibleStringExpander getAction() {

+        return action;

+    }

+

+    public String getAction(Map<String, ? extends Object> context) {

+        if (UtilValidate.isNotEmpty(this.action))

+            return action.expandString(context);

+        return null;

+    }

+

+    /**

+     * Gets the name of the Service Attribute (aka Parameter) that corresponds

+     * with this field. This can be used to get additional information about the field.

+     * Use the getServiceName() method to get the Entity name that the field is in.

+     *

+     * @return returns the name of the Service Attribute 

+     */

+    public String getAttributeName() {

+        if (UtilValidate.isNotEmpty(this.attributeName))

+            return this.attributeName;

+        return this.name;

+    }

+

+    public String getCurrentContainerId(Map<String, Object> context) {

+        ModelForm modelForm = this.getModelForm();

+        String idName = FlexibleStringExpander.expandString(this.getIdName(), context);

+

+        if (modelForm != null) {

+            Integer itemIndex = (Integer) context.get("itemIndex");

+            if ("list".equals(modelForm.getType()) || "multi".equals(modelForm.getType())) {

+                if (itemIndex != null) {

+                    return idName + modelForm.getItemIndexSeparator() + itemIndex.intValue();

+                }

+            }

+        }

+        return idName;

+    }

+

+    public boolean getEncodeOutput() {

+        return this.encodeOutput;

+    }

+

+    public String getEntityName() {

+        if (UtilValidate.isNotEmpty(this.entityName))

+            return this.entityName;

+        return this.modelForm.getDefaultEntityName();

+    }

+

+    /**

+     * Gets the entry from the context that corresponds to this field; if this

+     * form is being rendered in an error condition (ie isError in the context

+     * is true) then the value will be retrieved from the parameters Map in

+     * the context.

+     *

+     * @param context the context

+     * @return returns the entry from the context that corresponds to this field

+     */

+    public String getEntry(Map<String, ? extends Object> context) {

+        return this.getEntry(context, "");

+    }

+

+    public String getEntry(Map<String, ? extends Object> context, String defaultValue) {

+        Boolean isError = (Boolean) context.get("isError");

+        Boolean useRequestParameters = (Boolean) context.get("useRequestParameters");

+

+        Locale locale = (Locale) context.get("locale");

+        if (locale == null)

+            locale = Locale.getDefault();

+        TimeZone timeZone = (TimeZone) context.get("timeZone");

+        if (timeZone == null)

+            timeZone = TimeZone.getDefault();

+

+        String returnValue;

+

+        // if useRequestParameters is TRUE then parameters will always be used, if FALSE then parameters will never be used

+        // if isError is TRUE and useRequestParameters is not FALSE (ie is null or TRUE) then parameters will be used

+        if ((Boolean.TRUE.equals(isError) && !Boolean.FALSE.equals(useRequestParameters))

+                || (Boolean.TRUE.equals(useRequestParameters))) {

+            //Debug.logInfo("Getting entry, isError true so getting from parameters for field " + this.getName() + " of form " + this.modelForm.getName(), module);

+            Map<String, Object> parameters = UtilGenerics.checkMap(context.get("parameters"), String.class, Object.class);

+            String parameterName = this.getParameterName(context);

+            if (parameters != null && parameters.get(parameterName) != null) {

+                Object parameterValue = parameters.get(parameterName);

+                if (parameterValue instanceof String) {

+                    returnValue = (String) parameterValue;

+                } else {

+                    // we might want to do something else here in the future, but for now this is probably best

+                    Debug.logWarning("Found a non-String parameter value for field [" + this.getModelForm().getName() + "."

+                            + this.getFieldName() + "]", module);

+                    returnValue = defaultValue;

+                }

+            } else {

+                returnValue = defaultValue;

+            }

+        } else {

+            //Debug.logInfo("Getting entry, isError false so getting from Map in context for field " + this.getName() + " of form " + this.modelForm.getName(), module);

+            Map<String, ? extends Object> dataMap = this.getMap(context);

+            boolean dataMapIsContext = false;

+            if (dataMap == null) {

+                //Debug.logInfo("Getting entry, no Map found with name " + this.getMapName() + ", using context for field " + this.getName() + " of form " + this.modelForm.getName(), module);

+                dataMap = context;

+                dataMapIsContext = true;

+            }

+            Object retVal = null;

+            if (UtilValidate.isNotEmpty(this.entryAcsr)) {

+                if (dataMap instanceof GenericEntity) {

+                    GenericEntity genEnt = (GenericEntity) dataMap;

+                    if (genEnt.getModelEntity().isField(this.entryAcsr.getOriginalName())) {

+                        retVal = genEnt.get(this.entryAcsr.getOriginalName(), locale);

+                    } else {

+                        //TODO: this may never come up, but if necessary use the FlexibleStringExander to eval the name first: String evaled = this.entryAcsr

+                    }

+                } else {

+                    retVal = this.entryAcsr.get(dataMap, locale);

+                }

+            } else {

+                // if no entry name was specified, use the field's name

+                if (dataMap.containsKey(this.name)) {

+                    retVal = dataMap.get(this.name);

+                }

+            }

+

+            // this is a special case to fill in fields during a create by default from parameters passed in

+            if (dataMapIsContext && retVal == null && !Boolean.FALSE.equals(useRequestParameters)) {

+                Map<String, ? extends Object> parameters = UtilGenerics.checkMap(context.get("parameters"));

+                if (parameters != null) {

+                    if (UtilValidate.isNotEmpty(this.entryAcsr))

+                        retVal = this.entryAcsr.get(parameters);

+                    else

+                        retVal = parameters.get(this.name);

+                }

+            }

+

+            if (retVal != null) {

+                // format string based on the user's locale and time zone

+                if (retVal instanceof Double || retVal instanceof Float || retVal instanceof BigDecimal) {

+                    NumberFormat nf = NumberFormat.getInstance(locale);

+                    nf.setMaximumFractionDigits(10);

+                    return nf.format(retVal);

+                } else if (retVal instanceof java.sql.Date) {

+                    DateFormat df = UtilDateTime.toDateFormat(UtilDateTime.DATE_FORMAT, timeZone, null);

+                    return df.format((java.util.Date) retVal);

+                } else if (retVal instanceof java.sql.Time) {

+                    DateFormat df = UtilDateTime.toTimeFormat(UtilDateTime.TIME_FORMAT, timeZone, null);

+                    return df.format((java.util.Date) retVal);

+                } else if (retVal instanceof java.sql.Timestamp) {

+                    DateFormat df = UtilDateTime.toDateTimeFormat(UtilDateTime.DATE_TIME_FORMAT, timeZone, null);

+                    return df.format((java.util.Date) retVal);

+                } else if (retVal instanceof java.util.Date) {

+                    DateFormat df = UtilDateTime.toDateTimeFormat("EEE MMM dd hh:mm:ss z yyyy", timeZone, null);

+                    return df.format((java.util.Date) retVal);

+                } else {

+                    returnValue = retVal.toString();

+                }

+            } else {

+                returnValue = defaultValue;

+            }

+        }

+

+        if (this.getEncodeOutput() && returnValue != null) {

+            UtilCodec.SimpleEncoder simpleEncoder = (UtilCodec.SimpleEncoder) context.get("simpleEncoder");

+            if (simpleEncoder != null)

+                returnValue = simpleEncoder.encode(returnValue);

+        }

+        return returnValue;

+    }

+

+    public FlexibleMapAccessor<Object> getEntryAcsr() {

+        return entryAcsr;

+    }

+

+    public String getEntryName() {

+        if (UtilValidate.isNotEmpty(this.entryAcsr))

+            return this.entryAcsr.getOriginalName();

+        return this.name;

+    }

+

+    public String getEvent() {

+        return event;

+    }

+

+    public FieldInfo getFieldInfo() {

+        return fieldInfo;

+    }

+

+    /**

+     * Gets the name of the Entity Field that corresponds

+     * with this field. This can be used to get additional information about the field.

+     * Use the getEntityName() method to get the Entity name that the field is in.

+     *

+     * @return return the name of the Entity Field that corresponds with this field

+     */

+    public String getFieldName() {

+        if (UtilValidate.isNotEmpty(this.fieldName))

+            return this.fieldName;

+        return this.name;

+    }

+

+    public String getHeaderLink() {

+        return headerLink;

+    }

+

+    public String getHeaderLinkStyle() {

+        return headerLinkStyle;

+    }

+

+    public String getIdName() {

+        if (UtilValidate.isNotEmpty(idName))

+            return idName;

+        return this.modelForm.getName() + "_" + this.getFieldName();

+    }

+

+    public Map<String, ? extends Object> getMap(Map<String, ? extends Object> context) {

+        if (UtilValidate.isEmpty(this.mapAcsr))

+            return this.modelForm.getDefaultMap(context); //Debug.logInfo("Getting Map from default of the form because of no mapAcsr for field " + this.getName(), module);

+

+        // Debug.logInfo("Getting Map from mapAcsr for field " + this.getName() + ", map-name=" + mapAcsr.getOriginalName() + ", context type=" + context.getClass().toString(), module);

+        Map<String, ? extends Object> result = null;

+        try {

+            result = mapAcsr.get(context);

+        } catch (java.lang.ClassCastException e) {

+            String errMsg = "Got an unexpected object type (not a Map) for map-name [" + mapAcsr.getOriginalName()

+                    + "] in field with name [" + this.getName() + "]: " + e.getMessage();

+            Debug.logError(errMsg, module);

+            throw new ClassCastException(errMsg);

+        }

+        return result;

+    }

+

+    public FlexibleMapAccessor<Map<String, ? extends Object>> getMapAcsr() {

+        return mapAcsr;

+    }

+

+    /** Get the name of the Map in the form context that contains the entry,

+     * available from the getEntryName() method. This entry is used to

+     * pre-populate the field widget when not in an error condition. In an

+     * error condition the parameter name is used to get the value from the

+     * parameters Map.

+     *

+     * @return returns the name of the Map in the form context that contains the entry

+     */

+    public String getMapName() {

+        if (UtilValidate.isNotEmpty(this.mapAcsr))

+            return this.mapAcsr.getOriginalName();

+        return this.modelForm.getDefaultMapName();

+    }

+

+    public ModelForm getModelForm() {

+        return modelForm;

+    }

+

+    public String getName() {

+        return name;

+    }

+

+    public List<UpdateArea> getOnChangeUpdateAreas() {

+        return onChangeUpdateAreas;

+    }

+

+    public List<UpdateArea> getOnClickUpdateAreas() {

+        return onClickUpdateAreas;

+    }

+

+    public String getParameterName() {

+        return parameterName;

+    }

+

+    /**

+     * Get the name to use for the parameter for this field in the form interpreter.

+     * For HTML forms this is the request parameter name.

+     *

+     * @return returns the name to use for the parameter for this field in the form interpreter

+     */

+    public String getParameterName(Map<String, ? extends Object> context) {

+        String baseName;

+        if (UtilValidate.isNotEmpty(this.parameterName))

+            baseName = this.parameterName;

+        else

+            baseName = this.name;

+

+        Integer itemIndex = (Integer) context.get("itemIndex");

+        if (itemIndex != null && "multi".equals(this.modelForm.getType())) {

+            return baseName + this.modelForm.getItemIndexSeparator() + itemIndex.intValue();

+        } else {

+            return baseName;

+        }

+    }

+

+    public int getPosition() {

+        if (this.position == null)

+            return 1;

+        return position.intValue();

+    }

+

+    public String getRedWhen() {

+        return redWhen;

+    }

+

+    public boolean getRequiredField() {

+        return this.requiredField != null ? this.requiredField : false;

+    }

+

+    public String getRequiredFieldStyle() {

+        if (UtilValidate.isNotEmpty(this.requiredFieldStyle))

+            return this.requiredFieldStyle;

+        return this.modelForm.getDefaultRequiredFieldStyle();

+    }

+

+    public boolean getSeparateColumn() {

+        return this.separateColumn;

+    }

+

+    public String getServiceName() {

+        if (UtilValidate.isNotEmpty(this.serviceName))

+            return this.serviceName;

+        return this.modelForm.getDefaultServiceName();

+    }

+

+    public Boolean getSortField() {

+        return sortField;

+    }

+

+    public String getSortFieldAscStyle() {

+        return sortFieldAscStyle;

+    }

+

+    public String getSortFieldDescStyle() {

+        return sortFieldDescStyle;

+    }

+

+    public String getSortFieldHelpText() {

+        return sortFieldHelpText;

+    }

+

+    public String getSortFieldHelpText(Map<String, Object> context) {

+        return FlexibleStringExpander.expandString(this.sortFieldHelpText, context);

+    }

+

+    public String getSortFieldStyle() {

+        if (UtilValidate.isNotEmpty(this.sortFieldStyle))

+            return this.sortFieldStyle;

+        return this.modelForm.getDefaultSortFieldStyle();

+    }

+

+    public String getSortFieldStyleAsc() {

+        if (UtilValidate.isNotEmpty(this.sortFieldAscStyle))

+            return this.sortFieldAscStyle;

+        return this.modelForm.getDefaultSortFieldAscStyle();

+    }

+

+    public String getSortFieldStyleDesc() {

+        if (UtilValidate.isNotEmpty(this.sortFieldDescStyle))

+            return this.sortFieldDescStyle;

+        return this.modelForm.getDefaultSortFieldDescStyle();

+    }

+

+    public FlexibleStringExpander getTitle() {

+        return title;

+    }

+

+    public String getTitle(Map<String, Object> context) {

+        if (UtilValidate.isNotEmpty(this.title))

+            return title.expandString(context);

+

+        // create a title from the name of this field; expecting a Java method/field style name, ie productName or productCategoryId

+        if (UtilValidate.isEmpty(this.name))

+            return ""; // this should never happen, ie name is required

+

+        // search for a localized label for the field's name

+        Map<String, String> uiLabelMap = UtilGenerics.checkMap(context.get("uiLabelMap"));

+        if (uiLabelMap != null) {

+            String titleFieldName = "FormFieldTitle_" + this.name;

+            String localizedName = uiLabelMap.get(titleFieldName);

+            if (!localizedName.equals(titleFieldName)) {

+                return localizedName;

+            }

+        } else {

+            Debug.logWarning("Could not find uiLabelMap in context while rendering form " + this.modelForm.getName(), module);

+        }

+

+        // create a title from the name of this field; expecting a Java method/field style name, ie productName or productCategoryId

+        StringBuilder autoTitlewriter = new StringBuilder();

+

+        // always use upper case first letter...

+        autoTitlewriter.append(Character.toUpperCase(this.name.charAt(0)));

+

+        // just put spaces before the upper case letters

+        for (int i = 1; i < this.name.length(); i++) {

+            char curChar = this.name.charAt(i);

+            if (Character.isUpperCase(curChar)) {

+                autoTitlewriter.append(' ');

+            }

+            autoTitlewriter.append(curChar);

+        }

+

+        return autoTitlewriter.toString();

+    }

+

+    public String getTitleAreaStyle() {

+        if (UtilValidate.isNotEmpty(this.titleAreaStyle))

+            return this.titleAreaStyle;

+        return this.modelForm.getDefaultTitleAreaStyle();

+    }

+

+    public String getTitleStyle() {

+        if (UtilValidate.isNotEmpty(this.titleStyle))

+            return this.titleStyle;

+        return this.modelForm.getDefaultTitleStyle();

+    }

+

+    public FlexibleStringExpander getTooltip() {

+        return tooltip;

+    }

+

+    public String getTooltip(Map<String, Object> context) {

+        String tooltipString = "";

+        if (UtilValidate.isNotEmpty(tooltip))

+            tooltipString = tooltip.expandString(context);

+        if (this.getEncodeOutput()) {

+            UtilCodec.SimpleEncoder simpleEncoder = (UtilCodec.SimpleEncoder) context.get("simpleEncoder");

+            if (simpleEncoder != null)

+                tooltipString = simpleEncoder.encode(tooltipString);

+        }

+        return tooltipString;

+    }

+

+    public String getTooltipStyle() {

+        if (UtilValidate.isNotEmpty(this.tooltipStyle))

+            return this.tooltipStyle;

+        return this.modelForm.getDefaultTooltipStyle();

+    }

+

+    public FlexibleStringExpander getUseWhen() {

+        return useWhen;

+    }

+

+    public String getUseWhen(Map<String, Object> context) {

+        if (UtilValidate.isNotEmpty(this.useWhen))

+            return this.useWhen.expandString(context);

+        return "";

+    }

+

+    public String getWidgetAreaStyle() {

+        if (UtilValidate.isNotEmpty(this.widgetAreaStyle))

+            return this.widgetAreaStyle;

+        return this.modelForm.getDefaultWidgetAreaStyle();

+    }

+

+    public String getWidgetStyle() {

+        if (UtilValidate.isNotEmpty(this.widgetStyle))

+            return this.widgetStyle;

+        return this.modelForm.getDefaultWidgetStyle();

+    }

+

+    /**

+     * Checks if field is a row submit field.

+     */

+    public boolean isRowSubmit() {

+        if (!"multi".equals(getModelForm().getType()))

+            return false;

+        if (getFieldInfo().getFieldType() != FieldInfo.CHECK)

+            return false;

+        if (!CheckField.ROW_SUBMIT_FIELD_NAME.equals(getName()))

+            return false;

+        return true;

+    }

+

+    public boolean isSortField() {

+        return this.sortField != null && this.sortField.booleanValue();

+    }

+

+    public boolean isUseWhenEmpty() {

+        if (this.useWhen == null) {

+            return true;

+        }

+

+        return this.useWhen.isEmpty();

+    }

+

+    public void renderFieldString(Appendable writer, Map<String, Object> context, FormStringRenderer formStringRenderer)

+            throws IOException {

+        this.fieldInfo.renderFieldString(writer, context, formStringRenderer);

+    }

+

+    /**

+     * the widget/interaction part will be red if the date value is

+     *  before-now (for ex. thruDate), after-now (for ex. fromDate), or by-name (if the

+     *  field's name or entry-name or fromDate or thruDate the corresponding

+     *  action will be done); only applicable when the field is a timestamp

+     *

+     * @param context the context

+     * @return true if the field should be read otherwise false

+     */

+    public boolean shouldBeRed(Map<String, Object> context) {

+        // red-when (never | before-now | after-now | by-name) "by-name"

+

+        String redCondition = this.redWhen;

+

+        if ("never".equals(redCondition))

+            return false;

+

+        // for performance resaons we check this first, most fields will be eliminated here and the valueOfs will not be necessary

+        if (UtilValidate.isEmpty(redCondition) || "by-name".equals(redCondition)) {

+            if ("fromDate".equals(this.name) || (this.entryAcsr != null && "fromDate".equals(this.entryAcsr.getOriginalName()))) {

+                redCondition = "after-now";

+            } else if ("thruDate".equals(this.name)

+                    || (this.entryAcsr != null && "thruDate".equals(this.entryAcsr.getOriginalName()))) {

+                redCondition = "before-now";

+            } else {

+                return false;

+            }

+        }

+

+        boolean isBeforeNow = false;

+        if ("before-now".equals(redCondition)) {

+            isBeforeNow = true;

+        } else if ("after-now".equals(redCondition)) {

+            isBeforeNow = false;

+        } else {

+            return false;

+        }

+

+        java.sql.Date dateVal = null;

+        java.sql.Time timeVal = null;

+        java.sql.Timestamp timestampVal = null;

+

+        //now before going on, check to see if the current entry is a valid date and/or time and get the value

+        String value = this.getEntry(context, null);

+        try {

+            timestampVal = java.sql.Timestamp.valueOf(value);

+        } catch (Exception e) {

+            // okay, not a timestamp...

+        }

+

+        if (timestampVal == null) {

+            try {

+                dateVal = java.sql.Date.valueOf(value);

+            } catch (Exception e) {

+                // okay, not a date...

+            }

+        }

+

+        if (timestampVal == null && dateVal == null) {

+            try {

+                timeVal = java.sql.Time.valueOf(value);

+            } catch (Exception e) {

+                // okay, not a time...

+            }

+        }

+

+        if (timestampVal == null && dateVal == null && timeVal == null) {

+            return false;

+        }

+

+        long nowMillis = System.currentTimeMillis();

+        if (timestampVal != null) {

+            java.sql.Timestamp nowStamp = new java.sql.Timestamp(nowMillis);

+            if (!timestampVal.equals(nowStamp)) {

+                if (isBeforeNow) {

+                    if (timestampVal.before(nowStamp)) {

+                        return true;

+                    }

+                } else {

+                    if (timestampVal.after(nowStamp)) {

+                        return true;

+                    }

+                }

+            }

+        } else if (dateVal != null) {

+            java.sql.Date nowDate = new java.sql.Date(nowMillis);

+            if (!dateVal.equals(nowDate)) {

+                if (isBeforeNow) {

+                    if (dateVal.before(nowDate)) {

+                        return true;

+                    }

+                } else {

+                    if (dateVal.after(nowDate)) {

+                        return true;

+                    }

+                }

+            }

+        } else if (timeVal != null) {

+            java.sql.Time nowTime = new java.sql.Time(nowMillis);

+            if (!timeVal.equals(nowTime)) {

+                if (isBeforeNow) {

+                    if (timeVal.before(nowTime)) {

+                        return true;

+                    }

+                } else {

+                    if (timeVal.after(nowTime)) {

+                        return true;

+                    }

+                }

+            }

+        }

+

+        return false;

+    }

+

+    public boolean shouldUse(Map<String, Object> context) {

+        String useWhenStr = this.getUseWhen(context);

+        if (UtilValidate.isEmpty(useWhenStr))

+            return true;

+

+        try {

+            Interpreter bsh = this.modelForm.getBshInterpreter(context);

+            Object retVal = bsh.eval(StringUtil.convertOperatorSubstitutions(useWhenStr));

+            boolean condTrue = false;

+            // retVal should be a Boolean, if not something weird is up...

+            if (retVal instanceof Boolean) {

+                Boolean boolVal = (Boolean) retVal;

+                condTrue = boolVal.booleanValue();

+            } else {

+                throw new IllegalArgumentException("Return value from use-when condition eval was not a Boolean: "

+                        + (retVal != null ? retVal.getClass().getName() : "null") + " [" + retVal + "] on the field " + this.name

+                        + " of form " + this.modelForm.getName());

+            }

+

+            return condTrue;

+        } catch (EvalError e) {

+            String errMsg = "Error evaluating BeanShell use-when condition [" + useWhenStr + "] on the field " + this.name

+                    + " of form " + this.modelForm.getName() + ": " + e.toString();

+            Debug.logError(e, errMsg, module);

+            //Debug.logError("For use-when eval error context is: " + context, module);

+            throw new IllegalArgumentException(errMsg);

+        }

+    }

+

+    /**

+     * Models the &lt;auto-complete&gt; element.

+     * 

+     * @see <code>widget-form.xsd</code>

+     */

+    public static class AutoComplete {

+        private final String autoSelect;

+        private final String choices;

+        private final String frequency;

+        private final String fullSearch;

+        private final String ignoreCase;

+        private final String minChars;

+        private final String partialChars;

+        private final String partialSearch;

+

+        public AutoComplete(Element element) {

+            this.autoSelect = element.getAttribute("auto-select");

+            this.frequency = element.getAttribute("frequency");

+            this.minChars = element.getAttribute("min-chars");

+            this.choices = element.getAttribute("choices");

+            this.partialSearch = element.getAttribute("partial-search");

+            this.partialChars = element.getAttribute("partial-chars");

+            this.ignoreCase = element.getAttribute("ignore-case");

+            this.fullSearch = element.getAttribute("full-search");

+        }

+

+        public String getAutoSelect() {

+            return this.autoSelect;

+        }

+

+        public String getChoices() {

+            return this.choices;

+        }

+

+        public String getFrequency() {

+            return this.frequency;

+        }

+

+        public String getFullSearch() {

+            return this.fullSearch;

+        }

+

+        public String getIgnoreCase() {

+            return this.ignoreCase;

+        }

+

+        public String getMinChars() {

+            return this.minChars;

+        }

+

+        public String getPartialChars() {

+            return this.partialChars;

+        }

+

+        public String getPartialSearch() {

+            return this.partialSearch;

+        }

+    }

+

+    /**

+     * Models the &lt;check&gt; element.

+     * 

+     * @see <code>widget-form.xsd</code>

+     */

+    public static class CheckField extends FieldInfoWithOptions {

+        public final static String ROW_SUBMIT_FIELD_NAME = "_rowSubmit";

+        private final FlexibleStringExpander allChecked;

+

+        private CheckField(CheckField original, ModelFormField modelFormField) {

+            super(original, modelFormField);

+            this.allChecked = original.allChecked;

+        }

+

+        public CheckField(Element element, ModelFormField modelFormField) {

+            super(element, modelFormField);

+            allChecked = FlexibleStringExpander.getInstance(element.getAttribute("all-checked"));

+        }

+

+        public CheckField(int fieldSource, ModelFormField modelFormField) {

+            super(fieldSource, FieldInfo.CHECK, modelFormField);

+            this.allChecked = FlexibleStringExpander.getInstance("");

+        }

+

+        public CheckField(ModelFormField modelFormField) {

+            super(FieldInfo.SOURCE_EXPLICIT, FieldInfo.CHECK, modelFormField);

+            this.allChecked = FlexibleStringExpander.getInstance("");

+        }

+

+        @Override

+        public void accept(ModelFieldVisitor visitor) throws Exception {

+            visitor.visit(this);

+        }

+

+        @Override

+        public FieldInfo copy(ModelFormField modelFormField) {

+            return new CheckField(this, modelFormField);

+        }

+

+        public FlexibleStringExpander getAllChecked() {

+            return allChecked;

+        }

+

+        public Boolean isAllChecked(Map<String, Object> context) {

+            String allCheckedStr = this.allChecked.expandString(context);

+            if (!allCheckedStr.isEmpty())

+                return Boolean.valueOf("true".equals(allCheckedStr));

+            else

+                return null;

+        }

+

+        @Override

+        public void renderFieldString(Appendable writer, Map<String, Object> context, FormStringRenderer formStringRenderer)

+                throws IOException {

+            formStringRenderer.renderCheckField(writer, context, this);

+        }

+    }

+

+    /**

+     * Models the &lt;container&gt; element.

+     * 

+     * @see <code>widget-form.xsd</code>

+     */

+    public static class ContainerField extends FieldInfo {

+

+        private ContainerField(ContainerField original, ModelFormField modelFormField) {

+            super(original.getFieldSource(), original.getFieldType(), modelFormField);

+        }

+

+        public ContainerField(Element element, ModelFormField modelFormField) {

+            super(element, modelFormField);

+        }

+

+        public ContainerField(int fieldSource, int fieldType, ModelFormField modelFormField) {

+            super(fieldSource, fieldType, modelFormField);

+        }

+

+        @Override

+        public void accept(ModelFieldVisitor visitor) throws Exception {

+            visitor.visit(this);

+        }

+

+        @Override

+        public FieldInfo copy(ModelFormField modelFormField) {

+            return new ContainerField(this, modelFormField);

+        }

+

+        @Override

+        public void renderFieldString(Appendable writer, Map<String, Object> context, FormStringRenderer formStringRenderer)

+                throws IOException {

+            formStringRenderer.renderContainerFindField(writer, context, this);

+        }

+    }

+

+    /**

+     * Models the &lt;date-find&gt; element.

+     * 

+     * @see <code>widget-form.xsd</code>

+     */

+    public static class DateFindField extends DateTimeField {

+        private final String defaultOptionFrom;

+        private final String defaultOptionThru;

+

+        private DateFindField(DateFindField original, ModelFormField modelFormField) {

+            super(original, modelFormField);

+            this.defaultOptionFrom = original.defaultOptionFrom;

+            this.defaultOptionThru = original.defaultOptionThru;

+        }

+

+        public DateFindField(Element element, ModelFormField modelFormField) {

+            super(element, modelFormField);

+            this.defaultOptionFrom = element.getAttribute("default-option-from");

+            this.defaultOptionThru = element.getAttribute("default-option-thru");

+        }

+

+        public DateFindField(int fieldSource, ModelFormField modelFormField) {

+            super(fieldSource, modelFormField);

+            this.defaultOptionFrom = "greaterThanEqualTo";

+            this.defaultOptionThru = "lessThanEqualTo";

+        }

+

+        public DateFindField(int fieldSource, String type) {

+            super(fieldSource, type);

+            this.defaultOptionFrom = "greaterThanEqualTo";

+            this.defaultOptionThru = "lessThanEqualTo";

+        }

+

+        @Override

+        public void accept(ModelFieldVisitor visitor) throws Exception {

+            visitor.visit(this);

+        }

+

+        @Override

+        public FieldInfo copy(ModelFormField modelFormField) {

+            return new DateFindField(this, modelFormField);

+        }

+

+        public String getDefaultOptionFrom() {

+            return this.defaultOptionFrom;

+        }

+

+        public String getDefaultOptionThru() {

+            return this.defaultOptionThru;

+        }

+

+        @Override

+        public void renderFieldString(Appendable writer, Map<String, Object> context, FormStringRenderer formStringRenderer)

+                throws IOException {

+            formStringRenderer.renderDateFindField(writer, context, this);

+        }

+    }

+

+    /**

+     * Models the &lt;date-time&gt; element.

+     * 

+     * @see <code>widget-form.xsd</code>

+     */

+    public static class DateTimeField extends FieldInfo {

+        private final String clock;

+        private final FlexibleStringExpander defaultValue;

+        private final String inputMethod;

+        private final String mask;

+        private final String step;

+        private final String type;

+

+        protected DateTimeField(DateTimeField original, ModelFormField modelFormField) {

+            super(original.getFieldSource(), original.getFieldType(), modelFormField);

+            this.defaultValue = original.defaultValue;

+            this.type = original.type;

+            this.inputMethod = original.inputMethod;

+            this.clock = original.clock;

+            this.mask = original.mask;

+            this.step = original.step;

+        }

+

+        public DateTimeField(Element element, ModelFormField modelFormField) {

+            super(element, modelFormField);

+            this.defaultValue = FlexibleStringExpander.getInstance(element.getAttribute("default-value"));

+            this.type = element.getAttribute("type");

+            this.inputMethod = element.getAttribute("input-method");

+            this.clock = element.getAttribute("clock");

+            this.mask = element.getAttribute("mask");

+            String step = element.getAttribute("step");

+            if (step.isEmpty()) {

+                step = "1";

+            }

+            this.step = step;

+        }

+

+        public DateTimeField(int fieldSource, ModelFormField modelFormField) {

+            super(fieldSource, FieldInfo.DATE_TIME, modelFormField);

+            this.defaultValue = FlexibleStringExpander.getInstance("");

+            this.type = "";

+            this.inputMethod = "";

+            this.clock = "";

+            this.mask = "";

+            this.step = "1";

+        }

+

+        public DateTimeField(int fieldSource, String type) {

+            super(fieldSource, FieldInfo.DATE_TIME, null);

+            this.defaultValue = FlexibleStringExpander.getInstance("");

+            this.type = type;

+            this.inputMethod = "";

+            this.clock = "";

+            this.mask = "";

+            this.step = "1";

+        }

+

+        public DateTimeField(ModelFormField modelFormField) {

+            super(FieldInfo.SOURCE_EXPLICIT, FieldInfo.DATE_TIME, modelFormField);

+            this.defaultValue = FlexibleStringExpander.getInstance("");

+            this.type = "";

+            this.inputMethod = "";

+            this.clock = "";

+            this.mask = "";

+            this.step = "1";

+        }

+

+        @Override

+        public void accept(ModelFieldVisitor visitor) throws Exception {

+            visitor.visit(this);

+        }

+

+        @Override

+        public FieldInfo copy(ModelFormField modelFormField) {

+            return new DateTimeField(this, modelFormField);

+        }

+

+        public String getClock() {

+            return this.clock;

+        }

+

+        /**

+         * Returns the default-value if specified, otherwise the current date, time or timestamp

+         *

+         * @param context Context Map

+         * @return Default value string for date-time

+         */

+        public String getDefaultDateTimeString(Map<String, Object> context) {

+            if (UtilValidate.isNotEmpty(this.defaultValue))

+                return this.getDefaultValue(context);

+

+            if ("date".equals(this.type))

+                return (new java.sql.Date(System.currentTimeMillis())).toString();

+            else if ("time".equals(this.type))

+                return (new java.sql.Time(System.currentTimeMillis())).toString();

+            else

+                return UtilDateTime.nowTimestamp().toString();

+        }

+

+        public FlexibleStringExpander getDefaultValue() {

+            return defaultValue;

+        }

+

+        public String getDefaultValue(Map<String, Object> context) {

+            if (this.defaultValue != null) {

+                return this.defaultValue.expandString(context);

+            } else {

+                return "";

+            }

+        }

+

+        public String getInputMethod() {

+            return this.inputMethod;

+        }

+

+        public String getMask() {

+            return this.mask;

+        }

+

+        public String getStep() {

+            return this.step;

+        }

+

+        public String getType() {

+            return type;

+        }

+

+        @Override

+        public void renderFieldString(Appendable writer, Map<String, Object> context, FormStringRenderer formStringRenderer)

+                throws IOException {

+            formStringRenderer.renderDateTimeField(writer, context, this);

+        }

+    }

+

+    /**

+     * Models the &lt;display-entity&gt; element.

+     * 

+     * @see <code>widget-form.xsd</code>

+     */

+    public static class DisplayEntityField extends DisplayField {

+        private final boolean cache;

+        private final String entityName;

+        private final String keyFieldName;

+        private final SubHyperlink subHyperlink;

+

+        private DisplayEntityField(DisplayEntityField original, ModelFormField modelFormField) {

+            super(original, modelFormField);

+            this.cache = original.cache;

+            this.entityName = original.entityName;

+            this.keyFieldName = original.keyFieldName;

+            if (original.subHyperlink != null) {

+                this.subHyperlink = new SubHyperlink(original.subHyperlink, modelFormField);

+            } else {

+                this.subHyperlink = null;

+            }

+        }

+

+        public DisplayEntityField(Element element, ModelFormField modelFormField) {

+            super(element, modelFormField);

+            this.cache = !"false".equals(element.getAttribute("cache"));

+            this.entityName = element.getAttribute("entity-name");

+            this.keyFieldName = element.getAttribute("key-field-name");

+            Element subHyperlinkElement = UtilXml.firstChildElement(element, "sub-hyperlink");

+            if (subHyperlinkElement != null) {

+                this.subHyperlink = new SubHyperlink(subHyperlinkElement, modelFormField);

+            } else {

+                this.subHyperlink = null;

+            }

+        }

+

+        public DisplayEntityField(int fieldSource, ModelFormField modelFormField) {

+            super(fieldSource, FieldInfo.DISPLAY_ENTITY, modelFormField);

+            this.cache = true;

+            this.entityName = "";

+            this.keyFieldName = "";

+            this.subHyperlink = null;

+        }

+

+        public DisplayEntityField(ModelFormField modelFormField) {

+            super(FieldInfo.SOURCE_EXPLICIT, FieldInfo.DISPLAY_ENTITY, modelFormField);

+            this.cache = true;

+            this.entityName = "";

+            this.keyFieldName = "";

+            this.subHyperlink = null;

+        }

+

+        @Override

+        public void accept(ModelFieldVisitor visitor) throws Exception {

+            visitor.visit(this);

+        }

+

+        @Override

+        public FieldInfo copy(ModelFormField modelFormField) {

+            return new DisplayEntityField(this, modelFormField);

+        }

+

+        public boolean getCache() {

+            return cache;

+        }

+

+        @Override

+        public String getDescription(Map<String, Object> context) {

+            Locale locale = UtilMisc.ensureLocale(context.get("locale"));

+

+            // rather than using the context to expand the string, lookup the given entity and use it to expand the string

+            GenericValue value = null;

+            String fieldKey = this.keyFieldName;

+            if (UtilValidate.isEmpty(fieldKey))

+                fieldKey = getModelFormField().fieldName;

+

+            Delegator delegator = WidgetWorker.getDelegator(context);

+            String fieldValue = getModelFormField().getEntry(context);

+            try {

+                value = delegator.findOne(this.entityName, this.cache, fieldKey, fieldValue);

+            } catch (GenericEntityException e) {

+                String errMsg = "Error getting value from the database for display of field [" + getModelFormField().getName()

+                        + "] on form [" + getModelFormField().modelForm.getName() + "]: " + e.toString();

+                Debug.logError(e, errMsg, module);

+                throw new IllegalArgumentException(errMsg);

+            }

+

+            String retVal = null;

+            if (value != null) {

+                // expanding ${} stuff, passing locale explicitly to expand value string because it won't be found in the Entity

+                MapStack<String> localContext = MapStack.create(context);

+                // Rendering code might try to modify the GenericEntity instance,

+                // so we make a copy of it.

+                Map<String, Object> genericEntityClone = UtilGenerics.cast(value.clone());

+                localContext.push(genericEntityClone);

+

+                // expand with the new localContext, which is locale aware

+                retVal = this.getDescription().expandString(localContext, locale);

+            }

+            // try to get the entry for the field if description doesn't expand to anything

+            if (UtilValidate.isEmpty(retVal))

+                retVal = fieldValue;

+            if (UtilValidate.isEmpty(retVal))

+                retVal = "";

+            return retVal;

+        }

+

+        public String getEntityName() {

+            return entityName;

+        }

+

+        public String getKeyFieldName() {

+            return keyFieldName;

+        }

+

+        public SubHyperlink getSubHyperlink() {

+            return this.subHyperlink;

+        }

+    }

+

+    /**

+     * Models the &lt;display&gt; element.

+     * 

+     * @see <code>widget-form.xsd</code>

+     */

+    public static class DisplayField extends FieldInfo {

+        private final boolean alsoHidden;

+        private final FlexibleStringExpander currency;

+        private final FlexibleStringExpander date;

+        private final FlexibleStringExpander defaultValue;

+        private final FlexibleStringExpander description;

+        private final FlexibleStringExpander imageLocation;

+        private final InPlaceEditor inPlaceEditor;

+        private final String size; // maximum number of characters to display

+        private final String type; // matches type of field, currently text or currency

+

+        protected DisplayField(DisplayField original, ModelFormField modelFormField) {

+            super(original.getFieldSource(), original.getFieldType(), modelFormField);

+            this.alsoHidden = original.alsoHidden;

+            this.currency = original.currency;

+            this.date = original.date;

+            this.defaultValue = original.defaultValue;

+            this.description = original.description;

+            this.imageLocation = original.imageLocation;

+            this.inPlaceEditor = original.inPlaceEditor;

+            this.size = original.size;

+            this.type = original.type;

+        }

+

+        public DisplayField(Element element, ModelFormField modelFormField) {

+            super(element, modelFormField);

+            this.alsoHidden = !"false".equals(element.getAttribute("also-hidden"));

+            this.currency = FlexibleStringExpander.getInstance(element.getAttribute("currency"));

+            this.date = FlexibleStringExpander.getInstance(element.getAttribute("date"));

+            this.defaultValue = FlexibleStringExpander.getInstance(element.getAttribute("default-value"));

+            this.description = FlexibleStringExpander.getInstance(element.getAttribute("description"));

+            this.imageLocation = FlexibleStringExpander.getInstance(element.getAttribute("image-location"));

+            Element inPlaceEditorElement = UtilXml.firstChildElement(element, "in-place-editor");

+            if (inPlaceEditorElement != null) {

+                this.inPlaceEditor = new InPlaceEditor(inPlaceEditorElement);

+            } else {

+                this.inPlaceEditor = null;

+            }

+            this.size = element.getAttribute("size");

+            this.type = element.getAttribute("type");

+        }

+

+        public DisplayField(int fieldSource, int fieldType, ModelFormField modelFormField) {

+            super(fieldSource, fieldType, modelFormField);

+            this.alsoHidden = true;

+            this.currency = FlexibleStringExpander.getInstance("");

+            this.date = FlexibleStringExpander.getInstance("");

+            this.defaultValue = FlexibleStringExpander.getInstance("");

+            this.description = FlexibleStringExpander.getInstance("");

+            this.imageLocation = FlexibleStringExpander.getInstance("");

+            this.inPlaceEditor = null;

+            this.size = "";

+            this.type = "";

+        }

+

+        public DisplayField(int fieldSource, ModelFormField modelFormField) {

+            super(fieldSource, FieldInfo.DISPLAY, modelFormField);

+            this.alsoHidden = true;

+            this.currency = FlexibleStringExpander.getInstance("");

+            this.date = FlexibleStringExpander.getInstance("");

+            this.defaultValue = FlexibleStringExpander.getInstance("");

+            this.description = FlexibleStringExpander.getInstance("");

+            this.imageLocation = FlexibleStringExpander.getInstance("");

+            this.inPlaceEditor = null;

+            this.size = "";

+            this.type = "";

+        }

+

+        public DisplayField(ModelFormField modelFormField) {

+            super(FieldInfo.SOURCE_EXPLICIT, FieldInfo.DISPLAY, modelFormField);

+            this.alsoHidden = true;

+            this.currency = FlexibleStringExpander.getInstance("");

+            this.date = FlexibleStringExpander.getInstance("");

+            this.defaultValue = FlexibleStringExpander.getInstance("");

+            this.description = FlexibleStringExpander.getInstance("");

+            this.imageLocation = FlexibleStringExpander.getInstance("");

+            this.inPlaceEditor = null;

+            this.size = "";

+            this.type = "";

+        }

+

+        @Override

+        public void accept(ModelFieldVisitor visitor) throws Exception {

+            visitor.visit(this);

+        }

+

+        @Override

+        public FieldInfo copy(ModelFormField modelFormField) {

+            return new DisplayField(this, modelFormField);

+        }

+

+        public boolean getAlsoHidden() {

+            return alsoHidden;

+        }

+

+        public FlexibleStringExpander getCurrency() {

+            return currency;

+        }

+

+        public FlexibleStringExpander getDate() {

+            return date;

+        }

+

+        public FlexibleStringExpander getDefaultValue() {

+            return defaultValue;

+        }

+

+        public String getDefaultValue(Map<String, Object> context) {

+            if (this.defaultValue != null) {

+                return this.defaultValue.expandString(context);

+            } else {

+                return "";

+            }

+        }

+

+        public FlexibleStringExpander getDescription() {

+            return description;

+        }

+

+        public String getDescription(Map<String, Object> context) {

+            String retVal = null;

+            if (UtilValidate.isNotEmpty(this.description))

+                retVal = this.description.expandString(context);

+            else

+                retVal = getModelFormField().getEntry(context);

+

+            if (UtilValidate.isEmpty(retVal)) {

+                retVal = this.getDefaultValue(context);

+            } else if ("currency".equals(type)) {

+                retVal = retVal.replaceAll("&nbsp;", " "); // FIXME : encoding currency is a problem for some locale, we should not have any &nbsp; in retVal other case may arise in future...

+                Locale locale = (Locale) context.get("locale");

+                if (locale == null)

+                    locale = Locale.getDefault();

+                String isoCode = null;

+                if (UtilValidate.isNotEmpty(this.currency))

+                    isoCode = this.currency.expandString(context);

+

+                try {

+                    BigDecimal parsedRetVal = (BigDecimal) ObjectType.simpleTypeConvert(retVal, "BigDecimal", null, null, locale,

+                            true);

+                    retVal = UtilFormatOut.formatCurrency(parsedRetVal, isoCode, locale, 10); // we set the max to 10 digits as an hack to not round numbers in the ui

+                } catch (GeneralException e) {

+                    String errMsg = "Error formatting currency value [" + retVal + "]: " + e.toString();

+                    Debug.logError(e, errMsg, module);

+                    throw new IllegalArgumentException(errMsg);

+                }

+            } else if ("date".equals(this.type) && retVal.length() > 10) {

+                Locale locale = (Locale) context.get("locale");

+                if (locale == null) {

+                    locale = Locale.getDefault();

+                }

+

+                StringToTimestamp stringToTimestamp = new DateTimeConverters.StringToTimestamp();

+                Timestamp timestamp = null;

+                try {

+                    timestamp = stringToTimestamp.convert(retVal);

+                    Date date = new Date(timestamp.getTime());

+

+                    DateFormat dateFormatter = DateFormat.getDateInstance(DateFormat.SHORT, locale);

+                    retVal = dateFormatter.format(date);

+                } catch (ConversionException e) {

+                    String errMsg = "Error formatting date using default instead [" + retVal + "]: " + e.toString();

+                    Debug.logError(e, errMsg, module);

+                    // create default date value from timestamp string

+                    retVal = retVal.substring(0, 10);

+                }

+

+            } else if ("date-time".equals(this.type) && retVal.length() > 16) {

+                Locale locale = (Locale) context.get("locale");

+                TimeZone timeZone = (TimeZone) context.get("timeZone");

+                if (locale == null) {

+                    locale = Locale.getDefault();

+                }

+                if (timeZone == null) {

+                    timeZone = TimeZone.getDefault();

+                }

+

+                StringToTimestamp stringToTimestamp = new DateTimeConverters.StringToTimestamp();

+                Timestamp timestamp = null;

+                try {

+                    timestamp = stringToTimestamp.convert(retVal);

+                    Date date = new Date(timestamp.getTime());

+

+                    DateFormat dateFormatter = UtilDateTime.toDateTimeFormat(null, timeZone, locale);

+                    retVal = dateFormatter.format(date);

+                } catch (ConversionException e) {

+                    String errMsg = "Error formatting date/time using default instead [" + retVal + "]: " + e.toString();

+                    Debug.logError(e, errMsg, module);

+                    // create default date/time value from timestamp string

+                    retVal = retVal.substring(0, 16);

+                }

+            } else if ("accounting-number".equals(this.type)) {

+                Locale locale = (Locale) context.get("locale");

+                if (locale == null) {

+                    locale = Locale.getDefault();

+                }

+                try {

+                    Double parsedRetVal = (Double) ObjectType.simpleTypeConvert(retVal, "Double", null, locale, false);

+                    String template = UtilProperties.getPropertyValue("arithmetic", "accounting-number.format",

+                            "#,##0.00;(#,##0.00)");

+                    retVal = UtilFormatOut.formatDecimalNumber(parsedRetVal.doubleValue(), template, locale);

+                } catch (GeneralException e) {

+                    String errMsg = "Error formatting number [" + retVal + "]: " + e.toString();

+                    Debug.logError(e, errMsg, module);

+                    throw new IllegalArgumentException(errMsg);

+                }

+            }

+            if (UtilValidate.isNotEmpty(this.description) && retVal != null && this.getModelFormField().getEncodeOutput()) {

+                UtilCodec.SimpleEncoder simpleEncoder = (UtilCodec.SimpleEncoder) context.get("simpleEncoder");

+                if (simpleEncoder != null) {

+                    retVal = simpleEncoder.encode(retVal);

+                }

+            }

+            return retVal;

+        }

+

+        public FlexibleStringExpander getImageLocation() {

+            return imageLocation;

+        }

+

+        public String getImageLocation(Map<String, Object> context) {

+            if (this.imageLocation != null)

+                return this.imageLocation.expandString(context);

+            return "";

+        }

+

+        public InPlaceEditor getInPlaceEditor() {

+            return this.inPlaceEditor;

+        }

+

+        public String getSize() {

+            return this.size;

+        }

+

+        public String getType() {

+            return this.type;

+        }

+

+        @Override

+        public void renderFieldString(Appendable writer, Map<String, Object> context, FormStringRenderer formStringRenderer)

+                throws IOException {

+            formStringRenderer.renderDisplayField(writer, context, this);

+        }

+    }

+

+    /**

+     * Models the &lt;drop-down&gt; element.

+     * 

+     * @see <code>widget-form.xsd</code>

+     */

+    public static class DropDownField extends FieldInfoWithOptions {

+        private final boolean allowEmpty;

+        private final boolean allowMulti;

+        private final AutoComplete autoComplete;

+        private final String current;

+        private final FlexibleStringExpander currentDescription;

+        private final int otherFieldSize;

+        private final String size;

+        private final SubHyperlink subHyperlink;

+        private final String textSize;

+

+        private DropDownField(DropDownField original, ModelFormField modelFormField) {

+            super(original, modelFormField);

+            this.allowEmpty = original.allowEmpty;

+            this.allowMulti = original.allowMulti;

+            this.autoComplete = original.autoComplete;

+            this.current = original.current;

+            this.currentDescription = original.currentDescription;

+            this.otherFieldSize = original.otherFieldSize;

+            this.size = original.size;

+            if (original.subHyperlink != null) {

+                this.subHyperlink = new SubHyperlink(original.subHyperlink, modelFormField);

+            } else {

+                this.subHyperlink = null;

+            }

+            this.textSize = original.textSize;

+        }

+

+        public DropDownField(Element element, ModelFormField modelFormField) {

+            super(element, modelFormField);

+            this.allowEmpty = "true".equals(element.getAttribute("allow-empty"));

+            this.allowMulti = "true".equals(element.getAttribute("allow-multiple"));

+            Element autoCompleteElement = UtilXml.firstChildElement(element, "auto-complete");

+            if (autoCompleteElement != null) {

+                this.autoComplete = new AutoComplete(autoCompleteElement);

+            } else {

+                this.autoComplete = null;

+            }

+            this.current = element.getAttribute("current");

+            this.currentDescription = FlexibleStringExpander.getInstance(element.getAttribute("current-description"));

+            int otherFieldSize = 0;

+            String sizeStr = element.getAttribute("other-field-size");

+            if (!sizeStr.isEmpty()) {

+                try {

+                    otherFieldSize = Integer.parseInt(sizeStr);

+                } catch (Exception e) {

+                    Debug.logError("Could not parse the size value of the text element: [" + sizeStr

+                            + "], setting to the default of 0", module);

+                }

+            }

+            this.otherFieldSize = otherFieldSize;

+            String size = element.getAttribute("size");

+            if (size.isEmpty()) {

+                size = "1";

+            }

+            this.size = size;

+            Element subHyperlinkElement = UtilXml.firstChildElement(element, "sub-hyperlink");

+            if (subHyperlinkElement != null) {

+                this.subHyperlink = new SubHyperlink(subHyperlinkElement, this.getModelFormField());

+            } else {

+                this.subHyperlink = null;

+            }

+            String textSize = element.getAttribute("text-size");

+            if (textSize.isEmpty()) {

+                textSize = "0";

+            }

+            this.textSize = textSize;

+        }

+

+        public DropDownField(int fieldSource, List<OptionSource> optionSources) {

+            super(fieldSource, FieldInfo.DROP_DOWN, optionSources);

+            this.allowEmpty = false;

+            this.allowMulti = false;

+            this.autoComplete = null;

+            this.current = "";

+            this.currentDescription = FlexibleStringExpander.getInstance("");

+            this.otherFieldSize = 0;

+            this.size = "1";

+            this.subHyperlink = null;

+            this.textSize = "0";

+        }

+

+        public DropDownField(int fieldSource, ModelFormField modelFormField) {

+            super(fieldSource, FieldInfo.DROP_DOWN, modelFormField);

+            this.allowEmpty = false;

+            this.allowMulti = false;

+            this.autoComplete = null;

+            this.current = "";

+            this.currentDescription = FlexibleStringExpander.getInstance("");

+            this.otherFieldSize = 0;

+            this.size = "1";

+            this.subHyperlink = null;

+            this.textSize = "0";

+        }

+

+        public DropDownField(ModelFormField modelFormField) {

+            super(FieldInfo.SOURCE_EXPLICIT, FieldInfo.DROP_DOWN, modelFormField);

+            this.allowEmpty = false;

+            this.allowMulti = false;

+            this.autoComplete = null;

+            this.current = "";

+            this.currentDescription = FlexibleStringExpander.getInstance("");

+            this.otherFieldSize = 0;

+            this.size = "1";

+            this.subHyperlink = null;

+            this.textSize = "0";

+        }

+

+        @Override

+        public void accept(ModelFieldVisitor visitor) throws Exception {

+            visitor.visit(this);

+        }

+

+        @Override

+        public FieldInfo copy(ModelFormField modelFormField) {

+            return new DropDownField(this, modelFormField);

+        }

+

+        public boolean getAllowMulti() {

+            return allowMulti;

+        }

+

+        public AutoComplete getAutoComplete() {

+            return this.autoComplete;

+        }

+

+        public String getCurrent() {

+            if (UtilValidate.isEmpty(this.current))

+                return "first-in-list";

+            return this.current;

+        }

+

+        public FlexibleStringExpander getCurrentDescription() {

+            return currentDescription;

+        }

+

+        public String getCurrentDescription(Map<String, Object> context) {

+            if (this.currentDescription == null)

+                return null;

+            return this.currentDescription.expandString(context);

+        }

+

+        public int getOtherFieldSize() {

+            return this.otherFieldSize;

+        }

+

+        /**

+         * Get the name to use for the parameter for this field in the form interpreter.

+         * For HTML forms this is the request parameter name.

+         * @param context the context

+         * @return returns the name to use for the parameter for this field in the form interpreter.

+         */

+        public String getParameterNameOther(Map<String, Object> context) {

+            String baseName;

+            if (UtilValidate.isNotEmpty(getModelFormField().parameterName))

+                baseName = getModelFormField().parameterName;

+            else

+                baseName = getModelFormField().name;

+

+            baseName += "_OTHER";

+            Integer itemIndex = (Integer) context.get("itemIndex");

+            if (itemIndex != null && "multi".equals(getModelFormField().modelForm.getType())) {

+                return baseName + getModelFormField().modelForm.getItemIndexSeparator() + itemIndex.intValue();

+            } else {

+                return baseName;

+            }

+        }

+

+        public String getSize() {

+            return this.size;

+        }

+

+        public SubHyperlink getSubHyperlink() {

+            return this.subHyperlink;

+        }

+

+        public String getTextSize() {

+            return this.textSize;

+        }

+

+        public boolean getAllowEmpty() {

+            return this.allowEmpty;

+        }

+

+        public boolean getAllowMultiple() {

+            return this.allowMulti;

+        }

+

+        @Override

+        public void renderFieldString(Appendable writer, Map<String, Object> context, FormStringRenderer formStringRenderer)

+                throws IOException {

+            formStringRenderer.renderDropDownField(writer, context, this);

+        }

+    }

+

+    /**

+     * Models the &lt;entity-options&gt; element.

+     * 

+     * @see <code>widget-form.xsd</code>

+     */

+    public static class EntityOptions extends OptionSource {

+        private final boolean cache;

+        private final List<EntityFinderUtil.ConditionExpr> constraintList;

+        private final FlexibleStringExpander description;

+        private final String entityName;

+        private final String filterByDate;

+        private final String keyFieldName;

+        private final List<String> orderByList;

+

+        public EntityOptions(Element entityOptionsElement, ModelFormField modelFormField) {

+            super(modelFormField);

+            this.cache = !"false".equals(entityOptionsElement.getAttribute("cache"));

+            List<? extends Element> constraintElements = UtilXml.childElementList(entityOptionsElement, "entity-constraint");

+            if (!constraintElements.isEmpty()) {

+                List<EntityFinderUtil.ConditionExpr> constraintList = new ArrayList<EntityFinderUtil.ConditionExpr>(

+                        constraintElements.size());

+                for (Element constraintElement : constraintElements) {

+                    constraintList.add(new EntityFinderUtil.ConditionExpr(constraintElement));

+                }

+                this.constraintList = Collections.unmodifiableList(constraintList);

+            } else {

+                this.constraintList = Collections.emptyList();

+            }

+            this.description = FlexibleStringExpander.getInstance(entityOptionsElement.getAttribute("description"));

+            this.entityName = entityOptionsElement.getAttribute("entity-name");

+            this.filterByDate = entityOptionsElement.getAttribute("filter-by-date");

+            this.keyFieldName = entityOptionsElement.getAttribute("key-field-name");

+            List<? extends Element> orderByElements = UtilXml.childElementList(entityOptionsElement, "entity-order-by");

+            if (!orderByElements.isEmpty()) {

+                List<String> orderByList = new ArrayList<String>(orderByElements.size());

+                for (Element orderByElement : orderByElements) {

+                    orderByList.add(orderByElement.getAttribute("field-name"));

+                }

+                this.orderByList = Collections.unmodifiableList(orderByList);

+            } else {

+                this.orderByList = Collections.emptyList();

+            }

+        }

+

+        private EntityOptions(EntityOptions original, ModelFormField modelFormField) {

+            super(modelFormField);

+            this.cache = original.cache;

+            this.constraintList = original.constraintList;

+            this.description = original.description;

+            this.entityName = original.entityName;

+            this.filterByDate = original.filterByDate;

+            this.keyFieldName = original.keyFieldName;

+            this.orderByList = original.orderByList;

+        }

+

+        public EntityOptions(ModelFormField modelFormField) {

+            super(modelFormField);

+            this.cache = true;

+            this.constraintList = Collections.emptyList();

+            this.description = FlexibleStringExpander.getInstance("");

+            this.entityName = "";

+            this.filterByDate = "";

+            this.keyFieldName = "";

+            this.orderByList = Collections.emptyList();

+        }

+

+        @Override

+        public void addOptionValues(List<OptionValue> optionValues, Map<String, Object> context, Delegator delegator) {

+            // first expand any conditions that need expanding based on the current context

+            EntityCondition findCondition = null;

+            if (UtilValidate.isNotEmpty(this.constraintList)) {

+                List<EntityCondition> expandedConditionList = new LinkedList<EntityCondition>();

+                for (EntityFinderUtil.Condition condition : constraintList) {

+                    ModelEntity modelEntity = delegator.getModelEntity(this.entityName);

+                    if (modelEntity == null) {

+                        throw new IllegalArgumentException("Error in entity-options: could not find entity [" + this.entityName

+                                + "]");

+                    }

+                    EntityCondition createdCondition = condition.createCondition(context, modelEntity,

+                            delegator.getModelFieldTypeReader(modelEntity));

+                    if (createdCondition != null) {

+                        expandedConditionList.add(createdCondition);

+                    }

+                }

+                findCondition = EntityCondition.makeCondition(expandedConditionList);

+            }

+

+            try {

+                Locale locale = UtilMisc.ensureLocale(context.get("locale"));

+

+                List<GenericValue> values = null;

+                values = delegator.findList(this.entityName, findCondition, null, this.orderByList, null, this.cache);

+

+                // filter-by-date if requested

+                if ("true".equals(this.filterByDate)) {

+                    values = EntityUtil.filterByDate(values, true);

+                } else if (!"false".equals(this.filterByDate)) {

+                    // not explicitly true or false, check to see if has fromDate and thruDate, if so do the filter

+                    ModelEntity modelEntity = delegator.getModelEntity(this.entityName);

+                    if (modelEntity != null && modelEntity.isField("fromDate") && modelEntity.isField("thruDate")) {

+                        values = EntityUtil.filterByDate(values, true);

+                    }

+                }

+

+                for (GenericValue value : values) {

+                    // add key and description with string expansion, ie expanding ${} stuff, passing locale explicitly to expand value string because it won't be found in the Entity

+                    MapStack<String> localContext = MapStack.create(context);

+                    // Rendering code might try to modify the GenericEntity instance,

+                    // so we make a copy of it.

+                    Map<String, Object> genericEntityClone = UtilGenerics.cast(value.clone());

+                    localContext.push(genericEntityClone);

+

+                    // expand with the new localContext, which is locale aware

+                    String optionDesc = this.description.expandString(localContext, locale);

+

+                    Object keyFieldObject = value.get(this.getKeyFieldName());

+                    if (keyFieldObject == null) {

+                        throw new IllegalArgumentException(

+                                "The entity-options identifier (from key-name attribute, or default to the field name) ["

+                                        + this.getKeyFieldName() + "], may not be a valid key field name for the entity ["

+                                        + this.entityName + "].");

+                    }

+                    String keyFieldValue = keyFieldObject.toString();

+                    optionValues.add(new OptionValue(keyFieldValue, optionDesc));

+                }

+            } catch (GenericEntityException e) {

+                Debug.logError(e, "Error getting entity options in form", module);

+            }

+        }

+

+        @Override

+        public OptionSource copy(ModelFormField modelFormField) {

+            return new EntityOptions(this, modelFormField);

+        }

+

+        public boolean getCache() {

+            return cache;

+        }

+

+        public List<EntityFinderUtil.ConditionExpr> getConstraintList() {

+            return constraintList;

+        }

+

+        public FlexibleStringExpander getDescription() {

+            return description;

+        }

+

+        public String getEntityName() {

+            return entityName;

+        }

+

+        public String getFilterByDate() {

+            return filterByDate;

+        }

+

+        public String getKeyFieldName() {

+            if (UtilValidate.isNotEmpty(this.keyFieldName))

+                return this.keyFieldName;

+            return getModelFormField().getFieldName(); // get the modelFormField fieldName

+        }

+

+        public List<String> getOrderByList() {

+            return orderByList;

+        }

+    }

+

+    public static abstract class FieldInfoWithOptions extends FieldInfo {

+

+        public static String getDescriptionForOptionKey(String key, List<OptionValue> allOptionValues) {

+            if (UtilValidate.isEmpty(key))

+                return "";

+

+            if (UtilValidate.isEmpty(allOptionValues))

+                return key;

+

+            for (OptionValue optionValue : allOptionValues) {

+                if (key.equals(optionValue.getKey())) {

+                    return optionValue.getDescription();

+                }

+            }

+

+            // if we get here we didn't find a match, just return the key

+            return key;

+        }

+

+        private final FlexibleStringExpander noCurrentSelectedKey;

+        private final List<OptionSource> optionSources;

+

+        public FieldInfoWithOptions(Element element, ModelFormField modelFormField) {

+            super(element, modelFormField);

+            this.noCurrentSelectedKey = FlexibleStringExpander.getInstance(element.getAttribute("no-current-selected-key"));

+            // read all option and entity-options sub-elements, maintaining order

+            ArrayList<OptionSource> optionSources = new ArrayList<OptionSource>();

+            List<? extends Element> childElements = UtilXml.childElementList(element);

+            if (childElements.size() > 0) {

+                for (Element childElement : childElements) {

+                    if ("option".equals(childElement.getTagName())) {

+                        optionSources.add(new SingleOption(childElement, modelFormField));

+                    } else if ("list-options".equals(childElement.getTagName())) {

+                        optionSources.add(new ListOptions(childElement, modelFormField));

+                    } else if ("entity-options".equals(childElement.getTagName())) {

+                        optionSources.add(new EntityOptions(childElement, modelFormField));

+                    }

+                }

+            } else {

+                // this must be added or the multi-form select box options would not show up

+                optionSources.add(new SingleOption("Y", " ", modelFormField));

+            }

+            optionSources.trimToSize();

+            this.optionSources = Collections.unmodifiableList(optionSources);

+        }

+

+        // Copy constructor.

+        protected FieldInfoWithOptions(FieldInfoWithOptions original, ModelFormField modelFormField) {

+            super(original.getFieldSource(), original.getFieldType(), modelFormField);

+            this.noCurrentSelectedKey = original.noCurrentSelectedKey;

+            if (original.optionSources.isEmpty()) {

+                this.optionSources = original.optionSources;

+            } else {

+                List<OptionSource> optionSources = new ArrayList<OptionSource>(original.optionSources.size());

+                for (OptionSource source : original.optionSources) {

+                    optionSources.add(source.copy(modelFormField));

+                }

+                this.optionSources = Collections.unmodifiableList(optionSources);

+            }

+        }

+

+        protected FieldInfoWithOptions(int fieldSource, int fieldType, List<OptionSource> optionSources) {

+            super(fieldSource, fieldType, null);

+            this.noCurrentSelectedKey = FlexibleStringExpander.getInstance("");

+            this.optionSources = Collections.unmodifiableList(new ArrayList<OptionSource>(optionSources));

+        }

+

+        public FieldInfoWithOptions(int fieldSource, int fieldType, ModelFormField modelFormField) {

+            super(fieldSource, fieldType, modelFormField);

+            this.noCurrentSelectedKey = FlexibleStringExpander.getInstance("");

+            this.optionSources = Collections.emptyList();

+        }

+

+        public List<OptionValue> getAllOptionValues(Map<String, Object> context, Delegator delegator) {

+            List<OptionValue> optionValues = new LinkedList<OptionValue>();

+            for (OptionSource optionSource : this.optionSources) {

+                optionSource.addOptionValues(optionValues, context, delegator);

+            }

+            return optionValues;

+        }

+

+        public FlexibleStringExpander getNoCurrentSelectedKey() {

+            return noCurrentSelectedKey;

+        }

+

+        public String getNoCurrentSelectedKey(Map<String, Object> context) {

+            return this.noCurrentSelectedKey.expandString(context);

+        }

+

+        public List<OptionSource> getOptionSources() {

+            return optionSources;

+        }

+    }

+

+    /**

+     * Models the &lt;file&gt; element.

+     * 

+     * @see <code>widget-form.xsd</code>

+     */

+    public static class FileField extends TextField {

+

+        public FileField(Element element, ModelFormField modelFormField) {

+            super(element, modelFormField);

+        }

+

+        private FileField(FileField original, ModelFormField modelFormField) {

+            super(original, modelFormField);

+        }

+

+        public FileField(int fieldSource, ModelFormField modelFormField) {

+            super(fieldSource, modelFormField);

+        }

+

+        @Override

+        public void accept(ModelFieldVisitor visitor) throws Exception {

+            visitor.visit(this);

+        }

+

+        @Override

+        public FieldInfo copy(ModelFormField modelFormField) {

+            return new FileField(this, modelFormField);

+        }

+

+        @Override

+        public void renderFieldString(Appendable writer, Map<String, Object> context, FormStringRenderer formStringRenderer)

+                throws IOException {

+            formStringRenderer.renderFileField(writer, context, this);

+        }

+    }

+

+    /**

+     * Models the &lt;hidden&gt; element.

+     * 

+     * @see <code>widget-form.xsd</code>

+     */

+    public static class HiddenField extends FieldInfo {

+        private final FlexibleStringExpander value;

+

+        public HiddenField(Element element, ModelFormField modelFormField) {

+            super(element, modelFormField);

+            this.value = FlexibleStringExpander.getInstance(element.getAttribute("value"));

+        }

+

+        private HiddenField(HiddenField original, ModelFormField modelFormField) {

+            super(original.getFieldSource(), original.getFieldType(), modelFormField);

+            this.value = original.value;

+        }

+

+        public HiddenField(int fieldSource, ModelFormField modelFormField) {

+            super(fieldSource, FieldInfo.HIDDEN, modelFormField);

+            this.value = FlexibleStringExpander.getInstance("");

+        }

+

+        public HiddenField(ModelFormField modelFormField) {

+            super(FieldInfo.SOURCE_EXPLICIT, FieldInfo.HIDDEN, modelFormField);

+            this.value = FlexibleStringExpander.getInstance("");

+        }

+

+        @Override

+        public void accept(ModelFieldVisitor visitor) throws Exception {

+            visitor.visit(this);

+        }

+

+        @Override

+        public FieldInfo copy(ModelFormField modelFormField) {

+            return new HiddenField(this, modelFormField);

+        }

+

+        public FlexibleStringExpander getValue() {

+            return value;

+        }

+

+        public String getValue(Map<String, Object> context) {

+            if (UtilValidate.isNotEmpty(this.value)) {

+                String valueEnc = this.value.expandString(context);

+                UtilCodec.SimpleEncoder simpleEncoder = (UtilCodec.SimpleEncoder) context.get("simpleEncoder");

+                if (simpleEncoder != null) {

+                    valueEnc = simpleEncoder.encode(valueEnc);

+                }

+                return valueEnc;

+            } else {

+                return getModelFormField().getEntry(context);

+            }

+        }

+

+        @Override

+        public void renderFieldString(Appendable writer, Map<String, Object> context, FormStringRenderer formStringRenderer)

+                throws IOException {

+            formStringRenderer.renderHiddenField(writer, context, this);

+        }

+    }

+

+    /**

+     * Models the &lt;hyperlink&gt; element.

+     * 

+     * @see <code>widget-form.xsd</code>

+     */

+    public static class HyperlinkField extends FieldInfo {

+

+        private final boolean alsoHidden;

+        private final FlexibleStringExpander confirmationMsgExdr;

+        private final FlexibleStringExpander description;

+        private final boolean requestConfirmation;

+        private final Link link;

+        public HyperlinkField(Element element, ModelFormField modelFormField) {

+            super(element, modelFormField);

+            this.alsoHidden = !"false".equals(element.getAttribute("also-hidden"));

+            this.confirmationMsgExdr = FlexibleStringExpander.getInstance(element.getAttribute("confirmation-message"));

+            this.description = FlexibleStringExpander.getInstance(element.getAttribute("description"));

+            this.requestConfirmation = "true".equals(element.getAttribute("request-confirmation"));

+            this.link = new Link(element);

+        }

+

+        private HyperlinkField(HyperlinkField original, ModelFormField modelFormField) {

+            super(original.getFieldSource(), original.getFieldType(), modelFormField);

+            this.alsoHidden = original.alsoHidden;

+            this.confirmationMsgExdr = original.confirmationMsgExdr;

+            this.description = original.description;

+            this.requestConfirmation = original.requestConfirmation;

+            this.link = original.link;

+        }

+

+        @Override

+        public void accept(ModelFieldVisitor visitor) throws Exception {

+            visitor.visit(this);

+        }

+

+        @Override

+        public FieldInfo copy(ModelFormField modelFormField) {

+            return new HyperlinkField(this, modelFormField);

+        }

+

+        public boolean getAlsoHidden() {

+            return this.alsoHidden;

+        }

+

+        public String getConfirmation(Map<String, Object> context) {

+            String message = getConfirmationMsg(context);

+            if (UtilValidate.isNotEmpty(message))

+                return message;

+            if (getRequestConfirmation()) {

+                String defaultMessage = UtilProperties.getPropertyValue("general", "default.confirmation.message",

+                        "${uiLabelMap.CommonConfirm}");

+                return FlexibleStringExpander.expandString(defaultMessage, context);

+            }

+            return "";

+        }

+

+        public String getAlternate(Map<String, Object> context) {

+            if (link.getImage() != null) {

+                return link.getImage().getAlt(context);

+            }

+            return "";

+        }

+

+        public String getImageTitle(Map<String, Object> context) {

+            if (link.getImage() != null) {

+                return link.getImage().getTitleExdr().expandString(context);

+            }

+            return "";

+        }

+

+        public String getImageLocation(Map<String, Object> context) {

+            if (link.getImage() != null) {

+                return link.getImage().getSrc(context);

+            }

+            return "";

+        }

+

+        public String getConfirmationMsg(Map<String, Object> context) {

+            return this.confirmationMsgExdr.expandString(context);

+        }

+

+        public FlexibleStringExpander getConfirmationMsgExdr() {

+            return confirmationMsgExdr;

+        }

+

+        public FlexibleStringExpander getDescription() {

+            return description;

+        }

+

+        public String getDescription(Map<String, Object> context) {

+            return this.description.expandString(context);

+        }

+

+        public boolean getRequestConfirmation() {

+            return this.requestConfirmation;

+        }

+

+        public Link getLink() {

+            return link;

+        }

+

+        public AutoEntityParameters getAutoEntityParameters() {

+            return link.getAutoEntityParameters();

+        }

+

+        public AutoServiceParameters getAutoServiceParameters() {

+            return link.getAutoServiceParameters();

+        }

+

+        public boolean getEncode() {

+            return link.getEncode();

+        }

+

+        public boolean getFullPath() {

+            return link.getFullPath();

+        }

+

+        public String getHeight() {

+            return link.getHeight();

+        }

+

+        public String getId(Map<String, Object> context) {

+            return link.getId(context);

+        }

+

+        public FlexibleStringExpander getIdExdr() {

+            return link.getIdExdr();

+        }

+

+        public Image getImage() {

+            return link.getImage();

+        }

+

+        public String getLinkType() {

+            return link.getLinkType();

+        }

+

+        public String getName() {

+            return link.getName();

+        }

+

+        public String getName(Map<String, Object> context) {

+            return link.getName(context);

+        }

+

+        public FlexibleStringExpander getNameExdr() {

+            return link.getNameExdr();

+        }

+

+        public List<Parameter> getParameterList() {

+            return link.getParameterList();

+        }

+

+        public Map<String, String> getParameterMap(Map<String, Object> context) {

+            return link.getParameterMap(context);

+        }

+

+        public String getPrefix(Map<String, Object> context) {

+            return link.getPrefix(context);

+        }

+

+        public FlexibleStringExpander getPrefixExdr() {

+            return link.getPrefixExdr();

+        }

+

+        public boolean getSecure() {

+            return link.getSecure();

+        }

+

+        public Integer getSize() {

+            return link.getSize();

+        }

+

+        public String getStyle(Map<String, Object> context) {

+            return link.getStyle(context);

+        }

+

+        public FlexibleStringExpander getStyleExdr() {

+            return link.getStyleExdr();

+        }

+

+        public String getTarget(Map<String, Object> context) {

+            return link.getTarget(context);

+        }

+

+        public FlexibleStringExpander getTargetExdr() {

+            return link.getTargetExdr();

+        }

+

+        public String getTargetWindow(Map<String, Object> context) {

+            return link.getTargetWindow(context);

+        }

+

+        public FlexibleStringExpander getTargetWindowExdr() {

+            return link.getTargetWindowExdr();

+        }

+

+        public String getText(Map<String, Object> context) {

+            return link.getText(context);

+        }

+

+        public FlexibleStringExpander getTextExdr() {

+            return link.getTextExdr();

+        }

+

+        public String getUrlMode() {

+            return link.getUrlMode();

+        }

+

+        public String getWidth() {

+            return link.getWidth();

+        }

+

+        @Override

+        public void renderFieldString(Appendable writer, Map<String, Object> context, FormStringRenderer formStringRenderer)

+                throws IOException {

+            formStringRenderer.renderHyperlinkField(writer, context, this);

+        }

+    }

+

+    /**

+     * Models the &lt;ignored&gt; element.

+     * 

+     * @see <code>widget-form.xsd</code>

+     */

+    public static class IgnoredField extends FieldInfo {

+

+        public IgnoredField(Element element, ModelFormField modelFormField) {

+            super(element, modelFormField);

+        }

+

+        private IgnoredField(IgnoredField original, ModelFormField modelFormField) {

+            super(original.getFieldSource(), original.getFieldType(), modelFormField);

+        }

+

+        public IgnoredField(int fieldSource, ModelFormField modelFormField) {

+            super(fieldSource, FieldInfo.IGNORED, modelFormField);

+        }

+

+        public IgnoredField(ModelFormField modelFormField) {

+            super(FieldInfo.SOURCE_EXPLICIT, FieldInfo.IGNORED, modelFormField);

+        }

+

+        @Override

+        public void accept(ModelFieldVisitor visitor) throws Exception {

+            visitor.visit(this);

+        }

+

+        @Override

+        public FieldInfo copy(ModelFormField modelFormField) {

+            return new IgnoredField(this, modelFormField);

+        }

+

+        @Override

+        public void renderFieldString(Appendable writer, Map<String, Object> context, FormStringRenderer formStringRenderer)

+                throws IOException {

+            formStringRenderer.renderIgnoredField(writer, context, this);

+        }

+    }

+

+    /**

+     * Models the &lt;image&gt; element.

+     * 

+     * @see <code>widget-form.xsd</code>

+     */

+    public static class ImageField extends FieldInfo {

+        private final FlexibleStringExpander alternate;

+        private final FlexibleStringExpander defaultValue;

+        private final FlexibleStringExpander description;

+        private final FlexibleStringExpander style;

+        private final SubHyperlink subHyperlink;

+        private final FlexibleStringExpander value;

+

+        public ImageField(Element element, ModelFormField modelFormField) {

+            super(element, modelFormField);

+            this.alternate = FlexibleStringExpander.getInstance(element.getAttribute("alternate"));

+            this.defaultValue = FlexibleStringExpander.getInstance(element.getAttribute("default-value"));

+            this.description = FlexibleStringExpander.getInstance(element.getAttribute("description"));

+            this.style = FlexibleStringExpander.getInstance(element.getAttribute("style"));

+            Element subHyperlinkElement = UtilXml.firstChildElement(element, "sub-hyperlink");

+            if (subHyperlinkElement != null) {

+                this.subHyperlink = new SubHyperlink(subHyperlinkElement, modelFormField);

+            } else {

+                this.subHyperlink = null;

+            }

+            this.value = FlexibleStringExpander.getInstance(element.getAttribute("value"));

+        }

+

+        public ImageField(ImageField original, ModelFormField modelFormField) {

+            super(original.getFieldSource(), original.getFieldType(), modelFormField);

+            this.alternate = original.alternate;

+            this.defaultValue = original.defaultValue;

+            this.description = original.description;

+            this.style = original.style;

+            if (original.subHyperlink != null) {

+                this.subHyperlink = new SubHyperlink(original.subHyperlink, modelFormField);

+            } else {

+                this.subHyperlink = null;

+            }

+            this.value = original.value;

+        }

+

+        public ImageField(int fieldSource, ModelFormField modelFormField) {

+            super(fieldSource, FieldInfo.IMAGE, modelFormField);

+            this.alternate = FlexibleStringExpander.getInstance("");

+            this.defaultValue = FlexibleStringExpander.getInstance("");

+            this.description = FlexibleStringExpander.getInstance("");

+            this.style = FlexibleStringExpander.getInstance("");

+            this.subHyperlink = null;

+            this.value = FlexibleStringExpander.getInstance("");

+        }

+

+        public ImageField(ModelFormField modelFormField) {

+            this(FieldInfo.SOURCE_EXPLICIT, modelFormField);

+        }

+

+        @Override

+        public void accept(ModelFieldVisitor visitor) throws Exception {

+            visitor.visit(this);

+        }

+

+        @Override

+        public FieldInfo copy(ModelFormField modelFormField) {

+            return new ImageField(this, modelFormField);

+        }

+

+        public FlexibleStringExpander getAlternate() {

+            return alternate;

+        }

+

+        public String getAlternate(Map<String, Object> context) {

+            if (UtilValidate.isNotEmpty(this.alternate))

+                return this.alternate.expandString(context);

+            return "";

+        }

+

+        public FlexibleStringExpander getDefaultValue() {

+            return defaultValue;

+        }

+

+        public String getDefaultValue(Map<String, Object> context) {

+            if (this.defaultValue != null) {

+                return this.defaultValue.expandString(context);

+            } else {

+                return "";

+            }

+        }

+

+        public FlexibleStringExpander getDescription() {

+            return description;

+        }

+

+        public String getDescription(Map<String, Object> context) {

+            if (UtilValidate.isNotEmpty(this.description))

+                return this.description.expandString(context);

+            return "";

+        }

+

+        public FlexibleStringExpander getStyle() {

+            return style;

+        }

+

+        public String getStyle(Map<String, Object> context) {

+            if (UtilValidate.isNotEmpty(this.style))

+                return this.style.expandString(context);

+            return "";

+        }

+

+        public SubHyperlink getSubHyperlink() {

+            return this.subHyperlink;

+        }

+

+        public FlexibleStringExpander getValue() {

+            return value;

+        }

+

+        public String getValue(Map<String, Object> context) {

+            if (UtilValidate.isNotEmpty(this.value))

+                return this.value.expandString(context);

+            return getModelFormField().getEntry(context);

+        }

+

+        @Override

+        public void renderFieldString(Appendable writer, Map<String, Object> context, FormStringRenderer formStringRenderer)

+                throws IOException {

+            formStringRenderer.renderImageField(writer, context, this);

+        }

+    }

+

+    /**

+     * Models the &lt;in-place-editor&gt; element.

+     * 

+     * @see <code>widget-form.xsd</code>

+     */

+    public static class InPlaceEditor {

+        private final String cancelControl;

+        private final String cancelText;

+        private final String clickToEditText;

+        private final String cols;

+        private final Map<FlexibleMapAccessor<Object>, Object> fieldMap;

+        private final String fieldPostCreation;

+        private final String formClassName;

+        private final String highlightColor;

+        private final String highlightEndColor;

+        private final String hoverClassName;

+        private final String htmlResponse;

+        private final String loadingClassName;

+        private final String loadingText;

+        private final String okControl;

+        private final String okText;

+        private final String paramName;

+        private final String rows;

+        private final String savingClassName;

+        private final String savingText;

+        private final String submitOnBlur;

+        private final String textAfterControls;

+        private final String textBeforeControls;

+        private final String textBetweenControls;

+        private final String updateAfterRequestCall;

+        private final FlexibleStringExpander url;

+

+        public InPlaceEditor(Element element) {

+            this.cancelControl = element.getAttribute("cancel-control");

+            this.cancelText = element.getAttribute("cancel-text");

+            this.clickToEditText = element.getAttribute("click-to-edit-text");

+            this.fieldPostCreation = element.getAttribute("field-post-creation");

+            this.formClassName = element.getAttribute("form-class-name");

+            this.highlightColor = element.getAttribute("highlight-color");

+            this.highlightEndColor = element.getAttribute("highlight-end-color");

+            this.hoverClassName = element.getAttribute("hover-class-name");

+            this.htmlResponse = element.getAttribute("html-response");

+            this.loadingClassName = element.getAttribute("loading-class-name");

+            this.loadingText = element.getAttribute("loading-text");

+            this.okControl = element.getAttribute("ok-control");

+            this.okText = element.getAttribute("ok-text");

+            this.paramName = element.getAttribute("param-name");

+            this.savingClassName = element.getAttribute("saving-class-name");

+            this.savingText = element.getAttribute("saving-text");

+            this.submitOnBlur = element.getAttribute("submit-on-blur");

+            this.textBeforeControls = element.getAttribute("text-before-controls");

+            this.textAfterControls = element.getAttribute("text-after-controls");

+            this.textBetweenControls = element.getAttribute("text-between-controls");

+            this.updateAfterRequestCall = element.getAttribute("update-after-request-call");

+            Element simpleElement = UtilXml.firstChildElement(element, "simple-editor");

+            if (simpleElement != null) {

+                this.rows = simpleElement.getAttribute("rows");

+                this.cols = simpleElement.getAttribute("cols");

+            } else {

+                this.rows = "";

+                this.cols = "";

+            }

+            this.fieldMap = EntityFinderUtil.makeFieldMap(element);

+            this.url = FlexibleStringExpander.getInstance(element.getAttribute("url"));

+        }

+

+        public String getCancelControl() {

+            return this.cancelControl;

+        }

+

+        public String getCancelText() {

+            return this.cancelText;

+        }

+

+        public String getClickToEditText() {

+            return this.clickToEditText;

+        }

+

+        public String getCols() {

+            return this.cols;

+        }

+

+        public Map<FlexibleMapAccessor<Object>, Object> getFieldMap() {

+            return fieldMap;

+        }

+

+        public Map<String, Object> getFieldMap(Map<String, Object> context) {

+            Map<String, Object> inPlaceEditorContext = new HashMap<String, Object>();

+            EntityFinderUtil.expandFieldMapToContext(this.fieldMap, context, inPlaceEditorContext);

+            return inPlaceEditorContext;

+        }

+

+        public String getFieldPostCreation() {

+            return this.fieldPostCreation;

+        }

+

+        public String getFormClassName() {

+            return this.formClassName;

+        }

+

+        public String getHighlightColor() {

+            return this.highlightColor;

+        }

+

+        public String getHighlightEndColor() {

+            return this.highlightEndColor;

+        }

+

+        public String getHoverClassName() {

+            return this.hoverClassName;

+        }

+

+        public String getHtmlResponse() {

+            return this.htmlResponse;

+        }

+

+        public String getLoadingClassName() {

+            return this.loadingClassName;

+        }

+

+        public String getLoadingText() {

+            return this.loadingText;

+        }

+

+        public String getOkControl() {

+            return this.okControl;

+        }

+

+        public String getOkText() {

+            return this.okText;

+        }

+

+        public String getParamName() {

+            return this.paramName;

+        }

+

+        public String getRows() {

+            return this.rows;

+        }

+

+        public String getSavingClassName() {

+            return this.savingClassName;

+        }

+

+        public String getSavingText() {

+            return this.savingText;

+        }

+

+        public String getSubmitOnBlur() {

+            return this.submitOnBlur;

+        }

+

+        public String getTextAfterControls() {

+            return this.textAfterControls;

+        }

+

+        public String getTextBeforeControls() {

+            return this.textBeforeControls;

+        }

+

+        public String getTextBetweenControls() {

+            return this.textBetweenControls;

+        }

+

+        public String getUpdateAfterRequestCall() {

+            return this.updateAfterRequestCall;

+        }

+

+        public FlexibleStringExpander getUrl() {

+            return url;

+        }

+

+        public String getUrl(Map<String, Object> context) {

+            if (this.url != null) {

+                return this.url.expandString(context);

+            } else {

+                return "";

+            }

+        }

+    }

+

+    /**

+     * Models the &lt;list-options&gt; element.

+     * 

+     * @see <code>widget-form.xsd</code>

+     */

+    public static class ListOptions extends OptionSource {

+        private final FlexibleStringExpander description;

+        private final FlexibleMapAccessor<Object> keyAcsr;

+        private final FlexibleMapAccessor<List<? extends Object>> listAcsr;

+        private final String listEntryName;

+

+        public ListOptions(Element optionElement, ModelFormField modelFormField) {

+            super(modelFormField);

+            this.listEntryName = optionElement.getAttribute("list-entry-name");

+            this.keyAcsr = FlexibleMapAccessor.getInstance(optionElement.getAttribute("key-name"));

+            this.listAcsr = FlexibleMapAccessor.getInstance(optionElement.getAttribute("list-name"));

+            this.description = FlexibleStringExpander.getInstance(optionElement.getAttribute("description"));

+        }

+

+        private ListOptions(ListOptions original, ModelFormField modelFormField) {

+            super(modelFormField);

+            this.listAcsr = original.listAcsr;

+            this.listEntryName = original.listEntryName;

+            this.keyAcsr = original.keyAcsr;

+            this.description = original.description;

+        }

+

+        public ListOptions(String listName, String listEntryName, String keyName, String description,

+                ModelFormField modelFormField) {

+            super(modelFormField);

+            this.listAcsr = FlexibleMapAccessor.getInstance(listName);

+            this.listEntryName = listEntryName;

+            this.keyAcsr = FlexibleMapAccessor.getInstance(keyName);

+            this.description = FlexibleStringExpander.getInstance(description);

+        }

+

+        @Override

+        public void addOptionValues(List<OptionValue> optionValues, Map<String, Object> context, Delegator delegator) {

+            List<? extends Object> dataList = UtilGenerics.checkList(this.listAcsr.get(context));

+            if (dataList != null && dataList.size() != 0) {

+                for (Object data : dataList) {

+                    Map<String, Object> localContext = new HashMap<String, Object>();

+                    localContext.putAll(context);

+                    if (UtilValidate.isNotEmpty(this.listEntryName)) {

+                        localContext.put(this.listEntryName, data);

+                    } else {

+                        Map<String, Object> dataMap = UtilGenerics.checkMap(data);

+                        localContext.putAll(dataMap);

+                    }

+                    Object keyObj = keyAcsr.get(localContext);

+                    String key = null;

+                    if (keyObj instanceof String) {

+                        key = (String) keyObj;

+                    } else {

+                        try {

+                            key = (String) ObjectType.simpleTypeConvert(keyObj, "String", null, null);

+                        } catch (GeneralException e) {

+                            String errMsg = "Could not convert field value for the field: [" + this.keyAcsr.toString()

+                                    + "] to String for the value [" + keyObj + "]: " + e.toString();

+                            Debug.logError(e, errMsg, module);

+                        }

+                    }

+                    optionValues.add(new OptionValue(key, description.expandString(localContext)));

+                }

+            }

+        }

+

+        @Override

+        public OptionSource copy(ModelFormField modelFormField) {

+            return new ListOptions(this, modelFormField);

+        }

+

+        public FlexibleStringExpander getDescription() {

+            return description;

+        }

+

+        public FlexibleMapAccessor<Object> getKeyAcsr() {

+            return keyAcsr;

+        }

+

+        public FlexibleMapAccessor<List<? extends Object>> getListAcsr() {

+            return listAcsr;

+        }

+

+        public String getListEntryName() {

+            return listEntryName;

+        }

+    }

+

+    /**

+     * Models the &lt;lookup&gt; element.

+     * 

+     * @see <code>widget-form.xsd</code>

+     */

+    public static class LookupField extends TextField {

+        private final String descriptionFieldName;

+        private final String fadeBackground;

+        private final FlexibleStringExpander formName;

+        private final String initiallyCollapsed;

+        private final String lookupHeight;

+        private final String lookupPosition;

+        private final String lookupPresentation;

+        private final String lookupWidth;

+        private final String showDescription;

+        private final String targetParameter;

+

+        public LookupField(Element element, ModelFormField modelFormField) {

+            super(element, modelFormField);

+            this.descriptionFieldName = element.getAttribute("description-field-name");

+            this.fadeBackground = element.getAttribute("fade-background");

+            this.formName = FlexibleStringExpander.getInstance(element.getAttribute("target-form-name"));

+            this.initiallyCollapsed = element.getAttribute("initially-collapsed");

+            this.lookupHeight = element.getAttribute("height");

+            this.lookupPosition = element.getAttribute("position");

+            this.lookupPresentation = element.getAttribute("presentation");

+            this.lookupWidth = element.getAttribute("width");

+            this.showDescription = element.getAttribute("show-description");

+            this.targetParameter = element.getAttribute("target-parameter");

+        }

+

+        public LookupField(int fieldSource, ModelFormField modelFormField) {

+            super(fieldSource, modelFormField);

+            this.descriptionFieldName = "";

+            this.fadeBackground = "";

+            this.formName = FlexibleStringExpander.getInstance("");

+            this.initiallyCollapsed = "";

+            this.lookupHeight = "";

+            this.lookupPosition = "";

+            this.lookupPresentation = "";

+            this.lookupWidth = "";

+            this.showDescription = "";

+            this.targetParameter = "";

+        }

+

+        public LookupField(LookupField original, ModelFormField modelFormField) {

+            super(original, modelFormField);

+            this.descriptionFieldName = original.descriptionFieldName;

+            this.fadeBackground = original.fadeBackground;

+            this.formName = original.formName;

+            this.initiallyCollapsed = original.initiallyCollapsed;

+            this.lookupHeight = original.lookupHeight;

+            this.lookupPosition = original.lookupPosition;

+            this.lookupPresentation = original.lookupPresentation;

+            this.lookupWidth = original.lookupWidth;

+            this.showDescription = original.showDescription;

+            this.targetParameter = original.targetParameter;

+        }

+

+        @Override

+        public void accept(ModelFieldVisitor visitor) throws Exception {

+            visitor.visit(this);

+        }

+

+        @Override

+        public FieldInfo copy(ModelFormField modelFormField) {

+            return new LookupField(this, modelFormField);

+        }

+

+        public String getDescriptionFieldName() {

+            return this.descriptionFieldName;

+        }

+

+        public String getFadeBackground() {

+            return this.fadeBackground;

+        }

+

+        public FlexibleStringExpander getFormName() {

+            return formName;

+        }

+

+        public String getFormName(Map<String, Object> context) {

+            return this.formName.expandString(context);

+        }

+

+        //initially-collapsed status

+        public boolean getInitiallyCollapsed() {

+            return "true".equals(this.initiallyCollapsed);

+        }

+

+        public String getLookupHeight() {

+            return this.lookupHeight;

+        }

+

+        public String getLookupPosition() {

+            return this.lookupPosition;

+        }

+

+        public String getLookupPresentation() {

+            return this.lookupPresentation;

+        }

+

+        public String getLookupWidth() {

+            return this.lookupWidth;

+        }

+

+        public Boolean getShowDescription() {

+            return UtilValidate.isEmpty(this.showDescription) ? null : "true".equals(this.showDescription);

+        }

+

+        public String getTargetParameter() {

+            return targetParameter;

+        }

+

+        public List<String> getTargetParameterList() {

+            List<String> paramList = new LinkedList<String>();

+            if (UtilValidate.isNotEmpty(this.targetParameter)) {

+                StringTokenizer stk = new StringTokenizer(this.targetParameter, ", ");

+                while (stk.hasMoreTokens()) {

+                    paramList.add(stk.nextToken());

+                }

+            }

+            return paramList;

+        }

+

+        @Override

+        public void renderFieldString(Appendable writer, Map<String, Object> context, FormStringRenderer formStringRenderer)

+                throws IOException {

+            formStringRenderer.renderLookupField(writer, context, this);

+        }

+    }

+

+    public static abstract class OptionSource {

+

+        private final ModelFormField modelFormField;

+

+        protected OptionSource(ModelFormField modelFormField) {

+            this.modelFormField = modelFormField;

+        }

+

+        public abstract void addOptionValues(List<OptionValue> optionValues, Map<String, Object> context, Delegator delegator);

+

+        public abstract OptionSource copy(ModelFormField modelFormField);

+

+        public ModelFormField getModelFormField() {

+            return modelFormField;

+        }

+    }

+

+    public static class OptionValue {

+        private final String description;

+        private final String key;

+

+        public OptionValue(String key, String description) {

+            this.key = key;

+            this.description = description;

+        }

+

+        public String getDescription() {

+            return description;

+        }

+

+        public String getKey() {

+            return key;

+        }

+    }

+

+    /**

+     * Models the &lt;password&gt; element.

+     * 

+     * @see <code>widget-form.xsd</code>

+     */

+    public static class PasswordField extends TextField {

+

+        public PasswordField(Element element, ModelFormField modelFormField) {

+            super(element, modelFormField);

+        }

+

+        public PasswordField(int fieldSource, ModelFormField modelFormField) {

+            super(fieldSource, modelFormField);

+        }

+

+        private PasswordField(PasswordField original, ModelFormField modelFormField) {

+            super(original, modelFormField);

+        }

+

+        @Override

+        public void accept(ModelFieldVisitor visitor) throws Exception {

+            visitor.visit(this);

+        }

+

+        @Override

+        public FieldInfo copy(ModelFormField modelFormField) {

+            return new PasswordField(this, modelFormField);

+        }

+

+        @Override

+        public void renderFieldString(Appendable writer, Map<String, Object> context, FormStringRenderer formStringRenderer)

+                throws IOException {

+            formStringRenderer.renderPasswordField(writer, context, this);

+        }

+    }

+

+    /**

+     * Models the &lt;radio&gt; element.

+     * 

+     * @see <code>widget-form.xsd</code>

+     */

+    public static class RadioField extends FieldInfoWithOptions {

+

+        public RadioField(Element element, ModelFormField modelFormField) {

+            super(element, modelFormField);

+        }

+

+        public RadioField(int fieldSource, ModelFormField modelFormField) {

+            super(fieldSource, FieldInfo.RADIO, modelFormField);

+        }

+

+        public RadioField(ModelFormField modelFormField) {

+            super(FieldInfo.SOURCE_EXPLICIT, FieldInfo.RADIO, modelFormField);

+        }

+

+        private RadioField(RadioField original, ModelFormField modelFormField) {

+            super(original, modelFormField);

+        }

+

+        @Override

+        public void accept(ModelFieldVisitor visitor) throws Exception {

+            visitor.visit(this);

+        }

+

+        @Override

+        public FieldInfo copy(ModelFormField modelFormField) {

+            return new RadioField(this, modelFormField);

+        }

+

+        @Override

+        public void renderFieldString(Appendable writer, Map<String, Object> context, FormStringRenderer formStringRenderer)

+                throws IOException {

+            formStringRenderer.renderRadioField(writer, context, this);

+        }

+    }

+

+    /**

+     * Models the &lt;range-find&gt; element.

+     * 

+     * @see <code>widget-form.xsd</code>

+     */

+    public static class RangeFindField extends TextField {

+        private final String defaultOptionFrom;

+        private final String defaultOptionThru;

+

+        public RangeFindField(Element element, ModelFormField modelFormField) {

+            super(element, modelFormField);

+            this.defaultOptionFrom = element.getAttribute("default-option-from");

+            this.defaultOptionThru = element.getAttribute("default-option-thru");

+        }

+

+        public RangeFindField(int fieldSource, int size, ModelFormField modelFormField) {

+            super(fieldSource, size, null, modelFormField);

+            this.defaultOptionFrom = "greaterThanEqualTo";

+            this.defaultOptionThru = "lessThanEqualTo";

+        }

+

+        private RangeFindField(RangeFindField original, ModelFormField modelFormField) {

+            super(original, modelFormField);

+            this.defaultOptionFrom = original.defaultOptionFrom;

+            this.defaultOptionThru = original.defaultOptionThru;

+        }

+

+        @Override

+        public void accept(ModelFieldVisitor visitor) throws Exception {

+            visitor.visit(this);

+        }

+

+        @Override

+        public FieldInfo copy(ModelFormField modelFormField) {

+            return new RangeFindField(this, modelFormField);

+        }

+

+        public String getDefaultOptionFrom() {

+            return this.defaultOptionFrom;

+        }

+

+        public String getDefaultOptionThru() {

+            return this.defaultOptionThru;

+        }

+

+        @Override

+        public void renderFieldString(Appendable writer, Map<String, Object> context, FormStringRenderer formStringRenderer)

+                throws IOException {

+            formStringRenderer.renderRangeFindField(writer, context, this);

+        }

+    }

+

+    /**

+     * Models the &lt;reset&gt; element.

+     * 

+     * @see <code>widget-form.xsd</code>

+     */

+    public static class ResetField extends FieldInfo {

+

+        public ResetField(Element element, ModelFormField modelFormField) {

+            super(element, modelFormField);

+        }

+

+        public ResetField(int fieldSource, ModelFormField modelFormField) {

+            super(fieldSource, FieldInfo.RESET, modelFormField);

+        }

+

+        public ResetField(ModelFormField modelFormField) {

+            super(FieldInfo.SOURCE_EXPLICIT, FieldInfo.RESET, modelFormField);

+        }

+

+        private ResetField(ResetField original, ModelFormField modelFormField) {

+            super(original.getFieldSource(), original.getFieldType(), modelFormField);

+        }

+

+        @Override

+        public void accept(ModelFieldVisitor visitor) throws Exception {

+            visitor.visit(this);

+        }

+

+        @Override

+        public FieldInfo copy(ModelFormField modelFormField) {

+            return new ResetField(this, modelFormField);

+        }

+

+        @Override

+        public void renderFieldString(Appendable writer, Map<String, Object> context, FormStringRenderer formStringRenderer)

+                throws IOException {

+            formStringRenderer.renderResetField(writer, context, this);

+        }

+    }

+

+    /**

+     * Models the &lt;option&gt; element.

+     * 

+     * @see <code>widget-form.xsd</code>

+     */

+    public static class SingleOption extends OptionSource {

+        private final FlexibleStringExpander description;

+        private final FlexibleStringExpander key;

+

+        public SingleOption(Element optionElement, ModelFormField modelFormField) {

+            super(modelFormField);

+            this.key = FlexibleStringExpander.getInstance(optionElement.getAttribute("key"));

+            this.description = FlexibleStringExpander.getInstance(UtilXml.checkEmpty(optionElement.getAttribute("description"),

+                    optionElement.getAttribute("key")));

+        }

+

+        private SingleOption(SingleOption original, ModelFormField modelFormField) {

+            super(modelFormField);

+            this.key = original.key;

+            this.description = original.description;

+        }

+

+        public SingleOption(String key, String description, ModelFormField modelFormField) {

+            super(modelFormField);

+            this.key = FlexibleStringExpander.getInstance(key);

+            this.description = FlexibleStringExpander.getInstance(UtilXml.checkEmpty(description, key));

+        }

+

+        @Override

+        public void addOptionValues(List<OptionValue> optionValues, Map<String, Object> context, Delegator delegator) {

+            optionValues.add(new OptionValue(key.expandString(context), description.expandString(context)));

+        }

+

+        @Override

+        public OptionSource copy(ModelFormField modelFormField) {

+            return new SingleOption(this, modelFormField);

+        }

+

+        public FlexibleStringExpander getDescription() {

+            return description;

+        }

+

+        public FlexibleStringExpander getKey() {

+            return key;

+        }

+    }

+

+    /**

+     * Models the &lt;sub-hyperlink&gt; element.

+     * 

+     * @see <code>widget-form.xsd</code>

+     */

+    public static class SubHyperlink {

+        private final FlexibleStringExpander description;

+        private final FlexibleStringExpander useWhen;

+        private final Link link;

+        private final ModelFormField modelFormField;

+

+        public SubHyperlink(Element element, ModelFormField modelFormField) {

+            this.description = FlexibleStringExpander.getInstance(element.getAttribute("description"));

+            this.useWhen = FlexibleStringExpander.getInstance(element.getAttribute("use-when"));

+            this.link = new Link(element);

+            this.modelFormField = modelFormField;

+        }

+

+        public SubHyperlink(SubHyperlink original, ModelFormField modelFormField) {

+            this.description = original.description;

+            this.useWhen = original.useWhen;

+            this.link = original.link;

+            this.modelFormField = modelFormField;

+        }

+

+        public AutoEntityParameters getAutoEntityParameters() {

+            return link.getAutoEntityParameters();

+        }

+

+        public AutoServiceParameters getAutoServiceParameters() {

+            return link.getAutoServiceParameters();

+        }

+

+        public boolean getEncode() {

+            return link.getEncode();

+        }

+

+        public boolean getFullPath() {

+            return link.getFullPath();

+        }

+

+        public String getHeight() {

+            return link.getHeight();

+        }

+

+        public String getId(Map<String, Object> context) {

+            return link.getId(context);

+        }

+

+        public FlexibleStringExpander getIdExdr() {

+            return link.getIdExdr();

+        }

+

+        public Image getImage() {

+            return link.getImage();

+        }

+

+        public String getLinkType() {

+            return link.getLinkType();

+        }

+

+        public String getName() {

+            return link.getName();

+        }

+

+        public String getName(Map<String, Object> context) {

+            return link.getName(context);

+        }

+

+        public FlexibleStringExpander getNameExdr() {

+            return link.getNameExdr();

+        }

+

+        public List<Parameter> getParameterList() {

+            return link.getParameterList();

+        }

+

+        public Map<String, String> getParameterMap(Map<String, Object> context) {

+            return link.getParameterMap(context);

+        }

+

+        public String getPrefix(Map<String, Object> context) {

+            return link.getPrefix(context);

+        }

+

+        public FlexibleStringExpander getPrefixExdr() {

+            return link.getPrefixExdr();

+        }

+

+        public boolean getSecure() {

+            return link.getSecure();

+        }

+

+        public Integer getSize() {

+            return link.getSize();

+        }

+

+        public String getStyle(Map<String, Object> context) {

+            return link.getStyle(context);

+        }

+

+        public FlexibleStringExpander getStyleExdr() {

+            return link.getStyleExdr();

+        }

+

+        public String getTarget(Map<String, Object> context) {

+            return link.getTarget(context);

+        }

+

+        public FlexibleStringExpander getTargetExdr() {

+            return link.getTargetExdr();

+        }

+

+        public String getTargetWindow(Map<String, Object> context) {

+            return link.getTargetWindow(context);

+        }

+

+        public FlexibleStringExpander getTargetWindowExdr() {

+            return link.getTargetWindowExdr();

+        }

+

+        public String getText(Map<String, Object> context) {

+            return link.getText(context);

+        }

+

+        public FlexibleStringExpander getTextExdr() {

+            return link.getTextExdr();

+        }

+

+        public String getUrlMode() {

+            return link.getUrlMode();

+        }

+

+        public String getWidth() {

+            return link.getWidth();

+        }

+

+        public FlexibleStringExpander getDescription() {

+            return description;

+        }

+

+        public String getDescription(Map<String, Object> context) {

+            return description.expandString(context);

+        }

+

+        public FlexibleStringExpander getUseWhen() {

+            return useWhen;

+        }

+

+        public Link getLink() {

+            return link;

+        }

+

+        public String getUseWhen(Map<String, Object> context) {

+            return this.useWhen.expandString(context);

+        }

+

+        public ModelFormField getModelFormField() {

+            return modelFormField;

+        }

+

+        public boolean shouldUse(Map<String, Object> context) {

+            boolean shouldUse = true;

+            String useWhen = this.getUseWhen(context);

+            if (UtilValidate.isNotEmpty(useWhen)) {

+                try {

+                    Interpreter bsh = (Interpreter) context.get("bshInterpreter");

+                    if (bsh == null) {

+                        bsh = BshUtil.makeInterpreter(context);

+                        context.put("bshInterpreter", bsh);

+                    }

+

+                    Object retVal = bsh.eval(StringUtil.convertOperatorSubstitutions(useWhen));

+

+                    // retVal should be a Boolean, if not something weird is up...

+                    if (retVal instanceof Boolean) {

+                        Boolean boolVal = (Boolean) retVal;

+                        shouldUse = boolVal.booleanValue();

+                    } else {

+                        throw new IllegalArgumentException("Return value from target condition eval was not a Boolean: "

+                                + retVal.getClass().getName() + " [" + retVal + "]");

+                    }

+                } catch (EvalError e) {

+                    String errmsg = "Error evaluating BeanShell target conditions";

+                    Debug.logError(e, errmsg, module);

+                    throw new IllegalArgumentException(errmsg);

+                }

+            }

+            return shouldUse;

+        }

+    }

+

+    /**

+     * Models the &lt;submit&gt; element.

+     * 

+     * @see <code>widget-form.xsd</code>

+     */

+    public static class SubmitField extends FieldInfo {

+        private final FlexibleStringExpander backgroundSubmitRefreshTargetExdr;

+        private final String buttonType;

+        private final FlexibleStringExpander confirmationMsgExdr;

+        private final FlexibleStringExpander imageLocation;

+        private final boolean requestConfirmation;

+

+        public SubmitField(Element element, ModelFormField modelFormField) {

+            super(element, modelFormField);

+            this.backgroundSubmitRefreshTargetExdr = FlexibleStringExpander.getInstance(element

+                    .getAttribute("background-submit-refresh-target"));

+            this.buttonType = element.getAttribute("button-type");

+            this.confirmationMsgExdr = FlexibleStringExpander.getInstance(element.getAttribute("confirmation-message"));

+            this.imageLocation = FlexibleStringExpander.getInstance(element.getAttribute("image-location"));

+            this.requestConfirmation = "true".equals(element.getAttribute("request-confirmation"));

+        }

+

+        public SubmitField(int fieldInfo, ModelFormField modelFormField) {

+            super(fieldInfo, FieldInfo.SUBMIT, modelFormField);

+            this.backgroundSubmitRefreshTargetExdr = FlexibleStringExpander.getInstance("");

+            this.buttonType = "";

+            this.confirmationMsgExdr = FlexibleStringExpander.getInstance("");

+            this.imageLocation = FlexibleStringExpander.getInstance("");

+            this.requestConfirmation = false;

+        }

+

+        public SubmitField(ModelFormField modelFormField) {

+            this(FieldInfo.SOURCE_EXPLICIT, modelFormField);

+        }

+

+        private SubmitField(SubmitField original, ModelFormField modelFormField) {

+            super(original.getFieldSource(), original.getFieldType(), modelFormField);

+            this.buttonType = original.buttonType;

+            this.imageLocation = original.imageLocation;

+            this.backgroundSubmitRefreshTargetExdr = original.backgroundSubmitRefreshTargetExdr;

+            this.requestConfirmation = original.requestConfirmation;

+            this.confirmationMsgExdr = original.confirmationMsgExdr;

+        }

+

+        @Override

+        public void accept(ModelFieldVisitor visitor) throws Exception {

+            visitor.visit(this);

+        }

+

+        @Override

+        public FieldInfo copy(ModelFormField modelFormField) {

+            return new SubmitField(this, modelFormField);

+        }

+

+        public String getBackgroundSubmitRefreshTarget(Map<String, Object> context) {

+            return this.backgroundSubmitRefreshTargetExdr.expandString(context);

+        }

+

+        public FlexibleStringExpander getBackgroundSubmitRefreshTargetExdr() {

+            return backgroundSubmitRefreshTargetExdr;

+        }

+

+        public String getButtonType() {

+            return buttonType;

+        }

+

+        public String getConfirmation(Map<String, Object> context) {

+            String message = getConfirmationMsg(context);

+            if (UtilValidate.isNotEmpty(message))

+                return message;

+            else if (getRequestConfirmation()) {

+                String defaultMessage = UtilProperties.getPropertyValue("general", "default.confirmation.message",

+                        "${uiLabelMap.CommonConfirm}");

+                return FlexibleStringExpander.expandString(defaultMessage, context);

+            }

+            return "";

+        }

+

+        public String getConfirmationMsg(Map<String, Object> context) {

+            return this.confirmationMsgExdr.expandString(context);

+        }

+

+        public FlexibleStringExpander getConfirmationMsgExdr() {

+            return confirmationMsgExdr;

+        }

+

+        public FlexibleStringExpander getImageLocation() {

+            return imageLocation;

+        }

+

+        public String getImageLocation(Map<String, Object> context) {

+            return this.imageLocation.expandString(context);

+        }

+

+        public boolean getRequestConfirmation() {

+            return this.requestConfirmation;

+        }

+

+        @Override

+        public void renderFieldString(Appendable writer, Map<String, Object> context, FormStringRenderer formStringRenderer)

+                throws IOException {

+            formStringRenderer.renderSubmitField(writer, context, this);

+        }

+    }

+

+    /**

+     * Models the &lt;textarea&gt; element.

+     * 

+     * @see <code>widget-form.xsd</code>

+     */

+    public static class TextareaField extends FieldInfo {

+        private final int cols;

+        private final FlexibleStringExpander defaultValue;

+        private final boolean readOnly;

+        private final int rows;

+        private final FlexibleStringExpander visualEditorButtons;

+        private final boolean visualEditorEnable;

+

+        public TextareaField(Element element, ModelFormField modelFormField) {

+            super(element, modelFormField);

+            int cols = 60;

+            String colsStr = element.getAttribute("cols");

+            if (!colsStr.isEmpty()) {

+                try {

+                    cols = Integer.parseInt(colsStr);

+                } catch (Exception e) {

+                    if (UtilValidate.isNotEmpty(colsStr)) {

+                        Debug.logError("Could not parse the size value of the text element: [" + colsStr

+                                + "], setting to default of " + cols, module);

+                    }

+                }

+            }

+            this.cols = cols;

+            this.defaultValue = FlexibleStringExpander.getInstance(element.getAttribute("default-value"));

+            this.readOnly = "true".equals(element.getAttribute("read-only"));

+            int rows = 2;

+            String rowsStr = element.getAttribute("rows");

+            if (!rowsStr.isEmpty()) {

+                try {

+                    rows = Integer.parseInt(rowsStr);

+                } catch (Exception e) {

+                    if (UtilValidate.isNotEmpty(rowsStr)) {

+                        Debug.logError("Could not parse the size value of the text element: [" + rowsStr

+                                + "], setting to default of " + rows, module);

+                    }

+                }

+            }

+            this.rows = rows;

+            this.visualEditorButtons = FlexibleStringExpander.getInstance(element.getAttribute("visual-editor-buttons"));

+            this.visualEditorEnable = "true".equals(element.getAttribute("visual-editor-enable"));

+        }

+

+        public TextareaField(int fieldSource, ModelFormField modelFormField) {

+            super(fieldSource, FieldInfo.TEXTAREA, modelFormField);

+            this.cols = 60;

+            this.defaultValue = FlexibleStringExpander.getInstance("");

+            this.readOnly = false;

+            this.rows = 2;

+            this.visualEditorButtons = FlexibleStringExpander.getInstance("");

+            this.visualEditorEnable = false;

+        }

+

+        public TextareaField(ModelFormField modelFormField) {

+            this(FieldInfo.SOURCE_EXPLICIT, modelFormField);

+        }

+

+        private TextareaField(TextareaField original, ModelFormField modelFormField) {

+            super(original.getFieldSource(), original.getFieldType(), modelFormField);

+            this.defaultValue = original.defaultValue;

+            this.visualEditorEnable = original.visualEditorEnable;

+            this.visualEditorButtons = original.visualEditorButtons;

+            this.readOnly = original.readOnly;

+            this.cols = original.cols;

+            this.rows = original.rows;

+        }

+

+        @Override

+        public void accept(ModelFieldVisitor visitor) throws Exception {

+            visitor.visit(this);

+        }

+

+        @Override

+        public FieldInfo copy(ModelFormField modelFormField) {

+            return new TextareaField(this, modelFormField);

+        }

+

+        public int getCols() {

+            return cols;

+        }

+

+        public FlexibleStringExpander getDefaultValue() {

+            return defaultValue;

+        }

+

+        public String getDefaultValue(Map<String, Object> context) {

+            if (this.defaultValue != null) {

+                return this.defaultValue.expandString(context);

+            } else {

+                return "";

+            }

+        }

+

+        public int getRows() {

+            return rows;

+        }

+

+        public FlexibleStringExpander getVisualEditorButtons() {

+            return visualEditorButtons;

+        }

+

+        public String getVisualEditorButtons(Map<String, Object> context) {

+            return this.visualEditorButtons.expandString(context);

+        }

+

+        public boolean getVisualEditorEnable() {

+            return this.visualEditorEnable;

+        }

+

+        public boolean isReadOnly() {

+            return readOnly;

+        }

+

+        @Override

+        public void renderFieldString(Appendable writer, Map<String, Object> context, FormStringRenderer formStringRenderer)

+                throws IOException {

+            formStringRenderer.renderTextareaField(writer, context, this);

+        }

+    }

+

+    /**

+     * Models the &lt;text&gt; element.

+     * 

+     * @see <code>widget-form.xsd</code>

+     */

+    public static class TextField extends FieldInfo {

+        private final boolean clientAutocompleteField;

+        private final FlexibleStringExpander defaultValue;

+        private final boolean disabled;

+        private final String mask;

+        private final Integer maxlength;

+        private final FlexibleStringExpander placeholder;

+        private final boolean readonly;

+        private final int size;

+        private final SubHyperlink subHyperlink;

+

+        public TextField(Element element, ModelFormField modelFormField) {

+            super(element, modelFormField);

+            this.clientAutocompleteField = !"false".equals(element.getAttribute("client-autocomplete-field"));

+            this.defaultValue = FlexibleStringExpander.getInstance(element.getAttribute("default-value"));

+            this.disabled = "true".equals(element.getAttribute("disabled"));

+            this.mask = element.getAttribute("mask");

+            Integer maxlength = null;

+            String maxlengthStr = element.getAttribute("maxlength");

+            if (!maxlengthStr.isEmpty()) {

+                try {

+                    maxlength = Integer.valueOf(maxlengthStr);

+                } catch (Exception e) {

+                    Debug.logError("Could not parse the max-length value of the text element: [" + maxlengthStr

+                            + "], setting to null; default of no maxlength will be used", module);

+                }

+            }

+            this.maxlength = maxlength;

+            this.placeholder = FlexibleStringExpander.getInstance(element.getAttribute("placeholder"));

+            this.readonly = "true".equals(element.getAttribute("read-only"));

+            int size = 25;

+            String sizeStr = element.getAttribute("size");

+            if (!sizeStr.isEmpty()) {

+                try {

+                    size = Integer.parseInt(sizeStr);

+                } catch (Exception e) {

+                    Debug.logError("Could not parse the size value of the text element: [" + sizeStr

+                            + "], setting to the default of " + size, module);

+                }

+            }

+            this.size = size;

+            Element subHyperlinkElement = UtilXml.firstChildElement(element, "sub-hyperlink");

+            if (subHyperlinkElement != null) {

+                this.subHyperlink = new SubHyperlink(subHyperlinkElement, this.getModelFormField());

+            } else {

+                this.subHyperlink = null;

+            }

+        }

+

+        protected TextField(int fieldSource, int size, Integer maxlength, ModelFormField modelFormField) {

+            super(fieldSource, FieldInfo.TEXT, modelFormField);

+            this.clientAutocompleteField = true;

+            this.defaultValue = FlexibleStringExpander.getInstance("");

+            this.disabled = false;

+            this.mask = "";

+            this.maxlength = maxlength;

+            this.placeholder = FlexibleStringExpander.getInstance("");

+            this.readonly = false;

+            this.size = size;

+            this.subHyperlink = null;

+        }

+

+        private TextField(int fieldSource, int fieldType, ModelFormField modelFormField) {

+            super(fieldSource, fieldType, modelFormField);

+            this.clientAutocompleteField = true;

+            this.defaultValue = FlexibleStringExpander.getInstance("");

+            this.disabled = false;

+            this.mask = "";

+            this.maxlength = null;

+            this.placeholder = FlexibleStringExpander.getInstance("");

+            this.readonly = false;

+            this.size = 25;

+            this.subHyperlink = null;

+        }

+

+        public TextField(int fieldSource, ModelFormField modelFormField) {

+            this(fieldSource, FieldInfo.TEXT, modelFormField);

+        }

+

+        public TextField(ModelFormField modelFormField) {

+            this(FieldInfo.SOURCE_EXPLICIT, FieldInfo.TEXT, modelFormField);

+        }

+

+        protected TextField(TextField original, ModelFormField modelFormField) {

+            super(original.getFieldSource(), original.getFieldType(), modelFormField);

+            this.clientAutocompleteField = original.clientAutocompleteField;

+            this.defaultValue = original.defaultValue;

+            this.mask = original.mask;

+            this.placeholder = original.placeholder;

+            this.size = original.size;

+            this.maxlength = original.maxlength;

+            this.disabled = original.disabled;

+            this.readonly = original.readonly;

+            if (original.subHyperlink != null) {

+                this.subHyperlink = new SubHyperlink(original.subHyperlink, modelFormField);

+            } else {

+                this.subHyperlink = null;

+            }

+        }

+

+        @Override

+        public void accept(ModelFieldVisitor visitor) throws Exception {

+            visitor.visit(this);

+        }

+

+        @Override

+        public FieldInfo copy(ModelFormField modelFormField) {

+            return new TextField(this, modelFormField);

+        }

+

+        public boolean getClientAutocompleteField() {

+            return this.clientAutocompleteField;

+        }

+

+        public FlexibleStringExpander getDefaultValue() {

+            return defaultValue;

+        }

+

+        public String getDefaultValue(Map<String, Object> context) {

+            if (this.defaultValue != null) {

+                return this.defaultValue.expandString(context);

+            } else {

+                return "";

+            }

+        }

+

+        public boolean getDisabled() {

+            return this.disabled;

+        }

+

+        public String getMask() {

+            return this.mask;

+        }

+

+        public Integer getMaxlength() {

+            return maxlength;

+        }

+

+        public FlexibleStringExpander getPlaceholder() {

+            return placeholder;

+        }

+

+        public String getPlaceholder(Map<String, Object> context) {

+            return this.placeholder.expandString(context);

+        }

+

+        public boolean getReadonly() {

+            return this.readonly;

+        }

+

+        public int getSize() {

+            return size;

+        }

+

+        public SubHyperlink getSubHyperlink() {

+            return this.subHyperlink;

+        }

+

+        @Override

+        public void renderFieldString(Appendable writer, Map<String, Object> context, FormStringRenderer formStringRenderer)

+                throws IOException {

+            formStringRenderer.renderTextField(writer, context, this);

+        }

+    }

+

+    /**

+     * Models the &lt;text-find&gt; element.

+     * 

+     * @see <code>widget-form.xsd</code>

+     */

+    public static class TextFindField extends TextField {

+        private final String defaultOption;

+        private final boolean hideIgnoreCase;

+        private final boolean hideOptions;

+        private final boolean ignoreCase;

+

+        public TextFindField(Element element, ModelFormField modelFormField) {

+            super(element, modelFormField);

+            if (element.hasAttribute("default-option")) {

+                this.defaultOption = element.getAttribute("default-option");

+            } else {

+                this.defaultOption = UtilProperties.getPropertyValue("widget", "widget.form.defaultTextFindOption", "contains");

+            }

+            this.hideIgnoreCase = "true".equals(element.getAttribute("hide-options"))

+                    || "ignore-case".equals(element.getAttribute("hide-options")) ? true : false;

+            this.hideOptions = "true".equals(element.getAttribute("hide-options"))

+                    || "options".equals(element.getAttribute("hide-options")) ? true : false;

+            this.ignoreCase = "true".equals(element.getAttribute("ignore-case"));

+        }

+

+        public TextFindField(int fieldSource, int size, Integer maxlength, ModelFormField modelFormField) {

+            super(fieldSource, size, maxlength, modelFormField);

+            this.defaultOption = UtilProperties.getPropertyValue("widget", "widget.form.defaultTextFindOption", "contains");

+            this.hideIgnoreCase = false;

+            this.hideOptions = false;

+            this.ignoreCase = true;

+        }

+

+        public TextFindField(int fieldSource, ModelFormField modelFormField) {

+            super(fieldSource, modelFormField);

+            this.defaultOption = UtilProperties.getPropertyValue("widget", "widget.form.defaultTextFindOption", "contains");

+            this.hideIgnoreCase = false;

+            this.hideOptions = false;

+            this.ignoreCase = true;

+        }

+

+        private TextFindField(TextFindField original, ModelFormField modelFormField) {

+            super(original, modelFormField);

+            this.ignoreCase = original.ignoreCase;

+            this.hideIgnoreCase = original.hideIgnoreCase;

+            this.defaultOption = original.defaultOption;

+            this.hideOptions = original.hideOptions;

+        }

+

+        @Override

+        public void accept(ModelFieldVisitor visitor) throws Exception {

+            visitor.visit(this);

+        }

+

+        @Override

+        public FieldInfo copy(ModelFormField modelFormField) {

+            return new TextFindField(this, modelFormField);

+        }

+

+        public String getDefaultOption() {

+            return this.defaultOption;

+        }

+

+        public boolean getHideIgnoreCase() {

+            return this.hideIgnoreCase;

+        }

+

+        public boolean getHideOptions() {

+            return this.hideOptions;

+        }

+

+        public boolean getIgnoreCase() {

+            return this.ignoreCase;

+        }

+

+        @Override

+        public void renderFieldString(Appendable writer, Map<String, Object> context, FormStringRenderer formStringRenderer)

+                throws IOException {

+            formStringRenderer.renderTextFindField(writer, context, this);

+        }

+    }

+}

diff --git a/framework/widget/src/org/ofbiz/widget/form/ModelFormFieldBuilder.java b/framework/widget/src/org/ofbiz/widget/model/ModelFormFieldBuilder.java
similarity index 96%
rename from framework/widget/src/org/ofbiz/widget/form/ModelFormFieldBuilder.java
rename to framework/widget/src/org/ofbiz/widget/model/ModelFormFieldBuilder.java
index e77d8d5..be52bd7 100644
--- a/framework/widget/src/org/ofbiz/widget/form/ModelFormFieldBuilder.java
+++ b/framework/widget/src/org/ofbiz/widget/model/ModelFormFieldBuilder.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations

  * under the License.

  *******************************************************************************/

-package org.ofbiz.widget.form;

+package org.ofbiz.widget.model;

 

 import java.util.ArrayList;

 import java.util.List;

@@ -35,29 +35,29 @@
 import org.ofbiz.service.GenericServiceException;

 import org.ofbiz.service.ModelParam;

 import org.ofbiz.service.ModelService;

-import org.ofbiz.widget.form.ModelForm.UpdateArea;

-import org.ofbiz.widget.form.ModelFormField.CheckField;

-import org.ofbiz.widget.form.ModelFormField.ContainerField;

-import org.ofbiz.widget.form.ModelFormField.DateFindField;

-import org.ofbiz.widget.form.ModelFormField.DateTimeField;

-import org.ofbiz.widget.form.ModelFormField.DisplayEntityField;

-import org.ofbiz.widget.form.ModelFormField.DisplayField;

-import org.ofbiz.widget.form.ModelFormField.DropDownField;

-import org.ofbiz.widget.form.ModelFormField.FileField;

-import org.ofbiz.widget.form.ModelFormField.HiddenField;

-import org.ofbiz.widget.form.ModelFormField.HyperlinkField;

-import org.ofbiz.widget.form.ModelFormField.IgnoredField;

-import org.ofbiz.widget.form.ModelFormField.ImageField;

-import org.ofbiz.widget.form.ModelFormField.LookupField;

-import org.ofbiz.widget.form.ModelFormField.OptionSource;

-import org.ofbiz.widget.form.ModelFormField.PasswordField;

-import org.ofbiz.widget.form.ModelFormField.RadioField;

-import org.ofbiz.widget.form.ModelFormField.RangeFindField;

-import org.ofbiz.widget.form.ModelFormField.ResetField;

-import org.ofbiz.widget.form.ModelFormField.SubmitField;

-import org.ofbiz.widget.form.ModelFormField.TextField;

-import org.ofbiz.widget.form.ModelFormField.TextFindField;

-import org.ofbiz.widget.form.ModelFormField.TextareaField;

+import org.ofbiz.widget.model.ModelForm.UpdateArea;

+import org.ofbiz.widget.model.ModelFormField.CheckField;

+import org.ofbiz.widget.model.ModelFormField.ContainerField;

+import org.ofbiz.widget.model.ModelFormField.DateFindField;

+import org.ofbiz.widget.model.ModelFormField.DateTimeField;

+import org.ofbiz.widget.model.ModelFormField.DisplayEntityField;

+import org.ofbiz.widget.model.ModelFormField.DisplayField;

+import org.ofbiz.widget.model.ModelFormField.DropDownField;

+import org.ofbiz.widget.model.ModelFormField.FileField;

+import org.ofbiz.widget.model.ModelFormField.HiddenField;

+import org.ofbiz.widget.model.ModelFormField.HyperlinkField;

+import org.ofbiz.widget.model.ModelFormField.IgnoredField;

+import org.ofbiz.widget.model.ModelFormField.ImageField;

+import org.ofbiz.widget.model.ModelFormField.LookupField;

+import org.ofbiz.widget.model.ModelFormField.OptionSource;

+import org.ofbiz.widget.model.ModelFormField.PasswordField;

+import org.ofbiz.widget.model.ModelFormField.RadioField;

+import org.ofbiz.widget.model.ModelFormField.RangeFindField;

+import org.ofbiz.widget.model.ModelFormField.ResetField;

+import org.ofbiz.widget.model.ModelFormField.SubmitField;

+import org.ofbiz.widget.model.ModelFormField.TextField;

+import org.ofbiz.widget.model.ModelFormField.TextFindField;

+import org.ofbiz.widget.model.ModelFormField.TextareaField;

 import org.w3c.dom.Element;

 

 /**

diff --git a/framework/widget/src/org/ofbiz/widget/menu/ModelMenu.java b/framework/widget/src/org/ofbiz/widget/model/ModelMenu.java
similarity index 99%
rename from framework/widget/src/org/ofbiz/widget/menu/ModelMenu.java
rename to framework/widget/src/org/ofbiz/widget/model/ModelMenu.java
index 44fc162..7d98c20 100644
--- a/framework/widget/src/org/ofbiz/widget/menu/ModelMenu.java
+++ b/framework/widget/src/org/ofbiz/widget/model/ModelMenu.java
@@ -1,536 +1,534 @@
-/*******************************************************************************
- * 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.menu;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import org.ofbiz.base.util.Debug;
-import org.ofbiz.base.util.UtilValidate;
-import org.ofbiz.base.util.UtilXml;
-import org.ofbiz.base.util.collections.FlexibleMapAccessor;
-import org.ofbiz.base.util.string.FlexibleStringExpander;
-import org.ofbiz.widget.ModelWidget;
-import org.ofbiz.widget.*;
-import org.ofbiz.widget.ModelWidgetVisitor;
-import org.w3c.dom.Element;
-
-/**
- * Models the &lt;menu&gt; element.
- * 
- * @see <code>widget-menu.xsd</code>
- */
-@SuppressWarnings("serial")
-public class ModelMenu extends ModelWidget {
-
-    /*
-     * ----------------------------------------------------------------------- *
-     *                     DEVELOPERS PLEASE READ
-     * ----------------------------------------------------------------------- *
-     * 
-     * This model is intended to be a read-only data structure that represents
-     * an XML element. Outside of object construction, the class should not
-     * have any behaviors.
-     * 
-     * Instances of this class will be shared by multiple threads - therefore
-     * it is immutable. DO NOT CHANGE THE OBJECT'S STATE AT RUN TIME!
-     * 
-     */
-
-    public static final String module = ModelMenu.class.getName();
-
-    private final List<ModelAction> actions;
-    private final String defaultAlign;
-    private final String defaultAlignStyle;
-    private final FlexibleStringExpander defaultAssociatedContentId;
-    private final String defaultCellWidth;
-    private final String defaultDisabledTitleStyle;
-    private final String defaultEntityName;
-    private final Boolean defaultHideIfSelected;
-    private final String defaultMenuItemName;
-    private final String defaultPermissionEntityAction;
-    private final String defaultPermissionOperation;
-    private final String defaultSelectedStyle;
-    private final String defaultTitleStyle;
-    private final String defaultTooltipStyle;
-    private final String defaultWidgetStyle;
-    private final FlexibleStringExpander extraIndex;
-    private final String fillStyle;
-    private final String id;
-    private final FlexibleStringExpander menuContainerStyleExdr;
-    /** This List will contain one copy of each item for each item name in the order
-     * they were encountered in the service, entity, or menu definition; item definitions
-     * with constraints will also be in this list but may appear multiple times for the same
-     * item name.
-     *
-     * When rendering the menu 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 menu definition to keep the
-     * list clean and implement the override features for item definitions.
-     */
-    private final List<ModelMenuItem> menuItemList;
-    /** This Map is keyed with the item name and has a ModelMenuItem for the value; items
-     * with conditions will not be put in this Map so item definition overrides for items
-     * with conditions is not possible.
-     */
-    private final Map<String, ModelMenuItem> menuItemMap;
-    private final String menuLocation;
-    private final String menuWidth;
-    private final String orientation;
-    private final ModelMenu parentMenu;
-    private final FlexibleMapAccessor<String> selectedMenuItemContextFieldName;
-    private final String target;
-    private final FlexibleStringExpander title;
-    private final String tooltip;
-    private final String type;
-
-    /** XML Constructor */
-    public ModelMenu(Element menuElement, String menuLocation) {
-        super(menuElement);
-        ArrayList<ModelAction> actions = new ArrayList<ModelAction>();
-        String defaultAlign = "";
-        String defaultAlignStyle = "";
-        FlexibleStringExpander defaultAssociatedContentId = FlexibleStringExpander.getInstance("");
-        String defaultCellWidth = "";
-        String defaultDisabledTitleStyle = "";
-        String defaultEntityName = "";
-        Boolean defaultHideIfSelected = Boolean.FALSE;
-        String defaultMenuItemName = "";
-        String defaultPermissionEntityAction = "";
-        String defaultPermissionOperation = "";
-        String defaultSelectedStyle = "";
-        String defaultTitleStyle = "";
-        String defaultTooltipStyle = "";
-        String defaultWidgetStyle = "";
-        FlexibleStringExpander extraIndex = FlexibleStringExpander.getInstance("");
-        String fillStyle = "";
-        String id = "";
-        FlexibleStringExpander menuContainerStyleExdr = FlexibleStringExpander.getInstance("");
-        ArrayList<ModelMenuItem> menuItemList = new ArrayList<ModelMenuItem>();
-        Map<String, ModelMenuItem> menuItemMap = new HashMap<String, ModelMenuItem>();
-        String menuWidth = "";
-        String orientation = "horizontal";
-        FlexibleMapAccessor<String> selectedMenuItemContextFieldName = FlexibleMapAccessor.getInstance("");
-        String target = "";
-        FlexibleStringExpander title = FlexibleStringExpander.getInstance("");
-        String tooltip = "";
-        String type = "";
-        // check if there is a parent menu to inherit from
-        ModelMenu parent = null;
-        String parentResource = menuElement.getAttribute("extends-resource");
-        String parentMenu = menuElement.getAttribute("extends");
-        if (!parentMenu.isEmpty()) {
-            if (!parentResource.isEmpty()) {
-                try {
-                    parent = MenuFactory.getMenuFromLocation(parentResource, parentMenu);
-                } catch (Exception e) {
-                    Debug.logError(e, "Failed to load parent menu definition '" + parentMenu + "' at resource '" + parentResource
-                            + "'", module);
-                }
-            } else {
-                parentResource = menuLocation;
-                // try to find a menu definition in the same file
-                Element rootElement = menuElement.getOwnerDocument().getDocumentElement();
-                List<? extends Element> menuElements = UtilXml.childElementList(rootElement, "menu");
-                for (Element menuElementEntry : menuElements) {
-                    if (menuElementEntry.getAttribute("name").equals(parentMenu)) {
-                        parent = new ModelMenu(menuElementEntry, parentResource);
-                        break;
-                    }
-                }
-                if (parent == null) {
-                    Debug.logError("Failed to find parent menu definition '" + parentMenu + "' in same document.", module);
-                }
-            }
-            if (parent != null) {
-                type = parent.type;
-                target = parent.target;
-                id = parent.id;
-                title = parent.title;
-                tooltip = parent.tooltip;
-                defaultEntityName = parent.defaultEntityName;
-                defaultTitleStyle = parent.defaultTitleStyle;
-                defaultSelectedStyle = parent.defaultSelectedStyle;
-                defaultWidgetStyle = parent.defaultWidgetStyle;
-                defaultTooltipStyle = parent.defaultTooltipStyle;
-                defaultMenuItemName = parent.defaultMenuItemName;
-                menuItemList.addAll(parent.menuItemList);
-                menuItemMap.putAll(parent.menuItemMap);
-                defaultPermissionOperation = parent.defaultPermissionOperation;
-                defaultPermissionEntityAction = parent.defaultPermissionEntityAction;
-                defaultAssociatedContentId = parent.defaultAssociatedContentId;
-                defaultHideIfSelected = parent.defaultHideIfSelected;
-                orientation = parent.orientation;
-                menuWidth = parent.menuWidth;
-                defaultCellWidth = parent.defaultCellWidth;
-                defaultDisabledTitleStyle = parent.defaultDisabledTitleStyle;
-                defaultAlign = parent.defaultAlign;
-                defaultAlignStyle = parent.defaultAlignStyle;
-                fillStyle = parent.fillStyle;
-                extraIndex = parent.extraIndex;
-                selectedMenuItemContextFieldName = parent.selectedMenuItemContextFieldName;
-                menuContainerStyleExdr = parent.menuContainerStyleExdr;
-                if (parent.actions != null) {
-                    actions.addAll(parent.actions);
-                }
-            }
-        }
-        if (!menuElement.getAttribute("type").isEmpty())
-            type = menuElement.getAttribute("type");
-        if (!menuElement.getAttribute("target").isEmpty())
-            target = menuElement.getAttribute("target");
-        if (!menuElement.getAttribute("id").isEmpty())
-            id = menuElement.getAttribute("id");
-        if (!menuElement.getAttribute("title").isEmpty())
-            title = FlexibleStringExpander.getInstance(menuElement.getAttribute("title"));
-        if (!menuElement.getAttribute("tooltip").isEmpty())
-            tooltip = menuElement.getAttribute("tooltip");
-        if (!menuElement.getAttribute("default-entity-name").isEmpty())
-            defaultEntityName = menuElement.getAttribute("default-entity-name");
-        if (!menuElement.getAttribute("default-title-style").isEmpty())
-            defaultTitleStyle = menuElement.getAttribute("default-title-style");
-        if (!menuElement.getAttribute("default-selected-style").isEmpty())
-            defaultSelectedStyle = menuElement.getAttribute("default-selected-style");
-        if (!menuElement.getAttribute("default-widget-style").isEmpty())
-            defaultWidgetStyle = menuElement.getAttribute("default-widget-style");
-        if (!menuElement.getAttribute("default-tooltip-style").isEmpty())
-            defaultTooltipStyle = menuElement.getAttribute("default-tooltip-style");
-        if (!menuElement.getAttribute("default-menu-item-name").isEmpty())
-            defaultMenuItemName = menuElement.getAttribute("default-menu-item-name");
-        if (!menuElement.getAttribute("default-permission-operation").isEmpty())
-            defaultPermissionOperation = menuElement.getAttribute("default-permission-operation");
-        if (!menuElement.getAttribute("default-permission-entity-action").isEmpty())
-            defaultPermissionEntityAction = menuElement.getAttribute("default-permission-entity-action");
-        if (!menuElement.getAttribute("default-associated-content-id").isEmpty())
-            defaultAssociatedContentId = FlexibleStringExpander.getInstance(menuElement
-                    .getAttribute("default-associated-content-id"));
-        if (!menuElement.getAttribute("orientation").isEmpty())
-            orientation = menuElement.getAttribute("orientation");
-        if (!menuElement.getAttribute("menu-width").isEmpty())
-            menuWidth = menuElement.getAttribute("menu-width");
-        if (!menuElement.getAttribute("default-cell-width").isEmpty())
-            defaultCellWidth = menuElement.getAttribute("default-cell-width");
-        if (!menuElement.getAttribute("default-hide-if-selected").isEmpty())
-            defaultHideIfSelected = "true".equals(menuElement.getAttribute("default-hide-if-selected").isEmpty());
-        if (!menuElement.getAttribute("default-disabled-title-style").isEmpty())
-            defaultDisabledTitleStyle = menuElement.getAttribute("default-disabled-title-style");
-        if (!menuElement.getAttribute("selected-menuitem-context-field-name").isEmpty())
-            selectedMenuItemContextFieldName = FlexibleMapAccessor.getInstance(menuElement
-                    .getAttribute("selected-menuitem-context-field-name"));
-        if (!menuElement.getAttribute("menu-container-style").isEmpty())
-            menuContainerStyleExdr = FlexibleStringExpander.getInstance(menuElement.getAttribute("menu-container-style"));
-        if (!menuElement.getAttribute("default-align").isEmpty())
-            defaultAlign = menuElement.getAttribute("default-align");
-        if (!menuElement.getAttribute("default-align-style").isEmpty())
-            defaultAlignStyle = menuElement.getAttribute("default-align-style");
-        if (!menuElement.getAttribute("fill-style").isEmpty())
-            fillStyle = menuElement.getAttribute("fill-style");
-        if (!menuElement.getAttribute("extra-index").isEmpty())
-            extraIndex = FlexibleStringExpander.getInstance(menuElement.getAttribute("extra-index"));
-        // read all actions under the "actions" element
-        Element actionsElement = UtilXml.firstChildElement(menuElement, "actions");
-        if (actionsElement != null) {
-            actions.addAll(ModelMenuAction.readSubActions(this, actionsElement));
-        }
-        actions.trimToSize();
-        this.actions = Collections.unmodifiableList(actions);
-        this.defaultAlign = defaultAlign;
-        this.defaultAlignStyle = defaultAlignStyle;
-        this.defaultAssociatedContentId = defaultAssociatedContentId;
-        this.defaultCellWidth = defaultCellWidth;
-        this.defaultDisabledTitleStyle = defaultDisabledTitleStyle;
-        this.defaultEntityName = defaultEntityName;
-        this.defaultHideIfSelected = defaultHideIfSelected;
-        this.defaultMenuItemName = defaultMenuItemName;
-        this.defaultPermissionEntityAction = defaultPermissionEntityAction;
-        this.defaultPermissionOperation = defaultPermissionOperation;
-        this.defaultSelectedStyle = defaultSelectedStyle;
-        this.defaultTitleStyle = defaultTitleStyle;
-        this.defaultTooltipStyle = defaultTooltipStyle;
-        this.defaultWidgetStyle = defaultWidgetStyle;
-        this.extraIndex = extraIndex;
-        this.fillStyle = fillStyle;
-        this.id = id;
-        this.menuContainerStyleExdr = menuContainerStyleExdr;
-        List<? extends Element> itemElements = UtilXml.childElementList(menuElement, "menu-item");
-        for (Element itemElement : itemElements) {
-            ModelMenuItem modelMenuItem = new ModelMenuItem(itemElement, this);
-            addUpdateMenuItem(modelMenuItem, menuItemList, menuItemMap);
-        }
-        menuItemList.trimToSize();
-        this.menuItemList = Collections.unmodifiableList(menuItemList);
-        this.menuItemMap = Collections.unmodifiableMap(menuItemMap);
-        this.menuLocation = menuLocation;
-        this.menuWidth = menuWidth;
-        this.orientation = orientation;
-        this.parentMenu = parent;
-        this.selectedMenuItemContextFieldName = selectedMenuItemContextFieldName;
-        this.target = target;
-        this.title = title;
-        this.tooltip = tooltip;
-        this.type = type;
-    }
-
-    @Override
-    public void accept(ModelWidgetVisitor visitor) throws Exception {
-        visitor.visit(this);
-    }
-
-    /**
-     * add/override modelMenuItem using the menuItemList and menuItemMap
-     *
-     */
-    private void addUpdateMenuItem(ModelMenuItem modelMenuItem, List<ModelMenuItem> menuItemList,
-            Map<String, ModelMenuItem> menuItemMap) {
-        ModelMenuItem existingMenuItem = menuItemMap.get(modelMenuItem.getName());
-        if (existingMenuItem != null) {
-            // does exist, update the item by doing a merge/override
-            ModelMenuItem mergedMenuItem = existingMenuItem.mergeOverrideModelMenuItem(modelMenuItem);
-            int existingItemIndex = menuItemList.indexOf(existingMenuItem);
-            menuItemList.set(existingItemIndex, mergedMenuItem);
-            menuItemMap.put(modelMenuItem.getName(), mergedMenuItem);
-        } else {
-            // does not exist, add to Map
-            menuItemList.add(modelMenuItem);
-            menuItemMap.put(modelMenuItem.getName(), modelMenuItem);
-        }
-    }
-
-    public List<ModelAction> getActions() {
-        return actions;
-    }
-
-    @Override
-    public String getBoundaryCommentName() {
-        return menuLocation + "#" + getName();
-    }
-
-    public String getCurrentMenuName(Map<String, Object> context) {
-        return getName();
-    }
-
-    public String getDefaultAlign() {
-        return this.defaultAlign;
-    }
-
-    public String getDefaultAlignStyle() {
-        return this.defaultAlignStyle;
-    }
-
-    public FlexibleStringExpander getDefaultAssociatedContentId() {
-        return defaultAssociatedContentId;
-    }
-
-    public String getDefaultAssociatedContentId(Map<String, Object> context) {
-        return defaultAssociatedContentId.expandString(context);
-    }
-
-    public String getDefaultCellWidth() {
-        return this.defaultCellWidth;
-    }
-
-    public String getDefaultDisabledTitleStyle() {
-        return this.defaultDisabledTitleStyle;
-    }
-
-    public String getDefaultEntityName() {
-        return this.defaultEntityName;
-    }
-
-    public Boolean getDefaultHideIfSelected() {
-        return this.defaultHideIfSelected;
-    }
-
-    public String getDefaultMenuItemName() {
-        return this.defaultMenuItemName;
-    }
-
-    public String getDefaultPermissionEntityAction() {
-        return this.defaultPermissionEntityAction;
-    }
-
-    public String getDefaultPermissionOperation() {
-        return this.defaultPermissionOperation;
-    }
-
-    public String getDefaultSelectedStyle() {
-        return this.defaultSelectedStyle;
-    }
-
-    public String getDefaultTitleStyle() {
-        return this.defaultTitleStyle;
-    }
-
-    public String getDefaultTooltipStyle() {
-        return this.defaultTooltipStyle;
-    }
-
-    public String getDefaultWidgetStyle() {
-        return this.defaultWidgetStyle;
-    }
-
-    public FlexibleStringExpander getExtraIndex() {
-        return extraIndex;
-    }
-
-    public String getExtraIndex(Map<String, Object> context) {
-        try {
-            return extraIndex.expandString(context);
-        } catch (Exception ex) {
-            return "";
-        }
-    }
-
-    public String getFillStyle() {
-        return this.fillStyle;
-    }
-
-    public String getId() {
-        return this.id;
-    }
-
-    public String getMenuContainerStyle(Map<String, Object> context) {
-        return menuContainerStyleExdr.expandString(context);
-    }
-
-    public FlexibleStringExpander getMenuContainerStyleExdr() {
-        return menuContainerStyleExdr;
-    }
-
-    public List<ModelMenuItem> getMenuItemList() {
-        return menuItemList;
-    }
-
-    public Map<String, ModelMenuItem> getMenuItemMap() {
-        return menuItemMap;
-    }
-
-    public String getMenuLocation() {
-        return menuLocation;
-    }
-
-    public String getMenuWidth() {
-        return this.menuWidth;
-    }
-
-    public ModelMenuItem getModelMenuItemByName(String name) {
-        return this.menuItemMap.get(name);
-    }
-
-    public String getOrientation() {
-        return this.orientation;
-    }
-
-    public ModelMenu getParentMenu() {
-        return parentMenu;
-    }
-
-    public FlexibleMapAccessor<String> getSelectedMenuItemContextFieldName() {
-        return selectedMenuItemContextFieldName;
-    }
-
-    public String getSelectedMenuItemContextFieldName(Map<String, Object> context) {
-        String menuItemName = this.selectedMenuItemContextFieldName.get(context);
-        if (UtilValidate.isEmpty(menuItemName)) {
-            return this.defaultMenuItemName;
-        }
-        return menuItemName;
-    }
-
-    public String getTarget() {
-        return target;
-    }
-
-    public FlexibleStringExpander getTitle() {
-        return title;
-    }
-
-    public String getTitle(Map<String, Object> context) {
-        return title.expandString(context);
-    }
-
-    public String getTooltip() {
-        return this.tooltip;
-    }
-
-    public String getType() {
-        return this.type;
-    }
-
-    public int renderedMenuItemCount(Map<String, Object> context) {
-        int count = 0;
-        for (ModelMenuItem item : this.menuItemList) {
-            if (item.shouldBeRendered(context))
-                count++;
-        }
-        return count;
-    }
-
-    /**
-     * Renders this menu to a String, i.e. in a text format, as defined with the
-     * MenuStringRenderer implementation.
-     *
-     * @param writer The Writer that the menu text will be written to
-     * @param context Map containing the menu context; the following are
-     *   reserved words in this context: parameters (Map), isError (Boolean),
-     *   itemIndex (Integer, for lists only, otherwise null), bshInterpreter,
-     *   menuName (String, optional alternate name for menu, defaults to the
-     *   value of the name attribute)
-     * @param menuStringRenderer An implementation of the MenuStringRenderer
-     *   interface that is responsible for the actual text generation for
-     *   different menu elements; implementing you own makes it possible to
-     *   use the same menu definitions for many types of menu UIs
-     */
-    public void renderMenuString(Appendable writer, Map<String, Object> context, MenuStringRenderer menuStringRenderer)
-            throws IOException {
-        AbstractModelAction.runSubActions(this.actions, context);
-        if ("simple".equals(this.type)) {
-            this.renderSimpleMenuString(writer, context, menuStringRenderer);
-        } else {
-            throw new IllegalArgumentException("The type " + this.getType() + " is not supported for menu with name "
-                    + this.getName());
-        }
-    }
-
-    public void renderSimpleMenuString(Appendable writer, Map<String, Object> context, MenuStringRenderer menuStringRenderer)
-            throws IOException {
-        // render menu open
-        menuStringRenderer.renderMenuOpen(writer, context, this);
-
-        // render formatting wrapper open
-        menuStringRenderer.renderFormatSimpleWrapperOpen(writer, context, this);
-
-        // render each menuItem row, except hidden & ignored rows
-        for (ModelMenuItem item : this.menuItemList) {
-            item.renderMenuItemString(writer, context, menuStringRenderer);
-        }
-        // render formatting wrapper close
-        menuStringRenderer.renderFormatSimpleWrapperClose(writer, context, this);
-
-        // render menu close
-        menuStringRenderer.renderMenuClose(writer, context, this);
-    }
-
-    public void runActions(Map<String, Object> context) {
-        AbstractModelAction.runSubActions(this.actions, context);
-    }
-}
+/*******************************************************************************

+ * Licensed to the Apache Software Foundation (ASF) under one

+ * or more contributor license agreements.  See the NOTICE file

+ * distributed with this work for additional information

+ * regarding copyright ownership.  The ASF licenses this file

+ * to you under the Apache License, Version 2.0 (the

+ * "License"); you may not use this file except in compliance

+ * with the License.  You may obtain a copy of the License at

+ *

+ * http://www.apache.org/licenses/LICENSE-2.0

+ *

+ * Unless required by applicable law or agreed to in writing,

+ * software distributed under the License is distributed on an

+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY

+ * KIND, either express or implied.  See the License for the

+ * specific language governing permissions and limitations

+ * under the License.

+ *******************************************************************************/

+package org.ofbiz.widget.model;

+

+import java.io.IOException;

+import java.util.ArrayList;

+import java.util.Collections;

+import java.util.HashMap;

+import java.util.List;

+import java.util.Map;

+

+import org.ofbiz.base.util.Debug;

+import org.ofbiz.base.util.UtilValidate;

+import org.ofbiz.base.util.UtilXml;

+import org.ofbiz.base.util.collections.FlexibleMapAccessor;

+import org.ofbiz.base.util.string.FlexibleStringExpander;

+import org.ofbiz.widget.renderer.MenuStringRenderer;

+import org.w3c.dom.Element;

+

+/**

+ * Models the &lt;menu&gt; element.

+ * 

+ * @see <code>widget-menu.xsd</code>

+ */

+@SuppressWarnings("serial")

+public class ModelMenu extends ModelWidget {

+

+    /*

+     * ----------------------------------------------------------------------- *

+     *                     DEVELOPERS PLEASE READ

+     * ----------------------------------------------------------------------- *

+     * 

+     * This model is intended to be a read-only data structure that represents

+     * an XML element. Outside of object construction, the class should not

+     * have any behaviors.

+     * 

+     * Instances of this class will be shared by multiple threads - therefore

+     * it is immutable. DO NOT CHANGE THE OBJECT'S STATE AT RUN TIME!

+     * 

+     */

+

+    public static final String module = ModelMenu.class.getName();

+

+    private final List<ModelAction> actions;

+    private final String defaultAlign;

+    private final String defaultAlignStyle;

+    private final FlexibleStringExpander defaultAssociatedContentId;

+    private final String defaultCellWidth;

+    private final String defaultDisabledTitleStyle;

+    private final String defaultEntityName;

+    private final Boolean defaultHideIfSelected;

+    private final String defaultMenuItemName;

+    private final String defaultPermissionEntityAction;

+    private final String defaultPermissionOperation;

+    private final String defaultSelectedStyle;

+    private final String defaultTitleStyle;

+    private final String defaultTooltipStyle;

+    private final String defaultWidgetStyle;

+    private final FlexibleStringExpander extraIndex;

+    private final String fillStyle;

+    private final String id;

+    private final FlexibleStringExpander menuContainerStyleExdr;

+    /** This List will contain one copy of each item for each item name in the order

+     * they were encountered in the service, entity, or menu definition; item definitions

+     * with constraints will also be in this list but may appear multiple times for the same

+     * item name.

+     *

+     * When rendering the menu 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 menu definition to keep the

+     * list clean and implement the override features for item definitions.

+     */

+    private final List<ModelMenuItem> menuItemList;

+    /** This Map is keyed with the item name and has a ModelMenuItem for the value; items

+     * with conditions will not be put in this Map so item definition overrides for items

+     * with conditions is not possible.

+     */

+    private final Map<String, ModelMenuItem> menuItemMap;

+    private final String menuLocation;

+    private final String menuWidth;

+    private final String orientation;

+    private final ModelMenu parentMenu;

+    private final FlexibleMapAccessor<String> selectedMenuItemContextFieldName;

+    private final String target;

+    private final FlexibleStringExpander title;

+    private final String tooltip;

+    private final String type;

+

+    /** XML Constructor */

+    public ModelMenu(Element menuElement, String menuLocation) {

+        super(menuElement);

+        ArrayList<ModelAction> actions = new ArrayList<ModelAction>();

+        String defaultAlign = "";

+        String defaultAlignStyle = "";

+        FlexibleStringExpander defaultAssociatedContentId = FlexibleStringExpander.getInstance("");

+        String defaultCellWidth = "";

+        String defaultDisabledTitleStyle = "";

+        String defaultEntityName = "";

+        Boolean defaultHideIfSelected = Boolean.FALSE;

+        String defaultMenuItemName = "";

+        String defaultPermissionEntityAction = "";

+        String defaultPermissionOperation = "";

+        String defaultSelectedStyle = "";

+        String defaultTitleStyle = "";

+        String defaultTooltipStyle = "";

+        String defaultWidgetStyle = "";

+        FlexibleStringExpander extraIndex = FlexibleStringExpander.getInstance("");

+        String fillStyle = "";

+        String id = "";

+        FlexibleStringExpander menuContainerStyleExdr = FlexibleStringExpander.getInstance("");

+        ArrayList<ModelMenuItem> menuItemList = new ArrayList<ModelMenuItem>();

+        Map<String, ModelMenuItem> menuItemMap = new HashMap<String, ModelMenuItem>();

+        String menuWidth = "";

+        String orientation = "horizontal";

+        FlexibleMapAccessor<String> selectedMenuItemContextFieldName = FlexibleMapAccessor.getInstance("");

+        String target = "";

+        FlexibleStringExpander title = FlexibleStringExpander.getInstance("");

+        String tooltip = "";

+        String type = "";

+        // check if there is a parent menu to inherit from

+        ModelMenu parent = null;

+        String parentResource = menuElement.getAttribute("extends-resource");

+        String parentMenu = menuElement.getAttribute("extends");

+        if (!parentMenu.isEmpty()) {

+            if (!parentResource.isEmpty()) {

+                try {

+                    parent = MenuFactory.getMenuFromLocation(parentResource, parentMenu);

+                } catch (Exception e) {

+                    Debug.logError(e, "Failed to load parent menu definition '" + parentMenu + "' at resource '" + parentResource

+                            + "'", module);

+                }

+            } else {

+                parentResource = menuLocation;

+                // try to find a menu definition in the same file

+                Element rootElement = menuElement.getOwnerDocument().getDocumentElement();

+                List<? extends Element> menuElements = UtilXml.childElementList(rootElement, "menu");

+                for (Element menuElementEntry : menuElements) {

+                    if (menuElementEntry.getAttribute("name").equals(parentMenu)) {

+                        parent = new ModelMenu(menuElementEntry, parentResource);

+                        break;

+                    }

+                }

+                if (parent == null) {

+                    Debug.logError("Failed to find parent menu definition '" + parentMenu + "' in same document.", module);

+                }

+            }

+            if (parent != null) {

+                type = parent.type;

+                target = parent.target;

+                id = parent.id;

+                title = parent.title;

+                tooltip = parent.tooltip;

+                defaultEntityName = parent.defaultEntityName;

+                defaultTitleStyle = parent.defaultTitleStyle;

+                defaultSelectedStyle = parent.defaultSelectedStyle;

+                defaultWidgetStyle = parent.defaultWidgetStyle;

+                defaultTooltipStyle = parent.defaultTooltipStyle;

+                defaultMenuItemName = parent.defaultMenuItemName;

+                menuItemList.addAll(parent.menuItemList);

+                menuItemMap.putAll(parent.menuItemMap);

+                defaultPermissionOperation = parent.defaultPermissionOperation;

+                defaultPermissionEntityAction = parent.defaultPermissionEntityAction;

+                defaultAssociatedContentId = parent.defaultAssociatedContentId;

+                defaultHideIfSelected = parent.defaultHideIfSelected;

+                orientation = parent.orientation;

+                menuWidth = parent.menuWidth;

+                defaultCellWidth = parent.defaultCellWidth;

+                defaultDisabledTitleStyle = parent.defaultDisabledTitleStyle;

+                defaultAlign = parent.defaultAlign;

+                defaultAlignStyle = parent.defaultAlignStyle;

+                fillStyle = parent.fillStyle;

+                extraIndex = parent.extraIndex;

+                selectedMenuItemContextFieldName = parent.selectedMenuItemContextFieldName;

+                menuContainerStyleExdr = parent.menuContainerStyleExdr;

+                if (parent.actions != null) {

+                    actions.addAll(parent.actions);

+                }

+            }

+        }

+        if (!menuElement.getAttribute("type").isEmpty())

+            type = menuElement.getAttribute("type");

+        if (!menuElement.getAttribute("target").isEmpty())

+            target = menuElement.getAttribute("target");

+        if (!menuElement.getAttribute("id").isEmpty())

+            id = menuElement.getAttribute("id");

+        if (!menuElement.getAttribute("title").isEmpty())

+            title = FlexibleStringExpander.getInstance(menuElement.getAttribute("title"));

+        if (!menuElement.getAttribute("tooltip").isEmpty())

+            tooltip = menuElement.getAttribute("tooltip");

+        if (!menuElement.getAttribute("default-entity-name").isEmpty())

+            defaultEntityName = menuElement.getAttribute("default-entity-name");

+        if (!menuElement.getAttribute("default-title-style").isEmpty())

+            defaultTitleStyle = menuElement.getAttribute("default-title-style");

+        if (!menuElement.getAttribute("default-selected-style").isEmpty())

+            defaultSelectedStyle = menuElement.getAttribute("default-selected-style");

+        if (!menuElement.getAttribute("default-widget-style").isEmpty())

+            defaultWidgetStyle = menuElement.getAttribute("default-widget-style");

+        if (!menuElement.getAttribute("default-tooltip-style").isEmpty())

+            defaultTooltipStyle = menuElement.getAttribute("default-tooltip-style");

+        if (!menuElement.getAttribute("default-menu-item-name").isEmpty())

+            defaultMenuItemName = menuElement.getAttribute("default-menu-item-name");

+        if (!menuElement.getAttribute("default-permission-operation").isEmpty())

+            defaultPermissionOperation = menuElement.getAttribute("default-permission-operation");

+        if (!menuElement.getAttribute("default-permission-entity-action").isEmpty())

+            defaultPermissionEntityAction = menuElement.getAttribute("default-permission-entity-action");

+        if (!menuElement.getAttribute("default-associated-content-id").isEmpty())

+            defaultAssociatedContentId = FlexibleStringExpander.getInstance(menuElement

+                    .getAttribute("default-associated-content-id"));

+        if (!menuElement.getAttribute("orientation").isEmpty())

+            orientation = menuElement.getAttribute("orientation");

+        if (!menuElement.getAttribute("menu-width").isEmpty())

+            menuWidth = menuElement.getAttribute("menu-width");

+        if (!menuElement.getAttribute("default-cell-width").isEmpty())

+            defaultCellWidth = menuElement.getAttribute("default-cell-width");

+        if (!menuElement.getAttribute("default-hide-if-selected").isEmpty())

+            defaultHideIfSelected = "true".equals(menuElement.getAttribute("default-hide-if-selected").isEmpty());

+        if (!menuElement.getAttribute("default-disabled-title-style").isEmpty())

+            defaultDisabledTitleStyle = menuElement.getAttribute("default-disabled-title-style");

+        if (!menuElement.getAttribute("selected-menuitem-context-field-name").isEmpty())

+            selectedMenuItemContextFieldName = FlexibleMapAccessor.getInstance(menuElement

+                    .getAttribute("selected-menuitem-context-field-name"));

+        if (!menuElement.getAttribute("menu-container-style").isEmpty())

+            menuContainerStyleExdr = FlexibleStringExpander.getInstance(menuElement.getAttribute("menu-container-style"));

+        if (!menuElement.getAttribute("default-align").isEmpty())

+            defaultAlign = menuElement.getAttribute("default-align");

+        if (!menuElement.getAttribute("default-align-style").isEmpty())

+            defaultAlignStyle = menuElement.getAttribute("default-align-style");

+        if (!menuElement.getAttribute("fill-style").isEmpty())

+            fillStyle = menuElement.getAttribute("fill-style");

+        if (!menuElement.getAttribute("extra-index").isEmpty())

+            extraIndex = FlexibleStringExpander.getInstance(menuElement.getAttribute("extra-index"));

+        // read all actions under the "actions" element

+        Element actionsElement = UtilXml.firstChildElement(menuElement, "actions");

+        if (actionsElement != null) {

+            actions.addAll(ModelMenuAction.readSubActions(this, actionsElement));

+        }

+        actions.trimToSize();

+        this.actions = Collections.unmodifiableList(actions);

+        this.defaultAlign = defaultAlign;

+        this.defaultAlignStyle = defaultAlignStyle;

+        this.defaultAssociatedContentId = defaultAssociatedContentId;

+        this.defaultCellWidth = defaultCellWidth;

+        this.defaultDisabledTitleStyle = defaultDisabledTitleStyle;

+        this.defaultEntityName = defaultEntityName;

+        this.defaultHideIfSelected = defaultHideIfSelected;

+        this.defaultMenuItemName = defaultMenuItemName;

+        this.defaultPermissionEntityAction = defaultPermissionEntityAction;

+        this.defaultPermissionOperation = defaultPermissionOperation;

+        this.defaultSelectedStyle = defaultSelectedStyle;

+        this.defaultTitleStyle = defaultTitleStyle;

+        this.defaultTooltipStyle = defaultTooltipStyle;

+        this.defaultWidgetStyle = defaultWidgetStyle;

+        this.extraIndex = extraIndex;

+        this.fillStyle = fillStyle;

+        this.id = id;

+        this.menuContainerStyleExdr = menuContainerStyleExdr;

+        List<? extends Element> itemElements = UtilXml.childElementList(menuElement, "menu-item");

+        for (Element itemElement : itemElements) {

+            ModelMenuItem modelMenuItem = new ModelMenuItem(itemElement, this);

+            addUpdateMenuItem(modelMenuItem, menuItemList, menuItemMap);

+        }

+        menuItemList.trimToSize();

+        this.menuItemList = Collections.unmodifiableList(menuItemList);

+        this.menuItemMap = Collections.unmodifiableMap(menuItemMap);

+        this.menuLocation = menuLocation;

+        this.menuWidth = menuWidth;

+        this.orientation = orientation;

+        this.parentMenu = parent;

+        this.selectedMenuItemContextFieldName = selectedMenuItemContextFieldName;

+        this.target = target;

+        this.title = title;

+        this.tooltip = tooltip;

+        this.type = type;

+    }

+

+    @Override

+    public void accept(ModelWidgetVisitor visitor) throws Exception {

+        visitor.visit(this);

+    }

+

+    /**

+     * add/override modelMenuItem using the menuItemList and menuItemMap

+     *

+     */

+    private void addUpdateMenuItem(ModelMenuItem modelMenuItem, List<ModelMenuItem> menuItemList,

+            Map<String, ModelMenuItem> menuItemMap) {

+        ModelMenuItem existingMenuItem = menuItemMap.get(modelMenuItem.getName());

+        if (existingMenuItem != null) {

+            // does exist, update the item by doing a merge/override

+            ModelMenuItem mergedMenuItem = existingMenuItem.mergeOverrideModelMenuItem(modelMenuItem);

+            int existingItemIndex = menuItemList.indexOf(existingMenuItem);

+            menuItemList.set(existingItemIndex, mergedMenuItem);

+            menuItemMap.put(modelMenuItem.getName(), mergedMenuItem);

+        } else {

+            // does not exist, add to Map

+            menuItemList.add(modelMenuItem);

+            menuItemMap.put(modelMenuItem.getName(), modelMenuItem);

+        }

+    }

+

+    public List<ModelAction> getActions() {

+        return actions;

+    }

+

+    @Override

+    public String getBoundaryCommentName() {

+        return menuLocation + "#" + getName();

+    }

+

+    public String getCurrentMenuName(Map<String, Object> context) {

+        return getName();

+    }

+

+    public String getDefaultAlign() {

+        return this.defaultAlign;

+    }

+

+    public String getDefaultAlignStyle() {

+        return this.defaultAlignStyle;

+    }

+

+    public FlexibleStringExpander getDefaultAssociatedContentId() {

+        return defaultAssociatedContentId;

+    }

+

+    public String getDefaultAssociatedContentId(Map<String, Object> context) {

+        return defaultAssociatedContentId.expandString(context);

+    }

+

+    public String getDefaultCellWidth() {

+        return this.defaultCellWidth;

+    }

+

+    public String getDefaultDisabledTitleStyle() {

+        return this.defaultDisabledTitleStyle;

+    }

+

+    public String getDefaultEntityName() {

+        return this.defaultEntityName;

+    }

+

+    public Boolean getDefaultHideIfSelected() {

+        return this.defaultHideIfSelected;

+    }

+

+    public String getDefaultMenuItemName() {

+        return this.defaultMenuItemName;

+    }

+

+    public String getDefaultPermissionEntityAction() {

+        return this.defaultPermissionEntityAction;

+    }

+

+    public String getDefaultPermissionOperation() {

+        return this.defaultPermissionOperation;

+    }

+

+    public String getDefaultSelectedStyle() {

+        return this.defaultSelectedStyle;

+    }

+

+    public String getDefaultTitleStyle() {

+        return this.defaultTitleStyle;

+    }

+

+    public String getDefaultTooltipStyle() {

+        return this.defaultTooltipStyle;

+    }

+

+    public String getDefaultWidgetStyle() {

+        return this.defaultWidgetStyle;

+    }

+

+    public FlexibleStringExpander getExtraIndex() {

+        return extraIndex;

+    }

+

+    public String getExtraIndex(Map<String, Object> context) {

+        try {

+            return extraIndex.expandString(context);

+        } catch (Exception ex) {

+            return "";

+        }

+    }

+

+    public String getFillStyle() {

+        return this.fillStyle;

+    }

+

+    public String getId() {

+        return this.id;

+    }

+

+    public String getMenuContainerStyle(Map<String, Object> context) {

+        return menuContainerStyleExdr.expandString(context);

+    }

+

+    public FlexibleStringExpander getMenuContainerStyleExdr() {

+        return menuContainerStyleExdr;

+    }

+

+    public List<ModelMenuItem> getMenuItemList() {

+        return menuItemList;

+    }

+

+    public Map<String, ModelMenuItem> getMenuItemMap() {

+        return menuItemMap;

+    }

+

+    public String getMenuLocation() {

+        return menuLocation;

+    }

+

+    public String getMenuWidth() {

+        return this.menuWidth;

+    }

+

+    public ModelMenuItem getModelMenuItemByName(String name) {

+        return this.menuItemMap.get(name);

+    }

+

+    public String getOrientation() {

+        return this.orientation;

+    }

+

+    public ModelMenu getParentMenu() {

+        return parentMenu;

+    }

+

+    public FlexibleMapAccessor<String> getSelectedMenuItemContextFieldName() {

+        return selectedMenuItemContextFieldName;

+    }

+

+    public String getSelectedMenuItemContextFieldName(Map<String, Object> context) {

+        String menuItemName = this.selectedMenuItemContextFieldName.get(context);

+        if (UtilValidate.isEmpty(menuItemName)) {

+            return this.defaultMenuItemName;

+        }

+        return menuItemName;

+    }

+

+    public String getTarget() {

+        return target;

+    }

+

+    public FlexibleStringExpander getTitle() {

+        return title;

+    }

+

+    public String getTitle(Map<String, Object> context) {

+        return title.expandString(context);

+    }

+

+    public String getTooltip() {

+        return this.tooltip;

+    }

+

+    public String getType() {

+        return this.type;

+    }

+

+    public int renderedMenuItemCount(Map<String, Object> context) {

+        int count = 0;

+        for (ModelMenuItem item : this.menuItemList) {

+            if (item.shouldBeRendered(context))

+                count++;

+        }

+        return count;

+    }

+

+    /**

+     * Renders this menu to a String, i.e. in a text format, as defined with the

+     * MenuStringRenderer implementation.

+     *

+     * @param writer The Writer that the menu text will be written to

+     * @param context Map containing the menu context; the following are

+     *   reserved words in this context: parameters (Map), isError (Boolean),

+     *   itemIndex (Integer, for lists only, otherwise null), bshInterpreter,

+     *   menuName (String, optional alternate name for menu, defaults to the

+     *   value of the name attribute)

+     * @param menuStringRenderer An implementation of the MenuStringRenderer

+     *   interface that is responsible for the actual text generation for

+     *   different menu elements; implementing you own makes it possible to

+     *   use the same menu definitions for many types of menu UIs

+     */

+    public void renderMenuString(Appendable writer, Map<String, Object> context, MenuStringRenderer menuStringRenderer)

+            throws IOException {

+        AbstractModelAction.runSubActions(this.actions, context);

+        if ("simple".equals(this.type)) {

+            this.renderSimpleMenuString(writer, context, menuStringRenderer);

+        } else {

+            throw new IllegalArgumentException("The type " + this.getType() + " is not supported for menu with name "

+                    + this.getName());

+        }

+    }

+

+    public void renderSimpleMenuString(Appendable writer, Map<String, Object> context, MenuStringRenderer menuStringRenderer)

+            throws IOException {

+        // render menu open

+        menuStringRenderer.renderMenuOpen(writer, context, this);

+

+        // render formatting wrapper open

+        menuStringRenderer.renderFormatSimpleWrapperOpen(writer, context, this);

+

+        // render each menuItem row, except hidden & ignored rows

+        for (ModelMenuItem item : this.menuItemList) {

+            item.renderMenuItemString(writer, context, menuStringRenderer);

+        }

+        // render formatting wrapper close

+        menuStringRenderer.renderFormatSimpleWrapperClose(writer, context, this);

+

+        // render menu close

+        menuStringRenderer.renderMenuClose(writer, context, this);

+    }

+

+    public void runActions(Map<String, Object> context) {

+        AbstractModelAction.runSubActions(this.actions, context);

+    }

+}

diff --git a/framework/widget/src/org/ofbiz/widget/menu/ModelMenuAction.java b/framework/widget/src/org/ofbiz/widget/model/ModelMenuAction.java
similarity index 98%
rename from framework/widget/src/org/ofbiz/widget/menu/ModelMenuAction.java
rename to framework/widget/src/org/ofbiz/widget/model/ModelMenuAction.java
index 31e3ae4..7351724 100644
--- a/framework/widget/src/org/ofbiz/widget/menu/ModelMenuAction.java
+++ b/framework/widget/src/org/ofbiz/widget/model/ModelMenuAction.java
@@ -1,234 +1,232 @@
-/*******************************************************************************
- * 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.menu;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-import java.util.TimeZone;
-
-import javax.servlet.ServletContext;
-import javax.servlet.http.HttpSession;
-
-import org.ofbiz.base.util.Debug;
-import org.ofbiz.base.util.GeneralException;
-import org.ofbiz.base.util.ObjectType;
-import org.ofbiz.base.util.UtilGenerics;
-import org.ofbiz.base.util.UtilValidate;
-import org.ofbiz.base.util.UtilXml;
-import org.ofbiz.base.util.collections.FlexibleMapAccessor;
-import org.ofbiz.base.util.string.FlexibleStringExpander;
-import org.ofbiz.widget.ModelActionVisitor;
-import org.ofbiz.widget.*;
-import org.w3c.dom.Element;
-
-/**
- * Abstract menu action.
- */
-public abstract class ModelMenuAction {
-
-    public static final String module = ModelMenuAction.class.getName();
-
-    public static List<ModelAction> readSubActions(ModelMenu modelMenu, Element parentElement) {
-        List<? extends Element> actionElementList = UtilXml.childElementList(parentElement);
-        List<ModelAction> actions = new ArrayList<ModelAction>(actionElementList.size());
-        for (Element actionElement : actionElementList) {
-            if ("set".equals(actionElement.getNodeName())) {
-                actions.add(new SetField(modelMenu, actionElement));
-            } else {
-                actions.add(AbstractModelAction.newInstance(modelMenu, actionElement));
-            }
-        }
-        return Collections.unmodifiableList(actions);
-    }
-
-    /**
-     * Models the &lt;set&gt; element.
-     * 
-     * @see <code>widget-common.xsd</code>
-     */
-    @SuppressWarnings("serial")
-    public static class SetField extends AbstractModelAction {
-        private final FlexibleMapAccessor<Object> field;
-        private final FlexibleMapAccessor<Object> fromField;
-        private final FlexibleStringExpander valueExdr;
-        private final FlexibleStringExpander defaultExdr;
-        private final FlexibleStringExpander globalExdr;
-        private final String type;
-        private final String toScope;
-        private final String fromScope;
-
-        public SetField(ModelMenu modelMenu, Element setElement) {
-            super (modelMenu, setElement);
-            this.field = FlexibleMapAccessor.getInstance(setElement.getAttribute("field"));
-            this.fromField = FlexibleMapAccessor.getInstance(setElement.getAttribute("from-field"));
-            this.valueExdr = FlexibleStringExpander.getInstance(setElement.getAttribute("value"));
-            this.defaultExdr = UtilValidate.isNotEmpty(setElement.getAttribute("default-value")) ? FlexibleStringExpander.getInstance(setElement.getAttribute("default-value")) : null;
-            this.globalExdr = FlexibleStringExpander.getInstance(setElement.getAttribute("global"));
-            this.type = setElement.getAttribute("type");
-            this.toScope = setElement.getAttribute("to-scope");
-            this.fromScope = setElement.getAttribute("from-scope");
-            if (!this.fromField.isEmpty() && !this.valueExdr.isEmpty()) {
-                throw new IllegalArgumentException("Cannot specify a from-field [" + setElement.getAttribute("from-field") + "] and a value [" + setElement.getAttribute("value") + "] on the set action in a screen widget");
-            }
-        }
-
-        @SuppressWarnings("rawtypes")
-        @Override
-        public void runAction(Map<String, Object> context) {
-            String globalStr = this.globalExdr.expandString(context);
-            // default to false
-            boolean global = "true".equals(globalStr);
-
-            Object newValue = null;
-            if (this.fromScope != null && this.fromScope.equals("user")) {
-                if (!this.fromField.isEmpty()) {
-                    String originalName = this.fromField.getOriginalName();
-                    String currentWidgetTrail = (String)context.get("_WIDGETTRAIL_");
-                    String newKey = currentWidgetTrail + "|" + originalName;
-                    HttpSession session = (HttpSession)context.get("session");
-                    newValue = session.getAttribute(newKey);
-                    if (Debug.verboseOn()) Debug.logVerbose("In user getting value for field from [" + this.fromField.getOriginalName() + "]: " + newValue, module);
-                } else if (!this.valueExdr.isEmpty()) {
-                    newValue = this.valueExdr.expandString(context);
-                }
-
-            } else if (this.fromScope != null && this.fromScope.equals("application")) {
-                if (!this.fromField.isEmpty()) {
-                    String originalName = this.fromField.getOriginalName();
-                    String currentWidgetTrail = (String)context.get("_WIDGETTRAIL_");
-                    String newKey = currentWidgetTrail + "|" + originalName;
-                    ServletContext servletContext = (ServletContext)context.get("application");
-                    newValue = servletContext.getAttribute(newKey);
-                    if (Debug.verboseOn()) Debug.logVerbose("In application getting value for field from [" + this.fromField.getOriginalName() + "]: " + newValue, module);
-                } else if (!this.valueExdr.isEmpty()) {
-                    newValue = this.valueExdr.expandString(context);
-                }
-
-            } else {
-                if (!this.fromField.isEmpty()) {
-                    newValue = this.fromField.get(context);
-                    if (Debug.verboseOn()) Debug.logVerbose("In screen getting value for field from [" + this.fromField.getOriginalName() + "]: " + newValue, module);
-                } else if (!this.valueExdr.isEmpty()) {
-                    newValue = this.valueExdr.expandString(context);
-                }
-            }
-
-            // If newValue is still empty, use the default value
-               if (this.defaultExdr != null) {
-                   if (ObjectType.isEmpty(newValue)) {
-                    newValue = this.defaultExdr.expandString(context);
-                   }
-            }
-
-            if (UtilValidate.isNotEmpty(this.type)) {
-                if ("NewMap".equals(this.type)) {
-                    newValue = new HashMap();
-                } else if ("NewList".equals(this.type)) {
-                    newValue = new LinkedList();
-                } else {
-                    try {
-                        newValue = ObjectType.simpleTypeConvert(newValue, this.type, null, (TimeZone) context.get("timeZone"), (Locale) context.get("locale"), true);
-                    } catch (GeneralException e) {
-                        String errMsg = "Could not convert field value for the field: [" + this.field.getOriginalName() + "] to the [" + this.type + "] type for the value [" + newValue + "]: " + e.toString();
-                        Debug.logError(e, errMsg, module);
-                        throw new IllegalArgumentException(errMsg);
-                    }
-                }
-            }
-            if (this.toScope != null && this.toScope.equals("user")) {
-                    String originalName = this.field.getOriginalName();
-                    String currentWidgetTrail = (String)context.get("_WIDGETTRAIL_");
-                    String newKey = currentWidgetTrail + "|" + originalName;
-                    HttpSession session = (HttpSession)context.get("session");
-                    session.setAttribute(newKey, newValue);
-                    if (Debug.verboseOn()) Debug.logVerbose("In user setting value for field from [" + this.field.getOriginalName() + "]: " + newValue, module);
-
-            } else if (this.toScope != null && this.toScope.equals("application")) {
-                    String originalName = this.field.getOriginalName();
-                    String currentWidgetTrail = (String)context.get("_WIDGETTRAIL_");
-                    String newKey = currentWidgetTrail + "|" + originalName;
-                    ServletContext servletContext = (ServletContext)context.get("application");
-                    servletContext.setAttribute(newKey, newValue);
-                    if (Debug.verboseOn()) Debug.logVerbose("In application setting value for field from [" + this.field.getOriginalName() + "]: " + newValue, module);
-
-            } else {
-                if (Debug.verboseOn()) Debug.logVerbose("In screen setting field [" + this.field.getOriginalName() + "] to value: " + newValue, module);
-                this.field.put(context, newValue);
-            }
-
-            if (global) {
-                Map<String, Object> globalCtx = UtilGenerics.checkMap(context.get("globalContext"));
-                if (globalCtx != null) {
-                    this.field.put(globalCtx, newValue);
-                }
-            }
-
-            // this is a hack for backward compatibility with the JPublish page object
-            Map<String, Object> page = UtilGenerics.checkMap(context.get("page"));
-            if (page != null) {
-                this.field.put(page, newValue);
-            }
-        }
-
-        @Override
-        public void accept(ModelActionVisitor visitor) throws Exception {
-            visitor.visit(this);
-        }
-
-        public FlexibleMapAccessor<Object> getField() {
-            return field;
-        }
-
-        public FlexibleMapAccessor<Object> getFromField() {
-            return fromField;
-        }
-
-        public FlexibleStringExpander getValueExdr() {
-            return valueExdr;
-        }
-
-        public FlexibleStringExpander getDefaultExdr() {
-            return defaultExdr;
-        }
-
-        public FlexibleStringExpander getGlobalExdr() {
-            return globalExdr;
-        }
-
-        public String getType() {
-            return type;
-        }
-
-        public String getToScope() {
-            return toScope;
-        }
-
-        public String getFromScope() {
-            return fromScope;
-        }
-    }
-}
-
-
-
+/*******************************************************************************

+ * Licensed to the Apache Software Foundation (ASF) under one

+ * or more contributor license agreements.  See the NOTICE file

+ * distributed with this work for additional information

+ * regarding copyright ownership.  The ASF licenses this file

+ * to you under the Apache License, Version 2.0 (the

+ * "License"); you may not use this file except in compliance

+ * with the License.  You may obtain a copy of the License at

+ *

+ * http://www.apache.org/licenses/LICENSE-2.0

+ *

+ * Unless required by applicable law or agreed to in writing,

+ * software distributed under the License is distributed on an

+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY

+ * KIND, either express or implied.  See the License for the

+ * specific language governing permissions and limitations

+ * under the License.

+ *******************************************************************************/

+package org.ofbiz.widget.model;

+

+import java.util.ArrayList;

+import java.util.Collections;

+import java.util.HashMap;

+import java.util.LinkedList;

+import java.util.List;

+import java.util.Locale;

+import java.util.Map;

+import java.util.TimeZone;

+

+import javax.servlet.ServletContext;

+import javax.servlet.http.HttpSession;

+

+import org.ofbiz.base.util.Debug;

+import org.ofbiz.base.util.GeneralException;

+import org.ofbiz.base.util.ObjectType;

+import org.ofbiz.base.util.UtilGenerics;

+import org.ofbiz.base.util.UtilValidate;

+import org.ofbiz.base.util.UtilXml;

+import org.ofbiz.base.util.collections.FlexibleMapAccessor;

+import org.ofbiz.base.util.string.FlexibleStringExpander;

+import org.w3c.dom.Element;

+

+/**

+ * Abstract menu action.

+ */

+public abstract class ModelMenuAction {

+

+    public static final String module = ModelMenuAction.class.getName();

+

+    public static List<ModelAction> readSubActions(ModelMenu modelMenu, Element parentElement) {

+        List<? extends Element> actionElementList = UtilXml.childElementList(parentElement);

+        List<ModelAction> actions = new ArrayList<ModelAction>(actionElementList.size());

+        for (Element actionElement : actionElementList) {

+            if ("set".equals(actionElement.getNodeName())) {

+                actions.add(new SetField(modelMenu, actionElement));

+            } else {

+                actions.add(AbstractModelAction.newInstance(modelMenu, actionElement));

+            }

+        }

+        return Collections.unmodifiableList(actions);

+    }

+

+    /**

+     * Models the &lt;set&gt; element.

+     * 

+     * @see <code>widget-common.xsd</code>

+     */

+    @SuppressWarnings("serial")

+    public static class SetField extends AbstractModelAction {

+        private final FlexibleMapAccessor<Object> field;

+        private final FlexibleMapAccessor<Object> fromField;

+        private final FlexibleStringExpander valueExdr;

+        private final FlexibleStringExpander defaultExdr;

+        private final FlexibleStringExpander globalExdr;

+        private final String type;

+        private final String toScope;

+        private final String fromScope;

+

+        public SetField(ModelMenu modelMenu, Element setElement) {

+            super (modelMenu, setElement);

+            this.field = FlexibleMapAccessor.getInstance(setElement.getAttribute("field"));

+            this.fromField = FlexibleMapAccessor.getInstance(setElement.getAttribute("from-field"));

+            this.valueExdr = FlexibleStringExpander.getInstance(setElement.getAttribute("value"));

+            this.defaultExdr = UtilValidate.isNotEmpty(setElement.getAttribute("default-value")) ? FlexibleStringExpander.getInstance(setElement.getAttribute("default-value")) : null;

+            this.globalExdr = FlexibleStringExpander.getInstance(setElement.getAttribute("global"));

+            this.type = setElement.getAttribute("type");

+            this.toScope = setElement.getAttribute("to-scope");

+            this.fromScope = setElement.getAttribute("from-scope");

+            if (!this.fromField.isEmpty() && !this.valueExdr.isEmpty()) {

+                throw new IllegalArgumentException("Cannot specify a from-field [" + setElement.getAttribute("from-field") + "] and a value [" + setElement.getAttribute("value") + "] on the set action in a screen widget");

+            }

+        }

+

+        @SuppressWarnings("rawtypes")

+        @Override

+        public void runAction(Map<String, Object> context) {

+            String globalStr = this.globalExdr.expandString(context);

+            // default to false

+            boolean global = "true".equals(globalStr);

+

+            Object newValue = null;

+            if (this.fromScope != null && this.fromScope.equals("user")) {

+                if (!this.fromField.isEmpty()) {

+                    String originalName = this.fromField.getOriginalName();

+                    String currentWidgetTrail = (String)context.get("_WIDGETTRAIL_");

+                    String newKey = currentWidgetTrail + "|" + originalName;

+                    HttpSession session = (HttpSession)context.get("session");

+                    newValue = session.getAttribute(newKey);

+                    if (Debug.verboseOn()) Debug.logVerbose("In user getting value for field from [" + this.fromField.getOriginalName() + "]: " + newValue, module);

+                } else if (!this.valueExdr.isEmpty()) {

+                    newValue = this.valueExdr.expandString(context);

+                }

+

+            } else if (this.fromScope != null && this.fromScope.equals("application")) {

+                if (!this.fromField.isEmpty()) {

+                    String originalName = this.fromField.getOriginalName();

+                    String currentWidgetTrail = (String)context.get("_WIDGETTRAIL_");

+                    String newKey = currentWidgetTrail + "|" + originalName;

+                    ServletContext servletContext = (ServletContext)context.get("application");

+                    newValue = servletContext.getAttribute(newKey);

+                    if (Debug.verboseOn()) Debug.logVerbose("In application getting value for field from [" + this.fromField.getOriginalName() + "]: " + newValue, module);

+                } else if (!this.valueExdr.isEmpty()) {

+                    newValue = this.valueExdr.expandString(context);

+                }

+

+            } else {

+                if (!this.fromField.isEmpty()) {

+                    newValue = this.fromField.get(context);

+                    if (Debug.verboseOn()) Debug.logVerbose("In screen getting value for field from [" + this.fromField.getOriginalName() + "]: " + newValue, module);

+                } else if (!this.valueExdr.isEmpty()) {

+                    newValue = this.valueExdr.expandString(context);

+                }

+            }

+

+            // If newValue is still empty, use the default value

+               if (this.defaultExdr != null) {

+                   if (ObjectType.isEmpty(newValue)) {

+                    newValue = this.defaultExdr.expandString(context);

+                   }

+            }

+

+            if (UtilValidate.isNotEmpty(this.type)) {

+                if ("NewMap".equals(this.type)) {

+                    newValue = new HashMap();

+                } else if ("NewList".equals(this.type)) {

+                    newValue = new LinkedList();

+                } else {

+                    try {

+                        newValue = ObjectType.simpleTypeConvert(newValue, this.type, null, (TimeZone) context.get("timeZone"), (Locale) context.get("locale"), true);

+                    } catch (GeneralException e) {

+                        String errMsg = "Could not convert field value for the field: [" + this.field.getOriginalName() + "] to the [" + this.type + "] type for the value [" + newValue + "]: " + e.toString();

+                        Debug.logError(e, errMsg, module);

+                        throw new IllegalArgumentException(errMsg);

+                    }

+                }

+            }

+            if (this.toScope != null && this.toScope.equals("user")) {

+                    String originalName = this.field.getOriginalName();

+                    String currentWidgetTrail = (String)context.get("_WIDGETTRAIL_");

+                    String newKey = currentWidgetTrail + "|" + originalName;

+                    HttpSession session = (HttpSession)context.get("session");

+                    session.setAttribute(newKey, newValue);

+                    if (Debug.verboseOn()) Debug.logVerbose("In user setting value for field from [" + this.field.getOriginalName() + "]: " + newValue, module);

+

+            } else if (this.toScope != null && this.toScope.equals("application")) {

+                    String originalName = this.field.getOriginalName();

+                    String currentWidgetTrail = (String)context.get("_WIDGETTRAIL_");

+                    String newKey = currentWidgetTrail + "|" + originalName;

+                    ServletContext servletContext = (ServletContext)context.get("application");

+                    servletContext.setAttribute(newKey, newValue);

+                    if (Debug.verboseOn()) Debug.logVerbose("In application setting value for field from [" + this.field.getOriginalName() + "]: " + newValue, module);

+

+            } else {

+                if (Debug.verboseOn()) Debug.logVerbose("In screen setting field [" + this.field.getOriginalName() + "] to value: " + newValue, module);

+                this.field.put(context, newValue);

+            }

+

+            if (global) {

+                Map<String, Object> globalCtx = UtilGenerics.checkMap(context.get("globalContext"));

+                if (globalCtx != null) {

+                    this.field.put(globalCtx, newValue);

+                }

+            }

+

+            // this is a hack for backward compatibility with the JPublish page object

+            Map<String, Object> page = UtilGenerics.checkMap(context.get("page"));

+            if (page != null) {

+                this.field.put(page, newValue);

+            }

+        }

+

+        @Override

+        public void accept(ModelActionVisitor visitor) throws Exception {

+            visitor.visit(this);

+        }

+

+        public FlexibleMapAccessor<Object> getField() {

+            return field;

+        }

+

+        public FlexibleMapAccessor<Object> getFromField() {

+            return fromField;

+        }

+

+        public FlexibleStringExpander getValueExdr() {

+            return valueExdr;

+        }

+

+        public FlexibleStringExpander getDefaultExdr() {

+            return defaultExdr;

+        }

+

+        public FlexibleStringExpander getGlobalExdr() {

+            return globalExdr;

+        }

+

+        public String getType() {

+            return type;

+        }

+

+        public String getToScope() {

+            return toScope;

+        }

+

+        public String getFromScope() {

+            return fromScope;

+        }

+    }

+}

+

+

+

diff --git a/framework/widget/src/org/ofbiz/widget/menu/ModelMenuCondition.java b/framework/widget/src/org/ofbiz/widget/model/ModelMenuCondition.java
similarity index 95%
rename from framework/widget/src/org/ofbiz/widget/menu/ModelMenuCondition.java
rename to framework/widget/src/org/ofbiz/widget/model/ModelMenuCondition.java
index bd0e9f1..b9aec8c 100644
--- a/framework/widget/src/org/ofbiz/widget/menu/ModelMenuCondition.java
+++ b/framework/widget/src/org/ofbiz/widget/model/ModelMenuCondition.java
@@ -1,70 +1,68 @@
-/*******************************************************************************
- * 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.menu;
-
-import org.ofbiz.base.util.string.FlexibleStringExpander;
-import org.ofbiz.widget.AbstractModelCondition;
-import org.ofbiz.widget.ModelCondition;
-import org.w3c.dom.Element;
-
-/**
- * Models the &lt;condition&gt; element.
- * 
- * @see <code>widget-menu.xsd</code>
- */
-public final class ModelMenuCondition {
-
-    /*
-     * ----------------------------------------------------------------------- *
-     *                     DEVELOPERS PLEASE READ
-     * ----------------------------------------------------------------------- *
-     * 
-     * This model is intended to be a read-only data structure that represents
-     * an XML element. Outside of object construction, the class should not
-     * have any behaviors.
-     * 
-     * Instances of this class will be shared by multiple threads - therefore
-     * it is immutable. DO NOT CHANGE THE OBJECT'S STATE AT RUN TIME!
-     * 
-     */
-
-    public static final String module = ModelMenuCondition.class.getName();
-
-    private final FlexibleStringExpander passStyleExdr;
-    private final FlexibleStringExpander failStyleExdr;
-    private final ModelCondition condition;
-
-    public ModelMenuCondition(ModelMenuItem modelMenuItem, Element conditionElement) {
-        this.passStyleExdr = FlexibleStringExpander.getInstance(conditionElement.getAttribute("pass-style"));
-        this.failStyleExdr = FlexibleStringExpander.getInstance(conditionElement.getAttribute("disabled-style"));
-        this.condition = AbstractModelCondition.DEFAULT_CONDITION_FACTORY.newInstance(modelMenuItem, conditionElement);
-    }
-
-    public ModelCondition getCondition() {
-        return condition;
-    }
-
-    public FlexibleStringExpander getFailStyleExdr() {
-        return failStyleExdr;
-    }
-
-    public FlexibleStringExpander getPassStyleExdr() {
-        return passStyleExdr;
-    }
-}
+/*******************************************************************************

+ * Licensed to the Apache Software Foundation (ASF) under one

+ * or more contributor license agreements.  See the NOTICE file

+ * distributed with this work for additional information

+ * regarding copyright ownership.  The ASF licenses this file

+ * to you under the Apache License, Version 2.0 (the

+ * "License"); you may not use this file except in compliance

+ * with the License.  You may obtain a copy of the License at

+ *

+ * http://www.apache.org/licenses/LICENSE-2.0

+ *

+ * Unless required by applicable law or agreed to in writing,

+ * software distributed under the License is distributed on an

+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY

+ * KIND, either express or implied.  See the License for the

+ * specific language governing permissions and limitations

+ * under the License.

+ *******************************************************************************/

+package org.ofbiz.widget.model;

+

+import org.ofbiz.base.util.string.FlexibleStringExpander;

+import org.w3c.dom.Element;

+

+/**

+ * Models the &lt;condition&gt; element.

+ * 

+ * @see <code>widget-menu.xsd</code>

+ */

+public final class ModelMenuCondition {

+

+    /*

+     * ----------------------------------------------------------------------- *

+     *                     DEVELOPERS PLEASE READ

+     * ----------------------------------------------------------------------- *

+     * 

+     * This model is intended to be a read-only data structure that represents

+     * an XML element. Outside of object construction, the class should not

+     * have any behaviors.

+     * 

+     * Instances of this class will be shared by multiple threads - therefore

+     * it is immutable. DO NOT CHANGE THE OBJECT'S STATE AT RUN TIME!

+     * 

+     */

+

+    public static final String module = ModelMenuCondition.class.getName();

+

+    private final FlexibleStringExpander passStyleExdr;

+    private final FlexibleStringExpander failStyleExdr;

+    private final ModelCondition condition;

+

+    public ModelMenuCondition(ModelMenuItem modelMenuItem, Element conditionElement) {

+        this.passStyleExdr = FlexibleStringExpander.getInstance(conditionElement.getAttribute("pass-style"));

+        this.failStyleExdr = FlexibleStringExpander.getInstance(conditionElement.getAttribute("disabled-style"));

+        this.condition = AbstractModelCondition.DEFAULT_CONDITION_FACTORY.newInstance(modelMenuItem, conditionElement);

+    }

+

+    public ModelCondition getCondition() {

+        return condition;

+    }

+

+    public FlexibleStringExpander getFailStyleExdr() {

+        return failStyleExdr;

+    }

+

+    public FlexibleStringExpander getPassStyleExdr() {

+        return passStyleExdr;

+    }

+}

diff --git a/framework/widget/src/org/ofbiz/widget/menu/ModelMenuItem.java b/framework/widget/src/org/ofbiz/widget/model/ModelMenuItem.java
similarity index 97%
rename from framework/widget/src/org/ofbiz/widget/menu/ModelMenuItem.java
rename to framework/widget/src/org/ofbiz/widget/model/ModelMenuItem.java
index 2ddc1e4..2ee5b5a 100644
--- a/framework/widget/src/org/ofbiz/widget/menu/ModelMenuItem.java
+++ b/framework/widget/src/org/ofbiz/widget/model/ModelMenuItem.java
@@ -1,672 +1,669 @@
-/*******************************************************************************
- * 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.menu;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-
-import org.ofbiz.base.util.Debug;
-import org.ofbiz.base.util.UtilValidate;
-import org.ofbiz.base.util.UtilXml;
-import org.ofbiz.base.util.string.FlexibleStringExpander;
-import org.ofbiz.entity.GenericValue;
-import org.ofbiz.widget.AbstractModelAction;
-import org.ofbiz.widget.CommonWidgetModels.AutoEntityParameters;
-import org.ofbiz.widget.CommonWidgetModels.AutoServiceParameters;
-import org.ofbiz.widget.CommonWidgetModels.Image;
-import org.ofbiz.widget.CommonWidgetModels.Link;
-import org.ofbiz.widget.CommonWidgetModels.Parameter;
-import org.ofbiz.widget.ModelAction;
-import org.ofbiz.widget.ModelWidget;
-import org.ofbiz.widget.ModelWidgetVisitor;
-import org.ofbiz.widget.PortalPageWorker;
-import org.w3c.dom.Element;
-
-/**
- * Models the &lt;menu-item&gt; element.
- * 
- * @see <code>widget-menu.xsd</code>
- */
-@SuppressWarnings("serial")
-public class ModelMenuItem extends ModelWidget {
-
-    /*
-     * ----------------------------------------------------------------------- *
-     *                     DEVELOPERS PLEASE READ
-     * ----------------------------------------------------------------------- *
-     * 
-     * This model is intended to be a read-only data structure that represents
-     * an XML element. Outside of object construction, the class should not
-     * have any behaviors.
-     * 
-     * Instances of this class will be shared by multiple threads - therefore
-     * it is immutable. DO NOT CHANGE THE OBJECT'S STATE AT RUN TIME!
-     * 
-     */
-
-    public static final String module = ModelMenuItem.class.getName();
-
-    private final List<ModelAction> actions;
-    private final String align;
-    private final String alignStyle;
-    private final FlexibleStringExpander associatedContentId;
-    private final String cellWidth;
-    private final ModelMenuCondition condition;
-    private final String disabledTitleStyle;
-    private final String disableIfEmpty;
-    private final String entityName;
-    private final Boolean hideIfSelected;
-    private final MenuLink link;
-    private final List<ModelMenuItem> menuItemList;
-    private final ModelMenu modelMenu;
-    private final String overrideName;
-    private final ModelMenuItem parentMenuItem;
-    private final FlexibleStringExpander parentPortalPageId;
-    private final Integer position;
-    private final String selectedStyle;
-    private final String subMenu;
-    private final FlexibleStringExpander title;
-    private final String titleStyle;
-    private final FlexibleStringExpander tooltip;
-    private final String tooltipStyle;
-    private final String widgetStyle;
-
-    // ===== CONSTRUCTORS =====
-
-    public ModelMenuItem(Element menuItemElement, ModelMenu modelMenu) {
-        this(menuItemElement, modelMenu, null);
-    }
-
-    private ModelMenuItem(Element menuItemElement, ModelMenu modelMenu, ModelMenuItem parentMenuItem) {
-        super(menuItemElement);
-        this.modelMenu = modelMenu;
-        this.parentMenuItem = parentMenuItem;
-        this.entityName = menuItemElement.getAttribute("entity-name");
-        this.title = FlexibleStringExpander.getInstance(menuItemElement.getAttribute("title"));
-        this.tooltip = FlexibleStringExpander.getInstance(menuItemElement.getAttribute("tooltip"));
-        this.parentPortalPageId = FlexibleStringExpander.getInstance(menuItemElement.getAttribute("parent-portal-page-value"));
-        this.titleStyle = menuItemElement.getAttribute("title-style");
-        this.disabledTitleStyle = menuItemElement.getAttribute("disabled-title-style");
-        this.widgetStyle = menuItemElement.getAttribute("widget-style");
-        this.tooltipStyle = menuItemElement.getAttribute("tooltip-style");
-        this.selectedStyle = menuItemElement.getAttribute("selected-style");
-        String hideIfSelected = menuItemElement.getAttribute("hide-if-selected");
-        if (!hideIfSelected.isEmpty())
-            if (hideIfSelected.equalsIgnoreCase("true"))
-                this.hideIfSelected = Boolean.TRUE;
-            else
-                this.hideIfSelected = Boolean.FALSE;
-        else
-            this.hideIfSelected = null;
-        this.disableIfEmpty = menuItemElement.getAttribute("disable-if-empty");
-        this.align = menuItemElement.getAttribute("align");
-        this.alignStyle = menuItemElement.getAttribute("align-style");
-        Integer position = null;
-        String positionStr = menuItemElement.getAttribute("position");
-        if (!positionStr.isEmpty()) {
-            try {
-                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 menu renderer", module);
-                position = null;
-            }
-        }
-        this.position = position;
-        this.associatedContentId = FlexibleStringExpander.getInstance(menuItemElement.getAttribute("associated-content-id"));
-        this.cellWidth = menuItemElement.getAttribute("cell-width");
-        this.subMenu = menuItemElement.getAttribute("sub-menu");
-        Element linkElement = UtilXml.firstChildElement(menuItemElement, "link");
-        if (linkElement != null) {
-            this.link = new MenuLink(linkElement, this);
-        } else {
-            this.link = null;
-        }
-        // read in add item defs, add/override one by one using the menuItemList and menuItemMap
-        List<? extends Element> itemElements = UtilXml.childElementList(menuItemElement, "menu-item");
-        if (!itemElements.isEmpty()) {
-            ArrayList<ModelMenuItem> menuItemList = new ArrayList<ModelMenuItem>();
-            Map<String, ModelMenuItem> menuItemMap = new HashMap<String, ModelMenuItem>();
-            for (Element itemElement : itemElements) {
-                ModelMenuItem modelMenuItem = new ModelMenuItem(itemElement, modelMenu, this);
-                addUpdateMenuItem(modelMenuItem, menuItemList, menuItemMap);
-            }
-            menuItemList.trimToSize();
-            this.menuItemList = Collections.unmodifiableList(menuItemList);
-        } else {
-            this.menuItemList = Collections.emptyList();
-        }
-        // read condition under the "condition" element
-        Element conditionElement = UtilXml.firstChildElement(menuItemElement, "condition");
-        if (conditionElement != null) {
-            conditionElement = UtilXml.firstChildElement(conditionElement);
-            this.condition = new ModelMenuCondition(this, conditionElement);
-        } else {
-            this.condition = null;
-        }
-        // read all actions under the "actions" element
-        Element actionsElement = UtilXml.firstChildElement(conditionElement, "actions");
-        if (actionsElement != null) {
-            this.actions = AbstractModelAction.readSubActions(this, actionsElement);
-        } else {
-            this.actions = Collections.emptyList();
-        }
-        this.overrideName = "";
-    }
-
-    // Portal constructor
-    private ModelMenuItem(GenericValue portalPage, ModelMenuItem parentMenuItem, Locale locale) {
-        super(portalPage.getString("portalPageId"));
-        this.actions = Collections.emptyList();
-        this.align = "";
-        this.alignStyle = "";
-        this.associatedContentId = FlexibleStringExpander.getInstance("");
-        this.cellWidth = "";
-        this.condition = null;
-        this.disabledTitleStyle = "";
-        this.disableIfEmpty = "";
-        this.entityName = "";
-        this.hideIfSelected = null;
-        this.menuItemList = Collections.emptyList();
-        this.overrideName = "";
-        this.parentMenuItem = null;
-        this.parentPortalPageId = FlexibleStringExpander.getInstance(portalPage.getString("parentPortalPageId"));
-        this.position = null;
-        this.selectedStyle = "";
-        this.subMenu = "";
-        this.title = FlexibleStringExpander.getInstance((String) portalPage.get("portalPageName", locale));
-        this.titleStyle = "";
-        this.tooltip = FlexibleStringExpander.getInstance("");
-        this.tooltipStyle = "";
-        this.widgetStyle = "";
-        this.link = new MenuLink(portalPage, parentMenuItem, locale);
-        this.modelMenu = parentMenuItem.modelMenu;
-    }
-
-    // Merge constructor
-    private ModelMenuItem(ModelMenuItem existingMenuItem, ModelMenuItem overrideMenuItem) {
-        super(existingMenuItem.getName());
-        this.modelMenu = existingMenuItem.modelMenu;
-        if (UtilValidate.isNotEmpty(overrideMenuItem.getName())) {
-            this.overrideName = overrideMenuItem.getName();
-        } else {
-            this.overrideName = existingMenuItem.getName();
-        }
-        if (UtilValidate.isNotEmpty(overrideMenuItem.entityName)) {
-            this.entityName = overrideMenuItem.entityName;
-        } else {
-            this.entityName = existingMenuItem.entityName;
-        }
-        if (UtilValidate.isNotEmpty(overrideMenuItem.parentPortalPageId)) {
-            this.parentPortalPageId = overrideMenuItem.parentPortalPageId;
-        } else {
-            this.parentPortalPageId = existingMenuItem.parentPortalPageId;
-        }
-        if (UtilValidate.isNotEmpty(overrideMenuItem.title)) {
-            this.title = overrideMenuItem.title;
-        } else {
-            this.title = existingMenuItem.title;
-        }
-        if (UtilValidate.isNotEmpty(overrideMenuItem.tooltip)) {
-            this.tooltip = overrideMenuItem.tooltip;
-        } else {
-            this.tooltip = existingMenuItem.tooltip;
-        }
-        if (UtilValidate.isNotEmpty(overrideMenuItem.titleStyle)) {
-            this.titleStyle = overrideMenuItem.titleStyle;
-        } else {
-            this.titleStyle = existingMenuItem.titleStyle;
-        }
-        if (UtilValidate.isNotEmpty(overrideMenuItem.selectedStyle)) {
-            this.selectedStyle = overrideMenuItem.selectedStyle;
-        } else {
-            this.selectedStyle = existingMenuItem.selectedStyle;
-        }
-        if (UtilValidate.isNotEmpty(overrideMenuItem.widgetStyle)) {
-            this.widgetStyle = overrideMenuItem.widgetStyle;
-        } else {
-            this.widgetStyle = existingMenuItem.widgetStyle;
-        }
-        if (overrideMenuItem.position != null) {
-            this.position = overrideMenuItem.position;
-        } else {
-            this.position = existingMenuItem.position;
-        }
-        this.actions = existingMenuItem.actions;
-        this.align = existingMenuItem.align;
-        this.alignStyle = existingMenuItem.alignStyle;
-        this.associatedContentId = existingMenuItem.associatedContentId;
-        this.cellWidth = existingMenuItem.cellWidth;
-        this.condition = existingMenuItem.condition;
-        this.disabledTitleStyle = existingMenuItem.disabledTitleStyle;
-        this.disableIfEmpty = existingMenuItem.disableIfEmpty;
-        this.hideIfSelected = existingMenuItem.hideIfSelected;
-        this.menuItemList = existingMenuItem.menuItemList;
-        this.parentMenuItem = existingMenuItem.parentMenuItem;
-        this.subMenu = existingMenuItem.subMenu;
-        this.tooltipStyle = existingMenuItem.tooltipStyle;
-        this.link = existingMenuItem.link;
-    }
-
-    @Override
-    public void accept(ModelWidgetVisitor visitor) throws Exception {
-        visitor.visit(this);
-    }
-
-    private void addUpdateMenuItem(ModelMenuItem modelMenuItem, List<ModelMenuItem> menuItemList,
-            Map<String, ModelMenuItem> menuItemMap) {
-        ModelMenuItem existingMenuItem = menuItemMap.get(modelMenuItem.getName());
-        if (existingMenuItem != null) {
-            // does exist, update the item by doing a merge/override
-            ModelMenuItem mergedMenuItem = existingMenuItem.mergeOverrideModelMenuItem(modelMenuItem);
-            int existingItemIndex = menuItemList.indexOf(existingMenuItem);
-            menuItemList.set(existingItemIndex, mergedMenuItem);
-            menuItemMap.put(modelMenuItem.getName(), mergedMenuItem);
-        } else {
-            // does not exist, add to List and Map
-            menuItemList.add(modelMenuItem);
-            menuItemMap.put(modelMenuItem.getName(), modelMenuItem);
-        }
-    }
-
-    public List<ModelAction> getActions() {
-        return actions;
-    }
-
-    public String getAlign() {
-        if (!this.align.isEmpty()) {
-            return this.align;
-        } else if (parentMenuItem != null) {
-            return parentMenuItem.getAlign();
-        } else {
-            return this.modelMenu.getDefaultAlign();
-        }
-    }
-
-    public String getAlignStyle() {
-        if (!this.alignStyle.isEmpty()) {
-            return this.alignStyle;
-        } else if (parentMenuItem != null) {
-            return parentMenuItem.getAlignStyle();
-        } else {
-            return this.modelMenu.getDefaultAlignStyle();
-        }
-    }
-
-    public FlexibleStringExpander getAssociatedContentId() {
-        return associatedContentId;
-    }
-
-    public String getAssociatedContentId(Map<String, Object> context) {
-        String retStr = null;
-        if (this.associatedContentId != null) {
-            retStr = associatedContentId.expandString(context);
-        }
-        if (retStr.isEmpty()) {
-            retStr = this.modelMenu.getDefaultAssociatedContentId(context);
-        }
-        return retStr;
-    }
-
-    public String getCellWidth() {
-        if (!this.cellWidth.isEmpty()) {
-            return this.cellWidth;
-        } else {
-            return this.modelMenu.getDefaultCellWidth();
-        }
-    }
-
-    public ModelMenuCondition getCondition() {
-        return condition;
-    }
-
-    public String getDisabledTitleStyle() {
-        if (!this.disabledTitleStyle.isEmpty()) {
-            return this.disabledTitleStyle;
-        } else if (parentMenuItem != null) {
-            return parentMenuItem.getDisabledTitleStyle();
-        } else {
-            return this.modelMenu.getDefaultDisabledTitleStyle();
-        }
-    }
-
-    public String getDisableIfEmpty() {
-        return this.disableIfEmpty;
-    }
-
-    public String getEntityName() {
-        if (!this.entityName.isEmpty()) {
-            return this.entityName;
-        } else if (parentMenuItem != null) {
-            return parentMenuItem.getEntityName();
-        } else {
-            return this.modelMenu.getDefaultEntityName();
-        }
-    }
-
-    public Boolean getHideIfSelected() {
-        if (hideIfSelected != null) {
-            return this.hideIfSelected;
-        } else {
-            return this.modelMenu.getDefaultHideIfSelected();
-        }
-    }
-
-    public MenuLink getLink() {
-        return this.link;
-    }
-
-    public List<ModelMenuItem> getMenuItemList() {
-        return menuItemList;
-    }
-
-    public ModelMenu getModelMenu() {
-        return modelMenu;
-    }
-
-    @Override
-    public String getName() {
-        if (!this.overrideName.isEmpty()) {
-            return this.overrideName;
-        }
-        return super.getName();
-    }
-
-    public String getOverrideName() {
-        return overrideName;
-    }
-
-    public ModelMenuItem getParentMenuItem() {
-        return parentMenuItem;
-    }
-
-    public FlexibleStringExpander getParentPortalPageId() {
-        return parentPortalPageId;
-    }
-
-    public String getParentPortalPageId(Map<String, Object> context) {
-        return this.parentPortalPageId.expandString(context);
-    }
-
-    public int getPosition() {
-        if (this.position == null) {
-            return 1;
-        } else {
-            return position.intValue();
-        }
-    }
-
-    public String getSelectedStyle() {
-        if (!this.selectedStyle.isEmpty()) {
-            return this.selectedStyle;
-        } else if (parentMenuItem != null) {
-            return parentMenuItem.getSelectedStyle();
-        } else {
-            return this.modelMenu.getDefaultSelectedStyle();
-        }
-    }
-
-    public String getSubMenu() {
-        return subMenu;
-    }
-
-    public FlexibleStringExpander getTitle() {
-        return title;
-    }
-
-    public String getTitle(Map<String, Object> context) {
-        return title.expandString(context);
-    }
-
-    public String getTitleStyle() {
-        if (!this.titleStyle.isEmpty()) {
-            return this.titleStyle;
-        } else if (parentMenuItem != null) {
-            return parentMenuItem.getTitleStyle();
-        } else {
-            return this.modelMenu.getDefaultTitleStyle();
-        }
-    }
-
-    public FlexibleStringExpander getTooltip() {
-        return tooltip;
-    }
-
-    public String getTooltip(Map<String, Object> context) {
-        if (UtilValidate.isNotEmpty(tooltip)) {
-            return tooltip.expandString(context);
-        } else {
-            return "";
-        }
-    }
-
-    public String getTooltipStyle() {
-        if (!this.tooltipStyle.isEmpty()) {
-            return this.tooltipStyle;
-        } else if (parentMenuItem != null) {
-            return parentMenuItem.getTooltipStyle();
-        } else {
-            return this.modelMenu.getDefaultTooltipStyle();
-        }
-    }
-
-    public String getWidgetStyle() {
-        if (!this.widgetStyle.isEmpty()) {
-            return this.widgetStyle;
-        } else if (parentMenuItem != null) {
-            return parentMenuItem.getWidgetStyle();
-        } else {
-            return this.modelMenu.getDefaultWidgetStyle();
-        }
-    }
-
-    public boolean isSelected(Map<String, Object> context) {
-        return getName().equals(modelMenu.getSelectedMenuItemContextFieldName(context));
-    }
-
-    public ModelMenuItem mergeOverrideModelMenuItem(ModelMenuItem overrideMenuItem) {
-        return new ModelMenuItem(this, overrideMenuItem);
-    }
-
-    public void renderMenuItemString(Appendable writer, Map<String, Object> context, MenuStringRenderer menuStringRenderer)
-            throws IOException {
-        if (shouldBeRendered(context)) {
-            AbstractModelAction.runSubActions(actions, context);
-            String parentPortalPageId = getParentPortalPageId(context);
-            if (UtilValidate.isNotEmpty(parentPortalPageId)) {
-                List<GenericValue> portalPages = PortalPageWorker.getPortalPages(parentPortalPageId, context);
-                if (UtilValidate.isNotEmpty(portalPages)) {
-                    Locale locale = (Locale) context.get("locale");
-                    for (GenericValue portalPage : portalPages) {
-                        if (UtilValidate.isNotEmpty(portalPage.getString("portalPageName"))) {
-                            ModelMenuItem localItem = new ModelMenuItem(portalPage, this, locale);
-                            menuStringRenderer.renderMenuItem(writer, context, localItem);
-                        }
-                    }
-                }
-            } else {
-                menuStringRenderer.renderMenuItem(writer, context, this);
-            }
-        }
-    }
-
-    public boolean shouldBeRendered(Map<String, Object> context) {
-        if (this.condition != null) {
-            return this.condition.getCondition().eval(context);
-        }
-        return true;
-    }
-
-    public static class MenuLink {
-        private final ModelMenuItem linkMenuItem;
-        private final Link link;
-
-        public MenuLink(Element linkElement, ModelMenuItem parentMenuItem) {
-            this.linkMenuItem = parentMenuItem;
-            if (linkElement.getAttribute("text").isEmpty()) {
-                linkElement.setAttribute("text", parentMenuItem.getTitle().getOriginal());
-            }
-            if (linkElement.getAttribute("style").isEmpty()) {
-                linkElement.setAttribute("style", parentMenuItem.getWidgetStyle());
-            }
-            this.link = new Link(linkElement);
-        }
-
-        public MenuLink(GenericValue portalPage, ModelMenuItem parentMenuItem, Locale locale) {
-            this.linkMenuItem = parentMenuItem;
-            ArrayList<Parameter> parameterList = new ArrayList<Parameter>();
-            if (parentMenuItem.link != null) {
-                parameterList.addAll(parentMenuItem.link.getParameterList());
-            }
-            parameterList.add(new Parameter("portalPageId", portalPage.getString("portalPageId"), false));
-            parameterList.add(new Parameter("parentPortalPageId", portalPage.getString("parentPortalPageId"), false));
-            String target = "showPortalPage";
-            if (parentMenuItem.link != null) {
-                target= "";
-            }
-            this.link = new Link(portalPage, parameterList, target, locale);
-        }
-
-        public AutoEntityParameters getAutoEntityParameters() {
-            return link.getAutoEntityParameters();
-        }
-
-        public AutoServiceParameters getAutoServiceParameters() {
-            return link.getAutoServiceParameters();
-        }
-
-        public boolean getEncode() {
-            return link.getEncode();
-        }
-
-        public boolean getFullPath() {
-            return link.getFullPath();
-        }
-
-        public String getHeight() {
-            return link.getHeight();
-        }
-
-        public String getId(Map<String, Object> context) {
-            return link.getId(context);
-        }
-
-        public FlexibleStringExpander getIdExdr() {
-            return link.getIdExdr();
-        }
-
-        public Image getImage() {
-            return link.getImage();
-        }
-
-        public String getLinkType() {
-            return link.getLinkType();
-        }
-
-        public String getName() {
-            return link.getName();
-        }
-
-        public String getName(Map<String, Object> context) {
-            return link.getName(context);
-        }
-
-        public FlexibleStringExpander getNameExdr() {
-            return link.getNameExdr();
-        }
-
-        public List<Parameter> getParameterList() {
-            return link.getParameterList();
-        }
-
-        public Map<String, String> getParameterMap(Map<String, Object> context) {
-            return link.getParameterMap(context);
-        }
-
-        public String getPrefix(Map<String, Object> context) {
-            return link.getPrefix(context);
-        }
-
-        public FlexibleStringExpander getPrefixExdr() {
-            return link.getPrefixExdr();
-        }
-
-        public boolean getSecure() {
-            return link.getSecure();
-        }
-
-        public String getStyle(Map<String, Object> context) {
-            return link.getStyle(context);
-        }
-
-        public FlexibleStringExpander getStyleExdr() {
-            return link.getStyleExdr();
-        }
-
-        public String getTarget(Map<String, Object> context) {
-            return link.getTarget(context);
-        }
-
-        public FlexibleStringExpander getTargetExdr() {
-            return link.getTargetExdr();
-        }
-
-        public String getTargetWindow(Map<String, Object> context) {
-            return link.getTargetWindow(context);
-        }
-
-        public FlexibleStringExpander getTargetWindowExdr() {
-            return link.getTargetWindowExdr();
-        }
-
-        public String getText(Map<String, Object> context) {
-            return link.getText(context);
-        }
-
-        public FlexibleStringExpander getTextExdr() {
-            return link.getTextExdr();
-        }
-
-        public String getUrlMode() {
-            return link.getUrlMode();
-        }
-
-        public String getWidth() {
-            return link.getWidth();
-        }
-
-        public ModelMenuItem getLinkMenuItem() {
-            return linkMenuItem;
-        }
-
-        public Link getLink() {
-            return link;
-        }
-
-        public void renderLinkString(Appendable writer, Map<String, Object> context, MenuStringRenderer menuStringRenderer)
-                throws IOException {
-            menuStringRenderer.renderLink(writer, context, this);
-        }
-    }
-}
+/*******************************************************************************

+ * Licensed to the Apache Software Foundation (ASF) under one

+ * or more contributor license agreements.  See the NOTICE file

+ * distributed with this work for additional information

+ * regarding copyright ownership.  The ASF licenses this file

+ * to you under the Apache License, Version 2.0 (the

+ * "License"); you may not use this file except in compliance

+ * with the License.  You may obtain a copy of the License at

+ *

+ * http://www.apache.org/licenses/LICENSE-2.0

+ *

+ * Unless required by applicable law or agreed to in writing,

+ * software distributed under the License is distributed on an

+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY

+ * KIND, either express or implied.  See the License for the

+ * specific language governing permissions and limitations

+ * under the License.

+ *******************************************************************************/

+package org.ofbiz.widget.model;

+

+import java.io.IOException;

+import java.util.ArrayList;

+import java.util.Collections;

+import java.util.HashMap;

+import java.util.List;

+import java.util.Locale;

+import java.util.Map;

+

+import org.ofbiz.base.util.Debug;

+import org.ofbiz.base.util.UtilValidate;

+import org.ofbiz.base.util.UtilXml;

+import org.ofbiz.base.util.string.FlexibleStringExpander;

+import org.ofbiz.entity.GenericValue;

+import org.ofbiz.widget.model.CommonWidgetModels.AutoEntityParameters;

+import org.ofbiz.widget.model.CommonWidgetModels.AutoServiceParameters;

+import org.ofbiz.widget.model.CommonWidgetModels.Image;

+import org.ofbiz.widget.model.CommonWidgetModels.Link;

+import org.ofbiz.widget.model.CommonWidgetModels.Parameter;

+import org.ofbiz.widget.portal.PortalPageWorker;

+import org.ofbiz.widget.renderer.MenuStringRenderer;

+import org.w3c.dom.Element;

+

+/**

+ * Models the &lt;menu-item&gt; element.

+ * 

+ * @see <code>widget-menu.xsd</code>

+ */

+@SuppressWarnings("serial")

+public class ModelMenuItem extends ModelWidget {

+

+    /*

+     * ----------------------------------------------------------------------- *

+     *                     DEVELOPERS PLEASE READ

+     * ----------------------------------------------------------------------- *

+     * 

+     * This model is intended to be a read-only data structure that represents

+     * an XML element. Outside of object construction, the class should not

+     * have any behaviors.

+     * 

+     * Instances of this class will be shared by multiple threads - therefore

+     * it is immutable. DO NOT CHANGE THE OBJECT'S STATE AT RUN TIME!

+     * 

+     */

+

+    public static final String module = ModelMenuItem.class.getName();

+

+    private final List<ModelAction> actions;

+    private final String align;

+    private final String alignStyle;

+    private final FlexibleStringExpander associatedContentId;

+    private final String cellWidth;

+    private final ModelMenuCondition condition;

+    private final String disabledTitleStyle;

+    private final String disableIfEmpty;

+    private final String entityName;

+    private final Boolean hideIfSelected;

+    private final MenuLink link;

+    private final List<ModelMenuItem> menuItemList;

+    private final ModelMenu modelMenu;

+    private final String overrideName;

+    private final ModelMenuItem parentMenuItem;

+    private final FlexibleStringExpander parentPortalPageId;

+    private final Integer position;

+    private final String selectedStyle;

+    private final String subMenu;

+    private final FlexibleStringExpander title;

+    private final String titleStyle;

+    private final FlexibleStringExpander tooltip;

+    private final String tooltipStyle;

+    private final String widgetStyle;

+

+    // ===== CONSTRUCTORS =====

+

+    public ModelMenuItem(Element menuItemElement, ModelMenu modelMenu) {

+        this(menuItemElement, modelMenu, null);

+    }

+

+    private ModelMenuItem(Element menuItemElement, ModelMenu modelMenu, ModelMenuItem parentMenuItem) {

+        super(menuItemElement);

+        this.modelMenu = modelMenu;

+        this.parentMenuItem = parentMenuItem;

+        this.entityName = menuItemElement.getAttribute("entity-name");

+        this.title = FlexibleStringExpander.getInstance(menuItemElement.getAttribute("title"));

+        this.tooltip = FlexibleStringExpander.getInstance(menuItemElement.getAttribute("tooltip"));

+        this.parentPortalPageId = FlexibleStringExpander.getInstance(menuItemElement.getAttribute("parent-portal-page-value"));

+        this.titleStyle = menuItemElement.getAttribute("title-style");

+        this.disabledTitleStyle = menuItemElement.getAttribute("disabled-title-style");

+        this.widgetStyle = menuItemElement.getAttribute("widget-style");

+        this.tooltipStyle = menuItemElement.getAttribute("tooltip-style");

+        this.selectedStyle = menuItemElement.getAttribute("selected-style");

+        String hideIfSelected = menuItemElement.getAttribute("hide-if-selected");

+        if (!hideIfSelected.isEmpty())

+            if (hideIfSelected.equalsIgnoreCase("true"))

+                this.hideIfSelected = Boolean.TRUE;

+            else

+                this.hideIfSelected = Boolean.FALSE;

+        else

+            this.hideIfSelected = null;

+        this.disableIfEmpty = menuItemElement.getAttribute("disable-if-empty");

+        this.align = menuItemElement.getAttribute("align");

+        this.alignStyle = menuItemElement.getAttribute("align-style");

+        Integer position = null;

+        String positionStr = menuItemElement.getAttribute("position");

+        if (!positionStr.isEmpty()) {

+            try {

+                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 menu renderer", module);

+                position = null;

+            }

+        }

+        this.position = position;

+        this.associatedContentId = FlexibleStringExpander.getInstance(menuItemElement.getAttribute("associated-content-id"));

+        this.cellWidth = menuItemElement.getAttribute("cell-width");

+        this.subMenu = menuItemElement.getAttribute("sub-menu");

+        Element linkElement = UtilXml.firstChildElement(menuItemElement, "link");

+        if (linkElement != null) {

+            this.link = new MenuLink(linkElement, this);

+        } else {

+            this.link = null;

+        }

+        // read in add item defs, add/override one by one using the menuItemList and menuItemMap

+        List<? extends Element> itemElements = UtilXml.childElementList(menuItemElement, "menu-item");

+        if (!itemElements.isEmpty()) {

+            ArrayList<ModelMenuItem> menuItemList = new ArrayList<ModelMenuItem>();

+            Map<String, ModelMenuItem> menuItemMap = new HashMap<String, ModelMenuItem>();

+            for (Element itemElement : itemElements) {

+                ModelMenuItem modelMenuItem = new ModelMenuItem(itemElement, modelMenu, this);

+                addUpdateMenuItem(modelMenuItem, menuItemList, menuItemMap);

+            }

+            menuItemList.trimToSize();

+            this.menuItemList = Collections.unmodifiableList(menuItemList);

+        } else {

+            this.menuItemList = Collections.emptyList();

+        }

+        // read condition under the "condition" element

+        Element conditionElement = UtilXml.firstChildElement(menuItemElement, "condition");

+        if (conditionElement != null) {

+            conditionElement = UtilXml.firstChildElement(conditionElement);

+            this.condition = new ModelMenuCondition(this, conditionElement);

+        } else {

+            this.condition = null;

+        }

+        // read all actions under the "actions" element

+        Element actionsElement = UtilXml.firstChildElement(conditionElement, "actions");

+        if (actionsElement != null) {

+            this.actions = AbstractModelAction.readSubActions(this, actionsElement);

+        } else {

+            this.actions = Collections.emptyList();

+        }

+        this.overrideName = "";

+    }

+

+    // Portal constructor

+    private ModelMenuItem(GenericValue portalPage, ModelMenuItem parentMenuItem, Locale locale) {

+        super(portalPage.getString("portalPageId"));

+        this.actions = Collections.emptyList();

+        this.align = "";

+        this.alignStyle = "";

+        this.associatedContentId = FlexibleStringExpander.getInstance("");

+        this.cellWidth = "";

+        this.condition = null;

+        this.disabledTitleStyle = "";

+        this.disableIfEmpty = "";

+        this.entityName = "";

+        this.hideIfSelected = null;

+        this.menuItemList = Collections.emptyList();

+        this.overrideName = "";

+        this.parentMenuItem = null;

+        this.parentPortalPageId = FlexibleStringExpander.getInstance(portalPage.getString("parentPortalPageId"));

+        this.position = null;

+        this.selectedStyle = "";

+        this.subMenu = "";

+        this.title = FlexibleStringExpander.getInstance((String) portalPage.get("portalPageName", locale));

+        this.titleStyle = "";

+        this.tooltip = FlexibleStringExpander.getInstance("");

+        this.tooltipStyle = "";

+        this.widgetStyle = "";

+        this.link = new MenuLink(portalPage, parentMenuItem, locale);

+        this.modelMenu = parentMenuItem.modelMenu;

+    }

+

+    // Merge constructor

+    private ModelMenuItem(ModelMenuItem existingMenuItem, ModelMenuItem overrideMenuItem) {

+        super(existingMenuItem.getName());

+        this.modelMenu = existingMenuItem.modelMenu;

+        if (UtilValidate.isNotEmpty(overrideMenuItem.getName())) {

+            this.overrideName = overrideMenuItem.getName();

+        } else {

+            this.overrideName = existingMenuItem.getName();

+        }

+        if (UtilValidate.isNotEmpty(overrideMenuItem.entityName)) {

+            this.entityName = overrideMenuItem.entityName;

+        } else {

+            this.entityName = existingMenuItem.entityName;

+        }

+        if (UtilValidate.isNotEmpty(overrideMenuItem.parentPortalPageId)) {

+            this.parentPortalPageId = overrideMenuItem.parentPortalPageId;

+        } else {

+            this.parentPortalPageId = existingMenuItem.parentPortalPageId;

+        }

+        if (UtilValidate.isNotEmpty(overrideMenuItem.title)) {

+            this.title = overrideMenuItem.title;

+        } else {

+            this.title = existingMenuItem.title;

+        }

+        if (UtilValidate.isNotEmpty(overrideMenuItem.tooltip)) {

+            this.tooltip = overrideMenuItem.tooltip;

+        } else {

+            this.tooltip = existingMenuItem.tooltip;

+        }

+        if (UtilValidate.isNotEmpty(overrideMenuItem.titleStyle)) {

+            this.titleStyle = overrideMenuItem.titleStyle;

+        } else {

+            this.titleStyle = existingMenuItem.titleStyle;

+        }

+        if (UtilValidate.isNotEmpty(overrideMenuItem.selectedStyle)) {

+            this.selectedStyle = overrideMenuItem.selectedStyle;

+        } else {

+            this.selectedStyle = existingMenuItem.selectedStyle;

+        }

+        if (UtilValidate.isNotEmpty(overrideMenuItem.widgetStyle)) {

+            this.widgetStyle = overrideMenuItem.widgetStyle;

+        } else {

+            this.widgetStyle = existingMenuItem.widgetStyle;

+        }

+        if (overrideMenuItem.position != null) {

+            this.position = overrideMenuItem.position;

+        } else {

+            this.position = existingMenuItem.position;

+        }

+        this.actions = existingMenuItem.actions;

+        this.align = existingMenuItem.align;

+        this.alignStyle = existingMenuItem.alignStyle;

+        this.associatedContentId = existingMenuItem.associatedContentId;

+        this.cellWidth = existingMenuItem.cellWidth;

+        this.condition = existingMenuItem.condition;

+        this.disabledTitleStyle = existingMenuItem.disabledTitleStyle;

+        this.disableIfEmpty = existingMenuItem.disableIfEmpty;

+        this.hideIfSelected = existingMenuItem.hideIfSelected;

+        this.menuItemList = existingMenuItem.menuItemList;

+        this.parentMenuItem = existingMenuItem.parentMenuItem;

+        this.subMenu = existingMenuItem.subMenu;

+        this.tooltipStyle = existingMenuItem.tooltipStyle;

+        this.link = existingMenuItem.link;

+    }

+

+    @Override

+    public void accept(ModelWidgetVisitor visitor) throws Exception {

+        visitor.visit(this);

+    }

+

+    private void addUpdateMenuItem(ModelMenuItem modelMenuItem, List<ModelMenuItem> menuItemList,

+            Map<String, ModelMenuItem> menuItemMap) {

+        ModelMenuItem existingMenuItem = menuItemMap.get(modelMenuItem.getName());

+        if (existingMenuItem != null) {

+            // does exist, update the item by doing a merge/override

+            ModelMenuItem mergedMenuItem = existingMenuItem.mergeOverrideModelMenuItem(modelMenuItem);

+            int existingItemIndex = menuItemList.indexOf(existingMenuItem);

+            menuItemList.set(existingItemIndex, mergedMenuItem);

+            menuItemMap.put(modelMenuItem.getName(), mergedMenuItem);

+        } else {

+            // does not exist, add to List and Map

+            menuItemList.add(modelMenuItem);

+            menuItemMap.put(modelMenuItem.getName(), modelMenuItem);

+        }

+    }

+

+    public List<ModelAction> getActions() {

+        return actions;

+    }

+

+    public String getAlign() {

+        if (!this.align.isEmpty()) {

+            return this.align;

+        } else if (parentMenuItem != null) {

+            return parentMenuItem.getAlign();

+        } else {

+            return this.modelMenu.getDefaultAlign();

+        }

+    }

+

+    public String getAlignStyle() {

+        if (!this.alignStyle.isEmpty()) {

+            return this.alignStyle;

+        } else if (parentMenuItem != null) {

+            return parentMenuItem.getAlignStyle();

+        } else {

+            return this.modelMenu.getDefaultAlignStyle();

+        }

+    }

+

+    public FlexibleStringExpander getAssociatedContentId() {

+        return associatedContentId;

+    }

+

+    public String getAssociatedContentId(Map<String, Object> context) {

+        String retStr = null;

+        if (this.associatedContentId != null) {

+            retStr = associatedContentId.expandString(context);

+        }

+        if (retStr.isEmpty()) {

+            retStr = this.modelMenu.getDefaultAssociatedContentId(context);

+        }

+        return retStr;

+    }

+

+    public String getCellWidth() {

+        if (!this.cellWidth.isEmpty()) {

+            return this.cellWidth;

+        } else {

+            return this.modelMenu.getDefaultCellWidth();

+        }

+    }

+

+    public ModelMenuCondition getCondition() {

+        return condition;

+    }

+

+    public String getDisabledTitleStyle() {

+        if (!this.disabledTitleStyle.isEmpty()) {

+            return this.disabledTitleStyle;

+        } else if (parentMenuItem != null) {

+            return parentMenuItem.getDisabledTitleStyle();

+        } else {

+            return this.modelMenu.getDefaultDisabledTitleStyle();

+        }

+    }

+

+    public String getDisableIfEmpty() {

+        return this.disableIfEmpty;

+    }

+

+    public String getEntityName() {

+        if (!this.entityName.isEmpty()) {

+            return this.entityName;

+        } else if (parentMenuItem != null) {

+            return parentMenuItem.getEntityName();

+        } else {

+            return this.modelMenu.getDefaultEntityName();

+        }

+    }

+

+    public Boolean getHideIfSelected() {

+        if (hideIfSelected != null) {

+            return this.hideIfSelected;

+        } else {

+            return this.modelMenu.getDefaultHideIfSelected();

+        }

+    }

+

+    public MenuLink getLink() {

+        return this.link;

+    }

+

+    public List<ModelMenuItem> getMenuItemList() {

+        return menuItemList;

+    }

+

+    public ModelMenu getModelMenu() {

+        return modelMenu;

+    }

+

+    @Override

+    public String getName() {

+        if (!this.overrideName.isEmpty()) {

+            return this.overrideName;

+        }

+        return super.getName();

+    }

+

+    public String getOverrideName() {

+        return overrideName;

+    }

+

+    public ModelMenuItem getParentMenuItem() {

+        return parentMenuItem;

+    }

+

+    public FlexibleStringExpander getParentPortalPageId() {

+        return parentPortalPageId;

+    }

+

+    public String getParentPortalPageId(Map<String, Object> context) {

+        return this.parentPortalPageId.expandString(context);

+    }

+

+    public int getPosition() {

+        if (this.position == null) {

+            return 1;

+        } else {

+            return position.intValue();

+        }

+    }

+

+    public String getSelectedStyle() {

+        if (!this.selectedStyle.isEmpty()) {

+            return this.selectedStyle;

+        } else if (parentMenuItem != null) {

+            return parentMenuItem.getSelectedStyle();

+        } else {

+            return this.modelMenu.getDefaultSelectedStyle();

+        }

+    }

+

+    public String getSubMenu() {

+        return subMenu;

+    }

+

+    public FlexibleStringExpander getTitle() {

+        return title;

+    }

+

+    public String getTitle(Map<String, Object> context) {

+        return title.expandString(context);

+    }

+

+    public String getTitleStyle() {

+        if (!this.titleStyle.isEmpty()) {

+            return this.titleStyle;

+        } else if (parentMenuItem != null) {

+            return parentMenuItem.getTitleStyle();

+        } else {

+            return this.modelMenu.getDefaultTitleStyle();

+        }

+    }

+

+    public FlexibleStringExpander getTooltip() {

+        return tooltip;

+    }

+

+    public String getTooltip(Map<String, Object> context) {

+        if (UtilValidate.isNotEmpty(tooltip)) {

+            return tooltip.expandString(context);

+        } else {

+            return "";

+        }

+    }

+

+    public String getTooltipStyle() {

+        if (!this.tooltipStyle.isEmpty()) {

+            return this.tooltipStyle;

+        } else if (parentMenuItem != null) {

+            return parentMenuItem.getTooltipStyle();

+        } else {

+            return this.modelMenu.getDefaultTooltipStyle();

+        }

+    }

+

+    public String getWidgetStyle() {

+        if (!this.widgetStyle.isEmpty()) {

+            return this.widgetStyle;

+        } else if (parentMenuItem != null) {

+            return parentMenuItem.getWidgetStyle();

+        } else {

+            return this.modelMenu.getDefaultWidgetStyle();

+        }

+    }

+

+    public boolean isSelected(Map<String, Object> context) {

+        return getName().equals(modelMenu.getSelectedMenuItemContextFieldName(context));

+    }

+

+    public ModelMenuItem mergeOverrideModelMenuItem(ModelMenuItem overrideMenuItem) {

+        return new ModelMenuItem(this, overrideMenuItem);

+    }

+

+    public void renderMenuItemString(Appendable writer, Map<String, Object> context, MenuStringRenderer menuStringRenderer)

+            throws IOException {

+        if (shouldBeRendered(context)) {

+            AbstractModelAction.runSubActions(actions, context);

+            String parentPortalPageId = getParentPortalPageId(context);

+            if (UtilValidate.isNotEmpty(parentPortalPageId)) {

+                List<GenericValue> portalPages = PortalPageWorker.getPortalPages(parentPortalPageId, context);

+                if (UtilValidate.isNotEmpty(portalPages)) {

+                    Locale locale = (Locale) context.get("locale");

+                    for (GenericValue portalPage : portalPages) {

+                        if (UtilValidate.isNotEmpty(portalPage.getString("portalPageName"))) {

+                            ModelMenuItem localItem = new ModelMenuItem(portalPage, this, locale);

+                            menuStringRenderer.renderMenuItem(writer, context, localItem);

+                        }

+                    }

+                }

+            } else {

+                menuStringRenderer.renderMenuItem(writer, context, this);

+            }

+        }

+    }

+

+    public boolean shouldBeRendered(Map<String, Object> context) {

+        if (this.condition != null) {

+            return this.condition.getCondition().eval(context);

+        }

+        return true;

+    }

+

+    public static class MenuLink {

+        private final ModelMenuItem linkMenuItem;

+        private final Link link;

+

+        public MenuLink(Element linkElement, ModelMenuItem parentMenuItem) {

+            this.linkMenuItem = parentMenuItem;

+            if (linkElement.getAttribute("text").isEmpty()) {

+                linkElement.setAttribute("text", parentMenuItem.getTitle().getOriginal());

+            }

+            if (linkElement.getAttribute("style").isEmpty()) {

+                linkElement.setAttribute("style", parentMenuItem.getWidgetStyle());

+            }

+            this.link = new Link(linkElement);

+        }

+

+        public MenuLink(GenericValue portalPage, ModelMenuItem parentMenuItem, Locale locale) {

+            this.linkMenuItem = parentMenuItem;

+            ArrayList<Parameter> parameterList = new ArrayList<Parameter>();

+            if (parentMenuItem.link != null) {

+                parameterList.addAll(parentMenuItem.link.getParameterList());

+            }

+            parameterList.add(new Parameter("portalPageId", portalPage.getString("portalPageId"), false));

+            parameterList.add(new Parameter("parentPortalPageId", portalPage.getString("parentPortalPageId"), false));

+            String target = "showPortalPage";

+            if (parentMenuItem.link != null) {

+                target= "";

+            }

+            this.link = new Link(portalPage, parameterList, target, locale);

+        }

+

+        public AutoEntityParameters getAutoEntityParameters() {

+            return link.getAutoEntityParameters();

+        }

+

+        public AutoServiceParameters getAutoServiceParameters() {

+            return link.getAutoServiceParameters();

+        }

+

+        public boolean getEncode() {

+            return link.getEncode();

+        }

+

+        public boolean getFullPath() {

+            return link.getFullPath();

+        }

+

+        public String getHeight() {

+            return link.getHeight();

+        }

+

+        public String getId(Map<String, Object> context) {

+            return link.getId(context);

+        }

+

+        public FlexibleStringExpander getIdExdr() {

+            return link.getIdExdr();

+        }

+

+        public Image getImage() {

+            return link.getImage();

+        }

+

+        public String getLinkType() {

+            return link.getLinkType();

+        }

+

+        public String getName() {

+            return link.getName();

+        }

+

+        public String getName(Map<String, Object> context) {

+            return link.getName(context);

+        }

+

+        public FlexibleStringExpander getNameExdr() {

+            return link.getNameExdr();

+        }

+

+        public List<Parameter> getParameterList() {

+            return link.getParameterList();

+        }

+

+        public Map<String, String> getParameterMap(Map<String, Object> context) {

+            return link.getParameterMap(context);

+        }

+

+        public String getPrefix(Map<String, Object> context) {

+            return link.getPrefix(context);

+        }

+

+        public FlexibleStringExpander getPrefixExdr() {

+            return link.getPrefixExdr();

+        }

+

+        public boolean getSecure() {

+            return link.getSecure();

+        }

+

+        public String getStyle(Map<String, Object> context) {

+            return link.getStyle(context);

+        }

+

+        public FlexibleStringExpander getStyleExdr() {

+            return link.getStyleExdr();

+        }

+

+        public String getTarget(Map<String, Object> context) {

+            return link.getTarget(context);

+        }

+

+        public FlexibleStringExpander getTargetExdr() {

+            return link.getTargetExdr();

+        }

+

+        public String getTargetWindow(Map<String, Object> context) {

+            return link.getTargetWindow(context);

+        }

+

+        public FlexibleStringExpander getTargetWindowExdr() {

+            return link.getTargetWindowExdr();

+        }

+

+        public String getText(Map<String, Object> context) {

+            return link.getText(context);

+        }

+

+        public FlexibleStringExpander getTextExdr() {

+            return link.getTextExdr();

+        }

+

+        public String getUrlMode() {

+            return link.getUrlMode();

+        }

+

+        public String getWidth() {

+            return link.getWidth();

+        }

+

+        public ModelMenuItem getLinkMenuItem() {

+            return linkMenuItem;

+        }

+

+        public Link getLink() {

+            return link;

+        }

+

+        public void renderLinkString(Appendable writer, Map<String, Object> context, MenuStringRenderer menuStringRenderer)

+                throws IOException {

+            menuStringRenderer.renderLink(writer, context, this);

+        }

+    }

+}

diff --git a/framework/widget/src/org/ofbiz/widget/screen/ModelScreen.java b/framework/widget/src/org/ofbiz/widget/model/ModelScreen.java
similarity index 98%
rename from framework/widget/src/org/ofbiz/widget/screen/ModelScreen.java
rename to framework/widget/src/org/ofbiz/widget/model/ModelScreen.java
index ba51445..0058a3c 100644
--- a/framework/widget/src/org/ofbiz/widget/screen/ModelScreen.java
+++ b/framework/widget/src/org/ofbiz/widget/model/ModelScreen.java
@@ -1,194 +1,194 @@
-/*******************************************************************************
- * 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.screen;
-
-import java.util.Map;
-
-import org.ofbiz.base.util.Debug;
-import org.ofbiz.base.util.UtilGenerics;
-import org.ofbiz.base.util.UtilValidate;
-import org.ofbiz.base.util.UtilXml;
-import org.ofbiz.base.util.string.FlexibleStringExpander;
-import org.ofbiz.entity.Delegator;
-import org.ofbiz.entity.GenericEntity;
-import org.ofbiz.entity.GenericEntityException;
-import org.ofbiz.entity.transaction.TransactionUtil;
-import org.ofbiz.service.LocalDispatcher;
-import org.ofbiz.widget.ModelWidget;
-import org.ofbiz.widget.ModelWidgetVisitor;
-import org.w3c.dom.Element;
-
-/**
- * Widget Library - Screen model class
- */
-@SuppressWarnings("serial")
-public class ModelScreen extends ModelWidget {
-
-    public static final String module = ModelScreen.class.getName();
-
-    private final String sourceLocation;
-    private final FlexibleStringExpander transactionTimeoutExdr;
-    private final Map<String, ModelScreen> modelScreenMap;
-    private final boolean useTransaction;
-    private final boolean useCache;
-    private final ModelScreenWidget.Section section;
-
-    /** XML Constructor */
-    public ModelScreen(Element screenElement, Map<String, ModelScreen> modelScreenMap, String sourceLocation) {
-        super(screenElement);
-        this.sourceLocation = sourceLocation;
-        this.transactionTimeoutExdr = FlexibleStringExpander.getInstance(screenElement.getAttribute("transaction-timeout"));
-        this.modelScreenMap = modelScreenMap;
-        this.useTransaction = "true".equals(screenElement.getAttribute("use-transaction"));
-        this.useCache = "true".equals(screenElement.getAttribute("use-cache"));
-
-        // read in the section, which will read all sub-widgets too
-        Element sectionElement = UtilXml.firstChildElement(screenElement, "section");
-        if (sectionElement == null) {
-            throw new IllegalArgumentException("No section found for the screen definition with name: " + getName());
-        }
-        this.section = new ModelScreenWidget.Section(this, sectionElement, true);
-    }
-
-    @Override
-    public void accept(ModelWidgetVisitor visitor) throws Exception {
-        visitor.visit(this);
-    }
-
-    public String getTransactionTimeout() {
-        return transactionTimeoutExdr.getOriginal();
-    }
-
-    public Map<String, ModelScreen> getModelScreenMap() {
-        return modelScreenMap;
-    }
-
-    public boolean getUseTransaction() {
-        return useTransaction;
-    }
-
-    public boolean getUseCache() {
-        return useCache;
-    }
-
-    public ModelScreenWidget.Section getSection() {
-        return section;
-    }
-
-    public String getSourceLocation() {
-        return sourceLocation;
-    }
-
-    /**
-     * Renders this screen to a String, i.e. in a text format, as defined with the
-     * ScreenStringRenderer implementation.
-     *
-     * @param writer The Writer that the screen text will be written to
-     * @param context Map containing the screen context; the following are
-     *   reserved words in this context:
-     *    - parameters (contains any special initial parameters coming in)
-     *    - userLogin (if a user is logged in)
-     *    - autoUserLogin (if a user is automatically logged in, ie no password has been entered)
-     *    - formStringRenderer
-     *    - request, response, session, application (special case, only in HTML contexts, etc)
-     *    - delegator, dispatcher, security
-     *    - null (represents a null field value for entity operations)
-     *    - sections (used for decorators to reference the sections to be decorated and render them)
-     * @param screenStringRenderer An implementation of the ScreenStringRenderer
-     *   interface that is responsible for the actual text generation for
-     *   different screen elements; implementing your own makes it possible to
-     *   use the same screen definitions for many types of screen UIs
-     */
-    public void renderScreenString(Appendable writer, Map<String, Object> context, ScreenStringRenderer screenStringRenderer) throws ScreenRenderException {
-        // make sure the "nullField" object is in there for entity ops
-        context.put("nullField", GenericEntity.NULL_FIELD);
-
-        // wrap the whole screen rendering in a transaction, should improve performance in querying and such
-        Map<String, String> parameters = UtilGenerics.cast(context.get("parameters"));
-        boolean beganTransaction = false;
-        int transactionTimeout = -1;
-        if (parameters != null) {
-            String transactionTimeoutPar = parameters.get("TRANSACTION_TIMEOUT");
-            if (transactionTimeoutPar != null) {
-                try {
-                    transactionTimeout = Integer.parseInt(transactionTimeoutPar);
-                } catch (NumberFormatException nfe) {
-                    String msg = "TRANSACTION_TIMEOUT parameter for screen [" + this.sourceLocation + "#" + getName() + "] is invalid and it will be ignored: " + nfe.toString();
-                    Debug.logWarning(msg, module);
-                }
-            }
-        }
-
-        if (transactionTimeout < 0 && !transactionTimeoutExdr.isEmpty()) {
-            // no TRANSACTION_TIMEOUT parameter, check screen attribute
-            String transactionTimeoutStr = transactionTimeoutExdr.expandString(context);
-            if (UtilValidate.isNotEmpty(transactionTimeoutStr)) {
-                try {
-                    transactionTimeout = Integer.parseInt(transactionTimeoutStr);
-                } catch (NumberFormatException e) {
-                    Debug.logWarning(e, "Could not parse transaction-timeout value, original=[" + transactionTimeoutExdr + "], expanded=[" + transactionTimeoutStr + "]", module);
-                }
-            }
-        }
-
-        try {
-            // If transaction timeout is not present (i.e. is equal to -1), the default transaction timeout is used
-            // If transaction timeout is present, use it to start the transaction
-            // If transaction timeout is set to zero, no transaction is started
-            if (useTransaction) {
-                if (transactionTimeout < 0) {
-                    beganTransaction = TransactionUtil.begin();
-                }
-                if (transactionTimeout > 0) {
-                    beganTransaction = TransactionUtil.begin(transactionTimeout);
-                }
-            }
-
-            // render the screen, starting with the top-level section
-            this.section.renderWidgetString(writer, context, screenStringRenderer);
-            TransactionUtil.commit(beganTransaction);
-        } catch (Exception e) {
-            String errMsg = "Error rendering screen [" + this.sourceLocation + "#" + getName() + "]: " + e.toString();
-            Debug.logError(errMsg + ". Rolling back transaction.", module);
-            try {
-                // only rollback the transaction if we started one...
-                TransactionUtil.rollback(beganTransaction, errMsg, e);
-            } catch (GenericEntityException e2) {
-                Debug.logError(e2, "Could not rollback transaction: " + e2.toString(), module);
-            }
-
-            // throw nested exception, don't need to log details here: Debug.logError(e, errMsg, module);
-
-            // after rolling back, rethrow the exception
-            throw new ScreenRenderException(errMsg, e);
-        }
-    }
-
-    public LocalDispatcher getDispatcher(Map<String, Object> context) {
-        LocalDispatcher dispatcher = (LocalDispatcher) context.get("dispatcher");
-        return dispatcher;
-    }
-
-    public Delegator getDelegator(Map<String, Object> context) {
-        Delegator delegator = (Delegator) context.get("delegator");
-        return delegator;
-    }
-}
-
-
+/*******************************************************************************

+ * Licensed to the Apache Software Foundation (ASF) under one

+ * or more contributor license agreements.  See the NOTICE file

+ * distributed with this work for additional information

+ * regarding copyright ownership.  The ASF licenses this file

+ * to you under the Apache License, Version 2.0 (the

+ * "License"); you may not use this file except in compliance

+ * with the License.  You may obtain a copy of the License at

+ *

+ * http://www.apache.org/licenses/LICENSE-2.0

+ *

+ * Unless required by applicable law or agreed to in writing,

+ * software distributed under the License is distributed on an

+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY

+ * KIND, either express or implied.  See the License for the

+ * specific language governing permissions and limitations

+ * under the License.

+ *******************************************************************************/

+package org.ofbiz.widget.model;

+

+import java.util.Map;

+

+import org.ofbiz.base.util.Debug;

+import org.ofbiz.base.util.UtilGenerics;

+import org.ofbiz.base.util.UtilValidate;

+import org.ofbiz.base.util.UtilXml;

+import org.ofbiz.base.util.string.FlexibleStringExpander;

+import org.ofbiz.entity.Delegator;

+import org.ofbiz.entity.GenericEntity;

+import org.ofbiz.entity.GenericEntityException;

+import org.ofbiz.entity.transaction.TransactionUtil;

+import org.ofbiz.service.LocalDispatcher;

+import org.ofbiz.widget.renderer.ScreenRenderException;

+import org.ofbiz.widget.renderer.ScreenStringRenderer;

+import org.w3c.dom.Element;

+

+/**

+ * Widget Library - Screen model class

+ */

+@SuppressWarnings("serial")

+public class ModelScreen extends ModelWidget {

+

+    public static final String module = ModelScreen.class.getName();

+

+    private final String sourceLocation;

+    private final FlexibleStringExpander transactionTimeoutExdr;

+    private final Map<String, ModelScreen> modelScreenMap;

+    private final boolean useTransaction;

+    private final boolean useCache;

+    private final ModelScreenWidget.Section section;

+

+    /** XML Constructor */

+    public ModelScreen(Element screenElement, Map<String, ModelScreen> modelScreenMap, String sourceLocation) {

+        super(screenElement);

+        this.sourceLocation = sourceLocation;

+        this.transactionTimeoutExdr = FlexibleStringExpander.getInstance(screenElement.getAttribute("transaction-timeout"));

+        this.modelScreenMap = modelScreenMap;

+        this.useTransaction = "true".equals(screenElement.getAttribute("use-transaction"));

+        this.useCache = "true".equals(screenElement.getAttribute("use-cache"));

+

+        // read in the section, which will read all sub-widgets too

+        Element sectionElement = UtilXml.firstChildElement(screenElement, "section");

+        if (sectionElement == null) {

+            throw new IllegalArgumentException("No section found for the screen definition with name: " + getName());

+        }

+        this.section = new ModelScreenWidget.Section(this, sectionElement, true);

+    }

+

+    @Override

+    public void accept(ModelWidgetVisitor visitor) throws Exception {

+        visitor.visit(this);

+    }

+

+    public String getTransactionTimeout() {

+        return transactionTimeoutExdr.getOriginal();

+    }

+

+    public Map<String, ModelScreen> getModelScreenMap() {

+        return modelScreenMap;

+    }

+

+    public boolean getUseTransaction() {

+        return useTransaction;

+    }

+

+    public boolean getUseCache() {

+        return useCache;

+    }

+

+    public ModelScreenWidget.Section getSection() {

+        return section;

+    }

+

+    public String getSourceLocation() {

+        return sourceLocation;

+    }

+

+    /**

+     * Renders this screen to a String, i.e. in a text format, as defined with the

+     * ScreenStringRenderer implementation.

+     *

+     * @param writer The Writer that the screen text will be written to

+     * @param context Map containing the screen context; the following are

+     *   reserved words in this context:

+     *    - parameters (contains any special initial parameters coming in)

+     *    - userLogin (if a user is logged in)

+     *    - autoUserLogin (if a user is automatically logged in, ie no password has been entered)

+     *    - formStringRenderer

+     *    - request, response, session, application (special case, only in HTML contexts, etc)

+     *    - delegator, dispatcher, security

+     *    - null (represents a null field value for entity operations)

+     *    - sections (used for decorators to reference the sections to be decorated and render them)

+     * @param screenStringRenderer An implementation of the ScreenStringRenderer

+     *   interface that is responsible for the actual text generation for

+     *   different screen elements; implementing your own makes it possible to

+     *   use the same screen definitions for many types of screen UIs

+     */

+    public void renderScreenString(Appendable writer, Map<String, Object> context, ScreenStringRenderer screenStringRenderer) throws ScreenRenderException {

+        // make sure the "nullField" object is in there for entity ops

+        context.put("nullField", GenericEntity.NULL_FIELD);

+

+        // wrap the whole screen rendering in a transaction, should improve performance in querying and such

+        Map<String, String> parameters = UtilGenerics.cast(context.get("parameters"));

+        boolean beganTransaction = false;

+        int transactionTimeout = -1;

+        if (parameters != null) {

+            String transactionTimeoutPar = parameters.get("TRANSACTION_TIMEOUT");

+            if (transactionTimeoutPar != null) {

+                try {

+                    transactionTimeout = Integer.parseInt(transactionTimeoutPar);

+                } catch (NumberFormatException nfe) {

+                    String msg = "TRANSACTION_TIMEOUT parameter for screen [" + this.sourceLocation + "#" + getName() + "] is invalid and it will be ignored: " + nfe.toString();

+                    Debug.logWarning(msg, module);

+                }

+            }

+        }

+

+        if (transactionTimeout < 0 && !transactionTimeoutExdr.isEmpty()) {

+            // no TRANSACTION_TIMEOUT parameter, check screen attribute

+            String transactionTimeoutStr = transactionTimeoutExdr.expandString(context);

+            if (UtilValidate.isNotEmpty(transactionTimeoutStr)) {

+                try {

+                    transactionTimeout = Integer.parseInt(transactionTimeoutStr);

+                } catch (NumberFormatException e) {

+                    Debug.logWarning(e, "Could not parse transaction-timeout value, original=[" + transactionTimeoutExdr + "], expanded=[" + transactionTimeoutStr + "]", module);

+                }

+            }

+        }

+

+        try {

+            // If transaction timeout is not present (i.e. is equal to -1), the default transaction timeout is used

+            // If transaction timeout is present, use it to start the transaction

+            // If transaction timeout is set to zero, no transaction is started

+            if (useTransaction) {

+                if (transactionTimeout < 0) {

+                    beganTransaction = TransactionUtil.begin();

+                }

+                if (transactionTimeout > 0) {

+                    beganTransaction = TransactionUtil.begin(transactionTimeout);

+                }

+            }

+

+            // render the screen, starting with the top-level section

+            this.section.renderWidgetString(writer, context, screenStringRenderer);

+            TransactionUtil.commit(beganTransaction);

+        } catch (Exception e) {

+            String errMsg = "Error rendering screen [" + this.sourceLocation + "#" + getName() + "]: " + e.toString();

+            Debug.logError(errMsg + ". Rolling back transaction.", module);

+            try {

+                // only rollback the transaction if we started one...

+                TransactionUtil.rollback(beganTransaction, errMsg, e);

+            } catch (GenericEntityException e2) {

+                Debug.logError(e2, "Could not rollback transaction: " + e2.toString(), module);

+            }

+

+            // throw nested exception, don't need to log details here: Debug.logError(e, errMsg, module);

+

+            // after rolling back, rethrow the exception

+            throw new ScreenRenderException(errMsg, e);

+        }

+    }

+

+    public LocalDispatcher getDispatcher(Map<String, Object> context) {

+        LocalDispatcher dispatcher = (LocalDispatcher) context.get("dispatcher");

+        return dispatcher;

+    }

+

+    public Delegator getDelegator(Map<String, Object> context) {

+        Delegator delegator = (Delegator) context.get("delegator");

+        return delegator;

+    }

+}

+

+

diff --git a/framework/widget/src/org/ofbiz/widget/screen/ModelScreenCondition.java b/framework/widget/src/org/ofbiz/widget/model/ModelScreenCondition.java
similarity index 90%
rename from framework/widget/src/org/ofbiz/widget/screen/ModelScreenCondition.java
rename to framework/widget/src/org/ofbiz/widget/model/ModelScreenCondition.java
index fb1227a..8926f98 100644
--- a/framework/widget/src/org/ofbiz/widget/screen/ModelScreenCondition.java
+++ b/framework/widget/src/org/ofbiz/widget/model/ModelScreenCondition.java
@@ -1,96 +1,96 @@
-/*******************************************************************************
- * 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.screen;
-
-import java.util.Map;
-
-import org.ofbiz.base.util.UtilGenerics;
-import org.ofbiz.base.util.string.FlexibleStringExpander;
-import org.ofbiz.widget.AbstractModelCondition;
-import org.ofbiz.widget.AbstractModelCondition.DefaultConditionFactory;
-import org.ofbiz.widget.ModelCondition;
-import org.ofbiz.widget.ModelConditionFactory;
-import org.ofbiz.widget.ModelConditionVisitor;
-import org.ofbiz.widget.ModelWidget;
-import org.w3c.dom.Element;
-
-/**
- * Models the &lt;condition&gt; element.
- * 
- * @see <code>widget-screen.xsd</code>
- */
-@SuppressWarnings("serial")
-public final class ModelScreenCondition {
-
-    /*
-     * ----------------------------------------------------------------------- *
-     *                     DEVELOPERS PLEASE READ
-     * ----------------------------------------------------------------------- *
-     * 
-     * This model is intended to be a read-only data structure that represents
-     * an XML element. Outside of object construction, the class should not
-     * have any behaviors.
-     * 
-     * Instances of this class will be shared by multiple threads - therefore
-     * it is immutable. DO NOT CHANGE THE OBJECT'S STATE AT RUN TIME!
-     * 
-     */
-
-    public static final String module = ModelScreenCondition.class.getName();
-    public static final ModelConditionFactory SCREEN_CONDITION_FACTORY = new ScreenConditionFactory();
-
-    public static class IfEmptySection extends AbstractModelCondition {
-        private final FlexibleStringExpander sectionExdr;
-
-        private IfEmptySection(ModelConditionFactory factory, ModelWidget modelWidget, Element condElement) {
-            super (factory, modelWidget, condElement);
-            this.sectionExdr = FlexibleStringExpander.getInstance(condElement.getAttribute("section-name"));
-        }
-
-        @Override
-        public void accept(ModelConditionVisitor visitor) throws Exception {
-            visitor.visit(this);
-        }
-
-        @Override
-        public boolean eval(Map<String, Object> context) {
-            Map<String, Object> sectionsMap = UtilGenerics.toMap(context.get("sections"));
-            return !sectionsMap.containsKey(this.sectionExdr.expandString(context));
-        }
-
-        public FlexibleStringExpander getSectionExdr() {
-            return sectionExdr;
-        }
-    }
-
-    private static class ScreenConditionFactory extends DefaultConditionFactory {
-
-        @Override
-        public ModelCondition newInstance(ModelWidget modelWidget, Element conditionElement) {
-            if (conditionElement == null) {
-                return DefaultConditionFactory.TRUE;
-            }
-            if ("if-empty-section".equals(conditionElement.getNodeName())) {
-                return new IfEmptySection(this, modelWidget, conditionElement);
-            } else {
-                return super.newInstance(this, modelWidget,conditionElement);
-            }
-        }
-    }
-}
+/*******************************************************************************

+ * Licensed to the Apache Software Foundation (ASF) under one

+ * or more contributor license agreements.  See the NOTICE file

+ * distributed with this work for additional information

+ * regarding copyright ownership.  The ASF licenses this file

+ * to you under the Apache License, Version 2.0 (the

+ * "License"); you may not use this file except in compliance

+ * with the License.  You may obtain a copy of the License at

+ *

+ * http://www.apache.org/licenses/LICENSE-2.0

+ *

+ * Unless required by applicable law or agreed to in writing,

+ * software distributed under the License is distributed on an

+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY

+ * KIND, either express or implied.  See the License for the

+ * specific language governing permissions and limitations

+ * under the License.

+ *******************************************************************************/

+package org.ofbiz.widget.model;

+

+import java.util.Map;

+

+import org.ofbiz.base.util.UtilGenerics;

+import org.ofbiz.base.util.string.FlexibleStringExpander;

+import org.ofbiz.widget.model.AbstractModelCondition;

+import org.ofbiz.widget.model.AbstractModelCondition.DefaultConditionFactory;

+import org.ofbiz.widget.model.ModelCondition;

+import org.ofbiz.widget.model.ModelConditionFactory;

+import org.ofbiz.widget.model.ModelConditionVisitor;

+import org.ofbiz.widget.model.ModelWidget;

+import org.w3c.dom.Element;

+

+/**

+ * Models the &lt;condition&gt; element.

+ * 

+ * @see <code>widget-screen.xsd</code>

+ */

+@SuppressWarnings("serial")

+public final class ModelScreenCondition {

+

+    /*

+     * ----------------------------------------------------------------------- *

+     *                     DEVELOPERS PLEASE READ

+     * ----------------------------------------------------------------------- *

+     * 

+     * This model is intended to be a read-only data structure that represents

+     * an XML element. Outside of object construction, the class should not

+     * have any behaviors.

+     * 

+     * Instances of this class will be shared by multiple threads - therefore

+     * it is immutable. DO NOT CHANGE THE OBJECT'S STATE AT RUN TIME!

+     * 

+     */

+

+    public static final String module = ModelScreenCondition.class.getName();

+    public static final ModelConditionFactory SCREEN_CONDITION_FACTORY = new ScreenConditionFactory();

+

+    public static class IfEmptySection extends AbstractModelCondition {

+        private final FlexibleStringExpander sectionExdr;

+

+        private IfEmptySection(ModelConditionFactory factory, ModelWidget modelWidget, Element condElement) {

+            super (factory, modelWidget, condElement);

+            this.sectionExdr = FlexibleStringExpander.getInstance(condElement.getAttribute("section-name"));

+        }

+

+        @Override

+        public void accept(ModelConditionVisitor visitor) throws Exception {

+            visitor.visit(this);

+        }

+

+        @Override

+        public boolean eval(Map<String, Object> context) {

+            Map<String, Object> sectionsMap = UtilGenerics.toMap(context.get("sections"));

+            return !sectionsMap.containsKey(this.sectionExdr.expandString(context));

+        }

+

+        public FlexibleStringExpander getSectionExdr() {

+            return sectionExdr;

+        }

+    }

+

+    private static class ScreenConditionFactory extends DefaultConditionFactory {

+

+        @Override

+        public ModelCondition newInstance(ModelWidget modelWidget, Element conditionElement) {

+            if (conditionElement == null) {

+                return DefaultConditionFactory.TRUE;

+            }

+            if ("if-empty-section".equals(conditionElement.getNodeName())) {

+                return new IfEmptySection(this, modelWidget, conditionElement);

+            } else {

+                return super.newInstance(this, modelWidget,conditionElement);

+            }

+        }

+    }

+}

diff --git a/framework/widget/src/org/ofbiz/widget/screen/ModelScreenWidget.java b/framework/widget/src/org/ofbiz/widget/model/ModelScreenWidget.java
similarity index 98%
rename from framework/widget/src/org/ofbiz/widget/screen/ModelScreenWidget.java
rename to framework/widget/src/org/ofbiz/widget/model/ModelScreenWidget.java
index 4214aea..f5d1949 100644
--- a/framework/widget/src/org/ofbiz/widget/screen/ModelScreenWidget.java
+++ b/framework/widget/src/org/ofbiz/widget/model/ModelScreenWidget.java
@@ -1,1966 +1,1957 @@
-/*******************************************************************************
- * 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.screen;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.ListIterator;
-import java.util.Map;
-import java.util.Set;
-
-import javax.xml.parsers.ParserConfigurationException;
-
-import org.ofbiz.base.util.Debug;
-import org.ofbiz.base.util.GeneralException;
-import org.ofbiz.base.util.UtilCodec;
-import org.ofbiz.base.util.UtilGenerics;
-import org.ofbiz.base.util.UtilXml;
-import org.ofbiz.base.util.collections.MapStack;
-import org.ofbiz.base.util.string.FlexibleStringExpander;
-import org.ofbiz.entity.Delegator;
-import org.ofbiz.entity.GenericEntityException;
-import org.ofbiz.entity.GenericValue;
-import org.ofbiz.entity.util.EntityQuery;
-import org.ofbiz.widget.AbstractModelAction;
-import org.ofbiz.widget.CommonWidgetModels.*;
-import org.ofbiz.widget.CommonWidgetModels.AutoEntityParameters;
-import org.ofbiz.widget.CommonWidgetModels.AutoServiceParameters;
-import org.ofbiz.widget.CommonWidgetModels.Image;
-import org.ofbiz.widget.CommonWidgetModels.Parameter;
-import org.ofbiz.widget.ModelAction;
-import org.ofbiz.widget.ModelCondition;
-import org.ofbiz.widget.ModelWidget;
-import org.ofbiz.widget.ModelWidgetVisitor;
-import org.ofbiz.widget.PortalPageWorker;
-import org.ofbiz.widget.WidgetFactory;
-import org.ofbiz.widget.form.FormFactory;
-import org.ofbiz.widget.form.FormRenderer;
-import org.ofbiz.widget.form.FormStringRenderer;
-import org.ofbiz.widget.form.ModelForm;
-import org.ofbiz.widget.menu.MenuFactory;
-import org.ofbiz.widget.menu.MenuStringRenderer;
-import org.ofbiz.widget.menu.ModelMenu;
-import org.ofbiz.widget.tree.ModelTree;
-import org.ofbiz.widget.tree.TreeFactory;
-import org.ofbiz.widget.tree.TreeStringRenderer;
-import org.w3c.dom.Element;
-import org.xml.sax.SAXException;
-
-
-/**
- * Widget Library - Screen model class
- */
-@SuppressWarnings("serial")
-public abstract class ModelScreenWidget extends ModelWidget {
-    public static final String module = ModelScreenWidget.class.getName();
-
-    private final ModelScreen modelScreen;
-
-    public ModelScreenWidget(ModelScreen modelScreen, Element widgetElement) {
-        super(widgetElement);
-        this.modelScreen = modelScreen;
-        if (Debug.verboseOn()) Debug.logVerbose("Reading Screen sub-widget with name: " + widgetElement.getNodeName(), module);
-    }
-
-    public abstract void renderWidgetString(Appendable writer, Map<String, Object> context, ScreenStringRenderer screenStringRenderer) throws GeneralException, IOException;
-
-    protected static List<ModelScreenWidget> readSubWidgets(ModelScreen modelScreen, List<? extends Element> subElementList) {
-        if (subElementList.isEmpty()) {
-            return Collections.emptyList();
-        }
-        List<ModelScreenWidget> subWidgets = new ArrayList<ModelScreenWidget>(subElementList.size());
-        for (Element subElement: subElementList) {
-            subWidgets.add(WidgetFactory.getModelScreenWidget(modelScreen, subElement));
-        }
-        return Collections.unmodifiableList(subWidgets);
-    }
-
-    protected static void renderSubWidgetsString(List<ModelScreenWidget> subWidgets, Appendable writer, Map<String, Object> context, ScreenStringRenderer screenStringRenderer) throws GeneralException, IOException {
-        if (subWidgets == null) {
-            return;
-        }
-        for (ModelScreenWidget subWidget: subWidgets) {
-            if (Debug.verboseOn()) Debug.logVerbose("Rendering screen " + subWidget.getModelScreen().getName() + "; widget class is " + subWidget.getClass().getName(), module);
-
-            // render the sub-widget itself
-            subWidget.renderWidgetString(writer, context, screenStringRenderer);
-        }
-    }
-
-    public ModelScreen getModelScreen() {
-        return this.modelScreen;
-    }
-
-    public static final class SectionsRenderer implements Map<String, ModelScreenWidget> {
-        private final Map<String, ModelScreenWidget> sectionMap;
-        private final ScreenStringRenderer screenStringRenderer;
-        private final Map<String, Object> context;
-        private final Appendable writer;
-
-        public SectionsRenderer(Map<String, ModelScreenWidget> sectionMap, Map<String, Object> context, Appendable writer,
-                ScreenStringRenderer screenStringRenderer) {
-            Map<String, ModelScreenWidget> localMap = new HashMap<String, ModelScreenWidget>();
-            localMap.putAll(sectionMap);
-            this.sectionMap = Collections.unmodifiableMap(localMap);
-            this.context = context;
-            this.writer = writer;
-            this.screenStringRenderer = screenStringRenderer;
-        }
-
-        /** This is a lot like the ScreenRenderer class and returns an empty String so it can be used more easily with FreeMarker */
-        public String render(String sectionName) throws GeneralException, IOException {
-            ModelScreenWidget section = sectionMap.get(sectionName);
-            // if no section by that name, write nothing
-            if (section != null) {
-                section.renderWidgetString(this.writer, this.context, this.screenStringRenderer);
-            }
-            return "";
-        }
-
-        @Override
-        public int size() {
-            return sectionMap.size();
-        }
-
-        @Override
-        public boolean isEmpty() {
-            return sectionMap.isEmpty();
-        }
-
-        @Override
-        public boolean containsKey(Object key) {
-            return sectionMap.containsKey(key);
-        }
-
-        @Override
-        public boolean containsValue(Object value) {
-            return sectionMap.containsValue(value);
-        }
-
-        @Override
-        public ModelScreenWidget get(Object key) {
-            return sectionMap.get(key);
-        }
-
-        @Override
-        public ModelScreenWidget put(String key, ModelScreenWidget value) {
-            return sectionMap.put(key, value);
-        }
-
-        @Override
-        public ModelScreenWidget remove(Object key) {
-            return sectionMap.remove(key);
-        }
-
-        @Override
-        public void clear() {
-            sectionMap.clear();
-        }
-
-        @Override
-        public Set<String> keySet() {
-            return sectionMap.keySet();
-        }
-
-        @Override
-        public Collection<ModelScreenWidget> values() {
-            return sectionMap.values();
-        }
-
-        @Override
-        public Set<java.util.Map.Entry<String, ModelScreenWidget>> entrySet() {
-            return sectionMap.entrySet();
-        }
-
-        @Override
-        public boolean equals(Object o) {
-            return sectionMap.equals(o);
-        }
-
-        @Override
-        public int hashCode() {
-            return sectionMap.hashCode();
-        }
-
-        @Override
-        public void putAll(Map<? extends String, ? extends ModelScreenWidget> m) {
-            sectionMap.putAll(m);
-        }
-    }
-
-    public static final class Section extends ModelScreenWidget {
-        public static final String TAG_NAME = "section";
-        private final ModelCondition condition;
-        private final List<ModelAction> actions;
-        private final List<ModelScreenWidget> subWidgets;
-        private final List<ModelScreenWidget> failWidgets;
-        private final boolean isMainSection;
-
-        public Section(ModelScreen modelScreen, Element sectionElement) {
-            this(modelScreen, sectionElement, false);
-        }
-
-        public Section(ModelScreen modelScreen, Element sectionElement, boolean isMainSection) {
-            super(modelScreen, sectionElement);
-
-            // read condition under the "condition" element
-            Element conditionElement = UtilXml.firstChildElement(sectionElement, "condition");
-            if (conditionElement != null) {
-                conditionElement = UtilXml.firstChildElement(conditionElement);
-                this.condition = ModelScreenCondition.SCREEN_CONDITION_FACTORY.newInstance(modelScreen, conditionElement);
-            } else {
-                this.condition = null;
-            }
-
-            // read all actions under the "actions" element
-            Element actionsElement = UtilXml.firstChildElement(sectionElement, "actions");
-            if (actionsElement != null) {
-                this.actions = AbstractModelAction.readSubActions(modelScreen, actionsElement);
-            } else {
-                this.actions = Collections.emptyList();
-            }
-
-            // read sub-widgets
-            Element widgetsElement = UtilXml.firstChildElement(sectionElement, "widgets");
-            if (widgetsElement != null) {
-                List<? extends Element> subElementList = UtilXml.childElementList(widgetsElement);
-                this.subWidgets = ModelScreenWidget.readSubWidgets(getModelScreen(), subElementList);
-            } else {
-                this.subWidgets = Collections.emptyList();
-            }
-
-            // read fail-widgets
-            Element failWidgetsElement = UtilXml.firstChildElement(sectionElement, "fail-widgets");
-            if (failWidgetsElement != null) {
-                List<? extends Element> failElementList = UtilXml.childElementList(failWidgetsElement);
-                this.failWidgets = ModelScreenWidget.readSubWidgets(getModelScreen(), failElementList);
-            } else {
-                this.failWidgets = Collections.emptyList();
-            }
-            this.isMainSection = isMainSection;
-        }
-
-        @Override
-        public void accept(ModelWidgetVisitor visitor) throws Exception {
-            visitor.visit(this);
-        }
-
-        @Override
-        public void renderWidgetString(Appendable writer, Map<String, Object> context, ScreenStringRenderer screenStringRenderer) throws GeneralException, IOException {
-            // check the condition, if there is one
-            boolean condTrue = true;
-            if (this.condition != null) {
-                if (!this.condition.eval(context)) {
-                    condTrue = false;
-                }
-            }
-
-            // if condition does not exist or evals to true run actions and render widgets, otherwise render fail-widgets
-            if (condTrue) {
-                // run the actions only if true
-                AbstractModelAction.runSubActions(this.actions, context);
-
-                try {
-                    // section by definition do not themselves do anything, so this method will generally do nothing, but we'll call it anyway
-                    screenStringRenderer.renderSectionBegin(writer, context, this);
-
-                    // render sub-widgets
-                    renderSubWidgetsString(this.subWidgets, writer, context, screenStringRenderer);
-
-                    screenStringRenderer.renderSectionEnd(writer, context, this);
-                } catch (IOException e) {
-                    String errMsg = "Error rendering widgets section [" + getName() + "] in screen named [" + getModelScreen().getName() + "]: " + e.toString();
-                    Debug.logError(e, errMsg, module);
-                    throw new RuntimeException(errMsg);
-                }
-            } else {
-                try {
-                    // section by definition do not themselves do anything, so this method will generally do nothing, but we'll call it anyway
-                    screenStringRenderer.renderSectionBegin(writer, context, this);
-
-                    // render sub-widgets
-                    renderSubWidgetsString(this.failWidgets, writer, context, screenStringRenderer);
-
-                    screenStringRenderer.renderSectionEnd(writer, context, this);
-                } catch (IOException e) {
-                    String errMsg = "Error rendering fail-widgets section [" + this.getName() + "] in screen named [" + getModelScreen().getName() + "]: " + e.toString();
-                    Debug.logError(e, errMsg, module);
-                    throw new RuntimeException(errMsg);
-                }
-            }
-
-        }
-
-        @Override
-        public String getBoundaryCommentName() {
-            if (isMainSection) {
-                return getModelScreen().getSourceLocation() + "#" + getModelScreen().getName();
-            } else {
-                return getName();
-            }
-        }
-
-        public List<ModelAction> getActions() {
-            return actions;
-        }
-
-        public List<ModelScreenWidget> getSubWidgets() {
-            return subWidgets;
-        }
-
-        public List<ModelScreenWidget> getFailWidgets() {
-            return failWidgets;
-        }
-
-        public boolean isMainSection() {
-            return isMainSection;
-        }
-
-        public ModelCondition getCondition() {
-            return condition;
-        }
-    }
-
-    public static final class ColumnContainer extends ModelScreenWidget {
-        public static final String TAG_NAME = "column-container";
-        private final FlexibleStringExpander idExdr;
-        private final FlexibleStringExpander styleExdr;
-        private final List<Column> columns;
-
-        public ColumnContainer(ModelScreen modelScreen, Element containerElement) {
-            super(modelScreen, containerElement);
-            this.idExdr = FlexibleStringExpander.getInstance(containerElement.getAttribute("id"));
-            this.styleExdr = FlexibleStringExpander.getInstance(containerElement.getAttribute("style"));
-            List<? extends Element> subElementList = UtilXml.childElementList(containerElement, "column");
-            List<Column> columns = new ArrayList<Column>(subElementList.size());
-            for (Element element : subElementList) {
-                columns.add(new Column(modelScreen, element));
-            }
-            this.columns = Collections.unmodifiableList(columns);
-        }
-
-        @Override
-        public void accept(ModelWidgetVisitor visitor) throws Exception {
-            visitor.visit(this);
-        }
-
-        @Override
-        public void renderWidgetString(Appendable writer, Map<String, Object> context, ScreenStringRenderer screenStringRenderer) throws GeneralException, IOException {
-            try {
-                screenStringRenderer.renderColumnContainer(writer, context, this);
-            } catch (IOException e) {
-                String errMsg = "Error rendering container in screen named [" + getModelScreen().getName() + "]: " + e.toString();
-                Debug.logError(e, errMsg, module);
-                throw new RuntimeException(errMsg);
-            }
-        }
-
-        public List<Column> getColumns() {
-            return this.columns;
-        }
-
-        public String getId(Map<String, Object> context) {
-            return this.idExdr.expandString(context);
-        }
-
-        public String getStyle(Map<String, Object> context) {
-            return this.styleExdr.expandString(context);
-        }
-
-        public FlexibleStringExpander getIdExdr() {
-            return idExdr;
-        }
-
-        public FlexibleStringExpander getStyleExdr() {
-            return styleExdr;
-        }
-    }
-
-    public static final class Column extends ModelWidget {
-        private final FlexibleStringExpander idExdr;
-        private final FlexibleStringExpander styleExdr;
-        private final List<ModelScreenWidget> subWidgets;
-
-        public Column(ModelScreen modelScreen, Element columnElement) {
-            super(columnElement);
-            this.idExdr = FlexibleStringExpander.getInstance(columnElement.getAttribute("id"));
-            this.styleExdr = FlexibleStringExpander.getInstance(columnElement.getAttribute("style"));
-            List<? extends Element> subElementList = UtilXml.childElementList(columnElement);
-            this.subWidgets = Collections.unmodifiableList(readSubWidgets(modelScreen, subElementList));
-        }
-
-        public List<ModelScreenWidget> getSubWidgets() {
-            return this.subWidgets;
-        }
-
-        public String getId(Map<String, Object> context) {
-            return this.idExdr.expandString(context);
-        }
-
-        public String getStyle(Map<String, Object> context) {
-            return this.styleExdr.expandString(context);
-        }
-
-        @Override
-        public void accept(ModelWidgetVisitor visitor) throws Exception {
-            visitor.visit(this);
-        }
-
-        public FlexibleStringExpander getIdExdr() {
-            return idExdr;
-        }
-
-        public FlexibleStringExpander getStyleExdr() {
-            return styleExdr;
-        }
-    }
-
-    public static final class Container extends ModelScreenWidget {
-        public static final String TAG_NAME = "container";
-        private final FlexibleStringExpander idExdr;
-        private final FlexibleStringExpander styleExdr;
-        private final FlexibleStringExpander autoUpdateTargetExdr;
-        private final FlexibleStringExpander autoUpdateInterval;
-        private final List<ModelScreenWidget> subWidgets;
-
-        public Container(ModelScreen modelScreen, Element containerElement) {
-            super(modelScreen, containerElement);
-            this.idExdr = FlexibleStringExpander.getInstance(containerElement.getAttribute("id"));
-            this.styleExdr = FlexibleStringExpander.getInstance(containerElement.getAttribute("style"));
-            this.autoUpdateTargetExdr = FlexibleStringExpander.getInstance(containerElement.getAttribute("auto-update-target"));
-            String autoUpdateInterval = containerElement.getAttribute("auto-update-interval");
-            if (autoUpdateInterval.isEmpty()) {
-                autoUpdateInterval = "2";
-            }
-            this.autoUpdateInterval = FlexibleStringExpander.getInstance(autoUpdateInterval);
-            // read sub-widgets
-            List<? extends Element> subElementList = UtilXml.childElementList(containerElement);
-            this.subWidgets = ModelScreenWidget.readSubWidgets(getModelScreen(), subElementList);
-        }
-
-        @Override
-        public void renderWidgetString(Appendable writer, Map<String, Object> context, ScreenStringRenderer screenStringRenderer) throws GeneralException, IOException {
-            try {
-                screenStringRenderer.renderContainerBegin(writer, context, this);
-
-                // render sub-widgets
-                renderSubWidgetsString(this.subWidgets, writer, context, screenStringRenderer);
-
-                screenStringRenderer.renderContainerEnd(writer, context, this);
-            } catch (IOException e) {
-                String errMsg = "Error rendering container in screen named [" + getModelScreen().getName() + "]: " + e.toString();
-                Debug.logError(e, errMsg, module);
-                throw new RuntimeException(errMsg);
-            }
-        }
-
-        public String getId(Map<String, Object> context) {
-            return this.idExdr.expandString(context);
-        }
-
-        public String getStyle(Map<String, Object> context) {
-            return this.styleExdr.expandString(context);
-        }
-
-        public String getAutoUpdateTargetExdr(Map<String, Object> context) {
-            return this.autoUpdateTargetExdr.expandString(context);
-        }
-
-        public String getAutoUpdateInterval(Map<String, Object> context) {
-            return this.autoUpdateInterval.expandString(context);
-        }
-
-        public List<ModelScreenWidget> getSubWidgets() {
-            return subWidgets;
-        }
-
-        @Override
-        public void accept(ModelWidgetVisitor visitor) throws Exception {
-            visitor.visit(this);
-        }
-
-        public FlexibleStringExpander getIdExdr() {
-            return idExdr;
-        }
-
-        public FlexibleStringExpander getStyleExdr() {
-            return styleExdr;
-        }
-
-        public FlexibleStringExpander getAutoUpdateTargetExdr() {
-            return autoUpdateTargetExdr;
-        }
-
-        public FlexibleStringExpander getAutoUpdateInterval() {
-            return autoUpdateInterval;
-        }
-    }
-
-    public static final class Screenlet extends ModelScreenWidget {
-        public static final String TAG_NAME = "screenlet";
-        private final FlexibleStringExpander idExdr;
-        private final FlexibleStringExpander titleExdr;
-        private final Menu navigationMenu;
-        private final Menu tabMenu;
-        private final Form navigationForm;
-        private final boolean collapsible;
-        private final FlexibleStringExpander initiallyCollapsed;
-        private final boolean saveCollapsed;
-        private final boolean padded;
-        private final List<ModelScreenWidget> subWidgets;
-
-        public Screenlet(ModelScreen modelScreen, Element screenletElement) {
-            super(modelScreen, screenletElement);
-            this.idExdr = FlexibleStringExpander.getInstance(screenletElement.getAttribute("id"));
-            boolean collapsible = "true".equals(screenletElement.getAttribute("collapsible"));
-            this.initiallyCollapsed = FlexibleStringExpander.getInstance(screenletElement.getAttribute("initially-collapsed"));
-            if ("true".equals(this.initiallyCollapsed.getOriginal())) {
-                collapsible = true;
-            }
-            this.collapsible = collapsible;
-            // By default, for a collapsible screenlet, the collapsed/expanded status must be saved
-            this.saveCollapsed = !("false".equals(screenletElement.getAttribute("save-collapsed")));
-
-            boolean padded = !"false".equals(screenletElement.getAttribute("padded"));
-            if (this.collapsible && getName().isEmpty() && idExdr.isEmpty()) {
-                throw new IllegalArgumentException("Collapsible screenlets must have a name or id [" + getModelScreen().getName() + "]");
-            }
-            this.titleExdr = FlexibleStringExpander.getInstance(screenletElement.getAttribute("title"));
-            List<? extends Element> subElementList = UtilXml.childElementList(screenletElement);
-            // Make a copy of the unmodifiable List so we can modify it.
-            ArrayList<ModelScreenWidget> subWidgets = new ArrayList<ModelScreenWidget>(ModelScreenWidget.readSubWidgets(getModelScreen(), subElementList));
-            Menu navigationMenu = null;
-            String navMenuName = screenletElement.getAttribute("navigation-menu-name");
-            if (!navMenuName.isEmpty()) {
-                for (ModelWidget subWidget : subWidgets) {
-                    if (navMenuName.equals(subWidget.getName()) && subWidget instanceof Menu) {
-                        navigationMenu = (Menu) subWidget;
-                        subWidgets.remove(subWidget);
-                        break;
-                    }
-                }
-            }
-            this.navigationMenu = navigationMenu;
-            Menu tabMenu = null;
-            String tabMenuName = screenletElement.getAttribute("tab-menu-name");
-            if (!tabMenuName.isEmpty()) {
-                for (ModelWidget subWidget : subWidgets) {
-                    if (tabMenuName.equals(subWidget.getName()) && subWidget instanceof Menu) {
-                        tabMenu = (Menu) subWidget;
-                        subWidgets.remove(subWidget);
-                        break;
-                    }
-                }
-            }
-            this.tabMenu = tabMenu;
-            Form navigationForm = null;
-            String formName = screenletElement.getAttribute("navigation-form-name");
-            if (!formName.isEmpty() && this.navigationMenu == null) {
-                for (ModelWidget subWidget : subWidgets) {
-                    if (formName.equals(subWidget.getName()) && subWidget instanceof Form) {
-                        navigationForm = (Form) subWidget;
-                        padded = false;
-                        break;
-                    }
-                }
-            }
-            this.subWidgets = Collections.unmodifiableList(subWidgets);
-            this.navigationForm = navigationForm;
-            this.padded = padded;
-        }
-
-        @Override
-        public void renderWidgetString(Appendable writer, Map<String, Object> context, ScreenStringRenderer screenStringRenderer) throws GeneralException, IOException {
-            boolean collapsed = getInitiallyCollapsed(context);
-            if (this.collapsible) {
-                String preferenceKey = getPreferenceKey(context) + "_collapsed";
-                Map<String, Object> requestParameters = UtilGenerics.checkMap(context.get("requestParameters"));
-                if (requestParameters != null) {
-                    String collapsedParam = (String) requestParameters.get(preferenceKey);
-                    collapsed = "true".equals(collapsedParam);
-                }
-            }
-            try {
-                screenStringRenderer.renderScreenletBegin(writer, context, collapsed, this);
-                for (ModelScreenWidget subWidget : this.subWidgets) {
-                    screenStringRenderer.renderScreenletSubWidget(writer, context, subWidget, this);
-                }
-                screenStringRenderer.renderScreenletEnd(writer, context, this);
-            } catch (IOException e) {
-                String errMsg = "Error rendering screenlet in screen named [" + getModelScreen().getName() + "]: ";
-                Debug.logError(e, errMsg, module);
-                throw new RuntimeException(errMsg + e);
-            }
-        }
-
-        public boolean collapsible() {
-            return this.collapsible;
-        }
-
-        //initially-collapsed status, which may be overriden by user preference
-        public boolean getInitiallyCollapsed(Map<String, Object> context) {
-            String screenletId = this.getId(context) + "_collapsed";
-            Map<String, ? extends Object> userPreferences = UtilGenerics.checkMap(context.get("userPreferences"));
-            if (userPreferences != null && userPreferences.containsKey(screenletId)) {
-                return Boolean.valueOf((String)userPreferences.get(screenletId)).booleanValue() ;
-            }
-
-            return "true".equals(this.initiallyCollapsed.expand(context));
-        }
-
-        public boolean saveCollapsed() {
-            return this.saveCollapsed;
-        }
-        public boolean padded() {
-            return this.padded;
-        }
-
-        public String getPreferenceKey(Map<String, Object> context) {
-            String name = this.idExdr.expandString(context);
-            if (name.isEmpty()) {
-                name = "screenlet" + "_" + Integer.toHexString(hashCode());
-            }
-            return name;
-        }
-
-        public String getId(Map<String, Object> context) {
-            return this.idExdr.expandString(context);
-        }
-
-        public List<ModelScreenWidget> getSubWidgets() {
-            return subWidgets;
-        }
-
-        public String getTitle(Map<String, Object> context) {
-            String title = this.titleExdr.expandString(context);
-            UtilCodec.SimpleEncoder simpleEncoder = (UtilCodec.SimpleEncoder) context.get("simpleEncoder");
-            if (simpleEncoder != null) {
-                title = simpleEncoder.encode(title);
-            }
-            return title;
-        }
-
-        public Menu getNavigationMenu() {
-            return this.navigationMenu;
-        }
-
-        public Form getNavigationForm() {
-            return this.navigationForm;
-        }
-
-        public Menu getTabMenu() {
-            return this.tabMenu;
-        }
-
-        @Override
-        public void accept(ModelWidgetVisitor visitor) throws Exception {
-            visitor.visit(this);
-        }
-
-        public FlexibleStringExpander getIdExdr() {
-            return idExdr;
-        }
-
-        public FlexibleStringExpander getTitleExdr() {
-            return titleExdr;
-        }
-
-        public boolean getCollapsible() {
-            return collapsible;
-        }
-
-        public FlexibleStringExpander getInitiallyCollapsed() {
-            return initiallyCollapsed;
-        }
-
-        public boolean getSaveCollapsed() {
-            return saveCollapsed;
-        }
-
-        public boolean getPadded() {
-            return padded;
-        }
-    }
-
-    public static final class HorizontalSeparator extends ModelScreenWidget {
-        public static final String TAG_NAME = "horizontal-separator";
-        private final FlexibleStringExpander idExdr;
-        private final FlexibleStringExpander styleExdr;
-
-        public HorizontalSeparator(ModelScreen modelScreen, Element separatorElement) {
-            super(modelScreen, separatorElement);
-            this.idExdr = FlexibleStringExpander.getInstance(separatorElement.getAttribute("id"));
-            this.styleExdr = FlexibleStringExpander.getInstance(separatorElement.getAttribute("style"));
-        }
-
-        @Override
-        public void renderWidgetString(Appendable writer, Map<String, Object> context, ScreenStringRenderer screenStringRenderer) throws GeneralException, IOException {
-            screenStringRenderer.renderHorizontalSeparator(writer, context, this);
-        }
-
-        public String getId(Map<String, Object> context) {
-            return this.idExdr.expandString(context);
-        }
-
-        public String getStyle(Map<String, Object> context) {
-            return this.styleExdr.expandString(context);
-        }
-
-        @Override
-        public void accept(ModelWidgetVisitor visitor) throws Exception {
-            visitor.visit(this);
-        }
-
-        public FlexibleStringExpander getIdExdr() {
-            return idExdr;
-        }
-
-        public FlexibleStringExpander getStyleExdr() {
-            return styleExdr;
-        }
-    }
-
-    public static final class IncludeScreen extends ModelScreenWidget {
-        public static final String TAG_NAME = "include-screen";
-        private final FlexibleStringExpander nameExdr;
-        private final FlexibleStringExpander locationExdr;
-        private final FlexibleStringExpander shareScopeExdr;
-
-        public IncludeScreen(ModelScreen modelScreen, Element includeScreenElement) {
-            super(modelScreen, includeScreenElement);
-            this.nameExdr = FlexibleStringExpander.getInstance(includeScreenElement.getAttribute("name"));
-            this.locationExdr = FlexibleStringExpander.getInstance(includeScreenElement.getAttribute("location"));
-            this.shareScopeExdr = FlexibleStringExpander.getInstance(includeScreenElement.getAttribute("share-scope"));
-        }
-
-        @Override
-        public void renderWidgetString(Appendable writer, Map<String, Object> context, ScreenStringRenderer screenStringRenderer) throws GeneralException, IOException {
-            // if we are not sharing the scope, protect it using the MapStack
-            boolean protectScope = !shareScope(context);
-            if (protectScope) {
-                if (!(context instanceof MapStack<?>)) {
-                    context = MapStack.create(context);
-                }
-
-                UtilGenerics.<MapStack<String>>cast(context).push();
-
-                // build the widgetpath
-                List<String> widgetTrail = UtilGenerics.toList(context.get("_WIDGETTRAIL_"));
-                if (widgetTrail == null) {
-                    widgetTrail = new LinkedList<String>();
-                }
-
-                String thisName = nameExdr.expandString(context);
-                widgetTrail.add(thisName);
-                context.put("_WIDGETTRAIL_", widgetTrail);
-            }
-
-            // don't need the renderer here, will just pass this on down to another screen call; screenStringRenderer.renderContainerBegin(writer, context, this);
-            String name = this.getName(context);
-            String location = this.getLocation(context);
-
-            if (name.isEmpty()) {
-                if (Debug.verboseOn()) Debug.logVerbose("In the include-screen tag the screen name was empty, ignoring include; in screen [" + getModelScreen().getName() + "]", module);
-                return;
-            }
-
-            ScreenFactory.renderReferencedScreen(name, location, this, writer, context, screenStringRenderer);
-
-            if (protectScope) {
-                UtilGenerics.<MapStack<String>>cast(context).pop();
-            }
-        }
-
-        public String getName(Map<String, Object> context) {
-            return this.nameExdr.expandString(context);
-        }
-
-        public String getLocation(Map<String, Object> context) {
-            return this.locationExdr.expandString(context);
-        }
-
-        public boolean shareScope(Map<String, Object> context) {
-            String shareScopeString = this.shareScopeExdr.expandString(context);
-            // defaults to false, so anything but true is false
-            return "true".equals(shareScopeString);
-        }
-
-        @Override
-        public void accept(ModelWidgetVisitor visitor) throws Exception {
-            visitor.visit(this);
-        }
-
-        public FlexibleStringExpander getNameExdr() {
-            return nameExdr;
-        }
-
-        public FlexibleStringExpander getLocationExdr() {
-            return locationExdr;
-        }
-
-        public FlexibleStringExpander getShareScopeExdr() {
-            return shareScopeExdr;
-        }
-    }
-
-    public static final class DecoratorScreen extends ModelScreenWidget {
-        public static final String TAG_NAME = "decorator-screen";
-        private final FlexibleStringExpander nameExdr;
-        private final FlexibleStringExpander locationExdr;
-        private final Map<String, ModelScreenWidget> sectionMap;
-
-        public DecoratorScreen(ModelScreen modelScreen, Element decoratorScreenElement) {
-            super(modelScreen, decoratorScreenElement);
-            this.nameExdr = FlexibleStringExpander.getInstance(decoratorScreenElement.getAttribute("name"));
-            this.locationExdr = FlexibleStringExpander.getInstance(decoratorScreenElement.getAttribute("location"));
-            Map<String, ModelScreenWidget> sectionMap = new HashMap<String, ModelScreenWidget>();
-            List<? extends Element> decoratorSectionElementList = UtilXml.childElementList(decoratorScreenElement, "decorator-section");
-            for (Element decoratorSectionElement: decoratorSectionElementList) {
-                DecoratorSection decoratorSection = new DecoratorSection(modelScreen, decoratorSectionElement);
-                sectionMap.put(decoratorSection.getName(), decoratorSection);
-            }
-            this.sectionMap = Collections.unmodifiableMap(sectionMap);
-        }
-
-        @Override
-        @SuppressWarnings("unchecked")
-        public void renderWidgetString(Appendable writer, Map<String, Object> context, ScreenStringRenderer screenStringRenderer) throws GeneralException, IOException {
-            // isolate the scope
-            if (!(context instanceof MapStack)) {
-                context = MapStack.create(context);
-            }
-
-            MapStack contextMs = (MapStack) context;
-
-            // create a standAloneStack, basically a "save point" for this SectionsRenderer, and make a new "screens" object just for it so it is isolated and doesn't follow the stack down
-            MapStack standAloneStack = contextMs.standAloneChildStack();
-            standAloneStack.put("screens", new ScreenRenderer(writer, standAloneStack, screenStringRenderer));
-            SectionsRenderer sections = new SectionsRenderer(this.sectionMap, standAloneStack, writer, screenStringRenderer);
-
-            // put the sectionMap in the context, make sure it is in the sub-scope, ie after calling push on the MapStack
-            contextMs.push();
-            context.put("sections", sections);
-
-            String name = this.getName(context);
-            String location = this.getLocation(context);
-
-            ScreenFactory.renderReferencedScreen(name, location, this, writer, context, screenStringRenderer);
-
-            contextMs.pop();
-        }
-
-        public String getName(Map<String, Object> context) {
-            return this.nameExdr.expandString(context);
-        }
-
-        public String getLocation(Map<String, Object> context) {
-            return this.locationExdr.expandString(context);
-        }
-
-        public Map<String, ModelScreenWidget> getSectionMap() {
-            return sectionMap;
-        }
-
-        @Override
-        public void accept(ModelWidgetVisitor visitor) throws Exception {
-            visitor.visit(this);
-        }
-
-        public FlexibleStringExpander getNameExdr() {
-            return nameExdr;
-        }
-
-        public FlexibleStringExpander getLocationExdr() {
-            return locationExdr;
-        }
-
-    }
-
-    public static final class DecoratorSection extends ModelScreenWidget {
-        public static final String TAG_NAME = "decorator-section";
-        private final List<ModelScreenWidget> subWidgets;
-
-        public DecoratorSection(ModelScreen modelScreen, Element decoratorSectionElement) {
-            super(modelScreen, decoratorSectionElement);
-            // read sub-widgets
-            List<? extends Element> subElementList = UtilXml.childElementList(decoratorSectionElement);
-            this.subWidgets = ModelScreenWidget.readSubWidgets(getModelScreen(), subElementList);
-        }
-
-        @Override
-        public void renderWidgetString(Appendable writer, Map<String, Object> context, ScreenStringRenderer screenStringRenderer) throws GeneralException, IOException {
-            // render sub-widgets
-            renderSubWidgetsString(this.subWidgets, writer, context, screenStringRenderer);
-        }
-
-        public List<ModelScreenWidget> getSubWidgets() {
-            return subWidgets;
-        }
-
-        @Override
-        public void accept(ModelWidgetVisitor visitor) throws Exception {
-            visitor.visit(this);
-        }
-    }
-
-    public static final class DecoratorSectionInclude extends ModelScreenWidget {
-        public static final String TAG_NAME = "decorator-section-include";
-
-        public DecoratorSectionInclude(ModelScreen modelScreen, Element decoratorSectionElement) {
-            super(modelScreen, decoratorSectionElement);
-        }
-
-        @Override
-        public void renderWidgetString(Appendable writer, Map<String, Object> context, ScreenStringRenderer screenStringRenderer) throws GeneralException, IOException {
-            Map<String, ? extends Object> preRenderedContent = UtilGenerics.checkMap(context.get("preRenderedContent"));
-            if (preRenderedContent != null && preRenderedContent.containsKey(getName())) {
-                try {
-                    writer.append((String) preRenderedContent.get(getName()));
-                } catch (IOException e) {
-                    String errMsg = "Error rendering pre-rendered content in screen named [" + getModelScreen().getName() + "]: " + e.toString();
-                    Debug.logError(e, errMsg, module);
-                    throw new RuntimeException(errMsg);
-                }
-            } else {
-                SectionsRenderer sections = (SectionsRenderer) context.get("sections");
-                // for now if sections is null, just log a warning; may be permissible to make the screen for flexible
-                if (sections == null) {
-                    Debug.logWarning("In decorator-section-include could not find sections object in the context, not rendering section with name [" + getName() + "]", module);
-                } else {
-                    sections.render(getName());
-                }
-            }
-        }
-
-        @Override
-        public void accept(ModelWidgetVisitor visitor) throws Exception {
-            visitor.visit(this);
-        }
-    }
-
-    public static final class Label extends ModelScreenWidget {
-        public static final String TAG_NAME = "label";
-        private final FlexibleStringExpander textExdr;
-        private final FlexibleStringExpander idExdr;
-        private final FlexibleStringExpander styleExdr;
-
-        public Label(ModelScreen modelScreen, Element labelElement) {
-            super(modelScreen, labelElement);
-
-            // put the text attribute first, then the pcdata under the element, if both are there of course
-            String textAttr = labelElement.getAttribute("text");
-            String pcdata = UtilXml.elementValue(labelElement);
-            if (pcdata == null) {
-                pcdata = "";
-            }
-            this.textExdr = FlexibleStringExpander.getInstance(textAttr + pcdata);
-
-            this.idExdr = FlexibleStringExpander.getInstance(labelElement.getAttribute("id"));
-            this.styleExdr = FlexibleStringExpander.getInstance(labelElement.getAttribute("style"));
-        }
-
-        @Override
-        public void renderWidgetString(Appendable writer, Map<String, Object> context, ScreenStringRenderer screenStringRenderer) {
-            try {
-                screenStringRenderer.renderLabel(writer, context, this);
-            } catch (IOException e) {
-                String errMsg = "Error rendering label in screen named [" + getModelScreen().getName() + "]: " + e.toString();
-                Debug.logError(e, errMsg, module);
-                throw new RuntimeException(errMsg);
-            }
-        }
-
-        public String getText(Map<String, Object> context) {
-            String text = this.textExdr.expandString(context);
-            // FIXME: Encoding should be done by the renderer, not by the model.
-            UtilCodec.SimpleEncoder simpleEncoder = (UtilCodec.SimpleEncoder) context.get("simpleEncoder");
-            if (simpleEncoder != null) {
-                text = simpleEncoder.encode(text);
-            }
-            return text;
-        }
-
-        public String getId(Map<String, Object> context) {
-            return this.idExdr.expandString(context);
-        }
-
-        public String getStyle(Map<String, Object> context) {
-            return this.styleExdr.expandString(context);
-        }
-
-        @Override
-        public void accept(ModelWidgetVisitor visitor) throws Exception {
-            visitor.visit(this);
-        }
-
-        public FlexibleStringExpander getTextExdr() {
-            return textExdr;
-        }
-
-        public FlexibleStringExpander getIdExdr() {
-            return idExdr;
-        }
-
-        public FlexibleStringExpander getStyleExdr() {
-            return styleExdr;
-        }
-    }
-
-    public static final class Form extends ModelScreenWidget {
-        public static final String TAG_NAME = "include-form";
-        private final FlexibleStringExpander nameExdr;
-        private final FlexibleStringExpander locationExdr;
-        private final FlexibleStringExpander shareScopeExdr;
-
-        public Form(ModelScreen modelScreen, Element formElement) {
-            super(modelScreen, formElement);
-            this.nameExdr = FlexibleStringExpander.getInstance(formElement.getAttribute("name"));
-            this.locationExdr = FlexibleStringExpander.getInstance(formElement.getAttribute("location"));
-            this.shareScopeExdr = FlexibleStringExpander.getInstance(formElement.getAttribute("share-scope"));
-        }
-
-        @Override
-        public void renderWidgetString(Appendable writer, Map<String, Object> context, ScreenStringRenderer screenStringRenderer) {
-            // Output format might not support forms, so make form rendering optional.
-            FormStringRenderer formStringRenderer = (FormStringRenderer) context.get("formStringRenderer");
-            if (formStringRenderer == null) {
-                Debug.logVerbose("FormStringRenderer instance not found in rendering context, form not rendered.", module);
-                return;
-            }
-            boolean protectScope = !shareScope(context);
-            if (protectScope) {
-                if (!(context instanceof MapStack<?>)) {
-                    context = MapStack.create(context);
-                }
-                UtilGenerics.<MapStack<String>>cast(context).push();
-            }
-            ModelForm modelForm = getModelForm(context);
-            FormRenderer renderer = new FormRenderer(modelForm, formStringRenderer);
-            try {
-                renderer.render(writer, context);
-            } catch (Exception e) {
-                String errMsg = "Error rendering included form named [" + getName() + "] at location [" + this.getLocation(context) + "]: " + e.toString();
-                Debug.logError(e, errMsg, module);
-                throw new RuntimeException(errMsg + e);
-            }
-
-            if (protectScope) {
-                UtilGenerics.<MapStack<String>>cast(context).pop();
-            }
-        }
-
-        public ModelForm getModelForm(Map<String, Object> context) {
-            ModelForm modelForm = null;
-            String name = this.getName(context);
-            String location = this.getLocation(context);
-            try {
-                modelForm = FormFactory.getFormFromLocation(location, name, getModelScreen().getDelegator(context).getModelReader(), getModelScreen().getDispatcher(context).getDispatchContext());
-            } catch (Exception e) {
-                String errMsg = "Error rendering included form named [" + name + "] at location [" + location + "]: ";
-                Debug.logError(e, errMsg, module);
-                throw new RuntimeException(errMsg + e);
-            }
-            return modelForm;
-        }
-
-        public String getName(Map<String, Object> context) {
-            return this.nameExdr.expandString(context);
-        }
-
-        public String getLocation() {
-            return locationExdr.getOriginal();
-        }
-
-        public String getLocation(Map<String, Object> context) {
-            return this.locationExdr.expandString(context);
-        }
-
-        public boolean shareScope(Map<String, Object> context) {
-            String shareScopeString = this.shareScopeExdr.expandString(context);
-            // defaults to false, so anything but true is false
-            return "true".equals(shareScopeString);
-        }
-
-        @Override
-        public void accept(ModelWidgetVisitor visitor) throws Exception {
-            visitor.visit(this);
-        }
-
-        public FlexibleStringExpander getNameExdr() {
-            return nameExdr;
-        }
-
-        public FlexibleStringExpander getLocationExdr() {
-            return locationExdr;
-        }
-
-        public FlexibleStringExpander getShareScopeExdr() {
-            return shareScopeExdr;
-        }
-
-    }
-
-    public static final class Tree extends ModelScreenWidget {
-        public static final String TAG_NAME = "include-tree";
-        private final FlexibleStringExpander nameExdr;
-        private final FlexibleStringExpander locationExdr;
-        private final FlexibleStringExpander shareScopeExdr;
-
-        public Tree(ModelScreen modelScreen, Element treeElement) {
-            super(modelScreen, treeElement);
-            this.nameExdr = FlexibleStringExpander.getInstance(treeElement.getAttribute("name"));
-            this.locationExdr = FlexibleStringExpander.getInstance(treeElement.getAttribute("location"));
-            this.shareScopeExdr = FlexibleStringExpander.getInstance(treeElement.getAttribute("share-scope"));
-        }
-
-        @Override
-        public void renderWidgetString(Appendable writer, Map<String, Object> context, ScreenStringRenderer screenStringRenderer) throws GeneralException, IOException {
-            // Output format might not support trees, so make tree rendering optional.
-            TreeStringRenderer treeStringRenderer = (TreeStringRenderer) context.get("treeStringRenderer");
-            if (treeStringRenderer == null) {
-                Debug.logVerbose("TreeStringRenderer instance not found in rendering context, tree not rendered.", module);
-                return;
-            }
-            boolean protectScope = !shareScope(context);
-            if (protectScope) {
-                if (!(context instanceof MapStack<?>)) {
-                    context = MapStack.create(context);
-                }
-                UtilGenerics.<MapStack<String>>cast(context).push();
-            }
-
-            String name = this.getName(context);
-            String location = this.getLocation(context);
-            ModelTree modelTree = null;
-            try {
-                modelTree = TreeFactory.getTreeFromLocation(this.getLocation(context), this.getName(context), getModelScreen().getDelegator(context), getModelScreen().getDispatcher(context));
-            } catch (IOException e) {
-                String errMsg = "Error rendering included tree named [" + name + "] at location [" + location + "]: " + e.toString();
-                Debug.logError(e, errMsg, module);
-                throw new RuntimeException(errMsg);
-            } catch (SAXException e) {
-                String errMsg = "Error rendering included tree named [" + name + "] at location [" + location + "]: " + e.toString();
-                Debug.logError(e, errMsg, module);
-                throw new RuntimeException(errMsg);
-            } catch (ParserConfigurationException e) {
-                String errMsg = "Error rendering included tree named [" + name + "] at location [" + location + "]: " + e.toString();
-                Debug.logError(e, errMsg, module);
-                throw new RuntimeException(errMsg);
-            }
-            modelTree.renderTreeString(writer, context, treeStringRenderer);
-            if (protectScope) {
-                UtilGenerics.<MapStack<String>>cast(context).pop();
-            }
-        }
-
-        public String getName(Map<String, Object> context) {
-            return this.nameExdr.expandString(context);
-        }
-
-        public String getLocation(Map<String, Object> context) {
-            return this.locationExdr.expandString(context);
-        }
-
-        public boolean shareScope(Map<String, Object> context) {
-            String shareScopeString = this.shareScopeExdr.expandString(context);
-            // defaults to false, so anything but true is false
-            return "true".equals(shareScopeString);
-        }
-
-        @Override
-        public void accept(ModelWidgetVisitor visitor) throws Exception {
-            visitor.visit(this);
-        }
-
-        public FlexibleStringExpander getLocationExdr() {
-            return locationExdr;
-        }
-
-        public FlexibleStringExpander getShareScopeExdr() {
-            return shareScopeExdr;
-        }
-    }
-
-    public static final class PlatformSpecific extends ModelScreenWidget {
-        public static final String TAG_NAME = "platform-specific";
-        private final Map<String, ModelScreenWidget> subWidgets;
-
-        public PlatformSpecific(ModelScreen modelScreen, Element platformSpecificElement) {
-            super(modelScreen, platformSpecificElement);
-            Map<String, ModelScreenWidget> subWidgets = new HashMap<String, ModelScreenWidget>();
-            List<? extends Element> childElements = UtilXml.childElementList(platformSpecificElement);
-            if (childElements != null) {
-                for (Element childElement: childElements) {
-                    if ("html".equals(childElement.getNodeName())) {
-                        subWidgets.put("html", new HtmlWidget(modelScreen, childElement));
-                    } else if ("xsl-fo".equals(childElement.getNodeName())) {
-                        subWidgets.put("xsl-fo", new HtmlWidget(modelScreen, childElement));
-                    } else if ("xml".equals(childElement.getNodeName())) {
-                        subWidgets.put("xml", new HtmlWidget(modelScreen, childElement));
-                    } else {
-                        throw new IllegalArgumentException("Tag not supported under the platform-specific tag with name: " + childElement.getNodeName());
-                    }
-                }
-            }
-            this.subWidgets = Collections.unmodifiableMap(subWidgets);
-        }
-
-        @Override
-        public void renderWidgetString(Appendable writer, Map<String, Object> context, ScreenStringRenderer screenStringRenderer) throws GeneralException, IOException {
-            ModelScreenWidget subWidget = null;
-            subWidget = subWidgets.get(screenStringRenderer.getRendererName());
-            if (subWidget == null) {
-                // This is here for backward compatibility
-                Debug.logWarning("In platform-dependent could not find template for " + screenStringRenderer.getRendererName() + ", using the one for html.", module);
-                subWidget = subWidgets.get("html");
-            }
-            if (subWidget != null) {
-                subWidget.renderWidgetString(writer, context, screenStringRenderer);
-            }
-        }
-
-        @Override
-        public void accept(ModelWidgetVisitor visitor) throws Exception {
-            visitor.visit(this);
-        }
-
-        public Map<String, ModelScreenWidget> getSubWidgets() {
-            return subWidgets;
-        }
-    }
-
-    public static final class Content extends ModelScreenWidget {
-        public static final String TAG_NAME = "content";
-
-        private final FlexibleStringExpander contentId;
-        private final FlexibleStringExpander editRequest;
-        private final FlexibleStringExpander editContainerStyle;
-        private final FlexibleStringExpander enableEditName;
-        private final boolean xmlEscape;
-        private final FlexibleStringExpander dataResourceId;
-        private final String width;
-        private final String height;
-        private final String border;
-
-        public Content(ModelScreen modelScreen, Element subContentElement) {
-            super(modelScreen, subContentElement);
-            this.contentId = FlexibleStringExpander.getInstance(subContentElement.getAttribute("content-id"));
-            this.dataResourceId = FlexibleStringExpander.getInstance(subContentElement.getAttribute("dataresource-id"));
-            this.editRequest = FlexibleStringExpander.getInstance(subContentElement.getAttribute("edit-request"));
-            this.editContainerStyle = FlexibleStringExpander.getInstance(subContentElement.getAttribute("edit-container-style"));
-            this.enableEditName = FlexibleStringExpander.getInstance(subContentElement.getAttribute("enable-edit-name"));
-            this.xmlEscape = "true".equals(subContentElement.getAttribute("xml-escape"));
-            String width = subContentElement.getAttribute("width");
-            if (width.isEmpty())
-                width = "60%";
-            this.height = subContentElement.getAttribute("height");
-            if (this.height.isEmpty())
-                width = "400px";
-            this.width = width;
-            this.border = subContentElement.getAttribute("border");
-        }
-
-        @Override
-        public void renderWidgetString(Appendable writer, Map<String, Object> context, ScreenStringRenderer screenStringRenderer) {
-            try {
-                // pushing the contentId on the context as "contentId" is done
-                // because many times there will be embedded "subcontent" elements
-                // that use the syntax: <subcontent content-id="${contentId}"...
-                // and this is a step to make sure that it is there.
-                Delegator delegator = (Delegator) context.get("delegator");
-                GenericValue content = null;
-                String expandedDataResourceId = getDataResourceId(context);
-                String expandedContentId = getContentId(context);
-                if (!(context instanceof MapStack<?>)) {
-                    context = MapStack.create(context);
-                }
-
-                // This is an important step to make sure that the current contentId is in the context
-                // as templates that contain "subcontent" elements will expect to find the master
-                // contentId in the context as "contentId".
-                UtilGenerics.<MapStack<String>>cast(context).push();
-                context.put("contentId", expandedContentId);
-
-                if (expandedDataResourceId.isEmpty()) {
-                    if (!expandedContentId.isEmpty()) {
-                        content = EntityQuery.use(delegator).from("Content").where("contentId", expandedContentId).cache().queryOne();
-                    } else {
-                        String errMsg = "contentId is empty.";
-                        Debug.logError(errMsg, module);
-                        return;
-                    }
-                    if (content != null) {
-                        expandedDataResourceId = content.getString("dataResourceId");
-                    } else {
-                        String errMsg = "Could not find content with contentId [" + expandedContentId + "] ";
-                        Debug.logError(errMsg, module);
-                        throw new RuntimeException(errMsg);
-                    }
-                }
-
-                GenericValue dataResource = null;
-                if (!expandedDataResourceId.isEmpty()) {
-                    dataResource = EntityQuery.use(delegator).from("DataResource").where("dataResourceId", expandedDataResourceId).cache().queryOne();
-                }
-
-                String mimeTypeId = null;
-                if (dataResource != null) {
-                    mimeTypeId = dataResource.getString("mimeTypeId");
-                }
-                if (content != null) {
-                    mimeTypeId = content.getString("mimeTypeId");
-                }
-
-                if (!(mimeTypeId != null
-                        && ((mimeTypeId.indexOf("application") >= 0) || (mimeTypeId.indexOf("image")) >= 0))) {
-                    screenStringRenderer.renderContentBegin(writer, context, this);
-                    screenStringRenderer.renderContentBody(writer, context, this);
-                    screenStringRenderer.renderContentEnd(writer, context, this);
-                }
-                UtilGenerics.<MapStack<String>>cast(context).pop();
-            } catch (IOException e) {
-                String errMsg = "Error rendering content with contentId [" + getContentId(context) + "]: " + e.toString();
-                Debug.logError(e, errMsg, module);
-                throw new RuntimeException(errMsg);
-            } catch (GenericEntityException e) {
-                String errMsg = "Error obtaining content with contentId [" + getContentId(context) + "]: " + e.toString();
-                Debug.logError(e, errMsg, module);
-                throw new RuntimeException(errMsg);
-            }
-
-        }
-
-        public String getContentId(Map<String, Object> context) {
-            return this.contentId.expandString(context);
-        }
-
-        public String getDataResourceId() {
-            return this.dataResourceId.getOriginal();
-        }
-
-        public String getDataResourceId(Map<String, Object> context) {
-            return this.dataResourceId.expandString(context);
-        }
-
-        public String getEditRequest(Map<String, Object> context) {
-            return this.editRequest.expandString(context);
-        }
-
-        public String getEditContainerStyle(Map<String, Object> context) {
-            return this.editContainerStyle.expandString(context);
-        }
-
-        public String getEnableEditName(Map<String, Object> context) {
-            return this.enableEditName.expandString(context);
-        }
-
-        public boolean xmlEscape() {
-            return this.xmlEscape;
-        }
-
-        public String getWidth() {
-            return this.width;
-        }
-
-        public String getHeight() {
-            return this.height;
-        }
-
-        public String getBorder() {
-            return this.border;
-        }
-
-        @Override
-        public void accept(ModelWidgetVisitor visitor) throws Exception {
-            visitor.visit(this);
-        }
-
-        public FlexibleStringExpander getContentId() {
-            return contentId;
-        }
-
-        public FlexibleStringExpander getEditRequest() {
-            return editRequest;
-        }
-
-        public FlexibleStringExpander getEditContainerStyle() {
-            return editContainerStyle;
-        }
-
-        public FlexibleStringExpander getEnableEditName() {
-            return enableEditName;
-        }
-    }
-
-    public static final class SubContent extends ModelScreenWidget {
-        public static final String TAG_NAME = "sub-content";
-        private final FlexibleStringExpander contentId;
-        private final FlexibleStringExpander mapKey;
-        private final FlexibleStringExpander editRequest;
-        private final FlexibleStringExpander editContainerStyle;
-        private final FlexibleStringExpander enableEditName;
-        private final boolean xmlEscape;
-
-        public SubContent(ModelScreen modelScreen, Element subContentElement) {
-            super(modelScreen, subContentElement);
-            this.contentId = FlexibleStringExpander.getInstance(subContentElement.getAttribute("content-id"));
-            String mapKey = subContentElement.getAttribute("map-key");
-            if (mapKey.isEmpty()) {
-                mapKey = subContentElement.getAttribute("assoc-name");
-            }
-            this.mapKey = FlexibleStringExpander.getInstance(mapKey);
-            this.editRequest = FlexibleStringExpander.getInstance(subContentElement.getAttribute("edit-request"));
-            this.editContainerStyle = FlexibleStringExpander.getInstance(subContentElement.getAttribute("edit-container-style"));
-            this.enableEditName = FlexibleStringExpander.getInstance(subContentElement.getAttribute("enable-edit-name"));
-            this.xmlEscape = "true".equals(subContentElement.getAttribute("xml-escape"));
-        }
-
-        @Override
-        public void renderWidgetString(Appendable writer, Map<String, Object> context, ScreenStringRenderer screenStringRenderer) {
-            try {
-                screenStringRenderer.renderSubContentBegin(writer, context, this);
-                screenStringRenderer.renderSubContentBody(writer, context, this);
-                screenStringRenderer.renderSubContentEnd(writer, context, this);
-            } catch (IOException e) {
-                String errMsg = "Error rendering subContent with contentId [" + getContentId(context) + "]: " + e.toString();
-                Debug.logError(e, errMsg, module);
-                throw new RuntimeException(errMsg);
-            }
-        }
-
-        public String getContentId(Map<String, Object> context) {
-            return this.contentId.expandString(context);
-        }
-
-        public String getMapKey(Map<String, Object> context) {
-            return this.mapKey.expandString(context);
-        }
-
-        public String getEditRequest(Map<String, Object> context) {
-            return this.editRequest.expandString(context);
-        }
-
-        public String getEditContainerStyle(Map<String, Object> context) {
-            return this.editContainerStyle.expandString(context);
-        }
-
-        public String getEnableEditName(Map<String, Object> context) {
-            return this.enableEditName.expandString(context);
-        }
-
-        public boolean xmlEscape() {
-            return this.xmlEscape;
-        }
-
-        @Override
-        public void accept(ModelWidgetVisitor visitor) throws Exception {
-            // TODO Auto-generated method stub
-            
-        }
-    }
-
-    public static final class Menu extends ModelScreenWidget {
-        public static final String TAG_NAME = "include-menu";
-        private final FlexibleStringExpander nameExdr;
-        private final FlexibleStringExpander locationExdr;
-
-        public Menu(ModelScreen modelScreen, Element menuElement) {
-            super(modelScreen, menuElement);
-            this.nameExdr = FlexibleStringExpander.getInstance(menuElement.getAttribute("name"));
-            this.locationExdr = FlexibleStringExpander.getInstance(menuElement.getAttribute("location"));
-        }
-
-        @Override
-        public void renderWidgetString(Appendable writer, Map<String, Object> context, ScreenStringRenderer screenStringRenderer) throws IOException {
-            // Output format might not support menus, so make menu rendering optional.
-            MenuStringRenderer menuStringRenderer = (MenuStringRenderer) context.get("menuStringRenderer");
-            if (menuStringRenderer == null) {
-                Debug.logVerbose("MenuStringRenderer instance not found in rendering context, menu not rendered.", module);
-                return;
-            }
-            ModelMenu modelMenu = getModelMenu(context);
-            modelMenu.renderMenuString(writer, context, menuStringRenderer);
-        }
-
-        public ModelMenu getModelMenu(Map<String, Object> context) {
-            String name = this.getName(context);
-            String location = this.getLocation(context);
-            ModelMenu modelMenu = null;
-            try {
-                modelMenu = MenuFactory.getMenuFromLocation(location, name);
-            } catch (Exception e) {
-                String errMsg = "Error rendering included menu named [" + name + "] at location [" + location + "]: ";
-                Debug.logError(e, errMsg, module);
-                throw new RuntimeException(errMsg + e);
-            }
-            return modelMenu;
-        }
-
-        public String getName(Map<String, Object> context) {
-            return this.nameExdr.expandString(context);
-        }
-
-        public String getLocation(Map<String, Object> context) {
-            return this.locationExdr.expandString(context);
-        }
-
-        @Override
-        public void accept(ModelWidgetVisitor visitor) throws Exception {
-            visitor.visit(this);
-        }
-
-        public FlexibleStringExpander getLocationExdr() {
-            return locationExdr;
-        }
-    }
-
-    public static final class ScreenLink extends ModelScreenWidget {
-        public static final String TAG_NAME = "link";
-        private final Link link;
-        private final ScreenImage image;
-
-        public ScreenLink(ModelScreen modelScreen, Element linkElement) {
-            super(modelScreen, linkElement);
-            this.link = new Link(linkElement);
-            Element imageElement = UtilXml.firstChildElement(linkElement, "image");
-            if (imageElement != null) {
-                this.image = new ScreenImage(modelScreen, imageElement);
-            } else {
-                this.image = null;
-            }
-        }
-
-        public String getName() {
-            return link.getName();
-        }
-
-        public String getText(Map<String, Object> context) {
-            return link.getText(context);
-        }
-
-        public String getId(Map<String, Object> context) {
-            return link.getId(context);
-        }
-
-        public String getStyle(Map<String, Object> context) {
-            return link.getStyle(context);
-        }
-
-        public String getTarget(Map<String, Object> context) {
-            return link.getTarget(context);
-        }
-
-        public String getName(Map<String, Object> context) {
-            return link.getName(context);
-        }
-
-        public String getTargetWindow(Map<String, Object> context) {
-            return link.getTargetWindow(context);
-        }
-
-        public String getUrlMode() {
-            return link.getUrlMode();
-        }
-
-        public String getPrefix(Map<String, Object> context) {
-            return link.getPrefix(context);
-        }
-
-        public boolean getFullPath() {
-            return link.getFullPath();
-        }
-
-        public boolean getSecure() {
-            return link.getSecure();
-        }
-
-        public boolean getEncode() {
-            return link.getEncode();
-        }
-
-        public ScreenImage getImage() {
-            return image;
-        }
-
-        public String getLinkType() {
-            return link.getLinkType();
-        }
-
-        public String getWidth() {
-            return link.getWidth();
-        }
-
-        public String getHeight() {
-            return link.getHeight();
-        }
-
-        public Map<String, String> getParameterMap(Map<String, Object> context) {
-            return link.getParameterMap(context);
-        }
-
-        public FlexibleStringExpander getTextExdr() {
-            return link.getTextExdr();
-        }
-
-        public FlexibleStringExpander getIdExdr() {
-            return link.getIdExdr();
-        }
-
-        public FlexibleStringExpander getStyleExdr() {
-            return link.getStyleExdr();
-        }
-
-        public FlexibleStringExpander getTargetExdr() {
-            return link.getTargetExdr();
-        }
-
-        public FlexibleStringExpander getTargetWindowExdr() {
-            return link.getTargetWindowExdr();
-        }
-
-        public FlexibleStringExpander getPrefixExdr() {
-            return link.getPrefixExdr();
-        }
-
-        public FlexibleStringExpander getNameExdr() {
-            return link.getNameExdr();
-        }
-
-        public List<Parameter> getParameterList() {
-            return link.getParameterList();
-        }
-
-        public AutoServiceParameters getAutoServiceParameters() {
-            return link.getAutoServiceParameters();
-        }
-
-        public AutoEntityParameters getAutoEntityParameters() {
-            return link.getAutoEntityParameters();
-        }
-
-        @Override
-        public void renderWidgetString(Appendable writer, Map<String, Object> context, ScreenStringRenderer screenStringRenderer) {
-            try {
-                screenStringRenderer.renderLink(writer, context, this);
-            } catch (IOException e) {
-                String errMsg = "Error rendering link with id [" + link.getId(context) + "]: " + e.toString();
-                Debug.logError(e, errMsg, module);
-                throw new RuntimeException(errMsg);
-            }
-        }
-
-        @Override
-        public void accept(ModelWidgetVisitor visitor) throws Exception {
-            visitor.visit(this);
-        }
-
-        public Link getLink() {
-            return link;
-        }
-    }
-
-    public static final class ScreenImage extends ModelScreenWidget {
-        public static final String TAG_NAME = "image";
-        private final Image image;
-
-        public String getName() {
-            return image.getName();
-        }
-
-        public String getSrc(Map<String, Object> context) {
-            return image.getSrc(context);
-        }
-
-        public String getId(Map<String, Object> context) {
-            return image.getId(context);
-        }
-
-        public String getStyle(Map<String, Object> context) {
-            return image.getStyle(context);
-        }
-
-        public String getWidth(Map<String, Object> context) {
-            return image.getWidth(context);
-        }
-
-        public String getHeight(Map<String, Object> context) {
-            return image.getHeight(context);
-        }
-
-        public String getBorder(Map<String, Object> context) {
-            return image.getBorder(context);
-        }
-
-        public String getAlt(Map<String, Object> context) {
-            return image.getAlt(context);
-        }
-
-        public String getUrlMode() {
-            return image.getUrlMode();
-        }
-
-        public FlexibleStringExpander getSrcExdr() {
-            return image.getSrcExdr();
-        }
-
-        public FlexibleStringExpander getIdExdr() {
-            return image.getIdExdr();
-        }
-
-        public FlexibleStringExpander getStyleExdr() {
-            return image.getStyleExdr();
-        }
-
-        public FlexibleStringExpander getWidthExdr() {
-            return image.getWidthExdr();
-        }
-
-        public FlexibleStringExpander getHeightExdr() {
-            return image.getHeightExdr();
-        }
-
-        public FlexibleStringExpander getBorderExdr() {
-            return image.getBorderExdr();
-        }
-
-        public FlexibleStringExpander getAlt() {
-            return image.getAlt();
-        }
-
-        public ScreenImage(ModelScreen modelScreen, Element imageElement) {
-            super(modelScreen, imageElement);
-            this.image = new Image(imageElement);
-        }
-
-        @Override
-        public void renderWidgetString(Appendable writer, Map<String, Object> context, ScreenStringRenderer screenStringRenderer) {
-            try {
-                screenStringRenderer.renderImage(writer, context, this);
-            } catch (IOException e) {
-                String errMsg = "Error rendering image with id [" + image.getId(context) + "]: " + e.toString();
-                Debug.logError(e, errMsg, module);
-                throw new RuntimeException(errMsg);
-            }
-        }
-
-        @Override
-        public void accept(ModelWidgetVisitor visitor) throws Exception {
-            visitor.visit(this);
-        }
-
-        public Image getImage() {
-            return image;
-        }
-    }
-
-    public static final class PortalPage extends ModelScreenWidget {
-        public static final String TAG_NAME = "include-portal-page";
-        private final FlexibleStringExpander idExdr;
-        private final FlexibleStringExpander confModeExdr;
-        private final Boolean usePrivate;
-
-        public PortalPage(ModelScreen modelScreen, Element portalPageElement) {
-            super(modelScreen, portalPageElement);
-            this.idExdr = FlexibleStringExpander.getInstance(portalPageElement.getAttribute("id"));
-            this.confModeExdr = FlexibleStringExpander.getInstance(portalPageElement.getAttribute("conf-mode"));
-            this.usePrivate = !("false".equals(portalPageElement.getAttribute("use-private")));
-        }
-
-        private GenericValue getPortalPageValue(Map<String, Object> context) {
-            Delegator delegator = (Delegator) context.get("delegator");
-            String expandedPortalPageId = getId(context);
-            GenericValue portalPage = null;
-            if (!expandedPortalPageId.isEmpty()) {
-                if (usePrivate) {
-                    portalPage = PortalPageWorker.getPortalPage(expandedPortalPageId, context);
-                } else {
-                    try {
-                        portalPage = EntityQuery.use(delegator)
-                                                .from("PortalPage")
-                                                .where("portalPageId", expandedPortalPageId)
-                                                .cache().queryOne();
-                    } catch (GenericEntityException e) {
-                        throw new RuntimeException(e);
-                    }
-                }
-            }
-            if (portalPage == null) {
-                String errMsg = "Could not find PortalPage with portalPageId [" + expandedPortalPageId + "] ";
-                Debug.logError(errMsg, module);
-                throw new RuntimeException(errMsg);
-            }
-            return portalPage;
-        }
-
-        @Override
-        public void renderWidgetString(Appendable writer, Map<String, Object> context, ScreenStringRenderer screenStringRenderer) throws GeneralException, IOException {
-            try {
-                Delegator delegator = (Delegator) context.get("delegator");
-                List<GenericValue> portalPageColumns = null;
-                List<GenericValue> portalPagePortlets = null;
-                List<GenericValue> portletAttributes = null;
-                GenericValue portalPage = getPortalPageValue(context);
-                String actualPortalPageId = portalPage.getString("portalPageId");
-                portalPageColumns = EntityQuery.use(delegator)
-                                               .from("PortalPageColumn")
-                                               .where("portalPageId", actualPortalPageId)
-                                               .orderBy("columnSeqId")
-                                               .cache(true)
-                                               .queryList();
-                
-                // Renders the portalPage header
-                screenStringRenderer.renderPortalPageBegin(writer, context, this);
-                
-                // First column has no previous column
-                String prevColumnSeqId = "";
-                
-                // Iterates through the PortalPage columns
-                ListIterator <GenericValue>columnsIterator = portalPageColumns.listIterator();
-                while(columnsIterator.hasNext()) {
-                    GenericValue columnValue = columnsIterator.next();
-                    String columnSeqId = columnValue.getString("columnSeqId");
-                    
-                    // Renders the portalPageColumn header
-                    screenStringRenderer.renderPortalPageColumnBegin(writer, context, this, columnValue);
-
-                    // Get the Portlets located in the current column
-                    portalPagePortlets = EntityQuery.use(delegator)
-                                                    .from("PortalPagePortletView")
-                                                    .where("portalPageId", portalPage.getString("portalPageId"), "columnSeqId", columnSeqId)
-                                                    .orderBy("sequenceNum")
-                                                    .queryList();
-                    // First Portlet in a Column has no previous Portlet
-                    String prevPortletId = "";
-                    String prevPortletSeqId = "";
-
-                    // If this is not the last column, get the next columnSeqId
-                    String nextColumnSeqId = "";
-                    if (columnsIterator.hasNext()) {
-                        nextColumnSeqId = portalPageColumns.get(columnsIterator.nextIndex()).getString("columnSeqId");
-                    }
-                    
-                    // Iterates through the Portlets in the Column
-                    ListIterator <GenericValue>portletsIterator = portalPagePortlets.listIterator();
-                    while(portletsIterator.hasNext()) {
-                        GenericValue portletValue = portletsIterator.next();
-
-                        // If not the last portlet in the column, get the next nextPortletId and nextPortletSeqId
-                        String nextPortletId = "";
-                        String nextPortletSeqId = "";
-                        if (portletsIterator.hasNext()) {
-                            nextPortletId = portalPagePortlets.get(portletsIterator.nextIndex()).getString("portalPortletId");
-                            nextPortletSeqId = portalPagePortlets.get(portletsIterator.nextIndex()).getString("portletSeqId");
-                        }
-
-                        // Set info to allow portlet movement in the page
-                        context.put("prevPortletId", prevPortletId);
-                        context.put("prevPortletSeqId", prevPortletSeqId);
-                        context.put("nextPortletId", nextPortletId);
-                        context.put("nextPortletSeqId", nextPortletSeqId);
-                        context.put("prevColumnSeqId", prevColumnSeqId);
-                        context.put("nextColumnSeqId", nextColumnSeqId);
-                       
-                        // Get portlet's attributes
-                        portletAttributes = EntityQuery.use(delegator)
-                                                       .from("PortletAttribute")
-                                                       .where("portalPageId", portletValue.get("portalPageId"), "portalPortletId", portletValue.get("portalPortletId"), "portletSeqId", portletValue.get("portletSeqId"))
-                                                       .queryList();
-                        
-                        ListIterator <GenericValue>attributesIterator = portletAttributes.listIterator();
-                        while (attributesIterator.hasNext()) {
-                            GenericValue attribute = attributesIterator.next();
-                            context.put(attribute.getString("attrName"), attribute.getString("attrValue"));
-                        }
-                        
-                        // Renders the portalPagePortlet
-                        screenStringRenderer.renderPortalPagePortletBegin(writer, context, this, portletValue);
-                        screenStringRenderer.renderPortalPagePortletBody(writer, context, this, portletValue);
-                        screenStringRenderer.renderPortalPagePortletEnd(writer, context, this, portletValue);
-
-                        // Remove the portlet's attributes so that these are not available for other portlets
-                        while (attributesIterator.hasPrevious()) {
-                            GenericValue attribute = attributesIterator.previous();
-                            context.remove(attribute.getString("attrName"));
-                        }
-                        
-                        // Uses the actual portlet as prevPortlet for next iteration
-                        prevPortletId = (String) portletValue.get("portalPortletId");
-                        prevPortletSeqId = (String) portletValue.get("portletSeqId");
-                    }
-                    // Renders the portalPageColumn footer
-                    screenStringRenderer.renderPortalPageColumnEnd(writer, context, this, columnValue);
-
-                    // Uses the actual columnSeqId as prevColumnSeqId for next iteration
-                    prevColumnSeqId = columnSeqId;
-                }
-                // Renders the portalPage footer
-                screenStringRenderer.renderPortalPageEnd(writer, context, this);
-            } catch (IOException e) {
-                String errMsg = "Error rendering PortalPage with portalPageId [" + getId(context) + "]: " + e.toString();
-                Debug.logError(e, errMsg, module);
-                throw new RuntimeException(errMsg);
-            } catch (GenericEntityException e) {
-                String errMsg = "Error obtaining PortalPage with portalPageId [" + getId(context) + "]: " + e.toString();
-                Debug.logError(e, errMsg, module);
-                throw new RuntimeException(errMsg);
-            }
-        }
-
-        public String getId(Map<String, Object> context) {
-            return this.idExdr.expandString(context);
-        }
-
-        public String getOriginalPortalPageId(Map<String, Object> context) {
-            GenericValue portalPage = getPortalPageValue(context);
-            return portalPage.getString("originalPortalPageId");
-        }
-        
-        public String getActualPortalPageId(Map<String, Object> context) {
-            GenericValue portalPage = getPortalPageValue(context);
-            return portalPage.getString("portalPageId");
-        }
-
-        public String getConfMode(Map<String, Object> context) {
-            return this.confModeExdr.expandString(context);
-        }
-
-        public String getUsePrivate() {
-            return Boolean.toString(this.usePrivate);
-        }
-
-        @Override
-        public void accept(ModelWidgetVisitor visitor) throws Exception {
-            visitor.visit(this);
-        }
-
-        public FlexibleStringExpander getIdExdr() {
-            return idExdr;
-        }
-
-        public FlexibleStringExpander getConfModeExdr() {
-            return confModeExdr;
-        }
-    }
-
-}
+/*******************************************************************************

+ * Licensed to the Apache Software Foundation (ASF) under one

+ * or more contributor license agreements.  See the NOTICE file

+ * distributed with this work for additional information

+ * regarding copyright ownership.  The ASF licenses this file

+ * to you under the Apache License, Version 2.0 (the

+ * "License"); you may not use this file except in compliance

+ * with the License.  You may obtain a copy of the License at

+ *

+ * http://www.apache.org/licenses/LICENSE-2.0

+ *

+ * Unless required by applicable law or agreed to in writing,

+ * software distributed under the License is distributed on an

+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY

+ * KIND, either express or implied.  See the License for the

+ * specific language governing permissions and limitations

+ * under the License.

+ *******************************************************************************/

+package org.ofbiz.widget.model;

+

+import java.io.IOException;

+import java.util.ArrayList;

+import java.util.Collection;

+import java.util.Collections;

+import java.util.HashMap;

+import java.util.LinkedList;

+import java.util.List;

+import java.util.ListIterator;

+import java.util.Map;

+import java.util.Set;

+

+import javax.xml.parsers.ParserConfigurationException;

+

+import org.ofbiz.base.util.Debug;

+import org.ofbiz.base.util.GeneralException;

+import org.ofbiz.base.util.UtilCodec;

+import org.ofbiz.base.util.UtilGenerics;

+import org.ofbiz.base.util.UtilXml;

+import org.ofbiz.base.util.collections.MapStack;

+import org.ofbiz.base.util.string.FlexibleStringExpander;

+import org.ofbiz.entity.Delegator;

+import org.ofbiz.entity.GenericEntityException;

+import org.ofbiz.entity.GenericValue;

+import org.ofbiz.entity.util.EntityQuery;

+import org.ofbiz.widget.WidgetFactory;

+import org.ofbiz.widget.model.CommonWidgetModels.AutoEntityParameters;

+import org.ofbiz.widget.model.CommonWidgetModels.AutoServiceParameters;

+import org.ofbiz.widget.model.CommonWidgetModels.Image;

+import org.ofbiz.widget.model.CommonWidgetModels.Link;

+import org.ofbiz.widget.model.CommonWidgetModels.Parameter;

+import org.ofbiz.widget.portal.PortalPageWorker;

+import org.ofbiz.widget.renderer.FormRenderer;

+import org.ofbiz.widget.renderer.FormStringRenderer;

+import org.ofbiz.widget.renderer.MenuStringRenderer;

+import org.ofbiz.widget.renderer.ScreenRenderer;

+import org.ofbiz.widget.renderer.ScreenStringRenderer;

+import org.ofbiz.widget.renderer.TreeStringRenderer;

+import org.w3c.dom.Element;

+import org.xml.sax.SAXException;

+

+

+/**

+ * Widget Library - Screen model class

+ */

+@SuppressWarnings("serial")

+public abstract class ModelScreenWidget extends ModelWidget {

+    public static final String module = ModelScreenWidget.class.getName();

+

+    private final ModelScreen modelScreen;

+

+    public ModelScreenWidget(ModelScreen modelScreen, Element widgetElement) {

+        super(widgetElement);

+        this.modelScreen = modelScreen;

+        if (Debug.verboseOn()) Debug.logVerbose("Reading Screen sub-widget with name: " + widgetElement.getNodeName(), module);

+    }

+

+    public abstract void renderWidgetString(Appendable writer, Map<String, Object> context, ScreenStringRenderer screenStringRenderer) throws GeneralException, IOException;

+

+    protected static List<ModelScreenWidget> readSubWidgets(ModelScreen modelScreen, List<? extends Element> subElementList) {

+        if (subElementList.isEmpty()) {

+            return Collections.emptyList();

+        }

+        List<ModelScreenWidget> subWidgets = new ArrayList<ModelScreenWidget>(subElementList.size());

+        for (Element subElement: subElementList) {

+            subWidgets.add(WidgetFactory.getModelScreenWidget(modelScreen, subElement));

+        }

+        return Collections.unmodifiableList(subWidgets);

+    }

+

+    protected static void renderSubWidgetsString(List<ModelScreenWidget> subWidgets, Appendable writer, Map<String, Object> context, ScreenStringRenderer screenStringRenderer) throws GeneralException, IOException {

+        if (subWidgets == null) {

+            return;

+        }

+        for (ModelScreenWidget subWidget: subWidgets) {

+            if (Debug.verboseOn()) Debug.logVerbose("Rendering screen " + subWidget.getModelScreen().getName() + "; widget class is " + subWidget.getClass().getName(), module);

+

+            // render the sub-widget itself

+            subWidget.renderWidgetString(writer, context, screenStringRenderer);

+        }

+    }

+

+    public ModelScreen getModelScreen() {

+        return this.modelScreen;

+    }

+

+    public static final class SectionsRenderer implements Map<String, ModelScreenWidget> {

+        private final Map<String, ModelScreenWidget> sectionMap;

+        private final ScreenStringRenderer screenStringRenderer;

+        private final Map<String, Object> context;

+        private final Appendable writer;

+

+        public SectionsRenderer(Map<String, ModelScreenWidget> sectionMap, Map<String, Object> context, Appendable writer,

+                ScreenStringRenderer screenStringRenderer) {

+            Map<String, ModelScreenWidget> localMap = new HashMap<String, ModelScreenWidget>();

+            localMap.putAll(sectionMap);

+            this.sectionMap = Collections.unmodifiableMap(localMap);

+            this.context = context;

+            this.writer = writer;

+            this.screenStringRenderer = screenStringRenderer;

+        }

+

+        /** This is a lot like the ScreenRenderer class and returns an empty String so it can be used more easily with FreeMarker */

+        public String render(String sectionName) throws GeneralException, IOException {

+            ModelScreenWidget section = sectionMap.get(sectionName);

+            // if no section by that name, write nothing

+            if (section != null) {

+                section.renderWidgetString(this.writer, this.context, this.screenStringRenderer);

+            }

+            return "";

+        }

+

+        @Override

+        public int size() {

+            return sectionMap.size();

+        }

+

+        @Override

+        public boolean isEmpty() {

+            return sectionMap.isEmpty();

+        }

+

+        @Override

+        public boolean containsKey(Object key) {

+            return sectionMap.containsKey(key);

+        }

+

+        @Override

+        public boolean containsValue(Object value) {

+            return sectionMap.containsValue(value);

+        }

+

+        @Override

+        public ModelScreenWidget get(Object key) {

+            return sectionMap.get(key);

+        }

+

+        @Override

+        public ModelScreenWidget put(String key, ModelScreenWidget value) {

+            return sectionMap.put(key, value);

+        }

+

+        @Override

+        public ModelScreenWidget remove(Object key) {

+            return sectionMap.remove(key);

+        }

+

+        @Override

+        public void clear() {

+            sectionMap.clear();

+        }

+

+        @Override

+        public Set<String> keySet() {

+            return sectionMap.keySet();

+        }

+

+        @Override

+        public Collection<ModelScreenWidget> values() {

+            return sectionMap.values();

+        }

+

+        @Override

+        public Set<java.util.Map.Entry<String, ModelScreenWidget>> entrySet() {

+            return sectionMap.entrySet();

+        }

+

+        @Override

+        public boolean equals(Object o) {

+            return sectionMap.equals(o);

+        }

+

+        @Override

+        public int hashCode() {

+            return sectionMap.hashCode();

+        }

+

+        @Override

+        public void putAll(Map<? extends String, ? extends ModelScreenWidget> m) {

+            sectionMap.putAll(m);

+        }

+    }

+

+    public static final class Section extends ModelScreenWidget {

+        public static final String TAG_NAME = "section";

+        private final ModelCondition condition;

+        private final List<ModelAction> actions;

+        private final List<ModelScreenWidget> subWidgets;

+        private final List<ModelScreenWidget> failWidgets;

+        private final boolean isMainSection;

+

+        public Section(ModelScreen modelScreen, Element sectionElement) {

+            this(modelScreen, sectionElement, false);

+        }

+

+        public Section(ModelScreen modelScreen, Element sectionElement, boolean isMainSection) {

+            super(modelScreen, sectionElement);

+

+            // read condition under the "condition" element

+            Element conditionElement = UtilXml.firstChildElement(sectionElement, "condition");

+            if (conditionElement != null) {

+                conditionElement = UtilXml.firstChildElement(conditionElement);

+                this.condition = ModelScreenCondition.SCREEN_CONDITION_FACTORY.newInstance(modelScreen, conditionElement);

+            } else {

+                this.condition = null;

+            }

+

+            // read all actions under the "actions" element

+            Element actionsElement = UtilXml.firstChildElement(sectionElement, "actions");

+            if (actionsElement != null) {

+                this.actions = AbstractModelAction.readSubActions(modelScreen, actionsElement);

+            } else {

+                this.actions = Collections.emptyList();

+            }

+

+            // read sub-widgets

+            Element widgetsElement = UtilXml.firstChildElement(sectionElement, "widgets");

+            if (widgetsElement != null) {

+                List<? extends Element> subElementList = UtilXml.childElementList(widgetsElement);

+                this.subWidgets = ModelScreenWidget.readSubWidgets(getModelScreen(), subElementList);

+            } else {

+                this.subWidgets = Collections.emptyList();

+            }

+

+            // read fail-widgets

+            Element failWidgetsElement = UtilXml.firstChildElement(sectionElement, "fail-widgets");

+            if (failWidgetsElement != null) {

+                List<? extends Element> failElementList = UtilXml.childElementList(failWidgetsElement);

+                this.failWidgets = ModelScreenWidget.readSubWidgets(getModelScreen(), failElementList);

+            } else {

+                this.failWidgets = Collections.emptyList();

+            }

+            this.isMainSection = isMainSection;

+        }

+

+        @Override

+        public void accept(ModelWidgetVisitor visitor) throws Exception {

+            visitor.visit(this);

+        }

+

+        @Override

+        public void renderWidgetString(Appendable writer, Map<String, Object> context, ScreenStringRenderer screenStringRenderer) throws GeneralException, IOException {

+            // check the condition, if there is one

+            boolean condTrue = true;

+            if (this.condition != null) {

+                if (!this.condition.eval(context)) {

+                    condTrue = false;

+                }

+            }

+

+            // if condition does not exist or evals to true run actions and render widgets, otherwise render fail-widgets

+            if (condTrue) {

+                // run the actions only if true

+                AbstractModelAction.runSubActions(this.actions, context);

+

+                try {

+                    // section by definition do not themselves do anything, so this method will generally do nothing, but we'll call it anyway

+                    screenStringRenderer.renderSectionBegin(writer, context, this);

+

+                    // render sub-widgets

+                    renderSubWidgetsString(this.subWidgets, writer, context, screenStringRenderer);

+

+                    screenStringRenderer.renderSectionEnd(writer, context, this);

+                } catch (IOException e) {

+                    String errMsg = "Error rendering widgets section [" + getName() + "] in screen named [" + getModelScreen().getName() + "]: " + e.toString();

+                    Debug.logError(e, errMsg, module);

+                    throw new RuntimeException(errMsg);

+                }

+            } else {

+                try {

+                    // section by definition do not themselves do anything, so this method will generally do nothing, but we'll call it anyway

+                    screenStringRenderer.renderSectionBegin(writer, context, this);

+

+                    // render sub-widgets

+                    renderSubWidgetsString(this.failWidgets, writer, context, screenStringRenderer);

+

+                    screenStringRenderer.renderSectionEnd(writer, context, this);

+                } catch (IOException e) {

+                    String errMsg = "Error rendering fail-widgets section [" + this.getName() + "] in screen named [" + getModelScreen().getName() + "]: " + e.toString();

+                    Debug.logError(e, errMsg, module);

+                    throw new RuntimeException(errMsg);

+                }

+            }

+

+        }

+

+        @Override

+        public String getBoundaryCommentName() {

+            if (isMainSection) {

+                return getModelScreen().getSourceLocation() + "#" + getModelScreen().getName();

+            } else {

+                return getName();

+            }

+        }

+

+        public List<ModelAction> getActions() {

+            return actions;

+        }

+

+        public List<ModelScreenWidget> getSubWidgets() {

+            return subWidgets;

+        }

+

+        public List<ModelScreenWidget> getFailWidgets() {

+            return failWidgets;

+        }

+

+        public boolean isMainSection() {

+            return isMainSection;

+        }

+

+        public ModelCondition getCondition() {

+            return condition;

+        }

+    }

+

+    public static final class ColumnContainer extends ModelScreenWidget {

+        public static final String TAG_NAME = "column-container";

+        private final FlexibleStringExpander idExdr;

+        private final FlexibleStringExpander styleExdr;

+        private final List<Column> columns;

+

+        public ColumnContainer(ModelScreen modelScreen, Element containerElement) {

+            super(modelScreen, containerElement);

+            this.idExdr = FlexibleStringExpander.getInstance(containerElement.getAttribute("id"));

+            this.styleExdr = FlexibleStringExpander.getInstance(containerElement.getAttribute("style"));

+            List<? extends Element> subElementList = UtilXml.childElementList(containerElement, "column");

+            List<Column> columns = new ArrayList<Column>(subElementList.size());

+            for (Element element : subElementList) {

+                columns.add(new Column(modelScreen, element));

+            }

+            this.columns = Collections.unmodifiableList(columns);

+        }

+

+        @Override

+        public void accept(ModelWidgetVisitor visitor) throws Exception {

+            visitor.visit(this);

+        }

+

+        @Override

+        public void renderWidgetString(Appendable writer, Map<String, Object> context, ScreenStringRenderer screenStringRenderer) throws GeneralException, IOException {

+            try {

+                screenStringRenderer.renderColumnContainer(writer, context, this);

+            } catch (IOException e) {

+                String errMsg = "Error rendering container in screen named [" + getModelScreen().getName() + "]: " + e.toString();

+                Debug.logError(e, errMsg, module);

+                throw new RuntimeException(errMsg);

+            }

+        }

+

+        public List<Column> getColumns() {

+            return this.columns;

+        }

+

+        public String getId(Map<String, Object> context) {

+            return this.idExdr.expandString(context);

+        }

+

+        public String getStyle(Map<String, Object> context) {

+            return this.styleExdr.expandString(context);

+        }

+

+        public FlexibleStringExpander getIdExdr() {

+            return idExdr;

+        }

+

+        public FlexibleStringExpander getStyleExdr() {

+            return styleExdr;

+        }

+    }

+

+    public static final class Column extends ModelWidget {

+        private final FlexibleStringExpander idExdr;

+        private final FlexibleStringExpander styleExdr;

+        private final List<ModelScreenWidget> subWidgets;

+

+        public Column(ModelScreen modelScreen, Element columnElement) {

+            super(columnElement);

+            this.idExdr = FlexibleStringExpander.getInstance(columnElement.getAttribute("id"));

+            this.styleExdr = FlexibleStringExpander.getInstance(columnElement.getAttribute("style"));

+            List<? extends Element> subElementList = UtilXml.childElementList(columnElement);

+            this.subWidgets = Collections.unmodifiableList(readSubWidgets(modelScreen, subElementList));

+        }

+

+        public List<ModelScreenWidget> getSubWidgets() {

+            return this.subWidgets;

+        }

+

+        public String getId(Map<String, Object> context) {

+            return this.idExdr.expandString(context);

+        }

+

+        public String getStyle(Map<String, Object> context) {

+            return this.styleExdr.expandString(context);

+        }

+

+        @Override

+        public void accept(ModelWidgetVisitor visitor) throws Exception {

+            visitor.visit(this);

+        }

+

+        public FlexibleStringExpander getIdExdr() {

+            return idExdr;

+        }

+

+        public FlexibleStringExpander getStyleExdr() {

+            return styleExdr;

+        }

+    }

+

+    public static final class Container extends ModelScreenWidget {

+        public static final String TAG_NAME = "container";

+        private final FlexibleStringExpander idExdr;

+        private final FlexibleStringExpander styleExdr;

+        private final FlexibleStringExpander autoUpdateTargetExdr;

+        private final FlexibleStringExpander autoUpdateInterval;

+        private final List<ModelScreenWidget> subWidgets;

+

+        public Container(ModelScreen modelScreen, Element containerElement) {

+            super(modelScreen, containerElement);

+            this.idExdr = FlexibleStringExpander.getInstance(containerElement.getAttribute("id"));

+            this.styleExdr = FlexibleStringExpander.getInstance(containerElement.getAttribute("style"));

+            this.autoUpdateTargetExdr = FlexibleStringExpander.getInstance(containerElement.getAttribute("auto-update-target"));

+            String autoUpdateInterval = containerElement.getAttribute("auto-update-interval");

+            if (autoUpdateInterval.isEmpty()) {

+                autoUpdateInterval = "2";

+            }

+            this.autoUpdateInterval = FlexibleStringExpander.getInstance(autoUpdateInterval);

+            // read sub-widgets

+            List<? extends Element> subElementList = UtilXml.childElementList(containerElement);

+            this.subWidgets = ModelScreenWidget.readSubWidgets(getModelScreen(), subElementList);

+        }

+

+        @Override

+        public void renderWidgetString(Appendable writer, Map<String, Object> context, ScreenStringRenderer screenStringRenderer) throws GeneralException, IOException {

+            try {

+                screenStringRenderer.renderContainerBegin(writer, context, this);

+

+                // render sub-widgets

+                renderSubWidgetsString(this.subWidgets, writer, context, screenStringRenderer);

+

+                screenStringRenderer.renderContainerEnd(writer, context, this);

+            } catch (IOException e) {

+                String errMsg = "Error rendering container in screen named [" + getModelScreen().getName() + "]: " + e.toString();

+                Debug.logError(e, errMsg, module);

+                throw new RuntimeException(errMsg);

+            }

+        }

+

+        public String getId(Map<String, Object> context) {

+            return this.idExdr.expandString(context);

+        }

+

+        public String getStyle(Map<String, Object> context) {

+            return this.styleExdr.expandString(context);

+        }

+

+        public String getAutoUpdateTargetExdr(Map<String, Object> context) {

+            return this.autoUpdateTargetExdr.expandString(context);

+        }

+

+        public String getAutoUpdateInterval(Map<String, Object> context) {

+            return this.autoUpdateInterval.expandString(context);

+        }

+

+        public List<ModelScreenWidget> getSubWidgets() {

+            return subWidgets;

+        }

+

+        @Override

+        public void accept(ModelWidgetVisitor visitor) throws Exception {

+            visitor.visit(this);

+        }

+

+        public FlexibleStringExpander getIdExdr() {

+            return idExdr;

+        }

+

+        public FlexibleStringExpander getStyleExdr() {

+            return styleExdr;

+        }

+

+        public FlexibleStringExpander getAutoUpdateTargetExdr() {

+            return autoUpdateTargetExdr;

+        }

+

+        public FlexibleStringExpander getAutoUpdateInterval() {

+            return autoUpdateInterval;

+        }

+    }

+

+    public static final class Screenlet extends ModelScreenWidget {

+        public static final String TAG_NAME = "screenlet";

+        private final FlexibleStringExpander idExdr;

+        private final FlexibleStringExpander titleExdr;

+        private final Menu navigationMenu;

+        private final Menu tabMenu;

+        private final Form navigationForm;

+        private final boolean collapsible;

+        private final FlexibleStringExpander initiallyCollapsed;

+        private final boolean saveCollapsed;

+        private final boolean padded;

+        private final List<ModelScreenWidget> subWidgets;

+

+        public Screenlet(ModelScreen modelScreen, Element screenletElement) {

+            super(modelScreen, screenletElement);

+            this.idExdr = FlexibleStringExpander.getInstance(screenletElement.getAttribute("id"));

+            boolean collapsible = "true".equals(screenletElement.getAttribute("collapsible"));

+            this.initiallyCollapsed = FlexibleStringExpander.getInstance(screenletElement.getAttribute("initially-collapsed"));

+            if ("true".equals(this.initiallyCollapsed.getOriginal())) {

+                collapsible = true;

+            }

+            this.collapsible = collapsible;

+            // By default, for a collapsible screenlet, the collapsed/expanded status must be saved

+            this.saveCollapsed = !("false".equals(screenletElement.getAttribute("save-collapsed")));

+

+            boolean padded = !"false".equals(screenletElement.getAttribute("padded"));

+            if (this.collapsible && getName().isEmpty() && idExdr.isEmpty()) {

+                throw new IllegalArgumentException("Collapsible screenlets must have a name or id [" + getModelScreen().getName() + "]");

+            }

+            this.titleExdr = FlexibleStringExpander.getInstance(screenletElement.getAttribute("title"));

+            List<? extends Element> subElementList = UtilXml.childElementList(screenletElement);

+            // Make a copy of the unmodifiable List so we can modify it.

+            ArrayList<ModelScreenWidget> subWidgets = new ArrayList<ModelScreenWidget>(ModelScreenWidget.readSubWidgets(getModelScreen(), subElementList));

+            Menu navigationMenu = null;

+            String navMenuName = screenletElement.getAttribute("navigation-menu-name");

+            if (!navMenuName.isEmpty()) {

+                for (ModelWidget subWidget : subWidgets) {

+                    if (navMenuName.equals(subWidget.getName()) && subWidget instanceof Menu) {

+                        navigationMenu = (Menu) subWidget;

+                        subWidgets.remove(subWidget);

+                        break;

+                    }

+                }

+            }

+            this.navigationMenu = navigationMenu;

+            Menu tabMenu = null;

+            String tabMenuName = screenletElement.getAttribute("tab-menu-name");

+            if (!tabMenuName.isEmpty()) {

+                for (ModelWidget subWidget : subWidgets) {

+                    if (tabMenuName.equals(subWidget.getName()) && subWidget instanceof Menu) {

+                        tabMenu = (Menu) subWidget;

+                        subWidgets.remove(subWidget);

+                        break;

+                    }

+                }

+            }

+            this.tabMenu = tabMenu;

+            Form navigationForm = null;

+            String formName = screenletElement.getAttribute("navigation-form-name");

+            if (!formName.isEmpty() && this.navigationMenu == null) {

+                for (ModelWidget subWidget : subWidgets) {

+                    if (formName.equals(subWidget.getName()) && subWidget instanceof Form) {

+                        navigationForm = (Form) subWidget;

+                        padded = false;

+                        break;

+                    }

+                }

+            }

+            this.subWidgets = Collections.unmodifiableList(subWidgets);

+            this.navigationForm = navigationForm;

+            this.padded = padded;

+        }

+

+        @Override

+        public void renderWidgetString(Appendable writer, Map<String, Object> context, ScreenStringRenderer screenStringRenderer) throws GeneralException, IOException {

+            boolean collapsed = getInitiallyCollapsed(context);

+            if (this.collapsible) {

+                String preferenceKey = getPreferenceKey(context) + "_collapsed";

+                Map<String, Object> requestParameters = UtilGenerics.checkMap(context.get("requestParameters"));

+                if (requestParameters != null) {

+                    String collapsedParam = (String) requestParameters.get(preferenceKey);

+                    collapsed = "true".equals(collapsedParam);

+                }

+            }

+            try {

+                screenStringRenderer.renderScreenletBegin(writer, context, collapsed, this);

+                for (ModelScreenWidget subWidget : this.subWidgets) {

+                    screenStringRenderer.renderScreenletSubWidget(writer, context, subWidget, this);

+                }

+                screenStringRenderer.renderScreenletEnd(writer, context, this);

+            } catch (IOException e) {

+                String errMsg = "Error rendering screenlet in screen named [" + getModelScreen().getName() + "]: ";

+                Debug.logError(e, errMsg, module);

+                throw new RuntimeException(errMsg + e);

+            }

+        }

+

+        public boolean collapsible() {

+            return this.collapsible;

+        }

+

+        //initially-collapsed status, which may be overriden by user preference

+        public boolean getInitiallyCollapsed(Map<String, Object> context) {

+            String screenletId = this.getId(context) + "_collapsed";

+            Map<String, ? extends Object> userPreferences = UtilGenerics.checkMap(context.get("userPreferences"));

+            if (userPreferences != null && userPreferences.containsKey(screenletId)) {

+                return Boolean.valueOf((String)userPreferences.get(screenletId)).booleanValue() ;

+            }

+

+            return "true".equals(this.initiallyCollapsed.expand(context));

+        }

+

+        public boolean saveCollapsed() {

+            return this.saveCollapsed;

+        }

+        public boolean padded() {

+            return this.padded;

+        }

+

+        public String getPreferenceKey(Map<String, Object> context) {

+            String name = this.idExdr.expandString(context);

+            if (name.isEmpty()) {

+                name = "screenlet" + "_" + Integer.toHexString(hashCode());

+            }

+            return name;

+        }

+

+        public String getId(Map<String, Object> context) {

+            return this.idExdr.expandString(context);

+        }

+

+        public List<ModelScreenWidget> getSubWidgets() {

+            return subWidgets;

+        }

+

+        public String getTitle(Map<String, Object> context) {

+            String title = this.titleExdr.expandString(context);

+            UtilCodec.SimpleEncoder simpleEncoder = (UtilCodec.SimpleEncoder) context.get("simpleEncoder");

+            if (simpleEncoder != null) {

+                title = simpleEncoder.encode(title);

+            }

+            return title;

+        }

+

+        public Menu getNavigationMenu() {

+            return this.navigationMenu;

+        }

+

+        public Form getNavigationForm() {

+            return this.navigationForm;

+        }

+

+        public Menu getTabMenu() {

+            return this.tabMenu;

+        }

+

+        @Override

+        public void accept(ModelWidgetVisitor visitor) throws Exception {

+            visitor.visit(this);

+        }

+

+        public FlexibleStringExpander getIdExdr() {

+            return idExdr;

+        }

+

+        public FlexibleStringExpander getTitleExdr() {

+            return titleExdr;

+        }

+

+        public boolean getCollapsible() {

+            return collapsible;

+        }

+

+        public FlexibleStringExpander getInitiallyCollapsed() {

+            return initiallyCollapsed;

+        }

+

+        public boolean getSaveCollapsed() {

+            return saveCollapsed;

+        }

+

+        public boolean getPadded() {

+            return padded;

+        }

+    }

+

+    public static final class HorizontalSeparator extends ModelScreenWidget {

+        public static final String TAG_NAME = "horizontal-separator";

+        private final FlexibleStringExpander idExdr;

+        private final FlexibleStringExpander styleExdr;

+

+        public HorizontalSeparator(ModelScreen modelScreen, Element separatorElement) {

+            super(modelScreen, separatorElement);

+            this.idExdr = FlexibleStringExpander.getInstance(separatorElement.getAttribute("id"));

+            this.styleExdr = FlexibleStringExpander.getInstance(separatorElement.getAttribute("style"));

+        }

+

+        @Override

+        public void renderWidgetString(Appendable writer, Map<String, Object> context, ScreenStringRenderer screenStringRenderer) throws GeneralException, IOException {

+            screenStringRenderer.renderHorizontalSeparator(writer, context, this);

+        }

+

+        public String getId(Map<String, Object> context) {

+            return this.idExdr.expandString(context);

+        }

+

+        public String getStyle(Map<String, Object> context) {

+            return this.styleExdr.expandString(context);

+        }

+

+        @Override

+        public void accept(ModelWidgetVisitor visitor) throws Exception {

+            visitor.visit(this);

+        }

+

+        public FlexibleStringExpander getIdExdr() {

+            return idExdr;

+        }

+

+        public FlexibleStringExpander getStyleExdr() {

+            return styleExdr;

+        }

+    }

+

+    public static final class IncludeScreen extends ModelScreenWidget {

+        public static final String TAG_NAME = "include-screen";

+        private final FlexibleStringExpander nameExdr;

+        private final FlexibleStringExpander locationExdr;

+        private final FlexibleStringExpander shareScopeExdr;

+

+        public IncludeScreen(ModelScreen modelScreen, Element includeScreenElement) {

+            super(modelScreen, includeScreenElement);

+            this.nameExdr = FlexibleStringExpander.getInstance(includeScreenElement.getAttribute("name"));

+            this.locationExdr = FlexibleStringExpander.getInstance(includeScreenElement.getAttribute("location"));

+            this.shareScopeExdr = FlexibleStringExpander.getInstance(includeScreenElement.getAttribute("share-scope"));

+        }

+

+        @Override

+        public void renderWidgetString(Appendable writer, Map<String, Object> context, ScreenStringRenderer screenStringRenderer) throws GeneralException, IOException {

+            // if we are not sharing the scope, protect it using the MapStack

+            boolean protectScope = !shareScope(context);

+            if (protectScope) {

+                if (!(context instanceof MapStack<?>)) {

+                    context = MapStack.create(context);

+                }

+

+                UtilGenerics.<MapStack<String>>cast(context).push();

+

+                // build the widgetpath

+                List<String> widgetTrail = UtilGenerics.toList(context.get("_WIDGETTRAIL_"));

+                if (widgetTrail == null) {

+                    widgetTrail = new LinkedList<String>();

+                }

+

+                String thisName = nameExdr.expandString(context);

+                widgetTrail.add(thisName);

+                context.put("_WIDGETTRAIL_", widgetTrail);

+            }

+

+            // don't need the renderer here, will just pass this on down to another screen call; screenStringRenderer.renderContainerBegin(writer, context, this);

+            String name = this.getName(context);

+            String location = this.getLocation(context);

+

+            if (name.isEmpty()) {

+                if (Debug.verboseOn()) Debug.logVerbose("In the include-screen tag the screen name was empty, ignoring include; in screen [" + getModelScreen().getName() + "]", module);

+                return;

+            }

+

+            ScreenFactory.renderReferencedScreen(name, location, this, writer, context, screenStringRenderer);

+

+            if (protectScope) {

+                UtilGenerics.<MapStack<String>>cast(context).pop();

+            }

+        }

+

+        public String getName(Map<String, Object> context) {

+            return this.nameExdr.expandString(context);

+        }

+

+        public String getLocation(Map<String, Object> context) {

+            return this.locationExdr.expandString(context);

+        }

+

+        public boolean shareScope(Map<String, Object> context) {

+            String shareScopeString = this.shareScopeExdr.expandString(context);

+            // defaults to false, so anything but true is false

+            return "true".equals(shareScopeString);

+        }

+

+        @Override

+        public void accept(ModelWidgetVisitor visitor) throws Exception {

+            visitor.visit(this);

+        }

+

+        public FlexibleStringExpander getNameExdr() {

+            return nameExdr;

+        }

+

+        public FlexibleStringExpander getLocationExdr() {

+            return locationExdr;

+        }

+

+        public FlexibleStringExpander getShareScopeExdr() {

+            return shareScopeExdr;

+        }

+    }

+

+    public static final class DecoratorScreen extends ModelScreenWidget {

+        public static final String TAG_NAME = "decorator-screen";

+        private final FlexibleStringExpander nameExdr;

+        private final FlexibleStringExpander locationExdr;

+        private final Map<String, ModelScreenWidget> sectionMap;

+

+        public DecoratorScreen(ModelScreen modelScreen, Element decoratorScreenElement) {

+            super(modelScreen, decoratorScreenElement);

+            this.nameExdr = FlexibleStringExpander.getInstance(decoratorScreenElement.getAttribute("name"));

+            this.locationExdr = FlexibleStringExpander.getInstance(decoratorScreenElement.getAttribute("location"));

+            Map<String, ModelScreenWidget> sectionMap = new HashMap<String, ModelScreenWidget>();

+            List<? extends Element> decoratorSectionElementList = UtilXml.childElementList(decoratorScreenElement, "decorator-section");

+            for (Element decoratorSectionElement: decoratorSectionElementList) {

+                DecoratorSection decoratorSection = new DecoratorSection(modelScreen, decoratorSectionElement);

+                sectionMap.put(decoratorSection.getName(), decoratorSection);

+            }

+            this.sectionMap = Collections.unmodifiableMap(sectionMap);

+        }

+

+        @Override

+        @SuppressWarnings("unchecked")

+        public void renderWidgetString(Appendable writer, Map<String, Object> context, ScreenStringRenderer screenStringRenderer) throws GeneralException, IOException {

+            // isolate the scope

+            if (!(context instanceof MapStack)) {

+                context = MapStack.create(context);

+            }

+

+            MapStack contextMs = (MapStack) context;

+

+            // create a standAloneStack, basically a "save point" for this SectionsRenderer, and make a new "screens" object just for it so it is isolated and doesn't follow the stack down

+            MapStack standAloneStack = contextMs.standAloneChildStack();

+            standAloneStack.put("screens", new ScreenRenderer(writer, standAloneStack, screenStringRenderer));

+            SectionsRenderer sections = new SectionsRenderer(this.sectionMap, standAloneStack, writer, screenStringRenderer);

+

+            // put the sectionMap in the context, make sure it is in the sub-scope, ie after calling push on the MapStack

+            contextMs.push();

+            context.put("sections", sections);

+

+            String name = this.getName(context);

+            String location = this.getLocation(context);

+

+            ScreenFactory.renderReferencedScreen(name, location, this, writer, context, screenStringRenderer);

+

+            contextMs.pop();

+        }

+

+        public String getName(Map<String, Object> context) {

+            return this.nameExdr.expandString(context);

+        }

+

+        public String getLocation(Map<String, Object> context) {

+            return this.locationExdr.expandString(context);

+        }

+

+        public Map<String, ModelScreenWidget> getSectionMap() {

+            return sectionMap;

+        }

+

+        @Override

+        public void accept(ModelWidgetVisitor visitor) throws Exception {

+            visitor.visit(this);

+        }

+

+        public FlexibleStringExpander getNameExdr() {

+            return nameExdr;

+        }

+

+        public FlexibleStringExpander getLocationExdr() {

+            return locationExdr;

+        }

+

+    }

+

+    public static final class DecoratorSection extends ModelScreenWidget {

+        public static final String TAG_NAME = "decorator-section";

+        private final List<ModelScreenWidget> subWidgets;

+

+        public DecoratorSection(ModelScreen modelScreen, Element decoratorSectionElement) {

+            super(modelScreen, decoratorSectionElement);

+            // read sub-widgets

+            List<? extends Element> subElementList = UtilXml.childElementList(decoratorSectionElement);

+            this.subWidgets = ModelScreenWidget.readSubWidgets(getModelScreen(), subElementList);

+        }

+

+        @Override

+        public void renderWidgetString(Appendable writer, Map<String, Object> context, ScreenStringRenderer screenStringRenderer) throws GeneralException, IOException {

+            // render sub-widgets

+            renderSubWidgetsString(this.subWidgets, writer, context, screenStringRenderer);

+        }

+

+        public List<ModelScreenWidget> getSubWidgets() {

+            return subWidgets;

+        }

+

+        @Override

+        public void accept(ModelWidgetVisitor visitor) throws Exception {

+            visitor.visit(this);

+        }

+    }

+

+    public static final class DecoratorSectionInclude extends ModelScreenWidget {

+        public static final String TAG_NAME = "decorator-section-include";

+

+        public DecoratorSectionInclude(ModelScreen modelScreen, Element decoratorSectionElement) {

+            super(modelScreen, decoratorSectionElement);

+        }

+

+        @Override

+        public void renderWidgetString(Appendable writer, Map<String, Object> context, ScreenStringRenderer screenStringRenderer) throws GeneralException, IOException {

+            Map<String, ? extends Object> preRenderedContent = UtilGenerics.checkMap(context.get("preRenderedContent"));

+            if (preRenderedContent != null && preRenderedContent.containsKey(getName())) {

+                try {

+                    writer.append((String) preRenderedContent.get(getName()));

+                } catch (IOException e) {

+                    String errMsg = "Error rendering pre-rendered content in screen named [" + getModelScreen().getName() + "]: " + e.toString();

+                    Debug.logError(e, errMsg, module);

+                    throw new RuntimeException(errMsg);

+                }

+            } else {

+                SectionsRenderer sections = (SectionsRenderer) context.get("sections");

+                // for now if sections is null, just log a warning; may be permissible to make the screen for flexible

+                if (sections == null) {

+                    Debug.logWarning("In decorator-section-include could not find sections object in the context, not rendering section with name [" + getName() + "]", module);

+                } else {

+                    sections.render(getName());

+                }

+            }

+        }

+

+        @Override

+        public void accept(ModelWidgetVisitor visitor) throws Exception {

+            visitor.visit(this);

+        }

+    }

+

+    public static final class Label extends ModelScreenWidget {

+        public static final String TAG_NAME = "label";

+        private final FlexibleStringExpander textExdr;

+        private final FlexibleStringExpander idExdr;

+        private final FlexibleStringExpander styleExdr;

+

+        public Label(ModelScreen modelScreen, Element labelElement) {

+            super(modelScreen, labelElement);

+

+            // put the text attribute first, then the pcdata under the element, if both are there of course

+            String textAttr = labelElement.getAttribute("text");

+            String pcdata = UtilXml.elementValue(labelElement);

+            if (pcdata == null) {

+                pcdata = "";

+            }

+            this.textExdr = FlexibleStringExpander.getInstance(textAttr + pcdata);

+

+            this.idExdr = FlexibleStringExpander.getInstance(labelElement.getAttribute("id"));

+            this.styleExdr = FlexibleStringExpander.getInstance(labelElement.getAttribute("style"));

+        }

+

+        @Override

+        public void renderWidgetString(Appendable writer, Map<String, Object> context, ScreenStringRenderer screenStringRenderer) {

+            try {

+                screenStringRenderer.renderLabel(writer, context, this);

+            } catch (IOException e) {

+                String errMsg = "Error rendering label in screen named [" + getModelScreen().getName() + "]: " + e.toString();

+                Debug.logError(e, errMsg, module);

+                throw new RuntimeException(errMsg);

+            }

+        }

+

+        public String getText(Map<String, Object> context) {

+            String text = this.textExdr.expandString(context);

+            // FIXME: Encoding should be done by the renderer, not by the model.

+            UtilCodec.SimpleEncoder simpleEncoder = (UtilCodec.SimpleEncoder) context.get("simpleEncoder");

+            if (simpleEncoder != null) {

+                text = simpleEncoder.encode(text);

+            }

+            return text;

+        }

+

+        public String getId(Map<String, Object> context) {

+            return this.idExdr.expandString(context);

+        }

+

+        public String getStyle(Map<String, Object> context) {

+            return this.styleExdr.expandString(context);

+        }

+

+        @Override

+        public void accept(ModelWidgetVisitor visitor) throws Exception {

+            visitor.visit(this);

+        }

+

+        public FlexibleStringExpander getTextExdr() {

+            return textExdr;

+        }

+

+        public FlexibleStringExpander getIdExdr() {

+            return idExdr;

+        }

+

+        public FlexibleStringExpander getStyleExdr() {

+            return styleExdr;

+        }

+    }

+

+    public static final class Form extends ModelScreenWidget {

+        public static final String TAG_NAME = "include-form";

+        private final FlexibleStringExpander nameExdr;

+        private final FlexibleStringExpander locationExdr;

+        private final FlexibleStringExpander shareScopeExdr;

+

+        public Form(ModelScreen modelScreen, Element formElement) {

+            super(modelScreen, formElement);

+            this.nameExdr = FlexibleStringExpander.getInstance(formElement.getAttribute("name"));

+            this.locationExdr = FlexibleStringExpander.getInstance(formElement.getAttribute("location"));

+            this.shareScopeExdr = FlexibleStringExpander.getInstance(formElement.getAttribute("share-scope"));

+        }

+

+        @Override

+        public void renderWidgetString(Appendable writer, Map<String, Object> context, ScreenStringRenderer screenStringRenderer) {

+            // Output format might not support forms, so make form rendering optional.

+            FormStringRenderer formStringRenderer = (FormStringRenderer) context.get("formStringRenderer");

+            if (formStringRenderer == null) {

+                Debug.logVerbose("FormStringRenderer instance not found in rendering context, form not rendered.", module);

+                return;

+            }

+            boolean protectScope = !shareScope(context);

+            if (protectScope) {

+                if (!(context instanceof MapStack<?>)) {

+                    context = MapStack.create(context);

+                }

+                UtilGenerics.<MapStack<String>>cast(context).push();

+            }

+            ModelForm modelForm = getModelForm(context);

+            FormRenderer renderer = new FormRenderer(modelForm, formStringRenderer);

+            try {

+                renderer.render(writer, context);

+            } catch (Exception e) {

+                String errMsg = "Error rendering included form named [" + getName() + "] at location [" + this.getLocation(context) + "]: " + e.toString();

+                Debug.logError(e, errMsg, module);

+                throw new RuntimeException(errMsg + e);

+            }

+

+            if (protectScope) {

+                UtilGenerics.<MapStack<String>>cast(context).pop();

+            }

+        }

+

+        public ModelForm getModelForm(Map<String, Object> context) {

+            ModelForm modelForm = null;

+            String name = this.getName(context);

+            String location = this.getLocation(context);

+            try {

+                modelForm = FormFactory.getFormFromLocation(location, name, getModelScreen().getDelegator(context).getModelReader(), getModelScreen().getDispatcher(context).getDispatchContext());

+            } catch (Exception e) {

+                String errMsg = "Error rendering included form named [" + name + "] at location [" + location + "]: ";

+                Debug.logError(e, errMsg, module);

+                throw new RuntimeException(errMsg + e);

+            }

+            return modelForm;

+        }

+

+        public String getName(Map<String, Object> context) {

+            return this.nameExdr.expandString(context);

+        }

+

+        public String getLocation() {

+            return locationExdr.getOriginal();

+        }

+

+        public String getLocation(Map<String, Object> context) {

+            return this.locationExdr.expandString(context);

+        }

+

+        public boolean shareScope(Map<String, Object> context) {

+            String shareScopeString = this.shareScopeExdr.expandString(context);

+            // defaults to false, so anything but true is false

+            return "true".equals(shareScopeString);

+        }

+

+        @Override

+        public void accept(ModelWidgetVisitor visitor) throws Exception {

+            visitor.visit(this);

+        }

+

+        public FlexibleStringExpander getNameExdr() {

+            return nameExdr;

+        }

+

+        public FlexibleStringExpander getLocationExdr() {

+            return locationExdr;

+        }

+

+        public FlexibleStringExpander getShareScopeExdr() {

+            return shareScopeExdr;

+        }

+

+    }

+

+    public static final class Tree extends ModelScreenWidget {

+        public static final String TAG_NAME = "include-tree";

+        private final FlexibleStringExpander nameExdr;

+        private final FlexibleStringExpander locationExdr;

+        private final FlexibleStringExpander shareScopeExdr;

+

+        public Tree(ModelScreen modelScreen, Element treeElement) {

+            super(modelScreen, treeElement);

+            this.nameExdr = FlexibleStringExpander.getInstance(treeElement.getAttribute("name"));

+            this.locationExdr = FlexibleStringExpander.getInstance(treeElement.getAttribute("location"));

+            this.shareScopeExdr = FlexibleStringExpander.getInstance(treeElement.getAttribute("share-scope"));

+        }

+

+        @Override

+        public void renderWidgetString(Appendable writer, Map<String, Object> context, ScreenStringRenderer screenStringRenderer) throws GeneralException, IOException {

+            // Output format might not support trees, so make tree rendering optional.

+            TreeStringRenderer treeStringRenderer = (TreeStringRenderer) context.get("treeStringRenderer");

+            if (treeStringRenderer == null) {

+                Debug.logVerbose("TreeStringRenderer instance not found in rendering context, tree not rendered.", module);

+                return;

+            }

+            boolean protectScope = !shareScope(context);

+            if (protectScope) {

+                if (!(context instanceof MapStack<?>)) {

+                    context = MapStack.create(context);

+                }

+                UtilGenerics.<MapStack<String>>cast(context).push();

+            }

+

+            String name = this.getName(context);

+            String location = this.getLocation(context);

+            ModelTree modelTree = null;

+            try {

+                modelTree = TreeFactory.getTreeFromLocation(this.getLocation(context), this.getName(context), getModelScreen().getDelegator(context), getModelScreen().getDispatcher(context));

+            } catch (IOException e) {

+                String errMsg = "Error rendering included tree named [" + name + "] at location [" + location + "]: " + e.toString();

+                Debug.logError(e, errMsg, module);

+                throw new RuntimeException(errMsg);

+            } catch (SAXException e) {

+                String errMsg = "Error rendering included tree named [" + name + "] at location [" + location + "]: " + e.toString();

+                Debug.logError(e, errMsg, module);

+                throw new RuntimeException(errMsg);

+            } catch (ParserConfigurationException e) {

+                String errMsg = "Error rendering included tree named [" + name + "] at location [" + location + "]: " + e.toString();

+                Debug.logError(e, errMsg, module);

+                throw new RuntimeException(errMsg);

+            }

+            modelTree.renderTreeString(writer, context, treeStringRenderer);

+            if (protectScope) {

+                UtilGenerics.<MapStack<String>>cast(context).pop();

+            }

+        }

+

+        public String getName(Map<String, Object> context) {

+            return this.nameExdr.expandString(context);

+        }

+

+        public String getLocation(Map<String, Object> context) {

+            return this.locationExdr.expandString(context);

+        }

+

+        public boolean shareScope(Map<String, Object> context) {

+            String shareScopeString = this.shareScopeExdr.expandString(context);

+            // defaults to false, so anything but true is false

+            return "true".equals(shareScopeString);

+        }

+

+        @Override

+        public void accept(ModelWidgetVisitor visitor) throws Exception {

+            visitor.visit(this);

+        }

+

+        public FlexibleStringExpander getLocationExdr() {

+            return locationExdr;

+        }

+

+        public FlexibleStringExpander getShareScopeExdr() {

+            return shareScopeExdr;

+        }

+    }

+

+    public static final class PlatformSpecific extends ModelScreenWidget {

+        public static final String TAG_NAME = "platform-specific";

+        private final Map<String, ModelScreenWidget> subWidgets;

+

+        public PlatformSpecific(ModelScreen modelScreen, Element platformSpecificElement) {

+            super(modelScreen, platformSpecificElement);

+            Map<String, ModelScreenWidget> subWidgets = new HashMap<String, ModelScreenWidget>();

+            List<? extends Element> childElements = UtilXml.childElementList(platformSpecificElement);

+            if (childElements != null) {

+                for (Element childElement: childElements) {

+                    if ("html".equals(childElement.getNodeName())) {

+                        subWidgets.put("html", new HtmlWidget(modelScreen, childElement));

+                    } else if ("xsl-fo".equals(childElement.getNodeName())) {

+                        subWidgets.put("xsl-fo", new HtmlWidget(modelScreen, childElement));

+                    } else if ("xml".equals(childElement.getNodeName())) {

+                        subWidgets.put("xml", new HtmlWidget(modelScreen, childElement));

+                    } else {

+                        throw new IllegalArgumentException("Tag not supported under the platform-specific tag with name: " + childElement.getNodeName());

+                    }

+                }

+            }

+            this.subWidgets = Collections.unmodifiableMap(subWidgets);

+        }

+

+        @Override

+        public void renderWidgetString(Appendable writer, Map<String, Object> context, ScreenStringRenderer screenStringRenderer) throws GeneralException, IOException {

+            ModelScreenWidget subWidget = null;

+            subWidget = subWidgets.get(screenStringRenderer.getRendererName());

+            if (subWidget == null) {

+                // This is here for backward compatibility

+                Debug.logWarning("In platform-dependent could not find template for " + screenStringRenderer.getRendererName() + ", using the one for html.", module);

+                subWidget = subWidgets.get("html");

+            }

+            if (subWidget != null) {

+                subWidget.renderWidgetString(writer, context, screenStringRenderer);

+            }

+        }

+

+        @Override

+        public void accept(ModelWidgetVisitor visitor) throws Exception {

+            visitor.visit(this);

+        }

+

+        public Map<String, ModelScreenWidget> getSubWidgets() {

+            return subWidgets;

+        }

+    }

+

+    public static final class Content extends ModelScreenWidget {

+        public static final String TAG_NAME = "content";

+

+        private final FlexibleStringExpander contentId;

+        private final FlexibleStringExpander editRequest;

+        private final FlexibleStringExpander editContainerStyle;

+        private final FlexibleStringExpander enableEditName;

+        private final boolean xmlEscape;

+        private final FlexibleStringExpander dataResourceId;

+        private final String width;

+        private final String height;

+        private final String border;

+

+        public Content(ModelScreen modelScreen, Element subContentElement) {

+            super(modelScreen, subContentElement);

+            this.contentId = FlexibleStringExpander.getInstance(subContentElement.getAttribute("content-id"));

+            this.dataResourceId = FlexibleStringExpander.getInstance(subContentElement.getAttribute("dataresource-id"));

+            this.editRequest = FlexibleStringExpander.getInstance(subContentElement.getAttribute("edit-request"));

+            this.editContainerStyle = FlexibleStringExpander.getInstance(subContentElement.getAttribute("edit-container-style"));

+            this.enableEditName = FlexibleStringExpander.getInstance(subContentElement.getAttribute("enable-edit-name"));

+            this.xmlEscape = "true".equals(subContentElement.getAttribute("xml-escape"));

+            String width = subContentElement.getAttribute("width");

+            if (width.isEmpty())

+                width = "60%";

+            this.height = subContentElement.getAttribute("height");

+            if (this.height.isEmpty())

+                width = "400px";

+            this.width = width;

+            this.border = subContentElement.getAttribute("border");

+        }

+

+        @Override

+        public void renderWidgetString(Appendable writer, Map<String, Object> context, ScreenStringRenderer screenStringRenderer) {

+            try {

+                // pushing the contentId on the context as "contentId" is done

+                // because many times there will be embedded "subcontent" elements

+                // that use the syntax: <subcontent content-id="${contentId}"...

+                // and this is a step to make sure that it is there.

+                Delegator delegator = (Delegator) context.get("delegator");

+                GenericValue content = null;

+                String expandedDataResourceId = getDataResourceId(context);

+                String expandedContentId = getContentId(context);

+                if (!(context instanceof MapStack<?>)) {

+                    context = MapStack.create(context);

+                }

+

+                // This is an important step to make sure that the current contentId is in the context

+                // as templates that contain "subcontent" elements will expect to find the master

+                // contentId in the context as "contentId".

+                UtilGenerics.<MapStack<String>>cast(context).push();

+                context.put("contentId", expandedContentId);

+

+                if (expandedDataResourceId.isEmpty()) {

+                    if (!expandedContentId.isEmpty()) {

+                        content = EntityQuery.use(delegator).from("Content").where("contentId", expandedContentId).cache().queryOne();

+                    } else {

+                        String errMsg = "contentId is empty.";

+                        Debug.logError(errMsg, module);

+                        return;

+                    }

+                    if (content != null) {

+                        expandedDataResourceId = content.getString("dataResourceId");

+                    } else {

+                        String errMsg = "Could not find content with contentId [" + expandedContentId + "] ";

+                        Debug.logError(errMsg, module);

+                        throw new RuntimeException(errMsg);

+                    }

+                }

+

+                GenericValue dataResource = null;

+                if (!expandedDataResourceId.isEmpty()) {

+                    dataResource = EntityQuery.use(delegator).from("DataResource").where("dataResourceId", expandedDataResourceId).cache().queryOne();

+                }

+

+                String mimeTypeId = null;

+                if (dataResource != null) {

+                    mimeTypeId = dataResource.getString("mimeTypeId");

+                }

+                if (content != null) {

+                    mimeTypeId = content.getString("mimeTypeId");

+                }

+

+                if (!(mimeTypeId != null

+                        && ((mimeTypeId.indexOf("application") >= 0) || (mimeTypeId.indexOf("image")) >= 0))) {

+                    screenStringRenderer.renderContentBegin(writer, context, this);

+                    screenStringRenderer.renderContentBody(writer, context, this);

+                    screenStringRenderer.renderContentEnd(writer, context, this);

+                }

+                UtilGenerics.<MapStack<String>>cast(context).pop();

+            } catch (IOException e) {

+                String errMsg = "Error rendering content with contentId [" + getContentId(context) + "]: " + e.toString();

+                Debug.logError(e, errMsg, module);

+                throw new RuntimeException(errMsg);

+            } catch (GenericEntityException e) {

+                String errMsg = "Error obtaining content with contentId [" + getContentId(context) + "]: " + e.toString();

+                Debug.logError(e, errMsg, module);

+                throw new RuntimeException(errMsg);

+            }

+

+        }

+

+        public String getContentId(Map<String, Object> context) {

+            return this.contentId.expandString(context);

+        }

+

+        public String getDataResourceId() {

+            return this.dataResourceId.getOriginal();

+        }

+

+        public String getDataResourceId(Map<String, Object> context) {

+            return this.dataResourceId.expandString(context);

+        }

+

+        public String getEditRequest(Map<String, Object> context) {

+            return this.editRequest.expandString(context);

+        }

+

+        public String getEditContainerStyle(Map<String, Object> context) {

+            return this.editContainerStyle.expandString(context);

+        }

+

+        public String getEnableEditName(Map<String, Object> context) {

+            return this.enableEditName.expandString(context);

+        }

+

+        public boolean xmlEscape() {

+            return this.xmlEscape;

+        }

+

+        public String getWidth() {

+            return this.width;

+        }

+

+        public String getHeight() {

+            return this.height;

+        }

+

+        public String getBorder() {

+            return this.border;

+        }

+

+        @Override

+        public void accept(ModelWidgetVisitor visitor) throws Exception {

+            visitor.visit(this);

+        }

+

+        public FlexibleStringExpander getContentId() {

+            return contentId;

+        }

+

+        public FlexibleStringExpander getEditRequest() {

+            return editRequest;

+        }

+

+        public FlexibleStringExpander getEditContainerStyle() {

+            return editContainerStyle;

+        }

+

+        public FlexibleStringExpander getEnableEditName() {

+            return enableEditName;

+        }

+    }

+

+    public static final class SubContent extends ModelScreenWidget {

+        public static final String TAG_NAME = "sub-content";

+        private final FlexibleStringExpander contentId;

+        private final FlexibleStringExpander mapKey;

+        private final FlexibleStringExpander editRequest;

+        private final FlexibleStringExpander editContainerStyle;

+        private final FlexibleStringExpander enableEditName;

+        private final boolean xmlEscape;

+

+        public SubContent(ModelScreen modelScreen, Element subContentElement) {

+            super(modelScreen, subContentElement);

+            this.contentId = FlexibleStringExpander.getInstance(subContentElement.getAttribute("content-id"));

+            String mapKey = subContentElement.getAttribute("map-key");

+            if (mapKey.isEmpty()) {

+                mapKey = subContentElement.getAttribute("assoc-name");

+            }

+            this.mapKey = FlexibleStringExpander.getInstance(mapKey);

+            this.editRequest = FlexibleStringExpander.getInstance(subContentElement.getAttribute("edit-request"));

+            this.editContainerStyle = FlexibleStringExpander.getInstance(subContentElement.getAttribute("edit-container-style"));

+            this.enableEditName = FlexibleStringExpander.getInstance(subContentElement.getAttribute("enable-edit-name"));

+            this.xmlEscape = "true".equals(subContentElement.getAttribute("xml-escape"));

+        }

+

+        @Override

+        public void renderWidgetString(Appendable writer, Map<String, Object> context, ScreenStringRenderer screenStringRenderer) {

+            try {

+                screenStringRenderer.renderSubContentBegin(writer, context, this);

+                screenStringRenderer.renderSubContentBody(writer, context, this);

+                screenStringRenderer.renderSubContentEnd(writer, context, this);

+            } catch (IOException e) {

+                String errMsg = "Error rendering subContent with contentId [" + getContentId(context) + "]: " + e.toString();

+                Debug.logError(e, errMsg, module);

+                throw new RuntimeException(errMsg);

+            }

+        }

+

+        public String getContentId(Map<String, Object> context) {

+            return this.contentId.expandString(context);

+        }

+

+        public String getMapKey(Map<String, Object> context) {

+            return this.mapKey.expandString(context);

+        }

+

+        public String getEditRequest(Map<String, Object> context) {

+            return this.editRequest.expandString(context);

+        }

+

+        public String getEditContainerStyle(Map<String, Object> context) {

+            return this.editContainerStyle.expandString(context);

+        }

+

+        public String getEnableEditName(Map<String, Object> context) {

+            return this.enableEditName.expandString(context);

+        }

+

+        public boolean xmlEscape() {

+            return this.xmlEscape;

+        }

+

+        @Override

+        public void accept(ModelWidgetVisitor visitor) throws Exception {

+            // TODO Auto-generated method stub

+            

+        }

+    }

+

+    public static final class Menu extends ModelScreenWidget {

+        public static final String TAG_NAME = "include-menu";

+        private final FlexibleStringExpander nameExdr;

+        private final FlexibleStringExpander locationExdr;

+

+        public Menu(ModelScreen modelScreen, Element menuElement) {

+            super(modelScreen, menuElement);

+            this.nameExdr = FlexibleStringExpander.getInstance(menuElement.getAttribute("name"));

+            this.locationExdr = FlexibleStringExpander.getInstance(menuElement.getAttribute("location"));

+        }

+

+        @Override

+        public void renderWidgetString(Appendable writer, Map<String, Object> context, ScreenStringRenderer screenStringRenderer) throws IOException {

+            // Output format might not support menus, so make menu rendering optional.

+            MenuStringRenderer menuStringRenderer = (MenuStringRenderer) context.get("menuStringRenderer");

+            if (menuStringRenderer == null) {

+                Debug.logVerbose("MenuStringRenderer instance not found in rendering context, menu not rendered.", module);

+                return;

+            }

+            ModelMenu modelMenu = getModelMenu(context);

+            modelMenu.renderMenuString(writer, context, menuStringRenderer);

+        }

+

+        public ModelMenu getModelMenu(Map<String, Object> context) {

+            String name = this.getName(context);

+            String location = this.getLocation(context);

+            ModelMenu modelMenu = null;

+            try {

+                modelMenu = MenuFactory.getMenuFromLocation(location, name);

+            } catch (Exception e) {

+                String errMsg = "Error rendering included menu named [" + name + "] at location [" + location + "]: ";

+                Debug.logError(e, errMsg, module);

+                throw new RuntimeException(errMsg + e);

+            }

+            return modelMenu;

+        }

+

+        public String getName(Map<String, Object> context) {

+            return this.nameExdr.expandString(context);

+        }

+

+        public String getLocation(Map<String, Object> context) {

+            return this.locationExdr.expandString(context);

+        }

+

+        @Override

+        public void accept(ModelWidgetVisitor visitor) throws Exception {

+            visitor.visit(this);

+        }

+

+        public FlexibleStringExpander getLocationExdr() {

+            return locationExdr;

+        }

+    }

+

+    public static final class ScreenLink extends ModelScreenWidget {

+        public static final String TAG_NAME = "link";

+        private final Link link;

+        private final ScreenImage image;

+

+        public ScreenLink(ModelScreen modelScreen, Element linkElement) {

+            super(modelScreen, linkElement);

+            this.link = new Link(linkElement);

+            Element imageElement = UtilXml.firstChildElement(linkElement, "image");

+            if (imageElement != null) {

+                this.image = new ScreenImage(modelScreen, imageElement);

+            } else {

+                this.image = null;

+            }

+        }

+

+        public String getName() {

+            return link.getName();

+        }

+

+        public String getText(Map<String, Object> context) {

+            return link.getText(context);

+        }

+

+        public String getId(Map<String, Object> context) {

+            return link.getId(context);

+        }

+

+        public String getStyle(Map<String, Object> context) {

+            return link.getStyle(context);

+        }

+

+        public String getTarget(Map<String, Object> context) {

+            return link.getTarget(context);

+        }

+

+        public String getName(Map<String, Object> context) {

+            return link.getName(context);

+        }

+

+        public String getTargetWindow(Map<String, Object> context) {

+            return link.getTargetWindow(context);

+        }

+

+        public String getUrlMode() {

+            return link.getUrlMode();

+        }

+

+        public String getPrefix(Map<String, Object> context) {

+            return link.getPrefix(context);

+        }

+

+        public boolean getFullPath() {

+            return link.getFullPath();

+        }

+

+        public boolean getSecure() {

+            return link.getSecure();

+        }

+

+        public boolean getEncode() {

+            return link.getEncode();

+        }

+

+        public ScreenImage getImage() {

+            return image;

+        }

+

+        public String getLinkType() {

+            return link.getLinkType();

+        }

+

+        public String getWidth() {

+            return link.getWidth();

+        }

+

+        public String getHeight() {

+            return link.getHeight();

+        }

+

+        public Map<String, String> getParameterMap(Map<String, Object> context) {

+            return link.getParameterMap(context);

+        }

+

+        public FlexibleStringExpander getTextExdr() {

+            return link.getTextExdr();

+        }

+

+        public FlexibleStringExpander getIdExdr() {

+            return link.getIdExdr();

+        }

+

+        public FlexibleStringExpander getStyleExdr() {

+            return link.getStyleExdr();

+        }

+

+        public FlexibleStringExpander getTargetExdr() {

+            return link.getTargetExdr();

+        }

+

+        public FlexibleStringExpander getTargetWindowExdr() {

+            return link.getTargetWindowExdr();

+        }

+

+        public FlexibleStringExpander getPrefixExdr() {

+            return link.getPrefixExdr();

+        }

+

+        public FlexibleStringExpander getNameExdr() {

+            return link.getNameExdr();

+        }

+

+        public List<Parameter> getParameterList() {

+            return link.getParameterList();

+        }

+

+        public AutoServiceParameters getAutoServiceParameters() {

+            return link.getAutoServiceParameters();

+        }

+

+        public AutoEntityParameters getAutoEntityParameters() {

+            return link.getAutoEntityParameters();

+        }

+

+        @Override

+        public void renderWidgetString(Appendable writer, Map<String, Object> context, ScreenStringRenderer screenStringRenderer) {

+            try {

+                screenStringRenderer.renderLink(writer, context, this);

+            } catch (IOException e) {

+                String errMsg = "Error rendering link with id [" + link.getId(context) + "]: " + e.toString();

+                Debug.logError(e, errMsg, module);

+                throw new RuntimeException(errMsg);

+            }

+        }

+

+        @Override

+        public void accept(ModelWidgetVisitor visitor) throws Exception {

+            visitor.visit(this);

+        }

+

+        public Link getLink() {

+            return link;

+        }

+    }

+

+    public static final class ScreenImage extends ModelScreenWidget {

+        public static final String TAG_NAME = "image";

+        private final Image image;

+

+        public String getName() {

+            return image.getName();

+        }

+

+        public String getSrc(Map<String, Object> context) {

+            return image.getSrc(context);

+        }

+

+        public String getId(Map<String, Object> context) {

+            return image.getId(context);

+        }

+

+        public String getStyle(Map<String, Object> context) {

+            return image.getStyle(context);

+        }

+

+        public String getWidth(Map<String, Object> context) {

+            return image.getWidth(context);

+        }

+

+        public String getHeight(Map<String, Object> context) {

+            return image.getHeight(context);

+        }

+

+        public String getBorder(Map<String, Object> context) {

+            return image.getBorder(context);

+        }

+

+        public String getAlt(Map<String, Object> context) {

+            return image.getAlt(context);

+        }

+

+        public String getUrlMode() {

+            return image.getUrlMode();

+        }

+

+        public FlexibleStringExpander getSrcExdr() {

+            return image.getSrcExdr();

+        }

+

+        public FlexibleStringExpander getIdExdr() {

+            return image.getIdExdr();

+        }

+

+        public FlexibleStringExpander getStyleExdr() {

+            return image.getStyleExdr();

+        }

+

+        public FlexibleStringExpander getWidthExdr() {

+            return image.getWidthExdr();

+        }

+

+        public FlexibleStringExpander getHeightExdr() {

+            return image.getHeightExdr();

+        }

+

+        public FlexibleStringExpander getBorderExdr() {

+            return image.getBorderExdr();

+        }

+

+        public FlexibleStringExpander getAlt() {

+            return image.getAlt();

+        }

+

+        public ScreenImage(ModelScreen modelScreen, Element imageElement) {

+            super(modelScreen, imageElement);

+            this.image = new Image(imageElement);

+        }

+

+        @Override

+        public void renderWidgetString(Appendable writer, Map<String, Object> context, ScreenStringRenderer screenStringRenderer) {

+            try {

+                screenStringRenderer.renderImage(writer, context, this);

+            } catch (IOException e) {

+                String errMsg = "Error rendering image with id [" + image.getId(context) + "]: " + e.toString();

+                Debug.logError(e, errMsg, module);

+                throw new RuntimeException(errMsg);

+            }

+        }

+

+        @Override

+        public void accept(ModelWidgetVisitor visitor) throws Exception {

+            visitor.visit(this);

+        }

+

+        public Image getImage() {

+            return image;

+        }

+    }

+

+    public static final class PortalPage extends ModelScreenWidget {

+        public static final String TAG_NAME = "include-portal-page";

+        private final FlexibleStringExpander idExdr;

+        private final FlexibleStringExpander confModeExdr;

+        private final Boolean usePrivate;

+

+        public PortalPage(ModelScreen modelScreen, Element portalPageElement) {

+            super(modelScreen, portalPageElement);

+            this.idExdr = FlexibleStringExpander.getInstance(portalPageElement.getAttribute("id"));

+            this.confModeExdr = FlexibleStringExpander.getInstance(portalPageElement.getAttribute("conf-mode"));

+            this.usePrivate = !("false".equals(portalPageElement.getAttribute("use-private")));

+        }

+

+        private GenericValue getPortalPageValue(Map<String, Object> context) {

+            Delegator delegator = (Delegator) context.get("delegator");

+            String expandedPortalPageId = getId(context);

+            GenericValue portalPage = null;

+            if (!expandedPortalPageId.isEmpty()) {

+                if (usePrivate) {

+                    portalPage = PortalPageWorker.getPortalPage(expandedPortalPageId, context);

+                } else {

+                    try {

+                        portalPage = EntityQuery.use(delegator)

+                                                .from("PortalPage")

+                                                .where("portalPageId", expandedPortalPageId)

+                                                .cache().queryOne();

+                    } catch (GenericEntityException e) {

+                        throw new RuntimeException(e);

+                    }

+                }

+            }

+            if (portalPage == null) {

+                String errMsg = "Could not find PortalPage with portalPageId [" + expandedPortalPageId + "] ";

+                Debug.logError(errMsg, module);

+                throw new RuntimeException(errMsg);

+            }

+            return portalPage;

+        }

+

+        @Override

+        public void renderWidgetString(Appendable writer, Map<String, Object> context, ScreenStringRenderer screenStringRenderer) throws GeneralException, IOException {

+            try {

+                Delegator delegator = (Delegator) context.get("delegator");

+                List<GenericValue> portalPageColumns = null;

+                List<GenericValue> portalPagePortlets = null;

+                List<GenericValue> portletAttributes = null;

+                GenericValue portalPage = getPortalPageValue(context);

+                String actualPortalPageId = portalPage.getString("portalPageId");

+                portalPageColumns = EntityQuery.use(delegator)

+                                               .from("PortalPageColumn")

+                                               .where("portalPageId", actualPortalPageId)

+                                               .orderBy("columnSeqId")

+                                               .cache(true)

+                                               .queryList();

+                

+                // Renders the portalPage header

+                screenStringRenderer.renderPortalPageBegin(writer, context, this);

+                

+                // First column has no previous column

+                String prevColumnSeqId = "";

+                

+                // Iterates through the PortalPage columns

+                ListIterator <GenericValue>columnsIterator = portalPageColumns.listIterator();

+                while(columnsIterator.hasNext()) {

+                    GenericValue columnValue = columnsIterator.next();

+                    String columnSeqId = columnValue.getString("columnSeqId");

+                    

+                    // Renders the portalPageColumn header

+                    screenStringRenderer.renderPortalPageColumnBegin(writer, context, this, columnValue);

+

+                    // Get the Portlets located in the current column

+                    portalPagePortlets = EntityQuery.use(delegator)

+                                                    .from("PortalPagePortletView")

+                                                    .where("portalPageId", portalPage.getString("portalPageId"), "columnSeqId", columnSeqId)

+                                                    .orderBy("sequenceNum")

+                                                    .queryList();

+                    // First Portlet in a Column has no previous Portlet

+                    String prevPortletId = "";

+                    String prevPortletSeqId = "";

+

+                    // If this is not the last column, get the next columnSeqId

+                    String nextColumnSeqId = "";

+                    if (columnsIterator.hasNext()) {

+                        nextColumnSeqId = portalPageColumns.get(columnsIterator.nextIndex()).getString("columnSeqId");

+                    }

+                    

+                    // Iterates through the Portlets in the Column

+                    ListIterator <GenericValue>portletsIterator = portalPagePortlets.listIterator();

+                    while(portletsIterator.hasNext()) {

+                        GenericValue portletValue = portletsIterator.next();

+

+                        // If not the last portlet in the column, get the next nextPortletId and nextPortletSeqId

+                        String nextPortletId = "";

+                        String nextPortletSeqId = "";

+                        if (portletsIterator.hasNext()) {

+                            nextPortletId = portalPagePortlets.get(portletsIterator.nextIndex()).getString("portalPortletId");

+                            nextPortletSeqId = portalPagePortlets.get(portletsIterator.nextIndex()).getString("portletSeqId");

+                        }

+

+                        // Set info to allow portlet movement in the page

+                        context.put("prevPortletId", prevPortletId);

+                        context.put("prevPortletSeqId", prevPortletSeqId);

+                        context.put("nextPortletId", nextPortletId);

+                        context.put("nextPortletSeqId", nextPortletSeqId);

+                        context.put("prevColumnSeqId", prevColumnSeqId);

+                        context.put("nextColumnSeqId", nextColumnSeqId);

+                       

+                        // Get portlet's attributes

+                        portletAttributes = EntityQuery.use(delegator)

+                                                       .from("PortletAttribute")

+                                                       .where("portalPageId", portletValue.get("portalPageId"), "portalPortletId", portletValue.get("portalPortletId"), "portletSeqId", portletValue.get("portletSeqId"))

+                                                       .queryList();

+                        

+                        ListIterator <GenericValue>attributesIterator = portletAttributes.listIterator();

+                        while (attributesIterator.hasNext()) {

+                            GenericValue attribute = attributesIterator.next();

+                            context.put(attribute.getString("attrName"), attribute.getString("attrValue"));

+                        }

+                        

+                        // Renders the portalPagePortlet

+                        screenStringRenderer.renderPortalPagePortletBegin(writer, context, this, portletValue);

+                        screenStringRenderer.renderPortalPagePortletBody(writer, context, this, portletValue);

+                        screenStringRenderer.renderPortalPagePortletEnd(writer, context, this, portletValue);

+

+                        // Remove the portlet's attributes so that these are not available for other portlets

+                        while (attributesIterator.hasPrevious()) {

+                            GenericValue attribute = attributesIterator.previous();

+                            context.remove(attribute.getString("attrName"));

+                        }

+                        

+                        // Uses the actual portlet as prevPortlet for next iteration

+                        prevPortletId = (String) portletValue.get("portalPortletId");

+                        prevPortletSeqId = (String) portletValue.get("portletSeqId");

+                    }

+                    // Renders the portalPageColumn footer

+                    screenStringRenderer.renderPortalPageColumnEnd(writer, context, this, columnValue);

+

+                    // Uses the actual columnSeqId as prevColumnSeqId for next iteration

+                    prevColumnSeqId = columnSeqId;

+                }

+                // Renders the portalPage footer

+                screenStringRenderer.renderPortalPageEnd(writer, context, this);

+            } catch (IOException e) {

+                String errMsg = "Error rendering PortalPage with portalPageId [" + getId(context) + "]: " + e.toString();

+                Debug.logError(e, errMsg, module);

+                throw new RuntimeException(errMsg);

+            } catch (GenericEntityException e) {

+                String errMsg = "Error obtaining PortalPage with portalPageId [" + getId(context) + "]: " + e.toString();

+                Debug.logError(e, errMsg, module);

+                throw new RuntimeException(errMsg);

+            }

+        }

+

+        public String getId(Map<String, Object> context) {

+            return this.idExdr.expandString(context);

+        }

+

+        public String getOriginalPortalPageId(Map<String, Object> context) {

+            GenericValue portalPage = getPortalPageValue(context);

+            return portalPage.getString("originalPortalPageId");

+        }

+        

+        public String getActualPortalPageId(Map<String, Object> context) {

+            GenericValue portalPage = getPortalPageValue(context);

+            return portalPage.getString("portalPageId");

+        }

+

+        public String getConfMode(Map<String, Object> context) {

+            return this.confModeExdr.expandString(context);

+        }

+

+        public String getUsePrivate() {

+            return Boolean.toString(this.usePrivate);

+        }

+

+        @Override

+        public void accept(ModelWidgetVisitor visitor) throws Exception {

+            visitor.visit(this);

+        }

+

+        public FlexibleStringExpander getIdExdr() {

+            return idExdr;

+        }

+

+        public FlexibleStringExpander getConfModeExdr() {

+            return confModeExdr;

+        }

+    }

+

+}

diff --git a/framework/widget/src/org/ofbiz/widget/tree/ModelTree.java b/framework/widget/src/org/ofbiz/widget/model/ModelTree.java
similarity index 98%
rename from framework/widget/src/org/ofbiz/widget/tree/ModelTree.java
rename to framework/widget/src/org/ofbiz/widget/model/ModelTree.java
index 8c85016..9a2bf60 100644
--- a/framework/widget/src/org/ofbiz/widget/tree/ModelTree.java
+++ b/framework/widget/src/org/ofbiz/widget/model/ModelTree.java
@@ -1,1139 +1,1135 @@
-/*******************************************************************************
- * 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.tree;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.ListIterator;
-import java.util.Map;
-
-import javax.servlet.http.HttpServletRequest;
-import javax.xml.parsers.ParserConfigurationException;
-
-import org.ofbiz.base.util.Debug;
-import org.ofbiz.base.util.GeneralException;
-import org.ofbiz.base.util.StringUtil;
-import org.ofbiz.base.util.UtilCodec;
-import org.ofbiz.base.util.UtilGenerics;
-import org.ofbiz.base.util.UtilHttp;
-import org.ofbiz.base.util.UtilValidate;
-import org.ofbiz.base.util.UtilXml;
-import org.ofbiz.base.util.collections.MapStack;
-import org.ofbiz.base.util.string.FlexibleStringExpander;
-import org.ofbiz.entity.Delegator;
-import org.ofbiz.entity.GenericEntityException;
-import org.ofbiz.entity.GenericValue;
-import org.ofbiz.entity.model.ModelEntity;
-import org.ofbiz.entity.model.ModelField;
-import org.ofbiz.entity.util.EntityListIterator;
-import org.ofbiz.entity.util.EntityQuery;
-import org.ofbiz.widget.ModelWidget;
-import org.ofbiz.widget.*;
-import org.ofbiz.widget.ModelWidgetVisitor;
-import org.ofbiz.widget.WidgetWorker;
-import org.ofbiz.widget.CommonWidgetModels.Parameter;
-import org.ofbiz.widget.screen.ModelScreen;
-import org.ofbiz.widget.screen.ScreenFactory;
-import org.ofbiz.widget.screen.ScreenRenderException;
-import org.ofbiz.widget.screen.ScreenStringRenderer;
-import org.w3c.dom.Element;
-import org.xml.sax.SAXException;
-
-/**
- * Models the &lt;tree&gt; element.
- * 
- * @see <code>widget-tree.xsd</code>
- */
-@SuppressWarnings("serial")
-public class ModelTree extends ModelWidget {
-
-    /*
-     * ----------------------------------------------------------------------- *
-     *                     DEVELOPERS PLEASE READ
-     * ----------------------------------------------------------------------- *
-     * 
-     * This model is intended to be a read-only data structure that represents
-     * an XML element. Outside of object construction, the class should not
-     * have any behaviors.
-     * 
-     * Instances of this class will be shared by multiple threads - therefore
-     * it is immutable. DO NOT CHANGE THE OBJECT'S STATE AT RUN TIME!
-     * 
-     */
-
-    public static final String module = ModelTree.class.getName();
-
-    private final String defaultEntityName;
-    private final String defaultRenderStyle;
-    private final FlexibleStringExpander defaultWrapStyleExdr;
-    private final FlexibleStringExpander expandCollapseRequestExdr;
-    private final boolean forceChildCheck;
-    private final String location;
-    private final Map<String, ModelNode> nodeMap;
-    private final int openDepth;
-    private final int postTrailOpenDepth;
-    private final String rootNodeName;
-    private final FlexibleStringExpander trailNameExdr;
-
-    public ModelTree(Element treeElement, String location) {
-        super(treeElement);
-        this.location = location;
-        this.rootNodeName = treeElement.getAttribute("root-node-name");
-        String defaultRenderStyle = UtilXml.checkEmpty(treeElement.getAttribute("default-render-style"), "simple");
-        // A temporary hack to accommodate those who might still be using "render-style" instead of "default-render-style"
-        if (defaultRenderStyle.isEmpty() || defaultRenderStyle.equals("simple")) {
-            String rStyle = treeElement.getAttribute("render-style");
-            if (!rStyle.isEmpty())
-                defaultRenderStyle = rStyle;
-        }
-        this.defaultRenderStyle = defaultRenderStyle;
-        this.defaultWrapStyleExdr = FlexibleStringExpander.getInstance(treeElement.getAttribute("default-wrap-style"));
-        this.expandCollapseRequestExdr = FlexibleStringExpander.getInstance(treeElement.getAttribute("expand-collapse-request"));
-        this.trailNameExdr = FlexibleStringExpander.getInstance(UtilXml.checkEmpty(treeElement.getAttribute("trail-name"),
-                "trail"));
-        this.forceChildCheck = !"false".equals(treeElement.getAttribute("force-child-check"));
-        this.defaultEntityName = treeElement.getAttribute("entity-name");
-        int openDepth = 0;
-        if (treeElement.hasAttribute("open-depth")) {
-            try {
-                openDepth = Integer.parseInt(treeElement.getAttribute("open-depth"));
-            } catch (NumberFormatException e) {
-                throw new IllegalArgumentException("Invalid open-depth attribute value for the tree definition with name: "
-                        + getName());
-            }
-        }
-        this.openDepth = openDepth;
-        int postTrailOpenDepth = 999;
-        if (treeElement.hasAttribute("post-trail-open-depth")) {
-            try {
-                postTrailOpenDepth = Integer.parseInt(treeElement.getAttribute("post-trail-open-depth"));
-            } catch (NumberFormatException e) {
-                throw new IllegalArgumentException(
-                        "Invalid post-trail-open-depth attribute value for the tree definition with name: " + getName());
-            }
-        }
-        this.postTrailOpenDepth = postTrailOpenDepth;
-        List<? extends Element> nodeElements = UtilXml.childElementList(treeElement, "node");
-        if (nodeElements.size() == 0) {
-            throw new IllegalArgumentException("No node elements found for the tree definition with name: " + getName());
-        }
-        Map<String, ModelNode> nodeMap = new HashMap<String, ModelNode>();
-        for (Element nodeElementEntry : UtilXml.childElementList(treeElement, "node")) {
-            ModelNode node = new ModelNode(nodeElementEntry, this);
-            String nodeName = node.getName();
-            nodeMap.put(nodeName, node);
-        }
-        this.nodeMap = Collections.unmodifiableMap(nodeMap);
-    }
-
-    @Override
-    public void accept(ModelWidgetVisitor visitor) throws Exception {
-        visitor.visit(this);
-    }
-
-    @Override
-    public String getBoundaryCommentName() {
-        return location + "#" + getName();
-    }
-
-    public String getDefaultEntityName() {
-        return this.defaultEntityName;
-    }
-
-    public String getDefaultPkName(Map<String, Object> context) {
-        ModelEntity modelEntity = WidgetWorker.getDelegator(context).getModelEntity(this.defaultEntityName);
-        if (modelEntity.getPksSize() == 1) {
-            ModelField modelField = modelEntity.getOnlyPk();
-            return modelField.getName();
-        }
-        return null;
-    }
-
-    public String getExpandCollapseRequest(Map<String, Object> context) {
-        String expColReq = this.expandCollapseRequestExdr.expandString(context);
-        if (UtilValidate.isEmpty(expColReq)) {
-            HttpServletRequest request = (HttpServletRequest) context.get("request");
-            String s1 = request.getRequestURI();
-            int pos = s1.lastIndexOf("/");
-            if (pos >= 0)
-                expColReq = s1.substring(pos + 1);
-            else
-                expColReq = s1;
-        }
-        //append also the request parameters
-        Map<String, Object> paramMap = UtilGenerics.checkMap(context.get("requestParameters"));
-        if (UtilValidate.isNotEmpty(paramMap)) {
-            Map<String, Object> requestParameters = new HashMap<String, Object>(paramMap);
-            requestParameters.remove(this.getTrailName(context));
-            if (UtilValidate.isNotEmpty(requestParameters)) {
-                String queryString = UtilHttp.urlEncodeArgs(requestParameters, false);
-                if (expColReq.indexOf("?") < 0) {
-                    expColReq += "?";
-                } else {
-                    expColReq += "&amp;";
-                }
-                expColReq += queryString;
-            }
-        }
-        return expColReq;
-    }
-
-    public int getOpenDepth() {
-        return openDepth;
-    }
-
-    public int getPostTrailOpenDepth() {
-        return postTrailOpenDepth;
-    }
-
-    public String getRenderStyle() {
-        return this.defaultRenderStyle;
-    }
-
-    public String getRootNodeName() {
-        return rootNodeName;
-    }
-
-    public String getTrailName(Map<String, Object> context) {
-        return this.trailNameExdr.expandString(context);
-    }
-
-    public String getWrapStyle(Map<String, Object> context) {
-        return this.defaultWrapStyleExdr.expandString(context);
-    }
-
-    /**
-     * Renders this model.
-     *
-     * @param writer
-     * @param context
-     * @param treeStringRenderer
-     */
-    @SuppressWarnings("rawtypes")
-    public void renderTreeString(Appendable writer, Map<String, Object> context, TreeStringRenderer treeStringRenderer)
-            throws GeneralException {
-        Map<String, Object> parameters = UtilGenerics.checkMap(context.get("parameters"));
-        ModelNode node = nodeMap.get(rootNodeName);
-        String trailName = trailNameExdr.expandString(context);
-        String treeString = (String) context.get(trailName);
-        if (UtilValidate.isEmpty(treeString)) {
-            treeString = (String) parameters.get(trailName);
-        }
-        List<String> trail = null;
-        if (UtilValidate.isNotEmpty(treeString)) {
-            trail = StringUtil.split(treeString, "|");
-            if (UtilValidate.isEmpty(trail))
-                throw new RuntimeException("Tree 'trail' value is empty.");
-            context.put("rootEntityId", trail.get(0));
-            context.put(getDefaultPkName(context), trail.get(0));
-        } else {
-            trail = new LinkedList<String>();
-        }
-        context.put("targetNodeTrail", trail);
-        context.put("currentNodeTrail", new LinkedList());
-        try {
-            node.renderNodeString(writer, context, treeStringRenderer, 0);
-        } catch (IOException e2) {
-            String errMsg = "Error rendering included label with name [" + getName() + "] : " + e2.toString();
-            Debug.logError(e2, errMsg, module);
-            throw new RuntimeException(errMsg);
-        }
-
-    }
-
-    public String getDefaultRenderStyle() {
-        return defaultRenderStyle;
-    }
-
-    public FlexibleStringExpander getDefaultWrapStyleExdr() {
-        return defaultWrapStyleExdr;
-    }
-
-    public FlexibleStringExpander getExpandCollapseRequestExdr() {
-        return expandCollapseRequestExdr;
-    }
-
-    public boolean getForceChildCheck() {
-        return forceChildCheck;
-    }
-
-    public String getLocation() {
-        return location;
-    }
-
-    public Map<String, ModelNode> getNodeMap() {
-        return nodeMap;
-    }
-
-    public FlexibleStringExpander getTrailNameExdr() {
-        return trailNameExdr;
-    }
-
-    /**
-     * Models the &lt;node&gt; element.
-     * 
-     * @see <code>widget-tree.xsd</code>
-     */
-    public static class ModelNode extends ModelWidget {
-
-        private final List<ModelAction> actions;
-        // TODO: Make this a generic condition object.
-        private final ModelTreeCondition condition;
-        private final String entityName;
-        private final String entryName;
-        private final String expandCollapseStyle;
-        private final Label label;
-        private final Link link;
-        private final ModelTree modelTree;
-        private final String pkName;
-        private final String renderStyle;
-        private final FlexibleStringExpander screenLocationExdr;
-        private final FlexibleStringExpander screenNameExdr;
-        private final String shareScope;
-        private final List<ModelSubNode> subNodeList;
-        private final FlexibleStringExpander wrapStyleExdr;
-
-        public ModelNode(Element nodeElement, ModelTree modelTree) {
-            super(nodeElement);
-            this.modelTree = modelTree;
-            this.expandCollapseStyle = nodeElement.getAttribute("expand-collapse-style");
-            this.wrapStyleExdr = FlexibleStringExpander.getInstance(nodeElement.getAttribute("wrap-style"));
-            this.renderStyle = nodeElement.getAttribute("render-style");
-            this.entryName = nodeElement.getAttribute("entry-name");
-            this.entityName = nodeElement.getAttribute("entity-name");
-            this.pkName = nodeElement.getAttribute("join-field-name");
-            ArrayList<ModelAction> actions = new ArrayList<ModelAction>();
-            // FIXME: Validate child elements, should be only one of actions, entity-one, service, script.
-            Element actionsElement = UtilXml.firstChildElement(nodeElement, "actions");
-            if (actionsElement != null) {
-                actions.addAll(ModelTreeAction.readNodeActions(this, actionsElement));
-            }
-            Element actionElement = UtilXml.firstChildElement(nodeElement, "entity-one");
-            if (actionElement != null) {
-                actions.add(new AbstractModelAction.EntityOne(this, actionElement));
-            }
-            actionElement = UtilXml.firstChildElement(nodeElement, "service");
-            if (actionElement != null) {
-                actions.add(new ModelTreeAction.Service(this, actionElement));
-            }
-            actionElement = UtilXml.firstChildElement(nodeElement, "script");
-            if (actionElement != null) {
-                actions.add(new ModelTreeAction.Script(this, actionElement));
-            }
-            actions.trimToSize();
-            this.actions = Collections.unmodifiableList(actions);
-            Element screenElement = UtilXml.firstChildElement(nodeElement, "include-screen");
-            if (screenElement != null) {
-                this.screenNameExdr = FlexibleStringExpander.getInstance(screenElement.getAttribute("name"));
-                this.screenLocationExdr = FlexibleStringExpander.getInstance(screenElement.getAttribute("location"));
-                this.shareScope = screenElement.getAttribute("share-scope");
-            } else {
-                this.screenNameExdr = FlexibleStringExpander.getInstance("");
-                this.screenLocationExdr = FlexibleStringExpander.getInstance("");
-                this.shareScope = "";
-            }
-            Element labelElement = UtilXml.firstChildElement(nodeElement, "label");
-            if (labelElement != null) {
-                this.label = new Label(labelElement);
-            } else {
-                this.label = null;
-            }
-            Element linkElement = UtilXml.firstChildElement(nodeElement, "link");
-            if (linkElement != null) {
-                this.link = new Link(linkElement);
-            } else {
-                this.link = null;
-            }
-            Element conditionElement = UtilXml.firstChildElement(nodeElement, "condition");
-            if (conditionElement != null) {
-                this.condition = new ModelTreeCondition(modelTree, conditionElement);
-            } else {
-                this.condition = null;
-            }
-            List<? extends Element> nodeElements = UtilXml.childElementList(nodeElement, "sub-node");
-            if (!nodeElements.isEmpty()) {
-                List<ModelSubNode> subNodeList = new ArrayList<ModelSubNode>();
-                for (Element subNodeElementEntry : nodeElements) {
-                    ModelSubNode subNode = new ModelSubNode(subNodeElementEntry, this);
-                    subNodeList.add(subNode);
-                }
-                this.subNodeList = Collections.unmodifiableList(subNodeList);
-            } else {
-                this.subNodeList = Collections.emptyList();
-            }
-        }
-
-        @Override
-        public void accept(ModelWidgetVisitor visitor) throws Exception {
-            visitor.visit(this);
-        }
-
-        private List<Object[]> getChildren(Map<String, Object> context) {
-            List<Object[]> subNodeValues = new ArrayList<Object[]>();
-            for (ModelSubNode subNode : subNodeList) {
-                String nodeName = subNode.getNodeName(context);
-                ModelNode node = modelTree.nodeMap.get(nodeName);
-                List<ModelAction> subNodeActions = subNode.getActions();
-                //if (Debug.infoOn()) Debug.logInfo(" context.currentValue:" + context.get("currentValue"), module);
-                AbstractModelAction.runSubActions(subNodeActions, context);
-                // List dataFound = (List)context.get("dataFound");
-                Iterator<? extends Map<String, ? extends Object>> dataIter = subNode.getListIterator(context);
-                if (dataIter instanceof EntityListIterator) {
-                    EntityListIterator eli = (EntityListIterator) dataIter;
-                    Map<String, Object> val = null;
-                    while ((val = eli.next()) != null) {
-                        Object[] arr = { node, val };
-                        subNodeValues.add(arr);
-                    }
-                    try {
-                        eli.close();
-                    } catch (GenericEntityException e) {
-                        Debug.logError(e, module);
-                        throw new RuntimeException(e.getMessage());
-                    }
-                } else if (dataIter != null) {
-                    while (dataIter.hasNext()) {
-                        Map<String, ? extends Object> val = dataIter.next();
-                        Object[] arr = { node, val };
-                        subNodeValues.add(arr);
-                    }
-                }
-            }
-            return subNodeValues;
-        }
-
-        public String getEntityName() {
-            if (!this.entityName.isEmpty()) {
-                return this.entityName;
-            } else {
-                return this.modelTree.getDefaultEntityName();
-            }
-        }
-
-        public String getEntryName() {
-            return this.entryName;
-        }
-
-        public String getExpandCollapseStyle() {
-            return expandCollapseStyle;
-        }
-
-        public ModelTree getModelTree() {
-            return this.modelTree;
-        }
-
-        public String getPkName(Map<String, Object> context) {
-            if (UtilValidate.isNotEmpty(this.pkName)) {
-                return this.pkName;
-            } else {
-                return this.modelTree.getDefaultPkName(context);
-            }
-        }
-
-        public String getRenderStyle() {
-            if (this.renderStyle.isEmpty())
-                return modelTree.getRenderStyle();
-            return this.renderStyle;
-        }
-
-        public String getWrapStyle(Map<String, Object> context) {
-            String val = this.wrapStyleExdr.expandString(context);
-            if (val.isEmpty()) {
-                val = this.modelTree.getWrapStyle(context);
-            }
-            return val;
-        }
-
-        public boolean hasChildren(Map<String, Object> context) {
-            List<Object[]> subNodeValues = getChildren(context);
-            boolean hasChildren = false;
-            Long nodeCount = null;
-            String countFieldName = "childBranchCount";
-            Object obj = null;
-            if (!this.entryName.isEmpty()) {
-                Map<String, Object> map = UtilGenerics.cast(context.get(this.entryName));
-                if (map instanceof GenericValue) {
-                    ModelEntity modelEntity = ((GenericValue) map).getModelEntity();
-                    if (modelEntity.isField(countFieldName)) {
-                        obj = map.get(countFieldName);
-                    }
-                }
-            } else {
-                obj = context.get(countFieldName);
-            }
-            if (obj != null) {
-                nodeCount = (Long) obj;
-            }
-            String entName = this.getEntityName();
-            Delegator delegator = WidgetWorker.getDelegator(context);
-            ModelEntity modelEntity = delegator.getModelEntity(entName);
-            ModelField modelField = null;
-            if (modelEntity.isField(countFieldName)) {
-                modelField = modelEntity.getField(countFieldName);
-            }
-            if (nodeCount == null && modelField != null || this.modelTree.forceChildCheck) {
-                getChildren(context);
-                /*
-                String id = (String)context.get(modelTree.getPkName());
-                if (UtilValidate.isNotEmpty(id)) {
-                    try {
-                        int leafCount = ContentManagementWorker.updateStatsTopDown(delegator, id, UtilMisc.toList("SUB_CONTENT", "PUBLISH_LINK"));
-                        GenericValue entity = delegator.findOne(entName, UtilMisc.toMap(modelTree.getPkName(), id), true);
-                        obj = entity.get("childBranchCount");
-                       if (obj != null)
-                           nodeCount = (Long)obj;
-                    } catch (GenericEntityException e) {
-                        Debug.logError(e, module);
-                       throw new RuntimeException(e.getMessage());
-                    }
-                }
-                */
-                nodeCount = Long.valueOf(subNodeValues.size());
-                String pkName = this.getPkName(context);
-                String id = null;
-                if (!this.entryName.isEmpty()) {
-                    id = UtilGenerics.<Map<String, String>> cast(context.get(this.entryName)).get(pkName);
-                } else {
-                    id = (String) context.get(pkName);
-                }
-                try {
-                    if (id != null && modelEntity.getPksSize() == 1) {
-                        GenericValue entity = EntityQuery.use(delegator).from(entName).where(pkName, id).queryOne();
-                        if (modelEntity.isField("childBranchCount")) {
-                            entity.put("childBranchCount", nodeCount);
-                            entity.store();
-                        }
-                    }
-                } catch (GenericEntityException e) {
-                    Debug.logError(e, module);
-                    throw new RuntimeException(e.getMessage());
-                }
-            } else if (nodeCount == null) {
-                getChildren(context);
-                if (subNodeValues != null) {
-                    nodeCount = Long.valueOf(subNodeValues.size());
-                }
-            }
-            if (nodeCount != null && nodeCount.intValue() > 0) {
-                hasChildren = true;
-            }
-            return hasChildren;
-        }
-
-        public boolean isExpandCollapse() {
-            boolean isExpCollapse = false;
-            String rStyle = getRenderStyle();
-            if (rStyle != null && rStyle.equals("expand-collapse"))
-                isExpCollapse = true;
-            return isExpCollapse;
-        }
-
-        public boolean isFollowTrail() {
-            boolean isFollowTrail = false;
-            String rStyle = getRenderStyle();
-            if (rStyle != null && (rStyle.equals("follow-trail") || rStyle.equals("show-peers") || rStyle.equals("follow-trail"))) {
-                isFollowTrail = true;
-            }
-            return isFollowTrail;
-        }
-
-        public boolean isRootNode() {
-            return getName().equals(modelTree.getRootNodeName());
-        }
-
-        public void renderNodeString(Appendable writer, Map<String, Object> context, TreeStringRenderer treeStringRenderer,
-                int depth) throws IOException, GeneralException {
-            boolean passed = true;
-            if (this.condition != null) {
-                if (!this.condition.getCondition().eval(context)) {
-                    passed = false;
-                }
-            }
-            //Debug.logInfo("in ModelMenu, name:" + this.getName(), module);
-            if (passed) {
-                List<String> currentNodeTrail = UtilGenerics.toList(context.get("currentNodeTrail"));
-                context.put("processChildren", Boolean.TRUE);
-                // this action will usually obtain the "current" entity
-                ModelTreeAction.runSubActions(this.actions, context);
-                String pkName = getPkName(context);
-                String id = null;
-                if (!this.entryName.isEmpty()) {
-                    id = UtilGenerics.<Map<String, String>> cast(context.get(this.entryName)).get(pkName);
-                } else {
-                    id = (String) context.get(pkName);
-                }
-                currentNodeTrail.add(id);
-                treeStringRenderer.renderNodeBegin(writer, context, this, depth);
-                //if (Debug.infoOn()) Debug.logInfo(" context:" +
-                // context.entrySet(), module);
-                try {
-                    String screenName = null;
-                    if (!screenNameExdr.isEmpty())
-                        screenName = screenNameExdr.expandString(context);
-                    String screenLocation = null;
-                    if (!screenLocationExdr.isEmpty())
-                        screenLocation = screenLocationExdr.expandString(context);
-                    if (screenName != null && screenLocation != null) {
-                        ScreenStringRenderer screenStringRenderer = treeStringRenderer.getScreenStringRenderer(context);
-                        ModelScreen modelScreen = ScreenFactory.getScreenFromLocation(screenLocation, screenName);
-                        modelScreen.renderScreenString(writer, context, screenStringRenderer);
-                    }
-                    if (label != null) {
-                        label.renderLabelString(writer, context, treeStringRenderer);
-                    }
-                    if (link != null) {
-                        link.renderLinkString(writer, context, treeStringRenderer);
-                    }
-                    treeStringRenderer.renderLastElement(writer, context, this);
-                    Boolean processChildren = (Boolean) context.get("processChildren");
-                    //if (Debug.infoOn()) Debug.logInfo(" processChildren:" + processChildren, module);
-                    if (processChildren.booleanValue()) {
-                        List<Object[]> subNodeValues = getChildren(context);
-                        int newDepth = depth + 1;
-                        for (Object[] arr : subNodeValues) {
-                            ModelNode node = (ModelNode) arr[0];
-                            Map<String, Object> val = UtilGenerics.checkMap(arr[1]);
-                            //GenericPK pk = val.getPrimaryKey();
-                            //if (Debug.infoOn()) Debug.logInfo(" pk:" + pk,
-                            // module);
-                            String thisPkName = node.getPkName(context);
-                            String thisEntityId = (String) val.get(thisPkName);
-                            MapStack<String> newContext = MapStack.create(context);
-                            newContext.push();
-                            String nodeEntryName = node.getEntryName();
-                            if (!nodeEntryName.isEmpty()) {
-                                newContext.put(nodeEntryName, val);
-                            } else {
-                                newContext.putAll(val);
-                            }
-                            String targetEntityId = null;
-                            List<String> targetNodeTrail = UtilGenerics.checkList(context.get("targetNodeTrail"));
-                            if (newDepth < targetNodeTrail.size()) {
-                                targetEntityId = targetNodeTrail.get(newDepth);
-                            }
-                            if ((targetEntityId != null && targetEntityId.equals(thisEntityId))
-                                    || this.showPeers(newDepth, context)) {
-                                node.renderNodeString(writer, newContext, treeStringRenderer, newDepth);
-                            }
-                        }
-                    }
-                } catch (ScreenRenderException e) {
-                    String errMsg = "Error rendering included label with name [" + getName() + "] : " + e.toString();
-                    Debug.logError(e, errMsg, module);
-                    throw new RuntimeException(errMsg);
-                } catch (SAXException e) {
-                    String errMsg = "Error rendering included label with name [" + getName() + "] : " + e.toString();
-                    Debug.logError(e, errMsg, module);
-                    throw new RuntimeException(errMsg);
-                } catch (ParserConfigurationException e3) {
-                    String errMsg = "Error rendering included label with name [" + getName() + "] : " + e3.toString();
-                    Debug.logError(e3, errMsg, module);
-                    throw new RuntimeException(errMsg);
-                } catch (IOException e2) {
-                    String errMsg = "Error rendering included label with name [" + getName() + "] : " + e2.toString();
-                    Debug.logError(e2, errMsg, module);
-                    throw new RuntimeException(errMsg);
-                }
-                treeStringRenderer.renderNodeEnd(writer, context, this);
-                int removeIdx = currentNodeTrail.size() - 1;
-                if (removeIdx >= 0)
-                    currentNodeTrail.remove(removeIdx);
-            }
-        }
-
-        public boolean showPeers(int currentDepth, Map<String, Object> context) {
-            int trailSize = 0;
-            List<?> trail = UtilGenerics.checkList(context.get("targetNodeTrail"));
-            int openDepth = modelTree.getOpenDepth();
-            int postTrailOpenDepth = modelTree.getPostTrailOpenDepth();
-            if (trail != null)
-                trailSize = trail.size();
-
-            boolean showPeers = false;
-            String rStyle = getRenderStyle();
-            if (rStyle == null) {
-                showPeers = true;
-            } else if (!isFollowTrail()) {
-                showPeers = true;
-            } else if ((currentDepth < trailSize) && (rStyle != null)
-                    && (rStyle.equals("show-peers") || rStyle.equals("expand-collapse"))) {
-                showPeers = true;
-            } else if (openDepth >= currentDepth) {
-                showPeers = true;
-            } else {
-                int depthAfterTrail = currentDepth - trailSize;
-                if (depthAfterTrail >= 0 && depthAfterTrail <= postTrailOpenDepth)
-                    showPeers = true;
-            }
-            return showPeers;
-        }
-        
-        public List<ModelAction> getActions() {
-            return actions;
-        }
-
-        public ModelTreeCondition getCondition() {
-            return condition;
-        }
-
-        public Label getLabel() {
-            return label;
-        }
-
-        public Link getLink() {
-            return link;
-        }
-
-        public String getPkName() {
-            return pkName;
-        }
-
-        public FlexibleStringExpander getScreenLocationExdr() {
-            return screenLocationExdr;
-        }
-
-        public FlexibleStringExpander getScreenNameExdr() {
-            return screenNameExdr;
-        }
-
-        public String getShareScope() {
-            return shareScope;
-        }
-
-        public List<ModelSubNode> getSubNodeList() {
-            return subNodeList;
-        }
-
-        public FlexibleStringExpander getWrapStyleExdr() {
-            return wrapStyleExdr;
-        }
-
-        /**
-         * Models the &lt;image&gt; element.
-         * 
-         * @see <code>widget-tree.xsd</code>
-         */
-        public static class Image {
-
-            private final FlexibleStringExpander borderExdr;
-            private final FlexibleStringExpander heightExdr;
-            private final FlexibleStringExpander idExdr;
-            private final FlexibleStringExpander srcExdr;
-            private final FlexibleStringExpander styleExdr;
-            private final String urlMode;
-            private final FlexibleStringExpander widthExdr;
-
-            public Image(Element imageElement) {
-                this.borderExdr = FlexibleStringExpander
-                        .getInstance(UtilXml.checkEmpty(imageElement.getAttribute("border"), "0"));
-                this.heightExdr = FlexibleStringExpander.getInstance(imageElement.getAttribute("height"));
-                this.idExdr = FlexibleStringExpander.getInstance(imageElement.getAttribute("id"));
-                this.srcExdr = FlexibleStringExpander.getInstance(imageElement.getAttribute("src"));
-                this.styleExdr = FlexibleStringExpander.getInstance(imageElement.getAttribute("style"));
-                this.urlMode = UtilXml.checkEmpty(imageElement.getAttribute("url-mode"), "content");
-                this.widthExdr = FlexibleStringExpander.getInstance(imageElement.getAttribute("width"));
-            }
-
-            public String getBorder(Map<String, Object> context) {
-                return this.borderExdr.expandString(context);
-            }
-
-            public String getHeight(Map<String, Object> context) {
-                return this.heightExdr.expandString(context);
-            }
-
-            public String getId(Map<String, Object> context) {
-                return this.idExdr.expandString(context);
-            }
-
-            public String getSrc(Map<String, Object> context) {
-                return this.srcExdr.expandString(context);
-            }
-
-            public String getStyle(Map<String, Object> context) {
-                return this.styleExdr.expandString(context);
-            }
-
-            public String getUrlMode() {
-                return this.urlMode;
-            }
-
-            public String getWidth(Map<String, Object> context) {
-                return this.widthExdr.expandString(context);
-            }
-
-            public void renderImageString(Appendable writer, Map<String, Object> context, TreeStringRenderer treeStringRenderer) {
-                try {
-                    treeStringRenderer.renderImage(writer, context, this);
-                } catch (IOException e) {
-                    String errMsg = "Error rendering image with id [" + getId(context) + "]: " + e.toString();
-                    Debug.logError(e, errMsg, module);
-                    throw new RuntimeException(errMsg);
-                }
-            }
-        }
-
-        /**
-         * Models the &lt;label&gt; element.
-         * 
-         * @see <code>widget-tree.xsd</code>
-         */
-        public static final class Label {
-            private final FlexibleStringExpander idExdr;
-            private final FlexibleStringExpander styleExdr;
-            private final FlexibleStringExpander textExdr;
-
-            public Label(Element labelElement) {
-                String textAttr = labelElement.getAttribute("text");
-                String pcdata = UtilXml.checkEmpty(UtilXml.elementValue(labelElement), "");
-                this.textExdr = FlexibleStringExpander.getInstance(textAttr + pcdata);
-                this.idExdr = FlexibleStringExpander.getInstance(labelElement.getAttribute("id"));
-                this.styleExdr = FlexibleStringExpander.getInstance(labelElement.getAttribute("style"));
-            }
-
-            public String getId(Map<String, Object> context) {
-                return this.idExdr.expandString(context);
-            }
-
-            public String getStyle(Map<String, Object> context) {
-                return this.styleExdr.expandString(context);
-            }
-
-            public String getText(Map<String, Object> context) {
-                String text = this.textExdr.expandString(context);
-                // FIXME: Encoding should be done by the renderer, not by the model.
-                UtilCodec.SimpleEncoder simpleEncoder = (UtilCodec.SimpleEncoder) context.get("simpleEncoder");
-                if (simpleEncoder != null) {
-                    text = simpleEncoder.encode(text);
-                }
-                return text;
-            }
-
-            public void renderLabelString(Appendable writer, Map<String, Object> context, TreeStringRenderer treeStringRenderer) {
-                try {
-                    treeStringRenderer.renderLabel(writer, context, this);
-                } catch (IOException e) {
-                    String errMsg = "Error rendering label with id [" + getId(context) + "]: " + e.toString();
-                    Debug.logError(e, errMsg, module);
-                    throw new RuntimeException(errMsg);
-                }
-            }
-
-            public FlexibleStringExpander getIdExdr() {
-                return idExdr;
-            }
-
-            public FlexibleStringExpander getStyleExdr() {
-                return styleExdr;
-            }
-
-            public FlexibleStringExpander getTextExdr() {
-                return textExdr;
-            }
-        }
-
-        /**
-         * Models the &lt;link&gt; element.
-         * 
-         * @see <code>widget-tree.xsd</code>
-         */
-        public static class Link {
-            private final boolean encode;
-            private final boolean fullPath;
-            private final FlexibleStringExpander idExdr;
-            private final Image image;
-            private final String linkType;
-            private final FlexibleStringExpander nameExdr;
-            private final List<Parameter> parameterList;
-            private final FlexibleStringExpander prefixExdr;
-            private final boolean secure;
-            private final FlexibleStringExpander styleExdr;
-            private final FlexibleStringExpander targetExdr;
-            private final FlexibleStringExpander targetWindowExdr;
-            private final FlexibleStringExpander textExdr;
-            private final FlexibleStringExpander titleExdr;
-            private final String urlMode;
-
-            public Link(Element linkElement) {
-                this.encode = "true".equals(linkElement.getAttribute("encode"));
-                this.fullPath = "true".equals(linkElement.getAttribute("full-path"));
-                this.idExdr = FlexibleStringExpander.getInstance(linkElement.getAttribute("id"));
-                Element imageElement = UtilXml.firstChildElement(linkElement, "image");
-                if (imageElement != null) {
-                    this.image = new Image(imageElement);
-                } else {
-                    this.image = null;
-                }
-                this.linkType = linkElement.getAttribute("link-type");
-                this.nameExdr = FlexibleStringExpander.getInstance(linkElement.getAttribute("name"));
-                List<? extends Element> parameterElementList = UtilXml.childElementList(linkElement, "parameter");
-                if (!parameterElementList.isEmpty()) {
-                    List<Parameter> parameterList = new ArrayList<Parameter>(parameterElementList.size());
-                    for (Element parameterElement : parameterElementList) {
-                        parameterList.add(new Parameter(parameterElement));
-                    }
-                    this.parameterList = Collections.unmodifiableList(parameterList);
-                } else {
-                    this.parameterList = Collections.emptyList();
-                }
-                this.prefixExdr = FlexibleStringExpander.getInstance(linkElement.getAttribute("prefix"));
-                this.secure = "true".equals(linkElement.getAttribute("secure"));
-                this.styleExdr = FlexibleStringExpander.getInstance(linkElement.getAttribute("style"));
-                this.targetExdr = FlexibleStringExpander.getInstance(linkElement.getAttribute("target"));
-                this.targetWindowExdr = FlexibleStringExpander.getInstance(linkElement.getAttribute("target-window"));
-                this.textExdr = FlexibleStringExpander.getInstance(linkElement.getAttribute("text"));
-                this.titleExdr = FlexibleStringExpander.getInstance(linkElement.getAttribute("title"));
-                this.urlMode = UtilXml.checkEmpty(linkElement.getAttribute("link-type"), "intra-app");
-            }
-
-            // FIXME: Using a widget model in this way is an ugly hack.
-            public Link(String style, String target, String text) {
-                this.encode = false;
-                this.fullPath = false;
-                this.idExdr = FlexibleStringExpander.getInstance("");
-                this.image = null;
-                this.linkType = "";
-                this.nameExdr = FlexibleStringExpander.getInstance("");
-                this.parameterList = Collections.emptyList();
-                this.prefixExdr = FlexibleStringExpander.getInstance("");
-                this.secure = false;
-                this.styleExdr = FlexibleStringExpander.getInstance(style);
-                this.targetExdr = FlexibleStringExpander.getInstance(target);
-                this.targetWindowExdr = FlexibleStringExpander.getInstance("");
-                this.textExdr = FlexibleStringExpander.getInstance(text);
-                this.titleExdr = FlexibleStringExpander.getInstance("");
-                this.urlMode = "intra-app";
-            }
-
-            public boolean getEncode() {
-                return this.encode;
-            }
-
-            public boolean getFullPath() {
-                return this.fullPath;
-            }
-
-            public String getId(Map<String, Object> context) {
-                return this.idExdr.expandString(context);
-            }
-
-            public Image getImage() {
-                return this.image;
-            }
-
-            public String getLinkType() {
-                return this.linkType;
-            }
-
-            public String getName(Map<String, Object> context) {
-                return this.nameExdr.expandString(context);
-            }
-
-            public Map<String, String> getParameterMap(Map<String, Object> context) {
-                Map<String, String> fullParameterMap = new HashMap<String, String>();
-                /* leaving this here... may want to add it at some point like the hyperlink element:
-                Map<String, String> addlParamMap = this.parametersMapAcsr.get(context);
-                if (addlParamMap != null) {
-                    fullParameterMap.putAll(addlParamMap);
-                }
-                */
-                for (CommonWidgetModels.Parameter parameter : this.parameterList) {
-                    fullParameterMap.put(parameter.getName(), parameter.getValue(context));
-                }
-                return fullParameterMap;
-            }
-
-            public String getPrefix(Map<String, Object> context) {
-                return this.prefixExdr.expandString(context);
-            }
-
-            public boolean getSecure() {
-                return this.secure;
-            }
-
-            public String getStyle(Map<String, Object> context) {
-                return this.styleExdr.expandString(context);
-            }
-
-            public String getTarget(Map<String, Object> context) {
-                UtilCodec.SimpleEncoder simpleEncoder = (UtilCodec.SimpleEncoder) context.get("simpleEncoder");
-                if (simpleEncoder != null) {
-                    return this.targetExdr.expandString(UtilCodec.HtmlEncodingMapWrapper.getHtmlEncodingMapWrapper(context,
-                            simpleEncoder));
-                } else {
-                    return this.targetExdr.expandString(context);
-                }
-            }
-
-            public String getTargetWindow(Map<String, Object> context) {
-                return this.targetWindowExdr.expandString(context);
-            }
-
-            public String getText(Map<String, Object> context) {
-                String text = this.textExdr.expandString(context);
-                // FIXME: Encoding should be done by the renderer, not by the model.
-                UtilCodec.SimpleEncoder simpleEncoder = (UtilCodec.SimpleEncoder) context.get("simpleEncoder");
-                if (simpleEncoder != null) {
-                    text = simpleEncoder.encode(text);
-                }
-                return text;
-            }
-
-            public String getTitle(Map<String, Object> context) {
-                String title = this.titleExdr.expandString(context);
-                // FIXME: Encoding should be done by the renderer, not by the model.
-                UtilCodec.SimpleEncoder simpleEncoder = (UtilCodec.SimpleEncoder) context.get("simpleEncoder");
-                if (simpleEncoder != null) {
-                    title = simpleEncoder.encode(title);
-                }
-                return title;
-            }
-
-            public String getUrlMode() {
-                return this.urlMode;
-            }
-
-            public void renderLinkString(Appendable writer, Map<String, Object> context, TreeStringRenderer treeStringRenderer) {
-                try {
-                    treeStringRenderer.renderLink(writer, context, this);
-                } catch (IOException e) {
-                    String errMsg = "Error rendering link with id [" + getId(context) + "]: " + e.toString();
-                    Debug.logError(e, errMsg, module);
-                    throw new RuntimeException(errMsg);
-                }
-            }
-
-            public FlexibleStringExpander getIdExdr() {
-                return idExdr;
-            }
-
-            public FlexibleStringExpander getNameExdr() {
-                return nameExdr;
-            }
-
-            public List<Parameter> getParameterList() {
-                return parameterList;
-            }
-
-            public FlexibleStringExpander getPrefixExdr() {
-                return prefixExdr;
-            }
-
-            public FlexibleStringExpander getStyleExdr() {
-                return styleExdr;
-            }
-
-            public FlexibleStringExpander getTargetExdr() {
-                return targetExdr;
-            }
-
-            public FlexibleStringExpander getTargetWindowExdr() {
-                return targetWindowExdr;
-            }
-
-            public FlexibleStringExpander getTextExdr() {
-                return textExdr;
-            }
-
-            public FlexibleStringExpander getTitleExdr() {
-                return titleExdr;
-            }
-        }
-
-        /**
-         * Models the &lt;sub-node&gt; element.
-         * 
-         * @see <code>widget-tree.xsd</code>
-         */
-        public static class ModelSubNode extends ModelWidget {
-
-            private final List<ModelAction> actions;
-            private final FlexibleStringExpander nodeNameExdr;
-            private final ModelNode rootNode;
-            private final String iteratorKey;
-
-            public ModelSubNode(Element subNodeElement, ModelNode modelNode) {
-                super(subNodeElement);
-                this.rootNode = modelNode;
-                this.nodeNameExdr = FlexibleStringExpander.getInstance(subNodeElement.getAttribute("node-name"));
-                ArrayList<ModelAction> actions = new ArrayList<ModelAction>();
-                // FIXME: Validate child elements, should be only one of actions, entity-and, entity-condition, service, script.
-                Element actionsElement = UtilXml.firstChildElement(subNodeElement, "actions");
-                if (actionsElement != null) {
-                    actions.addAll(ModelTreeAction.readSubNodeActions(this, actionsElement));
-                }
-                Element actionElement = UtilXml.firstChildElement(subNodeElement, "entity-and");
-                if (actionElement != null) {
-                    actions.add(new ModelTreeAction.EntityAnd(this, actionElement));
-                }
-                actionElement = UtilXml.firstChildElement(subNodeElement, "service");
-                if (actionElement != null) {
-                    actions.add(new ModelTreeAction.Service(this, actionElement));
-                }
-                actionElement = UtilXml.firstChildElement(subNodeElement, "entity-condition");
-                if (actionElement != null) {
-                    actions.add(new ModelTreeAction.EntityCondition(this, actionElement));
-                }
-                actionElement = UtilXml.firstChildElement(subNodeElement, "script");
-                if (actionElement != null) {
-                    actions.add(new ModelTreeAction.Script(this, actionElement));
-                }
-                actions.trimToSize();
-                this.actions = Collections.unmodifiableList(actions);
-                this.iteratorKey = this.rootNode.getName().concat(".").concat(this.nodeNameExdr.getOriginal())
-                        .concat(".ITERATOR");
-            }
-
-            @Override
-            public void accept(ModelWidgetVisitor visitor) throws Exception {
-                visitor.visit(this);
-            }
-
-            public List<ModelAction> getActions() {
-                return actions;
-            }
-
-            @SuppressWarnings("unchecked")
-            public ListIterator<? extends Map<String, ? extends Object>> getListIterator(Map<String, Object> context) {
-                return (ListIterator<? extends Map<String, ? extends Object>>) context.get(this.iteratorKey);
-            }
-
-            public ModelTree.ModelNode getNode() {
-                return this.rootNode;
-            }
-
-            public String getNodeName(Map<String, Object> context) {
-                return this.nodeNameExdr.expandString(context);
-            }
-
-            public FlexibleStringExpander getNodeNameExdr() {
-                return nodeNameExdr;
-            }
-
-            public void setListIterator(ListIterator<? extends Map<String, ? extends Object>> iter, Map<String, Object> context) {
-                context.put(this.iteratorKey, iter);
-            }
-        }
-    }
-}
+/*******************************************************************************

+ * Licensed to the Apache Software Foundation (ASF) under one

+ * or more contributor license agreements.  See the NOTICE file

+ * distributed with this work for additional information

+ * regarding copyright ownership.  The ASF licenses this file

+ * to you under the Apache License, Version 2.0 (the

+ * "License"); you may not use this file except in compliance

+ * with the License.  You may obtain a copy of the License at

+ *

+ * http://www.apache.org/licenses/LICENSE-2.0

+ *

+ * Unless required by applicable law or agreed to in writing,

+ * software distributed under the License is distributed on an

+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY

+ * KIND, either express or implied.  See the License for the

+ * specific language governing permissions and limitations

+ * under the License.

+ *******************************************************************************/

+package org.ofbiz.widget.model;

+

+import java.io.IOException;

+import java.util.ArrayList;

+import java.util.Collections;

+import java.util.HashMap;

+import java.util.Iterator;

+import java.util.LinkedList;

+import java.util.List;

+import java.util.ListIterator;

+import java.util.Map;

+

+import javax.servlet.http.HttpServletRequest;

+import javax.xml.parsers.ParserConfigurationException;

+

+import org.ofbiz.base.util.Debug;

+import org.ofbiz.base.util.GeneralException;

+import org.ofbiz.base.util.StringUtil;

+import org.ofbiz.base.util.UtilCodec;

+import org.ofbiz.base.util.UtilGenerics;

+import org.ofbiz.base.util.UtilHttp;

+import org.ofbiz.base.util.UtilValidate;

+import org.ofbiz.base.util.UtilXml;

+import org.ofbiz.base.util.collections.MapStack;

+import org.ofbiz.base.util.string.FlexibleStringExpander;

+import org.ofbiz.entity.Delegator;

+import org.ofbiz.entity.GenericEntityException;

+import org.ofbiz.entity.GenericValue;

+import org.ofbiz.entity.model.ModelEntity;

+import org.ofbiz.entity.model.ModelField;

+import org.ofbiz.entity.util.EntityListIterator;

+import org.ofbiz.entity.util.EntityQuery;

+import org.ofbiz.widget.WidgetWorker;

+import org.ofbiz.widget.model.CommonWidgetModels.Parameter;

+import org.ofbiz.widget.renderer.ScreenRenderException;

+import org.ofbiz.widget.renderer.ScreenStringRenderer;

+import org.ofbiz.widget.renderer.TreeStringRenderer;

+import org.w3c.dom.Element;

+import org.xml.sax.SAXException;

+

+/**

+ * Models the &lt;tree&gt; element.

+ * 

+ * @see <code>widget-tree.xsd</code>

+ */

+@SuppressWarnings("serial")

+public class ModelTree extends ModelWidget {

+

+    /*

+     * ----------------------------------------------------------------------- *

+     *                     DEVELOPERS PLEASE READ

+     * ----------------------------------------------------------------------- *

+     * 

+     * This model is intended to be a read-only data structure that represents

+     * an XML element. Outside of object construction, the class should not

+     * have any behaviors.

+     * 

+     * Instances of this class will be shared by multiple threads - therefore

+     * it is immutable. DO NOT CHANGE THE OBJECT'S STATE AT RUN TIME!

+     * 

+     */

+

+    public static final String module = ModelTree.class.getName();

+

+    private final String defaultEntityName;

+    private final String defaultRenderStyle;

+    private final FlexibleStringExpander defaultWrapStyleExdr;

+    private final FlexibleStringExpander expandCollapseRequestExdr;

+    private final boolean forceChildCheck;

+    private final String location;

+    private final Map<String, ModelNode> nodeMap;

+    private final int openDepth;

+    private final int postTrailOpenDepth;

+    private final String rootNodeName;

+    private final FlexibleStringExpander trailNameExdr;

+

+    public ModelTree(Element treeElement, String location) {

+        super(treeElement);

+        this.location = location;

+        this.rootNodeName = treeElement.getAttribute("root-node-name");

+        String defaultRenderStyle = UtilXml.checkEmpty(treeElement.getAttribute("default-render-style"), "simple");

+        // A temporary hack to accommodate those who might still be using "render-style" instead of "default-render-style"

+        if (defaultRenderStyle.isEmpty() || defaultRenderStyle.equals("simple")) {

+            String rStyle = treeElement.getAttribute("render-style");

+            if (!rStyle.isEmpty())

+                defaultRenderStyle = rStyle;

+        }

+        this.defaultRenderStyle = defaultRenderStyle;

+        this.defaultWrapStyleExdr = FlexibleStringExpander.getInstance(treeElement.getAttribute("default-wrap-style"));

+        this.expandCollapseRequestExdr = FlexibleStringExpander.getInstance(treeElement.getAttribute("expand-collapse-request"));

+        this.trailNameExdr = FlexibleStringExpander.getInstance(UtilXml.checkEmpty(treeElement.getAttribute("trail-name"),

+                "trail"));

+        this.forceChildCheck = !"false".equals(treeElement.getAttribute("force-child-check"));

+        this.defaultEntityName = treeElement.getAttribute("entity-name");

+        int openDepth = 0;

+        if (treeElement.hasAttribute("open-depth")) {

+            try {

+                openDepth = Integer.parseInt(treeElement.getAttribute("open-depth"));

+            } catch (NumberFormatException e) {

+                throw new IllegalArgumentException("Invalid open-depth attribute value for the tree definition with name: "

+                        + getName());

+            }

+        }

+        this.openDepth = openDepth;

+        int postTrailOpenDepth = 999;

+        if (treeElement.hasAttribute("post-trail-open-depth")) {

+            try {

+                postTrailOpenDepth = Integer.parseInt(treeElement.getAttribute("post-trail-open-depth"));

+            } catch (NumberFormatException e) {

+                throw new IllegalArgumentException(

+                        "Invalid post-trail-open-depth attribute value for the tree definition with name: " + getName());

+            }

+        }

+        this.postTrailOpenDepth = postTrailOpenDepth;

+        List<? extends Element> nodeElements = UtilXml.childElementList(treeElement, "node");

+        if (nodeElements.size() == 0) {

+            throw new IllegalArgumentException("No node elements found for the tree definition with name: " + getName());

+        }

+        Map<String, ModelNode> nodeMap = new HashMap<String, ModelNode>();

+        for (Element nodeElementEntry : UtilXml.childElementList(treeElement, "node")) {

+            ModelNode node = new ModelNode(nodeElementEntry, this);

+            String nodeName = node.getName();

+            nodeMap.put(nodeName, node);

+        }

+        this.nodeMap = Collections.unmodifiableMap(nodeMap);

+    }

+

+    @Override

+    public void accept(ModelWidgetVisitor visitor) throws Exception {

+        visitor.visit(this);

+    }

+

+    @Override

+    public String getBoundaryCommentName() {

+        return location + "#" + getName();

+    }

+

+    public String getDefaultEntityName() {

+        return this.defaultEntityName;

+    }

+

+    public String getDefaultPkName(Map<String, Object> context) {

+        ModelEntity modelEntity = WidgetWorker.getDelegator(context).getModelEntity(this.defaultEntityName);

+        if (modelEntity.getPksSize() == 1) {

+            ModelField modelField = modelEntity.getOnlyPk();

+            return modelField.getName();

+        }

+        return null;

+    }

+

+    public String getExpandCollapseRequest(Map<String, Object> context) {

+        String expColReq = this.expandCollapseRequestExdr.expandString(context);

+        if (UtilValidate.isEmpty(expColReq)) {

+            HttpServletRequest request = (HttpServletRequest) context.get("request");

+            String s1 = request.getRequestURI();

+            int pos = s1.lastIndexOf("/");

+            if (pos >= 0)

+                expColReq = s1.substring(pos + 1);

+            else

+                expColReq = s1;

+        }

+        //append also the request parameters

+        Map<String, Object> paramMap = UtilGenerics.checkMap(context.get("requestParameters"));

+        if (UtilValidate.isNotEmpty(paramMap)) {

+            Map<String, Object> requestParameters = new HashMap<String, Object>(paramMap);

+            requestParameters.remove(this.getTrailName(context));

+            if (UtilValidate.isNotEmpty(requestParameters)) {

+                String queryString = UtilHttp.urlEncodeArgs(requestParameters, false);

+                if (expColReq.indexOf("?") < 0) {

+                    expColReq += "?";

+                } else {

+                    expColReq += "&amp;";

+                }

+                expColReq += queryString;

+            }

+        }

+        return expColReq;

+    }

+

+    public int getOpenDepth() {

+        return openDepth;

+    }

+

+    public int getPostTrailOpenDepth() {

+        return postTrailOpenDepth;

+    }

+

+    public String getRenderStyle() {

+        return this.defaultRenderStyle;

+    }

+

+    public String getRootNodeName() {

+        return rootNodeName;

+    }

+

+    public String getTrailName(Map<String, Object> context) {

+        return this.trailNameExdr.expandString(context);

+    }

+

+    public String getWrapStyle(Map<String, Object> context) {

+        return this.defaultWrapStyleExdr.expandString(context);

+    }

+

+    /**

+     * Renders this model.

+     *

+     * @param writer

+     * @param context

+     * @param treeStringRenderer

+     */

+    @SuppressWarnings("rawtypes")

+    public void renderTreeString(Appendable writer, Map<String, Object> context, TreeStringRenderer treeStringRenderer)

+            throws GeneralException {

+        Map<String, Object> parameters = UtilGenerics.checkMap(context.get("parameters"));

+        ModelNode node = nodeMap.get(rootNodeName);

+        String trailName = trailNameExdr.expandString(context);

+        String treeString = (String) context.get(trailName);

+        if (UtilValidate.isEmpty(treeString)) {

+            treeString = (String) parameters.get(trailName);

+        }

+        List<String> trail = null;

+        if (UtilValidate.isNotEmpty(treeString)) {

+            trail = StringUtil.split(treeString, "|");

+            if (UtilValidate.isEmpty(trail))

+                throw new RuntimeException("Tree 'trail' value is empty.");

+            context.put("rootEntityId", trail.get(0));

+            context.put(getDefaultPkName(context), trail.get(0));

+        } else {

+            trail = new LinkedList<String>();

+        }

+        context.put("targetNodeTrail", trail);

+        context.put("currentNodeTrail", new LinkedList());

+        try {

+            node.renderNodeString(writer, context, treeStringRenderer, 0);

+        } catch (IOException e2) {

+            String errMsg = "Error rendering included label with name [" + getName() + "] : " + e2.toString();

+            Debug.logError(e2, errMsg, module);

+            throw new RuntimeException(errMsg);

+        }

+

+    }

+

+    public String getDefaultRenderStyle() {

+        return defaultRenderStyle;

+    }

+

+    public FlexibleStringExpander getDefaultWrapStyleExdr() {

+        return defaultWrapStyleExdr;

+    }

+

+    public FlexibleStringExpander getExpandCollapseRequestExdr() {

+        return expandCollapseRequestExdr;

+    }

+

+    public boolean getForceChildCheck() {

+        return forceChildCheck;

+    }

+

+    public String getLocation() {

+        return location;

+    }

+

+    public Map<String, ModelNode> getNodeMap() {

+        return nodeMap;

+    }

+

+    public FlexibleStringExpander getTrailNameExdr() {

+        return trailNameExdr;

+    }

+

+    /**

+     * Models the &lt;node&gt; element.

+     * 

+     * @see <code>widget-tree.xsd</code>

+     */

+    public static class ModelNode extends ModelWidget {

+

+        private final List<ModelAction> actions;

+        // TODO: Make this a generic condition object.

+        private final ModelTreeCondition condition;

+        private final String entityName;

+        private final String entryName;

+        private final String expandCollapseStyle;

+        private final Label label;

+        private final Link link;

+        private final ModelTree modelTree;

+        private final String pkName;

+        private final String renderStyle;

+        private final FlexibleStringExpander screenLocationExdr;

+        private final FlexibleStringExpander screenNameExdr;

+        private final String shareScope;

+        private final List<ModelSubNode> subNodeList;

+        private final FlexibleStringExpander wrapStyleExdr;

+

+        public ModelNode(Element nodeElement, ModelTree modelTree) {

+            super(nodeElement);

+            this.modelTree = modelTree;

+            this.expandCollapseStyle = nodeElement.getAttribute("expand-collapse-style");

+            this.wrapStyleExdr = FlexibleStringExpander.getInstance(nodeElement.getAttribute("wrap-style"));

+            this.renderStyle = nodeElement.getAttribute("render-style");

+            this.entryName = nodeElement.getAttribute("entry-name");

+            this.entityName = nodeElement.getAttribute("entity-name");

+            this.pkName = nodeElement.getAttribute("join-field-name");

+            ArrayList<ModelAction> actions = new ArrayList<ModelAction>();

+            // FIXME: Validate child elements, should be only one of actions, entity-one, service, script.

+            Element actionsElement = UtilXml.firstChildElement(nodeElement, "actions");

+            if (actionsElement != null) {

+                actions.addAll(ModelTreeAction.readNodeActions(this, actionsElement));

+            }

+            Element actionElement = UtilXml.firstChildElement(nodeElement, "entity-one");

+            if (actionElement != null) {

+                actions.add(new AbstractModelAction.EntityOne(this, actionElement));

+            }

+            actionElement = UtilXml.firstChildElement(nodeElement, "service");

+            if (actionElement != null) {

+                actions.add(new ModelTreeAction.Service(this, actionElement));

+            }

+            actionElement = UtilXml.firstChildElement(nodeElement, "script");

+            if (actionElement != null) {

+                actions.add(new ModelTreeAction.Script(this, actionElement));

+            }

+            actions.trimToSize();

+            this.actions = Collections.unmodifiableList(actions);

+            Element screenElement = UtilXml.firstChildElement(nodeElement, "include-screen");

+            if (screenElement != null) {

+                this.screenNameExdr = FlexibleStringExpander.getInstance(screenElement.getAttribute("name"));

+                this.screenLocationExdr = FlexibleStringExpander.getInstance(screenElement.getAttribute("location"));

+                this.shareScope = screenElement.getAttribute("share-scope");

+            } else {

+                this.screenNameExdr = FlexibleStringExpander.getInstance("");

+                this.screenLocationExdr = FlexibleStringExpander.getInstance("");

+                this.shareScope = "";

+            }

+            Element labelElement = UtilXml.firstChildElement(nodeElement, "label");

+            if (labelElement != null) {

+                this.label = new Label(labelElement);

+            } else {

+                this.label = null;

+            }

+            Element linkElement = UtilXml.firstChildElement(nodeElement, "link");

+            if (linkElement != null) {

+                this.link = new Link(linkElement);

+            } else {

+                this.link = null;

+            }

+            Element conditionElement = UtilXml.firstChildElement(nodeElement, "condition");

+            if (conditionElement != null) {

+                this.condition = new ModelTreeCondition(modelTree, conditionElement);

+            } else {

+                this.condition = null;

+            }

+            List<? extends Element> nodeElements = UtilXml.childElementList(nodeElement, "sub-node");

+            if (!nodeElements.isEmpty()) {

+                List<ModelSubNode> subNodeList = new ArrayList<ModelSubNode>();

+                for (Element subNodeElementEntry : nodeElements) {

+                    ModelSubNode subNode = new ModelSubNode(subNodeElementEntry, this);

+                    subNodeList.add(subNode);

+                }

+                this.subNodeList = Collections.unmodifiableList(subNodeList);

+            } else {

+                this.subNodeList = Collections.emptyList();

+            }

+        }

+

+        @Override

+        public void accept(ModelWidgetVisitor visitor) throws Exception {

+            visitor.visit(this);

+        }

+

+        private List<Object[]> getChildren(Map<String, Object> context) {

+            List<Object[]> subNodeValues = new ArrayList<Object[]>();

+            for (ModelSubNode subNode : subNodeList) {

+                String nodeName = subNode.getNodeName(context);

+                ModelNode node = modelTree.nodeMap.get(nodeName);

+                List<ModelAction> subNodeActions = subNode.getActions();

+                //if (Debug.infoOn()) Debug.logInfo(" context.currentValue:" + context.get("currentValue"), module);

+                AbstractModelAction.runSubActions(subNodeActions, context);

+                // List dataFound = (List)context.get("dataFound");

+                Iterator<? extends Map<String, ? extends Object>> dataIter = subNode.getListIterator(context);

+                if (dataIter instanceof EntityListIterator) {

+                    EntityListIterator eli = (EntityListIterator) dataIter;

+                    Map<String, Object> val = null;

+                    while ((val = eli.next()) != null) {

+                        Object[] arr = { node, val };

+                        subNodeValues.add(arr);

+                    }

+                    try {

+                        eli.close();

+                    } catch (GenericEntityException e) {

+                        Debug.logError(e, module);

+                        throw new RuntimeException(e.getMessage());

+                    }

+                } else if (dataIter != null) {

+                    while (dataIter.hasNext()) {

+                        Map<String, ? extends Object> val = dataIter.next();

+                        Object[] arr = { node, val };

+                        subNodeValues.add(arr);

+                    }

+                }

+            }

+            return subNodeValues;

+        }

+

+        public String getEntityName() {

+            if (!this.entityName.isEmpty()) {

+                return this.entityName;

+            } else {

+                return this.modelTree.getDefaultEntityName();

+            }

+        }

+

+        public String getEntryName() {

+            return this.entryName;

+        }

+

+        public String getExpandCollapseStyle() {

+            return expandCollapseStyle;

+        }

+

+        public ModelTree getModelTree() {

+            return this.modelTree;

+        }

+

+        public String getPkName(Map<String, Object> context) {

+            if (UtilValidate.isNotEmpty(this.pkName)) {

+                return this.pkName;

+            } else {

+                return this.modelTree.getDefaultPkName(context);

+            }

+        }

+

+        public String getRenderStyle() {

+            if (this.renderStyle.isEmpty())

+                return modelTree.getRenderStyle();

+            return this.renderStyle;

+        }

+

+        public String getWrapStyle(Map<String, Object> context) {

+            String val = this.wrapStyleExdr.expandString(context);

+            if (val.isEmpty()) {

+                val = this.modelTree.getWrapStyle(context);

+            }

+            return val;

+        }

+

+        public boolean hasChildren(Map<String, Object> context) {

+            List<Object[]> subNodeValues = getChildren(context);

+            boolean hasChildren = false;

+            Long nodeCount = null;

+            String countFieldName = "childBranchCount";

+            Object obj = null;

+            if (!this.entryName.isEmpty()) {

+                Map<String, Object> map = UtilGenerics.cast(context.get(this.entryName));

+                if (map instanceof GenericValue) {

+                    ModelEntity modelEntity = ((GenericValue) map).getModelEntity();

+                    if (modelEntity.isField(countFieldName)) {

+                        obj = map.get(countFieldName);

+                    }

+                }

+            } else {

+                obj = context.get(countFieldName);

+            }

+            if (obj != null) {

+                nodeCount = (Long) obj;

+            }

+            String entName = this.getEntityName();

+            Delegator delegator = WidgetWorker.getDelegator(context);

+            ModelEntity modelEntity = delegator.getModelEntity(entName);

+            ModelField modelField = null;

+            if (modelEntity.isField(countFieldName)) {

+                modelField = modelEntity.getField(countFieldName);

+            }

+            if (nodeCount == null && modelField != null || this.modelTree.forceChildCheck) {

+                getChildren(context);

+                /*

+                String id = (String)context.get(modelTree.getPkName());

+                if (UtilValidate.isNotEmpty(id)) {

+                    try {

+                        int leafCount = ContentManagementWorker.updateStatsTopDown(delegator, id, UtilMisc.toList("SUB_CONTENT", "PUBLISH_LINK"));

+                        GenericValue entity = delegator.findOne(entName, UtilMisc.toMap(modelTree.getPkName(), id), true);

+                        obj = entity.get("childBranchCount");

+                       if (obj != null)

+                           nodeCount = (Long)obj;

+                    } catch (GenericEntityException e) {

+                        Debug.logError(e, module);

+                       throw new RuntimeException(e.getMessage());

+                    }

+                }

+                */

+                nodeCount = Long.valueOf(subNodeValues.size());

+                String pkName = this.getPkName(context);

+                String id = null;

+                if (!this.entryName.isEmpty()) {

+                    id = UtilGenerics.<Map<String, String>> cast(context.get(this.entryName)).get(pkName);

+                } else {

+                    id = (String) context.get(pkName);

+                }

+                try {

+                    if (id != null && modelEntity.getPksSize() == 1) {

+                        GenericValue entity = EntityQuery.use(delegator).from(entName).where(pkName, id).queryOne();

+                        if (modelEntity.isField("childBranchCount")) {

+                            entity.put("childBranchCount", nodeCount);

+                            entity.store();

+                        }

+                    }

+                } catch (GenericEntityException e) {

+                    Debug.logError(e, module);

+                    throw new RuntimeException(e.getMessage());

+                }

+            } else if (nodeCount == null) {

+                getChildren(context);

+                if (subNodeValues != null) {

+                    nodeCount = Long.valueOf(subNodeValues.size());

+                }

+            }

+            if (nodeCount != null && nodeCount.intValue() > 0) {

+                hasChildren = true;

+            }

+            return hasChildren;

+        }

+

+        public boolean isExpandCollapse() {

+            boolean isExpCollapse = false;

+            String rStyle = getRenderStyle();

+            if (rStyle != null && rStyle.equals("expand-collapse"))

+                isExpCollapse = true;

+            return isExpCollapse;

+        }

+

+        public boolean isFollowTrail() {

+            boolean isFollowTrail = false;

+            String rStyle = getRenderStyle();

+            if (rStyle != null && (rStyle.equals("follow-trail") || rStyle.equals("show-peers") || rStyle.equals("follow-trail"))) {

+                isFollowTrail = true;

+            }

+            return isFollowTrail;

+        }

+

+        public boolean isRootNode() {

+            return getName().equals(modelTree.getRootNodeName());

+        }

+

+        public void renderNodeString(Appendable writer, Map<String, Object> context, TreeStringRenderer treeStringRenderer,

+                int depth) throws IOException, GeneralException {

+            boolean passed = true;

+            if (this.condition != null) {

+                if (!this.condition.getCondition().eval(context)) {

+                    passed = false;

+                }

+            }

+            //Debug.logInfo("in ModelMenu, name:" + this.getName(), module);

+            if (passed) {

+                List<String> currentNodeTrail = UtilGenerics.toList(context.get("currentNodeTrail"));

+                context.put("processChildren", Boolean.TRUE);

+                // this action will usually obtain the "current" entity

+                ModelTreeAction.runSubActions(this.actions, context);

+                String pkName = getPkName(context);

+                String id = null;

+                if (!this.entryName.isEmpty()) {

+                    id = UtilGenerics.<Map<String, String>> cast(context.get(this.entryName)).get(pkName);

+                } else {

+                    id = (String) context.get(pkName);

+                }

+                currentNodeTrail.add(id);

+                treeStringRenderer.renderNodeBegin(writer, context, this, depth);

+                //if (Debug.infoOn()) Debug.logInfo(" context:" +

+                // context.entrySet(), module);

+                try {

+                    String screenName = null;

+                    if (!screenNameExdr.isEmpty())

+                        screenName = screenNameExdr.expandString(context);

+                    String screenLocation = null;

+                    if (!screenLocationExdr.isEmpty())

+                        screenLocation = screenLocationExdr.expandString(context);

+                    if (screenName != null && screenLocation != null) {

+                        ScreenStringRenderer screenStringRenderer = treeStringRenderer.getScreenStringRenderer(context);

+                        ModelScreen modelScreen = ScreenFactory.getScreenFromLocation(screenLocation, screenName);

+                        modelScreen.renderScreenString(writer, context, screenStringRenderer);

+                    }

+                    if (label != null) {

+                        label.renderLabelString(writer, context, treeStringRenderer);

+                    }

+                    if (link != null) {

+                        link.renderLinkString(writer, context, treeStringRenderer);

+                    }

+                    treeStringRenderer.renderLastElement(writer, context, this);

+                    Boolean processChildren = (Boolean) context.get("processChildren");

+                    //if (Debug.infoOn()) Debug.logInfo(" processChildren:" + processChildren, module);

+                    if (processChildren.booleanValue()) {

+                        List<Object[]> subNodeValues = getChildren(context);

+                        int newDepth = depth + 1;

+                        for (Object[] arr : subNodeValues) {

+                            ModelNode node = (ModelNode) arr[0];

+                            Map<String, Object> val = UtilGenerics.checkMap(arr[1]);

+                            //GenericPK pk = val.getPrimaryKey();

+                            //if (Debug.infoOn()) Debug.logInfo(" pk:" + pk,

+                            // module);

+                            String thisPkName = node.getPkName(context);

+                            String thisEntityId = (String) val.get(thisPkName);

+                            MapStack<String> newContext = MapStack.create(context);

+                            newContext.push();

+                            String nodeEntryName = node.getEntryName();

+                            if (!nodeEntryName.isEmpty()) {

+                                newContext.put(nodeEntryName, val);

+                            } else {

+                                newContext.putAll(val);

+                            }

+                            String targetEntityId = null;

+                            List<String> targetNodeTrail = UtilGenerics.checkList(context.get("targetNodeTrail"));

+                            if (newDepth < targetNodeTrail.size()) {

+                                targetEntityId = targetNodeTrail.get(newDepth);

+                            }

+                            if ((targetEntityId != null && targetEntityId.equals(thisEntityId))

+                                    || this.showPeers(newDepth, context)) {

+                                node.renderNodeString(writer, newContext, treeStringRenderer, newDepth);

+                            }

+                        }

+                    }

+                } catch (ScreenRenderException e) {

+                    String errMsg = "Error rendering included label with name [" + getName() + "] : " + e.toString();

+                    Debug.logError(e, errMsg, module);

+                    throw new RuntimeException(errMsg);

+                } catch (SAXException e) {

+                    String errMsg = "Error rendering included label with name [" + getName() + "] : " + e.toString();

+                    Debug.logError(e, errMsg, module);

+                    throw new RuntimeException(errMsg);

+                } catch (ParserConfigurationException e3) {

+                    String errMsg = "Error rendering included label with name [" + getName() + "] : " + e3.toString();

+                    Debug.logError(e3, errMsg, module);

+                    throw new RuntimeException(errMsg);

+                } catch (IOException e2) {

+                    String errMsg = "Error rendering included label with name [" + getName() + "] : " + e2.toString();

+                    Debug.logError(e2, errMsg, module);

+                    throw new RuntimeException(errMsg);

+                }

+                treeStringRenderer.renderNodeEnd(writer, context, this);

+                int removeIdx = currentNodeTrail.size() - 1;

+                if (removeIdx >= 0)

+                    currentNodeTrail.remove(removeIdx);

+            }

+        }

+

+        public boolean showPeers(int currentDepth, Map<String, Object> context) {

+            int trailSize = 0;

+            List<?> trail = UtilGenerics.checkList(context.get("targetNodeTrail"));

+            int openDepth = modelTree.getOpenDepth();

+            int postTrailOpenDepth = modelTree.getPostTrailOpenDepth();

+            if (trail != null)

+                trailSize = trail.size();

+

+            boolean showPeers = false;

+            String rStyle = getRenderStyle();

+            if (rStyle == null) {

+                showPeers = true;

+            } else if (!isFollowTrail()) {

+                showPeers = true;

+            } else if ((currentDepth < trailSize) && (rStyle != null)

+                    && (rStyle.equals("show-peers") || rStyle.equals("expand-collapse"))) {

+                showPeers = true;

+            } else if (openDepth >= currentDepth) {

+                showPeers = true;

+            } else {

+                int depthAfterTrail = currentDepth - trailSize;

+                if (depthAfterTrail >= 0 && depthAfterTrail <= postTrailOpenDepth)

+                    showPeers = true;

+            }

+            return showPeers;

+        }

+        

+        public List<ModelAction> getActions() {

+            return actions;

+        }

+

+        public ModelTreeCondition getCondition() {

+            return condition;

+        }

+

+        public Label getLabel() {

+            return label;

+        }

+

+        public Link getLink() {

+            return link;

+        }

+

+        public String getPkName() {

+            return pkName;

+        }

+

+        public FlexibleStringExpander getScreenLocationExdr() {

+            return screenLocationExdr;

+        }

+

+        public FlexibleStringExpander getScreenNameExdr() {

+            return screenNameExdr;

+        }

+

+        public String getShareScope() {

+            return shareScope;

+        }

+

+        public List<ModelSubNode> getSubNodeList() {

+            return subNodeList;

+        }

+

+        public FlexibleStringExpander getWrapStyleExdr() {

+            return wrapStyleExdr;

+        }

+

+        /**

+         * Models the &lt;image&gt; element.

+         * 

+         * @see <code>widget-tree.xsd</code>

+         */

+        public static class Image {

+

+            private final FlexibleStringExpander borderExdr;

+            private final FlexibleStringExpander heightExdr;

+            private final FlexibleStringExpander idExdr;

+            private final FlexibleStringExpander srcExdr;

+            private final FlexibleStringExpander styleExdr;

+            private final String urlMode;

+            private final FlexibleStringExpander widthExdr;

+

+            public Image(Element imageElement) {

+                this.borderExdr = FlexibleStringExpander

+                        .getInstance(UtilXml.checkEmpty(imageElement.getAttribute("border"), "0"));

+                this.heightExdr = FlexibleStringExpander.getInstance(imageElement.getAttribute("height"));

+                this.idExdr = FlexibleStringExpander.getInstance(imageElement.getAttribute("id"));

+                this.srcExdr = FlexibleStringExpander.getInstance(imageElement.getAttribute("src"));

+                this.styleExdr = FlexibleStringExpander.getInstance(imageElement.getAttribute("style"));

+                this.urlMode = UtilXml.checkEmpty(imageElement.getAttribute("url-mode"), "content");

+                this.widthExdr = FlexibleStringExpander.getInstance(imageElement.getAttribute("width"));

+            }

+

+            public String getBorder(Map<String, Object> context) {

+                return this.borderExdr.expandString(context);

+            }

+

+            public String getHeight(Map<String, Object> context) {

+                return this.heightExdr.expandString(context);

+            }

+

+            public String getId(Map<String, Object> context) {

+                return this.idExdr.expandString(context);

+            }

+

+            public String getSrc(Map<String, Object> context) {

+                return this.srcExdr.expandString(context);

+            }

+

+            public String getStyle(Map<String, Object> context) {

+                return this.styleExdr.expandString(context);

+            }

+

+            public String getUrlMode() {

+                return this.urlMode;

+            }

+

+            public String getWidth(Map<String, Object> context) {

+                return this.widthExdr.expandString(context);

+            }

+

+            public void renderImageString(Appendable writer, Map<String, Object> context, TreeStringRenderer treeStringRenderer) {

+                try {

+                    treeStringRenderer.renderImage(writer, context, this);

+                } catch (IOException e) {

+                    String errMsg = "Error rendering image with id [" + getId(context) + "]: " + e.toString();

+                    Debug.logError(e, errMsg, module);

+                    throw new RuntimeException(errMsg);

+                }

+            }

+        }

+

+        /**

+         * Models the &lt;label&gt; element.

+         * 

+         * @see <code>widget-tree.xsd</code>

+         */

+        public static final class Label {

+            private final FlexibleStringExpander idExdr;

+            private final FlexibleStringExpander styleExdr;

+            private final FlexibleStringExpander textExdr;

+

+            public Label(Element labelElement) {

+                String textAttr = labelElement.getAttribute("text");

+                String pcdata = UtilXml.checkEmpty(UtilXml.elementValue(labelElement), "");

+                this.textExdr = FlexibleStringExpander.getInstance(textAttr + pcdata);

+                this.idExdr = FlexibleStringExpander.getInstance(labelElement.getAttribute("id"));

+                this.styleExdr = FlexibleStringExpander.getInstance(labelElement.getAttribute("style"));

+            }

+

+            public String getId(Map<String, Object> context) {

+                return this.idExdr.expandString(context);

+            }

+

+            public String getStyle(Map<String, Object> context) {

+                return this.styleExdr.expandString(context);

+            }

+

+            public String getText(Map<String, Object> context) {

+                String text = this.textExdr.expandString(context);

+                // FIXME: Encoding should be done by the renderer, not by the model.

+                UtilCodec.SimpleEncoder simpleEncoder = (UtilCodec.SimpleEncoder) context.get("simpleEncoder");

+                if (simpleEncoder != null) {

+                    text = simpleEncoder.encode(text);

+                }

+                return text;

+            }

+

+            public void renderLabelString(Appendable writer, Map<String, Object> context, TreeStringRenderer treeStringRenderer) {

+                try {

+                    treeStringRenderer.renderLabel(writer, context, this);

+                } catch (IOException e) {

+                    String errMsg = "Error rendering label with id [" + getId(context) + "]: " + e.toString();

+                    Debug.logError(e, errMsg, module);

+                    throw new RuntimeException(errMsg);

+                }

+            }

+

+            public FlexibleStringExpander getIdExdr() {

+                return idExdr;

+            }

+

+            public FlexibleStringExpander getStyleExdr() {

+                return styleExdr;

+            }

+

+            public FlexibleStringExpander getTextExdr() {

+                return textExdr;

+            }

+        }

+

+        /**

+         * Models the &lt;link&gt; element.

+         * 

+         * @see <code>widget-tree.xsd</code>

+         */

+        public static class Link {

+            private final boolean encode;

+            private final boolean fullPath;

+            private final FlexibleStringExpander idExdr;

+            private final Image image;

+            private final String linkType;

+            private final FlexibleStringExpander nameExdr;

+            private final List<Parameter> parameterList;

+            private final FlexibleStringExpander prefixExdr;

+            private final boolean secure;

+            private final FlexibleStringExpander styleExdr;

+            private final FlexibleStringExpander targetExdr;

+            private final FlexibleStringExpander targetWindowExdr;

+            private final FlexibleStringExpander textExdr;

+            private final FlexibleStringExpander titleExdr;

+            private final String urlMode;

+

+            public Link(Element linkElement) {

+                this.encode = "true".equals(linkElement.getAttribute("encode"));

+                this.fullPath = "true".equals(linkElement.getAttribute("full-path"));

+                this.idExdr = FlexibleStringExpander.getInstance(linkElement.getAttribute("id"));

+                Element imageElement = UtilXml.firstChildElement(linkElement, "image");

+                if (imageElement != null) {

+                    this.image = new Image(imageElement);

+                } else {

+                    this.image = null;

+                }

+                this.linkType = linkElement.getAttribute("link-type");

+                this.nameExdr = FlexibleStringExpander.getInstance(linkElement.getAttribute("name"));

+                List<? extends Element> parameterElementList = UtilXml.childElementList(linkElement, "parameter");

+                if (!parameterElementList.isEmpty()) {

+                    List<Parameter> parameterList = new ArrayList<Parameter>(parameterElementList.size());

+                    for (Element parameterElement : parameterElementList) {

+                        parameterList.add(new Parameter(parameterElement));

+                    }

+                    this.parameterList = Collections.unmodifiableList(parameterList);

+                } else {

+                    this.parameterList = Collections.emptyList();

+                }

+                this.prefixExdr = FlexibleStringExpander.getInstance(linkElement.getAttribute("prefix"));

+                this.secure = "true".equals(linkElement.getAttribute("secure"));

+                this.styleExdr = FlexibleStringExpander.getInstance(linkElement.getAttribute("style"));

+                this.targetExdr = FlexibleStringExpander.getInstance(linkElement.getAttribute("target"));

+                this.targetWindowExdr = FlexibleStringExpander.getInstance(linkElement.getAttribute("target-window"));

+                this.textExdr = FlexibleStringExpander.getInstance(linkElement.getAttribute("text"));

+                this.titleExdr = FlexibleStringExpander.getInstance(linkElement.getAttribute("title"));

+                this.urlMode = UtilXml.checkEmpty(linkElement.getAttribute("link-type"), "intra-app");

+            }

+

+            // FIXME: Using a widget model in this way is an ugly hack.

+            public Link(String style, String target, String text) {

+                this.encode = false;

+                this.fullPath = false;

+                this.idExdr = FlexibleStringExpander.getInstance("");

+                this.image = null;

+                this.linkType = "";

+                this.nameExdr = FlexibleStringExpander.getInstance("");

+                this.parameterList = Collections.emptyList();

+                this.prefixExdr = FlexibleStringExpander.getInstance("");

+                this.secure = false;

+                this.styleExdr = FlexibleStringExpander.getInstance(style);

+                this.targetExdr = FlexibleStringExpander.getInstance(target);

+                this.targetWindowExdr = FlexibleStringExpander.getInstance("");

+                this.textExdr = FlexibleStringExpander.getInstance(text);

+                this.titleExdr = FlexibleStringExpander.getInstance("");

+                this.urlMode = "intra-app";

+            }

+

+            public boolean getEncode() {

+                return this.encode;

+            }

+

+            public boolean getFullPath() {

+                return this.fullPath;

+            }

+

+            public String getId(Map<String, Object> context) {

+                return this.idExdr.expandString(context);

+            }

+

+            public Image getImage() {

+                return this.image;

+            }

+

+            public String getLinkType() {

+                return this.linkType;

+            }

+

+            public String getName(Map<String, Object> context) {

+                return this.nameExdr.expandString(context);

+            }

+

+            public Map<String, String> getParameterMap(Map<String, Object> context) {

+                Map<String, String> fullParameterMap = new HashMap<String, String>();

+                /* leaving this here... may want to add it at some point like the hyperlink element:

+                Map<String, String> addlParamMap = this.parametersMapAcsr.get(context);

+                if (addlParamMap != null) {

+                    fullParameterMap.putAll(addlParamMap);

+                }

+                */

+                for (CommonWidgetModels.Parameter parameter : this.parameterList) {

+                    fullParameterMap.put(parameter.getName(), parameter.getValue(context));

+                }

+                return fullParameterMap;

+            }

+

+            public String getPrefix(Map<String, Object> context) {

+                return this.prefixExdr.expandString(context);

+            }

+

+            public boolean getSecure() {

+                return this.secure;

+            }

+

+            public String getStyle(Map<String, Object> context) {

+                return this.styleExdr.expandString(context);

+            }

+

+            public String getTarget(Map<String, Object> context) {

+                UtilCodec.SimpleEncoder simpleEncoder = (UtilCodec.SimpleEncoder) context.get("simpleEncoder");

+                if (simpleEncoder != null) {

+                    return this.targetExdr.expandString(UtilCodec.HtmlEncodingMapWrapper.getHtmlEncodingMapWrapper(context,

+                            simpleEncoder));

+                } else {

+                    return this.targetExdr.expandString(context);

+                }

+            }

+

+            public String getTargetWindow(Map<String, Object> context) {

+                return this.targetWindowExdr.expandString(context);

+            }

+

+            public String getText(Map<String, Object> context) {

+                String text = this.textExdr.expandString(context);

+                // FIXME: Encoding should be done by the renderer, not by the model.

+                UtilCodec.SimpleEncoder simpleEncoder = (UtilCodec.SimpleEncoder) context.get("simpleEncoder");

+                if (simpleEncoder != null) {

+                    text = simpleEncoder.encode(text);

+                }

+                return text;

+            }

+

+            public String getTitle(Map<String, Object> context) {

+                String title = this.titleExdr.expandString(context);

+                // FIXME: Encoding should be done by the renderer, not by the model.

+                UtilCodec.SimpleEncoder simpleEncoder = (UtilCodec.SimpleEncoder) context.get("simpleEncoder");

+                if (simpleEncoder != null) {

+                    title = simpleEncoder.encode(title);

+                }

+                return title;

+            }

+

+            public String getUrlMode() {

+                return this.urlMode;

+            }

+

+            public void renderLinkString(Appendable writer, Map<String, Object> context, TreeStringRenderer treeStringRenderer) {

+                try {

+                    treeStringRenderer.renderLink(writer, context, this);

+                } catch (IOException e) {

+                    String errMsg = "Error rendering link with id [" + getId(context) + "]: " + e.toString();

+                    Debug.logError(e, errMsg, module);

+                    throw new RuntimeException(errMsg);

+                }

+            }

+

+            public FlexibleStringExpander getIdExdr() {

+                return idExdr;

+            }

+

+            public FlexibleStringExpander getNameExdr() {

+                return nameExdr;

+            }

+

+            public List<Parameter> getParameterList() {

+                return parameterList;

+            }

+

+            public FlexibleStringExpander getPrefixExdr() {

+                return prefixExdr;

+            }

+

+            public FlexibleStringExpander getStyleExdr() {

+                return styleExdr;

+            }

+

+            public FlexibleStringExpander getTargetExdr() {

+                return targetExdr;

+            }

+

+            public FlexibleStringExpander getTargetWindowExdr() {

+                return targetWindowExdr;

+            }

+

+            public FlexibleStringExpander getTextExdr() {

+                return textExdr;

+            }

+

+            public FlexibleStringExpander getTitleExdr() {

+                return titleExdr;

+            }

+        }

+

+        /**

+         * Models the &lt;sub-node&gt; element.

+         * 

+         * @see <code>widget-tree.xsd</code>

+         */

+        public static class ModelSubNode extends ModelWidget {

+

+            private final List<ModelAction> actions;

+            private final FlexibleStringExpander nodeNameExdr;

+            private final ModelNode rootNode;

+            private final String iteratorKey;

+

+            public ModelSubNode(Element subNodeElement, ModelNode modelNode) {

+                super(subNodeElement);

+                this.rootNode = modelNode;

+                this.nodeNameExdr = FlexibleStringExpander.getInstance(subNodeElement.getAttribute("node-name"));

+                ArrayList<ModelAction> actions = new ArrayList<ModelAction>();

+                // FIXME: Validate child elements, should be only one of actions, entity-and, entity-condition, service, script.

+                Element actionsElement = UtilXml.firstChildElement(subNodeElement, "actions");

+                if (actionsElement != null) {

+                    actions.addAll(ModelTreeAction.readSubNodeActions(this, actionsElement));

+                }

+                Element actionElement = UtilXml.firstChildElement(subNodeElement, "entity-and");

+                if (actionElement != null) {

+                    actions.add(new ModelTreeAction.EntityAnd(this, actionElement));

+                }

+                actionElement = UtilXml.firstChildElement(subNodeElement, "service");

+                if (actionElement != null) {

+                    actions.add(new ModelTreeAction.Service(this, actionElement));

+                }

+                actionElement = UtilXml.firstChildElement(subNodeElement, "entity-condition");

+                if (actionElement != null) {

+                    actions.add(new ModelTreeAction.EntityCondition(this, actionElement));

+                }

+                actionElement = UtilXml.firstChildElement(subNodeElement, "script");

+                if (actionElement != null) {

+                    actions.add(new ModelTreeAction.Script(this, actionElement));

+                }

+                actions.trimToSize();

+                this.actions = Collections.unmodifiableList(actions);

+                this.iteratorKey = this.rootNode.getName().concat(".").concat(this.nodeNameExdr.getOriginal())

+                        .concat(".ITERATOR");

+            }

+

+            @Override

+            public void accept(ModelWidgetVisitor visitor) throws Exception {

+                visitor.visit(this);

+            }

+

+            public List<ModelAction> getActions() {

+                return actions;

+            }

+

+            @SuppressWarnings("unchecked")

+            public ListIterator<? extends Map<String, ? extends Object>> getListIterator(Map<String, Object> context) {

+                return (ListIterator<? extends Map<String, ? extends Object>>) context.get(this.iteratorKey);

+            }

+

+            public ModelTree.ModelNode getNode() {

+                return this.rootNode;

+            }

+

+            public String getNodeName(Map<String, Object> context) {

+                return this.nodeNameExdr.expandString(context);

+            }

+

+            public FlexibleStringExpander getNodeNameExdr() {

+                return nodeNameExdr;

+            }

+

+            public void setListIterator(ListIterator<? extends Map<String, ? extends Object>> iter, Map<String, Object> context) {

+                context.put(this.iteratorKey, iter);

+            }

+        }

+    }

+}

diff --git a/framework/widget/src/org/ofbiz/widget/tree/ModelTreeAction.java b/framework/widget/src/org/ofbiz/widget/model/ModelTreeAction.java
similarity index 98%
rename from framework/widget/src/org/ofbiz/widget/tree/ModelTreeAction.java
rename to framework/widget/src/org/ofbiz/widget/model/ModelTreeAction.java
index 3460b5b..f9734c8 100644
--- a/framework/widget/src/org/ofbiz/widget/tree/ModelTreeAction.java
+++ b/framework/widget/src/org/ofbiz/widget/model/ModelTreeAction.java
@@ -1,463 +1,460 @@
-/*******************************************************************************
- * 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.tree;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.ListIterator;
-import java.util.Map;
-import java.util.regex.PatternSyntaxException;
-
-import org.ofbiz.base.util.Debug;
-import org.ofbiz.base.util.GeneralException;
-import org.ofbiz.base.util.ScriptUtil;
-import org.ofbiz.base.util.UtilFormatOut;
-import org.ofbiz.base.util.UtilGenerics;
-import org.ofbiz.base.util.UtilValidate;
-import org.ofbiz.base.util.UtilXml;
-import org.ofbiz.base.util.collections.FlexibleMapAccessor;
-import org.ofbiz.base.util.string.FlexibleStringExpander;
-import org.ofbiz.entity.finder.ByAndFinder;
-import org.ofbiz.entity.finder.ByConditionFinder;
-import org.ofbiz.entity.finder.EntityFinderUtil;
-import org.ofbiz.entity.util.EntityListIterator;
-import org.ofbiz.minilang.MiniLangException;
-import org.ofbiz.minilang.SimpleMethod;
-import org.ofbiz.minilang.method.MethodContext;
-import org.ofbiz.service.DispatchContext;
-import org.ofbiz.service.GenericServiceException;
-import org.ofbiz.service.ModelService;
-import org.ofbiz.widget.AbstractModelAction;
-import org.ofbiz.widget.ModelAction;
-import org.ofbiz.widget.ModelActionVisitor;
-import org.ofbiz.widget.WidgetWorker;
-import org.ofbiz.widget.tree.ModelTree.ModelNode;
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-
-/**
- * Abstract tree action.
- */
-@SuppressWarnings("serial")
-public abstract class ModelTreeAction extends AbstractModelAction {
-
-    /*
-     * ----------------------------------------------------------------------- *
-     *                     DEVELOPERS PLEASE READ
-     * ----------------------------------------------------------------------- *
-     * 
-     * This model is intended to be a read-only data structure that represents
-     * an XML element. Outside of object construction, the class should not
-     * have any behaviors.
-     * 
-     * Instances of this class will be shared by multiple threads - therefore
-     * it is immutable. DO NOT CHANGE THE OBJECT'S STATE AT RUN TIME!
-     * 
-     */
-
-    public static final String module = ModelTreeAction.class.getName();
-
-    public static List<ModelAction> readNodeActions(ModelNode modelNode, Element actionsElement) {
-        List<? extends Element> actionElementList = UtilXml.childElementList(actionsElement);
-        List<ModelAction> actions = new ArrayList<ModelAction>(actionElementList.size());
-        for (Element actionElement : actionElementList) {
-            if ("service".equals(actionElement.getNodeName())) {
-                actions.add(new Service(modelNode, actionElement));
-            } else if ("script".equals(actionElement.getNodeName())) {
-                actions.add(new Script(modelNode, actionElement));
-            } else {
-                actions.add(AbstractModelAction.newInstance(modelNode, actionElement));
-            }
-        }
-        return actions;
-    }
-
-    public static List<ModelAction> readSubNodeActions(ModelNode.ModelSubNode modelSubNode, Element actionsElement) {
-        List<? extends Element> actionElementList = UtilXml.childElementList(actionsElement);
-        List<ModelAction> actions = new ArrayList<ModelAction>(actionElementList.size());
-        for (Element actionElement : actionElementList) {
-            if ("service".equals(actionElement.getNodeName())) {
-                actions.add(new Service(modelSubNode, actionElement));
-            } else if ("entity-and".equals(actionElement.getNodeName())) {
-                actions.add(new EntityAnd(modelSubNode, actionElement));
-            } else if ("entity-condition".equals(actionElement.getNodeName())) {
-                actions.add(new EntityCondition(modelSubNode, actionElement));
-            } else if ("script".equals(actionElement.getNodeName())) {
-                actions.add(new Script(modelSubNode, actionElement));
-            } else {
-                actions.add(AbstractModelAction.newInstance(modelSubNode, actionElement));
-            }
-        }
-        return actions;
-    }
-
-    private final ModelNode.ModelSubNode modelSubNode;
-    private final ModelTree modelTree;
-
-    protected ModelTreeAction(ModelNode modelNode, Element actionElement) {
-        if (Debug.verboseOn())
-            Debug.logVerbose("Reading Tree action with name: " + actionElement.getNodeName(), module);
-        this.modelTree = modelNode.getModelTree();
-        this.modelSubNode = null;
-    }
-
-    protected ModelTreeAction(ModelNode.ModelSubNode modelSubNode, Element actionElement) {
-        if (Debug.verboseOn())
-            Debug.logVerbose("Reading Tree action with name: " + actionElement.getNodeName(), module);
-        this.modelSubNode = modelSubNode;
-        this.modelTree = modelSubNode.getNode().getModelTree();
-    }
-
-    public ModelNode.ModelSubNode getModelSubNode() {
-        return modelSubNode;
-    }
-
-    public ModelTree getModelTree() {
-        return modelTree;
-    }
-
-    /**
-     * Models the &lt;entity-and&gt; element.
-     * 
-     * @see <code>widget-tree.xsd</code>
-     */
-    public static class EntityAnd extends ModelTreeAction {
-        private final ByAndFinder finder;
-        private final String listName;
-
-        public EntityAnd(ModelNode.ModelSubNode modelSubNode, Element entityAndElement) {
-            super(modelSubNode, entityAndElement);
-            boolean useCache = "true".equalsIgnoreCase(entityAndElement.getAttribute("use-cache"));
-            Document ownerDoc = entityAndElement.getOwnerDocument();
-            if (!useCache)
-                UtilXml.addChildElement(entityAndElement, "use-iterator", ownerDoc);
-            String listName = UtilFormatOut.checkEmpty(entityAndElement.getAttribute("list"),
-                    entityAndElement.getAttribute("list-name"));
-            if (UtilValidate.isEmpty(listName))
-                listName = "_LIST_ITERATOR_";
-            this.listName = listName;
-            entityAndElement.setAttribute("list-name", this.listName);
-            finder = new ByAndFinder(entityAndElement);
-        }
-
-        @Override
-        public void accept(ModelActionVisitor visitor) throws Exception {
-            visitor.visit(this);
-        }
-
-        public ByAndFinder getFinder() {
-            return finder;
-        }
-
-        public String getListName() {
-            return listName;
-        }
-
-        @Override
-        public void runAction(Map<String, Object> context) {
-            try {
-                context.put(this.listName, null);
-                finder.runFind(context, WidgetWorker.getDelegator(context));
-                Object obj = context.get(this.listName);
-                if (obj != null && (obj instanceof EntityListIterator || obj instanceof ListIterator<?>)) {
-                    ListIterator<? extends Map<String, ? extends Object>> listIt = UtilGenerics.cast(obj);
-                    this.getModelSubNode().setListIterator(listIt, context);
-                } else {
-                    if (obj instanceof List<?>) {
-                        List<? extends Map<String, ? extends Object>> list = UtilGenerics.checkList(obj);
-                        this.getModelSubNode().setListIterator(list.listIterator(), context);
-                    }
-                }
-            } catch (GeneralException e) {
-                String errMsg = "Error doing entity query by condition: " + e.toString();
-                Debug.logError(e, errMsg, module);
-                throw new IllegalArgumentException(errMsg);
-            }
-        }
-    }
-
-    /**
-     * Models the &lt;entity-condition&gt; element.
-     * 
-     * @see <code>widget-tree.xsd</code>
-     */
-    public static class EntityCondition extends ModelTreeAction {
-        private final ByConditionFinder finder;
-        private final String listName;
-
-        public EntityCondition(ModelNode.ModelSubNode modelSubNode, Element entityConditionElement) {
-            super(modelSubNode, entityConditionElement);
-            Document ownerDoc = entityConditionElement.getOwnerDocument();
-            boolean useCache = "true".equalsIgnoreCase(entityConditionElement.getAttribute("use-cache"));
-            if (!useCache)
-                UtilXml.addChildElement(entityConditionElement, "use-iterator", ownerDoc);
-            String listName = UtilFormatOut.checkEmpty(entityConditionElement.getAttribute("list"),
-                    entityConditionElement.getAttribute("list-name"));
-            if (UtilValidate.isEmpty(listName))
-                listName = "_LIST_ITERATOR_";
-            this.listName = listName;
-            entityConditionElement.setAttribute("list-name", this.listName);
-            finder = new ByConditionFinder(entityConditionElement);
-        }
-
-        @Override
-        public void accept(ModelActionVisitor visitor) throws Exception {
-            visitor.visit(this);
-        }
-
-        public ByConditionFinder getFinder() {
-            return finder;
-        }
-
-        public String getListName() {
-            return listName;
-        }
-
-        @Override
-        public void runAction(Map<String, Object> context) {
-            try {
-                context.put(this.listName, null);
-                finder.runFind(context, WidgetWorker.getDelegator(context));
-                Object obj = context.get(this.listName);
-                if (obj != null && (obj instanceof EntityListIterator || obj instanceof ListIterator<?>)) {
-                    ListIterator<? extends Map<String, ? extends Object>> listIt = UtilGenerics.cast(obj);
-                    this.getModelSubNode().setListIterator(listIt, context);
-                } else {
-                    if (obj instanceof List<?>) {
-                        List<? extends Map<String, ? extends Object>> list = UtilGenerics.cast(obj);
-                        this.getModelSubNode().setListIterator(list.listIterator(), context);
-                    }
-                }
-            } catch (GeneralException e) {
-                String errMsg = "Error doing entity query by condition: " + e.toString();
-                Debug.logError(e, errMsg, module);
-                throw new IllegalArgumentException(errMsg);
-            }
-        }
-    }
-
-    /**
-     * Models the &lt;script&gt; element.
-     * 
-     * @see <code>widget-tree.xsd</code>
-     */
-    public static class Script extends ModelTreeAction {
-        private final String location;
-        private final String method;
-
-        public Script(ModelNode modelNode, Element scriptElement) {
-            super(modelNode, scriptElement);
-            String scriptLocation = scriptElement.getAttribute("location");
-            this.location = WidgetWorker.getScriptLocation(scriptLocation);
-            this.method = WidgetWorker.getScriptMethodName(scriptLocation);
-        }
-
-        public Script(ModelNode.ModelSubNode modelSubNode, Element scriptElement) {
-            super(modelSubNode, scriptElement);
-            String scriptLocation = scriptElement.getAttribute("location");
-            this.location = WidgetWorker.getScriptLocation(scriptLocation);
-            this.method = WidgetWorker.getScriptMethodName(scriptLocation);
-        }
-
-        @Override
-        public void accept(ModelActionVisitor visitor) throws Exception {
-            visitor.visit(this);
-        }
-
-        public String getLocation() {
-            return location;
-        }
-
-        public String getMethod() {
-            return method;
-        }
-
-        @Override
-        public void runAction(Map<String, Object> context) {
-            context.put("_LIST_ITERATOR_", null);
-            if (location.endsWith(".xml")) {
-                Map<String, Object> localContext = new HashMap<String, Object>();
-                localContext.putAll(context);
-                DispatchContext ctx = WidgetWorker.getDispatcher(context).getDispatchContext();
-                MethodContext methodContext = new MethodContext(ctx, localContext, null);
-                try {
-                    SimpleMethod.runSimpleMethod(location, method, methodContext);
-                    context.putAll(methodContext.getResults());
-                } catch (MiniLangException e) {
-                    throw new RuntimeException("Error running simple method at location [" + location + "]", e);
-                }
-            } else {
-                ScriptUtil.executeScript(this.location, this.method, context);
-            }
-            Object obj = context.get("_LIST_ITERATOR_");
-            if (this.getModelSubNode() != null) {
-                if (obj != null && (obj instanceof EntityListIterator || obj instanceof ListIterator<?>)) {
-                    ListIterator<? extends Map<String, ? extends Object>> listIt = UtilGenerics.cast(obj);
-                    this.getModelSubNode().setListIterator(listIt, context);
-                } else {
-                    if (obj instanceof List<?>) {
-                        List<? extends Map<String, ? extends Object>> list = UtilGenerics.checkList(obj);
-                        this.getModelSubNode().setListIterator(list.listIterator(), context);
-                    }
-                }
-            }
-        }
-    }
-
-    /**
-     * Models the &lt;service&gt; element.
-     * 
-     * @see <code>widget-tree.xsd</code>
-     */
-    public static class Service extends ModelTreeAction {
-        private final FlexibleStringExpander autoFieldMapExdr;
-        private final Map<FlexibleMapAccessor<Object>, Object> fieldMap;
-        private final FlexibleStringExpander resultMapListNameExdr;
-        private final FlexibleMapAccessor<Map<String, Object>> resultMapNameAcsr;
-        private final FlexibleStringExpander resultMapValueNameExdr;
-        private final FlexibleStringExpander serviceNameExdr;
-        private final FlexibleStringExpander valueNameExdr;
-
-        public Service(ModelNode modelNode, Element serviceElement) {
-            super(modelNode, serviceElement);
-            this.serviceNameExdr = FlexibleStringExpander.getInstance(serviceElement.getAttribute("service-name"));
-            this.resultMapNameAcsr = FlexibleMapAccessor.getInstance(serviceElement.getAttribute("result-map"));
-            this.autoFieldMapExdr = FlexibleStringExpander.getInstance(serviceElement.getAttribute("auto-field-map"));
-            this.resultMapListNameExdr = FlexibleStringExpander.getInstance(serviceElement.getAttribute("result-map-list"));
-            this.resultMapValueNameExdr = FlexibleStringExpander.getInstance(serviceElement.getAttribute("result-map-value"));
-            this.valueNameExdr = FlexibleStringExpander.getInstance(serviceElement.getAttribute("value"));
-            this.fieldMap = EntityFinderUtil.makeFieldMap(serviceElement);
-        }
-
-        public Service(ModelNode.ModelSubNode modelSubNode, Element serviceElement) {
-            super(modelSubNode, serviceElement);
-            this.serviceNameExdr = FlexibleStringExpander.getInstance(serviceElement.getAttribute("service-name"));
-            this.resultMapNameAcsr = FlexibleMapAccessor.getInstance(serviceElement.getAttribute("result-map"));
-            this.autoFieldMapExdr = FlexibleStringExpander.getInstance(serviceElement.getAttribute("auto-field-map"));
-            this.resultMapListNameExdr = FlexibleStringExpander.getInstance(serviceElement.getAttribute("result-map-list"));
-            this.resultMapValueNameExdr = FlexibleStringExpander.getInstance(serviceElement.getAttribute("result-map-value"));
-            this.valueNameExdr = FlexibleStringExpander.getInstance(serviceElement.getAttribute("value"));
-            this.fieldMap = EntityFinderUtil.makeFieldMap(serviceElement);
-        }
-
-        @Override
-        public void accept(ModelActionVisitor visitor) throws Exception {
-            visitor.visit(this);
-        }
-
-        public FlexibleStringExpander getAutoFieldMapExdr() {
-            return autoFieldMapExdr;
-        }
-
-        public Map<FlexibleMapAccessor<Object>, Object> getFieldMap() {
-            return fieldMap;
-        }
-
-        public FlexibleStringExpander getResultMapListNameExdr() {
-            return resultMapListNameExdr;
-        }
-
-        public FlexibleMapAccessor<Map<String, Object>> getResultMapNameAcsr() {
-            return resultMapNameAcsr;
-        }
-
-        public FlexibleStringExpander getResultMapValueNameExdr() {
-            return resultMapValueNameExdr;
-        }
-
-        public FlexibleStringExpander getServiceNameExdr() {
-            return serviceNameExdr;
-        }
-
-        public FlexibleStringExpander getValueNameExdr() {
-            return valueNameExdr;
-        }
-
-        @Override
-        public void runAction(Map<String, Object> context) {
-            String serviceNameExpanded = this.serviceNameExdr.expandString(context);
-            if (UtilValidate.isEmpty(serviceNameExpanded)) {
-                throw new IllegalArgumentException("Service name was empty, expanded from: " + this.serviceNameExdr.getOriginal());
-            }
-            String autoFieldMapString = this.autoFieldMapExdr.expandString(context);
-            boolean autoFieldMapBool = !"false".equals(autoFieldMapString);
-            try {
-                Map<String, Object> serviceContext = null;
-                if (autoFieldMapBool) {
-                    serviceContext = WidgetWorker.getDispatcher(context).getDispatchContext()
-                            .makeValidContext(serviceNameExpanded, ModelService.IN_PARAM, context);
-                } else {
-                    serviceContext = new HashMap<String, Object>();
-                }
-                if (this.fieldMap != null) {
-                    EntityFinderUtil.expandFieldMapToContext(this.fieldMap, context, serviceContext);
-                }
-                Map<String, Object> result = WidgetWorker.getDispatcher(context).runSync(serviceNameExpanded, serviceContext);
-                if (!this.resultMapNameAcsr.isEmpty()) {
-                    this.resultMapNameAcsr.put(context, result);
-                    String queryString = (String) result.get("queryString");
-                    context.put("queryString", queryString);
-                    context.put("queryStringMap", result.get("queryStringMap"));
-                    if (UtilValidate.isNotEmpty(queryString)) {
-                        try {
-                            String queryStringEncoded = queryString.replaceAll("&", "%26");
-                            context.put("queryStringEncoded", queryStringEncoded);
-                        } catch (PatternSyntaxException e) {
-
-                        }
-                    }
-                } else {
-                    context.putAll(result);
-                }
-                String resultMapListName = resultMapListNameExdr.expandString(context);
-                //String resultMapListIteratorName = resultMapListIteratorNameExdr.expandString(context);
-                String resultMapValueName = resultMapValueNameExdr.expandString(context);
-                String valueName = valueNameExdr.expandString(context);
-                if (this.getModelSubNode() != null) {
-                    //ListIterator iter = null;
-                    if (UtilValidate.isNotEmpty(resultMapListName)) {
-                        List<? extends Map<String, ? extends Object>> lst = UtilGenerics.checkList(result.get(resultMapListName));
-                        if (lst != null) {
-                            if (lst instanceof ListIterator<?>) {
-                                ListIterator<? extends Map<String, ? extends Object>> listIt = UtilGenerics.cast(lst);
-                                this.getModelSubNode().setListIterator(listIt, context);
-                            } else {
-                                this.getModelSubNode().setListIterator(lst.listIterator(), context);
-                            }
-                        }
-                    }
-                } else {
-                    if (UtilValidate.isNotEmpty(resultMapValueName)) {
-                        if (UtilValidate.isNotEmpty(valueName)) {
-                            context.put(valueName, result.get(resultMapValueName));
-                        } else {
-                            Map<String, Object> resultMap = UtilGenerics.checkMap(result.get(resultMapValueName));
-                            context.putAll(resultMap);
-                        }
-                    }
-                }
-            } catch (GenericServiceException e) {
-                String errMsg = "Error calling service with name " + serviceNameExpanded + ": " + e.toString();
-                Debug.logError(e, errMsg, module);
-                throw new IllegalArgumentException(errMsg);
-            }
-        }
-    }
-}
+/*******************************************************************************

+ * Licensed to the Apache Software Foundation (ASF) under one

+ * or more contributor license agreements.  See the NOTICE file

+ * distributed with this work for additional information

+ * regarding copyright ownership.  The ASF licenses this file

+ * to you under the Apache License, Version 2.0 (the

+ * "License"); you may not use this file except in compliance

+ * with the License.  You may obtain a copy of the License at

+ *

+ * http://www.apache.org/licenses/LICENSE-2.0

+ *

+ * Unless required by applicable law or agreed to in writing,

+ * software distributed under the License is distributed on an

+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY

+ * KIND, either express or implied.  See the License for the

+ * specific language governing permissions and limitations

+ * under the License.

+ *******************************************************************************/

+package org.ofbiz.widget.model;

+

+import java.util.ArrayList;

+import java.util.HashMap;

+import java.util.List;

+import java.util.ListIterator;

+import java.util.Map;

+import java.util.regex.PatternSyntaxException;

+

+import org.ofbiz.base.util.Debug;

+import org.ofbiz.base.util.GeneralException;

+import org.ofbiz.base.util.ScriptUtil;

+import org.ofbiz.base.util.UtilFormatOut;

+import org.ofbiz.base.util.UtilGenerics;

+import org.ofbiz.base.util.UtilValidate;

+import org.ofbiz.base.util.UtilXml;

+import org.ofbiz.base.util.collections.FlexibleMapAccessor;

+import org.ofbiz.base.util.string.FlexibleStringExpander;

+import org.ofbiz.entity.finder.ByAndFinder;

+import org.ofbiz.entity.finder.ByConditionFinder;

+import org.ofbiz.entity.finder.EntityFinderUtil;

+import org.ofbiz.entity.util.EntityListIterator;

+import org.ofbiz.minilang.MiniLangException;

+import org.ofbiz.minilang.SimpleMethod;

+import org.ofbiz.minilang.method.MethodContext;

+import org.ofbiz.service.DispatchContext;

+import org.ofbiz.service.GenericServiceException;

+import org.ofbiz.service.ModelService;

+import org.ofbiz.widget.WidgetWorker;

+import org.ofbiz.widget.model.ModelTree.ModelNode;

+import org.w3c.dom.Document;

+import org.w3c.dom.Element;

+

+/**

+ * Abstract tree action.

+ */

+@SuppressWarnings("serial")

+public abstract class ModelTreeAction extends AbstractModelAction {

+

+    /*

+     * ----------------------------------------------------------------------- *

+     *                     DEVELOPERS PLEASE READ

+     * ----------------------------------------------------------------------- *

+     * 

+     * This model is intended to be a read-only data structure that represents

+     * an XML element. Outside of object construction, the class should not

+     * have any behaviors.

+     * 

+     * Instances of this class will be shared by multiple threads - therefore

+     * it is immutable. DO NOT CHANGE THE OBJECT'S STATE AT RUN TIME!

+     * 

+     */

+

+    public static final String module = ModelTreeAction.class.getName();

+

+    public static List<ModelAction> readNodeActions(ModelNode modelNode, Element actionsElement) {

+        List<? extends Element> actionElementList = UtilXml.childElementList(actionsElement);

+        List<ModelAction> actions = new ArrayList<ModelAction>(actionElementList.size());

+        for (Element actionElement : actionElementList) {

+            if ("service".equals(actionElement.getNodeName())) {

+                actions.add(new Service(modelNode, actionElement));

+            } else if ("script".equals(actionElement.getNodeName())) {

+                actions.add(new Script(modelNode, actionElement));

+            } else {

+                actions.add(AbstractModelAction.newInstance(modelNode, actionElement));

+            }

+        }

+        return actions;

+    }

+

+    public static List<ModelAction> readSubNodeActions(ModelNode.ModelSubNode modelSubNode, Element actionsElement) {

+        List<? extends Element> actionElementList = UtilXml.childElementList(actionsElement);

+        List<ModelAction> actions = new ArrayList<ModelAction>(actionElementList.size());

+        for (Element actionElement : actionElementList) {

+            if ("service".equals(actionElement.getNodeName())) {

+                actions.add(new Service(modelSubNode, actionElement));

+            } else if ("entity-and".equals(actionElement.getNodeName())) {

+                actions.add(new EntityAnd(modelSubNode, actionElement));

+            } else if ("entity-condition".equals(actionElement.getNodeName())) {

+                actions.add(new EntityCondition(modelSubNode, actionElement));

+            } else if ("script".equals(actionElement.getNodeName())) {

+                actions.add(new Script(modelSubNode, actionElement));

+            } else {

+                actions.add(AbstractModelAction.newInstance(modelSubNode, actionElement));

+            }

+        }

+        return actions;

+    }

+

+    private final ModelNode.ModelSubNode modelSubNode;

+    private final ModelTree modelTree;

+

+    protected ModelTreeAction(ModelNode modelNode, Element actionElement) {

+        if (Debug.verboseOn())

+            Debug.logVerbose("Reading Tree action with name: " + actionElement.getNodeName(), module);

+        this.modelTree = modelNode.getModelTree();

+        this.modelSubNode = null;

+    }

+

+    protected ModelTreeAction(ModelNode.ModelSubNode modelSubNode, Element actionElement) {

+        if (Debug.verboseOn())

+            Debug.logVerbose("Reading Tree action with name: " + actionElement.getNodeName(), module);

+        this.modelSubNode = modelSubNode;

+        this.modelTree = modelSubNode.getNode().getModelTree();

+    }

+

+    public ModelNode.ModelSubNode getModelSubNode() {

+        return modelSubNode;

+    }

+

+    public ModelTree getModelTree() {

+        return modelTree;

+    }

+

+    /**

+     * Models the &lt;entity-and&gt; element.

+     * 

+     * @see <code>widget-tree.xsd</code>

+     */

+    public static class EntityAnd extends ModelTreeAction {

+        private final ByAndFinder finder;

+        private final String listName;

+

+        public EntityAnd(ModelNode.ModelSubNode modelSubNode, Element entityAndElement) {

+            super(modelSubNode, entityAndElement);

+            boolean useCache = "true".equalsIgnoreCase(entityAndElement.getAttribute("use-cache"));

+            Document ownerDoc = entityAndElement.getOwnerDocument();

+            if (!useCache)

+                UtilXml.addChildElement(entityAndElement, "use-iterator", ownerDoc);

+            String listName = UtilFormatOut.checkEmpty(entityAndElement.getAttribute("list"),

+                    entityAndElement.getAttribute("list-name"));

+            if (UtilValidate.isEmpty(listName))

+                listName = "_LIST_ITERATOR_";

+            this.listName = listName;

+            entityAndElement.setAttribute("list-name", this.listName);

+            finder = new ByAndFinder(entityAndElement);

+        }

+

+        @Override

+        public void accept(ModelActionVisitor visitor) throws Exception {

+            visitor.visit(this);

+        }

+

+        public ByAndFinder getFinder() {

+            return finder;

+        }

+

+        public String getListName() {

+            return listName;

+        }

+

+        @Override

+        public void runAction(Map<String, Object> context) {

+            try {

+                context.put(this.listName, null);

+                finder.runFind(context, WidgetWorker.getDelegator(context));

+                Object obj = context.get(this.listName);

+                if (obj != null && (obj instanceof EntityListIterator || obj instanceof ListIterator<?>)) {

+                    ListIterator<? extends Map<String, ? extends Object>> listIt = UtilGenerics.cast(obj);

+                    this.getModelSubNode().setListIterator(listIt, context);

+                } else {

+                    if (obj instanceof List<?>) {

+                        List<? extends Map<String, ? extends Object>> list = UtilGenerics.checkList(obj);

+                        this.getModelSubNode().setListIterator(list.listIterator(), context);

+                    }

+                }

+            } catch (GeneralException e) {

+                String errMsg = "Error doing entity query by condition: " + e.toString();

+                Debug.logError(e, errMsg, module);

+                throw new IllegalArgumentException(errMsg);

+            }

+        }

+    }

+

+    /**

+     * Models the &lt;entity-condition&gt; element.

+     * 

+     * @see <code>widget-tree.xsd</code>

+     */

+    public static class EntityCondition extends ModelTreeAction {

+        private final ByConditionFinder finder;

+        private final String listName;

+

+        public EntityCondition(ModelNode.ModelSubNode modelSubNode, Element entityConditionElement) {

+            super(modelSubNode, entityConditionElement);

+            Document ownerDoc = entityConditionElement.getOwnerDocument();

+            boolean useCache = "true".equalsIgnoreCase(entityConditionElement.getAttribute("use-cache"));

+            if (!useCache)

+                UtilXml.addChildElement(entityConditionElement, "use-iterator", ownerDoc);

+            String listName = UtilFormatOut.checkEmpty(entityConditionElement.getAttribute("list"),

+                    entityConditionElement.getAttribute("list-name"));

+            if (UtilValidate.isEmpty(listName))

+                listName = "_LIST_ITERATOR_";

+            this.listName = listName;

+            entityConditionElement.setAttribute("list-name", this.listName);

+            finder = new ByConditionFinder(entityConditionElement);

+        }

+

+        @Override

+        public void accept(ModelActionVisitor visitor) throws Exception {

+            visitor.visit(this);

+        }

+

+        public ByConditionFinder getFinder() {

+            return finder;

+        }

+

+        public String getListName() {

+            return listName;

+        }

+

+        @Override

+        public void runAction(Map<String, Object> context) {

+            try {

+                context.put(this.listName, null);

+                finder.runFind(context, WidgetWorker.getDelegator(context));

+                Object obj = context.get(this.listName);

+                if (obj != null && (obj instanceof EntityListIterator || obj instanceof ListIterator<?>)) {

+                    ListIterator<? extends Map<String, ? extends Object>> listIt = UtilGenerics.cast(obj);

+                    this.getModelSubNode().setListIterator(listIt, context);

+                } else {

+                    if (obj instanceof List<?>) {

+                        List<? extends Map<String, ? extends Object>> list = UtilGenerics.cast(obj);

+                        this.getModelSubNode().setListIterator(list.listIterator(), context);

+                    }

+                }

+            } catch (GeneralException e) {

+                String errMsg = "Error doing entity query by condition: " + e.toString();

+                Debug.logError(e, errMsg, module);

+                throw new IllegalArgumentException(errMsg);

+            }

+        }

+    }

+

+    /**

+     * Models the &lt;script&gt; element.

+     * 

+     * @see <code>widget-tree.xsd</code>

+     */

+    public static class Script extends ModelTreeAction {

+        private final String location;

+        private final String method;

+

+        public Script(ModelNode modelNode, Element scriptElement) {

+            super(modelNode, scriptElement);

+            String scriptLocation = scriptElement.getAttribute("location");

+            this.location = WidgetWorker.getScriptLocation(scriptLocation);

+            this.method = WidgetWorker.getScriptMethodName(scriptLocation);

+        }

+

+        public Script(ModelNode.ModelSubNode modelSubNode, Element scriptElement) {

+            super(modelSubNode, scriptElement);

+            String scriptLocation = scriptElement.getAttribute("location");

+            this.location = WidgetWorker.getScriptLocation(scriptLocation);

+            this.method = WidgetWorker.getScriptMethodName(scriptLocation);

+        }

+

+        @Override

+        public void accept(ModelActionVisitor visitor) throws Exception {

+            visitor.visit(this);

+        }

+

+        public String getLocation() {

+            return location;

+        }

+

+        public String getMethod() {

+            return method;

+        }

+

+        @Override

+        public void runAction(Map<String, Object> context) {

+            context.put("_LIST_ITERATOR_", null);

+            if (location.endsWith(".xml")) {

+                Map<String, Object> localContext = new HashMap<String, Object>();

+                localContext.putAll(context);

+                DispatchContext ctx = WidgetWorker.getDispatcher(context).getDispatchContext();

+                MethodContext methodContext = new MethodContext(ctx, localContext, null);

+                try {

+                    SimpleMethod.runSimpleMethod(location, method, methodContext);

+                    context.putAll(methodContext.getResults());

+                } catch (MiniLangException e) {

+                    throw new RuntimeException("Error running simple method at location [" + location + "]", e);

+                }

+            } else {

+                ScriptUtil.executeScript(this.location, this.method, context);

+            }

+            Object obj = context.get("_LIST_ITERATOR_");

+            if (this.getModelSubNode() != null) {

+                if (obj != null && (obj instanceof EntityListIterator || obj instanceof ListIterator<?>)) {

+                    ListIterator<? extends Map<String, ? extends Object>> listIt = UtilGenerics.cast(obj);

+                    this.getModelSubNode().setListIterator(listIt, context);

+                } else {

+                    if (obj instanceof List<?>) {

+                        List<? extends Map<String, ? extends Object>> list = UtilGenerics.checkList(obj);

+                        this.getModelSubNode().setListIterator(list.listIterator(), context);

+                    }

+                }

+            }

+        }

+    }

+

+    /**

+     * Models the &lt;service&gt; element.

+     * 

+     * @see <code>widget-tree.xsd</code>

+     */

+    public static class Service extends ModelTreeAction {

+        private final FlexibleStringExpander autoFieldMapExdr;

+        private final Map<FlexibleMapAccessor<Object>, Object> fieldMap;

+        private final FlexibleStringExpander resultMapListNameExdr;

+        private final FlexibleMapAccessor<Map<String, Object>> resultMapNameAcsr;

+        private final FlexibleStringExpander resultMapValueNameExdr;

+        private final FlexibleStringExpander serviceNameExdr;

+        private final FlexibleStringExpander valueNameExdr;

+

+        public Service(ModelNode modelNode, Element serviceElement) {

+            super(modelNode, serviceElement);

+            this.serviceNameExdr = FlexibleStringExpander.getInstance(serviceElement.getAttribute("service-name"));

+            this.resultMapNameAcsr = FlexibleMapAccessor.getInstance(serviceElement.getAttribute("result-map"));

+            this.autoFieldMapExdr = FlexibleStringExpander.getInstance(serviceElement.getAttribute("auto-field-map"));

+            this.resultMapListNameExdr = FlexibleStringExpander.getInstance(serviceElement.getAttribute("result-map-list"));

+            this.resultMapValueNameExdr = FlexibleStringExpander.getInstance(serviceElement.getAttribute("result-map-value"));

+            this.valueNameExdr = FlexibleStringExpander.getInstance(serviceElement.getAttribute("value"));

+            this.fieldMap = EntityFinderUtil.makeFieldMap(serviceElement);

+        }

+

+        public Service(ModelNode.ModelSubNode modelSubNode, Element serviceElement) {

+            super(modelSubNode, serviceElement);

+            this.serviceNameExdr = FlexibleStringExpander.getInstance(serviceElement.getAttribute("service-name"));

+            this.resultMapNameAcsr = FlexibleMapAccessor.getInstance(serviceElement.getAttribute("result-map"));

+            this.autoFieldMapExdr = FlexibleStringExpander.getInstance(serviceElement.getAttribute("auto-field-map"));

+            this.resultMapListNameExdr = FlexibleStringExpander.getInstance(serviceElement.getAttribute("result-map-list"));

+            this.resultMapValueNameExdr = FlexibleStringExpander.getInstance(serviceElement.getAttribute("result-map-value"));

+            this.valueNameExdr = FlexibleStringExpander.getInstance(serviceElement.getAttribute("value"));

+            this.fieldMap = EntityFinderUtil.makeFieldMap(serviceElement);

+        }

+

+        @Override

+        public void accept(ModelActionVisitor visitor) throws Exception {

+            visitor.visit(this);

+        }

+

+        public FlexibleStringExpander getAutoFieldMapExdr() {

+            return autoFieldMapExdr;

+        }

+

+        public Map<FlexibleMapAccessor<Object>, Object> getFieldMap() {

+            return fieldMap;

+        }

+

+        public FlexibleStringExpander getResultMapListNameExdr() {

+            return resultMapListNameExdr;

+        }

+

+        public FlexibleMapAccessor<Map<String, Object>> getResultMapNameAcsr() {

+            return resultMapNameAcsr;

+        }

+

+        public FlexibleStringExpander getResultMapValueNameExdr() {

+            return resultMapValueNameExdr;

+        }

+

+        public FlexibleStringExpander getServiceNameExdr() {

+            return serviceNameExdr;

+        }

+

+        public FlexibleStringExpander getValueNameExdr() {

+            return valueNameExdr;

+        }

+

+        @Override

+        public void runAction(Map<String, Object> context) {

+            String serviceNameExpanded = this.serviceNameExdr.expandString(context);

+            if (UtilValidate.isEmpty(serviceNameExpanded)) {

+                throw new IllegalArgumentException("Service name was empty, expanded from: " + this.serviceNameExdr.getOriginal());

+            }

+            String autoFieldMapString = this.autoFieldMapExdr.expandString(context);

+            boolean autoFieldMapBool = !"false".equals(autoFieldMapString);

+            try {

+                Map<String, Object> serviceContext = null;

+                if (autoFieldMapBool) {

+                    serviceContext = WidgetWorker.getDispatcher(context).getDispatchContext()

+                            .makeValidContext(serviceNameExpanded, ModelService.IN_PARAM, context);

+                } else {

+                    serviceContext = new HashMap<String, Object>();

+                }

+                if (this.fieldMap != null) {

+                    EntityFinderUtil.expandFieldMapToContext(this.fieldMap, context, serviceContext);

+                }

+                Map<String, Object> result = WidgetWorker.getDispatcher(context).runSync(serviceNameExpanded, serviceContext);

+                if (!this.resultMapNameAcsr.isEmpty()) {

+                    this.resultMapNameAcsr.put(context, result);

+                    String queryString = (String) result.get("queryString");

+                    context.put("queryString", queryString);

+                    context.put("queryStringMap", result.get("queryStringMap"));

+                    if (UtilValidate.isNotEmpty(queryString)) {

+                        try {

+                            String queryStringEncoded = queryString.replaceAll("&", "%26");

+                            context.put("queryStringEncoded", queryStringEncoded);

+                        } catch (PatternSyntaxException e) {

+

+                        }

+                    }

+                } else {

+                    context.putAll(result);

+                }

+                String resultMapListName = resultMapListNameExdr.expandString(context);

+                //String resultMapListIteratorName = resultMapListIteratorNameExdr.expandString(context);

+                String resultMapValueName = resultMapValueNameExdr.expandString(context);

+                String valueName = valueNameExdr.expandString(context);

+                if (this.getModelSubNode() != null) {

+                    //ListIterator iter = null;

+                    if (UtilValidate.isNotEmpty(resultMapListName)) {

+                        List<? extends Map<String, ? extends Object>> lst = UtilGenerics.checkList(result.get(resultMapListName));

+                        if (lst != null) {

+                            if (lst instanceof ListIterator<?>) {

+                                ListIterator<? extends Map<String, ? extends Object>> listIt = UtilGenerics.cast(lst);

+                                this.getModelSubNode().setListIterator(listIt, context);

+                            } else {

+                                this.getModelSubNode().setListIterator(lst.listIterator(), context);

+                            }

+                        }

+                    }

+                } else {

+                    if (UtilValidate.isNotEmpty(resultMapValueName)) {

+                        if (UtilValidate.isNotEmpty(valueName)) {

+                            context.put(valueName, result.get(resultMapValueName));

+                        } else {

+                            Map<String, Object> resultMap = UtilGenerics.checkMap(result.get(resultMapValueName));

+                            context.putAll(resultMap);

+                        }

+                    }

+                }

+            } catch (GenericServiceException e) {

+                String errMsg = "Error calling service with name " + serviceNameExpanded + ": " + e.toString();

+                Debug.logError(e, errMsg, module);

+                throw new IllegalArgumentException(errMsg);

+            }

+        }

+    }

+}

diff --git a/framework/widget/src/org/ofbiz/widget/tree/ModelTreeCondition.java b/framework/widget/src/org/ofbiz/widget/model/ModelTreeCondition.java
similarity index 92%
rename from framework/widget/src/org/ofbiz/widget/tree/ModelTreeCondition.java
rename to framework/widget/src/org/ofbiz/widget/model/ModelTreeCondition.java
index 6812871..a225bfc 100644
--- a/framework/widget/src/org/ofbiz/widget/tree/ModelTreeCondition.java
+++ b/framework/widget/src/org/ofbiz/widget/model/ModelTreeCondition.java
@@ -1,41 +1,39 @@
-/*******************************************************************************
- * 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.tree;
-
-import org.ofbiz.widget.AbstractModelCondition;
-import org.ofbiz.widget.ModelCondition;
-import org.w3c.dom.Element;
-
-/**
- * Models the &lt;condition&gt; element.
- * 
- * @see <code>widget-tree.xsd</code>
- */
-public class ModelTreeCondition {
-    public static final String module = ModelTreeCondition.class.getName();
-    private final ModelCondition condition;
-
-    public ModelTreeCondition(ModelTree modelTree, Element conditionElement) {
-        this.condition = AbstractModelCondition.DEFAULT_CONDITION_FACTORY.newInstance(modelTree, conditionElement);
-    }
-
-    public ModelCondition getCondition() {
-        return condition;
-    }
-}
+/*******************************************************************************

+ * Licensed to the Apache Software Foundation (ASF) under one

+ * or more contributor license agreements.  See the NOTICE file

+ * distributed with this work for additional information

+ * regarding copyright ownership.  The ASF licenses this file

+ * to you under the Apache License, Version 2.0 (the

+ * "License"); you may not use this file except in compliance

+ * with the License.  You may obtain a copy of the License at

+ *

+ * http://www.apache.org/licenses/LICENSE-2.0

+ *

+ * Unless required by applicable law or agreed to in writing,

+ * software distributed under the License is distributed on an

+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY

+ * KIND, either express or implied.  See the License for the

+ * specific language governing permissions and limitations

+ * under the License.

+ *******************************************************************************/

+package org.ofbiz.widget.model;

+

+import org.w3c.dom.Element;

+

+/**

+ * Models the &lt;condition&gt; element.

+ * 

+ * @see <code>widget-tree.xsd</code>

+ */

+public class ModelTreeCondition {

+    public static final String module = ModelTreeCondition.class.getName();

+    private final ModelCondition condition;

+

+    public ModelTreeCondition(ModelTree modelTree, Element conditionElement) {

+        this.condition = AbstractModelCondition.DEFAULT_CONDITION_FACTORY.newInstance(modelTree, conditionElement);

+    }

+

+    public ModelCondition getCondition() {

+        return condition;

+    }

+}

diff --git a/framework/widget/src/org/ofbiz/widget/ModelWidget.java b/framework/widget/src/org/ofbiz/widget/model/ModelWidget.java
similarity index 98%
rename from framework/widget/src/org/ofbiz/widget/ModelWidget.java
rename to framework/widget/src/org/ofbiz/widget/model/ModelWidget.java
index 9c9e4b4..8aec83e 100644
--- a/framework/widget/src/org/ofbiz/widget/ModelWidget.java
+++ b/framework/widget/src/org/ofbiz/widget/model/ModelWidget.java
@@ -1,155 +1,154 @@
-/*******************************************************************************
- * 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;
-
-import java.io.Serializable;
-import java.util.Map;
-
-import org.ofbiz.base.util.Debug;
-import org.ofbiz.base.util.UtilGenerics;
-import org.ofbiz.base.util.UtilProperties;
-import org.ofbiz.widget.xml.XmlWidgetVisitor;
-import org.w3c.dom.Element;
-
-/**
- * Widget Library - Widget model class. ModelWidget is a base class that is
- * extended by other widget model classes.
- */
-@SuppressWarnings("serial")
-public abstract class ModelWidget implements Serializable {
-
-    public static final String module = ModelWidget.class.getName();
-    /**
-     * The parameter name used to control widget boundary comments. Currently
-     * set to "widgetVerbose".
-     */
-    public static final String enableBoundaryCommentsParam = "widgetVerbose";
-
-    private final String name;
-    private final String systemId;
-    private final int startColumn;
-    private final int startLine;
-
-    /**
-     * Derived classes must call this constructor.
-     * @param name The widget name
-     */
-    protected ModelWidget(String name) {
-        this.name = name;
-        this.systemId = "anonymous";
-        this.startColumn = 0;
-        this.startLine = 0;
-    }
-
-    /**
-     * Derived classes must call this constructor.
-     * @param widgetElement The XML Element for the widget
-     */
-    protected ModelWidget(Element widgetElement) {
-        this.name = widgetElement.getAttribute("name");
-        this.systemId = (String) widgetElement.getUserData("systemId");
-        this.startColumn = ((Integer) widgetElement.getUserData("startColumn")).intValue();
-        this.startLine = ((Integer) widgetElement.getUserData("startLine")).intValue();
-    }
-
-    public abstract void accept(ModelWidgetVisitor visitor) throws Exception;
-
-    /**
-     * Returns the widget's name.
-     * @return Widget's name
-     */
-    public String getName() {
-        return name;
-    }
-
-    /**
-     * Returns the url as a string, from where this widget was defined.
-     * @return url
-     */
-    public String getSystemId() {
-        return systemId;
-    }
-
-    /**
-     * Returns the column where this widget was defined, in it's containing xml file.
-     * @return start column
-     */
-    public int getStartColumn() {
-        return startColumn;
-    }
-
-    /**
-     * Returns the line where this widget was defined, in it's containing xml file.
-     * @return start line
-     */
-    public int getStartLine() {
-        return startLine;
-    }
-
-    @Override
-    public String toString() {
-        StringBuilder sb = new StringBuilder();
-        ModelWidgetVisitor visitor = new XmlWidgetVisitor(sb);
-        try {
-            accept(visitor);
-        } catch (Exception e) {
-            Debug.logWarning(e, "Exception thrown in XmlWidgetVisitor: ", module);
-        }
-        return sb.toString();
-    }
-
-    /**
-     * Returns the widget's name to be used in boundary comments. The default action
-     * is to return the widget's name. Derived classes can override this method to
-     * return a customized name.
-     * @return Name to be used in boundary comments
-     */
-    public String getBoundaryCommentName() {
-        return name;
-    }
-
-    /**
-     * Returns <code>true</code> if widget boundary comments are enabled. Widget boundary comments are
-     * enabled by setting <code>widget.verbose=true</code> in the <code>widget.properties</code> file.
-     * The <code>true</code> setting can be overridden in <code>web.xml</code> or in the screen
-     * rendering context. If <code>widget.verbose</code> is set to <code>false</code> in the
-     * <code>widget.properties</code> file, then that setting will override all other settings and
-     * disable all widget boundary comments.
-     * 
-     * @param context Optional context Map
-     */
-    public static boolean widgetBoundaryCommentsEnabled(Map<String, ? extends Object> context) {
-        boolean result = "true".equals(UtilProperties.getPropertyValue("widget", "widget.verbose"));
-        if (result && context != null) {
-            String str = (String) context.get(enableBoundaryCommentsParam);
-            if (str != null) {
-                result = "true".equals(str);
-            } else{
-                Map<String, ? extends Object> parameters = UtilGenerics.checkMap(context.get("parameters"));
-                if (parameters != null) {
-                    str = (String) parameters.get(enableBoundaryCommentsParam);
-                    if (str != null) {
-                        result = "true".equals(str);
-                    }
-                }
-            }
-        }
-        return result;
-    }
-}
+/*******************************************************************************

+ * Licensed to the Apache Software Foundation (ASF) under one

+ * or more contributor license agreements.  See the NOTICE file

+ * distributed with this work for additional information

+ * regarding copyright ownership.  The ASF licenses this file

+ * to you under the Apache License, Version 2.0 (the

+ * "License"); you may not use this file except in compliance

+ * with the License.  You may obtain a copy of the License at

+ *

+ * http://www.apache.org/licenses/LICENSE-2.0

+ *

+ * Unless required by applicable law or agreed to in writing,

+ * software distributed under the License is distributed on an

+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY

+ * KIND, either express or implied.  See the License for the

+ * specific language governing permissions and limitations

+ * under the License.

+ *******************************************************************************/

+package org.ofbiz.widget.model;

+

+import java.io.Serializable;

+import java.util.Map;

+

+import org.ofbiz.base.util.Debug;

+import org.ofbiz.base.util.UtilGenerics;

+import org.ofbiz.base.util.UtilProperties;

+import org.w3c.dom.Element;

+

+/**

+ * Widget Library - Widget model class. ModelWidget is a base class that is

+ * extended by other widget model classes.

+ */

+@SuppressWarnings("serial")

+public abstract class ModelWidget implements Serializable {

+

+    public static final String module = ModelWidget.class.getName();

+    /**

+     * The parameter name used to control widget boundary comments. Currently

+     * set to "widgetVerbose".

+     */

+    public static final String enableBoundaryCommentsParam = "widgetVerbose";

+

+    private final String name;

+    private final String systemId;

+    private final int startColumn;

+    private final int startLine;

+

+    /**

+     * Derived classes must call this constructor.

+     * @param name The widget name

+     */

+    protected ModelWidget(String name) {

+        this.name = name;

+        this.systemId = "anonymous";

+        this.startColumn = 0;

+        this.startLine = 0;

+    }

+

+    /**

+     * Derived classes must call this constructor.

+     * @param widgetElement The XML Element for the widget

+     */

+    protected ModelWidget(Element widgetElement) {

+        this.name = widgetElement.getAttribute("name");

+        this.systemId = (String) widgetElement.getUserData("systemId");

+        this.startColumn = ((Integer) widgetElement.getUserData("startColumn")).intValue();

+        this.startLine = ((Integer) widgetElement.getUserData("startLine")).intValue();

+    }

+

+    public abstract void accept(ModelWidgetVisitor visitor) throws Exception;

+

+    /**

+     * Returns the widget's name.

+     * @return Widget's name

+     */

+    public String getName() {

+        return name;

+    }

+

+    /**

+     * Returns the url as a string, from where this widget was defined.

+     * @return url

+     */

+    public String getSystemId() {

+        return systemId;

+    }

+

+    /**

+     * Returns the column where this widget was defined, in it's containing xml file.

+     * @return start column

+     */

+    public int getStartColumn() {

+        return startColumn;

+    }

+

+    /**

+     * Returns the line where this widget was defined, in it's containing xml file.

+     * @return start line

+     */

+    public int getStartLine() {

+        return startLine;

+    }

+

+    @Override

+    public String toString() {

+        StringBuilder sb = new StringBuilder();

+        ModelWidgetVisitor visitor = new XmlWidgetVisitor(sb);

+        try {

+            accept(visitor);

+        } catch (Exception e) {

+            Debug.logWarning(e, "Exception thrown in XmlWidgetVisitor: ", module);

+        }

+        return sb.toString();

+    }

+

+    /**

+     * Returns the widget's name to be used in boundary comments. The default action

+     * is to return the widget's name. Derived classes can override this method to

+     * return a customized name.

+     * @return Name to be used in boundary comments

+     */

+    public String getBoundaryCommentName() {

+        return name;

+    }

+

+    /**

+     * Returns <code>true</code> if widget boundary comments are enabled. Widget boundary comments are

+     * enabled by setting <code>widget.verbose=true</code> in the <code>widget.properties</code> file.

+     * The <code>true</code> setting can be overridden in <code>web.xml</code> or in the screen

+     * rendering context. If <code>widget.verbose</code> is set to <code>false</code> in the

+     * <code>widget.properties</code> file, then that setting will override all other settings and

+     * disable all widget boundary comments.

+     * 

+     * @param context Optional context Map

+     */

+    public static boolean widgetBoundaryCommentsEnabled(Map<String, ? extends Object> context) {

+        boolean result = "true".equals(UtilProperties.getPropertyValue("widget", "widget.verbose"));

+        if (result && context != null) {

+            String str = (String) context.get(enableBoundaryCommentsParam);

+            if (str != null) {

+                result = "true".equals(str);

+            } else{

+                Map<String, ? extends Object> parameters = UtilGenerics.checkMap(context.get("parameters"));

+                if (parameters != null) {

+                    str = (String) parameters.get(enableBoundaryCommentsParam);

+                    if (str != null) {

+                        result = "true".equals(str);

+                    }

+                }

+            }

+        }

+        return result;

+    }

+}

diff --git a/framework/widget/src/org/ofbiz/widget/ModelWidgetCondition.java b/framework/widget/src/org/ofbiz/widget/model/ModelWidgetCondition.java
similarity index 99%
rename from framework/widget/src/org/ofbiz/widget/ModelWidgetCondition.java
rename to framework/widget/src/org/ofbiz/widget/model/ModelWidgetCondition.java
index 56feb69..99fce33 100644
--- a/framework/widget/src/org/ofbiz/widget/ModelWidgetCondition.java
+++ b/framework/widget/src/org/ofbiz/widget/model/ModelWidgetCondition.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations

  * under the License.

  *******************************************************************************/

-package org.ofbiz.widget;

+package org.ofbiz.widget.model;

 

 import java.io.Serializable;

 import java.lang.reflect.Method;

diff --git a/framework/widget/src/org/ofbiz/widget/ModelWidgetVisitor.java b/framework/widget/src/org/ofbiz/widget/model/ModelWidgetVisitor.java
similarity index 89%
rename from framework/widget/src/org/ofbiz/widget/ModelWidgetVisitor.java
rename to framework/widget/src/org/ofbiz/widget/model/ModelWidgetVisitor.java
index c2b13ca..50643fa 100644
--- a/framework/widget/src/org/ofbiz/widget/ModelWidgetVisitor.java
+++ b/framework/widget/src/org/ofbiz/widget/model/ModelWidgetVisitor.java
@@ -16,16 +16,9 @@
  * specific language governing permissions and limitations

  * under the License.

  *******************************************************************************/

-package org.ofbiz.widget;

+package org.ofbiz.widget.model;

 

-import org.ofbiz.widget.form.ModelForm;

-import org.ofbiz.widget.menu.ModelMenu;

-import org.ofbiz.widget.menu.ModelMenuItem;

-import org.ofbiz.widget.screen.HtmlWidget;

-import org.ofbiz.widget.screen.IterateSectionWidget;

-import org.ofbiz.widget.screen.ModelScreen;

-import org.ofbiz.widget.screen.ModelScreenWidget;

-import org.ofbiz.widget.tree.ModelTree;

+import org.ofbiz.widget.model.HtmlWidget;

 

 /**

  *  A <code>ModelWidget</code> visitor.

diff --git a/framework/widget/src/org/ofbiz/widget/screen/ScreenFactory.java b/framework/widget/src/org/ofbiz/widget/model/ScreenFactory.java
similarity index 98%
rename from framework/widget/src/org/ofbiz/widget/screen/ScreenFactory.java
rename to framework/widget/src/org/ofbiz/widget/model/ScreenFactory.java
index 1cdaaa1..d6021ef 100644
--- a/framework/widget/src/org/ofbiz/widget/screen/ScreenFactory.java
+++ b/framework/widget/src/org/ofbiz/widget/model/ScreenFactory.java
@@ -1,212 +1,213 @@
-/*******************************************************************************
- * 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.screen;
-
-import java.io.IOException;
-import java.net.URL;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import javax.servlet.ServletContext;
-import javax.servlet.http.HttpServletRequest;
-import javax.xml.parsers.ParserConfigurationException;
-
-import org.ofbiz.base.location.FlexibleLocation;
-import org.ofbiz.base.util.Debug;
-import org.ofbiz.base.util.GeneralException;
-import org.ofbiz.base.util.UtilHttp;
-import org.ofbiz.base.util.UtilValidate;
-import org.ofbiz.base.util.UtilXml;
-import org.ofbiz.base.util.cache.UtilCache;
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-import org.xml.sax.SAXException;
-
-
-/**
- * Widget Library - Screen factory class
- */
-public class ScreenFactory {
-
-    public static final String module = ScreenFactory.class.getName();
-
-    public static final UtilCache<String, Map<String, ModelScreen>> screenLocationCache = UtilCache.createUtilCache("widget.screen.locationResource", 0, 0, false);
-    public static final UtilCache<String, Map<String, ModelScreen>> screenWebappCache = UtilCache.createUtilCache("widget.screen.webappResource", 0, 0, false);
-
-    public static boolean isCombinedName(String combinedName) {
-        int numSignIndex = combinedName.lastIndexOf("#");
-        if (numSignIndex == -1) {
-            return false;
-        }
-        if (numSignIndex + 1 >= combinedName.length()) {
-            return false;
-        }
-        return true;
-    }
-
-    public static String getResourceNameFromCombined(String combinedName) {
-        // split out the name on the last "#"
-        int numSignIndex = combinedName.lastIndexOf("#");
-        if (numSignIndex == -1) {
-            throw new IllegalArgumentException("Error in screen location/name: no \"#\" found to separate the location from the name; correct example: component://product/screen/product/ProductScreens.xml#EditProduct");
-        }
-        if (numSignIndex + 1 >= combinedName.length()) {
-            throw new IllegalArgumentException("Error in screen location/name: the \"#\" was at the end with no screen name after it; correct example: component://product/screen/product/ProductScreens.xml#EditProduct");
-        }
-        String resourceName = combinedName.substring(0, numSignIndex);
-        return resourceName;
-    }
-
-    public static String getScreenNameFromCombined(String combinedName) {
-        // split out the name on the last "#"
-        int numSignIndex = combinedName.lastIndexOf("#");
-        if (numSignIndex == -1) {
-            throw new IllegalArgumentException("Error in screen location/name: no \"#\" found to separate the location from the name; correct example: component://product/screen/product/ProductScreens.xml#EditProduct");
-        }
-        if (numSignIndex + 1 >= combinedName.length()) {
-            throw new IllegalArgumentException("Error in screen location/name: the \"#\" was at the end with no screen name after it; correct example: component://product/screen/product/ProductScreens.xml#EditProduct");
-        }
-        String screenName = combinedName.substring(numSignIndex + 1);
-        return screenName;
-    }
-
-    public static ModelScreen getScreenFromLocation(String combinedName)
-            throws IOException, SAXException, ParserConfigurationException {
-        String resourceName = getResourceNameFromCombined(combinedName);
-        String screenName = getScreenNameFromCombined(combinedName);
-        return getScreenFromLocation(resourceName, screenName);
-    }
-
-    public static ModelScreen getScreenFromLocation(String resourceName, String screenName)
-            throws IOException, SAXException, ParserConfigurationException {
-        Map<String, ModelScreen> modelScreenMap = getScreensFromLocation(resourceName);
-        ModelScreen modelScreen = modelScreenMap.get(screenName);
-        if (modelScreen == null) {
-            throw new IllegalArgumentException("Could not find screen with name [" + screenName + "] in class resource [" + resourceName + "]");
-        }
-        return modelScreen;
-    }
-
-    public static Map<String, ModelScreen> getScreensFromLocation(String resourceName)
-            throws IOException, SAXException, ParserConfigurationException {
-        Map<String, ModelScreen> modelScreenMap = screenLocationCache.get(resourceName);
-        if (modelScreenMap == null) {
-            synchronized (ScreenFactory.class) {
-                modelScreenMap = screenLocationCache.get(resourceName);
-                if (modelScreenMap == null) {
-                    long startTime = System.currentTimeMillis();
-                    URL screenFileUrl = null;
-                    screenFileUrl = FlexibleLocation.resolveLocation(resourceName);
-                    if (screenFileUrl == null) {
-                        throw new IllegalArgumentException("Could not resolve location to URL: " + resourceName);
-                    }
-                    Document screenFileDoc = UtilXml.readXmlDocument(screenFileUrl, true, true);
-                    modelScreenMap = readScreenDocument(screenFileDoc, resourceName);
-                    screenLocationCache.put(resourceName, modelScreenMap);
-                    double totalSeconds = (System.currentTimeMillis() - startTime)/1000.0;
-                    Debug.logInfo("Got " + modelScreenMap.size() + " screens in " + totalSeconds + "s from: " + screenFileUrl.toExternalForm(), module);
-                }
-            }
-        }
-
-        if (modelScreenMap.isEmpty()) {
-            throw new IllegalArgumentException("Could not find screen file with name [" + resourceName + "]");
-        }
-        return modelScreenMap;
-    }
-
-    public static ModelScreen getScreenFromWebappContext(String resourceName, String screenName, HttpServletRequest request)
-            throws IOException, SAXException, ParserConfigurationException {
-        String webappName = UtilHttp.getApplicationName(request);
-        String cacheKey = webappName + "::" + resourceName;
-
-
-        Map<String, ModelScreen> modelScreenMap = screenWebappCache.get(cacheKey);
-        if (modelScreenMap == null) {
-            synchronized (ScreenFactory.class) {
-                modelScreenMap = screenWebappCache.get(cacheKey);
-                if (modelScreenMap == null) {
-                    ServletContext servletContext = (ServletContext) request.getAttribute("servletContext");
-
-                    URL screenFileUrl = servletContext.getResource(resourceName);
-                    Document screenFileDoc = UtilXml.readXmlDocument(screenFileUrl, true, true);
-                    modelScreenMap = readScreenDocument(screenFileDoc, resourceName);
-                    screenWebappCache.put(cacheKey, modelScreenMap);
-                }
-            }
-        }
-
-        ModelScreen modelScreen = modelScreenMap.get(screenName);
-        if (modelScreen == null) {
-            throw new IllegalArgumentException("Could not find screen with name [" + screenName + "] in webapp resource [" + resourceName + "] in the webapp [" + webappName + "]");
-        }
-        return modelScreen;
-    }
-
-    public static Map<String, ModelScreen> readScreenDocument(Document screenFileDoc, String sourceLocation) {
-        Map<String, ModelScreen> modelScreenMap = new HashMap<String, ModelScreen>();
-        if (screenFileDoc != null) {
-            // read document and construct ModelScreen for each screen element
-            Element rootElement = screenFileDoc.getDocumentElement();
-            List<? extends Element> screenElements = UtilXml.childElementList(rootElement, "screen");
-            for (Element screenElement: screenElements) {
-                ModelScreen modelScreen = new ModelScreen(screenElement, modelScreenMap, sourceLocation);
-                //Debug.logInfo("Read Screen with name: " + modelScreen.getName(), module);
-                modelScreenMap.put(modelScreen.getName(), modelScreen);
-            }
-        }
-        return modelScreenMap;
-    }
-
-    public static void renderReferencedScreen(String name, String location, ModelScreenWidget parentWidget, Appendable writer, Map<String, Object> context, ScreenStringRenderer screenStringRenderer) throws GeneralException, IOException {
-        // check to see if the name is a composite name separated by a #, if so split it up and get it by the full loc#name
-        if (ScreenFactory.isCombinedName(name)) {
-            String combinedName = name;
-            location = ScreenFactory.getResourceNameFromCombined(combinedName);
-            name = ScreenFactory.getScreenNameFromCombined(combinedName);
-        }
-
-        ModelScreen modelScreen = null;
-        if (UtilValidate.isNotEmpty(location)) {
-            try {
-                modelScreen = ScreenFactory.getScreenFromLocation(location, name);
-            } catch (IOException e) {
-                String errMsg = "Error rendering included screen named [" + name + "] at location [" + location + "]: " + e.toString();
-                Debug.logError(e, errMsg, module);
-                throw new RuntimeException(errMsg);
-            } catch (SAXException e) {
-                String errMsg = "Error rendering included screen named [" + name + "] at location [" + location + "]: " + e.toString();
-                Debug.logError(e, errMsg, module);
-                throw new RuntimeException(errMsg);
-            } catch (ParserConfigurationException e) {
-                String errMsg = "Error rendering included screen named [" + name + "] at location [" + location + "]: " + e.toString();
-                Debug.logError(e, errMsg, module);
-                throw new RuntimeException(errMsg);
-            }
-        } else {
-            modelScreen = parentWidget.getModelScreen().getModelScreenMap().get(name);
-            if (modelScreen == null) {
-                throw new IllegalArgumentException("Could not find screen with name [" + name + "] in the same file as the screen with name [" + parentWidget.getModelScreen().getName() + "]");
-            }
-        }
-        //Debug.logInfo("parent(" + parentWidget + ") rendering(" + modelScreen + ")", module);
-        modelScreen.renderScreenString(writer, context, screenStringRenderer);
-    }
-}
+/*******************************************************************************

+ * Licensed to the Apache Software Foundation (ASF) under one

+ * or more contributor license agreements.  See the NOTICE file

+ * distributed with this work for additional information

+ * regarding copyright ownership.  The ASF licenses this file

+ * to you under the Apache License, Version 2.0 (the

+ * "License"); you may not use this file except in compliance

+ * with the License.  You may obtain a copy of the License at

+ *

+ * http://www.apache.org/licenses/LICENSE-2.0

+ *

+ * Unless required by applicable law or agreed to in writing,

+ * software distributed under the License is distributed on an

+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY

+ * KIND, either express or implied.  See the License for the

+ * specific language governing permissions and limitations

+ * under the License.

+ *******************************************************************************/

+package org.ofbiz.widget.model;

+

+import java.io.IOException;

+import java.net.URL;

+import java.util.HashMap;

+import java.util.List;

+import java.util.Map;

+

+import javax.servlet.ServletContext;

+import javax.servlet.http.HttpServletRequest;

+import javax.xml.parsers.ParserConfigurationException;

+

+import org.ofbiz.base.location.FlexibleLocation;

+import org.ofbiz.base.util.Debug;

+import org.ofbiz.base.util.GeneralException;

+import org.ofbiz.base.util.UtilHttp;

+import org.ofbiz.base.util.UtilValidate;

+import org.ofbiz.base.util.UtilXml;

+import org.ofbiz.base.util.cache.UtilCache;

+import org.ofbiz.widget.renderer.ScreenStringRenderer;

+import org.w3c.dom.Document;

+import org.w3c.dom.Element;

+import org.xml.sax.SAXException;

+

+

+/**

+ * Widget Library - Screen factory class

+ */

+public class ScreenFactory {

+

+    public static final String module = ScreenFactory.class.getName();

+

+    public static final UtilCache<String, Map<String, ModelScreen>> screenLocationCache = UtilCache.createUtilCache("widget.screen.locationResource", 0, 0, false);

+    public static final UtilCache<String, Map<String, ModelScreen>> screenWebappCache = UtilCache.createUtilCache("widget.screen.webappResource", 0, 0, false);

+

+    public static boolean isCombinedName(String combinedName) {

+        int numSignIndex = combinedName.lastIndexOf("#");

+        if (numSignIndex == -1) {

+            return false;

+        }

+        if (numSignIndex + 1 >= combinedName.length()) {

+            return false;

+        }

+        return true;

+    }

+

+    public static String getResourceNameFromCombined(String combinedName) {

+        // split out the name on the last "#"

+        int numSignIndex = combinedName.lastIndexOf("#");

+        if (numSignIndex == -1) {

+            throw new IllegalArgumentException("Error in screen location/name: no \"#\" found to separate the location from the name; correct example: component://product/screen/product/ProductScreens.xml#EditProduct");

+        }

+        if (numSignIndex + 1 >= combinedName.length()) {

+            throw new IllegalArgumentException("Error in screen location/name: the \"#\" was at the end with no screen name after it; correct example: component://product/screen/product/ProductScreens.xml#EditProduct");

+        }

+        String resourceName = combinedName.substring(0, numSignIndex);

+        return resourceName;

+    }

+

+    public static String getScreenNameFromCombined(String combinedName) {

+        // split out the name on the last "#"

+        int numSignIndex = combinedName.lastIndexOf("#");

+        if (numSignIndex == -1) {

+            throw new IllegalArgumentException("Error in screen location/name: no \"#\" found to separate the location from the name; correct example: component://product/screen/product/ProductScreens.xml#EditProduct");

+        }

+        if (numSignIndex + 1 >= combinedName.length()) {

+            throw new IllegalArgumentException("Error in screen location/name: the \"#\" was at the end with no screen name after it; correct example: component://product/screen/product/ProductScreens.xml#EditProduct");

+        }

+        String screenName = combinedName.substring(numSignIndex + 1);

+        return screenName;

+    }

+

+    public static ModelScreen getScreenFromLocation(String combinedName)

+            throws IOException, SAXException, ParserConfigurationException {

+        String resourceName = getResourceNameFromCombined(combinedName);

+        String screenName = getScreenNameFromCombined(combinedName);

+        return getScreenFromLocation(resourceName, screenName);

+    }

+

+    public static ModelScreen getScreenFromLocation(String resourceName, String screenName)

+            throws IOException, SAXException, ParserConfigurationException {

+        Map<String, ModelScreen> modelScreenMap = getScreensFromLocation(resourceName);

+        ModelScreen modelScreen = modelScreenMap.get(screenName);

+        if (modelScreen == null) {

+            throw new IllegalArgumentException("Could not find screen with name [" + screenName + "] in class resource [" + resourceName + "]");

+        }

+        return modelScreen;

+    }

+

+    public static Map<String, ModelScreen> getScreensFromLocation(String resourceName)

+            throws IOException, SAXException, ParserConfigurationException {

+        Map<String, ModelScreen> modelScreenMap = screenLocationCache.get(resourceName);

+        if (modelScreenMap == null) {

+            synchronized (ScreenFactory.class) {

+                modelScreenMap = screenLocationCache.get(resourceName);

+                if (modelScreenMap == null) {

+                    long startTime = System.currentTimeMillis();

+                    URL screenFileUrl = null;

+                    screenFileUrl = FlexibleLocation.resolveLocation(resourceName);

+                    if (screenFileUrl == null) {

+                        throw new IllegalArgumentException("Could not resolve location to URL: " + resourceName);

+                    }

+                    Document screenFileDoc = UtilXml.readXmlDocument(screenFileUrl, true, true);

+                    modelScreenMap = readScreenDocument(screenFileDoc, resourceName);

+                    screenLocationCache.put(resourceName, modelScreenMap);

+                    double totalSeconds = (System.currentTimeMillis() - startTime)/1000.0;

+                    Debug.logInfo("Got " + modelScreenMap.size() + " screens in " + totalSeconds + "s from: " + screenFileUrl.toExternalForm(), module);

+                }

+            }

+        }

+

+        if (modelScreenMap.isEmpty()) {

+            throw new IllegalArgumentException("Could not find screen file with name [" + resourceName + "]");

+        }

+        return modelScreenMap;

+    }

+

+    public static ModelScreen getScreenFromWebappContext(String resourceName, String screenName, HttpServletRequest request)

+            throws IOException, SAXException, ParserConfigurationException {

+        String webappName = UtilHttp.getApplicationName(request);

+        String cacheKey = webappName + "::" + resourceName;

+

+

+        Map<String, ModelScreen> modelScreenMap = screenWebappCache.get(cacheKey);

+        if (modelScreenMap == null) {

+            synchronized (ScreenFactory.class) {

+                modelScreenMap = screenWebappCache.get(cacheKey);

+                if (modelScreenMap == null) {

+                    ServletContext servletContext = (ServletContext) request.getAttribute("servletContext");

+

+                    URL screenFileUrl = servletContext.getResource(resourceName);

+                    Document screenFileDoc = UtilXml.readXmlDocument(screenFileUrl, true, true);

+                    modelScreenMap = readScreenDocument(screenFileDoc, resourceName);

+                    screenWebappCache.put(cacheKey, modelScreenMap);

+                }

+            }

+        }

+

+        ModelScreen modelScreen = modelScreenMap.get(screenName);

+        if (modelScreen == null) {

+            throw new IllegalArgumentException("Could not find screen with name [" + screenName + "] in webapp resource [" + resourceName + "] in the webapp [" + webappName + "]");

+        }

+        return modelScreen;

+    }

+

+    public static Map<String, ModelScreen> readScreenDocument(Document screenFileDoc, String sourceLocation) {

+        Map<String, ModelScreen> modelScreenMap = new HashMap<String, ModelScreen>();

+        if (screenFileDoc != null) {

+            // read document and construct ModelScreen for each screen element

+            Element rootElement = screenFileDoc.getDocumentElement();

+            List<? extends Element> screenElements = UtilXml.childElementList(rootElement, "screen");

+            for (Element screenElement: screenElements) {

+                ModelScreen modelScreen = new ModelScreen(screenElement, modelScreenMap, sourceLocation);

+                //Debug.logInfo("Read Screen with name: " + modelScreen.getName(), module);

+                modelScreenMap.put(modelScreen.getName(), modelScreen);

+            }

+        }

+        return modelScreenMap;

+    }

+

+    public static void renderReferencedScreen(String name, String location, ModelScreenWidget parentWidget, Appendable writer, Map<String, Object> context, ScreenStringRenderer screenStringRenderer) throws GeneralException, IOException {

+        // check to see if the name is a composite name separated by a #, if so split it up and get it by the full loc#name

+        if (ScreenFactory.isCombinedName(name)) {

+            String combinedName = name;

+            location = ScreenFactory.getResourceNameFromCombined(combinedName);

+            name = ScreenFactory.getScreenNameFromCombined(combinedName);

+        }

+

+        ModelScreen modelScreen = null;

+        if (UtilValidate.isNotEmpty(location)) {

+            try {

+                modelScreen = ScreenFactory.getScreenFromLocation(location, name);

+            } catch (IOException e) {

+                String errMsg = "Error rendering included screen named [" + name + "] at location [" + location + "]: " + e.toString();

+                Debug.logError(e, errMsg, module);

+                throw new RuntimeException(errMsg);

+            } catch (SAXException e) {

+                String errMsg = "Error rendering included screen named [" + name + "] at location [" + location + "]: " + e.toString();

+                Debug.logError(e, errMsg, module);

+                throw new RuntimeException(errMsg);

+            } catch (ParserConfigurationException e) {

+                String errMsg = "Error rendering included screen named [" + name + "] at location [" + location + "]: " + e.toString();

+                Debug.logError(e, errMsg, module);

+                throw new RuntimeException(errMsg);

+            }

+        } else {

+            modelScreen = parentWidget.getModelScreen().getModelScreenMap().get(name);

+            if (modelScreen == null) {

+                throw new IllegalArgumentException("Could not find screen with name [" + name + "] in the same file as the screen with name [" + parentWidget.getModelScreen().getName() + "]");

+            }

+        }

+        //Debug.logInfo("parent(" + parentWidget + ") rendering(" + modelScreen + ")", module);

+        modelScreen.renderScreenString(writer, context, screenStringRenderer);

+    }

+}

diff --git a/framework/widget/src/org/ofbiz/widget/tree/TreeFactory.java b/framework/widget/src/org/ofbiz/widget/model/TreeFactory.java
similarity index 98%
rename from framework/widget/src/org/ofbiz/widget/tree/TreeFactory.java
rename to framework/widget/src/org/ofbiz/widget/model/TreeFactory.java
index 9e64cae..7772e7f 100644
--- a/framework/widget/src/org/ofbiz/widget/tree/TreeFactory.java
+++ b/framework/widget/src/org/ofbiz/widget/model/TreeFactory.java
@@ -1,87 +1,87 @@
-/*******************************************************************************
- * 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.tree;
-
-import java.io.IOException;
-import java.net.URL;
-import java.util.HashMap;
-import java.util.Map;
-
-import javax.xml.parsers.ParserConfigurationException;
-
-import org.ofbiz.base.location.FlexibleLocation;
-import org.ofbiz.base.util.UtilXml;
-import org.ofbiz.base.util.cache.UtilCache;
-import org.ofbiz.entity.Delegator;
-import org.ofbiz.service.LocalDispatcher;
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-import org.xml.sax.SAXException;
-
-
-/**
- * Widget Library - Tree factory class
- */
-public class TreeFactory {
-
-    public static final String module = TreeFactory.class.getName();
-
-    public static final UtilCache<String, Map<String, ModelTree>> treeLocationCache = UtilCache.createUtilCache("widget.tree.locationResource", 0, 0, false);
-
-    public static ModelTree getTreeFromLocation(String resourceName, String treeName, Delegator delegator, LocalDispatcher dispatcher)
-            throws IOException, SAXException, ParserConfigurationException {
-        Map<String, ModelTree> modelTreeMap = treeLocationCache.get(resourceName);
-        if (modelTreeMap == null) {
-            synchronized (TreeFactory.class) {
-                modelTreeMap = treeLocationCache.get(resourceName);
-                if (modelTreeMap == null) {
-                    ClassLoader loader = Thread.currentThread().getContextClassLoader();
-                    if (loader == null) {
-                        loader = TreeFactory.class.getClassLoader();
-                    }
-
-                    URL treeFileUrl = null;
-                    treeFileUrl = FlexibleLocation.resolveLocation(resourceName); //, loader);
-                    Document treeFileDoc = UtilXml.readXmlDocument(treeFileUrl, true, true);
-                    modelTreeMap = readTreeDocument(treeFileDoc, delegator, dispatcher, resourceName);
-                    treeLocationCache.put(resourceName, modelTreeMap);
-                }
-            }
-        }
-
-        ModelTree modelTree = modelTreeMap.get(treeName);
-        if (modelTree == null) {
-            throw new IllegalArgumentException("Could not find tree with name [" + treeName + "] in class resource [" + resourceName + "]");
-        }
-        return modelTree;
-    }
-
-    public static Map<String, ModelTree> readTreeDocument(Document treeFileDoc, Delegator delegator, LocalDispatcher dispatcher, String treeLocation) {
-        Map<String, ModelTree> modelTreeMap = new HashMap<String, ModelTree>();
-        if (treeFileDoc != null) {
-            // read document and construct ModelTree for each tree element
-            Element rootElement = treeFileDoc.getDocumentElement();
-            for (Element treeElement: UtilXml.childElementList(rootElement, "tree")) {
-                ModelTree modelTree = new ModelTree(treeElement, treeLocation);
-                modelTreeMap.put(modelTree.getName(), modelTree);
-            }
-        }
-        return modelTreeMap;
-    }
-}
+/*******************************************************************************

+ * Licensed to the Apache Software Foundation (ASF) under one

+ * or more contributor license agreements.  See the NOTICE file

+ * distributed with this work for additional information

+ * regarding copyright ownership.  The ASF licenses this file

+ * to you under the Apache License, Version 2.0 (the

+ * "License"); you may not use this file except in compliance

+ * with the License.  You may obtain a copy of the License at

+ *

+ * http://www.apache.org/licenses/LICENSE-2.0

+ *

+ * Unless required by applicable law or agreed to in writing,

+ * software distributed under the License is distributed on an

+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY

+ * KIND, either express or implied.  See the License for the

+ * specific language governing permissions and limitations

+ * under the License.

+ *******************************************************************************/

+package org.ofbiz.widget.model;

+

+import java.io.IOException;

+import java.net.URL;

+import java.util.HashMap;

+import java.util.Map;

+

+import javax.xml.parsers.ParserConfigurationException;

+

+import org.ofbiz.base.location.FlexibleLocation;

+import org.ofbiz.base.util.UtilXml;

+import org.ofbiz.base.util.cache.UtilCache;

+import org.ofbiz.entity.Delegator;

+import org.ofbiz.service.LocalDispatcher;

+import org.w3c.dom.Document;

+import org.w3c.dom.Element;

+import org.xml.sax.SAXException;

+

+

+/**

+ * Widget Library - Tree factory class

+ */

+public class TreeFactory {

+

+    public static final String module = TreeFactory.class.getName();

+

+    public static final UtilCache<String, Map<String, ModelTree>> treeLocationCache = UtilCache.createUtilCache("widget.tree.locationResource", 0, 0, false);

+

+    public static ModelTree getTreeFromLocation(String resourceName, String treeName, Delegator delegator, LocalDispatcher dispatcher)

+            throws IOException, SAXException, ParserConfigurationException {

+        Map<String, ModelTree> modelTreeMap = treeLocationCache.get(resourceName);

+        if (modelTreeMap == null) {

+            synchronized (TreeFactory.class) {

+                modelTreeMap = treeLocationCache.get(resourceName);

+                if (modelTreeMap == null) {

+                    ClassLoader loader = Thread.currentThread().getContextClassLoader();

+                    if (loader == null) {

+                        loader = TreeFactory.class.getClassLoader();

+                    }

+

+                    URL treeFileUrl = null;

+                    treeFileUrl = FlexibleLocation.resolveLocation(resourceName); //, loader);

+                    Document treeFileDoc = UtilXml.readXmlDocument(treeFileUrl, true, true);

+                    modelTreeMap = readTreeDocument(treeFileDoc, delegator, dispatcher, resourceName);

+                    treeLocationCache.put(resourceName, modelTreeMap);

+                }

+            }

+        }

+

+        ModelTree modelTree = modelTreeMap.get(treeName);

+        if (modelTree == null) {

+            throw new IllegalArgumentException("Could not find tree with name [" + treeName + "] in class resource [" + resourceName + "]");

+        }

+        return modelTree;

+    }

+

+    public static Map<String, ModelTree> readTreeDocument(Document treeFileDoc, Delegator delegator, LocalDispatcher dispatcher, String treeLocation) {

+        Map<String, ModelTree> modelTreeMap = new HashMap<String, ModelTree>();

+        if (treeFileDoc != null) {

+            // read document and construct ModelTree for each tree element

+            Element rootElement = treeFileDoc.getDocumentElement();

+            for (Element treeElement: UtilXml.childElementList(rootElement, "tree")) {

+                ModelTree modelTree = new ModelTree(treeElement, treeLocation);

+                modelTreeMap.put(modelTree.getName(), modelTree);

+            }

+        }

+        return modelTreeMap;

+    }

+}

diff --git a/framework/widget/src/org/ofbiz/widget/xml/AbstractWidgetVisitor.java b/framework/widget/src/org/ofbiz/widget/model/XmlAbstractWidgetVisitor.java
similarity index 93%
rename from framework/widget/src/org/ofbiz/widget/xml/AbstractWidgetVisitor.java
rename to framework/widget/src/org/ofbiz/widget/model/XmlAbstractWidgetVisitor.java
index 66d92ad..86d6e5d 100644
--- a/framework/widget/src/org/ofbiz/widget/xml/AbstractWidgetVisitor.java
+++ b/framework/widget/src/org/ofbiz/widget/model/XmlAbstractWidgetVisitor.java
@@ -16,29 +16,28 @@
  * specific language governing permissions and limitations

  * under the License.

  *******************************************************************************/

-package org.ofbiz.widget.xml;

+package org.ofbiz.widget.model;

 

 import java.util.Collection;

 

 import org.ofbiz.base.util.Assert;

 import org.ofbiz.base.util.collections.FlexibleMapAccessor;

 import org.ofbiz.base.util.string.FlexibleStringExpander;

-import org.ofbiz.widget.ModelWidget;

-import org.ofbiz.widget.CommonWidgetModels.AutoEntityParameters;

-import org.ofbiz.widget.CommonWidgetModels.AutoServiceParameters;

-import org.ofbiz.widget.CommonWidgetModels.Image;

-import org.ofbiz.widget.CommonWidgetModels.Link;

-import org.ofbiz.widget.CommonWidgetModels.Parameter;

+import org.ofbiz.widget.model.CommonWidgetModels.AutoEntityParameters;

+import org.ofbiz.widget.model.CommonWidgetModels.AutoServiceParameters;

+import org.ofbiz.widget.model.CommonWidgetModels.Image;

+import org.ofbiz.widget.model.CommonWidgetModels.Link;

+import org.ofbiz.widget.model.CommonWidgetModels.Parameter;

 

 /**

  * Abstract XML widget visitor.

  *

  */

-public abstract class AbstractWidgetVisitor {

+public abstract class XmlAbstractWidgetVisitor {

 

     protected final Appendable writer;

 

-    public AbstractWidgetVisitor(Appendable writer) {

+    public XmlAbstractWidgetVisitor(Appendable writer) {

         Assert.notNull("writer", writer);

         this.writer = writer;

     }

diff --git a/framework/widget/src/org/ofbiz/widget/xml/XmlWidgetActionVisitor.java b/framework/widget/src/org/ofbiz/widget/model/XmlWidgetActionVisitor.java
similarity index 83%
rename from framework/widget/src/org/ofbiz/widget/xml/XmlWidgetActionVisitor.java
rename to framework/widget/src/org/ofbiz/widget/model/XmlWidgetActionVisitor.java
index bfc76d3..540127e 100644
--- a/framework/widget/src/org/ofbiz/widget/xml/XmlWidgetActionVisitor.java
+++ b/framework/widget/src/org/ofbiz/widget/model/XmlWidgetActionVisitor.java
@@ -16,20 +16,19 @@
  * specific language governing permissions and limitations

  * under the License.

  *******************************************************************************/

-package org.ofbiz.widget.xml;

+package org.ofbiz.widget.model;

 

-import org.ofbiz.widget.AbstractModelAction.EntityAnd;

-import org.ofbiz.widget.AbstractModelAction.EntityCondition;

-import org.ofbiz.widget.AbstractModelAction.EntityOne;

-import org.ofbiz.widget.AbstractModelAction.GetRelated;

-import org.ofbiz.widget.AbstractModelAction.GetRelatedOne;

-import org.ofbiz.widget.AbstractModelAction.PropertyMap;

-import org.ofbiz.widget.AbstractModelAction.PropertyToField;

-import org.ofbiz.widget.AbstractModelAction.Script;

-import org.ofbiz.widget.AbstractModelAction.Service;

-import org.ofbiz.widget.AbstractModelAction.SetField;

-import org.ofbiz.widget.ModelActionVisitor;

-import org.ofbiz.widget.form.ModelFormAction.CallParentActions;

+import org.ofbiz.widget.model.AbstractModelAction.EntityAnd;

+import org.ofbiz.widget.model.AbstractModelAction.EntityCondition;

+import org.ofbiz.widget.model.AbstractModelAction.EntityOne;

+import org.ofbiz.widget.model.AbstractModelAction.GetRelated;

+import org.ofbiz.widget.model.AbstractModelAction.GetRelatedOne;

+import org.ofbiz.widget.model.AbstractModelAction.PropertyMap;

+import org.ofbiz.widget.model.AbstractModelAction.PropertyToField;

+import org.ofbiz.widget.model.AbstractModelAction.Script;

+import org.ofbiz.widget.model.AbstractModelAction.Service;

+import org.ofbiz.widget.model.AbstractModelAction.SetField;

+import org.ofbiz.widget.model.ModelFormAction.CallParentActions;

 

 /**

  * An object that generates XML from widget models.

@@ -37,7 +36,7 @@
  * "pretty print" the XML, then use a transformer.

  *

  */

-public class XmlWidgetActionVisitor extends AbstractWidgetVisitor implements ModelActionVisitor {

+public class XmlWidgetActionVisitor extends XmlAbstractWidgetVisitor implements ModelActionVisitor {

 

     public static final String module = XmlWidgetActionVisitor.class.getName();

 

@@ -57,7 +56,7 @@
     }

 

     @Override

-    public void visit(org.ofbiz.widget.tree.ModelTreeAction.EntityAnd entityAnd) throws Exception {

+    public void visit(org.ofbiz.widget.model.ModelTreeAction.EntityAnd entityAnd) throws Exception {

         writer.append("<entity-and/>");

         // TODO: Create ByAndFinder visitor

     }

@@ -69,7 +68,7 @@
     }

 

     @Override

-    public void visit(org.ofbiz.widget.tree.ModelTreeAction.EntityCondition entityCondition) throws Exception {

+    public void visit(org.ofbiz.widget.model.ModelTreeAction.EntityCondition entityCondition) throws Exception {

         writer.append("<entity-condition/>");

         // TODO: Create ByConditionFinder visitor

     }

@@ -133,7 +132,7 @@
     }

 

     @Override

-    public void visit(org.ofbiz.widget.tree.ModelTreeAction.Script script) throws Exception {

+    public void visit(org.ofbiz.widget.model.ModelTreeAction.Script script) throws Exception {

         writer.append("<script");

         visitAttribute("location", script.getLocation());

         visitAttribute("method", script.getMethod());

@@ -153,7 +152,7 @@
     }

 

     @Override

-    public void visit(org.ofbiz.widget.form.ModelFormAction.Service service) throws Exception {

+    public void visit(org.ofbiz.widget.model.ModelFormAction.Service service) throws Exception {

         writer.append("<service");

         visitAttribute("service-name", service.getServiceNameExdr());

         visitAttribute("result-map", service.getResultMapNameAcsr());

@@ -167,7 +166,7 @@
     }

 

     @Override

-    public void visit(org.ofbiz.widget.tree.ModelTreeAction.Service service) throws Exception {

+    public void visit(org.ofbiz.widget.model.ModelTreeAction.Service service) throws Exception {

         writer.append("<service");

         visitAttribute("service-name", service.getServiceNameExdr());

         visitAttribute("result-map", service.getResultMapNameAcsr());

@@ -196,7 +195,7 @@
     }

 

     @Override

-    public void visit(org.ofbiz.widget.menu.ModelMenuAction.SetField setField) throws Exception {

+    public void visit(org.ofbiz.widget.model.ModelMenuAction.SetField setField) throws Exception {

         writer.append("<set");

         visitAttribute("field", setField.getField());

         visitAttribute("from-field", setField.getFromField());

diff --git a/framework/widget/src/org/ofbiz/widget/xml/XmlWidgetConditionVisitor.java b/framework/widget/src/org/ofbiz/widget/model/XmlWidgetConditionVisitor.java
similarity index 84%
rename from framework/widget/src/org/ofbiz/widget/xml/XmlWidgetConditionVisitor.java
rename to framework/widget/src/org/ofbiz/widget/model/XmlWidgetConditionVisitor.java
index 5b13a26..9bd4b89 100644
--- a/framework/widget/src/org/ofbiz/widget/xml/XmlWidgetConditionVisitor.java
+++ b/framework/widget/src/org/ofbiz/widget/model/XmlWidgetConditionVisitor.java
@@ -16,27 +16,23 @@
  * specific language governing permissions and limitations

  * under the License.

  *******************************************************************************/

-package org.ofbiz.widget.xml;

+package org.ofbiz.widget.model;

 

 import java.util.Collection;

 

-import org.ofbiz.widget.AbstractModelCondition.And;

-import org.ofbiz.widget.AbstractModelCondition.IfCompare;

-import org.ofbiz.widget.AbstractModelCondition.IfCompareField;

-import org.ofbiz.widget.AbstractModelCondition.IfEmpty;

-import org.ofbiz.widget.AbstractModelCondition.IfEntityPermission;

-import org.ofbiz.widget.AbstractModelCondition.IfHasPermission;

-import org.ofbiz.widget.AbstractModelCondition.IfRegexp;

-import org.ofbiz.widget.AbstractModelCondition.IfServicePermission;

-import org.ofbiz.widget.AbstractModelCondition.IfValidateMethod;

-import org.ofbiz.widget.AbstractModelCondition.Not;

-import org.ofbiz.widget.AbstractModelCondition.Or;

-import org.ofbiz.widget.AbstractModelCondition.Xor;

-import org.ofbiz.widget.ModelCondition;

-import org.ofbiz.widget.ModelConditionVisitor;

-import org.ofbiz.widget.menu.ModelMenuCondition;

-import org.ofbiz.widget.screen.ModelScreenCondition.IfEmptySection;

-import org.ofbiz.widget.tree.ModelTreeCondition;

+import org.ofbiz.widget.model.AbstractModelCondition.And;

+import org.ofbiz.widget.model.AbstractModelCondition.IfCompare;

+import org.ofbiz.widget.model.AbstractModelCondition.IfCompareField;

+import org.ofbiz.widget.model.AbstractModelCondition.IfEmpty;

+import org.ofbiz.widget.model.AbstractModelCondition.IfEntityPermission;

+import org.ofbiz.widget.model.AbstractModelCondition.IfHasPermission;

+import org.ofbiz.widget.model.AbstractModelCondition.IfRegexp;

+import org.ofbiz.widget.model.AbstractModelCondition.IfServicePermission;

+import org.ofbiz.widget.model.AbstractModelCondition.IfValidateMethod;

+import org.ofbiz.widget.model.AbstractModelCondition.Not;

+import org.ofbiz.widget.model.AbstractModelCondition.Or;

+import org.ofbiz.widget.model.AbstractModelCondition.Xor;

+import org.ofbiz.widget.model.ModelScreenCondition.IfEmptySection;

 

 /**

  * An object that generates XML from widget models.

@@ -44,7 +40,7 @@
  * "pretty print" the XML, then use a transformer.

  *

  */

-public class XmlWidgetConditionVisitor extends AbstractWidgetVisitor implements ModelConditionVisitor {

+public class XmlWidgetConditionVisitor extends XmlAbstractWidgetVisitor implements ModelConditionVisitor {

 

     public XmlWidgetConditionVisitor(Appendable writer) {

         super(writer);

diff --git a/framework/widget/src/org/ofbiz/widget/xml/XmlWidgetFieldVisitor.java b/framework/widget/src/org/ofbiz/widget/model/XmlWidgetFieldVisitor.java
similarity index 92%
rename from framework/widget/src/org/ofbiz/widget/xml/XmlWidgetFieldVisitor.java
rename to framework/widget/src/org/ofbiz/widget/model/XmlWidgetFieldVisitor.java
index a07d92d..c56368c 100644
--- a/framework/widget/src/org/ofbiz/widget/xml/XmlWidgetFieldVisitor.java
+++ b/framework/widget/src/org/ofbiz/widget/model/XmlWidgetFieldVisitor.java
@@ -16,14 +16,36 @@
  * specific language governing permissions and limitations

  * under the License.

  *******************************************************************************/

-package org.ofbiz.widget.xml;

+package org.ofbiz.widget.model;

 

 import java.util.Collection;

 

-import org.ofbiz.widget.ModelFieldVisitor;

-import org.ofbiz.widget.CommonWidgetModels.Link;

-import org.ofbiz.widget.form.ModelFormField.*;

-import org.ofbiz.widget.form.*;

+import org.ofbiz.widget.model.CommonWidgetModels.Link;

+import org.ofbiz.widget.model.ModelFormField.AutoComplete;

+import org.ofbiz.widget.model.ModelFormField.CheckField;

+import org.ofbiz.widget.model.ModelFormField.ContainerField;

+import org.ofbiz.widget.model.ModelFormField.DateFindField;

+import org.ofbiz.widget.model.ModelFormField.DateTimeField;

+import org.ofbiz.widget.model.ModelFormField.DisplayEntityField;

+import org.ofbiz.widget.model.ModelFormField.DisplayField;

+import org.ofbiz.widget.model.ModelFormField.DropDownField;

+import org.ofbiz.widget.model.ModelFormField.FieldInfoWithOptions;

+import org.ofbiz.widget.model.ModelFormField.FileField;

+import org.ofbiz.widget.model.ModelFormField.HiddenField;

+import org.ofbiz.widget.model.ModelFormField.HyperlinkField;

+import org.ofbiz.widget.model.ModelFormField.IgnoredField;

+import org.ofbiz.widget.model.ModelFormField.ImageField;

+import org.ofbiz.widget.model.ModelFormField.InPlaceEditor;

+import org.ofbiz.widget.model.ModelFormField.LookupField;

+import org.ofbiz.widget.model.ModelFormField.PasswordField;

+import org.ofbiz.widget.model.ModelFormField.RadioField;

+import org.ofbiz.widget.model.ModelFormField.RangeFindField;

+import org.ofbiz.widget.model.ModelFormField.ResetField;

+import org.ofbiz.widget.model.ModelFormField.SubHyperlink;

+import org.ofbiz.widget.model.ModelFormField.SubmitField;

+import org.ofbiz.widget.model.ModelFormField.TextField;

+import org.ofbiz.widget.model.ModelFormField.TextFindField;

+import org.ofbiz.widget.model.ModelFormField.TextareaField;

 

 /**

  * An object that generates XML from widget models.

@@ -31,7 +53,7 @@
  * "pretty print" the XML, then use a transformer.

  *

  */

-public class XmlWidgetFieldVisitor extends AbstractWidgetVisitor implements ModelFieldVisitor {

+public class XmlWidgetFieldVisitor extends XmlAbstractWidgetVisitor implements ModelFieldVisitor {

 

     public XmlWidgetFieldVisitor(Appendable writer) {

         super(writer);

diff --git a/framework/widget/src/org/ofbiz/widget/xml/XmlWidgetVisitor.java b/framework/widget/src/org/ofbiz/widget/model/XmlWidgetVisitor.java
similarity index 92%
rename from framework/widget/src/org/ofbiz/widget/xml/XmlWidgetVisitor.java
rename to framework/widget/src/org/ofbiz/widget/model/XmlWidgetVisitor.java
index b55d0dd..129eb26 100644
--- a/framework/widget/src/org/ofbiz/widget/xml/XmlWidgetVisitor.java
+++ b/framework/widget/src/org/ofbiz/widget/model/XmlWidgetVisitor.java
@@ -16,50 +16,35 @@
  * specific language governing permissions and limitations

  * under the License.

  *******************************************************************************/

-package org.ofbiz.widget.xml;

+package org.ofbiz.widget.model;

 

 import java.util.Collection;

 import java.util.Map;

 

-import org.ofbiz.widget.ModelAction;

-import org.ofbiz.widget.ModelActionVisitor;

-import org.ofbiz.widget.ModelConditionVisitor;

-import org.ofbiz.widget.ModelFieldVisitor;

-import org.ofbiz.widget.ModelWidget;

-import org.ofbiz.widget.ModelWidgetVisitor;

-import org.ofbiz.widget.form.ModelForm;

-import org.ofbiz.widget.form.ModelFormField;

-import org.ofbiz.widget.menu.ModelMenu;

-import org.ofbiz.widget.menu.ModelMenuItem;

-import org.ofbiz.widget.screen.HtmlWidget;

-import org.ofbiz.widget.screen.HtmlWidget.HtmlTemplate;

-import org.ofbiz.widget.screen.HtmlWidget.HtmlTemplateDecorator;

-import org.ofbiz.widget.screen.HtmlWidget.HtmlTemplateDecoratorSection;

-import org.ofbiz.widget.screen.IterateSectionWidget;

-import org.ofbiz.widget.screen.ModelScreen;

-import org.ofbiz.widget.screen.ModelScreenWidget;

-import org.ofbiz.widget.screen.ModelScreenWidget.Column;

-import org.ofbiz.widget.screen.ModelScreenWidget.ColumnContainer;

-import org.ofbiz.widget.screen.ModelScreenWidget.Container;

-import org.ofbiz.widget.screen.ModelScreenWidget.Content;

-import org.ofbiz.widget.screen.ModelScreenWidget.DecoratorScreen;

-import org.ofbiz.widget.screen.ModelScreenWidget.DecoratorSection;

-import org.ofbiz.widget.screen.ModelScreenWidget.DecoratorSectionInclude;

-import org.ofbiz.widget.screen.ModelScreenWidget.Form;

-import org.ofbiz.widget.screen.ModelScreenWidget.HorizontalSeparator;

-import org.ofbiz.widget.screen.ModelScreenWidget.IncludeScreen;

-import org.ofbiz.widget.screen.ModelScreenWidget.Label;

-import org.ofbiz.widget.screen.ModelScreenWidget.Menu;

-import org.ofbiz.widget.screen.ModelScreenWidget.PlatformSpecific;

-import org.ofbiz.widget.screen.ModelScreenWidget.PortalPage;

-import org.ofbiz.widget.screen.ModelScreenWidget.ScreenImage;

-import org.ofbiz.widget.screen.ModelScreenWidget.ScreenLink;

-import org.ofbiz.widget.screen.ModelScreenWidget.Screenlet;

-import org.ofbiz.widget.screen.ModelScreenWidget.Section;

-import org.ofbiz.widget.screen.ModelScreenWidget.Tree;

-import org.ofbiz.widget.tree.ModelTree;

-import org.ofbiz.widget.tree.ModelTree.ModelNode;

-import org.ofbiz.widget.tree.ModelTree.ModelNode.ModelSubNode;

+import org.ofbiz.widget.model.HtmlWidget.HtmlTemplate;

+import org.ofbiz.widget.model.HtmlWidget.HtmlTemplateDecorator;

+import org.ofbiz.widget.model.HtmlWidget.HtmlTemplateDecoratorSection;

+import org.ofbiz.widget.model.ModelScreenWidget.Column;

+import org.ofbiz.widget.model.ModelScreenWidget.ColumnContainer;

+import org.ofbiz.widget.model.ModelScreenWidget.Container;

+import org.ofbiz.widget.model.ModelScreenWidget.Content;

+import org.ofbiz.widget.model.ModelScreenWidget.DecoratorScreen;

+import org.ofbiz.widget.model.ModelScreenWidget.DecoratorSection;

+import org.ofbiz.widget.model.ModelScreenWidget.DecoratorSectionInclude;

+import org.ofbiz.widget.model.ModelScreenWidget.Form;

+import org.ofbiz.widget.model.ModelScreenWidget.HorizontalSeparator;

+import org.ofbiz.widget.model.ModelScreenWidget.IncludeScreen;

+import org.ofbiz.widget.model.ModelScreenWidget.Label;

+import org.ofbiz.widget.model.ModelScreenWidget.Menu;

+import org.ofbiz.widget.model.ModelScreenWidget.PlatformSpecific;

+import org.ofbiz.widget.model.ModelScreenWidget.PortalPage;

+import org.ofbiz.widget.model.ModelScreenWidget.ScreenImage;

+import org.ofbiz.widget.model.ModelScreenWidget.ScreenLink;

+import org.ofbiz.widget.model.ModelScreenWidget.Screenlet;

+import org.ofbiz.widget.model.ModelScreenWidget.Section;

+import org.ofbiz.widget.model.ModelScreenWidget.Tree;

+import org.ofbiz.widget.model.ModelTree.ModelNode;

+import org.ofbiz.widget.model.ModelTree.ModelNode.ModelSubNode;

 

 /**

  * An object that generates an XML representation from widget models.

@@ -67,7 +52,7 @@
  * "pretty print" the XML, then use a transformer.

  *

  */

-public class XmlWidgetVisitor extends AbstractWidgetVisitor implements ModelWidgetVisitor {

+public class XmlWidgetVisitor extends XmlAbstractWidgetVisitor implements ModelWidgetVisitor {

 

     private final ModelFieldVisitor fieldVisitor;

     private final ModelActionVisitor actionVisitor;

@@ -399,7 +384,6 @@
         }

         for (ModelMenuItem menuItem : modelMenu.getMenuItemList()) {

             menuItem.accept(this);

-            ;

         }

         writer.append("</menu>");

     }

diff --git a/framework/widget/src/org/ofbiz/widget/PortalPageWorker.java b/framework/widget/src/org/ofbiz/widget/portal/PortalPageWorker.java
similarity index 98%
rename from framework/widget/src/org/ofbiz/widget/PortalPageWorker.java
rename to framework/widget/src/org/ofbiz/widget/portal/PortalPageWorker.java
index 5061208..7225b06 100644
--- a/framework/widget/src/org/ofbiz/widget/PortalPageWorker.java
+++ b/framework/widget/src/org/ofbiz/widget/portal/PortalPageWorker.java
@@ -1,176 +1,177 @@
-/*******************************************************************************
- * 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;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-
-import org.ofbiz.base.util.Debug;
-import org.ofbiz.base.util.GeneralException;
-import org.ofbiz.base.util.UtilMisc;
-import org.ofbiz.base.util.UtilValidate;
-import org.ofbiz.entity.Delegator;
-import org.ofbiz.entity.GenericEntityException;
-import org.ofbiz.entity.GenericValue;
-import org.ofbiz.entity.condition.EntityCondition;
-import org.ofbiz.entity.condition.EntityOperator;
-import org.ofbiz.entity.util.EntityQuery;
-import org.ofbiz.entity.util.EntityUtil;
-import org.ofbiz.security.Security;
-
-/**
- * PortalPageWorker Class
- */
-public class PortalPageWorker {
-
-    public static final String module = PortalPageWorker.class.getName();
-
-    public PortalPageWorker() { }
-
-    public String renderPortalPageAsTextExt(Delegator delegator, String portalPageId, Map<String, Object> templateContext,
-            boolean cache) throws GeneralException, IOException {
-        return "success";
-    }
-
-    /**
-    * Returns a list of PortalPages that have the specified parentPortalPageId as parent.
-    * If a specific PortalPage exists for the current userLogin it is returned instead of the original one.
-    */
-    public static List<GenericValue> getPortalPages(String parentPortalPageId, Map<String, Object> context) {
-        List<GenericValue> portalPages = null;
-        if (UtilValidate.isNotEmpty(parentPortalPageId)) {
-            Delegator delegator = WidgetWorker.getDelegator(context);
-            try {
-                // first get public pages
-                EntityCondition cond =
-                    EntityCondition.makeCondition(UtilMisc.toList(
-                        EntityCondition.makeCondition("ownerUserLoginId", EntityOperator.EQUALS, "_NA_"),
-                        EntityCondition.makeCondition(UtilMisc.toList(
-                                EntityCondition.makeCondition("portalPageId", EntityOperator.EQUALS, parentPortalPageId),
-                                EntityCondition.makeCondition("parentPortalPageId", EntityOperator.EQUALS, parentPortalPageId)),
-                                EntityOperator.OR)),
-                        EntityOperator.AND);
-                portalPages = EntityQuery.use(delegator).from("PortalPage").where(cond).queryList();
-                List<GenericValue> userPortalPages = new ArrayList<GenericValue>();
-                if (UtilValidate.isNotEmpty(context.get("userLogin"))) { // check if a user is logged in
-                    String userLoginId = ((GenericValue)context.get("userLogin")).getString("userLoginId");
-                    // replace with private pages
-                    for (GenericValue portalPage : portalPages) {
-                        List<GenericValue> privatePortalPages = EntityQuery.use(delegator)
-                                                                           .from("PortalPage")
-                                                                           .where("ownerUserLoginId", userLoginId, "originalPortalPageId", portalPage.getString("portalPageId"))
-                                                                           .queryList();
-                        if (UtilValidate.isNotEmpty(privatePortalPages)) {
-                            userPortalPages.add(privatePortalPages.get(0));
-                        } else {
-                            userPortalPages.add(portalPage);
-                        }
-                    }
-                    // add any other created private pages
-                    userPortalPages.addAll(EntityQuery.use(delegator)
-                                                      .from("PortalPage")
-                                                      .where("ownerUserLoginId", userLoginId, "originalPortalPageId", null, "parentPortalPageId", parentPortalPageId)
-                                                      .queryList());
-                }
-                portalPages = EntityUtil.orderBy(userPortalPages, UtilMisc.toList("sequenceNum"));
-            } catch (GenericEntityException e) {
-                Debug.logError("Could not retrieve portalpages:" + e.getMessage(), module);
-            }
-        }
-        return portalPages;
-    }
-
-    /**
-    * Returns the PortalPage with the specified portalPageId.
-    * If a specific PortalPage exists for the current userLogin it is returned instead of the original one.
-    */
-    public static GenericValue getPortalPage(String portalPageId, Map<String, Object> context) {
-        GenericValue portalPage = null;
-        if (UtilValidate.isNotEmpty(portalPageId)) {
-            Delegator delegator = WidgetWorker.getDelegator(context);
-            try {
-                // Get the current userLoginId
-                String userLoginId = "_NA_";
-                if (UtilValidate.isNotEmpty(context.get("userLogin"))) { // check if a user is logged in
-                    userLoginId = ((GenericValue)context.get("userLogin")).getString("userLoginId");
-                }
-                
-                // Get the PortalPage ensuring that it is either owned by the user or a system page
-                EntityCondition cond = EntityCondition.makeCondition(UtilMisc.toList(
-                    EntityCondition.makeCondition("portalPageId", EntityOperator.EQUALS, portalPageId),
-                    EntityCondition.makeCondition(UtilMisc.toList(
-                        EntityCondition.makeCondition("ownerUserLoginId", EntityOperator.EQUALS, "_NA_"),
-                        EntityCondition.makeCondition("ownerUserLoginId", EntityOperator.EQUALS, userLoginId)),
-                        EntityOperator.OR)),
-                    EntityOperator.AND);
-                List <GenericValue> portalPages = EntityQuery.use(delegator).from("PortalPage").where(cond).queryList();
-                if (UtilValidate.isNotEmpty(portalPages)) {
-                    portalPage = EntityUtil.getFirst(portalPages);
-                }
-                
-                // If a derived PortalPage private to the user exists, returns this instead of the system one
-                cond = EntityCondition.makeCondition(UtilMisc.toList(
-                        EntityCondition.makeCondition("originalPortalPageId", EntityOperator.EQUALS, portalPageId),
-                        EntityCondition.makeCondition("ownerUserLoginId", EntityOperator.EQUALS, userLoginId)),
-                        EntityOperator.AND);
-                List <GenericValue> privateDerivedPortalPages = EntityQuery.use(delegator).from("PortalPage").where(cond).queryList();
-                if (UtilValidate.isNotEmpty(privateDerivedPortalPages)) {
-                    portalPage = EntityUtil.getFirst(privateDerivedPortalPages);
-                }
-            } catch (GenericEntityException e) {
-                Debug.logError("Could not retrieve portalpage:" + e.getMessage(), module);
-            }
-        }
-        return portalPage;
-    }
-
-    /**
-    * Checks if the user is allowed to configure the PortalPage.
-    * PortalPage configuration is allowed if he is the PortalPage owner or he has got the PORTALPAGE_ADMIN permission
-    */   
-    public static Boolean userIsAllowedToConfigure(String portalPageId, Map<String, Object> context) {
-        Boolean userIsAllowed = false;
-
-        if (UtilValidate.isNotEmpty(portalPageId)) {
-            GenericValue userLogin = (GenericValue) context.get("userLogin");
-            if (UtilValidate.isNotEmpty(userLogin)) {
-                String userLoginId = (String) userLogin.get("userLoginId");
-                Security security = (Security) context.get("security");
-
-                Boolean hasPortalAdminPermission = security.hasPermission("PORTALPAGE_ADMIN", userLogin);
-                try {
-                    Delegator delegator = WidgetWorker.getDelegator(context);
-                    GenericValue portalPage = EntityQuery.use(delegator).from("PortalPage").where("portalPageId", portalPageId).queryOne();
-                    if (UtilValidate.isNotEmpty(portalPage)) {
-                        String ownerUserLoginId = (String) portalPage.get("ownerUserLoginId");
-                        // Users with PORTALPAGE_ADMIN permission can configure every Portal Page
-                        userIsAllowed = (ownerUserLoginId.equals(userLoginId) || hasPortalAdminPermission);
-                    }
-                } catch (GenericEntityException e) {
-                    return false;
-                }
-            }
-        }
-
-        return userIsAllowed;       
-    }
-    
-}
+/*******************************************************************************

+ * 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.portal;

+

+import java.io.IOException;

+import java.util.ArrayList;

+import java.util.List;

+import java.util.Map;

+

+import org.ofbiz.base.util.Debug;

+import org.ofbiz.base.util.GeneralException;

+import org.ofbiz.base.util.UtilMisc;

+import org.ofbiz.base.util.UtilValidate;

+import org.ofbiz.entity.Delegator;

+import org.ofbiz.entity.GenericEntityException;

+import org.ofbiz.entity.GenericValue;

+import org.ofbiz.entity.condition.EntityCondition;

+import org.ofbiz.entity.condition.EntityOperator;

+import org.ofbiz.entity.util.EntityQuery;

+import org.ofbiz.entity.util.EntityUtil;

+import org.ofbiz.security.Security;

+import org.ofbiz.widget.WidgetWorker;

+

+/**

+ * PortalPageWorker Class

+ */

+public class PortalPageWorker {

+

+    public static final String module = PortalPageWorker.class.getName();

+

+    public PortalPageWorker() { }

+

+    public String renderPortalPageAsTextExt(Delegator delegator, String portalPageId, Map<String, Object> templateContext,

+            boolean cache) throws GeneralException, IOException {

+        return "success";

+    }

+

+    /**

+    * Returns a list of PortalPages that have the specified parentPortalPageId as parent.

+    * If a specific PortalPage exists for the current userLogin it is returned instead of the original one.

+    */

+    public static List<GenericValue> getPortalPages(String parentPortalPageId, Map<String, Object> context) {

+        List<GenericValue> portalPages = null;

+        if (UtilValidate.isNotEmpty(parentPortalPageId)) {

+            Delegator delegator = WidgetWorker.getDelegator(context);

+            try {

+                // first get public pages

+                EntityCondition cond =

+                    EntityCondition.makeCondition(UtilMisc.toList(

+                        EntityCondition.makeCondition("ownerUserLoginId", EntityOperator.EQUALS, "_NA_"),

+                        EntityCondition.makeCondition(UtilMisc.toList(

+                                EntityCondition.makeCondition("portalPageId", EntityOperator.EQUALS, parentPortalPageId),

+                                EntityCondition.makeCondition("parentPortalPageId", EntityOperator.EQUALS, parentPortalPageId)),

+                                EntityOperator.OR)),

+                        EntityOperator.AND);

+                portalPages = EntityQuery.use(delegator).from("PortalPage").where(cond).queryList();

+                List<GenericValue> userPortalPages = new ArrayList<GenericValue>();

+                if (UtilValidate.isNotEmpty(context.get("userLogin"))) { // check if a user is logged in

+                    String userLoginId = ((GenericValue)context.get("userLogin")).getString("userLoginId");

+                    // replace with private pages

+                    for (GenericValue portalPage : portalPages) {

+                        List<GenericValue> privatePortalPages = EntityQuery.use(delegator)

+                                                                           .from("PortalPage")

+                                                                           .where("ownerUserLoginId", userLoginId, "originalPortalPageId", portalPage.getString("portalPageId"))

+                                                                           .queryList();

+                        if (UtilValidate.isNotEmpty(privatePortalPages)) {

+                            userPortalPages.add(privatePortalPages.get(0));

+                        } else {

+                            userPortalPages.add(portalPage);

+                        }

+                    }

+                    // add any other created private pages

+                    userPortalPages.addAll(EntityQuery.use(delegator)

+                                                      .from("PortalPage")

+                                                      .where("ownerUserLoginId", userLoginId, "originalPortalPageId", null, "parentPortalPageId", parentPortalPageId)

+                                                      .queryList());

+                }

+                portalPages = EntityUtil.orderBy(userPortalPages, UtilMisc.toList("sequenceNum"));

+            } catch (GenericEntityException e) {

+                Debug.logError("Could not retrieve portalpages:" + e.getMessage(), module);

+            }

+        }

+        return portalPages;

+    }

+

+    /**

+    * Returns the PortalPage with the specified portalPageId.

+    * If a specific PortalPage exists for the current userLogin it is returned instead of the original one.

+    */

+    public static GenericValue getPortalPage(String portalPageId, Map<String, Object> context) {

+        GenericValue portalPage = null;

+        if (UtilValidate.isNotEmpty(portalPageId)) {

+            Delegator delegator = WidgetWorker.getDelegator(context);

+            try {

+                // Get the current userLoginId

+                String userLoginId = "_NA_";

+                if (UtilValidate.isNotEmpty(context.get("userLogin"))) { // check if a user is logged in

+                    userLoginId = ((GenericValue)context.get("userLogin")).getString("userLoginId");

+                }

+                

+                // Get the PortalPage ensuring that it is either owned by the user or a system page

+                EntityCondition cond = EntityCondition.makeCondition(UtilMisc.toList(

+                    EntityCondition.makeCondition("portalPageId", EntityOperator.EQUALS, portalPageId),

+                    EntityCondition.makeCondition(UtilMisc.toList(

+                        EntityCondition.makeCondition("ownerUserLoginId", EntityOperator.EQUALS, "_NA_"),

+                        EntityCondition.makeCondition("ownerUserLoginId", EntityOperator.EQUALS, userLoginId)),

+                        EntityOperator.OR)),

+                    EntityOperator.AND);

+                List <GenericValue> portalPages = EntityQuery.use(delegator).from("PortalPage").where(cond).queryList();

+                if (UtilValidate.isNotEmpty(portalPages)) {

+                    portalPage = EntityUtil.getFirst(portalPages);

+                }

+                

+                // If a derived PortalPage private to the user exists, returns this instead of the system one

+                cond = EntityCondition.makeCondition(UtilMisc.toList(

+                        EntityCondition.makeCondition("originalPortalPageId", EntityOperator.EQUALS, portalPageId),

+                        EntityCondition.makeCondition("ownerUserLoginId", EntityOperator.EQUALS, userLoginId)),

+                        EntityOperator.AND);

+                List <GenericValue> privateDerivedPortalPages = EntityQuery.use(delegator).from("PortalPage").where(cond).queryList();

+                if (UtilValidate.isNotEmpty(privateDerivedPortalPages)) {

+                    portalPage = EntityUtil.getFirst(privateDerivedPortalPages);

+                }

+            } catch (GenericEntityException e) {

+                Debug.logError("Could not retrieve portalpage:" + e.getMessage(), module);

+            }

+        }

+        return portalPage;

+    }

+

+    /**

+    * Checks if the user is allowed to configure the PortalPage.

+    * PortalPage configuration is allowed if he is the PortalPage owner or he has got the PORTALPAGE_ADMIN permission

+    */   

+    public static Boolean userIsAllowedToConfigure(String portalPageId, Map<String, Object> context) {

+        Boolean userIsAllowed = false;

+

+        if (UtilValidate.isNotEmpty(portalPageId)) {

+            GenericValue userLogin = (GenericValue) context.get("userLogin");

+            if (UtilValidate.isNotEmpty(userLogin)) {

+                String userLoginId = (String) userLogin.get("userLoginId");

+                Security security = (Security) context.get("security");

+

+                Boolean hasPortalAdminPermission = security.hasPermission("PORTALPAGE_ADMIN", userLogin);

+                try {

+                    Delegator delegator = WidgetWorker.getDelegator(context);

+                    GenericValue portalPage = EntityQuery.use(delegator).from("PortalPage").where("portalPageId", portalPageId).queryOne();

+                    if (UtilValidate.isNotEmpty(portalPage)) {

+                        String ownerUserLoginId = (String) portalPage.get("ownerUserLoginId");

+                        // Users with PORTALPAGE_ADMIN permission can configure every Portal Page

+                        userIsAllowed = (ownerUserLoginId.equals(userLoginId) || hasPortalAdminPermission);

+                    }

+                } catch (GenericEntityException e) {

+                    return false;

+                }

+            }

+        }

+

+        return userIsAllowed;       

+    }

+    

+}

diff --git a/framework/widget/src/org/ofbiz/widget/PortalPageWorkerInterface.java b/framework/widget/src/org/ofbiz/widget/portal/PortalPageWorkerInterface.java
similarity index 97%
rename from framework/widget/src/org/ofbiz/widget/PortalPageWorkerInterface.java
rename to framework/widget/src/org/ofbiz/widget/portal/PortalPageWorkerInterface.java
index 3cc1d87..bc60a5b 100644
--- a/framework/widget/src/org/ofbiz/widget/PortalPageWorkerInterface.java
+++ b/framework/widget/src/org/ofbiz/widget/portal/PortalPageWorkerInterface.java
@@ -1,33 +1,33 @@
-/*******************************************************************************
- * 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;
-
-import java.io.IOException;
-import java.util.Map;
-
-import org.ofbiz.base.util.GeneralException;
-import org.ofbiz.entity.Delegator;
-
-/**
- * PortalPageWorkerInterface
- */
-public interface PortalPageWorkerInterface {
-    public String renderPortalPageAsTextExt(Delegator delegator, String portalPageId, Map<String, Object> templateContext,
-            boolean cache) throws GeneralException, IOException;
-}
+/*******************************************************************************

+ * 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.portal;

+

+import java.io.IOException;

+import java.util.Map;

+

+import org.ofbiz.base.util.GeneralException;

+import org.ofbiz.entity.Delegator;

+

+/**

+ * PortalPageWorkerInterface

+ */

+public interface PortalPageWorkerInterface {

+    public String renderPortalPageAsTextExt(Delegator delegator, String portalPageId, Map<String, Object> templateContext,

+            boolean cache) throws GeneralException, IOException;

+}

diff --git a/framework/widget/src/org/ofbiz/widget/WidgetPortalPageWorker.java b/framework/widget/src/org/ofbiz/widget/portal/WidgetPortalPageWorker.java
similarity index 94%
rename from framework/widget/src/org/ofbiz/widget/WidgetPortalPageWorker.java
rename to framework/widget/src/org/ofbiz/widget/portal/WidgetPortalPageWorker.java
index 8b942a3..66dd28d 100644
--- a/framework/widget/src/org/ofbiz/widget/WidgetPortalPageWorker.java
+++ b/framework/widget/src/org/ofbiz/widget/portal/WidgetPortalPageWorker.java
@@ -1,41 +1,42 @@
-/*******************************************************************************
- * 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;
-import org.ofbiz.base.util.Debug;
-
-/**
- * PortalPageWorker Class
- */
-public class WidgetPortalPageWorker {
-    public static final String module = WidgetPortalPageWorker.class.getName();
-    public static PortalPageWorkerInterface portalPageWorker = null;
-    static {
-        try {
-            ClassLoader loader = Thread.currentThread().getContextClassLoader();
-            // note: loadClass is necessary for these since this class doesn't know anything about them at compile time
-            portalPageWorker = (PortalPageWorkerInterface) loader.loadClass("org.ofbiz.widget.PortalPageWorker").newInstance();
-        } catch (ClassNotFoundException e) {
-            Debug.logError(e, "Could not pre-initialize dynamically loaded class: ", module);
-        } catch (IllegalAccessException e) {
-            Debug.logError(e, "Could not pre-initialize dynamically loaded class: ", module);
-        } catch (InstantiationException e) {
-            Debug.logError(e, "Could not pre-initialize dynamically loaded class: ", module);
-        }
-    }
-}
+/*******************************************************************************

+ * 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.portal;

+

+import org.ofbiz.base.util.Debug;

+

+/**

+ * PortalPageWorker Class

+ */

+public class WidgetPortalPageWorker {

+    public static final String module = WidgetPortalPageWorker.class.getName();

+    public static PortalPageWorkerInterface portalPageWorker = null;

+    static {

+        try {

+            ClassLoader loader = Thread.currentThread().getContextClassLoader();

+            // note: loadClass is necessary for these since this class doesn't know anything about them at compile time

+            portalPageWorker = (PortalPageWorkerInterface) loader.loadClass("org.ofbiz.widget.portal.PortalPageWorker").newInstance();

+        } catch (ClassNotFoundException e) {

+            Debug.logError(e, "Could not pre-initialize dynamically loaded class: ", module);

+        } catch (IllegalAccessException e) {

+            Debug.logError(e, "Could not pre-initialize dynamically loaded class: ", module);

+        } catch (InstantiationException e) {

+            Debug.logError(e, "Could not pre-initialize dynamically loaded class: ", module);

+        }

+    }

+}

diff --git a/framework/widget/src/org/ofbiz/widget/form/FormRenderer.java b/framework/widget/src/org/ofbiz/widget/renderer/FormRenderer.java
similarity index 99%
rename from framework/widget/src/org/ofbiz/widget/form/FormRenderer.java
rename to framework/widget/src/org/ofbiz/widget/renderer/FormRenderer.java
index c4619d1..f257c78 100644
--- a/framework/widget/src/org/ofbiz/widget/form/FormRenderer.java
+++ b/framework/widget/src/org/ofbiz/widget/renderer/FormRenderer.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations

  * under the License.

  *******************************************************************************/

-package org.ofbiz.widget.form;

+package org.ofbiz.widget.renderer;

 

 import java.io.IOException;

 import java.util.ArrayList;

@@ -41,10 +41,13 @@
 import org.ofbiz.entity.GenericEntity;

 import org.ofbiz.entity.GenericEntityException;

 import org.ofbiz.entity.util.EntityListIterator;

-import org.ofbiz.widget.AbstractModelAction;

 import org.ofbiz.widget.WidgetWorker;

-import org.ofbiz.widget.form.ModelForm.FieldGroup;

-import org.ofbiz.widget.form.ModelForm.FieldGroupBase;

+import org.ofbiz.widget.model.AbstractModelAction;

+import org.ofbiz.widget.model.FieldInfo;

+import org.ofbiz.widget.model.ModelForm;

+import org.ofbiz.widget.model.ModelForm.FieldGroup;

+import org.ofbiz.widget.model.ModelForm.FieldGroupBase;

+import org.ofbiz.widget.model.ModelFormField;

 

 /**

  * A form rendering engine.

diff --git a/framework/widget/src/org/ofbiz/widget/form/FormStringRenderer.java b/framework/widget/src/org/ofbiz/widget/renderer/FormStringRenderer.java
similarity index 98%
rename from framework/widget/src/org/ofbiz/widget/form/FormStringRenderer.java
rename to framework/widget/src/org/ofbiz/widget/renderer/FormStringRenderer.java
index 487d894..9f64859 100644
--- a/framework/widget/src/org/ofbiz/widget/form/FormStringRenderer.java
+++ b/framework/widget/src/org/ofbiz/widget/renderer/FormStringRenderer.java
@@ -1,96 +1,99 @@
-/*******************************************************************************
- * 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.Map;
-
-/**
- * Widget Library - Form String Renderer interface.
- */
-public interface FormStringRenderer {
-    public void renderDisplayField(Appendable writer, Map<String, Object> context, ModelFormField.DisplayField displayField) throws IOException;
-    public void renderHyperlinkField(Appendable writer, Map<String, Object> context, ModelFormField.HyperlinkField hyperlinkField) throws IOException;
-
-    public void renderTextField(Appendable writer, Map<String, Object> context, ModelFormField.TextField textField) throws IOException;
-    public void renderTextareaField(Appendable writer, Map<String, Object> context, ModelFormField.TextareaField textareaField) throws IOException;
-    public void renderDateTimeField(Appendable writer, Map<String, Object> context, ModelFormField.DateTimeField dateTimeField) throws IOException;
-
-    public void renderDropDownField(Appendable writer, Map<String, Object> context, ModelFormField.DropDownField dropDownField) throws IOException;
-    public void renderCheckField(Appendable writer, Map<String, Object> context, ModelFormField.CheckField checkField) throws IOException;
-    public void renderRadioField(Appendable writer, Map<String, Object> context, ModelFormField.RadioField radioField) throws IOException;
-
-    public void renderSubmitField(Appendable writer, Map<String, Object> context, ModelFormField.SubmitField submitField) throws IOException;
-    public void renderResetField(Appendable writer, Map<String, Object> context, ModelFormField.ResetField resetField) throws IOException;
-
-    public void renderHiddenField(Appendable writer, Map<String, Object> context, ModelFormField modelFormField, String value) throws IOException;
-    public void renderHiddenField(Appendable writer, Map<String, Object> context, ModelFormField.HiddenField hiddenField) throws IOException;
-    public void renderIgnoredField(Appendable writer, Map<String, Object> context, ModelFormField.IgnoredField ignoredField) throws IOException;
-
-    public void renderFieldTitle(Appendable writer, Map<String, Object> context, ModelFormField modelFormField) throws IOException;
-    public void renderSingleFormFieldTitle(Appendable writer, Map<String, Object> context, ModelFormField modelFormField) throws IOException;
-
-    public void renderFormOpen(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException;
-    public void renderFormClose(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException;
-    public void renderMultiFormClose(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException;
-
-    public void renderFormatListWrapperOpen(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException;
-    public void renderFormatListWrapperClose(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException;
-
-    public void renderFormatHeaderRowOpen(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException;
-    public void renderFormatHeaderRowClose(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException;
-    public void renderFormatHeaderRowCellOpen(Appendable writer, Map<String, Object> context, ModelForm modelForm, ModelFormField modelFormField, int positionSpan) throws IOException;
-    public void renderFormatHeaderRowCellClose(Appendable writer, Map<String, Object> context, ModelForm modelForm, ModelFormField modelFormField) throws IOException;
-
-    public void renderFormatHeaderRowFormCellOpen(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException;
-    public void renderFormatHeaderRowFormCellClose(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException;
-    public void renderFormatHeaderRowFormCellTitleSeparator(Appendable writer, Map<String, Object> context, ModelForm modelForm, ModelFormField modelFormField, boolean isLast) throws IOException;
-
-    public void renderFormatItemRowOpen(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException;
-    public void renderFormatItemRowClose(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException;
-    public void renderFormatItemRowCellOpen(Appendable writer, Map<String, Object> context, ModelForm modelForm, ModelFormField modelFormField, int positionSpan) throws IOException;
-    public void renderFormatItemRowCellClose(Appendable writer, Map<String, Object> context, ModelForm modelForm, ModelFormField modelFormField) throws IOException;
-    public void renderFormatItemRowFormCellOpen(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException;
-    public void renderFormatItemRowFormCellClose(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException;
-
-    public void renderFormatSingleWrapperOpen(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException;
-    public void renderFormatSingleWrapperClose(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException;
-
-    public void renderFormatFieldRowOpen(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException;
-    public void renderFormatFieldRowClose(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException;
-    public void renderFormatFieldRowTitleCellOpen(Appendable writer, Map<String, Object> context, ModelFormField modelFormField) throws IOException;
-    public void renderFormatFieldRowTitleCellClose(Appendable writer, Map<String, Object> context, ModelFormField modelFormField) throws IOException;
-    public void renderFormatFieldRowSpacerCell(Appendable writer, Map<String, Object> context, ModelFormField modelFormField) throws IOException;
-    public void renderFormatFieldRowWidgetCellOpen(Appendable writer, Map<String, Object> context, ModelFormField modelFormField, int positions, int positionSpan, Integer nextPositionInRow) throws IOException;
-    public void renderFormatFieldRowWidgetCellClose(Appendable writer, Map<String, Object> context, ModelFormField modelFormField, int positions, int positionSpan, Integer nextPositionInRow) throws IOException;
-
-    public void renderFormatEmptySpace(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException;
-
-    public void renderTextFindField(Appendable writer, Map<String, Object> context, ModelFormField.TextFindField textField) throws IOException;
-    public void renderDateFindField(Appendable writer, Map<String, Object> context, ModelFormField.DateFindField textField) throws IOException;
-    public void renderRangeFindField(Appendable writer, Map<String, Object> context, ModelFormField.RangeFindField textField) throws IOException;
-    public void renderLookupField(Appendable writer, Map<String, Object> context, ModelFormField.LookupField textField) throws IOException;
-    public void renderFileField(Appendable writer, Map<String, Object> context, ModelFormField.FileField textField) throws IOException;
-    public void renderPasswordField(Appendable writer, Map<String, Object> context, ModelFormField.PasswordField textField) throws IOException;
-    public void renderImageField(Appendable writer, Map<String, Object> context, ModelFormField.ImageField textField) throws IOException;
-    public void renderBanner(Appendable writer, Map<String, Object> context, ModelForm.Banner banner) throws IOException;
-    public void renderContainerFindField(Appendable writer, Map<String, Object> context, ModelFormField.ContainerField containerField) throws IOException;
-    public void renderFieldGroupOpen(Appendable writer, Map<String, Object> context, ModelForm.FieldGroup fieldGroup) throws IOException;
-    public void renderFieldGroupClose(Appendable writer, Map<String, Object> context, ModelForm.FieldGroup fieldGroup) throws IOException;
-}
+/*******************************************************************************

+ * 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.renderer;

+

+import java.io.IOException;

+import java.util.Map;

+

+import org.ofbiz.widget.model.ModelForm;

+import org.ofbiz.widget.model.ModelFormField;

+

+/**

+ * Widget Library - Form String Renderer interface.

+ */

+public interface FormStringRenderer {

+    public void renderDisplayField(Appendable writer, Map<String, Object> context, ModelFormField.DisplayField displayField) throws IOException;

+    public void renderHyperlinkField(Appendable writer, Map<String, Object> context, ModelFormField.HyperlinkField hyperlinkField) throws IOException;

+

+    public void renderTextField(Appendable writer, Map<String, Object> context, ModelFormField.TextField textField) throws IOException;

+    public void renderTextareaField(Appendable writer, Map<String, Object> context, ModelFormField.TextareaField textareaField) throws IOException;

+    public void renderDateTimeField(Appendable writer, Map<String, Object> context, ModelFormField.DateTimeField dateTimeField) throws IOException;

+

+    public void renderDropDownField(Appendable writer, Map<String, Object> context, ModelFormField.DropDownField dropDownField) throws IOException;

+    public void renderCheckField(Appendable writer, Map<String, Object> context, ModelFormField.CheckField checkField) throws IOException;

+    public void renderRadioField(Appendable writer, Map<String, Object> context, ModelFormField.RadioField radioField) throws IOException;

+

+    public void renderSubmitField(Appendable writer, Map<String, Object> context, ModelFormField.SubmitField submitField) throws IOException;

+    public void renderResetField(Appendable writer, Map<String, Object> context, ModelFormField.ResetField resetField) throws IOException;

+

+    public void renderHiddenField(Appendable writer, Map<String, Object> context, ModelFormField modelFormField, String value) throws IOException;

+    public void renderHiddenField(Appendable writer, Map<String, Object> context, ModelFormField.HiddenField hiddenField) throws IOException;

+    public void renderIgnoredField(Appendable writer, Map<String, Object> context, ModelFormField.IgnoredField ignoredField) throws IOException;

+

+    public void renderFieldTitle(Appendable writer, Map<String, Object> context, ModelFormField modelFormField) throws IOException;

+    public void renderSingleFormFieldTitle(Appendable writer, Map<String, Object> context, ModelFormField modelFormField) throws IOException;

+

+    public void renderFormOpen(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException;

+    public void renderFormClose(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException;

+    public void renderMultiFormClose(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException;

+

+    public void renderFormatListWrapperOpen(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException;

+    public void renderFormatListWrapperClose(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException;

+

+    public void renderFormatHeaderRowOpen(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException;

+    public void renderFormatHeaderRowClose(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException;

+    public void renderFormatHeaderRowCellOpen(Appendable writer, Map<String, Object> context, ModelForm modelForm, ModelFormField modelFormField, int positionSpan) throws IOException;

+    public void renderFormatHeaderRowCellClose(Appendable writer, Map<String, Object> context, ModelForm modelForm, ModelFormField modelFormField) throws IOException;

+

+    public void renderFormatHeaderRowFormCellOpen(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException;

+    public void renderFormatHeaderRowFormCellClose(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException;

+    public void renderFormatHeaderRowFormCellTitleSeparator(Appendable writer, Map<String, Object> context, ModelForm modelForm, ModelFormField modelFormField, boolean isLast) throws IOException;

+

+    public void renderFormatItemRowOpen(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException;

+    public void renderFormatItemRowClose(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException;

+    public void renderFormatItemRowCellOpen(Appendable writer, Map<String, Object> context, ModelForm modelForm, ModelFormField modelFormField, int positionSpan) throws IOException;

+    public void renderFormatItemRowCellClose(Appendable writer, Map<String, Object> context, ModelForm modelForm, ModelFormField modelFormField) throws IOException;

+    public void renderFormatItemRowFormCellOpen(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException;

+    public void renderFormatItemRowFormCellClose(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException;

+

+    public void renderFormatSingleWrapperOpen(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException;

+    public void renderFormatSingleWrapperClose(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException;

+

+    public void renderFormatFieldRowOpen(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException;

+    public void renderFormatFieldRowClose(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException;

+    public void renderFormatFieldRowTitleCellOpen(Appendable writer, Map<String, Object> context, ModelFormField modelFormField) throws IOException;

+    public void renderFormatFieldRowTitleCellClose(Appendable writer, Map<String, Object> context, ModelFormField modelFormField) throws IOException;

+    public void renderFormatFieldRowSpacerCell(Appendable writer, Map<String, Object> context, ModelFormField modelFormField) throws IOException;

+    public void renderFormatFieldRowWidgetCellOpen(Appendable writer, Map<String, Object> context, ModelFormField modelFormField, int positions, int positionSpan, Integer nextPositionInRow) throws IOException;

+    public void renderFormatFieldRowWidgetCellClose(Appendable writer, Map<String, Object> context, ModelFormField modelFormField, int positions, int positionSpan, Integer nextPositionInRow) throws IOException;

+

+    public void renderFormatEmptySpace(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException;

+

+    public void renderTextFindField(Appendable writer, Map<String, Object> context, ModelFormField.TextFindField textField) throws IOException;

+    public void renderDateFindField(Appendable writer, Map<String, Object> context, ModelFormField.DateFindField textField) throws IOException;

+    public void renderRangeFindField(Appendable writer, Map<String, Object> context, ModelFormField.RangeFindField textField) throws IOException;

+    public void renderLookupField(Appendable writer, Map<String, Object> context, ModelFormField.LookupField textField) throws IOException;

+    public void renderFileField(Appendable writer, Map<String, Object> context, ModelFormField.FileField textField) throws IOException;

+    public void renderPasswordField(Appendable writer, Map<String, Object> context, ModelFormField.PasswordField textField) throws IOException;

+    public void renderImageField(Appendable writer, Map<String, Object> context, ModelFormField.ImageField textField) throws IOException;

+    public void renderBanner(Appendable writer, Map<String, Object> context, ModelForm.Banner banner) throws IOException;

+    public void renderContainerFindField(Appendable writer, Map<String, Object> context, ModelFormField.ContainerField containerField) throws IOException;

+    public void renderFieldGroupOpen(Appendable writer, Map<String, Object> context, ModelForm.FieldGroup fieldGroup) throws IOException;

+    public void renderFieldGroupClose(Appendable writer, Map<String, Object> context, ModelForm.FieldGroup fieldGroup) throws IOException;

+}

diff --git a/framework/widget/src/org/ofbiz/widget/menu/MenuStringRenderer.java b/framework/widget/src/org/ofbiz/widget/renderer/MenuStringRenderer.java
similarity index 91%
rename from framework/widget/src/org/ofbiz/widget/menu/MenuStringRenderer.java
rename to framework/widget/src/org/ofbiz/widget/renderer/MenuStringRenderer.java
index 71f6a32..b1bf5c3 100644
--- a/framework/widget/src/org/ofbiz/widget/menu/MenuStringRenderer.java
+++ b/framework/widget/src/org/ofbiz/widget/renderer/MenuStringRenderer.java
@@ -1,39 +1,41 @@
-/*******************************************************************************
- * 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") throws IOException ; 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.menu;
-
-import java.io.IOException;
-import java.util.Map;
-
-import org.ofbiz.widget.CommonWidgetModels.Image;
-
-
-/**
- * Widget Library - Form String Renderer interface
- */
-public interface MenuStringRenderer {
-    public void renderMenuItem(Appendable writer, Map<String, Object> context, ModelMenuItem menuItem) throws IOException ;
-    public void renderMenuOpen(Appendable writer, Map<String, Object> context, ModelMenu menu) throws IOException ;
-    public void renderMenuClose(Appendable writer, Map<String, Object> context, ModelMenu menu) throws IOException ;
-    public void renderFormatSimpleWrapperOpen(Appendable writer, Map<String, Object> context, ModelMenu menu) throws IOException ;
-    public void renderFormatSimpleWrapperClose(Appendable writer, Map<String, Object> context, ModelMenu menu) throws IOException ;
-    public void renderFormatSimpleWrapperRows(Appendable writer, Map<String, Object> context, Object menu) throws IOException ;
-    public void renderLink(Appendable writer, Map<String, Object> context, ModelMenuItem.MenuLink link) throws IOException ;
-    public void renderImage(Appendable writer, Map<String, Object> context, Image image) throws IOException ;
-}
+/*******************************************************************************

+ * 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") throws IOException ; 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.renderer;

+

+import java.io.IOException;

+import java.util.Map;

+

+import org.ofbiz.widget.model.CommonWidgetModels.Image;

+import org.ofbiz.widget.model.ModelMenu;

+import org.ofbiz.widget.model.ModelMenuItem;

+

+

+/**

+ * Widget Library - Form String Renderer interface

+ */

+public interface MenuStringRenderer {

+    public void renderMenuItem(Appendable writer, Map<String, Object> context, ModelMenuItem menuItem) throws IOException ;

+    public void renderMenuOpen(Appendable writer, Map<String, Object> context, ModelMenu menu) throws IOException ;

+    public void renderMenuClose(Appendable writer, Map<String, Object> context, ModelMenu menu) throws IOException ;

+    public void renderFormatSimpleWrapperOpen(Appendable writer, Map<String, Object> context, ModelMenu menu) throws IOException ;

+    public void renderFormatSimpleWrapperClose(Appendable writer, Map<String, Object> context, ModelMenu menu) throws IOException ;

+    public void renderFormatSimpleWrapperRows(Appendable writer, Map<String, Object> context, Object menu) throws IOException ;

+    public void renderLink(Appendable writer, Map<String, Object> context, ModelMenuItem.MenuLink link) throws IOException ;

+    public void renderImage(Appendable writer, Map<String, Object> context, Image image) throws IOException ;

+}

diff --git a/framework/widget/src/org/ofbiz/widget/menu/MenuWrapTransform.java b/framework/widget/src/org/ofbiz/widget/renderer/MenuWrapTransform.java
similarity index 98%
rename from framework/widget/src/org/ofbiz/widget/menu/MenuWrapTransform.java
rename to framework/widget/src/org/ofbiz/widget/renderer/MenuWrapTransform.java
index e95b924..45120b5 100644
--- a/framework/widget/src/org/ofbiz/widget/menu/MenuWrapTransform.java
+++ b/framework/widget/src/org/ofbiz/widget/renderer/MenuWrapTransform.java
@@ -1,200 +1,200 @@
-/*******************************************************************************
- * 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.menu;
-
-import java.io.IOException;
-import java.io.Writer;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import javax.servlet.http.HttpSession;
-
-import org.ofbiz.base.util.Debug;
-import org.ofbiz.base.util.GeneralException;
-import org.ofbiz.base.util.UtilGenerics;
-import org.ofbiz.base.util.UtilValidate;
-import org.ofbiz.base.util.template.FreeMarkerWorker;
-import org.ofbiz.entity.Delegator;
-import org.ofbiz.entity.GenericValue;
-import org.ofbiz.webapp.ftl.LoopWriter;
-import org.ofbiz.widget.WidgetContentWorker;
-import org.ofbiz.widget.html.HtmlMenuWrapper;
-
-import freemarker.core.Environment;
-import freemarker.template.TemplateModelException;
-import freemarker.template.TemplateTransformModel;
-import freemarker.template.TransformControl;
-
-//import com.clarkware.profiler.Profiler;
-/**
- * MenuWrapTransform -  a FreeMarker transform that allow the ModelMenu
- * stuff to be used at the FM level. It can be used to add "function bars"
- * to pages.
- *
- * Accepts the following arguments (all of which can alternatively be present in the template context):
- * - List<Map<String, ? extends Object>> globalNodeTrail
- * - String contentAssocPredicateId
- * - String nullThruDatesOnly
- * - String subDataResourceTypeId
- * - String renderOnStart
- * - String renderOnClose
- * - String menuDefFile
- * - String menuName
- * - String menuWrapperClassName
- * - String associatedContentId
- *
- * This is an interactive FreeMarker transform that allows the user to modify the contents that are placed within it.
- */
-public class MenuWrapTransform implements TemplateTransformModel {
-
-    public static final String module = MenuWrapTransform.class.getName();
-    public static final String [] upSaveKeyNames = {"globalNodeTrail"};
-    public static final String [] saveKeyNames = {"contentId", "subContentId", "subDataResourceTypeId", "mimeTypeId", "whenMap", "locale",  "wrapTemplateId", "encloseWrapText", "nullThruDatesOnly", "renderOnStart", "renderOnClose", "menuDefFile", "menuName", "associatedContentId", "wrapperClassName"};
-
-    @SuppressWarnings("unchecked")
-    public Writer getWriter(final Writer out, Map args) {
-        final Environment env = Environment.getCurrentEnvironment();
-        final Delegator delegator = FreeMarkerWorker.getWrappedObject("delegator", env);
-        final HttpServletRequest request = FreeMarkerWorker.getWrappedObject("request", env);
-        final HttpServletResponse response = FreeMarkerWorker.getWrappedObject("response", env);
-        final HttpSession session = FreeMarkerWorker.getWrappedObject("session", env);
-
-        final GenericValue userLogin = FreeMarkerWorker.getWrappedObject("userLogin", env);
-        final Map<String, Object> templateCtx = FreeMarkerWorker.getWrappedObject("context", env);
-
-        FreeMarkerWorker.getSiteParameters(request, templateCtx);
-
-        final Map<String, Object> savedValuesUp = new HashMap<String, Object>();
-        FreeMarkerWorker.saveContextValues(templateCtx, upSaveKeyNames, savedValuesUp);
-
-        Map<String, Object> checkedArgs = UtilGenerics.checkMap(args);
-        FreeMarkerWorker.overrideWithArgs(templateCtx, checkedArgs);
-        //final String menuDefFile = (String)templateCtx.get("menuDefFile");
-        //final String menuName = (String)templateCtx.get("menuName");
-        //final String associatedContentId = (String)templateCtx.get("associatedContentId");
-        List<Map<String, ? extends Object>> trail = UtilGenerics.checkList(templateCtx.get("globalNodeTrail"));
-        String contentAssocPredicateId = (String)templateCtx.get("contentAssocPredicateId");
-        String strNullThruDatesOnly = (String)templateCtx.get("nullThruDatesOnly");
-        Boolean nullThruDatesOnly = (strNullThruDatesOnly != null && strNullThruDatesOnly.equalsIgnoreCase("true")) ? Boolean.TRUE :Boolean.FALSE;
-        GenericValue val = null;
-        try {
-            if (WidgetContentWorker.contentWorker != null) {
-                val = WidgetContentWorker.contentWorker.getCurrentContentExt(delegator, trail, userLogin, templateCtx, nullThruDatesOnly, contentAssocPredicateId);
-            } else {
-                Debug.logError("Not rendering content, not ContentWorker found.", module);
-            }
-        } catch (GeneralException e) {
-            throw new RuntimeException("Error getting current content. " + e.toString());
-        }
-        final GenericValue view = val;
-
-        String dataResourceId = null;
-        try {
-            dataResourceId = (String) view.get("drDataResourceId");
-        } catch (Exception e) {
-            dataResourceId = (String) view.get("dataResourceId");
-        }
-        String subContentIdSub = (String) view.get("contentId");
-        // This order is taken so that the dataResourceType can be overridden in the transform arguments.
-        String subDataResourceTypeId = (String)templateCtx.get("subDataResourceTypeId");
-        if (UtilValidate.isEmpty(subDataResourceTypeId)) {
-            try {
-                subDataResourceTypeId = (String) view.get("drDataResourceTypeId");
-            } catch (Exception e) {
-                // view may be "Content"
-            }
-            // TODO: If this value is still empty then it is probably necessary to get a value from
-            // the parent context. But it will already have one and it is the same context that is
-            // being passed.
-        }
-        // This order is taken so that the mimeType can be overridden in the transform arguments.
-        String mimeTypeId = null;
-        if (WidgetContentWorker.contentWorker != null) {
-            mimeTypeId = WidgetContentWorker.contentWorker.getMimeTypeIdExt(delegator, view, templateCtx);
-        } else {
-            Debug.logError("Not rendering content, not ContentWorker found.", module);
-        }
-        templateCtx.put("drDataResourceId", dataResourceId);
-        templateCtx.put("mimeTypeId", mimeTypeId);
-        templateCtx.put("dataResourceId", dataResourceId);
-        templateCtx.put("subContentIdSub", subContentIdSub);
-        templateCtx.put("subDataResourceTypeId", subDataResourceTypeId);
-        final Map<String, Object> savedValues = new HashMap<String, Object>();
-        FreeMarkerWorker.saveContextValues(templateCtx, saveKeyNames, savedValues);
-
-        final StringBuilder buf = new StringBuilder();
-
-        return new LoopWriter(out) {
-
-            @Override
-            public int onStart() throws TemplateModelException, IOException {
-                String renderOnStart = (String)templateCtx.get("renderOnStart");
-                if (renderOnStart != null && renderOnStart.equalsIgnoreCase("true")) {
-                    renderMenu();
-                }
-                return TransformControl.EVALUATE_BODY;
-            }
-
-            @Override
-            public void write(char cbuf[], int off, int len) {
-                buf.append(cbuf, off, len);
-            }
-
-            @Override
-            public void flush() throws IOException {
-                out.flush();
-            }
-
-            @Override
-            public void close() throws IOException {
-                FreeMarkerWorker.reloadValues(templateCtx, savedValues, env);
-                String wrappedContent = buf.toString();
-                out.write(wrappedContent);
-                String renderOnClose = (String)templateCtx.get("renderOnClose");
-                if (renderOnClose == null || !renderOnClose.equalsIgnoreCase("false")) {
-                    renderMenu();
-                }
-                FreeMarkerWorker.reloadValues(templateCtx, savedValuesUp, env);
-            }
-
-            public void renderMenu() throws IOException {
-
-                String menuDefFile = (String)templateCtx.get("menuDefFile");
-                String menuName = (String)templateCtx.get("menuName");
-                String menuWrapperClassName = (String)templateCtx.get("menuWrapperClassName");
-                HtmlMenuWrapper menuWrapper = HtmlMenuWrapper.getMenuWrapper(request, response, session, menuDefFile, menuName, menuWrapperClassName);
-
-                if (menuWrapper == null) {
-                    throw new IOException("HtmlMenuWrapper with def file:" + menuDefFile + " menuName:" + menuName + " and HtmlMenuWrapper class:" + menuWrapperClassName + " could not be instantiated.");
-                }
-
-                String associatedContentId = (String)templateCtx.get("associatedContentId");
-                menuWrapper.putInContext("defaultAssociatedContentId", associatedContentId);
-                menuWrapper.putInContext("currentValue", view);
-
-                String menuStr = menuWrapper.renderMenuString();
-                out.write(menuStr);
-            }
-
-        };
-    }
-}
+/*******************************************************************************

+ * 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.renderer;

+

+import java.io.IOException;

+import java.io.Writer;

+import java.util.HashMap;

+import java.util.List;

+import java.util.Map;

+

+import javax.servlet.http.HttpServletRequest;

+import javax.servlet.http.HttpServletResponse;

+import javax.servlet.http.HttpSession;

+

+import org.ofbiz.base.util.Debug;

+import org.ofbiz.base.util.GeneralException;

+import org.ofbiz.base.util.UtilGenerics;

+import org.ofbiz.base.util.UtilValidate;

+import org.ofbiz.base.util.template.FreeMarkerWorker;

+import org.ofbiz.entity.Delegator;

+import org.ofbiz.entity.GenericValue;

+import org.ofbiz.webapp.ftl.LoopWriter;

+import org.ofbiz.widget.content.WidgetContentWorker;

+import org.ofbiz.widget.renderer.html.HtmlMenuWrapper;

+

+import freemarker.core.Environment;

+import freemarker.template.TemplateModelException;

+import freemarker.template.TemplateTransformModel;

+import freemarker.template.TransformControl;

+

+//import com.clarkware.profiler.Profiler;

+/**

+ * MenuWrapTransform -  a FreeMarker transform that allow the ModelMenu

+ * stuff to be used at the FM level. It can be used to add "function bars"

+ * to pages.

+ *

+ * Accepts the following arguments (all of which can alternatively be present in the template context):

+ * - List<Map<String, ? extends Object>> globalNodeTrail

+ * - String contentAssocPredicateId

+ * - String nullThruDatesOnly

+ * - String subDataResourceTypeId

+ * - String renderOnStart

+ * - String renderOnClose

+ * - String menuDefFile

+ * - String menuName

+ * - String menuWrapperClassName

+ * - String associatedContentId

+ *

+ * This is an interactive FreeMarker transform that allows the user to modify the contents that are placed within it.

+ */

+public class MenuWrapTransform implements TemplateTransformModel {

+

+    public static final String module = MenuWrapTransform.class.getName();

+    public static final String [] upSaveKeyNames = {"globalNodeTrail"};

+    public static final String [] saveKeyNames = {"contentId", "subContentId", "subDataResourceTypeId", "mimeTypeId", "whenMap", "locale",  "wrapTemplateId", "encloseWrapText", "nullThruDatesOnly", "renderOnStart", "renderOnClose", "menuDefFile", "menuName", "associatedContentId", "wrapperClassName"};

+

+    @SuppressWarnings("unchecked")

+    public Writer getWriter(final Writer out, Map args) {

+        final Environment env = Environment.getCurrentEnvironment();

+        final Delegator delegator = FreeMarkerWorker.getWrappedObject("delegator", env);

+        final HttpServletRequest request = FreeMarkerWorker.getWrappedObject("request", env);

+        final HttpServletResponse response = FreeMarkerWorker.getWrappedObject("response", env);

+        final HttpSession session = FreeMarkerWorker.getWrappedObject("session", env);

+

+        final GenericValue userLogin = FreeMarkerWorker.getWrappedObject("userLogin", env);

+        final Map<String, Object> templateCtx = FreeMarkerWorker.getWrappedObject("context", env);

+

+        FreeMarkerWorker.getSiteParameters(request, templateCtx);

+

+        final Map<String, Object> savedValuesUp = new HashMap<String, Object>();

+        FreeMarkerWorker.saveContextValues(templateCtx, upSaveKeyNames, savedValuesUp);

+

+        Map<String, Object> checkedArgs = UtilGenerics.checkMap(args);

+        FreeMarkerWorker.overrideWithArgs(templateCtx, checkedArgs);

+        //final String menuDefFile = (String)templateCtx.get("menuDefFile");

+        //final String menuName = (String)templateCtx.get("menuName");

+        //final String associatedContentId = (String)templateCtx.get("associatedContentId");

+        List<Map<String, ? extends Object>> trail = UtilGenerics.checkList(templateCtx.get("globalNodeTrail"));

+        String contentAssocPredicateId = (String)templateCtx.get("contentAssocPredicateId");

+        String strNullThruDatesOnly = (String)templateCtx.get("nullThruDatesOnly");

+        Boolean nullThruDatesOnly = (strNullThruDatesOnly != null && strNullThruDatesOnly.equalsIgnoreCase("true")) ? Boolean.TRUE :Boolean.FALSE;

+        GenericValue val = null;

+        try {

+            if (WidgetContentWorker.contentWorker != null) {

+                val = WidgetContentWorker.contentWorker.getCurrentContentExt(delegator, trail, userLogin, templateCtx, nullThruDatesOnly, contentAssocPredicateId);

+            } else {

+                Debug.logError("Not rendering content, not ContentWorker found.", module);

+            }

+        } catch (GeneralException e) {

+            throw new RuntimeException("Error getting current content. " + e.toString());

+        }

+        final GenericValue view = val;

+

+        String dataResourceId = null;

+        try {

+            dataResourceId = (String) view.get("drDataResourceId");

+        } catch (Exception e) {

+            dataResourceId = (String) view.get("dataResourceId");

+        }

+        String subContentIdSub = (String) view.get("contentId");

+        // This order is taken so that the dataResourceType can be overridden in the transform arguments.

+        String subDataResourceTypeId = (String)templateCtx.get("subDataResourceTypeId");

+        if (UtilValidate.isEmpty(subDataResourceTypeId)) {

+            try {

+                subDataResourceTypeId = (String) view.get("drDataResourceTypeId");

+            } catch (Exception e) {

+                // view may be "Content"

+            }

+            // TODO: If this value is still empty then it is probably necessary to get a value from

+            // the parent context. But it will already have one and it is the same context that is

+            // being passed.

+        }

+        // This order is taken so that the mimeType can be overridden in the transform arguments.

+        String mimeTypeId = null;

+        if (WidgetContentWorker.contentWorker != null) {

+            mimeTypeId = WidgetContentWorker.contentWorker.getMimeTypeIdExt(delegator, view, templateCtx);

+        } else {

+            Debug.logError("Not rendering content, not ContentWorker found.", module);

+        }

+        templateCtx.put("drDataResourceId", dataResourceId);

+        templateCtx.put("mimeTypeId", mimeTypeId);

+        templateCtx.put("dataResourceId", dataResourceId);

+        templateCtx.put("subContentIdSub", subContentIdSub);

+        templateCtx.put("subDataResourceTypeId", subDataResourceTypeId);

+        final Map<String, Object> savedValues = new HashMap<String, Object>();

+        FreeMarkerWorker.saveContextValues(templateCtx, saveKeyNames, savedValues);

+

+        final StringBuilder buf = new StringBuilder();

+

+        return new LoopWriter(out) {

+

+            @Override

+            public int onStart() throws TemplateModelException, IOException {

+                String renderOnStart = (String)templateCtx.get("renderOnStart");

+                if (renderOnStart != null && renderOnStart.equalsIgnoreCase("true")) {

+                    renderMenu();

+                }

+                return TransformControl.EVALUATE_BODY;

+            }

+

+            @Override

+            public void write(char cbuf[], int off, int len) {

+                buf.append(cbuf, off, len);

+            }

+

+            @Override

+            public void flush() throws IOException {

+                out.flush();

+            }

+

+            @Override

+            public void close() throws IOException {

+                FreeMarkerWorker.reloadValues(templateCtx, savedValues, env);

+                String wrappedContent = buf.toString();

+                out.write(wrappedContent);

+                String renderOnClose = (String)templateCtx.get("renderOnClose");

+                if (renderOnClose == null || !renderOnClose.equalsIgnoreCase("false")) {

+                    renderMenu();

+                }

+                FreeMarkerWorker.reloadValues(templateCtx, savedValuesUp, env);

+            }

+

+            public void renderMenu() throws IOException {

+

+                String menuDefFile = (String)templateCtx.get("menuDefFile");

+                String menuName = (String)templateCtx.get("menuName");

+                String menuWrapperClassName = (String)templateCtx.get("menuWrapperClassName");

+                HtmlMenuWrapper menuWrapper = HtmlMenuWrapper.getMenuWrapper(request, response, session, menuDefFile, menuName, menuWrapperClassName);

+

+                if (menuWrapper == null) {

+                    throw new IOException("HtmlMenuWrapper with def file:" + menuDefFile + " menuName:" + menuName + " and HtmlMenuWrapper class:" + menuWrapperClassName + " could not be instantiated.");

+                }

+

+                String associatedContentId = (String)templateCtx.get("associatedContentId");

+                menuWrapper.putInContext("defaultAssociatedContentId", associatedContentId);

+                menuWrapper.putInContext("currentValue", view);

+

+                String menuStr = menuWrapper.renderMenuString();

+                out.write(menuStr);

+            }

+

+        };

+    }

+}

diff --git a/framework/widget/src/org/ofbiz/widget/form/Paginator.java b/framework/widget/src/org/ofbiz/widget/renderer/Paginator.java
similarity index 98%
rename from framework/widget/src/org/ofbiz/widget/form/Paginator.java
rename to framework/widget/src/org/ofbiz/widget/renderer/Paginator.java
index 621c9b0..2d051f1 100644
--- a/framework/widget/src/org/ofbiz/widget/form/Paginator.java
+++ b/framework/widget/src/org/ofbiz/widget/renderer/Paginator.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations

  * under the License.

  *******************************************************************************/

-package org.ofbiz.widget.form;

+package org.ofbiz.widget.renderer;

 

 import java.util.Iterator;

 import java.util.List;

@@ -29,6 +29,7 @@
 import org.ofbiz.entity.GenericEntityException;

 import org.ofbiz.entity.util.EntityListIterator;

 import org.ofbiz.widget.WidgetWorker;

+import org.ofbiz.widget.model.ModelForm;

 

 /**

  * Utility methods for handling list pagination.

diff --git a/framework/widget/src/org/ofbiz/widget/screen/ScreenRenderException.java b/framework/widget/src/org/ofbiz/widget/renderer/ScreenRenderException.java
similarity index 97%
rename from framework/widget/src/org/ofbiz/widget/screen/ScreenRenderException.java
rename to framework/widget/src/org/ofbiz/widget/renderer/ScreenRenderException.java
index ca8bdbc..9406a33 100644
--- a/framework/widget/src/org/ofbiz/widget/screen/ScreenRenderException.java
+++ b/framework/widget/src/org/ofbiz/widget/renderer/ScreenRenderException.java
@@ -1,48 +1,48 @@
-/*******************************************************************************
- * 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.screen;
-
-import org.ofbiz.base.util.GeneralException;
-
-/**
- * Wraps any exceptions encountered during the rendering of
- * a screen.  It is thrown to the top of the recursive
- * rendering process so that we avoid having to log redundant
- * exceptions.
- */
-@SuppressWarnings("serial")
-public class ScreenRenderException extends GeneralException {
-
-    public ScreenRenderException() {
-        super();
-    }
-
-    public ScreenRenderException(Throwable nested) {
-        super(nested);
-    }
-
-    public ScreenRenderException(String str) {
-        super(str);
-    }
-
-    public ScreenRenderException(String str, Throwable nested) {
-        super(str, nested);
-    }
-}
+/*******************************************************************************

+ * 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.renderer;

+

+import org.ofbiz.base.util.GeneralException;

+

+/**

+ * Wraps any exceptions encountered during the rendering of

+ * a screen.  It is thrown to the top of the recursive

+ * rendering process so that we avoid having to log redundant

+ * exceptions.

+ */

+@SuppressWarnings("serial")

+public class ScreenRenderException extends GeneralException {

+

+    public ScreenRenderException() {

+        super();

+    }

+

+    public ScreenRenderException(Throwable nested) {

+        super(nested);

+    }

+

+    public ScreenRenderException(String str) {

+        super(str);

+    }

+

+    public ScreenRenderException(String str, Throwable nested) {

+        super(str, nested);

+    }

+}

diff --git a/framework/widget/src/org/ofbiz/widget/screen/ScreenRenderer.java b/framework/widget/src/org/ofbiz/widget/renderer/ScreenRenderer.java
similarity index 98%
rename from framework/widget/src/org/ofbiz/widget/screen/ScreenRenderer.java
rename to framework/widget/src/org/ofbiz/widget/renderer/ScreenRenderer.java
index 738c009..87192b5 100644
--- a/framework/widget/src/org/ofbiz/widget/screen/ScreenRenderer.java
+++ b/framework/widget/src/org/ofbiz/widget/renderer/ScreenRenderer.java
@@ -1,316 +1,318 @@
-/*******************************************************************************
- * 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.screen;
-
-import java.io.IOException;
-import java.io.StringWriter;
-import java.io.Writer;
-import java.util.HashMap;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-import java.util.Set;
-
-import javax.servlet.ServletContext;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import javax.servlet.http.HttpSession;
-import javax.xml.parsers.ParserConfigurationException;
-
-import org.ofbiz.base.util.Debug;
-import org.ofbiz.base.util.GeneralException;
-import org.ofbiz.base.util.UtilDateTime;
-import org.ofbiz.base.util.UtilFormatOut;
-import org.ofbiz.base.util.UtilGenerics;
-import org.ofbiz.base.util.UtilHttp;
-import org.ofbiz.base.util.UtilMisc;
-import org.ofbiz.base.util.UtilValidate;
-import org.ofbiz.base.util.collections.MapStack;
-import org.ofbiz.base.util.template.FreeMarkerWorker;
-import org.ofbiz.entity.Delegator;
-import org.ofbiz.entity.GenericEntity;
-import org.ofbiz.entity.GenericValue;
-import org.ofbiz.security.Security;
-import org.ofbiz.service.DispatchContext;
-import org.ofbiz.service.GenericServiceException;
-import org.ofbiz.service.LocalDispatcher;
-import org.ofbiz.webapp.control.LoginWorker;
-import org.ofbiz.webapp.website.WebSiteWorker;
-import org.ofbiz.widget.cache.GenericWidgetOutput;
-import org.ofbiz.widget.cache.ScreenCache;
-import org.ofbiz.widget.cache.WidgetContextCacheKey;
-import org.xml.sax.SAXException;
-
-import freemarker.ext.jsp.TaglibFactory;
-import freemarker.ext.servlet.HttpRequestHashModel;
-import freemarker.ext.servlet.HttpSessionHashModel;
-
-/**
- * Widget Library - Screen model class
- */
-public class ScreenRenderer {
-
-    public static final String module = ScreenRenderer.class.getName();
-
-    protected Appendable writer;
-    protected MapStack<String> context;
-    protected ScreenStringRenderer screenStringRenderer;
-    protected int renderFormSeqNumber = 0;
-
-    public ScreenRenderer(Appendable writer, MapStack<String> context, ScreenStringRenderer screenStringRenderer) {
-        this.writer = writer;
-        this.context = context;
-        if (this.context == null) this.context = MapStack.create();
-        this.screenStringRenderer = screenStringRenderer;
-    }
-
-    /**
-     * Renders the named screen using the render environment configured when this ScreenRenderer was created.
-     *
-     * @param combinedName A combination of the resource name/location for the screen XML file and the name of the screen within that file, separated by a pound sign ("#"). This is the same format that is used in the view-map elements on the controller.xml file.
-     * @throws IOException
-     * @throws SAXException
-     * @throws ParserConfigurationException
-     */
-    public String render(String combinedName) throws GeneralException, IOException, SAXException, ParserConfigurationException {
-        String resourceName = ScreenFactory.getResourceNameFromCombined(combinedName);
-        String screenName = ScreenFactory.getScreenNameFromCombined(combinedName);
-        this.render(resourceName, screenName);
-        return "";
-    }
-
-    /**
-     * Renders the named screen using the render environment configured when this ScreenRenderer was created.
-     *
-     * @param resourceName The name/location of the resource to use, can use "component://[component-name]/" and "ofbiz://" and other special OFBiz style URLs
-     * @param screenName The name of the screen within the XML file specified by the resourceName.
-     * @throws IOException
-     * @throws SAXException
-     * @throws ParserConfigurationException
-     */
-    public String render(String resourceName, String screenName) throws GeneralException, IOException, SAXException, ParserConfigurationException {
-        ModelScreen modelScreen = ScreenFactory.getScreenFromLocation(resourceName, screenName);
-        if (modelScreen.getUseCache()) {
-            // if in the screen definition use-cache is set to true
-            // then try to get an already built screen output from the cache:
-            // 1) if we find it then we get it and attach it to the passed in writer
-            // 2) if we can't find one, we create a new StringWriter,
-            //    and pass it to the renderScreenString;
-            //    then we wrap its content and put it in the cache;
-            //    and we attach it to the passed in writer
-            WidgetContextCacheKey wcck = new WidgetContextCacheKey(context);
-            String screenCombinedName = resourceName + ":" + screenName;
-            ScreenCache screenCache = new ScreenCache();
-            GenericWidgetOutput gwo = screenCache.get(screenCombinedName, wcck);
-            if (gwo == null) {
-                Writer sw = new StringWriter();
-                modelScreen.renderScreenString(sw, context, screenStringRenderer);
-                gwo = new GenericWidgetOutput(sw.toString());
-                screenCache.put(screenCombinedName, wcck, gwo);
-                writer.append(gwo.toString());
-            } else {
-                writer.append(gwo.toString());
-            }
-        } else {
-            context.put("renderFormSeqNumber", String.valueOf(renderFormSeqNumber));
-            modelScreen.renderScreenString(writer, context, screenStringRenderer);
-        }
-        return "";
-    }
-
-    public void setRenderFormUniqueSeq (int renderFormSeqNumber) {
-        this.renderFormSeqNumber = renderFormSeqNumber;
-    }
-
-    public ScreenStringRenderer getScreenStringRenderer() {
-        return this.screenStringRenderer;
-    }
-
-    public void populateBasicContext(Map<String, Object> parameters, Delegator delegator, LocalDispatcher dispatcher, Security security, Locale locale, GenericValue userLogin) {
-        populateBasicContext(context, this, parameters, delegator, dispatcher, security, locale, userLogin);
-    }
-
-    public static void populateBasicContext(MapStack<String> context, ScreenRenderer screens, Map<String, Object> parameters, Delegator delegator, LocalDispatcher dispatcher, Security security, Locale locale, GenericValue userLogin) {
-        // ========== setup values that should always be in a screen context
-        // include an object to more easily render screens
-        context.put("screens", screens);
-
-        // make a reference for high level variables, a global context
-        context.put("globalContext", context.standAloneStack());
-
-        // make sure the "nullField" object is in there for entity ops; note this is nullField and not null because as null causes problems in FreeMarker and such...
-        context.put("nullField", GenericEntity.NULL_FIELD);
-
-        context.put("parameters", parameters);
-        context.put("delegator", delegator);
-        context.put("dispatcher", dispatcher);
-        context.put("security", security);
-        context.put("locale", locale);
-        context.put("userLogin", userLogin);
-        context.put("nowTimestamp", UtilDateTime.nowTimestamp());
-        try {
-            Map<String, Object> result = dispatcher.runSync("getUserPreferenceGroup", UtilMisc.toMap("userLogin", userLogin, "userPrefGroupTypeId", "GLOBAL_PREFERENCES"));
-            context.put("userPreferences", result.get("userPrefMap"));
-        } catch (GenericServiceException e) {
-            Debug.logError(e, "Error while getting user preferences: ", module);
-        }
-    }
-
-    /**
-     * This method populates the context for this ScreenRenderer based on the HTTP Request and Response objects and the ServletContext.
-     * It leverages various conventions used in other places, namely the ControlServlet and so on, of OFBiz to get the different resources needed.
-     *
-     * @param request
-     * @param response
-     * @param servletContext
-     */
-    public void populateContextForRequest(HttpServletRequest request, HttpServletResponse response, ServletContext servletContext) {
-        populateContextForRequest(context, this, request, response, servletContext);
-    }
-
-    @SuppressWarnings("rawtypes")
-    public static void populateContextForRequest(MapStack<String> context, ScreenRenderer screens, HttpServletRequest request, HttpServletResponse response, ServletContext servletContext) {
-        HttpSession session = request.getSession();
-
-        // attribute names to skip for session and application attributes; these are all handled as special cases, duplicating results and causing undesired messages
-        Set<String> attrNamesToSkip = UtilMisc.toSet("delegator", "dispatcher", "security", "webSiteId",
-                "org.apache.catalina.jsp_classpath");
-        Map<String, Object> parameterMap = UtilHttp.getCombinedMap(request, attrNamesToSkip);
-
-        GenericValue userLogin = (GenericValue) session.getAttribute("userLogin");
-
-        populateBasicContext(context, screens, parameterMap, (Delegator) request.getAttribute("delegator"),
-                (LocalDispatcher) request.getAttribute("dispatcher"),
-                (Security) request.getAttribute("security"), UtilHttp.getLocale(request), userLogin);
-
-        context.put("autoUserLogin", session.getAttribute("autoUserLogin"));
-        context.put("person", session.getAttribute("person"));
-        context.put("partyGroup", session.getAttribute("partyGroup"));
-
-        // some things also seem to require this, so here it is:
-        request.setAttribute("userLogin", userLogin);
-
-        // set up the user's time zone
-        context.put("timeZone", UtilHttp.getTimeZone(request));
-
-        // ========== setup values that are specific to OFBiz webapps
-
-        context.put("request", request);
-        context.put("response", response);
-        context.put("session", session);
-        context.put("application", servletContext);
-        if (session != null) {
-            context.put("webappName", session.getAttribute("_WEBAPP_NAME_"));
-        }
-        if (servletContext != null) {
-            String rootDir = (String) context.get("rootDir");
-            String webSiteId = (String) context.get("webSiteId");
-            String https = (String) context.get("https");
-            if (UtilValidate.isEmpty(rootDir)) {
-                rootDir = servletContext.getRealPath("/");
-                context.put("rootDir", rootDir);
-            }
-            if (UtilValidate.isEmpty(webSiteId)) {
-                webSiteId = WebSiteWorker.getWebSiteId(request);
-                context.put("webSiteId", webSiteId);
-            }
-            if (UtilValidate.isEmpty(https)) {
-                https = (String) servletContext.getAttribute("https");
-                context.put("https", https);
-            }
-        }
-        context.put("javaScriptEnabled", Boolean.valueOf(UtilHttp.isJavaScriptEnabled(request)));
-
-        // these ones are FreeMarker specific and will only work in FTL templates, mainly here for backward compatibility
-        context.put("sessionAttributes", new HttpSessionHashModel(session, FreeMarkerWorker.getDefaultOfbizWrapper()));
-        context.put("requestAttributes", new HttpRequestHashModel(request, FreeMarkerWorker.getDefaultOfbizWrapper()));
-        TaglibFactory JspTaglibs = new TaglibFactory(servletContext);
-        context.put("JspTaglibs", JspTaglibs);
-        context.put("requestParameters",  UtilHttp.getParameterMap(request));
-        
-        // this is a dummy object to stand-in for the JPublish page object for backward compatibility
-        context.put("page", new HashMap());
-
-        // some information from/about the ControlServlet environment
-        context.put("controlPath", request.getAttribute("_CONTROL_PATH_"));
-        context.put("contextRoot", request.getAttribute("_CONTEXT_ROOT_"));
-        context.put("serverRoot", request.getAttribute("_SERVER_ROOT_URL_"));
-        context.put("checkLoginUrl", LoginWorker.makeLoginUrl(request));
-        String externalLoginKey = LoginWorker.getExternalLoginKey(request);
-        String externalKeyParam = externalLoginKey == null ? "" : "&amp;externalLoginKey=" + externalLoginKey;
-        context.put("externalLoginKey", externalLoginKey);
-        context.put("externalKeyParam", externalKeyParam);
-
-        // setup message lists
-        List<String> eventMessageList = UtilGenerics.toList(request.getAttribute("eventMessageList"));
-        if (eventMessageList == null) eventMessageList = new LinkedList<String>();
-        List<String> errorMessageList = UtilGenerics.toList(request.getAttribute("errorMessageList"));
-        if (errorMessageList == null) errorMessageList = new LinkedList<String>();
-
-        if (request.getAttribute("_EVENT_MESSAGE_") != null) {
-            eventMessageList.add(UtilFormatOut.replaceString((String) request.getAttribute("_EVENT_MESSAGE_"), "\n", "<br/>"));
-            request.removeAttribute("_EVENT_MESSAGE_");
-        }
-        List<String> msgList = UtilGenerics.toList(request.getAttribute("_EVENT_MESSAGE_LIST_"));
-        if (msgList != null) {
-            eventMessageList.addAll(msgList);
-            request.removeAttribute("_EVENT_MESSAGE_LIST_");
-        }
-        if (request.getAttribute("_ERROR_MESSAGE_") != null) {
-            errorMessageList.add(UtilFormatOut.replaceString((String) request.getAttribute("_ERROR_MESSAGE_"), "\n", "<br/>"));
-            request.removeAttribute("_ERROR_MESSAGE_");
-        }
-        if (session.getAttribute("_ERROR_MESSAGE_") != null) {
-            errorMessageList.add(UtilFormatOut.replaceString((String) session.getAttribute("_ERROR_MESSAGE_"), "\n", "<br/>"));
-            session.removeAttribute("_ERROR_MESSAGE_");
-        }
-        msgList = UtilGenerics.toList(request.getAttribute("_ERROR_MESSAGE_LIST_"));
-        if (msgList != null) {
-            errorMessageList.addAll(msgList);
-            request.removeAttribute("_ERROR_MESSAGE_LIST_");
-        }
-        context.put("eventMessageList", eventMessageList);
-        context.put("errorMessageList", errorMessageList);
-
-        if (request.getAttribute("serviceValidationException") != null) {
-            context.put("serviceValidationException", request.getAttribute("serviceValidationException"));
-            request.removeAttribute("serviceValidationException");
-        }
-
-        // if there was an error message, this is an error
-        context.put("isError", errorMessageList.size() > 0 ? Boolean.TRUE : Boolean.FALSE);
-        // if a parameter was passed saying this is an error, it is an error
-        if ("true".equals(parameterMap.get("isError"))) {
-            context.put("isError", Boolean.TRUE);
-        }
-
-        // to preserve these values, push the MapStack
-        context.push();
-    }
-
-    public Map<String, Object> getContext() {
-        return context;
-    }
-
-    public void populateContextForService(DispatchContext dctx, Map<String, Object> serviceContext) {
-        this.populateBasicContext(serviceContext, dctx.getDelegator(), dctx.getDispatcher(),
-                dctx.getSecurity(), (Locale) serviceContext.get("locale"), (GenericValue) serviceContext.get("userLogin"));
-    }
-}
+/*******************************************************************************

+ * 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.renderer;

+

+import java.io.IOException;

+import java.io.StringWriter;

+import java.io.Writer;

+import java.util.HashMap;

+import java.util.LinkedList;

+import java.util.List;

+import java.util.Locale;

+import java.util.Map;

+import java.util.Set;

+

+import javax.servlet.ServletContext;

+import javax.servlet.http.HttpServletRequest;

+import javax.servlet.http.HttpServletResponse;

+import javax.servlet.http.HttpSession;

+import javax.xml.parsers.ParserConfigurationException;

+

+import org.ofbiz.base.util.Debug;

+import org.ofbiz.base.util.GeneralException;

+import org.ofbiz.base.util.UtilDateTime;

+import org.ofbiz.base.util.UtilFormatOut;

+import org.ofbiz.base.util.UtilGenerics;

+import org.ofbiz.base.util.UtilHttp;

+import org.ofbiz.base.util.UtilMisc;

+import org.ofbiz.base.util.UtilValidate;

+import org.ofbiz.base.util.collections.MapStack;

+import org.ofbiz.base.util.template.FreeMarkerWorker;

+import org.ofbiz.entity.Delegator;

+import org.ofbiz.entity.GenericEntity;

+import org.ofbiz.entity.GenericValue;

+import org.ofbiz.security.Security;

+import org.ofbiz.service.DispatchContext;

+import org.ofbiz.service.GenericServiceException;

+import org.ofbiz.service.LocalDispatcher;

+import org.ofbiz.webapp.control.LoginWorker;

+import org.ofbiz.webapp.website.WebSiteWorker;

+import org.ofbiz.widget.cache.GenericWidgetOutput;

+import org.ofbiz.widget.cache.ScreenCache;

+import org.ofbiz.widget.cache.WidgetContextCacheKey;

+import org.ofbiz.widget.model.ModelScreen;

+import org.ofbiz.widget.model.ScreenFactory;

+import org.xml.sax.SAXException;

+

+import freemarker.ext.jsp.TaglibFactory;

+import freemarker.ext.servlet.HttpRequestHashModel;

+import freemarker.ext.servlet.HttpSessionHashModel;

+

+/**

+ * Widget Library - Screen model class

+ */

+public class ScreenRenderer {

+

+    public static final String module = ScreenRenderer.class.getName();

+

+    protected Appendable writer;

+    protected MapStack<String> context;

+    protected ScreenStringRenderer screenStringRenderer;

+    protected int renderFormSeqNumber = 0;

+

+    public ScreenRenderer(Appendable writer, MapStack<String> context, ScreenStringRenderer screenStringRenderer) {

+        this.writer = writer;

+        this.context = context;

+        if (this.context == null) this.context = MapStack.create();

+        this.screenStringRenderer = screenStringRenderer;

+    }

+

+    /**

+     * Renders the named screen using the render environment configured when this ScreenRenderer was created.

+     *

+     * @param combinedName A combination of the resource name/location for the screen XML file and the name of the screen within that file, separated by a pound sign ("#"). This is the same format that is used in the view-map elements on the controller.xml file.

+     * @throws IOException

+     * @throws SAXException

+     * @throws ParserConfigurationException

+     */

+    public String render(String combinedName) throws GeneralException, IOException, SAXException, ParserConfigurationException {

+        String resourceName = ScreenFactory.getResourceNameFromCombined(combinedName);

+        String screenName = ScreenFactory.getScreenNameFromCombined(combinedName);

+        this.render(resourceName, screenName);

+        return "";

+    }

+

+    /**

+     * Renders the named screen using the render environment configured when this ScreenRenderer was created.

+     *

+     * @param resourceName The name/location of the resource to use, can use "component://[component-name]/" and "ofbiz://" and other special OFBiz style URLs

+     * @param screenName The name of the screen within the XML file specified by the resourceName.

+     * @throws IOException

+     * @throws SAXException

+     * @throws ParserConfigurationException

+     */

+    public String render(String resourceName, String screenName) throws GeneralException, IOException, SAXException, ParserConfigurationException {

+        ModelScreen modelScreen = ScreenFactory.getScreenFromLocation(resourceName, screenName);

+        if (modelScreen.getUseCache()) {

+            // if in the screen definition use-cache is set to true

+            // then try to get an already built screen output from the cache:

+            // 1) if we find it then we get it and attach it to the passed in writer

+            // 2) if we can't find one, we create a new StringWriter,

+            //    and pass it to the renderScreenString;

+            //    then we wrap its content and put it in the cache;

+            //    and we attach it to the passed in writer

+            WidgetContextCacheKey wcck = new WidgetContextCacheKey(context);

+            String screenCombinedName = resourceName + ":" + screenName;

+            ScreenCache screenCache = new ScreenCache();

+            GenericWidgetOutput gwo = screenCache.get(screenCombinedName, wcck);

+            if (gwo == null) {

+                Writer sw = new StringWriter();

+                modelScreen.renderScreenString(sw, context, screenStringRenderer);

+                gwo = new GenericWidgetOutput(sw.toString());

+                screenCache.put(screenCombinedName, wcck, gwo);

+                writer.append(gwo.toString());

+            } else {

+                writer.append(gwo.toString());

+            }

+        } else {

+            context.put("renderFormSeqNumber", String.valueOf(renderFormSeqNumber));

+            modelScreen.renderScreenString(writer, context, screenStringRenderer);

+        }

+        return "";

+    }

+

+    public void setRenderFormUniqueSeq (int renderFormSeqNumber) {

+        this.renderFormSeqNumber = renderFormSeqNumber;

+    }

+

+    public ScreenStringRenderer getScreenStringRenderer() {

+        return this.screenStringRenderer;

+    }

+

+    public void populateBasicContext(Map<String, Object> parameters, Delegator delegator, LocalDispatcher dispatcher, Security security, Locale locale, GenericValue userLogin) {

+        populateBasicContext(context, this, parameters, delegator, dispatcher, security, locale, userLogin);

+    }

+

+    public static void populateBasicContext(MapStack<String> context, ScreenRenderer screens, Map<String, Object> parameters, Delegator delegator, LocalDispatcher dispatcher, Security security, Locale locale, GenericValue userLogin) {

+        // ========== setup values that should always be in a screen context

+        // include an object to more easily render screens

+        context.put("screens", screens);

+

+        // make a reference for high level variables, a global context

+        context.put("globalContext", context.standAloneStack());

+

+        // make sure the "nullField" object is in there for entity ops; note this is nullField and not null because as null causes problems in FreeMarker and such...

+        context.put("nullField", GenericEntity.NULL_FIELD);

+

+        context.put("parameters", parameters);

+        context.put("delegator", delegator);

+        context.put("dispatcher", dispatcher);

+        context.put("security", security);

+        context.put("locale", locale);

+        context.put("userLogin", userLogin);

+        context.put("nowTimestamp", UtilDateTime.nowTimestamp());

+        try {

+            Map<String, Object> result = dispatcher.runSync("getUserPreferenceGroup", UtilMisc.toMap("userLogin", userLogin, "userPrefGroupTypeId", "GLOBAL_PREFERENCES"));

+            context.put("userPreferences", result.get("userPrefMap"));

+        } catch (GenericServiceException e) {

+            Debug.logError(e, "Error while getting user preferences: ", module);

+        }

+    }

+

+    /**

+     * This method populates the context for this ScreenRenderer based on the HTTP Request and Response objects and the ServletContext.

+     * It leverages various conventions used in other places, namely the ControlServlet and so on, of OFBiz to get the different resources needed.

+     *

+     * @param request

+     * @param response

+     * @param servletContext

+     */

+    public void populateContextForRequest(HttpServletRequest request, HttpServletResponse response, ServletContext servletContext) {

+        populateContextForRequest(context, this, request, response, servletContext);

+    }

+

+    @SuppressWarnings("rawtypes")

+    public static void populateContextForRequest(MapStack<String> context, ScreenRenderer screens, HttpServletRequest request, HttpServletResponse response, ServletContext servletContext) {

+        HttpSession session = request.getSession();

+

+        // attribute names to skip for session and application attributes; these are all handled as special cases, duplicating results and causing undesired messages

+        Set<String> attrNamesToSkip = UtilMisc.toSet("delegator", "dispatcher", "security", "webSiteId",

+                "org.apache.catalina.jsp_classpath");

+        Map<String, Object> parameterMap = UtilHttp.getCombinedMap(request, attrNamesToSkip);

+

+        GenericValue userLogin = (GenericValue) session.getAttribute("userLogin");

+

+        populateBasicContext(context, screens, parameterMap, (Delegator) request.getAttribute("delegator"),

+                (LocalDispatcher) request.getAttribute("dispatcher"),

+                (Security) request.getAttribute("security"), UtilHttp.getLocale(request), userLogin);

+

+        context.put("autoUserLogin", session.getAttribute("autoUserLogin"));

+        context.put("person", session.getAttribute("person"));

+        context.put("partyGroup", session.getAttribute("partyGroup"));

+

+        // some things also seem to require this, so here it is:

+        request.setAttribute("userLogin", userLogin);

+

+        // set up the user's time zone

+        context.put("timeZone", UtilHttp.getTimeZone(request));

+

+        // ========== setup values that are specific to OFBiz webapps

+

+        context.put("request", request);

+        context.put("response", response);

+        context.put("session", session);

+        context.put("application", servletContext);

+        if (session != null) {

+            context.put("webappName", session.getAttribute("_WEBAPP_NAME_"));

+        }

+        if (servletContext != null) {

+            String rootDir = (String) context.get("rootDir");

+            String webSiteId = (String) context.get("webSiteId");

+            String https = (String) context.get("https");

+            if (UtilValidate.isEmpty(rootDir)) {

+                rootDir = servletContext.getRealPath("/");

+                context.put("rootDir", rootDir);

+            }

+            if (UtilValidate.isEmpty(webSiteId)) {

+                webSiteId = WebSiteWorker.getWebSiteId(request);

+                context.put("webSiteId", webSiteId);

+            }

+            if (UtilValidate.isEmpty(https)) {

+                https = (String) servletContext.getAttribute("https");

+                context.put("https", https);

+            }

+        }

+        context.put("javaScriptEnabled", Boolean.valueOf(UtilHttp.isJavaScriptEnabled(request)));

+

+        // these ones are FreeMarker specific and will only work in FTL templates, mainly here for backward compatibility

+        context.put("sessionAttributes", new HttpSessionHashModel(session, FreeMarkerWorker.getDefaultOfbizWrapper()));

+        context.put("requestAttributes", new HttpRequestHashModel(request, FreeMarkerWorker.getDefaultOfbizWrapper()));

+        TaglibFactory JspTaglibs = new TaglibFactory(servletContext);

+        context.put("JspTaglibs", JspTaglibs);

+        context.put("requestParameters",  UtilHttp.getParameterMap(request));

+        

+        // this is a dummy object to stand-in for the JPublish page object for backward compatibility

+        context.put("page", new HashMap());

+

+        // some information from/about the ControlServlet environment

+        context.put("controlPath", request.getAttribute("_CONTROL_PATH_"));

+        context.put("contextRoot", request.getAttribute("_CONTEXT_ROOT_"));

+        context.put("serverRoot", request.getAttribute("_SERVER_ROOT_URL_"));

+        context.put("checkLoginUrl", LoginWorker.makeLoginUrl(request));

+        String externalLoginKey = LoginWorker.getExternalLoginKey(request);

+        String externalKeyParam = externalLoginKey == null ? "" : "&amp;externalLoginKey=" + externalLoginKey;

+        context.put("externalLoginKey", externalLoginKey);

+        context.put("externalKeyParam", externalKeyParam);

+

+        // setup message lists

+        List<String> eventMessageList = UtilGenerics.toList(request.getAttribute("eventMessageList"));

+        if (eventMessageList == null) eventMessageList = new LinkedList<String>();

+        List<String> errorMessageList = UtilGenerics.toList(request.getAttribute("errorMessageList"));

+        if (errorMessageList == null) errorMessageList = new LinkedList<String>();

+

+        if (request.getAttribute("_EVENT_MESSAGE_") != null) {

+            eventMessageList.add(UtilFormatOut.replaceString((String) request.getAttribute("_EVENT_MESSAGE_"), "\n", "<br/>"));

+            request.removeAttribute("_EVENT_MESSAGE_");

+        }

+        List<String> msgList = UtilGenerics.toList(request.getAttribute("_EVENT_MESSAGE_LIST_"));

+        if (msgList != null) {

+            eventMessageList.addAll(msgList);

+            request.removeAttribute("_EVENT_MESSAGE_LIST_");

+        }

+        if (request.getAttribute("_ERROR_MESSAGE_") != null) {

+            errorMessageList.add(UtilFormatOut.replaceString((String) request.getAttribute("_ERROR_MESSAGE_"), "\n", "<br/>"));

+            request.removeAttribute("_ERROR_MESSAGE_");

+        }

+        if (session.getAttribute("_ERROR_MESSAGE_") != null) {

+            errorMessageList.add(UtilFormatOut.replaceString((String) session.getAttribute("_ERROR_MESSAGE_"), "\n", "<br/>"));

+            session.removeAttribute("_ERROR_MESSAGE_");

+        }

+        msgList = UtilGenerics.toList(request.getAttribute("_ERROR_MESSAGE_LIST_"));

+        if (msgList != null) {

+            errorMessageList.addAll(msgList);

+            request.removeAttribute("_ERROR_MESSAGE_LIST_");

+        }

+        context.put("eventMessageList", eventMessageList);

+        context.put("errorMessageList", errorMessageList);

+

+        if (request.getAttribute("serviceValidationException") != null) {

+            context.put("serviceValidationException", request.getAttribute("serviceValidationException"));

+            request.removeAttribute("serviceValidationException");

+        }

+

+        // if there was an error message, this is an error

+        context.put("isError", errorMessageList.size() > 0 ? Boolean.TRUE : Boolean.FALSE);

+        // if a parameter was passed saying this is an error, it is an error

+        if ("true".equals(parameterMap.get("isError"))) {

+            context.put("isError", Boolean.TRUE);

+        }

+

+        // to preserve these values, push the MapStack

+        context.push();

+    }

+

+    public Map<String, Object> getContext() {

+        return context;

+    }

+

+    public void populateContextForService(DispatchContext dctx, Map<String, Object> serviceContext) {

+        this.populateBasicContext(serviceContext, dctx.getDelegator(), dctx.getDispatcher(),

+                dctx.getSecurity(), (Locale) serviceContext.get("locale"), (GenericValue) serviceContext.get("userLogin"));

+    }

+}

diff --git a/framework/widget/src/org/ofbiz/widget/screen/ScreenStringRenderer.java b/framework/widget/src/org/ofbiz/widget/renderer/ScreenStringRenderer.java
similarity index 98%
rename from framework/widget/src/org/ofbiz/widget/screen/ScreenStringRenderer.java
rename to framework/widget/src/org/ofbiz/widget/renderer/ScreenStringRenderer.java
index ecb39eb..5cdc80d 100644
--- a/framework/widget/src/org/ofbiz/widget/screen/ScreenStringRenderer.java
+++ b/framework/widget/src/org/ofbiz/widget/renderer/ScreenStringRenderer.java
@@ -1,66 +1,67 @@
-/*******************************************************************************
- * 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.screen;
-
-import java.io.IOException;
-import java.util.Map;
-import org.ofbiz.entity.GenericValue;
-
-import org.ofbiz.base.util.GeneralException;
-
-/**
- * Widget Library - Screen String Renderer interface.
- */
-public interface ScreenStringRenderer {
-    public String getRendererName();
-    public void renderScreenBegin(Appendable writer, Map<String, Object> context) throws IOException;
-    public void renderScreenEnd(Appendable writer, Map<String, Object> context) throws IOException;
-    public void renderSectionBegin(Appendable writer, Map<String, Object> context, ModelScreenWidget.Section section) throws IOException;
-    public void renderSectionEnd(Appendable writer, Map<String, Object> context, ModelScreenWidget.Section section) throws IOException;
-    public void renderColumnContainer(Appendable writer, Map<String, Object> context, ModelScreenWidget.ColumnContainer columnContainer) throws IOException;
-    public void renderContainerBegin(Appendable writer, Map<String, Object> context, ModelScreenWidget.Container container) throws IOException;
-    public void renderContainerEnd(Appendable writer, Map<String, Object> context, ModelScreenWidget.Container container) throws IOException;
-    public void renderContentBegin(Appendable writer, Map<String, Object> context, ModelScreenWidget.Content content) throws IOException;
-    public void renderContentBody(Appendable writer, Map<String, Object> context, ModelScreenWidget.Content content) throws IOException;
-    public void renderContentEnd(Appendable writer, Map<String, Object> context, ModelScreenWidget.Content content) throws IOException;
-    public void renderSubContentBegin(Appendable writer, Map<String, Object> context, ModelScreenWidget.SubContent content) throws IOException;
-    public void renderSubContentBody(Appendable writer, Map<String, Object> context, ModelScreenWidget.SubContent content) throws IOException;
-    public void renderSubContentEnd(Appendable writer, Map<String, Object> context, ModelScreenWidget.SubContent content) throws IOException;
-
-    public void renderHorizontalSeparator(Appendable writer, Map<String, Object> context, ModelScreenWidget.HorizontalSeparator separator) throws IOException;
-    public void renderLabel(Appendable writer, Map<String, Object> context, ModelScreenWidget.Label label) throws IOException;
-    public void renderLink(Appendable writer, Map<String, Object> context, ModelScreenWidget.ScreenLink link) throws IOException;
-    public void renderImage(Appendable writer, Map<String, Object> context, ModelScreenWidget.ScreenImage image) throws IOException;
-
-    public void renderContentFrame(Appendable writer, Map<String, Object> context, ModelScreenWidget.Content content) throws IOException;
-    public void renderScreenletBegin(Appendable writer, Map<String, Object> context, boolean collapsed, ModelScreenWidget.Screenlet screenlet) throws IOException;
-    public void renderScreenletSubWidget(Appendable writer, Map<String, Object> context, ModelScreenWidget subWidget, ModelScreenWidget.Screenlet screenlet) throws GeneralException, IOException;
-    public void renderScreenletEnd(Appendable writer, Map<String, Object> context, ModelScreenWidget.Screenlet screenlet) throws IOException;
-
-    public void renderPortalPageBegin(Appendable writer, Map<String, Object> context, ModelScreenWidget.PortalPage portalPage) throws GeneralException, IOException;
-    public void renderPortalPageEnd(Appendable writer, Map<String, Object> context, ModelScreenWidget.PortalPage portalPage) throws GeneralException, IOException;
-    public void renderPortalPageColumnBegin(Appendable writer, Map<String, Object> context, ModelScreenWidget.PortalPage portalPage, GenericValue portalPageColumn) throws GeneralException, IOException;
-    public void renderPortalPageColumnEnd(Appendable writer, Map<String, Object> context, ModelScreenWidget.PortalPage portalPage, GenericValue portalPageColumn) throws GeneralException, IOException;
-    public void renderPortalPagePortletBegin(Appendable writer, Map<String, Object> context, ModelScreenWidget.PortalPage portalPage, GenericValue portalPortlet) throws GeneralException, IOException;
-    public void renderPortalPagePortletBody(Appendable writer, Map<String, Object> context, ModelScreenWidget.PortalPage portalPage, GenericValue portalPortlet) throws GeneralException, IOException;
-    public void renderPortalPagePortletEnd(Appendable writer, Map<String, Object> context, ModelScreenWidget.PortalPage portalPage, GenericValue portalPortlet) throws GeneralException, IOException;
-}
-
-
-
+/*******************************************************************************

+ * 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.renderer;

+

+import java.io.IOException;

+import java.util.Map;

+

+import org.ofbiz.base.util.GeneralException;

+import org.ofbiz.entity.GenericValue;

+import org.ofbiz.widget.model.ModelScreenWidget;

+

+/**

+ * Widget Library - Screen String Renderer interface.

+ */

+public interface ScreenStringRenderer {

+    public String getRendererName();

+    public void renderScreenBegin(Appendable writer, Map<String, Object> context) throws IOException;

+    public void renderScreenEnd(Appendable writer, Map<String, Object> context) throws IOException;

+    public void renderSectionBegin(Appendable writer, Map<String, Object> context, ModelScreenWidget.Section section) throws IOException;

+    public void renderSectionEnd(Appendable writer, Map<String, Object> context, ModelScreenWidget.Section section) throws IOException;

+    public void renderColumnContainer(Appendable writer, Map<String, Object> context, ModelScreenWidget.ColumnContainer columnContainer) throws IOException;

+    public void renderContainerBegin(Appendable writer, Map<String, Object> context, ModelScreenWidget.Container container) throws IOException;

+    public void renderContainerEnd(Appendable writer, Map<String, Object> context, ModelScreenWidget.Container container) throws IOException;

+    public void renderContentBegin(Appendable writer, Map<String, Object> context, ModelScreenWidget.Content content) throws IOException;

+    public void renderContentBody(Appendable writer, Map<String, Object> context, ModelScreenWidget.Content content) throws IOException;

+    public void renderContentEnd(Appendable writer, Map<String, Object> context, ModelScreenWidget.Content content) throws IOException;

+    public void renderSubContentBegin(Appendable writer, Map<String, Object> context, ModelScreenWidget.SubContent content) throws IOException;

+    public void renderSubContentBody(Appendable writer, Map<String, Object> context, ModelScreenWidget.SubContent content) throws IOException;

+    public void renderSubContentEnd(Appendable writer, Map<String, Object> context, ModelScreenWidget.SubContent content) throws IOException;

+

+    public void renderHorizontalSeparator(Appendable writer, Map<String, Object> context, ModelScreenWidget.HorizontalSeparator separator) throws IOException;

+    public void renderLabel(Appendable writer, Map<String, Object> context, ModelScreenWidget.Label label) throws IOException;

+    public void renderLink(Appendable writer, Map<String, Object> context, ModelScreenWidget.ScreenLink link) throws IOException;

+    public void renderImage(Appendable writer, Map<String, Object> context, ModelScreenWidget.ScreenImage image) throws IOException;

+

+    public void renderContentFrame(Appendable writer, Map<String, Object> context, ModelScreenWidget.Content content) throws IOException;

+    public void renderScreenletBegin(Appendable writer, Map<String, Object> context, boolean collapsed, ModelScreenWidget.Screenlet screenlet) throws IOException;

+    public void renderScreenletSubWidget(Appendable writer, Map<String, Object> context, ModelScreenWidget subWidget, ModelScreenWidget.Screenlet screenlet) throws GeneralException, IOException;

+    public void renderScreenletEnd(Appendable writer, Map<String, Object> context, ModelScreenWidget.Screenlet screenlet) throws IOException;

+

+    public void renderPortalPageBegin(Appendable writer, Map<String, Object> context, ModelScreenWidget.PortalPage portalPage) throws GeneralException, IOException;

+    public void renderPortalPageEnd(Appendable writer, Map<String, Object> context, ModelScreenWidget.PortalPage portalPage) throws GeneralException, IOException;

+    public void renderPortalPageColumnBegin(Appendable writer, Map<String, Object> context, ModelScreenWidget.PortalPage portalPage, GenericValue portalPageColumn) throws GeneralException, IOException;

+    public void renderPortalPageColumnEnd(Appendable writer, Map<String, Object> context, ModelScreenWidget.PortalPage portalPage, GenericValue portalPageColumn) throws GeneralException, IOException;

+    public void renderPortalPagePortletBegin(Appendable writer, Map<String, Object> context, ModelScreenWidget.PortalPage portalPage, GenericValue portalPortlet) throws GeneralException, IOException;

+    public void renderPortalPagePortletBody(Appendable writer, Map<String, Object> context, ModelScreenWidget.PortalPage portalPage, GenericValue portalPortlet) throws GeneralException, IOException;

+    public void renderPortalPagePortletEnd(Appendable writer, Map<String, Object> context, ModelScreenWidget.PortalPage portalPage, GenericValue portalPortlet) throws GeneralException, IOException;

+}

+

+

+

diff --git a/framework/widget/src/org/ofbiz/widget/tree/TreeStringRenderer.java b/framework/widget/src/org/ofbiz/widget/renderer/TreeStringRenderer.java
similarity index 95%
rename from framework/widget/src/org/ofbiz/widget/tree/TreeStringRenderer.java
rename to framework/widget/src/org/ofbiz/widget/renderer/TreeStringRenderer.java
index 63184b7..d56d022 100644
--- a/framework/widget/src/org/ofbiz/widget/tree/TreeStringRenderer.java
+++ b/framework/widget/src/org/ofbiz/widget/renderer/TreeStringRenderer.java
@@ -1,38 +1,38 @@
-/*******************************************************************************
- * 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.tree;
-
-import java.io.IOException;
-import java.util.Map;
-
-import org.ofbiz.widget.screen.ScreenStringRenderer;
-
-/**
- * Widget Library - Tree String Renderer interface
- */
-public interface TreeStringRenderer {
-
-    public void renderNodeBegin(Appendable writer, Map<String, Object> context, ModelTree.ModelNode node, int depth) throws IOException;
-    public void renderNodeEnd(Appendable writer, Map<String, Object> context, ModelTree.ModelNode node) throws IOException;
-    public void renderLabel(Appendable writer, Map<String, Object> context, ModelTree.ModelNode.Label label) throws IOException;
-    public void renderLink(Appendable writer, Map<String, Object> context, ModelTree.ModelNode.Link link) throws IOException;
-    public void renderImage(Appendable writer, Map<String, Object> context, ModelTree.ModelNode.Image image) throws IOException;
-    public void renderLastElement(Appendable writer, Map<String, Object> context, ModelTree.ModelNode node) throws IOException;
-    public ScreenStringRenderer getScreenStringRenderer(Map<String, Object> context);
-}
+/*******************************************************************************

+ * 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.renderer;

+

+import java.io.IOException;

+import java.util.Map;

+

+import org.ofbiz.widget.model.ModelTree;

+

+/**

+ * Widget Library - Tree String Renderer interface

+ */

+public interface TreeStringRenderer {

+

+    public void renderNodeBegin(Appendable writer, Map<String, Object> context, ModelTree.ModelNode node, int depth) throws IOException;

+    public void renderNodeEnd(Appendable writer, Map<String, Object> context, ModelTree.ModelNode node) throws IOException;

+    public void renderLabel(Appendable writer, Map<String, Object> context, ModelTree.ModelNode.Label label) throws IOException;

+    public void renderLink(Appendable writer, Map<String, Object> context, ModelTree.ModelNode.Link link) throws IOException;

+    public void renderImage(Appendable writer, Map<String, Object> context, ModelTree.ModelNode.Image image) throws IOException;

+    public void renderLastElement(Appendable writer, Map<String, Object> context, ModelTree.ModelNode node) throws IOException;

+    public ScreenStringRenderer getScreenStringRenderer(Map<String, Object> context);

+}

diff --git a/framework/widget/src/org/ofbiz/widget/form/UtilHelpText.java b/framework/widget/src/org/ofbiz/widget/renderer/UtilHelpText.java
similarity index 98%
rename from framework/widget/src/org/ofbiz/widget/form/UtilHelpText.java
rename to framework/widget/src/org/ofbiz/widget/renderer/UtilHelpText.java
index a605bb1..5f88381 100644
--- a/framework/widget/src/org/ofbiz/widget/form/UtilHelpText.java
+++ b/framework/widget/src/org/ofbiz/widget/renderer/UtilHelpText.java
@@ -1,87 +1,87 @@
-/*******************************************************************************
- * 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.Locale;
-
-import org.ofbiz.base.util.Debug;
-import org.ofbiz.base.util.UtilProperties;
-import org.ofbiz.base.util.UtilValidate;
-import org.ofbiz.entity.Delegator;
-import org.ofbiz.entity.GenericEntityException;
-import org.ofbiz.entity.model.ModelEntity;
-import org.ofbiz.entity.model.ModelReader;
-
-/**
- * Util for working with Help Text
- */
-public class UtilHelpText {
-
-    public static final String module = UtilHelpText.class.getName();
-
-    /**
-     * Find the help text associated with an entity field.
-     * 
-     * @param entityName the entity name
-     * @param fieldName the field name
-     * @param delegator the delegator
-     * @param locale the locale
-     * @return the help text, or the resource propertyName if no help text exists
-     */
-    public static String getEntityFieldDescription(final String entityName, final String fieldName, final Delegator delegator, final Locale locale) {
-
-        if (UtilValidate.isEmpty(entityName)) {
-            // Debug.logWarning("entityName [" + entityName + "] is empty", module);
-            return "";
-        }
-        if (UtilValidate.isEmpty(fieldName)) {
-            Debug.logWarning("fieldName [" + fieldName + "] is empty", module);
-            return "";
-        }
-        ModelReader reader = delegator.getModelReader();
-        ModelEntity entity = null;
-        try {
-            if (!reader.getEntityNames().contains(entityName)) {
-                Debug.logWarning("couldn't find entityName [" + entityName + "]", module);
-                return "";
-            }
-            entity = reader.getModelEntity(entityName);
-        } catch (GenericEntityException e) {
-            Debug.logError(e, "Error getting help text for entity=" + entityName + " field " + fieldName, module);
-            return "";
-        }
-        String entityResourceName = entity.getDefaultResourceName();
-        String messageId = "FieldDescription." + entityName + "." + fieldName;
-        String fieldDescription = UtilProperties.getMessage(entityResourceName, messageId, locale);
-        if (fieldDescription.equals(messageId)) {
-            messageId = "FieldDescription." + fieldName;
-            if (Debug.verboseOn()) {
-                Debug.logVerbose("No help text found in [" + entityResourceName + "] with key [" + messageId + "], Trying with: " + messageId, module);
-            }
-            fieldDescription = UtilProperties.getMessage(entityResourceName, messageId, locale);
-            if (fieldDescription.equals(messageId)) {
-                if (Debug.verboseOn()) {
-                    Debug.logVerbose("No help text found in [" + entityResourceName + "] with key [" + messageId + "]", module);
-                }
-                return "";
-            }
-        }
-        return fieldDescription;
-    }
-}
+/*******************************************************************************

+ * 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.renderer;

+

+import java.util.Locale;

+

+import org.ofbiz.base.util.Debug;

+import org.ofbiz.base.util.UtilProperties;

+import org.ofbiz.base.util.UtilValidate;

+import org.ofbiz.entity.Delegator;

+import org.ofbiz.entity.GenericEntityException;

+import org.ofbiz.entity.model.ModelEntity;

+import org.ofbiz.entity.model.ModelReader;

+

+/**

+ * Util for working with Help Text

+ */

+public class UtilHelpText {

+

+    public static final String module = UtilHelpText.class.getName();

+

+    /**

+     * Find the help text associated with an entity field.

+     * 

+     * @param entityName the entity name

+     * @param fieldName the field name

+     * @param delegator the delegator

+     * @param locale the locale

+     * @return the help text, or the resource propertyName if no help text exists

+     */

+    public static String getEntityFieldDescription(final String entityName, final String fieldName, final Delegator delegator, final Locale locale) {

+

+        if (UtilValidate.isEmpty(entityName)) {

+            // Debug.logWarning("entityName [" + entityName + "] is empty", module);

+            return "";

+        }

+        if (UtilValidate.isEmpty(fieldName)) {

+            Debug.logWarning("fieldName [" + fieldName + "] is empty", module);

+            return "";

+        }

+        ModelReader reader = delegator.getModelReader();

+        ModelEntity entity = null;

+        try {

+            if (!reader.getEntityNames().contains(entityName)) {

+                Debug.logWarning("couldn't find entityName [" + entityName + "]", module);

+                return "";

+            }

+            entity = reader.getModelEntity(entityName);

+        } catch (GenericEntityException e) {

+            Debug.logError(e, "Error getting help text for entity=" + entityName + " field " + fieldName, module);

+            return "";

+        }

+        String entityResourceName = entity.getDefaultResourceName();

+        String messageId = "FieldDescription." + entityName + "." + fieldName;

+        String fieldDescription = UtilProperties.getMessage(entityResourceName, messageId, locale);

+        if (fieldDescription.equals(messageId)) {

+            messageId = "FieldDescription." + fieldName;

+            if (Debug.verboseOn()) {

+                Debug.logVerbose("No help text found in [" + entityResourceName + "] with key [" + messageId + "], Trying with: " + messageId, module);

+            }

+            fieldDescription = UtilProperties.getMessage(entityResourceName, messageId, locale);

+            if (fieldDescription.equals(messageId)) {

+                if (Debug.verboseOn()) {

+                    Debug.logVerbose("No help text found in [" + entityResourceName + "] with key [" + messageId + "]", module);

+                }

+                return "";

+            }

+        }

+        return fieldDescription;

+    }

+}

diff --git a/framework/widget/src/org/ofbiz/widget/fo/FoFormRenderer.java b/framework/widget/src/org/ofbiz/widget/renderer/fo/FoFormRenderer.java
similarity index 92%
rename from framework/widget/src/org/ofbiz/widget/fo/FoFormRenderer.java
rename to framework/widget/src/org/ofbiz/widget/renderer/fo/FoFormRenderer.java
index 01c78cd..29bc658 100644
--- a/framework/widget/src/org/ofbiz/widget/fo/FoFormRenderer.java
+++ b/framework/widget/src/org/ofbiz/widget/renderer/fo/FoFormRenderer.java
@@ -1,427 +1,427 @@
-/*******************************************************************************
- * 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.fo;
-
-import java.io.IOException;
-import java.util.List;
-import java.util.Map;
-
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.ofbiz.base.util.UtilFormatOut;
-import org.ofbiz.base.util.UtilValidate;
-import org.ofbiz.widget.ModelWidget;
-import org.ofbiz.widget.WidgetWorker;
-import org.ofbiz.widget.form.FieldInfo;
-import org.ofbiz.widget.form.FormStringRenderer;
-import org.ofbiz.widget.form.ModelForm;
-import org.ofbiz.widget.form.ModelFormField;
-import org.ofbiz.widget.form.ModelFormField.CheckField;
-import org.ofbiz.widget.form.ModelFormField.ContainerField;
-import org.ofbiz.widget.form.ModelFormField.DateFindField;
-import org.ofbiz.widget.form.ModelFormField.DateTimeField;
-import org.ofbiz.widget.form.ModelFormField.DisplayField;
-import org.ofbiz.widget.form.ModelFormField.DropDownField;
-import org.ofbiz.widget.form.ModelFormField.FieldInfoWithOptions;
-import org.ofbiz.widget.form.ModelFormField.FileField;
-import org.ofbiz.widget.form.ModelFormField.HiddenField;
-import org.ofbiz.widget.form.ModelFormField.HyperlinkField;
-import org.ofbiz.widget.form.ModelFormField.IgnoredField;
-import org.ofbiz.widget.form.ModelFormField.ImageField;
-import org.ofbiz.widget.form.ModelFormField.LookupField;
-import org.ofbiz.widget.form.ModelFormField.PasswordField;
-import org.ofbiz.widget.form.ModelFormField.RadioField;
-import org.ofbiz.widget.form.ModelFormField.RangeFindField;
-import org.ofbiz.widget.form.ModelFormField.ResetField;
-import org.ofbiz.widget.form.ModelFormField.SubmitField;
-import org.ofbiz.widget.form.ModelFormField.TextField;
-import org.ofbiz.widget.form.ModelFormField.TextFindField;
-import org.ofbiz.widget.form.ModelFormField.TextareaField;
-import org.ofbiz.widget.html.HtmlWidgetRenderer;
-
-
-/**
- * Widget Library - FO Form Renderer implementation
- *
- */
-public class FoFormRenderer extends HtmlWidgetRenderer implements FormStringRenderer {
-
-    public static final String module = FoFormRenderer.class.getName();
-
-    HttpServletRequest request;
-    HttpServletResponse response;
-
-    public FoFormRenderer() {}
-
-    public FoFormRenderer(HttpServletRequest request, HttpServletResponse response) throws IOException {
-        this.request = request;
-        this.response = response;
-    }
-
-    private void makeBlockString(Appendable writer, String widgetStyle, String text) throws IOException {
-        writer.append("<fo:block");
-        if (UtilValidate.isNotEmpty(widgetStyle)) {
-            writer.append(" ");
-            writer.append(FoScreenRenderer.getFoStyle(widgetStyle));
-        }
-        writer.append(">");
-        writer.append(UtilFormatOut.encodeXmlValue(text));
-        writer.append("</fo:block>");
-    }
-
-    public void renderDisplayField(Appendable writer, Map<String, Object> context, DisplayField displayField) throws IOException {
-        ModelFormField modelFormField = displayField.getModelFormField();
-        this.makeBlockString(writer, modelFormField.getWidgetStyle(), displayField.getDescription(context));
-        appendWhitespace(writer);
-    }
-
-    public void renderHyperlinkField(Appendable writer, Map<String, Object> context, HyperlinkField hyperlinkField) throws IOException {
-        ModelFormField modelFormField = hyperlinkField.getModelFormField();
-        this.makeBlockString(writer, modelFormField.getWidgetStyle(), hyperlinkField.getDescription(context));
-        appendWhitespace(writer);
-    }
-
-    public void renderTextField(Appendable writer, Map<String, Object> context, TextField textField) throws IOException {
-        ModelFormField modelFormField = textField.getModelFormField();
-        this.makeBlockString(writer, modelFormField.getWidgetStyle(), modelFormField.getEntry(context, textField.getDefaultValue(context)));
-        appendWhitespace(writer);
-    }
-
-    public void renderTextareaField(Appendable writer, Map<String, Object> context, TextareaField textareaField) throws IOException {
-        ModelFormField modelFormField = textareaField.getModelFormField();
-        this.makeBlockString(writer, modelFormField.getWidgetStyle(), modelFormField.getEntry(context, textareaField.getDefaultValue(context)));
-        appendWhitespace(writer);
-    }
-
-    public void renderDateTimeField(Appendable writer, Map<String, Object> context, DateTimeField dateTimeField) throws IOException {
-        ModelFormField modelFormField = dateTimeField.getModelFormField();
-        this.makeBlockString(writer, modelFormField.getWidgetStyle(), modelFormField.getEntry(context, dateTimeField.getDefaultValue(context)));
-        appendWhitespace(writer);
-    }
-
-    public void renderDropDownField(Appendable writer, Map<String, Object> context, DropDownField dropDownField) throws IOException {
-        ModelFormField modelFormField = dropDownField.getModelFormField();
-        String currentValue = modelFormField.getEntry(context);
-        List<ModelFormField.OptionValue> allOptionValues = dropDownField.getAllOptionValues(context, WidgetWorker.getDelegator(context));
-        // if the current value should go first, display it
-        if (UtilValidate.isNotEmpty(currentValue) && "first-in-list".equals(dropDownField.getCurrent())) {
-            String explicitDescription = dropDownField.getCurrentDescription(context);
-            if (UtilValidate.isNotEmpty(explicitDescription)) {
-                this.makeBlockString(writer, modelFormField.getWidgetStyle(), explicitDescription);
-            } else {
-                this.makeBlockString(writer, modelFormField.getWidgetStyle(), FieldInfoWithOptions.getDescriptionForOptionKey(currentValue, allOptionValues));
-            }
-        } else {
-            boolean optionSelected = false;
-            for (ModelFormField.OptionValue optionValue : allOptionValues) {
-                String noCurrentSelectedKey = dropDownField.getNoCurrentSelectedKey(context);
-                if ((UtilValidate.isNotEmpty(currentValue) && currentValue.equals(optionValue.getKey()) && "selected".equals(dropDownField.getCurrent())) ||
-                        (UtilValidate.isEmpty(currentValue) && noCurrentSelectedKey != null && noCurrentSelectedKey.equals(optionValue.getKey()))) {
-                    this.makeBlockString(writer, modelFormField.getWidgetStyle(), optionValue.getDescription());
-                    optionSelected = true;
-                    break;
-                }
-            }
-            if (!optionSelected) {
-                this.makeBlockString(writer, null, "");
-            }
-        }
-        appendWhitespace(writer);
-    }
-
-    public void renderCheckField(Appendable writer, Map<String, Object> context, CheckField checkField) throws IOException {
-        this.makeBlockString(writer, null, "");
-    }
-
-    public void renderRadioField(Appendable writer, Map<String, Object> context, RadioField radioField) throws IOException {
-        this.makeBlockString(writer, null, "");
-    }
-
-    public void renderSubmitField(Appendable writer, Map<String, Object> context, SubmitField submitField) throws IOException {
-        this.makeBlockString(writer, null, "");
-    }
-
-    public void renderResetField(Appendable writer, Map<String, Object> context, ResetField resetField) throws IOException {
-        this.makeBlockString(writer, null, "");
-    }
-
-    public void renderHiddenField(Appendable writer, Map<String, Object> context, HiddenField hiddenField) throws IOException {
-    }
-
-    public void renderHiddenField(Appendable writer, Map<String, Object> context, ModelFormField modelFormField, String value) throws IOException {
-    }
-
-    public void renderIgnoredField(Appendable writer, Map<String, Object> context, IgnoredField ignoredField) throws IOException {
-    }
-
-    public void renderFieldTitle(Appendable writer, Map<String, Object> context, ModelFormField modelFormField) throws IOException {
-        String tempTitleText = modelFormField.getTitle(context);
-        writer.append(tempTitleText);
-    }
-
-    public void renderSingleFormFieldTitle(Appendable writer, Map<String, Object> context, ModelFormField modelFormField) throws IOException {
-        renderFieldTitle(writer, context, modelFormField);
-    }
-
-    public void renderFormOpen(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {
-        this.widgetCommentsEnabled = ModelWidget.widgetBoundaryCommentsEnabled(context);
-        renderBeginningBoundaryComment(writer, "Form Widget", modelForm);
-    }
-
-    public void renderFormClose(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {
-        renderEndingBoundaryComment(writer, "Form Widget", modelForm);
-    }
-
-    public void renderMultiFormClose(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {
-        renderEndingBoundaryComment(writer, "Form Widget", modelForm);
-    }
-
-    public void renderFormatListWrapperOpen(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {
-        writer.append("<fo:table border=\"solid black\">");
-        List<ModelFormField> childFieldList = modelForm.getFieldList();
-        for (ModelFormField childField : childFieldList) {
-            int childFieldType = childField.getFieldInfo().getFieldType();
-            if (childFieldType == FieldInfo.HIDDEN || childFieldType == FieldInfo.IGNORED) {
-                continue;
-            }
-            writer.append("<fo:table-column");
-            String areaStyle = childField.getTitleAreaStyle();
-            if (UtilValidate.isNotEmpty(areaStyle)) {
-                writer.append(" ");
-                writer.append(FoScreenRenderer.getFoStyle(areaStyle));
-            }
-            writer.append("/>");
-            appendWhitespace(writer);
-        }
-        appendWhitespace(writer);
-    }
-
-    public void renderFormatListWrapperClose(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {
-        writer.append("</fo:table-body>");
-        writer.append("</fo:table>");
-        appendWhitespace(writer);
-    }
-
-    public void renderFormatHeaderRowOpen(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {
-        writer.append("<fo:table-header>");
-        writer.append("<fo:table-row>");
-        appendWhitespace(writer);
-    }
-
-    public void renderFormatHeaderRowClose(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {
-        writer.append("</fo:table-row>");
-        writer.append("</fo:table-header>");
-        writer.append("<fo:table-body>");
-        // FIXME: this is an hack to avoid FOP rendering errors for empty lists (fo:table-body cannot be null)
-        writer.append("<fo:table-row><fo:table-cell><fo:block/></fo:table-cell></fo:table-row>");
-        appendWhitespace(writer);
-    }
-
-    public void renderFormatHeaderRowCellOpen(Appendable writer, Map<String, Object> context, ModelForm modelForm, ModelFormField modelFormField, int positionSpan) throws IOException {
-        writer.append("<fo:table-cell ");
-        if (positionSpan > 1) {
-            writer.append("number-columns-spanned=\"");
-            writer.append(Integer.toString(positionSpan));
-            writer.append("\" ");
-        }
-        writer.append("font-weight=\"bold\" text-align=\"center\" border=\"solid black\" padding=\"2pt\"");
-        writer.append(">");
-        writer.append("<fo:block>");
-        appendWhitespace(writer);
-    }
-
-    public void renderFormatHeaderRowCellClose(Appendable writer, Map<String, Object> context, ModelForm modelForm, ModelFormField modelFormField) throws IOException {
-        writer.append("</fo:block>");
-        writer.append("</fo:table-cell>");
-        appendWhitespace(writer);
-    }
-
-    public void renderFormatHeaderRowFormCellOpen(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {
-        writer.append("<fo:table-cell>");
-        appendWhitespace(writer);
-    }
-
-    public void renderFormatHeaderRowFormCellClose(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {
-        writer.append("</fo:table-cell>");
-        appendWhitespace(writer);
-    }
-
-    public void renderFormatHeaderRowFormCellTitleSeparator(Appendable writer, Map<String, Object> context, ModelForm modelForm, ModelFormField modelFormField, boolean isLast) throws IOException {
-    }
-
-    public void renderFormatItemRowOpen(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {
-        writer.append("<fo:table-row>");
-        appendWhitespace(writer);
-    }
-
-    public void renderFormatItemRowClose(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {
-        writer.append("</fo:table-row>");
-        appendWhitespace(writer);
-    }
-
-    public void renderFormatItemRowCellOpen(Appendable writer, Map<String, Object> context, ModelForm modelForm, ModelFormField modelFormField, int positionSpan) throws IOException {
-        writer.append("<fo:table-cell ");
-        if (positionSpan > 1) {
-            writer.append("number-columns-spanned=\"");
-            writer.append(Integer.toString(positionSpan));
-            writer.append("\" ");
-        }
-        String areaStyle = modelFormField.getWidgetAreaStyle();
-        if (UtilValidate.isEmpty(areaStyle)) {
-            areaStyle = "tabletext";
-        }
-        writer.append(FoScreenRenderer.getFoStyle(areaStyle));
-        writer.append(">");
-        appendWhitespace(writer);
-    }
-
-    public void renderFormatItemRowCellClose(Appendable writer, Map<String, Object> context, ModelForm modelForm, ModelFormField modelFormField) throws IOException {
-        writer.append("</fo:table-cell>");
-        appendWhitespace(writer);
-    }
-
-    public void renderFormatItemRowFormCellOpen(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {
-        writer.append("<fo:table-cell>");
-        appendWhitespace(writer);
-    }
-
-    public void renderFormatItemRowFormCellClose(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {
-        writer.append("</fo:table-cell>");
-        appendWhitespace(writer);
-    }
-
-    // TODO: multi columns (position attribute) in single forms are still not implemented
-    public void renderFormatSingleWrapperOpen(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {
-        writer.append("<fo:table>");
-        appendWhitespace(writer);
-        writer.append("<fo:table-column column-width=\"2in\"/>");
-        appendWhitespace(writer);
-        writer.append("<fo:table-column/>");
-        appendWhitespace(writer);
-        writer.append("<fo:table-body>");
-        appendWhitespace(writer);
-    }
-    public void renderFormatSingleWrapperClose(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {
-        writer.append("</fo:table-body>");
-        writer.append("</fo:table>");
-        appendWhitespace(writer);
-    }
-
-    public void renderFormatFieldRowOpen(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {
-        writer.append("<fo:table-row>");
-        appendWhitespace(writer);
-    }
-
-    public void renderFormatFieldRowClose(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {
-        writer.append("</fo:table-row>");
-        appendWhitespace(writer);
-    }
-
-
-    public void renderFormatFieldRowTitleCellOpen(Appendable writer, Map<String, Object> context, ModelFormField modelFormField) throws IOException {
-        writer.append("<fo:table-cell font-weight=\"bold\" text-align=\"right\" padding=\"3pt\">");
-        writer.append("<fo:block>");
-        appendWhitespace(writer);
-    }
-
-    public void renderFormatFieldRowTitleCellClose(Appendable writer, Map<String, Object> context, ModelFormField modelFormField) throws IOException {
-        writer.append("</fo:block>");
-        writer.append("</fo:table-cell>");
-        appendWhitespace(writer);
-    }
-
-    public void renderFormatFieldRowSpacerCell(Appendable writer, Map<String, Object> context, ModelFormField modelFormField) throws IOException {
-    }
-
-    public void renderFormatFieldRowWidgetCellOpen(Appendable writer, Map<String, Object> context, ModelFormField modelFormField, int positions, int positionSpan, Integer nextPositionInRow) throws IOException {
-        writer.append("<fo:table-cell text-align=\"left\" padding=\"2pt\" padding-left=\"5pt\">");
-        appendWhitespace(writer);
-    }
-
-    public void renderFormatFieldRowWidgetCellClose(Appendable writer, Map<String, Object> context, ModelFormField modelFormField, int positions, int positionSpan, Integer nextPositionInRow) throws IOException {
-        writer.append("</fo:table-cell>");
-        appendWhitespace(writer);
-    }
-
-    public void renderFormatEmptySpace(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {
-        // TODO
-    }
-
-    public void renderTextFindField(Appendable writer, Map<String, Object> context, TextFindField textFindField) throws IOException {
-        ModelFormField modelFormField = textFindField.getModelFormField();
-        this.makeBlockString(writer, modelFormField.getWidgetStyle(), modelFormField.getEntry(context, textFindField.getDefaultValue(context)));
-        appendWhitespace(writer);
-    }
-
-    public void renderRangeFindField(Appendable writer, Map<String, Object> context, RangeFindField rangeFindField) throws IOException {
-        ModelFormField modelFormField = rangeFindField.getModelFormField();
-        this.makeBlockString(writer, modelFormField.getWidgetStyle(), modelFormField.getEntry(context, rangeFindField.getDefaultValue(context)));
-        appendWhitespace(writer);
-    }
-
-    public void renderDateFindField(Appendable writer, Map<String, Object> context, DateFindField dateFindField) throws IOException {
-        ModelFormField modelFormField = dateFindField.getModelFormField();
-        this.makeBlockString(writer, modelFormField.getWidgetStyle(), modelFormField.getEntry(context, dateFindField.getDefaultValue(context)));
-        appendWhitespace(writer);
-    }
-
-    public void renderLookupField(Appendable writer, Map<String, Object> context, LookupField lookupField) throws IOException {
-        ModelFormField modelFormField = lookupField.getModelFormField();
-        this.makeBlockString(writer, modelFormField.getWidgetStyle(), modelFormField.getEntry(context, lookupField.getDefaultValue(context)));
-        appendWhitespace(writer);
-    }
-
-    public void renderNextPrev(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {
-    }
-
-    public void renderFileField(Appendable writer, Map<String, Object> context, FileField textField) throws IOException {
-        ModelFormField modelFormField = textField.getModelFormField();
-        this.makeBlockString(writer, modelFormField.getWidgetStyle(), modelFormField.getEntry(context, textField.getDefaultValue(context)));
-        appendWhitespace(writer);
-    }
-
-    public void renderPasswordField(Appendable writer, Map<String, Object> context, PasswordField passwordField) throws IOException {
-        this.makeBlockString(writer, null, "");
-    }
-
-    public void renderImageField(Appendable writer, Map<String, Object> context, ImageField imageField) throws IOException {
-        // TODO
-        this.makeBlockString(writer, null, "");
-    }
-
-    public void renderFieldGroupOpen(Appendable writer, Map<String, Object> context, ModelForm.FieldGroup fieldGroup) throws IOException {
-        // TODO
-    }
-
-    public void renderFieldGroupClose(Appendable writer, Map<String, Object> context, ModelForm.FieldGroup fieldGroup) throws IOException {
-        // TODO
-    }
-
-    public void renderBanner(Appendable writer, Map<String, Object> context, ModelForm.Banner banner) throws IOException {
-        // TODO
-        this.makeBlockString(writer, null, "");
-    }
-
-    public void renderHyperlinkTitle(Appendable writer, Map<String, Object> context, ModelFormField modelFormField, String titleText) throws IOException {
-    }
-
-    public void renderContainerFindField(Appendable writer, Map<String, Object> context, ContainerField containerField) throws IOException {
-    }
-}
+/*******************************************************************************

+ * 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.renderer.fo;

+

+import java.io.IOException;

+import java.util.List;

+import java.util.Map;

+

+import javax.servlet.http.HttpServletRequest;

+import javax.servlet.http.HttpServletResponse;

+

+import org.ofbiz.base.util.UtilFormatOut;

+import org.ofbiz.base.util.UtilValidate;

+import org.ofbiz.widget.WidgetWorker;

+import org.ofbiz.widget.model.FieldInfo;

+import org.ofbiz.widget.model.ModelForm;

+import org.ofbiz.widget.model.ModelFormField;

+import org.ofbiz.widget.model.ModelFormField.CheckField;

+import org.ofbiz.widget.model.ModelFormField.ContainerField;

+import org.ofbiz.widget.model.ModelFormField.DateFindField;

+import org.ofbiz.widget.model.ModelFormField.DateTimeField;

+import org.ofbiz.widget.model.ModelFormField.DisplayField;

+import org.ofbiz.widget.model.ModelFormField.DropDownField;

+import org.ofbiz.widget.model.ModelFormField.FieldInfoWithOptions;

+import org.ofbiz.widget.model.ModelFormField.FileField;

+import org.ofbiz.widget.model.ModelFormField.HiddenField;

+import org.ofbiz.widget.model.ModelFormField.HyperlinkField;

+import org.ofbiz.widget.model.ModelFormField.IgnoredField;

+import org.ofbiz.widget.model.ModelFormField.ImageField;

+import org.ofbiz.widget.model.ModelFormField.LookupField;

+import org.ofbiz.widget.model.ModelFormField.PasswordField;

+import org.ofbiz.widget.model.ModelFormField.RadioField;

+import org.ofbiz.widget.model.ModelFormField.RangeFindField;

+import org.ofbiz.widget.model.ModelFormField.ResetField;

+import org.ofbiz.widget.model.ModelFormField.SubmitField;

+import org.ofbiz.widget.model.ModelFormField.TextField;

+import org.ofbiz.widget.model.ModelFormField.TextFindField;

+import org.ofbiz.widget.model.ModelFormField.TextareaField;

+import org.ofbiz.widget.model.ModelWidget;

+import org.ofbiz.widget.renderer.FormStringRenderer;

+import org.ofbiz.widget.renderer.html.HtmlWidgetRenderer;

+

+

+/**

+ * Widget Library - FO Form Renderer implementation

+ *

+ */

+public class FoFormRenderer extends HtmlWidgetRenderer implements FormStringRenderer {

+

+    public static final String module = FoFormRenderer.class.getName();

+

+    HttpServletRequest request;

+    HttpServletResponse response;

+

+    public FoFormRenderer() {}

+

+    public FoFormRenderer(HttpServletRequest request, HttpServletResponse response) throws IOException {

+        this.request = request;

+        this.response = response;

+    }

+

+    private void makeBlockString(Appendable writer, String widgetStyle, String text) throws IOException {

+        writer.append("<fo:block");

+        if (UtilValidate.isNotEmpty(widgetStyle)) {

+            writer.append(" ");

+            writer.append(FoScreenRenderer.getFoStyle(widgetStyle));

+        }

+        writer.append(">");

+        writer.append(UtilFormatOut.encodeXmlValue(text));

+        writer.append("</fo:block>");

+    }

+

+    public void renderDisplayField(Appendable writer, Map<String, Object> context, DisplayField displayField) throws IOException {

+        ModelFormField modelFormField = displayField.getModelFormField();

+        this.makeBlockString(writer, modelFormField.getWidgetStyle(), displayField.getDescription(context));

+        appendWhitespace(writer);

+    }

+

+    public void renderHyperlinkField(Appendable writer, Map<String, Object> context, HyperlinkField hyperlinkField) throws IOException {

+        ModelFormField modelFormField = hyperlinkField.getModelFormField();

+        this.makeBlockString(writer, modelFormField.getWidgetStyle(), hyperlinkField.getDescription(context));

+        appendWhitespace(writer);

+    }

+

+    public void renderTextField(Appendable writer, Map<String, Object> context, TextField textField) throws IOException {

+        ModelFormField modelFormField = textField.getModelFormField();

+        this.makeBlockString(writer, modelFormField.getWidgetStyle(), modelFormField.getEntry(context, textField.getDefaultValue(context)));

+        appendWhitespace(writer);

+    }

+

+    public void renderTextareaField(Appendable writer, Map<String, Object> context, TextareaField textareaField) throws IOException {

+        ModelFormField modelFormField = textareaField.getModelFormField();

+        this.makeBlockString(writer, modelFormField.getWidgetStyle(), modelFormField.getEntry(context, textareaField.getDefaultValue(context)));

+        appendWhitespace(writer);

+    }

+

+    public void renderDateTimeField(Appendable writer, Map<String, Object> context, DateTimeField dateTimeField) throws IOException {

+        ModelFormField modelFormField = dateTimeField.getModelFormField();

+        this.makeBlockString(writer, modelFormField.getWidgetStyle(), modelFormField.getEntry(context, dateTimeField.getDefaultValue(context)));

+        appendWhitespace(writer);

+    }

+

+    public void renderDropDownField(Appendable writer, Map<String, Object> context, DropDownField dropDownField) throws IOException {

+        ModelFormField modelFormField = dropDownField.getModelFormField();

+        String currentValue = modelFormField.getEntry(context);

+        List<ModelFormField.OptionValue> allOptionValues = dropDownField.getAllOptionValues(context, WidgetWorker.getDelegator(context));

+        // if the current value should go first, display it

+        if (UtilValidate.isNotEmpty(currentValue) && "first-in-list".equals(dropDownField.getCurrent())) {

+            String explicitDescription = dropDownField.getCurrentDescription(context);

+            if (UtilValidate.isNotEmpty(explicitDescription)) {

+                this.makeBlockString(writer, modelFormField.getWidgetStyle(), explicitDescription);

+            } else {

+                this.makeBlockString(writer, modelFormField.getWidgetStyle(), FieldInfoWithOptions.getDescriptionForOptionKey(currentValue, allOptionValues));

+            }

+        } else {

+            boolean optionSelected = false;

+            for (ModelFormField.OptionValue optionValue : allOptionValues) {

+                String noCurrentSelectedKey = dropDownField.getNoCurrentSelectedKey(context);

+                if ((UtilValidate.isNotEmpty(currentValue) && currentValue.equals(optionValue.getKey()) && "selected".equals(dropDownField.getCurrent())) ||

+                        (UtilValidate.isEmpty(currentValue) && noCurrentSelectedKey != null && noCurrentSelectedKey.equals(optionValue.getKey()))) {

+                    this.makeBlockString(writer, modelFormField.getWidgetStyle(), optionValue.getDescription());

+                    optionSelected = true;

+                    break;

+                }

+            }

+            if (!optionSelected) {

+                this.makeBlockString(writer, null, "");

+            }

+        }

+        appendWhitespace(writer);

+    }

+

+    public void renderCheckField(Appendable writer, Map<String, Object> context, CheckField checkField) throws IOException {

+        this.makeBlockString(writer, null, "");

+    }

+

+    public void renderRadioField(Appendable writer, Map<String, Object> context, RadioField radioField) throws IOException {

+        this.makeBlockString(writer, null, "");

+    }

+

+    public void renderSubmitField(Appendable writer, Map<String, Object> context, SubmitField submitField) throws IOException {

+        this.makeBlockString(writer, null, "");

+    }

+

+    public void renderResetField(Appendable writer, Map<String, Object> context, ResetField resetField) throws IOException {

+        this.makeBlockString(writer, null, "");

+    }

+

+    public void renderHiddenField(Appendable writer, Map<String, Object> context, HiddenField hiddenField) throws IOException {

+    }

+

+    public void renderHiddenField(Appendable writer, Map<String, Object> context, ModelFormField modelFormField, String value) throws IOException {

+    }

+

+    public void renderIgnoredField(Appendable writer, Map<String, Object> context, IgnoredField ignoredField) throws IOException {

+    }

+

+    public void renderFieldTitle(Appendable writer, Map<String, Object> context, ModelFormField modelFormField) throws IOException {

+        String tempTitleText = modelFormField.getTitle(context);

+        writer.append(tempTitleText);

+    }

+

+    public void renderSingleFormFieldTitle(Appendable writer, Map<String, Object> context, ModelFormField modelFormField) throws IOException {

+        renderFieldTitle(writer, context, modelFormField);

+    }

+

+    public void renderFormOpen(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {

+        this.widgetCommentsEnabled = ModelWidget.widgetBoundaryCommentsEnabled(context);

+        renderBeginningBoundaryComment(writer, "Form Widget", modelForm);

+    }

+

+    public void renderFormClose(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {

+        renderEndingBoundaryComment(writer, "Form Widget", modelForm);

+    }

+

+    public void renderMultiFormClose(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {

+        renderEndingBoundaryComment(writer, "Form Widget", modelForm);

+    }

+

+    public void renderFormatListWrapperOpen(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {

+        writer.append("<fo:table border=\"solid black\">");

+        List<ModelFormField> childFieldList = modelForm.getFieldList();

+        for (ModelFormField childField : childFieldList) {

+            int childFieldType = childField.getFieldInfo().getFieldType();

+            if (childFieldType == FieldInfo.HIDDEN || childFieldType == FieldInfo.IGNORED) {

+                continue;

+            }

+            writer.append("<fo:table-column");

+            String areaStyle = childField.getTitleAreaStyle();

+            if (UtilValidate.isNotEmpty(areaStyle)) {

+                writer.append(" ");

+                writer.append(FoScreenRenderer.getFoStyle(areaStyle));

+            }

+            writer.append("/>");

+            appendWhitespace(writer);

+        }

+        appendWhitespace(writer);

+    }

+

+    public void renderFormatListWrapperClose(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {

+        writer.append("</fo:table-body>");

+        writer.append("</fo:table>");

+        appendWhitespace(writer);

+    }

+

+    public void renderFormatHeaderRowOpen(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {

+        writer.append("<fo:table-header>");

+        writer.append("<fo:table-row>");

+        appendWhitespace(writer);

+    }

+

+    public void renderFormatHeaderRowClose(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {

+        writer.append("</fo:table-row>");

+        writer.append("</fo:table-header>");

+        writer.append("<fo:table-body>");

+        // FIXME: this is an hack to avoid FOP rendering errors for empty lists (fo:table-body cannot be null)

+        writer.append("<fo:table-row><fo:table-cell><fo:block/></fo:table-cell></fo:table-row>");

+        appendWhitespace(writer);

+    }

+

+    public void renderFormatHeaderRowCellOpen(Appendable writer, Map<String, Object> context, ModelForm modelForm, ModelFormField modelFormField, int positionSpan) throws IOException {

+        writer.append("<fo:table-cell ");

+        if (positionSpan > 1) {

+            writer.append("number-columns-spanned=\"");

+            writer.append(Integer.toString(positionSpan));

+            writer.append("\" ");

+        }

+        writer.append("font-weight=\"bold\" text-align=\"center\" border=\"solid black\" padding=\"2pt\"");

+        writer.append(">");

+        writer.append("<fo:block>");

+        appendWhitespace(writer);

+    }

+

+    public void renderFormatHeaderRowCellClose(Appendable writer, Map<String, Object> context, ModelForm modelForm, ModelFormField modelFormField) throws IOException {

+        writer.append("</fo:block>");

+        writer.append("</fo:table-cell>");

+        appendWhitespace(writer);

+    }

+

+    public void renderFormatHeaderRowFormCellOpen(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {

+        writer.append("<fo:table-cell>");

+        appendWhitespace(writer);

+    }

+

+    public void renderFormatHeaderRowFormCellClose(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {

+        writer.append("</fo:table-cell>");

+        appendWhitespace(writer);

+    }

+

+    public void renderFormatHeaderRowFormCellTitleSeparator(Appendable writer, Map<String, Object> context, ModelForm modelForm, ModelFormField modelFormField, boolean isLast) throws IOException {

+    }

+

+    public void renderFormatItemRowOpen(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {

+        writer.append("<fo:table-row>");

+        appendWhitespace(writer);

+    }

+

+    public void renderFormatItemRowClose(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {

+        writer.append("</fo:table-row>");

+        appendWhitespace(writer);

+    }

+

+    public void renderFormatItemRowCellOpen(Appendable writer, Map<String, Object> context, ModelForm modelForm, ModelFormField modelFormField, int positionSpan) throws IOException {

+        writer.append("<fo:table-cell ");

+        if (positionSpan > 1) {

+            writer.append("number-columns-spanned=\"");

+            writer.append(Integer.toString(positionSpan));

+            writer.append("\" ");

+        }

+        String areaStyle = modelFormField.getWidgetAreaStyle();

+        if (UtilValidate.isEmpty(areaStyle)) {

+            areaStyle = "tabletext";

+        }

+        writer.append(FoScreenRenderer.getFoStyle(areaStyle));

+        writer.append(">");

+        appendWhitespace(writer);

+    }

+

+    public void renderFormatItemRowCellClose(Appendable writer, Map<String, Object> context, ModelForm modelForm, ModelFormField modelFormField) throws IOException {

+        writer.append("</fo:table-cell>");

+        appendWhitespace(writer);

+    }

+

+    public void renderFormatItemRowFormCellOpen(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {

+        writer.append("<fo:table-cell>");

+        appendWhitespace(writer);

+    }

+

+    public void renderFormatItemRowFormCellClose(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {

+        writer.append("</fo:table-cell>");

+        appendWhitespace(writer);

+    }

+

+    // TODO: multi columns (position attribute) in single forms are still not implemented

+    public void renderFormatSingleWrapperOpen(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {

+        writer.append("<fo:table>");

+        appendWhitespace(writer);

+        writer.append("<fo:table-column column-width=\"2in\"/>");

+        appendWhitespace(writer);

+        writer.append("<fo:table-column/>");

+        appendWhitespace(writer);

+        writer.append("<fo:table-body>");

+        appendWhitespace(writer);

+    }

+    public void renderFormatSingleWrapperClose(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {

+        writer.append("</fo:table-body>");

+        writer.append("</fo:table>");

+        appendWhitespace(writer);

+    }

+

+    public void renderFormatFieldRowOpen(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {

+        writer.append("<fo:table-row>");

+        appendWhitespace(writer);

+    }

+

+    public void renderFormatFieldRowClose(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {

+        writer.append("</fo:table-row>");

+        appendWhitespace(writer);

+    }

+

+

+    public void renderFormatFieldRowTitleCellOpen(Appendable writer, Map<String, Object> context, ModelFormField modelFormField) throws IOException {

+        writer.append("<fo:table-cell font-weight=\"bold\" text-align=\"right\" padding=\"3pt\">");

+        writer.append("<fo:block>");

+        appendWhitespace(writer);

+    }

+

+    public void renderFormatFieldRowTitleCellClose(Appendable writer, Map<String, Object> context, ModelFormField modelFormField) throws IOException {

+        writer.append("</fo:block>");

+        writer.append("</fo:table-cell>");

+        appendWhitespace(writer);

+    }

+

+    public void renderFormatFieldRowSpacerCell(Appendable writer, Map<String, Object> context, ModelFormField modelFormField) throws IOException {

+    }

+

+    public void renderFormatFieldRowWidgetCellOpen(Appendable writer, Map<String, Object> context, ModelFormField modelFormField, int positions, int positionSpan, Integer nextPositionInRow) throws IOException {

+        writer.append("<fo:table-cell text-align=\"left\" padding=\"2pt\" padding-left=\"5pt\">");

+        appendWhitespace(writer);

+    }

+

+    public void renderFormatFieldRowWidgetCellClose(Appendable writer, Map<String, Object> context, ModelFormField modelFormField, int positions, int positionSpan, Integer nextPositionInRow) throws IOException {

+        writer.append("</fo:table-cell>");

+        appendWhitespace(writer);

+    }

+

+    public void renderFormatEmptySpace(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {

+        // TODO

+    }

+

+    public void renderTextFindField(Appendable writer, Map<String, Object> context, TextFindField textFindField) throws IOException {

+        ModelFormField modelFormField = textFindField.getModelFormField();

+        this.makeBlockString(writer, modelFormField.getWidgetStyle(), modelFormField.getEntry(context, textFindField.getDefaultValue(context)));

+        appendWhitespace(writer);

+    }

+

+    public void renderRangeFindField(Appendable writer, Map<String, Object> context, RangeFindField rangeFindField) throws IOException {

+        ModelFormField modelFormField = rangeFindField.getModelFormField();

+        this.makeBlockString(writer, modelFormField.getWidgetStyle(), modelFormField.getEntry(context, rangeFindField.getDefaultValue(context)));

+        appendWhitespace(writer);

+    }

+

+    public void renderDateFindField(Appendable writer, Map<String, Object> context, DateFindField dateFindField) throws IOException {

+        ModelFormField modelFormField = dateFindField.getModelFormField();

+        this.makeBlockString(writer, modelFormField.getWidgetStyle(), modelFormField.getEntry(context, dateFindField.getDefaultValue(context)));

+        appendWhitespace(writer);

+    }

+

+    public void renderLookupField(Appendable writer, Map<String, Object> context, LookupField lookupField) throws IOException {

+        ModelFormField modelFormField = lookupField.getModelFormField();

+        this.makeBlockString(writer, modelFormField.getWidgetStyle(), modelFormField.getEntry(context, lookupField.getDefaultValue(context)));

+        appendWhitespace(writer);

+    }

+

+    public void renderNextPrev(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {

+    }

+

+    public void renderFileField(Appendable writer, Map<String, Object> context, FileField textField) throws IOException {

+        ModelFormField modelFormField = textField.getModelFormField();

+        this.makeBlockString(writer, modelFormField.getWidgetStyle(), modelFormField.getEntry(context, textField.getDefaultValue(context)));

+        appendWhitespace(writer);

+    }

+

+    public void renderPasswordField(Appendable writer, Map<String, Object> context, PasswordField passwordField) throws IOException {

+        this.makeBlockString(writer, null, "");

+    }

+

+    public void renderImageField(Appendable writer, Map<String, Object> context, ImageField imageField) throws IOException {

+        // TODO

+        this.makeBlockString(writer, null, "");

+    }

+

+    public void renderFieldGroupOpen(Appendable writer, Map<String, Object> context, ModelForm.FieldGroup fieldGroup) throws IOException {

+        // TODO

+    }

+

+    public void renderFieldGroupClose(Appendable writer, Map<String, Object> context, ModelForm.FieldGroup fieldGroup) throws IOException {

+        // TODO

+    }

+

+    public void renderBanner(Appendable writer, Map<String, Object> context, ModelForm.Banner banner) throws IOException {

+        // TODO

+        this.makeBlockString(writer, null, "");

+    }

+

+    public void renderHyperlinkTitle(Appendable writer, Map<String, Object> context, ModelFormField modelFormField, String titleText) throws IOException {

+    }

+

+    public void renderContainerFindField(Appendable writer, Map<String, Object> context, ContainerField containerField) throws IOException {

+    }

+}

diff --git a/framework/widget/src/org/ofbiz/widget/fo/FoScreenRenderer.java b/framework/widget/src/org/ofbiz/widget/renderer/fo/FoScreenRenderer.java
similarity index 96%
rename from framework/widget/src/org/ofbiz/widget/fo/FoScreenRenderer.java
rename to framework/widget/src/org/ofbiz/widget/renderer/fo/FoScreenRenderer.java
index 882e013..3ffa1c9 100644
--- a/framework/widget/src/org/ofbiz/widget/fo/FoScreenRenderer.java
+++ b/framework/widget/src/org/ofbiz/widget/renderer/fo/FoScreenRenderer.java
@@ -1,195 +1,195 @@
-/*******************************************************************************
- * 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.fo;
-
-import java.io.IOException;
-import java.util.Map;
-
-import org.ofbiz.base.util.GeneralException;
-import org.ofbiz.base.util.UtilProperties;
-import org.ofbiz.base.util.UtilValidate;
-import org.ofbiz.widget.ModelWidget;
-import org.ofbiz.widget.html.HtmlWidgetRenderer;
-import org.ofbiz.widget.screen.ModelScreenWidget;
-import org.ofbiz.widget.screen.ScreenStringRenderer;
-import org.ofbiz.widget.screen.ModelScreenWidget.ColumnContainer;
-import org.ofbiz.entity.GenericValue;
-
-/**
- * Widget Library - HTML Form Renderer implementation
- * @deprecated Use MacroScreenRenderer.
- */
-public class FoScreenRenderer extends HtmlWidgetRenderer implements ScreenStringRenderer {
-
-    public static final String module = FoScreenRenderer.class.getName();
-
-    public FoScreenRenderer() {}
-
-    // This is a util method to get the style from a property file
-    public static String getFoStyle(String styleName) {
-        String value = UtilProperties.getPropertyValue("fo-styles.properties", styleName);
-        if (value.equals(styleName)) {
-            return "";
-        }
-        return value;
-    }
-
-    public String getRendererName() {
-        return "xsl-fo";
-    }
-
-    public void renderScreenBegin(Appendable writer, Map<String, Object> context) throws IOException {
-    }
-
-    public void renderScreenEnd(Appendable writer, Map<String, Object> context) throws IOException {
-
-    }
-
-    public void renderSectionBegin(Appendable writer, Map<String, Object> context, ModelScreenWidget.Section section) throws IOException {
-        if (section.isMainSection()) {
-            this.widgetCommentsEnabled = ModelWidget.widgetBoundaryCommentsEnabled(context);
-        }
-        renderBeginningBoundaryComment(writer, section.isMainSection()?"Screen":"Section Widget", section);
-    }
-    public void renderSectionEnd(Appendable writer, Map<String, Object> context, ModelScreenWidget.Section section) throws IOException {
-        renderEndingBoundaryComment(writer, section.isMainSection()?"Screen":"Section Widget", section);
-    }
-
-    public void renderContainerBegin(Appendable writer, Map<String, Object> context, ModelScreenWidget.Container container) throws IOException {
-        writer.append("<fo:block");
-
-        String style = container.getStyle(context);
-        if (UtilValidate.isNotEmpty(style)) {
-            writer.append(" ");
-            writer.append(FoScreenRenderer.getFoStyle(style));
-        }
-        writer.append(">");
-        appendWhitespace(writer);
-    }
-    public void renderContainerEnd(Appendable writer, Map<String, Object> context, ModelScreenWidget.Container container) throws IOException {
-        writer.append("</fo:block>");
-        appendWhitespace(writer);
-    }
-
-    public void renderLabel(Appendable writer, Map<String, Object> context, ModelScreenWidget.Label label) throws IOException {
-        String labelText = label.getText(context);
-        if (UtilValidate.isEmpty(labelText)) {
-            // nothing to render
-            return;
-        }
-        // open tag
-        String style = label.getStyle(context);
-        if (UtilValidate.isNotEmpty(style)) {
-            writer.append("<fo:inline ");
-            writer.append(FoScreenRenderer.getFoStyle(style));
-            writer.append(">");
-            // the text
-            writer.append(labelText);
-            // close tag
-            writer.append("</fo:inline>");
-        } else {
-            writer.append(labelText);
-        }
-        appendWhitespace(writer);
-    }
-
-    public void renderHorizontalSeparator(Appendable writer, Map<String, Object> context, ModelScreenWidget.HorizontalSeparator separator) throws IOException {
-        writer.append("<fo:block>");
-        appendWhitespace(writer);
-        writer.append("<fo:leader leader-length=\"100%\" leader-pattern=\"rule\" rule-style=\"solid\" rule-thickness=\"0.1mm\" color=\"black\"/>");
-        appendWhitespace(writer);
-        writer.append("</fo:block>");
-        appendWhitespace(writer);
-    }
-
-    public void renderLink(Appendable writer, Map<String, Object> context, ModelScreenWidget.ScreenLink link) throws IOException {
-        // TODO: not implemented
-    }
-
-    public void renderImage(Appendable writer, Map<String, Object> context, ModelScreenWidget.ScreenImage image) throws IOException {
-        // TODO: not implemented
-    }
-
-    public void renderContentBegin(Appendable writer, Map<String, Object> context, ModelScreenWidget.Content content) throws IOException {
-        // TODO: not implemented
-    }
-
-    public void renderContentBody(Appendable writer, Map<String, Object> context, ModelScreenWidget.Content content) throws IOException {
-        // TODO: not implemented
-    }
-
-    public void renderContentEnd(Appendable writer, Map<String, Object> context, ModelScreenWidget.Content content) throws IOException {
-        // TODO: not implemented
-    }
-
-    public void renderContentFrame(Appendable writer, Map<String, Object> context, ModelScreenWidget.Content content) throws IOException {
-        // TODO: not implemented
-    }
-
-    public void renderSubContentBegin(Appendable writer, Map<String, Object> context, ModelScreenWidget.SubContent content) throws IOException {
-        // TODO: not implemented
-    }
-
-    public void renderSubContentBody(Appendable writer, Map<String, Object> context, ModelScreenWidget.SubContent content) throws IOException {
-        // TODO: not implemented
-    }
-
-    public void renderSubContentEnd(Appendable writer, Map<String, Object> context, ModelScreenWidget.SubContent content) throws IOException {
-        // TODO: not implemented
-    }
-
-    public void renderScreenletBegin(Appendable writer, Map<String, Object> context, boolean collapsed, ModelScreenWidget.Screenlet screenlet) throws IOException {
-        // TODO: not implemented
-    }
-
-    public void renderScreenletSubWidget(Appendable writer, Map<String, Object> context, ModelScreenWidget subWidget, ModelScreenWidget.Screenlet screenlet) throws GeneralException {
-        // TODO: not implemented
-    }
-
-    public void renderScreenletEnd(Appendable writer, Map<String, Object> context, ModelScreenWidget.Screenlet screenlet) throws IOException {
-        // TODO: not implemented
-    }
-
-    public void renderPortalPageBegin(Appendable writer, Map<String, Object> context, ModelScreenWidget.PortalPage portalPage) throws GeneralException, IOException {
-        // TODO: not implemented
-    }
-    public void renderPortalPageEnd(Appendable writer, Map<String, Object> context, ModelScreenWidget.PortalPage portalPage) throws GeneralException, IOException {
-        // TODO: not implemented
-    }
-    public void renderPortalPageColumnBegin(Appendable writer, Map<String, Object> context, ModelScreenWidget.PortalPage portalPage, GenericValue portalPageColumn) throws GeneralException, IOException {
-        // TODO: not implemented
-    }
-    public void renderPortalPageColumnEnd(Appendable writer, Map<String, Object> context, ModelScreenWidget.PortalPage portalPage, GenericValue portalPageColumn) throws GeneralException, IOException {
-        // TODO: not implemented
-    }
-    public void renderPortalPagePortletBegin(Appendable writer, Map<String, Object> context, ModelScreenWidget.PortalPage portalPage, GenericValue portalPortlet) throws GeneralException, IOException {
-        // TODO: not implemented
-    }
-    public void renderPortalPagePortletEnd(Appendable writer, Map<String, Object> context, ModelScreenWidget.PortalPage portalPage, GenericValue portalPortlet) throws GeneralException, IOException {
-        // TODO: not implemented
-    }
-    public void renderPortalPagePortletBody(Appendable writer, Map<String, Object> context, ModelScreenWidget.PortalPage portalPage, GenericValue portalPortlet) throws GeneralException, IOException {
-        // TODO: not implemented
-    }
-
-    @Override
-    public void renderColumnContainer(Appendable writer, Map<String, Object> context, ColumnContainer columnContainer) throws IOException {
-        // TODO: not implemented
-    }
-}
+/*******************************************************************************

+ * 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.renderer.fo;

+

+import java.io.IOException;

+import java.util.Map;

+

+import org.ofbiz.base.util.GeneralException;

+import org.ofbiz.base.util.UtilProperties;

+import org.ofbiz.base.util.UtilValidate;

+import org.ofbiz.entity.GenericValue;

+import org.ofbiz.widget.model.ModelScreenWidget;

+import org.ofbiz.widget.model.ModelScreenWidget.ColumnContainer;

+import org.ofbiz.widget.model.ModelWidget;

+import org.ofbiz.widget.renderer.ScreenStringRenderer;

+import org.ofbiz.widget.renderer.html.HtmlWidgetRenderer;

+

+/**

+ * Widget Library - HTML Form Renderer implementation

+ * @deprecated Use MacroScreenRenderer.

+ */

+public class FoScreenRenderer extends HtmlWidgetRenderer implements ScreenStringRenderer {

+

+    public static final String module = FoScreenRenderer.class.getName();

+

+    public FoScreenRenderer() {}

+

+    // This is a util method to get the style from a property file

+    public static String getFoStyle(String styleName) {

+        String value = UtilProperties.getPropertyValue("fo-styles.properties", styleName);

+        if (value.equals(styleName)) {

+            return "";

+        }

+        return value;

+    }

+

+    public String getRendererName() {

+        return "xsl-fo";

+    }

+

+    public void renderScreenBegin(Appendable writer, Map<String, Object> context) throws IOException {

+    }

+

+    public void renderScreenEnd(Appendable writer, Map<String, Object> context) throws IOException {

+

+    }

+

+    public void renderSectionBegin(Appendable writer, Map<String, Object> context, ModelScreenWidget.Section section) throws IOException {

+        if (section.isMainSection()) {

+            this.widgetCommentsEnabled = ModelWidget.widgetBoundaryCommentsEnabled(context);

+        }

+        renderBeginningBoundaryComment(writer, section.isMainSection()?"Screen":"Section Widget", section);

+    }

+    public void renderSectionEnd(Appendable writer, Map<String, Object> context, ModelScreenWidget.Section section) throws IOException {

+        renderEndingBoundaryComment(writer, section.isMainSection()?"Screen":"Section Widget", section);

+    }

+

+    public void renderContainerBegin(Appendable writer, Map<String, Object> context, ModelScreenWidget.Container container) throws IOException {

+        writer.append("<fo:block");

+

+        String style = container.getStyle(context);

+        if (UtilValidate.isNotEmpty(style)) {

+            writer.append(" ");

+            writer.append(FoScreenRenderer.getFoStyle(style));

+        }

+        writer.append(">");

+        appendWhitespace(writer);

+    }

+    public void renderContainerEnd(Appendable writer, Map<String, Object> context, ModelScreenWidget.Container container) throws IOException {

+        writer.append("</fo:block>");

+        appendWhitespace(writer);

+    }

+

+    public void renderLabel(Appendable writer, Map<String, Object> context, ModelScreenWidget.Label label) throws IOException {

+        String labelText = label.getText(context);

+        if (UtilValidate.isEmpty(labelText)) {

+            // nothing to render

+            return;

+        }

+        // open tag

+        String style = label.getStyle(context);

+        if (UtilValidate.isNotEmpty(style)) {

+            writer.append("<fo:inline ");

+            writer.append(FoScreenRenderer.getFoStyle(style));

+            writer.append(">");

+            // the text

+            writer.append(labelText);

+            // close tag

+            writer.append("</fo:inline>");

+        } else {

+            writer.append(labelText);

+        }

+        appendWhitespace(writer);

+    }

+

+    public void renderHorizontalSeparator(Appendable writer, Map<String, Object> context, ModelScreenWidget.HorizontalSeparator separator) throws IOException {

+        writer.append("<fo:block>");

+        appendWhitespace(writer);

+        writer.append("<fo:leader leader-length=\"100%\" leader-pattern=\"rule\" rule-style=\"solid\" rule-thickness=\"0.1mm\" color=\"black\"/>");

+        appendWhitespace(writer);

+        writer.append("</fo:block>");

+        appendWhitespace(writer);

+    }

+

+    public void renderLink(Appendable writer, Map<String, Object> context, ModelScreenWidget.ScreenLink link) throws IOException {

+        // TODO: not implemented

+    }

+

+    public void renderImage(Appendable writer, Map<String, Object> context, ModelScreenWidget.ScreenImage image) throws IOException {

+        // TODO: not implemented

+    }

+

+    public void renderContentBegin(Appendable writer, Map<String, Object> context, ModelScreenWidget.Content content) throws IOException {

+        // TODO: not implemented

+    }

+

+    public void renderContentBody(Appendable writer, Map<String, Object> context, ModelScreenWidget.Content content) throws IOException {

+        // TODO: not implemented

+    }

+

+    public void renderContentEnd(Appendable writer, Map<String, Object> context, ModelScreenWidget.Content content) throws IOException {

+        // TODO: not implemented

+    }

+

+    public void renderContentFrame(Appendable writer, Map<String, Object> context, ModelScreenWidget.Content content) throws IOException {

+        // TODO: not implemented

+    }

+

+    public void renderSubContentBegin(Appendable writer, Map<String, Object> context, ModelScreenWidget.SubContent content) throws IOException {

+        // TODO: not implemented

+    }

+

+    public void renderSubContentBody(Appendable writer, Map<String, Object> context, ModelScreenWidget.SubContent content) throws IOException {

+        // TODO: not implemented

+    }

+

+    public void renderSubContentEnd(Appendable writer, Map<String, Object> context, ModelScreenWidget.SubContent content) throws IOException {

+        // TODO: not implemented

+    }

+

+    public void renderScreenletBegin(Appendable writer, Map<String, Object> context, boolean collapsed, ModelScreenWidget.Screenlet screenlet) throws IOException {

+        // TODO: not implemented

+    }

+

+    public void renderScreenletSubWidget(Appendable writer, Map<String, Object> context, ModelScreenWidget subWidget, ModelScreenWidget.Screenlet screenlet) throws GeneralException {

+        // TODO: not implemented

+    }

+

+    public void renderScreenletEnd(Appendable writer, Map<String, Object> context, ModelScreenWidget.Screenlet screenlet) throws IOException {

+        // TODO: not implemented

+    }

+

+    public void renderPortalPageBegin(Appendable writer, Map<String, Object> context, ModelScreenWidget.PortalPage portalPage) throws GeneralException, IOException {

+        // TODO: not implemented

+    }

+    public void renderPortalPageEnd(Appendable writer, Map<String, Object> context, ModelScreenWidget.PortalPage portalPage) throws GeneralException, IOException {

+        // TODO: not implemented

+    }

+    public void renderPortalPageColumnBegin(Appendable writer, Map<String, Object> context, ModelScreenWidget.PortalPage portalPage, GenericValue portalPageColumn) throws GeneralException, IOException {

+        // TODO: not implemented

+    }

+    public void renderPortalPageColumnEnd(Appendable writer, Map<String, Object> context, ModelScreenWidget.PortalPage portalPage, GenericValue portalPageColumn) throws GeneralException, IOException {

+        // TODO: not implemented

+    }

+    public void renderPortalPagePortletBegin(Appendable writer, Map<String, Object> context, ModelScreenWidget.PortalPage portalPage, GenericValue portalPortlet) throws GeneralException, IOException {

+        // TODO: not implemented

+    }

+    public void renderPortalPagePortletEnd(Appendable writer, Map<String, Object> context, ModelScreenWidget.PortalPage portalPage, GenericValue portalPortlet) throws GeneralException, IOException {

+        // TODO: not implemented

+    }

+    public void renderPortalPagePortletBody(Appendable writer, Map<String, Object> context, ModelScreenWidget.PortalPage portalPage, GenericValue portalPortlet) throws GeneralException, IOException {

+        // TODO: not implemented

+    }

+

+    @Override

+    public void renderColumnContainer(Appendable writer, Map<String, Object> context, ColumnContainer columnContainer) throws IOException {

+        // TODO: not implemented

+    }

+}

diff --git a/framework/widget/src/org/ofbiz/widget/screen/ScreenFopViewHandler.java b/framework/widget/src/org/ofbiz/widget/renderer/fo/ScreenFopViewHandler.java
similarity index 94%
rename from framework/widget/src/org/ofbiz/widget/screen/ScreenFopViewHandler.java
rename to framework/widget/src/org/ofbiz/widget/renderer/fo/ScreenFopViewHandler.java
index c76018c..ff649d0 100644
--- a/framework/widget/src/org/ofbiz/widget/screen/ScreenFopViewHandler.java
+++ b/framework/widget/src/org/ofbiz/widget/renderer/fo/ScreenFopViewHandler.java
@@ -1,141 +1,144 @@
-/*******************************************************************************
- * 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.screen;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.Reader;
-import java.io.StringReader;
-import java.io.StringWriter;
-import java.io.Writer;
-
-import javax.servlet.ServletContext;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import javax.xml.transform.stream.StreamSource;
-
-import org.apache.fop.apps.Fop;
-import org.ofbiz.base.util.Debug;
-import org.ofbiz.base.util.UtilCodec;
-import org.ofbiz.base.util.UtilProperties;
-import org.ofbiz.base.util.UtilValidate;
-import org.ofbiz.entity.Delegator;
-import org.ofbiz.entity.util.EntityUtilProperties;
-import org.ofbiz.webapp.view.AbstractViewHandler;
-import org.ofbiz.webapp.view.ApacheFopWorker;
-import org.ofbiz.webapp.view.ViewHandlerException;
-import org.ofbiz.widget.form.FormStringRenderer;
-import org.ofbiz.widget.form.MacroFormRenderer;
-import org.ofbiz.widget.html.HtmlScreenRenderer;
-
-/**
- * Uses XSL-FO formatted templates to generate PDF, PCL, POSTSCRIPT etc.  views
- * This handler will use JPublish to generate the XSL-FO
- */
-public class ScreenFopViewHandler extends AbstractViewHandler {
-    public static final String module = ScreenFopViewHandler.class.getName();
-    protected static final String DEFAULT_ERROR_TEMPLATE = "component://common/widget/CommonScreens.xml#FoError";
-
-    protected ServletContext servletContext = null;
-
-    /**
-     * @see org.ofbiz.webapp.view.ViewHandler#init(javax.servlet.ServletContext)
-     */
-    @Override
-    public void init(ServletContext context) throws ViewHandlerException {
-        this.servletContext = context;
-    }
-
-    /**
-     * @see org.ofbiz.webapp.view.ViewHandler#render(java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
-     */
-    @Override
-    public void render(String name, String page, String info, String contentType, String encoding, HttpServletRequest request, HttpServletResponse response) throws ViewHandlerException {
-
-        Delegator delegator = (Delegator) request.getAttribute("delegator");
-        // render and obtain the XSL-FO
-        Writer writer = new StringWriter();
-        try {
-            ScreenStringRenderer screenStringRenderer = new MacroScreenRenderer(EntityUtilProperties.getPropertyValue("widget", getName() + ".name", delegator), EntityUtilProperties.getPropertyValue("widget", getName() + ".screenrenderer", delegator));
-            FormStringRenderer formStringRenderer = new MacroFormRenderer(EntityUtilProperties.getPropertyValue("widget", getName() + ".formrenderer", delegator), request, response);
-            // TODO: uncomment these lines when the renderers are implemented
-            //TreeStringRenderer treeStringRenderer = new MacroTreeRenderer(UtilProperties.getPropertyValue("widget", getName() + ".treerenderer"), writer);
-            //MenuStringRenderer menuStringRenderer = new MacroMenuRenderer(UtilProperties.getPropertyValue("widget", getName() + ".menurenderer"), writer);
-            ScreenRenderer screens = new ScreenRenderer(writer, null, screenStringRenderer);
-            screens.populateContextForRequest(request, response, servletContext);
-
-            // this is the object used to render forms from their definitions
-            screens.getContext().put("formStringRenderer", formStringRenderer);
-            screens.getContext().put("simpleEncoder", UtilCodec.getEncoder(EntityUtilProperties.getPropertyValue("widget", getName() + ".encoder", delegator)));
-            screens.render(page);
-        } catch (Exception e) {
-            renderError("Problems with the response writer/output stream", e, "[Not Yet Rendered]", request, response);
-            return;
-        }
-
-        // set the input source (XSL-FO) and generate the output stream of contentType
-        String screenOutString = writer.toString();
-        if (!screenOutString.startsWith("<?xml")) {
-            screenOutString = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + screenOutString;
-        }
-        if (Debug.verboseOn()) Debug.logVerbose("XSL:FO Screen Output: " + screenOutString, module);
-
-        if (UtilValidate.isEmpty(contentType)) {
-            contentType = UtilProperties.getPropertyValue("widget", getName() + ".default.contenttype");
-        }
-        Reader reader = new StringReader(screenOutString);
-        StreamSource src = new StreamSource(reader);
-        ByteArrayOutputStream out = new ByteArrayOutputStream();
-        try {
-            Fop fop = ApacheFopWorker.createFopInstance(out, contentType);
-            ApacheFopWorker.transform(src, null, fop);
-        } catch (Exception e) {
-            renderError("Unable to transform FO file", e, screenOutString, request, response);
-            return;
-        }
-        // set the content type and length
-        response.setContentType(contentType);
-        response.setContentLength(out.size());
-
-        // write to the browser
-        try {
-            out.writeTo(response.getOutputStream());
-            response.getOutputStream().flush();
-        } catch (IOException e) {
-            renderError("Unable to write to OutputStream", e, screenOutString, request, response);
-        }
-    }
-
-    protected void renderError(String msg, Exception e, String screenOutString, HttpServletRequest request, HttpServletResponse response) throws ViewHandlerException {
-        Debug.logError(msg + ": " + e + "; Screen XSL:FO text was:\n" + screenOutString, module);
-        try {
-            Writer writer = new StringWriter();
-            ScreenRenderer screens = new ScreenRenderer(writer, null, new HtmlScreenRenderer());
-            screens.populateContextForRequest(request, response, servletContext);
-            screens.getContext().put("errorMessage", msg + ": " + e);
-            screens.render(DEFAULT_ERROR_TEMPLATE);
-            response.setContentType("text/html");
-            response.getWriter().write(writer.toString());
-            writer.close();
-        } catch (Exception x) {
-            Debug.logError("Multiple errors rendering FOP", module);
-            throw new ViewHandlerException("Multiple errors rendering FOP", x);
-        }
-    }
-}
+/*******************************************************************************

+ * 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.renderer.fo;

+

+import java.io.ByteArrayOutputStream;

+import java.io.IOException;

+import java.io.Reader;

+import java.io.StringReader;

+import java.io.StringWriter;

+import java.io.Writer;

+

+import javax.servlet.ServletContext;

+import javax.servlet.http.HttpServletRequest;

+import javax.servlet.http.HttpServletResponse;

+import javax.xml.transform.stream.StreamSource;

+

+import org.apache.fop.apps.Fop;

+import org.ofbiz.base.util.Debug;

+import org.ofbiz.base.util.UtilCodec;

+import org.ofbiz.base.util.UtilProperties;

+import org.ofbiz.base.util.UtilValidate;

+import org.ofbiz.entity.Delegator;

+import org.ofbiz.entity.util.EntityUtilProperties;

+import org.ofbiz.webapp.view.AbstractViewHandler;

+import org.ofbiz.webapp.view.ApacheFopWorker;

+import org.ofbiz.webapp.view.ViewHandlerException;

+import org.ofbiz.widget.renderer.FormStringRenderer;

+import org.ofbiz.widget.renderer.ScreenRenderer;

+import org.ofbiz.widget.renderer.ScreenStringRenderer;

+import org.ofbiz.widget.renderer.html.HtmlScreenRenderer;

+import org.ofbiz.widget.renderer.macro.MacroFormRenderer;

+import org.ofbiz.widget.renderer.macro.MacroScreenRenderer;

+

+/**

+ * Uses XSL-FO formatted templates to generate PDF, PCL, POSTSCRIPT etc.  views

+ * This handler will use JPublish to generate the XSL-FO

+ */

+public class ScreenFopViewHandler extends AbstractViewHandler {

+    public static final String module = ScreenFopViewHandler.class.getName();

+    protected static final String DEFAULT_ERROR_TEMPLATE = "component://common/widget/CommonScreens.xml#FoError";

+

+    protected ServletContext servletContext = null;

+

+    /**

+     * @see org.ofbiz.webapp.view.ViewHandler#init(javax.servlet.ServletContext)

+     */

+    @Override

+    public void init(ServletContext context) throws ViewHandlerException {

+        this.servletContext = context;

+    }

+

+    /**

+     * @see org.ofbiz.webapp.view.ViewHandler#render(java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)

+     */

+    @Override

+    public void render(String name, String page, String info, String contentType, String encoding, HttpServletRequest request, HttpServletResponse response) throws ViewHandlerException {

+

+        Delegator delegator = (Delegator) request.getAttribute("delegator");

+        // render and obtain the XSL-FO

+        Writer writer = new StringWriter();

+        try {

+            ScreenStringRenderer screenStringRenderer = new MacroScreenRenderer(EntityUtilProperties.getPropertyValue("widget", getName() + ".name", delegator), EntityUtilProperties.getPropertyValue("widget", getName() + ".screenrenderer", delegator));

+            FormStringRenderer formStringRenderer = new MacroFormRenderer(EntityUtilProperties.getPropertyValue("widget", getName() + ".formrenderer", delegator), request, response);

+            // TODO: uncomment these lines when the renderers are implemented

+            //TreeStringRenderer treeStringRenderer = new MacroTreeRenderer(UtilProperties.getPropertyValue("widget", getName() + ".treerenderer"), writer);

+            //MenuStringRenderer menuStringRenderer = new MacroMenuRenderer(UtilProperties.getPropertyValue("widget", getName() + ".menurenderer"), writer);

+            ScreenRenderer screens = new ScreenRenderer(writer, null, screenStringRenderer);

+            screens.populateContextForRequest(request, response, servletContext);

+

+            // this is the object used to render forms from their definitions

+            screens.getContext().put("formStringRenderer", formStringRenderer);

+            screens.getContext().put("simpleEncoder", UtilCodec.getEncoder(EntityUtilProperties.getPropertyValue("widget", getName() + ".encoder", delegator)));

+            screens.render(page);

+        } catch (Exception e) {

+            renderError("Problems with the response writer/output stream", e, "[Not Yet Rendered]", request, response);

+            return;

+        }

+

+        // set the input source (XSL-FO) and generate the output stream of contentType

+        String screenOutString = writer.toString();

+        if (!screenOutString.startsWith("<?xml")) {

+            screenOutString = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + screenOutString;

+        }

+        if (Debug.verboseOn()) Debug.logVerbose("XSL:FO Screen Output: " + screenOutString, module);

+

+        if (UtilValidate.isEmpty(contentType)) {

+            contentType = UtilProperties.getPropertyValue("widget", getName() + ".default.contenttype");

+        }

+        Reader reader = new StringReader(screenOutString);

+        StreamSource src = new StreamSource(reader);

+        ByteArrayOutputStream out = new ByteArrayOutputStream();

+        try {

+            Fop fop = ApacheFopWorker.createFopInstance(out, contentType);

+            ApacheFopWorker.transform(src, null, fop);

+        } catch (Exception e) {

+            renderError("Unable to transform FO file", e, screenOutString, request, response);

+            return;

+        }

+        // set the content type and length

+        response.setContentType(contentType);

+        response.setContentLength(out.size());

+

+        // write to the browser

+        try {

+            out.writeTo(response.getOutputStream());

+            response.getOutputStream().flush();

+        } catch (IOException e) {

+            renderError("Unable to write to OutputStream", e, screenOutString, request, response);

+        }

+    }

+

+    protected void renderError(String msg, Exception e, String screenOutString, HttpServletRequest request, HttpServletResponse response) throws ViewHandlerException {

+        Debug.logError(msg + ": " + e + "; Screen XSL:FO text was:\n" + screenOutString, module);

+        try {

+            Writer writer = new StringWriter();

+            ScreenRenderer screens = new ScreenRenderer(writer, null, new HtmlScreenRenderer());

+            screens.populateContextForRequest(request, response, servletContext);

+            screens.getContext().put("errorMessage", msg + ": " + e);

+            screens.render(DEFAULT_ERROR_TEMPLATE);

+            response.setContentType("text/html");

+            response.getWriter().write(writer.toString());

+            writer.close();

+        } catch (Exception x) {

+            Debug.logError("Multiple errors rendering FOP", module);

+            throw new ViewHandlerException("Multiple errors rendering FOP", x);

+        }

+    }

+}

diff --git a/framework/widget/src/org/ofbiz/widget/html/HtmlFormRenderer.java b/framework/widget/src/org/ofbiz/widget/renderer/html/HtmlFormRenderer.java
similarity index 96%
rename from framework/widget/src/org/ofbiz/widget/html/HtmlFormRenderer.java
rename to framework/widget/src/org/ofbiz/widget/renderer/html/HtmlFormRenderer.java
index 526da1c..18998c3 100644
--- a/framework/widget/src/org/ofbiz/widget/html/HtmlFormRenderer.java
+++ b/framework/widget/src/org/ofbiz/widget/renderer/html/HtmlFormRenderer.java
@@ -1,2823 +1,2823 @@
-/*******************************************************************************
- * 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.html;
-
-import java.io.IOException;
-import java.util.HashSet;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-import java.util.Map.Entry;
-
-import javax.servlet.ServletContext;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.ofbiz.base.util.Debug;
-import org.ofbiz.base.util.UtilCodec;
-import org.ofbiz.base.util.UtilGenerics;
-import org.ofbiz.base.util.UtilHttp;
-import org.ofbiz.base.util.UtilMisc;
-import org.ofbiz.base.util.UtilProperties;
-import org.ofbiz.base.util.UtilValidate;
-import org.ofbiz.base.util.string.FlexibleStringExpander;
-import org.ofbiz.base.util.template.FreeMarkerWorker;
-import org.ofbiz.entity.Delegator;
-import org.ofbiz.webapp.control.RequestHandler;
-import org.ofbiz.webapp.taglib.ContentUrlTag;
-import org.ofbiz.widget.CommonWidgetModels;
-import org.ofbiz.widget.ModelWidget;
-import org.ofbiz.widget.WidgetWorker;
-import org.ofbiz.widget.form.FormRenderer;
-import org.ofbiz.widget.form.FormStringRenderer;
-import org.ofbiz.widget.form.MacroFormRenderer;
-import org.ofbiz.widget.form.ModelForm;
-import org.ofbiz.widget.form.ModelFormField;
-import org.ofbiz.widget.form.ModelFormField.CheckField;
-import org.ofbiz.widget.form.ModelFormField.ContainerField;
-import org.ofbiz.widget.form.ModelFormField.DateFindField;
-import org.ofbiz.widget.form.ModelFormField.DateTimeField;
-import org.ofbiz.widget.form.ModelFormField.DisplayEntityField;
-import org.ofbiz.widget.form.ModelFormField.DisplayField;
-import org.ofbiz.widget.form.ModelFormField.DropDownField;
-import org.ofbiz.widget.form.ModelFormField.FieldInfoWithOptions;
-import org.ofbiz.widget.form.ModelFormField.FileField;
-import org.ofbiz.widget.form.ModelFormField.HiddenField;
-import org.ofbiz.widget.form.ModelFormField.HyperlinkField;
-import org.ofbiz.widget.form.ModelFormField.IgnoredField;
-import org.ofbiz.widget.form.ModelFormField.ImageField;
-import org.ofbiz.widget.form.ModelFormField.LookupField;
-import org.ofbiz.widget.form.ModelFormField.PasswordField;
-import org.ofbiz.widget.form.ModelFormField.RadioField;
-import org.ofbiz.widget.form.ModelFormField.RangeFindField;
-import org.ofbiz.widget.form.ModelFormField.ResetField;
-import org.ofbiz.widget.form.ModelFormField.SubmitField;
-import org.ofbiz.widget.form.ModelFormField.TextField;
-import org.ofbiz.widget.form.ModelFormField.TextFindField;
-import org.ofbiz.widget.form.ModelFormField.TextareaField;
-import org.ofbiz.widget.form.Paginator;
-import org.ofbiz.widget.form.UtilHelpText;
-
-import freemarker.template.TemplateException;
-
-/**
- * Widget Library - HTML Form Renderer implementation
- */
-public class HtmlFormRenderer extends HtmlWidgetRenderer implements FormStringRenderer {
-
-    public static final String module = HtmlFormRenderer.class.getName();
-
-    protected HttpServletRequest request;
-    protected HttpServletResponse response;
-    protected RequestHandler rh;
-    protected String lastFieldGroupId = "";
-    protected boolean renderPagination = true;
-    protected boolean javaScriptEnabled = false;
-    private UtilCodec.SimpleEncoder internalEncoder;
-
-    protected HtmlFormRenderer() {}
-
-    public HtmlFormRenderer(HttpServletRequest request, HttpServletResponse response) {
-        this.request = request;
-        this.response = response;
-        ServletContext ctx = (ServletContext) request.getAttribute("servletContext");
-        this.rh = (RequestHandler) ctx.getAttribute("_REQUEST_HANDLER_");
-        this.javaScriptEnabled = UtilHttp.isJavaScriptEnabled(request);
-        internalEncoder = UtilCodec.getEncoder("string");
-    }
-
-    public boolean getRenderPagination() {
-        return this.renderPagination;
-    }
-
-    public void setRenderPagination(boolean renderPagination) {
-        this.renderPagination = renderPagination;
-    }
-
-    public void appendOfbizUrl(Appendable writer, String location) throws IOException {
-        writer.append(this.rh.makeLink(this.request, this.response, location));
-    }
-
-    public void appendContentUrl(Appendable writer, String location) throws IOException {
-        ContentUrlTag.appendContentPrefix(this.request, writer);
-        writer.append(location);
-    }
-
-    public void appendTooltip(Appendable writer, Map<String, Object> context, ModelFormField modelFormField) throws IOException {
-        // render the tooltip, in other methods too
-        String tooltip = modelFormField.getTooltip(context);
-        if (UtilValidate.isNotEmpty(tooltip)) {
-            writer.append("<span class=\"");
-            String tooltipStyle = modelFormField.getTooltipStyle();
-            if (UtilValidate.isNotEmpty(tooltipStyle)) {
-                writer.append(tooltipStyle);
-            } else {
-                writer.append("tooltip");
-            }
-            writer.append("\">");
-            writer.append(tooltip);
-            writer.append("</span>");
-        }
-    }
-
-    public void addAsterisks(Appendable writer, Map<String, Object> context, ModelFormField modelFormField) throws IOException {
-
-        boolean requiredField = modelFormField.getRequiredField();
-        if (requiredField) {
-            String requiredStyle = modelFormField.getRequiredFieldStyle();
-
-            if (UtilValidate.isEmpty(requiredStyle)) {
-               writer.append("*");
-            }
-        }
-    }
-
-    public void appendClassNames(Appendable writer, Map<String, Object> context, ModelFormField modelFormField) throws IOException {
-        String className = modelFormField.getWidgetStyle();
-        if (UtilValidate.isNotEmpty(className) || modelFormField.shouldBeRed(context)) {
-            writer.append(" class=\"");
-            writer.append(className);
-            // add a style of red if redWhen is true
-            if (modelFormField.shouldBeRed(context)) {
-                writer.append(" alert");
-            }
-            writer.append('"');
-        }
-    }
-
-    /* (non-Javadoc)
-     * @see org.ofbiz.widget.form.FormStringRenderer#renderDisplayField(java.io.Writer, java.util.Map, org.ofbiz.widget.form.ModelFormField.DisplayField)
-     */
-    public void renderDisplayField(Appendable writer, Map<String, Object> context, DisplayField displayField) throws IOException {
-        ModelFormField modelFormField = displayField.getModelFormField();
-
-        StringBuilder str = new StringBuilder();
-
-        String idName = modelFormField.getCurrentContainerId(context);
-
-        if (UtilValidate.isNotEmpty(modelFormField.getWidgetStyle()) || modelFormField.shouldBeRed(context)) {
-            str.append("<span class=\"");
-            str.append(modelFormField.getWidgetStyle());
-            // add a style of red if this is a date/time field and redWhen is true
-            if (modelFormField.shouldBeRed(context)) {
-                str.append(" alert");
-            }
-            str.append('"');
-            if (UtilValidate.isNotEmpty(idName)) {
-                str.append(" id=\"");
-                str.append(idName+"_sp");
-                str.append('"');
-            }
-            str.append('>');
-        }
-
-        if (str.length() > 0) {
-            writer.append(str.toString());
-        }
-        String description = displayField.getDescription(context);
-        //Replace new lines with <br/>
-        description = description.replaceAll("\n", "<br/>");
-
-        if (UtilValidate.isEmpty(description)) {
-            this.renderFormatEmptySpace(writer, context, modelFormField.getModelForm());
-        } else {
-            writer.append(description);
-        }
-
-        if (str.length() > 0) {
-            writer.append("</span>");
-        }
-
-        ModelFormField.InPlaceEditor inPlaceEditor = displayField.getInPlaceEditor();
-        boolean ajaxEnabled = inPlaceEditor != null && this.javaScriptEnabled;
-
-        if (ajaxEnabled) {
-            writer.append("<script language=\"JavaScript\" type=\"text/javascript\">");
-            StringBuilder url = new StringBuilder(inPlaceEditor.getUrl(context));
-            Map<String, Object> fieldMap = inPlaceEditor.getFieldMap(context);
-            if (fieldMap != null) {
-                url.append('?');
-                int count = 0;
-                for (Entry<String, Object> field: fieldMap.entrySet()) {
-                    count++;
-                    url.append(field.getKey()).append('=').append(field.getValue());
-                    if (count < fieldMap.size()) {
-                        url.append('&');
-                    }
-                }
-            }
-            writer.append("ajaxInPlaceEditDisplayField('");
-            writer.append(idName).append("', '").append(url).append("', {");
-            if (UtilValidate.isNotEmpty(inPlaceEditor.getParamName())) {
-                writer.append("name: '").append(inPlaceEditor.getParamName()).append("'");
-            } else {
-                writer.append("name: '").append(modelFormField.getFieldName()).append("'");
-            }
-            if (UtilValidate.isNotEmpty(inPlaceEditor.getCancelControl())) {
-                writer.append(", cancelControl: ");
-                if (!"false".equals(inPlaceEditor.getCancelControl())) {
-                    writer.append("'");
-                }
-                writer.append(inPlaceEditor.getCancelControl());
-                if (!"false".equals(inPlaceEditor.getCancelControl())) {
-                    writer.append("'");
-                }
-            }
-            if (UtilValidate.isNotEmpty(inPlaceEditor.getCancelText())) {
-                writer.append(", cancel: '").append(inPlaceEditor.getCancelText()).append("'");
-            }
-            if (UtilValidate.isNotEmpty(inPlaceEditor.getClickToEditText())) {
-                writer.append(", tooltip: '").append(inPlaceEditor.getClickToEditText()).append("'");
-            }
-            if (UtilValidate.isNotEmpty(inPlaceEditor.getFieldPostCreation())) {
-                writer.append(", fieldPostCreation: ");
-                if (!"false".equals(inPlaceEditor.getFieldPostCreation())) {
-                    writer.append("'");
-                }
-                writer.append(inPlaceEditor.getFieldPostCreation());
-                if (!"false".equals(inPlaceEditor.getFieldPostCreation())) {
-                    writer.append("'");
-                }
-            }
-            if (UtilValidate.isNotEmpty(inPlaceEditor.getFormClassName())) {
-                writer.append(", cssclass: '").append(inPlaceEditor.getFormClassName()).append("'");
-            }
-            if (UtilValidate.isNotEmpty(inPlaceEditor.getHighlightColor())) {
-                writer.append(", highlightColor: '").append(inPlaceEditor.getHighlightColor()).append("'");
-            }
-            if (UtilValidate.isNotEmpty(inPlaceEditor.getHighlightEndColor())) {
-                writer.append(", highlightEndColor: '").append(inPlaceEditor.getHighlightEndColor()).append("'");
-            }
-            if (UtilValidate.isNotEmpty(inPlaceEditor.getHoverClassName())) {
-                writer.append(", hoverClassName: '").append(inPlaceEditor.getHoverClassName()).append("'");
-            }
-            if (UtilValidate.isNotEmpty(inPlaceEditor.getHtmlResponse())) {
-                writer.append(", htmlResponse: ").append(inPlaceEditor.getHtmlResponse());
-            }
-            if (UtilValidate.isNotEmpty(inPlaceEditor.getLoadingClassName())) {
-                writer.append(", loadingClassName: '").append(inPlaceEditor.getLoadingClassName()).append("'");
-            }
-            if (UtilValidate.isNotEmpty(inPlaceEditor.getLoadingText())) {
-                writer.append(", indicator: '").append(inPlaceEditor.getLoadingText()).append("'");
-            }
-            if (UtilValidate.isNotEmpty(inPlaceEditor.getOkControl())) {
-                writer.append(", submit: ");
-                if (!"false".equals(inPlaceEditor.getOkControl())) {
-                    writer.append("'");
-                }
-                writer.append(inPlaceEditor.getOkControl());
-                if (!"false".equals(inPlaceEditor.getOkControl())) {
-                    writer.append("'");
-                }
-            }
-            if (UtilValidate.isNotEmpty(inPlaceEditor.getOkText())) {
-                writer.append(", okText: '").append(inPlaceEditor.getOkText()).append("'");
-            }
-            if (UtilValidate.isNotEmpty(inPlaceEditor.getSavingClassName())) {
-                writer.append(", savingClassName: '").append(inPlaceEditor.getSavingClassName()).append("', ");
-            }
-            if (UtilValidate.isNotEmpty(inPlaceEditor.getSavingText())) {
-                writer.append(", savingText: '").append(inPlaceEditor.getSavingText()).append("'");
-            }
-            if (UtilValidate.isNotEmpty(inPlaceEditor.getSubmitOnBlur())) {
-                writer.append(", submitOnBlur: ").append(inPlaceEditor.getSubmitOnBlur());
-            }
-            if (UtilValidate.isNotEmpty(inPlaceEditor.getTextBeforeControls())) {
-                writer.append(", textBeforeControls: '").append(inPlaceEditor.getTextBeforeControls()).append("'");
-            }
-            if (UtilValidate.isNotEmpty(inPlaceEditor.getTextAfterControls())) {
-                writer.append(", textAfterControls: '").append(inPlaceEditor.getTextAfterControls()).append("'");
-            }
-            if (UtilValidate.isNotEmpty(inPlaceEditor.getTextBetweenControls())) {
-                writer.append(", textBetweenControls: '").append(inPlaceEditor.getTextBetweenControls()).append("'");
-            }
-            if (UtilValidate.isNotEmpty(inPlaceEditor.getUpdateAfterRequestCall())) {
-                writer.append(", updateAfterRequestCall: ").append(inPlaceEditor.getUpdateAfterRequestCall());
-            }
-            if (UtilValidate.isNotEmpty(inPlaceEditor.getRows())) {
-                writer.append(", rows: '").append(inPlaceEditor.getRows()).append("'");
-            }
-            if (UtilValidate.isNotEmpty(inPlaceEditor.getCols())) {
-                writer.append(", cols: '").append(inPlaceEditor.getCols()).append("'");
-            }
-            writer.append("});");
-            writer.append("</script>");
-        }
-
-        if (displayField instanceof DisplayEntityField) {
-            this.makeHyperlinkString(writer, ((DisplayEntityField) displayField).getSubHyperlink(), context);
-        }
-
-        this.appendTooltip(writer, context, modelFormField);
-
-        //appendWhitespace(writer);
-    }
-
-    /* (non-Javadoc)
-     * @see org.ofbiz.widget.form.FormStringRenderer#renderHyperlinkField(java.io.Writer, java.util.Map, org.ofbiz.widget.form.ModelFormField.HyperlinkField)
-     */
-    public void renderHyperlinkField(Appendable writer, Map<String, Object> context, HyperlinkField hyperlinkField) throws IOException {
-        this.request.setAttribute("image", hyperlinkField.getImageLocation(context));
-        ModelFormField modelFormField = hyperlinkField.getModelFormField();
-        String description = encode(hyperlinkField.getDescription(context), modelFormField, context);
-        String confirmation = encode(hyperlinkField.getConfirmation(context), modelFormField, context);
-        WidgetWorker.makeHyperlinkByType(writer, hyperlinkField.getLinkType(), modelFormField.getWidgetStyle(), hyperlinkField.getUrlMode(), hyperlinkField.getTarget(context),
-                hyperlinkField.getParameterMap(context), description, hyperlinkField.getTargetWindow(context), confirmation, modelFormField,
-                this.request, this.response, context);
-        this.appendTooltip(writer, context, modelFormField);
-        //appendWhitespace(writer);
-    }
-
-    public void makeHyperlinkString(Appendable writer, ModelFormField.SubHyperlink subHyperlink, Map<String, Object> context) throws IOException {
-        if (subHyperlink == null) {
-            return;
-        }
-        if (subHyperlink.shouldUse(context)) {
-            writer.append(' ');
-            String description = encode(subHyperlink.getDescription(context), subHyperlink.getModelFormField(), context);
-            WidgetWorker.makeHyperlinkByType(writer, subHyperlink.getLinkType(), subHyperlink.getStyle(context), subHyperlink.getUrlMode(), subHyperlink.getTarget(context),
-                    subHyperlink.getParameterMap(context), description, subHyperlink.getTargetWindow(context), null, subHyperlink.getModelFormField(),
-                    this.request, this.response, context);
-        }
-    }
-
-    private String encode(String value, ModelFormField modelFormField, Map<String, Object> context) {
-        if (UtilValidate.isEmpty(value)) {
-            return value;
-        }
-        UtilCodec.SimpleEncoder encoder = (UtilCodec.SimpleEncoder)context.get("simpleEncoder");
-        if (modelFormField.getEncodeOutput() && encoder != null) {
-            value = encoder.encode(value);
-        } else {
-            value = internalEncoder.encode(value);
-        }
-        return value;
-    }
-
-    /* (non-Javadoc)
-     * @see org.ofbiz.widget.form.FormStringRenderer#renderTextField(java.io.Writer, java.util.Map, org.ofbiz.widget.form.ModelFormField.TextField)
-     */
-    public void renderTextField(Appendable writer, Map<String, Object> context, TextField textField) throws IOException {
-        ModelFormField modelFormField = textField.getModelFormField();
-
-        writer.append("<input type=\"text\"");
-
-        appendClassNames(writer, context, modelFormField);
-
-        writer.append(" name=\"");
-        writer.append(modelFormField.getParameterName(context));
-        writer.append('"');
-
-        String value = modelFormField.getEntry(context, textField.getDefaultValue(context));
-        if (UtilValidate.isNotEmpty(value)) {
-            writer.append(" value=\"");
-            writer.append(value);
-            writer.append('"');
-        }
-
-        writer.append(" size=\"");
-        writer.append(Integer.toString(textField.getSize()));
-        writer.append('"');
-
-        Integer maxlength = textField.getMaxlength();
-        if (maxlength != null) {
-            writer.append(" maxlength=\"");
-            writer.append(maxlength.toString());
-            writer.append('"');
-        }
-
-        String idName = modelFormField.getCurrentContainerId(context);
-        if (UtilValidate.isNotEmpty(idName)) {
-            writer.append(" id=\"");
-            writer.append(idName);
-            writer.append('"');
-        }
-
-        String event = modelFormField.getEvent();
-        String action = modelFormField.getAction(context);
-        if (UtilValidate.isNotEmpty(event) && UtilValidate.isNotEmpty(action)) {
-            writer.append(" ");
-            writer.append(event);
-            writer.append("=\"");
-            writer.append(action);
-            writer.append('"');
-        }
-
-        List<ModelForm.UpdateArea> updateAreas = modelFormField.getOnChangeUpdateAreas();
-        boolean ajaxEnabled = updateAreas != null && this.javaScriptEnabled;
-        if (!textField.getClientAutocompleteField() || ajaxEnabled) {
-            writer.append(" autocomplete=\"off\"");
-        }
-
-        writer.append("/>");
-
-        this.addAsterisks(writer, context, modelFormField);
-
-        this.makeHyperlinkString(writer, textField.getSubHyperlink(), context);
-
-        this.appendTooltip(writer, context, modelFormField);
-
-        if (ajaxEnabled) {
-            appendWhitespace(writer);
-            writer.append("<script language=\"JavaScript\" type=\"text/javascript\">");
-            appendWhitespace(writer);
-            writer.append("ajaxAutoCompleter('").append(createAjaxParamsFromUpdateAreas(updateAreas, null, context)).append("');");
-            appendWhitespace(writer);
-            writer.append("</script>");
-        }
-        appendWhitespace(writer);
-    }
-
-    /* (non-Javadoc)
-     * @see org.ofbiz.widget.form.FormStringRenderer#renderTextareaField(java.io.Writer, java.util.Map, org.ofbiz.widget.form.ModelFormField.TextareaField)
-     */
-    public void renderTextareaField(Appendable writer, Map<String, Object> context, TextareaField textareaField) throws IOException {
-        ModelFormField modelFormField = textareaField.getModelFormField();
-
-        writer.append("<textarea");
-
-        appendClassNames(writer, context, modelFormField);
-
-        writer.append(" name=\"");
-        writer.append(modelFormField.getParameterName(context));
-        writer.append('"');
-
-        writer.append(" cols=\"");
-        writer.append(Integer.toString(textareaField.getCols()));
-        writer.append('"');
-
-        writer.append(" rows=\"");
-        writer.append(Integer.toString(textareaField.getRows()));
-        writer.append('"');
-
-        String idName = modelFormField.getCurrentContainerId(context);
-        if (UtilValidate.isNotEmpty(idName)) {
-            writer.append(" id=\"");
-            writer.append(idName);
-            writer.append('"');
-        } else if (textareaField.getVisualEditorEnable()) {
-            writer.append(" id=\"");
-            writer.append("htmlEditArea");
-            writer.append('"');
-        }
-
-        if (textareaField.isReadOnly()) {
-            writer.append(" readonly");
-        }
-
-        writer.append('>');
-
-        String value = modelFormField.getEntry(context, textareaField.getDefaultValue(context));
-        if (UtilValidate.isNotEmpty(value)) {
-            writer.append(value);
-        }
-
-        writer.append("</textarea>");
-
-        if (textareaField.getVisualEditorEnable()) {
-            writer.append("<script language=\"javascript\" src=\"/images/jquery/plugins/elrte-1.3/js/elrte.min.js\" type=\"text/javascript\"></script>");
-            writer.append("<link href=\"/images/jquery/plugins/elrte-1.3/css/elrte.min.css\" rel=\"stylesheet\" type=\"text/css\">");
-            writer.append("<script language=\"javascript\" type=\"text/javascript\"> var opts = { cssClass : 'el-rte', toolbar : ");
-            // define the toolsbar
-            String buttons = textareaField.getVisualEditorButtons(context);
-            if (UtilValidate.isNotEmpty(buttons)) {
-                writer.append(buttons);
-            } else {
-                writer.append("maxi");
-            }
-            writer.append(", doctype  : '<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">', //'<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\">'");
-            writer.append(", cssfiles : ['/images/jquery/plugins/elrte-1.3/css/elrte-inner.css'] ");
-            writer.append("}");
-            // load the wysiwyg editor
-            writer.append("jQuery('#");
-            if (UtilValidate.isNotEmpty(idName)) {
-                writer.append(idName);
-            } else {
-                writer.append("htmlEditArea");
-            }
-            writer.append("').elrte(opts);");
-            writer.append("</script>");
-        }
-
-        this.addAsterisks(writer, context, modelFormField);
-
-        this.appendTooltip(writer, context, modelFormField);
-
-        //appendWhitespace(writer);
-    }
-
-    /* (non-Javadoc)
-     * @see org.ofbiz.widget.form.FormStringRenderer#renderDateTimeField(java.io.Writer, java.util.Map, org.ofbiz.widget.form.ModelFormField.DateTimeField)
-     */
-    public void renderDateTimeField(Appendable writer, Map<String, Object> context, DateTimeField dateTimeField) throws IOException {
-        String macroLibraryPath = UtilProperties.getPropertyValue("widget", "screen.formrenderer");
-        try {
-            MacroFormRenderer macroFormRenderer = new MacroFormRenderer(macroLibraryPath, this.request, this.response);
-            macroFormRenderer.renderDateTimeField(writer, context, dateTimeField);
-        } catch (TemplateException e) {
-            Debug.logError(e, "Error rendering screen thru ftl macro: renderDateTimeField", module);
-        } catch (IOException e) {
-            Debug.logError(e, "Error rendering screen thru ftl, macro: renderDateTimeField", module);
-        }
-    }
-
-    /* (non-Javadoc)
-     * @see org.ofbiz.widget.form.FormStringRenderer#renderDropDownField(java.io.Writer, java.util.Map, org.ofbiz.widget.form.ModelFormField.DropDownField)
-     */
-    public void renderDropDownField(Appendable writer, Map<String, Object> context, DropDownField dropDownField) throws IOException {
-        ModelFormField modelFormField = dropDownField.getModelFormField();
-        ModelForm modelForm = modelFormField.getModelForm();
-        ModelFormField.AutoComplete autoComplete = dropDownField.getAutoComplete();
-        boolean ajaxEnabled = autoComplete != null && this.javaScriptEnabled;
-        List<ModelFormField.OptionValue> allOptionValues = dropDownField.getAllOptionValues(context, WidgetWorker.getDelegator(context));
-
-        String event = modelFormField.getEvent();
-        String action = modelFormField.getAction(context);
-
-        String currentValue = modelFormField.getEntry(context);
-        // Get the current value's description from the option value. If there
-        // is a localized version it will be there.
-        String currentDescription = null;
-        if (UtilValidate.isNotEmpty(currentValue)) {
-            for (ModelFormField.OptionValue optionValue : allOptionValues) {
-                if (encode(optionValue.getKey(), modelFormField, context).equals(currentValue)) {
-                    currentDescription = optionValue.getDescription();
-                    break;
-                }
-            }
-        }
-
-        if (ajaxEnabled) {
-            writer.append("<input type=\"text\"");
-        } else {
-            writer.append("<select");
-        }
-
-        appendClassNames(writer, context, modelFormField);
-
-        writer.append(" name=\"");
-        writer.append(modelFormField.getParameterName(context));
-
-        String idName = modelFormField.getCurrentContainerId(context);
-
-        if (ajaxEnabled) {
-            writer.append("_description\"");
-
-            String textFieldIdName = idName;
-            if (UtilValidate.isNotEmpty(textFieldIdName)) {
-                textFieldIdName += "_description";
-                writer.append(" id=\"");
-                writer.append(textFieldIdName);
-                writer.append('"');
-            }
-
-            if (UtilValidate.isNotEmpty(currentValue)) {
-                writer.append(" value=\"");
-                String explicitDescription = null;
-                if (currentDescription != null) {
-                    explicitDescription = currentDescription;
-                } else {
-                    explicitDescription = dropDownField.getCurrentDescription(context);
-                }
-                if (UtilValidate.isEmpty(explicitDescription)) {
-                    explicitDescription = FieldInfoWithOptions.getDescriptionForOptionKey(currentValue, allOptionValues);
-                }
-                explicitDescription = encode(explicitDescription, modelFormField, context);
-                writer.append(explicitDescription);
-                writer.append('"');
-            }
-            writer.append("/>");
-
-            appendWhitespace(writer);
-            writer.append("<input type=\"hidden\" name=\"");
-            writer.append(modelFormField.getParameterName(context));
-            writer.append('"');
-            if (UtilValidate.isNotEmpty(idName)) {
-                writer.append(" id=\"");
-                writer.append(idName);
-                writer.append('"');
-            }
-
-            if (UtilValidate.isNotEmpty(currentValue)) {
-                writer.append(" value=\"");
-                //String explicitDescription = dropDownField.getCurrentDescription(context);
-                writer.append(currentValue);
-                writer.append('"');
-            }
-
-            writer.append("/>");
-
-            appendWhitespace(writer);
-            writer.append("<script language=\"JavaScript\" type=\"text/javascript\">");
-            appendWhitespace(writer);
-            writer.append("var data = {");
-            int count = 0;
-            for (ModelFormField.OptionValue optionValue: allOptionValues) {
-                count++;
-                writer.append(optionValue.getKey()).append(": ");
-                writer.append(" '").append(optionValue.getDescription()).append("'");
-                if (count != allOptionValues.size()) {
-                    writer.append(", ");
-                }
-            }
-            writer.append("};");
-            appendWhitespace(writer);
-            writer.append("ajaxAutoCompleteDropDown('").append(textFieldIdName).append("', '").append(idName).append("', data, {autoSelect: ").append(
-                    autoComplete.getAutoSelect()).append(", frequency: ").append(autoComplete.getFrequency()).append(", minChars: ").append(autoComplete.getMinChars()).append(
-                    ", choices: ").append(autoComplete.getChoices()).append(", partialSearch: ").append(autoComplete.getPartialSearch()).append(
-                    ", partialChars: ").append(autoComplete.getPartialChars()).append(", ignoreCase: ").append(autoComplete.getIgnoreCase()).append(
-                    ", fullSearch: ").append(autoComplete.getFullSearch()).append("});");
-            appendWhitespace(writer);
-            writer.append("</script>");
-        } else {
-            writer.append('"');
-
-            if (UtilValidate.isNotEmpty(idName)) {
-                writer.append(" id=\"");
-                writer.append(idName);
-                writer.append('"');
-            }
-
-            if (dropDownField.getAllowMultiple()) {
-                writer.append(" multiple=\"multiple\"");
-            }
-
-            int otherFieldSize = dropDownField.getOtherFieldSize();
-            String otherFieldName = dropDownField.getParameterNameOther(context);
-            if (otherFieldSize > 0) {
-                //writer.append(" onchange=\"alert('ONCHANGE, process_choice:' + process_choice)\"");
-                //writer.append(" onchange='test_js()' ");
-                writer.append(" onchange=\"process_choice(this,document.");
-                writer.append(modelForm.getName());
-                writer.append(".");
-                writer.append(otherFieldName);
-                writer.append(")\" ");
-            }
-
-            if (UtilValidate.isNotEmpty(event) && UtilValidate.isNotEmpty(action)) {
-                writer.append(" ");
-                writer.append(event);
-                writer.append("=\"");
-                writer.append(action);
-                writer.append('"');
-            }
-
-            writer.append(" size=\"").append(dropDownField.getSize()).append("\">");
-
-            // if the current value should go first, stick it in
-            if (UtilValidate.isNotEmpty(currentValue) && "first-in-list".equals(dropDownField.getCurrent())) {
-                writer.append("<option");
-                writer.append(" selected=\"selected\"");
-                writer.append(" value=\"");
-                writer.append(currentValue);
-                writer.append("\">");
-                String explicitDescription = (currentDescription != null ? currentDescription : dropDownField.getCurrentDescription(context));
-                if (UtilValidate.isNotEmpty(explicitDescription)) {
-                    writer.append(encode(explicitDescription, modelFormField, context));
-                } else {
-                    String description = FieldInfoWithOptions.getDescriptionForOptionKey(currentValue, allOptionValues);
-                    writer.append(encode(description, modelFormField, context));
-                }
-                writer.append("</option>");
-
-                // add a "separator" option
-                writer.append("<option value=\"");
-                writer.append(currentValue);
-                writer.append("\">---</option>");
-            }
-
-            // if allow empty is true, add an empty option
-            if (dropDownField.getAllowEmpty()) {
-                writer.append("<option value=\"\">&nbsp;</option>");
-            }
-
-            // list out all options according to the option list
-            for (ModelFormField.OptionValue optionValue: allOptionValues) {
-                String noCurrentSelectedKey = dropDownField.getNoCurrentSelectedKey(context);
-                writer.append("<option");
-                // if current value should be selected in the list, select it
-                if (UtilValidate.isNotEmpty(currentValue) && currentValue.equals(optionValue.getKey()) && "selected".equals(dropDownField.getCurrent())) {
-                    writer.append(" selected=\"selected\"");
-                } else if (UtilValidate.isEmpty(currentValue) && noCurrentSelectedKey != null && noCurrentSelectedKey.equals(optionValue.getKey())) {
-                    writer.append(" selected=\"selected\"");
-                }
-                writer.append(" value=\"");
-                writer.append(encode(optionValue.getKey(), modelFormField, context));
-                writer.append("\">");
-                writer.append(encode(optionValue.getDescription(), modelFormField, context));
-                writer.append("</option>");
-            }
-
-            writer.append("</select>");
-
-
-            // Adapted from work by Yucca Korpela
-            // http://www.cs.tut.fi/~jkorpela/forms/combo.html
-            if (otherFieldSize > 0) {
-
-                String fieldName = modelFormField.getParameterName(context);
-                Map<String, Object> dataMap = UtilGenerics.checkMap(modelFormField.getMap(context));
-                if (dataMap == null) {
-                    dataMap = context;
-                }
-                Object otherValueObj = dataMap.get(otherFieldName);
-                String otherValue = (otherValueObj == null) ? "" : otherValueObj.toString();
-
-                writer.append("<noscript>");
-                writer.append("<input type='text' name='");
-                writer.append(otherFieldName);
-                writer.append("'/> ");
-                writer.append("</noscript>");
-                writer.append("\n<script type='text/javascript' language='JavaScript'><!--");
-                writer.append("\ndisa = ' disabled';");
-                writer.append("\nif (other_choice(document.");
-                writer.append(modelForm.getName());
-                writer.append(".");
-                writer.append(fieldName);
-                writer.append(")) disa = '';");
-                writer.append("\ndocument.write(\"<input type=");
-                writer.append("'text' name='");
-                writer.append(otherFieldName);
-                writer.append("' value='");
-                writer.append(otherValue);
-                writer.append("' size='");
-                writer.append(Integer.toString(otherFieldSize));
-                writer.append("' ");
-                writer.append("\" +disa+ \" onfocus='check_choice(document.");
-                writer.append(modelForm.getName());
-                writer.append(".");
-                writer.append(fieldName);
-                writer.append(")'/>\");");
-                writer.append("\nif (disa && document.styleSheets)");
-                writer.append(" document.");
-                writer.append(modelForm.getName());
-                writer.append(".");
-                writer.append(otherFieldName);
-                writer.append(".style.visibility  = 'hidden';");
-                writer.append("\n//--></script>");
-            }
-        }
-
-        this.makeHyperlinkString(writer, dropDownField.getSubHyperlink(), context);
-
-        this.appendTooltip(writer, context, modelFormField);
-
-        //appendWhitespace(writer);
-    }
-
-    /* (non-Javadoc)
-     * @see org.ofbiz.widget.form.FormStringRenderer#renderCheckField(java.io.Writer, java.util.Map, org.ofbiz.widget.form.ModelFormField.CheckField)
-     */
-    public void renderCheckField(Appendable writer, Map<String, Object> context, CheckField checkField) throws IOException {
-        ModelFormField modelFormField = checkField.getModelFormField();
-        String currentValue = modelFormField.getEntry(context);
-        Boolean allChecked = checkField.isAllChecked(context);
-
-        List<ModelFormField.OptionValue> allOptionValues = checkField.getAllOptionValues(context, WidgetWorker.getDelegator(context));
-        String event = modelFormField.getEvent();
-        String action = modelFormField.getAction(context);
-
-        // list out all options according to the option list
-        for (ModelFormField.OptionValue optionValue: allOptionValues) {
-
-            writer.append("<input type=\"checkbox\"");
-
-            appendClassNames(writer, context, modelFormField);
-
-            // if current value should be selected in the list, select it
-            if (Boolean.TRUE.equals(allChecked)) {
-                writer.append(" checked=\"checked\"");
-            } else if (Boolean.FALSE.equals(allChecked)) {
-                // do nothing
-            } else if (UtilValidate.isNotEmpty(currentValue) && currentValue.equals(optionValue.getKey())) {
-                writer.append(" checked=\"checked\"");
-            }
-            writer.append(" name=\"");
-            writer.append(modelFormField.getParameterName(context));
-            writer.append('"');
-            writer.append(" value=\"");
-            writer.append(encode(optionValue.getKey(), modelFormField, context));
-            writer.append("\"");
-
-            if (UtilValidate.isNotEmpty(event) && UtilValidate.isNotEmpty(action)) {
-                writer.append(" ");
-                writer.append(event);
-                writer.append("=\"");
-                writer.append(action);
-                writer.append('"');
-            }
-
-            writer.append("/>");
-
-            writer.append(encode(optionValue.getDescription(), modelFormField, context));
-        }
-
-        this.appendTooltip(writer, context, modelFormField);
-
-        //appendWhitespace(writer);
-    }
-
-    /* (non-Javadoc)
-     * @see org.ofbiz.widget.form.FormStringRenderer#renderRadioField(java.io.Writer, java.util.Map, org.ofbiz.widget.form.ModelFormField.RadioField)
-     */
-    public void renderRadioField(Appendable writer, Map<String, Object> context, RadioField radioField) throws IOException {
-        ModelFormField modelFormField = radioField.getModelFormField();
-        List<ModelFormField.OptionValue> allOptionValues = radioField.getAllOptionValues(context, WidgetWorker.getDelegator(context));
-        String currentValue = modelFormField.getEntry(context);
-        String event = modelFormField.getEvent();
-        String action = modelFormField.getAction(context);
-
-        // list out all options according to the option list
-        for (ModelFormField.OptionValue optionValue: allOptionValues) {
-
-            writer.append("<span");
-
-            appendClassNames(writer, context, modelFormField);
-
-            writer.append("><input type=\"radio\"");
-
-            // if current value should be selected in the list, select it
-            String noCurrentSelectedKey = radioField.getNoCurrentSelectedKey(context);
-            if (UtilValidate.isNotEmpty(currentValue) && currentValue.equals(optionValue.getKey())) {
-                writer.append(" checked=\"checked\"");
-            } else if (UtilValidate.isEmpty(currentValue) && noCurrentSelectedKey != null && noCurrentSelectedKey.equals(optionValue.getKey())) {
-                writer.append(" checked=\"checked\"");
-            }
-            writer.append(" name=\"");
-            writer.append(modelFormField.getParameterName(context));
-            writer.append('"');
-            writer.append(" value=\"");
-            writer.append(encode(optionValue.getKey(), modelFormField, context));
-            writer.append("\"");
-
-            if (UtilValidate.isNotEmpty(event) && UtilValidate.isNotEmpty(action)) {
-                writer.append(" ");
-                writer.append(event);
-                writer.append("=\"");
-                writer.append(action);
-                writer.append('"');
-            }
-
-            writer.append("/>");
-
-            writer.append(encode(optionValue.getDescription(), modelFormField, context));
-            writer.append("</span>");
-        }
-
-        this.appendTooltip(writer, context, modelFormField);
-
-        //appendWhitespace(writer);
-    }
-
-    /* (non-Javadoc)
-     * @see org.ofbiz.widget.form.FormStringRenderer#renderSubmitField(java.io.Writer, java.util.Map, org.ofbiz.widget.form.ModelFormField.SubmitField)
-     */
-    public void renderSubmitField(Appendable writer, Map<String, Object> context, SubmitField submitField) throws IOException {
-        ModelFormField modelFormField = submitField.getModelFormField();
-        ModelForm modelForm = modelFormField.getModelForm();
-        String event = null;
-        String action = null;
-        String confirmation =  encode(submitField.getConfirmation(context), modelFormField, context);
-
-        if ("text-link".equals(submitField.getButtonType())) {
-            writer.append("<a");
-
-            appendClassNames(writer, context, modelFormField);
-            if (UtilValidate.isNotEmpty(confirmation)) {
-                writer.append(" onclick=\"return confirm('");
-                writer.append(confirmation);
-                writer.append("'); \" ");
-            }
-
-            writer.append(" href=\"javascript:document.");
-            writer.append(FormRenderer.getCurrentFormName(modelForm, context));
-            writer.append(".submit()\">");
-
-            writer.append(encode(modelFormField.getTitle(context), modelFormField, context));
-
-            writer.append("</a>");
-        } else if ("image".equals(submitField.getButtonType())) {
-            writer.append("<input type=\"image\"");
-
-            appendClassNames(writer, context, modelFormField);
-
-            writer.append(" name=\"");
-            writer.append(modelFormField.getParameterName(context));
-            writer.append('"');
-
-            String title = modelFormField.getTitle(context);
-            if (UtilValidate.isNotEmpty(title)) {
-                writer.append(" alt=\"");
-                writer.append(encode(title, modelFormField, context));
-                writer.append('"');
-            }
-
-            writer.append(" src=\"");
-            this.appendContentUrl(writer, submitField.getImageLocation(context));
-            writer.append('"');
-
-            event = modelFormField.getEvent();
-            action = modelFormField.getAction(context);
-            if (UtilValidate.isNotEmpty(event) && UtilValidate.isNotEmpty(action)) {
-                writer.append(" ");
-                writer.append(event);
-                writer.append("=\"");
-                writer.append(action);
-                writer.append('"');
-            }
-
-            if (UtilValidate.isNotEmpty(confirmation)) {
-                writer.append("onclick=\" return confirm('");
-                writer.append(confirmation);
-                writer.append("); \" ");
-            }
-
-            writer.append("/>");
-        } else {
-            // default to "button"
-
-            String formId = modelForm.getContainerId();
-            List<ModelForm.UpdateArea> updateAreas = modelForm.getOnSubmitUpdateAreas();
-            // This is here for backwards compatibility. Use on-event-update-area
-            // elements instead.
-            String backgroundSubmitRefreshTarget = submitField.getBackgroundSubmitRefreshTarget(context);
-            if (UtilValidate.isNotEmpty(backgroundSubmitRefreshTarget)) {
-                if (updateAreas == null) {
-                    updateAreas = new LinkedList<ModelForm.UpdateArea>();
-                }
-                updateAreas.add(new ModelForm.UpdateArea("submit", formId, backgroundSubmitRefreshTarget));
-            }
-
-            boolean ajaxEnabled = (UtilValidate.isNotEmpty(updateAreas) || UtilValidate.isNotEmpty(backgroundSubmitRefreshTarget)) && this.javaScriptEnabled;
-            if (ajaxEnabled) {
-                writer.append("<input type=\"button\"");
-            } else {
-                writer.append("<input type=\"submit\"");
-            }
-
-            appendClassNames(writer, context, modelFormField);
-
-            writer.append(" name=\"");
-            writer.append(modelFormField.getParameterName(context));
-            writer.append('"');
-
-            String title = modelFormField.getTitle(context);
-            if (UtilValidate.isNotEmpty(title)) {
-                writer.append(" value=\"");
-                writer.append(encode(title, modelFormField, context));
-                writer.append('"');
-            }
-
-
-            event = modelFormField.getEvent();
-            action = modelFormField.getAction(context);
-            if (UtilValidate.isNotEmpty(event) && UtilValidate.isNotEmpty(action)) {
-                writer.append(" ");
-                writer.append(event);
-                writer.append("=\"");
-                writer.append(action);
-                writer.append('"');
-            } else {
-                //add single click JS onclick
-                // disabling for now, using form onSubmit action instead: writer.append(singleClickAction);
-            }
-
-            if (ajaxEnabled) {
-                writer.append(" onclick=\"");
-                if (UtilValidate.isNotEmpty(confirmation)) {
-                    writer.append("if  (confirm('");
-                    writer.append(confirmation);
-                    writer.append(");) ");
-                }
-                writer.append("ajaxSubmitFormUpdateAreas('");
-                writer.append(formId);
-                writer.append("', '").append(createAjaxParamsFromUpdateAreas(updateAreas, null, context));
-                writer.append("')\"");
-            }
-
-            writer.append("/>");
-        }
-
-        this.appendTooltip(writer, context, modelFormField);
-
-        //appendWhitespace(writer);
-    }
-
-    /* (non-Javadoc)
-     * @see org.ofbiz.widget.form.FormStringRenderer#renderResetField(java.io.Writer, java.util.Map, org.ofbiz.widget.form.ModelFormField.ResetField)
-     */
-    public void renderResetField(Appendable writer, Map<String, Object> context, ResetField resetField) throws IOException {
-        ModelFormField modelFormField = resetField.getModelFormField();
-
-        writer.append("<input type=\"reset\"");
-
-        appendClassNames(writer, context, modelFormField);
-
-        writer.append(" name=\"");
-        writer.append(modelFormField.getParameterName(context));
-        writer.append('"');
-
-        String title = modelFormField.getTitle(context);
-        if (UtilValidate.isNotEmpty(title)) {
-            writer.append(" value=\"");
-            writer.append(encode(title, modelFormField, context));
-            writer.append('"');
-        }
-
-        writer.append("/>");
-
-        this.appendTooltip(writer, context, modelFormField);
-
-        //appendWhitespace(writer);
-    }
-
-    /* (non-Javadoc)
-     * @see org.ofbiz.widget.form.FormStringRenderer#renderHiddenField(java.io.Writer, java.util.Map, org.ofbiz.widget.form.ModelFormField.HiddenField)
-     */
-    public void renderHiddenField(Appendable writer, Map<String, Object> context, HiddenField hiddenField) throws IOException {
-        ModelFormField modelFormField = hiddenField.getModelFormField();
-        String value = hiddenField.getValue(context);
-        this.renderHiddenField(writer, context, modelFormField, value);
-    }
-
-    public void renderHiddenField(Appendable writer, Map<String, Object> context, ModelFormField modelFormField, String value) throws IOException {
-        writer.append("<input type=\"hidden\"");
-
-        writer.append(" name=\"");
-        writer.append(modelFormField.getParameterName(context));
-        writer.append('"');
-
-        if (UtilValidate.isNotEmpty(value)) {
-            writer.append(" value=\"");
-            writer.append(value);
-            writer.append('"');
-        }
-
-        writer.append("/>");
-        appendWhitespace(writer);
-    }
-
-    /* (non-Javadoc)
-     * @see org.ofbiz.widget.form.FormStringRenderer#renderIgnoredField(java.io.Writer, java.util.Map, org.ofbiz.widget.form.ModelFormField.IgnoredField)
-     */
-    public void renderIgnoredField(Appendable writer, Map<String, Object> context, IgnoredField ignoredField) throws IOException {
-        // do nothing, it's an ignored field; could add a comment or something if we wanted to
-    }
-
-    /* (non-Javadoc)
-     * @see org.ofbiz.widget.form.FormStringRenderer#renderFieldTitle(java.io.Writer, java.util.Map, org.ofbiz.widget.form.ModelFormField)
-     */
-    public void renderFieldTitle(Appendable writer, Map<String, Object> context, ModelFormField modelFormField) throws IOException {
-        String tempTitleText = modelFormField.getTitle(context);
-        String titleText = UtilHttp.encodeAmpersands(tempTitleText);
-
-        if (UtilValidate.isNotEmpty(titleText)) {
-            // copied from MacroFormRenderer renderFieldTitle
-            String displayHelpText = UtilProperties.getPropertyValue("widget.properties", "widget.form.displayhelpText");
-            String helpText = null;
-            if ("Y".equals(displayHelpText)) {
-                Delegator delegator = WidgetWorker.getDelegator(context);
-                Locale locale = (Locale)context.get("locale");
-                String entityName = modelFormField.getEntityName();
-                String fieldName = modelFormField.getFieldName();
-                helpText = UtilHelpText.getEntityFieldDescription(entityName, fieldName, delegator, locale);
-            }
-            if (UtilValidate.isNotEmpty(modelFormField.getTitleStyle()) || UtilValidate.isNotEmpty(helpText)) {
-                writer.append("<span");
-                if (UtilValidate.isNotEmpty(modelFormField.getTitleStyle())){
-                    writer.append(" class=\"");
-                    writer.append(modelFormField.getTitleStyle());
-                }
-                if (UtilValidate.isNotEmpty(helpText)){
-                    writer.append(" title=\"");
-                    writer.append(FreeMarkerWorker.encodeDoubleQuotes(helpText));
-                }
-                writer.append("\">");
-            }
-            if (" ".equals(titleText)) {
-                // If the title content is just a blank then render it colling renderFormatEmptySpace:
-                // the method will set its content to work fine in most browser
-                this.renderFormatEmptySpace(writer, context, modelFormField.getModelForm());
-            } else {
-                renderHyperlinkTitle(writer, context, modelFormField, titleText);
-            }
-
-            if (UtilValidate.isNotEmpty(modelFormField.getTitleStyle())) {
-                writer.append("</span>");
-            }
-
-            //appendWhitespace(writer);
-        }
-    }
-
-    /* (non-Javadoc)
-     * @see org.ofbiz.widget.form.FormStringRenderer#renderFieldTitle(java.io.Writer, java.util.Map, org.ofbiz.widget.form.ModelFormField)
-     */
-    public void renderSingleFormFieldTitle(Appendable writer, Map<String, Object> context, ModelFormField modelFormField) throws IOException {
-        boolean requiredField = modelFormField.getRequiredField();
-        if (requiredField) {
-
-            String requiredStyle = modelFormField.getRequiredFieldStyle();
-            if (UtilValidate.isEmpty(requiredStyle)) {
-                requiredStyle = modelFormField.getTitleStyle();
-            }
-
-            if (UtilValidate.isNotEmpty(requiredStyle)) {
-                writer.append("<span class=\"");
-                writer.append(requiredStyle);
-                writer.append("\">");
-            }
-            renderHyperlinkTitle(writer, context, modelFormField, modelFormField.getTitle(context));
-            if (UtilValidate.isNotEmpty(requiredStyle)) {
-                writer.append("</span>");
-            }
-
-            //appendWhitespace(writer);
-        } else {
-            renderFieldTitle(writer, context, modelFormField);
-        }
-    }
-
-    /* (non-Javadoc)
-     * @see org.ofbiz.widget.form.FormStringRenderer#renderFormOpen(java.io.Writer, java.util.Map, org.ofbiz.widget.form.ModelForm)
-     */
-    public void renderFormOpen(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {
-        this.widgetCommentsEnabled = ModelWidget.widgetBoundaryCommentsEnabled(context);
-        renderBeginningBoundaryComment(writer, "Form Widget - Form Element", modelForm);
-        writer.append("<form method=\"post\" ");
-        String targetType = modelForm.getTargetType();
-        String targ = modelForm.getTarget(context, targetType);
-        // The 'action' attribute is mandatory in a form definition,
-        // even if it is empty.
-        writer.append(" action=\"");
-        if (UtilValidate.isNotEmpty(targ)) {
-            //this.appendOfbizUrl(writer, "/" + targ);
-            WidgetWorker.buildHyperlinkUrl(writer, targ, targetType, null, null, false, false, true, request, response, context);
-        }
-        writer.append("\" ");
-
-        String formType = modelForm.getType();
-        if (formType.equals("upload")) {
-            writer.append(" enctype=\"multipart/form-data\"");
-        }
-
-        String targetWindow = modelForm.getTargetWindow(context);
-        if (UtilValidate.isNotEmpty(targetWindow)) {
-            writer.append(" target=\"");
-            writer.append(targetWindow);
-            writer.append("\"");
-        }
-
-        String containerId = FormRenderer.getCurrentContainerId(modelForm, context);
-        if (UtilValidate.isNotEmpty(containerId)) {
-            writer.append(" id=\"");
-            writer.append(containerId);
-            writer.append("\"");
-        }
-
-        writer.append(" class=\"");
-        String containerStyle =  modelForm.getContainerStyle();
-        if (UtilValidate.isNotEmpty(containerStyle)) {
-            writer.append(containerStyle);
-        } else {
-            writer.append("basic-form");
-        }
-        writer.append("\"");
-
-        writer.append(" onsubmit=\"javascript:submitFormDisableSubmits(this)\"");
-
-        if (!modelForm.getClientAutocompleteFields()) {
-            writer.append(" autocomplete=\"off\"");
-        }
-
-        writer.append(" name=\"");
-        writer.append(FormRenderer.getCurrentContainerId(modelForm, context));
-        writer.append("\">");
-
-        boolean useRowSubmit = modelForm.getUseRowSubmit();
-        if (useRowSubmit) {
-            writer.append("<input type=\"hidden\" name=\"_useRowSubmit\" value=\"Y\"/>");
-        }
-
-        appendWhitespace(writer);
-    }
-
-    /* (non-Javadoc)
-     * @see org.ofbiz.widget.form.FormStringRenderer#renderFormClose(java.io.Writer, java.util.Map, org.ofbiz.widget.form.ModelForm)
-     */
-    public void renderFormClose(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {
-        writer.append("</form>");
-        String focusFieldName = FormRenderer.getFocusFieldName(modelForm, context);
-        if (UtilValidate.isNotEmpty(focusFieldName)) {
-            appendWhitespace(writer);
-            writer.append("<script language=\"JavaScript\" type=\"text/javascript\">");
-            appendWhitespace(writer);
-            writer.append("document.").append(FormRenderer.getCurrentFormName(modelForm, context)).append(".");
-            writer.append(focusFieldName).append(".focus();");
-            appendWhitespace(writer);
-            writer.append("</script>");
-        }
-        appendWhitespace(writer);
-        renderEndingBoundaryComment(writer, "Form Widget - Form Element", modelForm);
-    }
-
-    /* (non-Javadoc)
-     * @see org.ofbiz.widget.form.FormStringRenderer#renderFormClose(java.io.Writer, java.util.Map, org.ofbiz.widget.form.ModelForm)
-     */
-    public void renderMultiFormClose(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {
-        for (ModelFormField submitField: modelForm.getMultiSubmitFields()) {
-            if (submitField != null) {
-
-                // Threw this in that as a hack to keep the submit button from expanding the first field
-                // Needs a more rugged solution
-                // WARNING: this method (renderMultiFormClose) must be called after the
-                // table that contains the list has been closed (to avoid validation errors) so
-                // we cannot call here the methods renderFormatItemRowCell*: for this reason
-                // they are now commented.
-
-                // this.renderFormatItemRowCellOpen(writer, context, modelForm, submitField);
-                // this.renderFormatItemRowCellClose(writer, context, modelForm, submitField);
-
-                // this.renderFormatItemRowCellOpen(writer, context, modelForm, submitField);
-
-                submitField.renderFieldString(writer, context, this);
-
-                // this.renderFormatItemRowCellClose(writer, context, modelForm, submitField);
-
-            }
-        }
-        writer.append("</form>");
-        appendWhitespace(writer);
-
-        // see if there is anything that needs to be added outside of the multi-form
-        Map<String, Object> wholeFormContext = UtilGenerics.checkMap(context.get("wholeFormContext"));
-        Appendable postMultiFormWriter = wholeFormContext != null ? (Appendable) wholeFormContext.get("postMultiFormWriter") : null;
-        if (postMultiFormWriter != null) {
-            writer.append(postMultiFormWriter.toString());
-            appendWhitespace(writer);
-        }
-
-        renderEndingBoundaryComment(writer, "Form Widget - Form Element (Multi)", modelForm);
-    }
-
-    public void renderFormatListWrapperOpen(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {
-
-        Map<String, Object> inputFields = UtilGenerics.checkMap(context.get("requestParameters"));
-        Map<String, Object> queryStringMap = UtilGenerics.toMap(context.get("queryStringMap"));
-        if (UtilValidate.isNotEmpty(queryStringMap)) {
-            inputFields.putAll(queryStringMap);
-        }
-        if (modelForm.getType().equals("multi")) {
-            inputFields = UtilHttp.removeMultiFormParameters(inputFields);
-        }
-        String queryString = UtilHttp.urlEncodeArgs(inputFields);
-        context.put("_QBESTRING_", queryString);
-
-        this.widgetCommentsEnabled = ModelWidget.widgetBoundaryCommentsEnabled(context);
-        renderBeginningBoundaryComment(writer, "Form Widget", modelForm);
-
-        if (this.renderPagination) {
-            this.renderNextPrev(writer, context, modelForm);
-        }
-        writer.append(" <table cellspacing=\"0\" class=\"");
-        if (UtilValidate.isNotEmpty(modelForm.getDefaultTableStyle())) {
-            writer.append(FlexibleStringExpander.expandString(modelForm.getDefaultTableStyle(), context));
-        } else {
-            writer.append("basic-table form-widget-table dark-grid");
-        }
-        writer.append("\">");
-        appendWhitespace(writer);
-    }
-
-    public void renderFormatListWrapperClose(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {
-        writer.append(" </table>");
-
-        appendWhitespace(writer);
-        if (this.renderPagination) {
-            this.renderNextPrev(writer, context, modelForm);
-        }
-        renderEndingBoundaryComment(writer, "Form Widget - Formal List Wrapper", modelForm);
-    }
-
-    /* (non-Javadoc)
-     * @see org.ofbiz.widget.form.FormStringRenderer#renderFormatHeaderRowOpen(java.io.Writer, java.util.Map, org.ofbiz.widget.form.ModelForm)
-     */
-    public void renderFormatHeaderRowOpen(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {
-        writer.append("  <tr");
-        String headerStyle = FlexibleStringExpander.expandString(modelForm.getHeaderRowStyle(), context);
-        writer.append(" class=\"");
-        if (UtilValidate.isNotEmpty(headerStyle)) {
-            writer.append(headerStyle);
-        } else {
-            writer.append("header-row");
-        }
-        writer.append("\">");
-        appendWhitespace(writer);
-    }
-
-    /* (non-Javadoc)
-     * @see org.ofbiz.widget.form.FormStringRenderer#renderFormatHeaderRowClose(java.io.Writer, java.util.Map, org.ofbiz.widget.form.ModelForm)
-     */
-    public void renderFormatHeaderRowClose(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {
-        writer.append("  </tr>");
-
-        appendWhitespace(writer);
-    }
-
-    /* (non-Javadoc)
-     * @see org.ofbiz.widget.form.FormStringRenderer#renderFormatHeaderRowCellOpen(java.io.Writer, java.util.Map, org.ofbiz.widget.form.ModelForm, org.ofbiz.widget.form.ModelFormField, int positionSpan)
-     */
-    public void renderFormatHeaderRowCellOpen(Appendable writer, Map<String, Object> context, ModelForm modelForm, ModelFormField modelFormField, int positionSpan) throws IOException {
-        writer.append("   <td");
-        String areaStyle = modelFormField.getTitleAreaStyle();
-        if (positionSpan > 1) {
-            writer.append(" colspan=\"");
-            writer.append(Integer.toString(positionSpan));
-            writer.append("\"");
-        }
-        if (UtilValidate.isNotEmpty(areaStyle)) {
-            writer.append(" class=\"");
-            writer.append(areaStyle);
-            writer.append("\"");
-        }
-        writer.append(">");
-        //appendWhitespace(writer);
-    }
-
-    /* (non-Javadoc)
-     * @see org.ofbiz.widget.form.FormStringRenderer#renderFormatHeaderRowCellClose(java.io.Writer, java.util.Map, org.ofbiz.widget.form.ModelForm, org.ofbiz.widget.form.ModelFormField)
-     */
-    public void renderFormatHeaderRowCellClose(Appendable writer, Map<String, Object> context, ModelForm modelForm, ModelFormField modelFormField) throws IOException {
-        writer.append("</td>");
-        appendWhitespace(writer);
-    }
-
-    public void renderFormatHeaderRowFormCellOpen(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {
-        writer.append("   <td");
-        String areaStyle = modelForm.getFormTitleAreaStyle();
-        if (UtilValidate.isNotEmpty(areaStyle)) {
-            writer.append(" class=\"");
-            writer.append(areaStyle);
-            writer.append("\"");
-        }
-        writer.append(">");
-        //appendWhitespace(writer);
-    }
-
-    /* (non-Javadoc)
-     * @see org.ofbiz.widget.form.FormStringRenderer#renderFormatHeaderRowFormCellClose(java.io.Writer, java.util.Map, org.ofbiz.widget.form.ModelForm)
-     */
-    public void renderFormatHeaderRowFormCellClose(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {
-        writer.append("</td>");
-        appendWhitespace(writer);
-    }
-
-    /* (non-Javadoc)
-     * @see org.ofbiz.widget.form.FormStringRenderer#renderFormatHeaderRowFormCellTitleSeparator(java.io.Writer, java.util.Map, org.ofbiz.widget.form.ModelForm, boolean)
-     */
-    public void renderFormatHeaderRowFormCellTitleSeparator(Appendable writer, Map<String, Object> context, ModelForm modelForm, ModelFormField modelFormField, boolean isLast) throws IOException {
-
-        String titleStyle = modelFormField.getTitleStyle();
-        if (UtilValidate.isNotEmpty(titleStyle)) {
-            writer.append("<span class=\"");
-            writer.append(titleStyle);
-            writer.append("\">");
-        }
-        if (isLast) {
-            writer.append(" - ");
-        } else {
-            writer.append(" - ");
-        }
-        if (UtilValidate.isNotEmpty(titleStyle)) {
-            writer.append("</span>");
-        }
-    }
-
-    /* (non-Javadoc)
-     * @see org.ofbiz.widget.form.FormStringRenderer#renderFormatItemRowOpen(java.io.Writer, java.util.Map, org.ofbiz.widget.form.ModelForm)
-     */
-    public void renderFormatItemRowOpen(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {
-        Integer itemIndex = (Integer)context.get("itemIndex");
-
-        writer.append("  <tr");
-        if (itemIndex!=null) {
-
-            String altRowStyles = modelForm.getStyleAltRowStyle(context);
-            if (itemIndex.intValue() % 2 == 0) {
-                String evenRowStyle = modelForm.getEvenRowStyle();
-                if (UtilValidate.isNotEmpty(evenRowStyle)) {
-                    writer.append(" class=\"");
-                    writer.append(evenRowStyle);
-                    if (UtilValidate.isNotEmpty(altRowStyles)) {
-                        writer.append(altRowStyles);
-                    }
-                    writer.append("\"");
-                } else {
-                    if (UtilValidate.isNotEmpty(altRowStyles)) {
-                        writer.append(" class=\"");
-                        writer.append(altRowStyles);
-                        writer.append("\"");
-                    }
-                }
-            } else {
-                String oddRowStyle = FlexibleStringExpander.expandString(modelForm.getOddRowStyle(), context);
-                if (UtilValidate.isNotEmpty(oddRowStyle)) {
-                    writer.append(" class=\"");
-                    writer.append(oddRowStyle);
-                    if (UtilValidate.isNotEmpty(altRowStyles)) {
-                        writer.append(altRowStyles);
-                    }
-                    writer.append("\"");
-                } else {
-                    if (UtilValidate.isNotEmpty(altRowStyles)) {
-                        writer.append(" class=\"");
-                        writer.append(altRowStyles);
-                        writer.append("\"");
-                    }
-                }
-            }
-        }
-        writer.append(">");
-        appendWhitespace(writer);
-    }
-
-    /* (non-Javadoc)
-     * @see org.ofbiz.widget.form.FormStringRenderer#renderFormatItemRowClose(java.io.Writer, java.util.Map, org.ofbiz.widget.form.ModelForm)
-     */
-    public void renderFormatItemRowClose(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {
-        writer.append("  </tr>");
-
-        appendWhitespace(writer);
-    }
-
-    /* (non-Javadoc)
-     * @see org.ofbiz.widget.form.FormStringRenderer#renderFormatItemRowCellOpen(java.io.Writer, java.util.Map, org.ofbiz.widget.form.ModelForm, org.ofbiz.widget.form.ModelFormField)
-     */
-    public void renderFormatItemRowCellOpen(Appendable writer, Map<String, Object> context, ModelForm modelForm, ModelFormField modelFormField, int positionSpan) throws IOException {
-        writer.append("   <td");
-        String areaStyle = modelFormField.getWidgetAreaStyle();
-        if (positionSpan > 1) {
-            writer.append(" colspan=\"");
-            writer.append(Integer.toString(positionSpan));
-            writer.append("\"");
-        }
-        if (UtilValidate.isNotEmpty(areaStyle)) {
-            writer.append(" class=\"");
-            writer.append(areaStyle);
-            writer.append("\"");
-        }
-        writer.append(">");
-        //appendWhitespace(writer);
-    }
-
-    /* (non-Javadoc)
-     * @see org.ofbiz.widget.form.FormStringRenderer#renderFormatItemRowCellClose(java.io.Writer, java.util.Map, org.ofbiz.widget.form.ModelForm, org.ofbiz.widget.form.ModelFormField)
-     */
-    public void renderFormatItemRowCellClose(Appendable writer, Map<String, Object> context, ModelForm modelForm, ModelFormField modelFormField) throws IOException {
-        writer.append("</td>");
-        appendWhitespace(writer);
-    }
-
-    /* (non-Javadoc)
-     * @see org.ofbiz.widget.form.FormStringRenderer#renderFormatItemRowFormCellOpen(java.io.Writer, java.util.Map, org.ofbiz.widget.form.ModelForm)
-     */
-    public void renderFormatItemRowFormCellOpen(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {
-        writer.append("   <td");
-        String areaStyle = modelForm.getFormWidgetAreaStyle();
-        if (UtilValidate.isNotEmpty(areaStyle)) {
-            writer.append(" class=\"");
-            writer.append(areaStyle);
-            writer.append("\"");
-        }
-        writer.append(">");
-        //appendWhitespace(writer);
-    }
-
-    /* (non-Javadoc)
-     * @see org.ofbiz.widget.form.FormStringRenderer#renderFormatItemRowFormCellClose(java.io.Writer, java.util.Map, org.ofbiz.widget.form.ModelForm)
-     */
-    public void renderFormatItemRowFormCellClose(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {
-        writer.append("</td>");
-        appendWhitespace(writer);
-    }
-
-    public void renderFormatSingleWrapperOpen(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {
-        writer.append(" <table cellspacing=\"0\"");
-        if (UtilValidate.isNotEmpty(modelForm.getDefaultTableStyle())) {
-            writer.append(" class=\"").append(FlexibleStringExpander.expandString(modelForm.getDefaultTableStyle(), context)).append("\"");
-        }
-        writer.append(">");
-        appendWhitespace(writer);
-    }
-
-    public void renderFormatSingleWrapperClose(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {
-        writer.append(" </table>");
-        appendWhitespace(writer);
-    }
-
-    /* (non-Javadoc)
-     * @see org.ofbiz.widget.form.FormStringRenderer#renderFormatFieldRowOpen(java.io.Writer, java.util.Map, org.ofbiz.widget.form.ModelForm)
-     */
-    public void renderFormatFieldRowOpen(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {
-        writer.append("  <tr>");
-        appendWhitespace(writer);
-    }
-
-    /* (non-Javadoc)
-     * @see org.ofbiz.widget.form.FormStringRenderer#renderFormatFieldRowClose(java.io.Writer, java.util.Map, org.ofbiz.widget.form.ModelForm)
-     */
-    public void renderFormatFieldRowClose(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {
-        writer.append("  </tr>");
-        appendWhitespace(writer);
-    }
-
-    /* (non-Javadoc)
-     * @see org.ofbiz.widget.form.FormStringRenderer#renderFormatFieldRowTitleCellOpen(java.io.Writer, java.util.Map, org.ofbiz.widget.form.ModelFormField)
-     */
-    public void renderFormatFieldRowTitleCellOpen(Appendable writer, Map<String, Object> context, ModelFormField modelFormField) throws IOException {
-        writer.append("   <td");
-        String areaStyle = modelFormField.getTitleAreaStyle();
-        if (UtilValidate.isNotEmpty(areaStyle)) {
-            writer.append(" class=\"");
-            writer.append(areaStyle);
-            writer.append("\"");
-        } else {
-            writer.append(" class=\"label\"");
-        }
-        writer.append(">");
-        //appendWhitespace(writer);
-    }
-
-    /* (non-Javadoc)
-     * @see org.ofbiz.widget.form.FormStringRenderer#renderFormatFieldRowTitleCellClose(java.io.Writer, java.util.Map, org.ofbiz.widget.form.ModelFormField)
-     */
-    public void renderFormatFieldRowTitleCellClose(Appendable writer, Map<String, Object> context, ModelFormField modelFormField) throws IOException {
-        writer.append("</td>");
-        appendWhitespace(writer);
-    }
-
-    /* (non-Javadoc)
-     * @see org.ofbiz.widget.form.FormStringRenderer#renderFormatFieldRowSpacerCell(java.io.Writer, java.util.Map, org.ofbiz.widget.form.ModelFormField)
-     */
-    public void renderFormatFieldRowSpacerCell(Appendable writer, Map<String, Object> context, ModelFormField modelFormField) throws IOException {
-        // Embedded styling - bad idea
-        //writer.append("<td>&nbsp;</td>");
-
-        //appendWhitespace(writer);
-    }
-
-    /* (non-Javadoc)
-     * @see org.ofbiz.widget.form.FormStringRenderer#renderFormatFieldRowWidgetCellOpen(java.io.Writer, java.util.Map, org.ofbiz.widget.form.ModelFormField, int)
-     */
-    public void renderFormatFieldRowWidgetCellOpen(Appendable writer, Map<String, Object> context, ModelFormField modelFormField, int positions, int positionSpan, Integer nextPositionInRow) throws IOException {
-//        writer.append("<td width=\"");
-//        if (nextPositionInRow != null || modelFormField.getPosition() > 1) {
-//            writer.append("30");
-//        } else {
-//            writer.append("80");
-//        }
-//        writer.append("%\"");
-        writer.append("   <td");
-        if (positionSpan > 0) {
-            writer.append(" colspan=\"");
-            // do a span of 1 for this column, plus 3 columns for each spanned
-            //position or each blank position that this will be filling in
-            writer.append(Integer.toString(1 + (positionSpan * 3)));
-            writer.append("\"");
-        }
-        String areaStyle = modelFormField.getWidgetAreaStyle();
-        if (UtilValidate.isNotEmpty(areaStyle)) {
-            writer.append(" class=\"");
-            writer.append(areaStyle);
-            writer.append("\"");
-        }
-        writer.append(">");
-
-        //appendWhitespace(writer);
-    }
-
-    /* (non-Javadoc)
-     * @see org.ofbiz.widget.form.FormStringRenderer#renderFormatFieldRowWidgetCellClose(java.io.Writer, java.util.Map, org.ofbiz.widget.form.ModelFormField, int)
-     */
-    public void renderFormatFieldRowWidgetCellClose(Appendable writer, Map<String, Object> context, ModelFormField modelFormField, int positions, int positionSpan, Integer nextPositionInRow) throws IOException {
-        writer.append("</td>");
-        appendWhitespace(writer);
-    }
-
-    public void renderFormatEmptySpace(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {
-        writer.append("&nbsp;");
-    }
-
-    /* (non-Javadoc)
-     * @see org.ofbiz.widget.form.FormStringRenderer#renderTextFindField(java.io.Writer, java.util.Map, org.ofbiz.widget.form.ModelFormField.TextFindField)
-     */
-    public void renderTextFindField(Appendable writer, Map<String, Object> context, TextFindField textFindField) throws IOException {
-
-        ModelFormField modelFormField = textFindField.getModelFormField();
-
-        String defaultOption = textFindField.getDefaultOption();
-        Locale locale = (Locale)context.get("locale");
-        if (!textFindField.getHideOptions()) {
-            String opEquals = UtilProperties.getMessage("conditional", "equals", locale);
-            String opBeginsWith = UtilProperties.getMessage("conditional", "begins_with", locale);
-            String opContains = UtilProperties.getMessage("conditional", "contains", locale);
-            String opIsEmpty = UtilProperties.getMessage("conditional", "is_empty", locale);
-            String opNotEqual = UtilProperties.getMessage("conditional", "not_equal", locale);
-            writer.append(" <select name=\"");
-            writer.append(modelFormField.getParameterName(context));
-            writer.append("_op\" class=\"selectBox\">");
-            writer.append("<option value=\"equals\"").append(("equals".equals(defaultOption)? " selected": "")).append(">").append(opEquals).append("</option>");
-            writer.append("<option value=\"like\"").append(("like".equals(defaultOption)? " selected": "")).append(">").append(opBeginsWith).append("</option>");
-            writer.append("<option value=\"contains\"").append(("contains".equals(defaultOption)? " selected": "")).append(">").append(opContains).append("</option>");
-            writer.append("<option value=\"empty\"").append(("empty".equals(defaultOption)? " selected": "")).append(">").append(opIsEmpty).append("</option>");
-            writer.append("<option value=\"notEqual\"").append(("notEqual".equals(defaultOption)? " selected": "")).append(">").append(opNotEqual).append("</option>");
-            writer.append("</select>");
-        } else {
-            writer.append(" <input type=\"hidden\" name=\"");
-            writer.append(modelFormField.getParameterName(context));
-            writer.append("_op\" value=\"").append(defaultOption).append("\"/>");
-        }
-
-        writer.append("<input type=\"text\"");
-
-        appendClassNames(writer, context, modelFormField);
-
-        writer.append(" name=\"");
-        writer.append(modelFormField.getParameterName(context));
-        writer.append('"');
-
-        String value = modelFormField.getEntry(context, textFindField.getDefaultValue(context));
-        if (UtilValidate.isNotEmpty(value)) {
-            writer.append(" value=\"");
-            writer.append(value);
-            writer.append('"');
-        }
-
-        writer.append(" size=\"");
-        writer.append(Integer.toString(textFindField.getSize()));
-        writer.append('"');
-
-        Integer maxlength = textFindField.getMaxlength();
-        if (maxlength != null) {
-            writer.append(" maxlength=\"");
-            writer.append(maxlength.toString());
-            writer.append('"');
-        }
-
-        if (!textFindField.getClientAutocompleteField()) {
-            writer.append(" autocomplete=\"off\"");
-        }
-
-        writer.append("/>");
-
-        if (UtilValidate.isNotEmpty(modelFormField.getTitleStyle())) {
-            writer.append(" <span class=\"");
-            writer.append(modelFormField.getTitleStyle());
-            writer.append("\">");
-        }
-
-        String ignoreCase = UtilProperties.getMessage("conditional", "ignore_case", locale);
-        boolean ignCase = textFindField.getIgnoreCase();
-
-        if (!textFindField.getHideIgnoreCase()) {
-            writer.append(" <input type=\"checkbox\" name=\"");
-            writer.append(modelFormField.getParameterName(context));
-            writer.append("_ic\" value=\"Y\"").append((ignCase ? " checked=\"checked\"" : "")).append("/>");
-            writer.append(ignoreCase);
-        } else {
-            writer.append("<input type=\"hidden\" name=\"");
-            writer.append(modelFormField.getParameterName(context));
-            writer.append("_ic\" value=\"").append((ignCase ? "Y" : "")).append("\"/>");
-        }
-
-        if (UtilValidate.isNotEmpty(modelFormField.getTitleStyle())) {
-            writer.append("</span>");
-        }
-
-        this.appendTooltip(writer, context, modelFormField);
-
-        //appendWhitespace(writer);
-    }
-
-    /* (non-Javadoc)
-     * @see org.ofbiz.widget.form.FormStringRenderer#renderRangeFindField(java.io.Writer, java.util.Map, org.ofbiz.widget.form.ModelFormField.RangeFindField)
-     */
-    public void renderRangeFindField(Appendable writer, Map<String, Object> context, RangeFindField rangeFindField) throws IOException {
-
-        ModelFormField modelFormField = rangeFindField.getModelFormField();
-        Locale locale = (Locale)context.get("locale");
-        String opEquals = UtilProperties.getMessage("conditional", "equals", locale);
-        String opGreaterThan = UtilProperties.getMessage("conditional", "greater_than", locale);
-        String opGreaterThanEquals = UtilProperties.getMessage("conditional", "greater_than_equals", locale);
-        String opLessThan = UtilProperties.getMessage("conditional", "less_than", locale);
-        String opLessThanEquals = UtilProperties.getMessage("conditional", "less_than_equals", locale);
-        //String opIsEmpty = UtilProperties.getMessage("conditional", "is_empty", locale);
-
-        writer.append("<input type=\"text\"");
-
-        appendClassNames(writer, context, modelFormField);
-
-        writer.append(" name=\"");
-        writer.append(modelFormField.getParameterName(context));
-        writer.append("_fld0_value\"");
-
-        String value = modelFormField.getEntry(context, rangeFindField.getDefaultValue(context));
-        if (UtilValidate.isNotEmpty(value)) {
-            writer.append(" value=\"");
-            writer.append(value);
-            writer.append('"');
-        }
-
-        writer.append(" size=\"");
-        writer.append(Integer.toString(rangeFindField.getSize()));
-        writer.append('"');
-
-        Integer maxlength = rangeFindField.getMaxlength();
-        if (maxlength != null) {
-            writer.append(" maxlength=\"");
-            writer.append(maxlength.toString());
-            writer.append('"');
-        }
-
-        if (!rangeFindField.getClientAutocompleteField()) {
-            writer.append(" autocomplete=\"off\"");
-        }
-
-        writer.append("/>");
-
-        if (UtilValidate.isNotEmpty(modelFormField.getTitleStyle())) {
-            writer.append(" <span class=\"");
-            writer.append(modelFormField.getTitleStyle());
-            writer.append("\">");
-        }
-
-        String defaultOptionFrom = rangeFindField.getDefaultOptionFrom();
-        writer.append(" <select name=\"");
-        writer.append(modelFormField.getParameterName(context));
-        writer.append("_fld0_op\" class=\"selectBox\">");
-        writer.append("<option value=\"equals\"").append(("equals".equals(defaultOptionFrom)? " selected": "")).append(">").append(opEquals).append("</option>");
-        writer.append("<option value=\"greaterThan\"").append(("greaterThan".equals(defaultOptionFrom)? " selected": "")).append(">").append(opGreaterThan).append("</option>");
-        writer.append("<option value=\"greaterThanEqualTo\"").append(("greaterThanEqualTo".equals(defaultOptionFrom)? " selected": "")).append(">").append(opGreaterThanEquals).append("</option>");
-        writer.append("</select>");
-
-        writer.append("</span>");
-
-        writer.append(" <br/> ");
-
-        writer.append("<input type=\"text\"");
-
-        appendClassNames(writer, context, modelFormField);
-
-        writer.append(" name=\"");
-        writer.append(modelFormField.getParameterName(context));
-        writer.append("_fld1_value\"");
-
-        value = modelFormField.getEntry(context);
-        if (UtilValidate.isNotEmpty(value)) {
-            writer.append(" value=\"");
-            writer.append(value);
-            writer.append('"');
-        }
-
-        writer.append(" size=\"");
-        writer.append(Integer.toString(rangeFindField.getSize()));
-        writer.append('"');
-
-        if (maxlength != null) {
-            writer.append(" maxlength=\"");
-            writer.append(maxlength.toString());
-            writer.append('"');
-        }
-
-        if (!rangeFindField.getClientAutocompleteField()) {
-            writer.append(" autocomplete=\"off\"");
-        }
-
-        writer.append("/>");
-
-        String defaultOptionThru = rangeFindField.getDefaultOptionThru();
-        writer.append(" <select name=\"");
-        writer.append(modelFormField.getParameterName(context));
-        writer.append("_fld1_op\" class=\"selectBox\">");
-        writer.append("<option value=\"lessThan\"").append(("lessThan".equals(defaultOptionThru)? " selected": "")).append(">").append(opLessThan).append("</option>");
-        writer.append("<option value=\"lessThanEqualTo\"").append(("lessThanEqualTo".equals(defaultOptionThru)? " selected": "")).append(">").append(opLessThanEquals).append("</option>");
-        writer.append("</select>");
-
-        if (UtilValidate.isNotEmpty(modelFormField.getTitleStyle())) {
-            writer.append("</span>");
-        }
-
-        this.appendTooltip(writer, context, modelFormField);
-
-        //appendWhitespace(writer);
-    }
-
-    /* (non-Javadoc)
-     * @see org.ofbiz.widget.form.FormStringRenderer#renderDateFindField(java.io.Writer, java.util.Map, org.ofbiz.widget.form.ModelFormField.DateFindField)
-     */
-    public void renderDateFindField(Appendable writer, Map<String, Object> context, DateFindField dateFindField) throws IOException {
-        ModelFormField modelFormField = dateFindField.getModelFormField();
-
-        Locale locale = (Locale)context.get("locale");
-        String opEquals = UtilProperties.getMessage("conditional", "equals", locale);
-        String opGreaterThan = UtilProperties.getMessage("conditional", "greater_than", locale);
-        String opSameDay = UtilProperties.getMessage("conditional", "same_day", locale);
-        String opGreaterThanFromDayStart = UtilProperties.getMessage("conditional",
-                                                "greater_than_from_day_start", locale);
-        String opLessThan = UtilProperties.getMessage("conditional", "less_than", locale);
-        String opUpToDay = UtilProperties.getMessage("conditional", "up_to_day", locale);
-        String opUpThruDay = UtilProperties.getMessage("conditional", "up_thru_day", locale);
-        String opIsEmpty = UtilProperties.getMessage("conditional", "is_empty", locale);
-
-        Map<String, String> uiLabelMap = UtilGenerics.checkMap(context.get("uiLabelMap"));
-        if (uiLabelMap == null) {
-            Debug.logWarning("Could not find uiLabelMap in context", module);
-        }
-        String localizedInputTitle = "", localizedIconTitle = "";
-
-        writer.append("<input type=\"text\"");
-
-        appendClassNames(writer, context, modelFormField);
-
-        writer.append(" name=\"");
-        writer.append(modelFormField.getParameterName(context));
-        writer.append("_fld0_value\"");
-
-        // the default values for a timestamp
-        int size = 25;
-        int maxlength = 30;
-
-        if ("date".equals(dateFindField.getType())) {
-            size = maxlength = 10;
-            if (uiLabelMap != null) {
-                localizedInputTitle = uiLabelMap.get("CommonFormatDate");
-            }
-        } else if ("time".equals(dateFindField.getType())) {
-            size = maxlength = 8;
-            if (uiLabelMap != null) {
-                localizedInputTitle = uiLabelMap.get("CommonFormatTime");
-            }
-        } else {
-            if (uiLabelMap != null) {
-                localizedInputTitle = uiLabelMap.get("CommonFormatDateTime");
-            }
-        }
-        writer.append(" title=\"");
-        writer.append(localizedInputTitle);
-        writer.append('"');
-
-        String value = modelFormField.getEntry(context, dateFindField.getDefaultValue(context));
-        if (UtilValidate.isNotEmpty(value)) {
-            if (value.length() > maxlength) {
-                value = value.substring(0, maxlength);
-            }
-            writer.append(" value=\"");
-            writer.append(value);
-            writer.append('"');
-        }
-
-        writer.append(" size=\"");
-        writer.append(Integer.toString(size));
-        writer.append('"');
-
-        writer.append(" maxlength=\"");
-        writer.append(Integer.toString(maxlength));
-        writer.append('"');
-
-        writer.append("/>");
-
-        // search for a localized label for the icon
-        if (uiLabelMap != null) {
-            localizedIconTitle = uiLabelMap.get("CommonViewCalendar");
-        }
-        ModelForm modelForm = modelFormField.getModelForm();
-        // add calendar pop-up button and seed data IF this is not a "time" type date-find
-        if (!"time".equals(dateFindField.getType())) {
-            if ("date".equals(dateFindField.getType())) {
-                writer.append("<a href=\"javascript:call_cal_notime(document.");
-            } else {
-                writer.append("<a href=\"javascript:call_cal(document.");
-            }
-            writer.append(FormRenderer.getCurrentFormName(modelForm, context));
-            writer.append('.');
-            writer.append(modelFormField.getParameterName(context));
-            writer.append("_fld0_value,'");
-            writer.append(UtilHttp.encodeBlanks(modelFormField.getEntry(context, dateFindField.getDefaultDateTimeString(context))));
-            writer.append("');\">");
-
-            writer.append("<img src=\"");
-            this.appendContentUrl(writer, "/images/cal.gif");
-            writer.append("\" width=\"16\" height=\"16\" border=\"0\" alt=\"");
-            writer.append(localizedIconTitle);
-            writer.append("\" title=\"");
-            writer.append(localizedIconTitle);
-            writer.append("\"/></a>");
-        }
-
-        if (UtilValidate.isNotEmpty(modelFormField.getTitleStyle())) {
-            writer.append(" <span class=\"");
-            writer.append(modelFormField.getTitleStyle());
-            writer.append("\">");
-        }
-
-        String defaultOptionFrom = dateFindField.getDefaultOptionFrom();
-        writer.append(" <select name=\"");
-        writer.append(modelFormField.getParameterName(context));
-        writer.append("_fld0_op\" class=\"selectBox\">");
-        writer.append("<option value=\"equals\"").append(("equals".equals(defaultOptionFrom)? " selected": "")).append(">").append(opEquals).append("</option>");
-        writer.append("<option value=\"sameDay\"").append(("sameDay".equals(defaultOptionFrom)? " selected": "")).append(">").append(opSameDay).append("</option>");
-        writer.append("<option value=\"greaterThanFromDayStart\"").append(("greaterThanFromDayStart".equals(defaultOptionFrom)? " selected": "")).append(">").append(opGreaterThanFromDayStart).append("</option>");
-        writer.append("<option value=\"greaterThan\"").append(("greaterThan".equals(defaultOptionFrom)? " selected": "")).append(">").append(opGreaterThan).append("</option>");
-        writer.append("</select>");
-
-        if (UtilValidate.isNotEmpty(modelFormField.getTitleStyle())) {
-            writer.append(" </span>");
-        }
-
-        writer.append(" <br/> ");
-
-        writer.append("<input type=\"text\"");
-
-        appendClassNames(writer, context, modelFormField);
-
-        writer.append(" name=\"");
-        writer.append(modelFormField.getParameterName(context));
-        writer.append("_fld1_value\"");
-
-        writer.append(" title=\"");
-        writer.append(localizedInputTitle);
-        writer.append('"');
-
-        value = modelFormField.getEntry(context);
-        if (UtilValidate.isNotEmpty(value)) {
-            if (value.length() > maxlength) {
-                value = value.substring(0, maxlength);
-            }
-            writer.append(" value=\"");
-            writer.append(value);
-            writer.append('"');
-        }
-
-        writer.append(" size=\"");
-        writer.append(Integer.toString(size));
-        writer.append('"');
-
-        writer.append(" maxlength=\"");
-        writer.append(Integer.toString(maxlength));
-        writer.append('"');
-
-        writer.append("/>");
-
-        // add calendar pop-up button and seed data IF this is not a "time" type date-find
-        if (!"time".equals(dateFindField.getType())) {
-            if ("date".equals(dateFindField.getType())) {
-                writer.append("<a href=\"javascript:call_cal_notime(document.");
-            } else {
-                writer.append("<a href=\"javascript:call_cal(document.");
-            }
-            writer.append(FormRenderer.getCurrentFormName(modelForm, context));
-            writer.append('.');
-            writer.append(modelFormField.getParameterName(context));
-            writer.append("_fld1_value,'");
-            writer.append(UtilHttp.encodeBlanks(modelFormField.getEntry(context, dateFindField.getDefaultDateTimeString(context))));
-            writer.append("');\">");
-
-            writer.append("<img src=\"");
-            this.appendContentUrl(writer, "/images/cal.gif");
-            writer.append("\" width=\"16\" height=\"16\" border=\"0\" alt=\"");
-            writer.append(localizedIconTitle);
-            writer.append("\" title=\"");
-            writer.append(localizedIconTitle);
-            writer.append("\"/></a>");
-        }
-
-        if (UtilValidate.isNotEmpty(modelFormField.getTitleStyle())) {
-            writer.append(" <span class=\"");
-            writer.append(modelFormField.getTitleStyle());
-            writer.append("\">");
-        }
-
-        String defaultOptionThru = dateFindField.getDefaultOptionThru();
-        writer.append(" <select name=\"");
-        writer.append(modelFormField.getParameterName(context));
-        writer.append("_fld1_op\" class=\"selectBox\">");
-        writer.append("<option value=\"lessThan\"").append(("lessThan".equals(defaultOptionThru)? " selected": "")).append(">").append(opLessThan).append("</option>");
-        writer.append("<option value=\"upToDay\"").append(("upToDay".equals(defaultOptionThru)? " selected": "")).append(">").append(opUpToDay).append("</option>");
-        writer.append("<option value=\"upThruDay\"").append(("upThruDay".equals(defaultOptionThru)? " selected": "")).append(">").append(opUpThruDay).append("</option>");
-        writer.append("<option value=\"empty\"").append(("empty".equals(defaultOptionThru)? " selected": "")).append(">").append(opIsEmpty).append("</option>");
-        writer.append("</select>");
-
-        if (UtilValidate.isNotEmpty(modelFormField.getTitleStyle())) {
-            writer.append("</span>");
-        }
-
-        this.appendTooltip(writer, context, modelFormField);
-
-        //appendWhitespace(writer);
-    }
-
-    /* (non-Javadoc)
-     * @see org.ofbiz.widget.form.FormStringRenderer#renderLookupField(java.io.Writer, java.util.Map, org.ofbiz.widget.form.ModelFormField.LookupField)
-     */
-    public void renderLookupField(Appendable writer, Map<String, Object> context, LookupField lookupField) throws IOException {
-        ModelFormField modelFormField = lookupField.getModelFormField();
-
-        writer.append("<input type=\"text\"");
-
-        appendClassNames(writer, context, modelFormField);
-
-        writer.append(" name=\"");
-        writer.append(modelFormField.getParameterName(context));
-        writer.append('"');
-
-        String value = modelFormField.getEntry(context, lookupField.getDefaultValue(context));
-        if (UtilValidate.isNotEmpty(value)) {
-            writer.append(" value=\"");
-            writer.append(value);
-            writer.append('"');
-        }
-
-        writer.append(" size=\"");
-        writer.append(Integer.toString(lookupField.getSize()));
-        writer.append('"');
-
-        Integer maxlength = lookupField.getMaxlength();
-        if (maxlength != null) {
-            writer.append(" maxlength=\"");
-            writer.append(maxlength.toString());
-            writer.append('"');
-        }
-
-        String idName = modelFormField.getCurrentContainerId(context);
-        if (UtilValidate.isNotEmpty(idName)) {
-            writer.append(" id=\"");
-            writer.append(idName);
-            writer.append('"');
-        }
-
-        List<ModelForm.UpdateArea> updateAreas = modelFormField.getOnChangeUpdateAreas();
-        boolean ajaxEnabled = updateAreas != null && this.javaScriptEnabled;
-        if (!lookupField.getClientAutocompleteField() || ajaxEnabled) {
-            writer.append(" autocomplete=\"off\"");
-        }
-
-        writer.append("/>");
-        ModelForm modelForm = modelFormField.getModelForm();
-        // add lookup pop-up button
-        String descriptionFieldName = lookupField.getDescriptionFieldName();
-        if (UtilValidate.isNotEmpty(descriptionFieldName)) {
-            writer.append("<a href=\"javascript:call_fieldlookup3(document.");
-            writer.append(FormRenderer.getCurrentFormName(modelForm, context));
-            writer.append('.');
-            writer.append(modelFormField.getParameterName(context));
-            writer.append(",'");
-            writer.append(descriptionFieldName);
-            writer.append(",'");
-        } else {
-            writer.append("<a href=\"javascript:call_fieldlookup2(document.");
-            writer.append(FormRenderer.getCurrentFormName(modelForm, context));
-            writer.append('.');
-            writer.append(modelFormField.getParameterName(context));
-            writer.append(",'");
-        }
-        writer.append(appendExternalLoginKey(lookupField.getFormName(context)));
-        writer.append("'");
-        List<String> targetParameterList = lookupField.getTargetParameterList();
-        for (String targetParameter: targetParameterList) {
-            // named like: document.${formName}.${targetParameter}.value
-            writer.append(", document.");
-            writer.append(FormRenderer.getCurrentFormName(modelForm, context));
-            writer.append(".");
-            writer.append(targetParameter);
-            writer.append(".value");
-        }
-        writer.append(");\">");
-        writer.append("<img src=\"");
-        this.appendContentUrl(writer, "/images/fieldlookup.gif");
-        writer.append("\" width=\"15\" height=\"14\" border=\"0\" alt=\"Lookup\"/></a>");
-
-        this.addAsterisks(writer, context, modelFormField);
-
-        this.makeHyperlinkString(writer, lookupField.getSubHyperlink(), context);
-        this.appendTooltip(writer, context, modelFormField);
-
-        if (ajaxEnabled) {
-            appendWhitespace(writer);
-            writer.append("<script language=\"JavaScript\" type=\"text/javascript\">");
-            appendWhitespace(writer);
-            writer.append("ajaxAutoCompleter('").append(createAjaxParamsFromUpdateAreas(updateAreas, null, context)).append("');");
-            appendWhitespace(writer);
-            writer.append("</script>");
-        }
-        appendWhitespace(writer);
-
-        //appendWhitespace(writer);
-    }
-
-    protected String appendExternalLoginKey(String target) {
-        String result = target;
-        String sessionId = ";jsessionid=" + request.getSession().getId();
-        int questionIndex = target.indexOf("?");
-        if (questionIndex == -1) {
-            result += sessionId;
-        } else {
-            result = result.replace("?", sessionId + "?");
-        }
-        return result;
-    }
-
-    private int getActualPageSize(Map<String, Object> context) {
-        Integer value = (Integer) context.get("actualPageSize");
-        return value != null ? value.intValue() : (getHighIndex(context) - getLowIndex(context));
-    }
-
-    private int getHighIndex(Map<String, Object> context) {
-        Integer value = (Integer) context.get("highIndex");
-        return value != null ? value.intValue() : 0;
-    }
-
-    private int getListSize(Map<String, Object> context) {
-        Integer value = (Integer) context.get("listSize");
-        return value != null ? value.intValue() : 0;
-    }
-
-    private int getLowIndex(Map<String, Object> context) {
-        Integer value = (Integer) context.get("lowIndex");
-        return value != null ? value.intValue() : 0;
-    }
-
-    public void renderNextPrev(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {
-        boolean ajaxEnabled = false;
-        List<ModelForm.UpdateArea> updateAreas = modelForm.getOnPaginateUpdateAreas();
-        String targetService = modelForm.getPaginateTarget(context);
-        if (this.javaScriptEnabled) {
-            if (UtilValidate.isNotEmpty(updateAreas)) {
-                ajaxEnabled = true;
-            }
-        }
-        if (targetService == null) {
-            targetService = "${targetService}";
-        }
-        if (UtilValidate.isEmpty(targetService) && updateAreas == null) {
-            Debug.logWarning("Cannot paginate because TargetService is empty for the form: " + modelForm.getName(), module);
-            return;
-        }
-
-        // get the parameterized pagination index and size fields
-        int paginatorNumber = WidgetWorker.getPaginatorNumber(context);
-        String viewIndexParam = modelForm.getMultiPaginateIndexField(context);
-        String viewSizeParam = modelForm.getMultiPaginateSizeField(context);
-
-        int viewIndex = Paginator.getViewIndex(modelForm, context);
-        int viewSize = Paginator.getViewSize(modelForm, context);
-        int listSize = getListSize(context);
-
-        int lowIndex = getLowIndex(context);
-        int highIndex = getHighIndex(context);
-        int actualPageSize = getActualPageSize(context);
-
-        // if this is all there seems to be (if listSize < 0, then size is unknown)
-        if (actualPageSize >= listSize && listSize >= 0) return;
-
-        // needed for the "Page" and "rows" labels
-        Map<String, String> uiLabelMap = UtilGenerics.checkMap(context.get("uiLabelMap"));
-        String pageLabel = "";
-        String commonDisplaying = "";
-        if (uiLabelMap == null) {
-            Debug.logWarning("Could not find uiLabelMap in context", module);
-        } else {
-            pageLabel = uiLabelMap.get("CommonPage");
-            Map<String, Integer> messageMap = UtilMisc.toMap("lowCount", Integer.valueOf(lowIndex + 1), "highCount", Integer.valueOf(lowIndex + actualPageSize), "total", Integer.valueOf(listSize));
-            commonDisplaying = UtilProperties.getMessage("CommonUiLabels", "CommonDisplaying", messageMap, (Locale) context.get("locale"));
-        }
-
-        // for legacy support, the viewSizeParam is VIEW_SIZE and viewIndexParam is VIEW_INDEX when the fields are "viewSize" and "viewIndex"
-        if (viewIndexParam.equals("viewIndex" + "_" + paginatorNumber)) viewIndexParam = "VIEW_INDEX" + "_" + paginatorNumber;
-        if (viewSizeParam.equals("viewSize" + "_" + paginatorNumber)) viewSizeParam = "VIEW_SIZE" + "_" + paginatorNumber;
-
-        String str = (String) context.get("_QBESTRING_");
-
-        // strip legacy viewIndex/viewSize params from the query string
-        String queryString = UtilHttp.stripViewParamsFromQueryString(str, "" + paginatorNumber);
-
-        // strip parametrized index/size params from the query string
-        HashSet<String> paramNames = new HashSet<String>();
-        paramNames.add(viewIndexParam);
-        paramNames.add(viewSizeParam);
-        queryString = UtilHttp.stripNamedParamsFromQueryString(queryString, paramNames);
-
-        String anchor = "";
-        String paginateAnchor = modelForm.getPaginateTargetAnchor();
-        if (paginateAnchor != null) anchor = "#" + paginateAnchor;
-
-        // Create separate url path String and request parameters String,
-        // add viewIndex/viewSize parameters to request parameter String
-        String urlPath = UtilHttp.removeQueryStringFromTarget(targetService);
-        StringBuilder prepLinkBuffer = new StringBuilder();
-        String prepLinkQueryString = UtilHttp.getQueryStringFromTarget(targetService);
-        if (prepLinkQueryString != null) {
-            prepLinkBuffer.append(prepLinkQueryString);
-        }
-        if (prepLinkBuffer.indexOf("?") < 0) {
-            prepLinkBuffer.append("?");
-        } else if (prepLinkBuffer.indexOf("?", prepLinkBuffer.length() - 1) > 0) {
-            prepLinkBuffer.append("&amp;");
-        }
-        if (!UtilValidate.isEmpty(queryString) && !queryString.equals("null")) {
-            prepLinkBuffer.append(queryString).append("&amp;");
-        }
-        prepLinkBuffer.append(viewSizeParam).append("=").append(viewSize).append("&amp;").append(viewIndexParam).append("=");
-        String prepLinkText = prepLinkBuffer.toString();
-        if (ajaxEnabled) {
-            // Prepare params for prototype.js
-            prepLinkText = prepLinkText.replace("?", "");
-            prepLinkText = prepLinkText.replace("&amp;", "&");
-        }
-
-        writer.append("<div class=\"").append(modelForm.getPaginateStyle()).append("\">");
-        appendWhitespace(writer);
-        writer.append(" <ul>");
-        appendWhitespace(writer);
-
-        String linkText;
-
-        // First button
-        writer.append("  <li class=\"").append(modelForm.getPaginateFirstStyle());
-        if (viewIndex > 0) {
-            writer.append("\"><a href=\"");
-            if (ajaxEnabled) {
-                writer.append("javascript:ajaxUpdateAreas('").append(createAjaxParamsFromUpdateAreas(updateAreas, prepLinkText + 0 + anchor, context)).append("')");
-            } else {
-                linkText = prepLinkText + 0 + anchor;
-                appendOfbizUrl(writer, urlPath + linkText);
-            }
-            writer.append("\">").append(modelForm.getPaginateFirstLabel(context)).append("</a>");
-        } else {
-            // disabled button
-            writer.append("-disabled\">").append(modelForm.getPaginateFirstLabel(context));
-        }
-        writer.append("</li>");
-        appendWhitespace(writer);
-
-        // Previous button
-        writer.append("  <li class=\"").append(modelForm.getPaginatePreviousStyle());
-        if (viewIndex > 0) {
-            writer.append("\"><a href=\"");
-            if (ajaxEnabled) {
-                writer.append("javascript:ajaxUpdateAreas('").append(createAjaxParamsFromUpdateAreas(updateAreas, prepLinkText + (viewIndex - 1) + anchor, context)).append("')");
-            } else {
-                linkText = prepLinkText + (viewIndex - 1) + anchor;
-                appendOfbizUrl(writer, urlPath + linkText);
-            }
-            writer.append("\">").append(modelForm.getPaginatePreviousLabel(context)).append("</a>");
-        } else {
-            // disabled button
-            writer.append("-disabled\">").append(modelForm.getPaginatePreviousLabel(context));
-        }
-        writer.append("</li>");
-        appendWhitespace(writer);
-
-        // Page select dropdown
-        if (listSize > 0 && this.javaScriptEnabled) {
-            writer.append("  <li>").append(pageLabel).append(" <select name=\"page\" size=\"1\" onchange=\"");
-            if (ajaxEnabled) {
-                writer.append("javascript:ajaxUpdateAreas('").append(createAjaxParamsFromUpdateAreas(updateAreas, prepLinkText + "' + this.value", context)).append(")");
-            } else {
-                linkText = prepLinkText;
-                if (linkText.startsWith("/")) {
-                    linkText = linkText.substring(1);
-                }
-                writer.append("location.href = '");
-                appendOfbizUrl(writer, urlPath + linkText);
-                writer.append("' + this.value;");
-            }
-            writer.append("\">");
-            // actual value
-            int page = 0;
-            for (int i = 0; i < listSize;) {
-                if (page == viewIndex) {
-                    writer.append("<option selected value=\"");
-                } else {
-                    writer.append("<option value=\"");
-                }
-                writer.append(Integer.toString(page));
-                writer.append("\">");
-                writer.append(Integer.toString(1 + page));
-                writer.append("</option>");
-                // increment page and calculate next index
-                page++;
-                i = page * viewSize;
-            }
-            writer.append("</select></li>");
-        }
-
-        //  show row count
-        writer.append("<li>");
-        writer.append(commonDisplaying);
-        writer.append("</li>");
-        appendWhitespace(writer);
-
-        // Next button
-        writer.append("  <li class=\"").append(modelForm.getPaginateNextStyle());
-        if (highIndex < listSize) {
-            writer.append("\"><a href=\"");
-            if (ajaxEnabled) {
-                writer.append("javascript:ajaxUpdateAreas('").append(createAjaxParamsFromUpdateAreas(updateAreas, prepLinkText + (viewIndex + 1) + anchor, context)).append("')");
-            } else {
-                linkText = prepLinkText + (viewIndex + 1) + anchor;
-                appendOfbizUrl(writer, urlPath + linkText);
-            }
-            writer.append("\">").append(modelForm.getPaginateNextLabel(context)).append("</a>");
-        } else {
-            // disabled button
-            writer.append("-disabled\">").append(modelForm.getPaginateNextLabel(context));
-        }
-        writer.append("</li>");
-        appendWhitespace(writer);
-
-        // Last button
-        writer.append("  <li class=\"").append(modelForm.getPaginateLastStyle());
-        if (highIndex < listSize) {
-            int lastIndex = UtilMisc.getViewLastIndex(listSize, viewSize);
-            writer.append("\"><a href=\"");
-            if (ajaxEnabled) {
-                writer.append("javascript:ajaxUpdateAreas('").append(createAjaxParamsFromUpdateAreas(updateAreas, prepLinkText + lastIndex + anchor, context)).append("')");
-            } else {
-                linkText = prepLinkText + lastIndex + anchor;
-                appendOfbizUrl(writer, urlPath + linkText);
-            }
-            writer.append("\">").append(modelForm.getPaginateLastLabel(context)).append("</a>");
-        } else {
-            // disabled button
-            writer.append("-disabled\">").append(modelForm.getPaginateLastLabel(context));
-        }
-        writer.append("</li>");
-        appendWhitespace(writer);
-
-        writer.append(" </ul>");
-        appendWhitespace(writer);
-        writer.append("</div>");
-        appendWhitespace(writer);
-    }
-
-    public void renderSortField(Appendable writer, Map<String, Object> context, ModelFormField modelFormField, String titleText) throws IOException {
-        boolean ajaxEnabled = false;
-        ModelForm modelForm = modelFormField.getModelForm();
-        List<ModelForm.UpdateArea> updateAreas = modelForm.getOnPaginateUpdateAreas();
-        String targetService = modelForm.getPaginateTarget(context);
-        if (this.javaScriptEnabled) {
-            if (UtilValidate.isNotEmpty(updateAreas)) {
-                ajaxEnabled = true;
-            }
-        }
-        if (targetService == null) {
-            targetService = "${targetService}";
-        }
-        if (UtilValidate.isEmpty(targetService) && updateAreas == null) {
-            Debug.logWarning("Cannot sort because TargetService is empty for the form: " + modelForm.getName(), module);
-            return;
-        }
-
-        String str = (String) context.get("_QBESTRING_");
-        String oldSortField = modelForm.getSortField(context);
-        String sortFieldStyle = modelFormField.getSortFieldStyle();
-
-        // if the entry-name is defined use this instead of field name
-        String columnField = modelFormField.getEntryName();
-        if (UtilValidate.isEmpty(columnField)) {
-            columnField = modelFormField.getFieldName();
-        }
-
-        // switch beetween asc/desc order
-        String newSortField = columnField;
-        if (UtilValidate.isNotEmpty(oldSortField)) {
-            if (oldSortField.equals(columnField)) {
-                newSortField = "-" + columnField;
-                sortFieldStyle = modelFormField.getSortFieldStyleDesc();
-            } else if (oldSortField.equals("-" + columnField)) {
-                newSortField = columnField;
-                sortFieldStyle = modelFormField.getSortFieldStyleAsc();
-            }
-        }
-
-        //  strip sortField param from the query string
-        HashSet<String> paramName = new HashSet<String>();
-        paramName.add("sortField");
-        String queryString = UtilHttp.stripNamedParamsFromQueryString(str, paramName);
-        String urlPath = UtilHttp.removeQueryStringFromTarget(targetService);
-        StringBuilder prepLinkBuffer = new StringBuilder();
-        String prepLinkQueryString = UtilHttp.getQueryStringFromTarget(targetService);
-        if (prepLinkQueryString != null) {
-            prepLinkBuffer.append(prepLinkQueryString);
-        }
-        if (prepLinkBuffer.indexOf("?") < 0) {
-            prepLinkBuffer.append("?");
-        } else if (prepLinkBuffer.indexOf("?", prepLinkBuffer.length() - 1) > 0) {
-            prepLinkBuffer.append("&amp;");
-        }
-        if (!UtilValidate.isEmpty(queryString) && !queryString.equals("null")) {
-            prepLinkBuffer.append(queryString).append("&amp;");
-        }
-        prepLinkBuffer.append("sortField").append("=").append(newSortField);
-        String prepLinkText = prepLinkBuffer.toString();
-        if (ajaxEnabled) {
-            prepLinkText = prepLinkText.replace("?", "");
-            prepLinkText = prepLinkText.replace("&amp;", "&");
-        }
-
-        writer.append("<a");
-        if (UtilValidate.isNotEmpty(sortFieldStyle)) {
-            writer.append(" class=\"");
-            writer.append(sortFieldStyle);
-            writer.append("\"");
-        }
-
-        writer.append(" href=\"");
-        if (ajaxEnabled) {
-            writer.append("javascript:ajaxUpdateAreas('").append(createAjaxParamsFromUpdateAreas(updateAreas, prepLinkText, context)).append("')");
-        } else {
-            appendOfbizUrl(writer, urlPath + prepLinkText);
-        }
-        writer.append("\">").append(titleText).append("</a>");
-    }
-
-    /* (non-Javadoc)
-     * @see org.ofbiz.widget.form.FormStringRenderer#renderFileField(java.io.Writer, java.util.Map, org.ofbiz.widget.form.ModelFormField.FileField)
-     */
-    public void renderFileField(Appendable writer, Map<String, Object> context, FileField textField) throws IOException {
-        ModelFormField modelFormField = textField.getModelFormField();
-
-        writer.append("<input type=\"file\"");
-
-        appendClassNames(writer, context, modelFormField);
-
-        writer.append(" name=\"");
-        writer.append(modelFormField.getParameterName(context));
-        writer.append('"');
-
-        String value = modelFormField.getEntry(context, textField.getDefaultValue(context));
-        if (UtilValidate.isNotEmpty(value)) {
-            writer.append(" value=\"");
-            writer.append(value);
-            writer.append('"');
-        }
-
-        writer.append(" size=\"");
-        writer.append(Integer.toString(textField.getSize()));
-        writer.append('"');
-
-        Integer maxlength = textField.getMaxlength();
-        if (maxlength != null) {
-            writer.append(" maxlength=\"");
-            writer.append(maxlength.toString());
-            writer.append('"');
-        }
-
-        if (!textField.getClientAutocompleteField()) {
-            writer.append(" autocomplete=\"off\"");
-        }
-
-        writer.append("/>");
-
-        this.makeHyperlinkString(writer, textField.getSubHyperlink(), context);
-
-        this.appendTooltip(writer, context, modelFormField);
-
-        //appendWhitespace(writer);
-    }
-
-    /* (non-Javadoc)
-     * @see org.ofbiz.widget.form.FormStringRenderer#renderPasswordField(java.io.Writer, java.util.Map, org.ofbiz.widget.form.ModelFormField.PasswordField)
-     */
-    public void renderPasswordField(Appendable writer, Map<String, Object> context, PasswordField passwordField) throws IOException {
-        ModelFormField modelFormField = passwordField.getModelFormField();
-
-        writer.append("<input type=\"password\"");
-
-        appendClassNames(writer, context, modelFormField);
-
-        writer.append(" name=\"");
-        writer.append(modelFormField.getParameterName(context));
-        writer.append('"');
-
-        String value = modelFormField.getEntry(context, passwordField.getDefaultValue(context));
-        if (UtilValidate.isNotEmpty(value)) {
-            writer.append(" value=\"");
-            writer.append(value);
-            writer.append('"');
-        }
-
-        writer.append(" size=\"");
-        writer.append(Integer.toString(passwordField.getSize()));
-        writer.append('"');
-
-        Integer maxlength = passwordField.getMaxlength();
-        if (maxlength != null) {
-            writer.append(" maxlength=\"");
-            writer.append(maxlength.toString());
-            writer.append('"');
-        }
-
-        String idName = modelFormField.getCurrentContainerId(context);
-        if (UtilValidate.isNotEmpty(idName)) {
-            writer.append(" id=\"");
-            writer.append(idName);
-            writer.append('"');
-        }
-
-        if (!passwordField.getClientAutocompleteField()) {
-            writer.append(" autocomplete=\"off\"");
-        }
-
-        writer.append("/>");
-
-        this.addAsterisks(writer, context, modelFormField);
-
-        this.makeHyperlinkString(writer, passwordField.getSubHyperlink(), context);
-
-        this.appendTooltip(writer, context, modelFormField);
-
-        //appendWhitespace(writer);
-    }
-
-    /* (non-Javadoc)
-     * @see org.ofbiz.widget.form.FormStringRenderer#renderImageField(java.io.Writer, java.util.Map, org.ofbiz.widget.form.ModelFormField.ImageField)
-     */
-    public void renderImageField(Appendable writer, Map<String, Object> context, ImageField imageField) throws IOException {
-        ModelFormField modelFormField = imageField.getModelFormField();
-
-        writer.append("<img ");
-
-        String value = modelFormField.getEntry(context, imageField.getValue(context));
-        if (UtilValidate.isNotEmpty(value)) {
-            writer.append(" src=\"");
-            appendContentUrl(writer, value);
-            writer.append('"');
-        }
-        
-        value = modelFormField.getEntry(context, imageField.getStyle(context));
-        if (UtilValidate.isNotEmpty(value)) {
-            writer.append(" class=\"");
-            appendContentUrl(writer, value);
-            writer.append('"');
-        }
-
-        String event = modelFormField.getEvent();
-        String action = modelFormField.getAction(context);
-        if (UtilValidate.isNotEmpty(event) && UtilValidate.isNotEmpty(action)) {
-            writer.append(" ");
-            writer.append(event);
-            writer.append("=\"");
-            writer.append(action);
-            writer.append('"');
-        }
-
-        writer.append("/>");
-
-        this.makeHyperlinkString(writer, imageField.getSubHyperlink(), context);
-
-        this.appendTooltip(writer, context, modelFormField);
-
-        //appendWhitespace(writer);
-    }
-
-    public void renderFieldGroupOpen(Appendable writer, Map<String, Object> context, ModelForm.FieldGroup fieldGroup) throws IOException {
-        String style = fieldGroup.getStyle();
-        String id = fieldGroup.getId();
-        FlexibleStringExpander titleNotExpanded = FlexibleStringExpander.getInstance(fieldGroup.getTitle());
-        String title = titleNotExpanded.expandString(context);
-        Boolean collapsed = fieldGroup.initiallyCollapsed();
-        String collapsibleAreaId = fieldGroup.getId() + "_body";
-
-        if (UtilValidate.isNotEmpty(style) || UtilValidate.isNotEmpty(id) || UtilValidate.isNotEmpty(title)) {
-
-            writer.append("<div class=\"fieldgroup");
-            if (UtilValidate.isNotEmpty(style)) {
-                writer.append(" ");
-                writer.append(style);
-            }
-            writer.append("\"");
-            if (UtilValidate.isNotEmpty(id)) {
-                writer.append(" id=\"");
-                writer.append(id);
-                writer.append("\"");
-            }
-            writer.append(">");
-
-            writer.append("<div class=\"fieldgroup-title-bar\"><table><tr><td class=\"collapse\">");
-
-            if (fieldGroup.collapsible()) {
-                String expandToolTip = null;
-                String collapseToolTip = null;
-                Map<String, Object> uiLabelMap = UtilGenerics.checkMap(context.get("uiLabelMap"));
-                //Map<String, Object> paramMap = UtilGenerics.checkMap(context.get("requestParameters"));
-                if (uiLabelMap != null) {
-                    expandToolTip = (String) uiLabelMap.get("CommonExpand");
-                    collapseToolTip = (String) uiLabelMap.get("CommonCollapse");
-                }
-
-                writer.append("<ul><li class=\"");
-                if (collapsed) {
-                    writer.append("collapsed\"><a ");
-                    writer.append("onclick=\"javascript:toggleCollapsiblePanel(this, '").append(collapsibleAreaId).append("', '").append(expandToolTip).append("', '").append(collapseToolTip).append("');\"");
-                } else {
-                    writer.append("expanded\"><a ");
-                    writer.append("onclick=\"javascript:toggleCollapsiblePanel(this, '").append(collapsibleAreaId).append("', '").append(expandToolTip).append("', '").append(collapseToolTip).append("');\"");
-                }
-                writer.append(">&nbsp&nbsp&nbsp</a></li></ul>");
-
-                appendWhitespace(writer);
-            }
-            writer.append("</td><td>");
-
-            if (UtilValidate.isNotEmpty(title)) {
-                writer.append("<div class=\"title\">");
-                writer.append(title);
-                writer.append("</div>");
-            }
-
-            writer.append("</td></tr></table></div>");
-
-            writer.append("<div id=\"").append(collapsibleAreaId).append("\" class=\"fieldgroup-body\"");
-            if (fieldGroup.collapsible() && collapsed) {
-                writer.append(" style=\"display: none;\"");
-            }
-            writer.append(">");
-        }
-    }
-
-    public void renderFieldGroupClose(Appendable writer, Map<String, Object> context, ModelForm.FieldGroup fieldGroup) throws IOException {
-        String style = fieldGroup.getStyle();
-        String id = fieldGroup.getId();
-        String title = fieldGroup.getTitle();
-        if (UtilValidate.isNotEmpty(style) || UtilValidate.isNotEmpty(id) || UtilValidate.isNotEmpty(title)) {
-            writer.append("</div>");
-            writer.append("</div>");
-        }
-    }
-
-    // TODO: Remove embedded styling
-    public void renderBanner(Appendable writer, Map<String, Object> context, ModelForm.Banner banner) throws IOException {
-        writer.append(" <table width=\"100%\">  <tr>");
-        String style = banner.getStyle(context);
-        String leftStyle = banner.getLeftTextStyle(context);
-        if (UtilValidate.isEmpty(leftStyle)) leftStyle = style;
-        String rightStyle = banner.getRightTextStyle(context);
-        if (UtilValidate.isEmpty(rightStyle)) rightStyle = style;
-
-        String leftText = banner.getLeftText(context);
-        if (UtilValidate.isNotEmpty(leftText)) {
-            writer.append("   <td align=\"left\">");
-            if (UtilValidate.isNotEmpty(leftStyle)) {
-               writer.append("<div");
-               writer.append(" class=\"");
-               writer.append(leftStyle);
-               writer.append("\"");
-               writer.append(">");
-            }
-            writer.append(leftText);
-            if (UtilValidate.isNotEmpty(leftStyle)) {
-                writer.append("</div>");
-            }
-            writer.append("</td>");
-        }
-
-        String text = banner.getText(context);
-        if (UtilValidate.isNotEmpty(text)) {
-            writer.append("   <td align=\"center\">");
-            if (UtilValidate.isNotEmpty(style)) {
-               writer.append("<div");
-               writer.append(" class=\"");
-               writer.append(style);
-               writer.append("\"");
-               writer.append(">");
-            }
-            writer.append(text);
-            if (UtilValidate.isNotEmpty(style)) {
-                writer.append("</div>");
-            }
-            writer.append("</td>");
-        }
-
-        String rightText = banner.getRightText(context);
-        if (UtilValidate.isNotEmpty(rightText)) {
-            writer.append("   <td align=\"right\">");
-            if (UtilValidate.isNotEmpty(rightStyle)) {
-               writer.append("<div");
-               writer.append(" class=\"");
-               writer.append(rightStyle);
-               writer.append("\"");
-               writer.append(">");
-            }
-            writer.append(rightText);
-            if (UtilValidate.isNotEmpty(rightStyle)) {
-                writer.append("</div>");
-            }
-            writer.append("</td>");
-        }
-        writer.append("</tr> </table>");
-    }
-
-    /**
-     * Renders a link for the column header fields when there is a header-link="" specified in the <field > tag, using
-     * style from header-link-style="".  Also renders a selectAll checkbox in multi forms.
-     * @param writer
-     * @param context
-     * @param modelFormField
-     * @param titleText
-     */
-    public void renderHyperlinkTitle(Appendable writer, Map<String, Object> context, ModelFormField modelFormField, String titleText) throws IOException {
-        if (UtilValidate.isNotEmpty(modelFormField.getHeaderLink())) {
-            StringBuilder targetBuffer = new StringBuilder();
-            FlexibleStringExpander target = FlexibleStringExpander.getInstance(modelFormField.getHeaderLink());
-            String fullTarget = target.expandString(context);
-            targetBuffer.append(fullTarget);
-            String targetType = CommonWidgetModels.Link.DEFAULT_URL_MODE;
-            if (UtilValidate.isNotEmpty(targetBuffer.toString()) && targetBuffer.toString().toLowerCase().startsWith("javascript:")) {
-                targetType="plain";
-            }
-            WidgetWorker.makeHyperlinkString(writer, modelFormField.getHeaderLinkStyle(), targetType, targetBuffer.toString(), null, titleText, null, modelFormField, this.request, this.response, null, null);
-        } else if (modelFormField.isSortField()) {
-            renderSortField (writer, context, modelFormField, titleText);
-        } else if (modelFormField.isRowSubmit()) {
-            if (UtilValidate.isNotEmpty(titleText)) writer.append(titleText).append("<br/>");
-            writer.append("<input type=\"checkbox\" name=\"selectAll\" value=\"Y\" onclick=\"javascript:toggleAll(this, '");
-            writer.append(modelFormField.getModelForm().getName());
-            writer.append("');\"/>");
-        } else {
-             writer.append(titleText);
-        }
-    }
-
-    public void renderContainerFindField(Appendable writer, Map<String, Object> context, ContainerField containerField) throws IOException {
-        writer.append("<div ");
-        String id = containerField.getModelFormField().getIdName();
-        if (UtilValidate.isNotEmpty(id)) {
-            writer.append("id=\"");
-            writer.append(id);
-            writer.append("\" ");
-        }
-        String className = containerField.getModelFormField().getWidgetStyle();
-        if (UtilValidate.isNotEmpty(className)) {
-            writer.append("class=\"");
-            writer.append(className);
-            writer.append("\" ");
-        }
-        writer.append("/>");
-    }
-
-    /** Create an ajaxXxxx JavaScript CSV string from a list of UpdateArea objects. See
-     * <code>selectall.js</code>.
-     * @param updateAreas
-     * @param extraParams Renderer-supplied additional target parameters
-     * @param context
-     * @return Parameter string or empty string if no UpdateArea objects were found
-     */
-    public String createAjaxParamsFromUpdateAreas(List<ModelForm.UpdateArea> updateAreas, String extraParams, Map<String, ? extends Object> context) {
-        if (updateAreas == null) {
-            return "";
-        }
-        StringBuilder ajaxUrl = new StringBuilder();
-        boolean firstLoop = true;
-        for (ModelForm.UpdateArea updateArea : updateAreas) {
-            if (firstLoop) {
-                firstLoop = false;
-            } else {
-                ajaxUrl.append(",");
-            }
-            String targetUrl = updateArea.getAreaTarget(context);
-            String ajaxParams = getAjaxParamsFromTarget(targetUrl);
-            if (UtilValidate.isNotEmpty(extraParams)) {
-                if (ajaxParams.length() > 0 && !extraParams.startsWith("&")) {
-                    ajaxParams += "&";
-                }
-                ajaxParams += extraParams;
-            }
-            ajaxUrl.append(updateArea.getAreaId()).append(",");
-            try {
-                appendOfbizUrl(ajaxUrl, UtilHttp.removeQueryStringFromTarget(targetUrl));
-            } catch (IOException e) {
-                throw UtilMisc.initCause(new InternalError(e.getMessage()), e);
-            }
-            ajaxUrl.append(",").append(ajaxParams);
-        }
-        return ajaxUrl.toString();
-    }
-}
+/*******************************************************************************

+ * 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.renderer.html;

+

+import java.io.IOException;

+import java.util.HashSet;

+import java.util.LinkedList;

+import java.util.List;

+import java.util.Locale;

+import java.util.Map;

+import java.util.Map.Entry;

+

+import javax.servlet.ServletContext;

+import javax.servlet.http.HttpServletRequest;

+import javax.servlet.http.HttpServletResponse;

+

+import org.ofbiz.base.util.Debug;

+import org.ofbiz.base.util.UtilCodec;

+import org.ofbiz.base.util.UtilGenerics;

+import org.ofbiz.base.util.UtilHttp;

+import org.ofbiz.base.util.UtilMisc;

+import org.ofbiz.base.util.UtilProperties;

+import org.ofbiz.base.util.UtilValidate;

+import org.ofbiz.base.util.string.FlexibleStringExpander;

+import org.ofbiz.base.util.template.FreeMarkerWorker;

+import org.ofbiz.entity.Delegator;

+import org.ofbiz.webapp.control.RequestHandler;

+import org.ofbiz.webapp.taglib.ContentUrlTag;

+import org.ofbiz.widget.WidgetWorker;

+import org.ofbiz.widget.model.CommonWidgetModels;

+import org.ofbiz.widget.model.ModelForm;

+import org.ofbiz.widget.model.ModelFormField;

+import org.ofbiz.widget.model.ModelFormField.CheckField;

+import org.ofbiz.widget.model.ModelFormField.ContainerField;

+import org.ofbiz.widget.model.ModelFormField.DateFindField;

+import org.ofbiz.widget.model.ModelFormField.DateTimeField;

+import org.ofbiz.widget.model.ModelFormField.DisplayEntityField;

+import org.ofbiz.widget.model.ModelFormField.DisplayField;

+import org.ofbiz.widget.model.ModelFormField.DropDownField;

+import org.ofbiz.widget.model.ModelFormField.FieldInfoWithOptions;

+import org.ofbiz.widget.model.ModelFormField.FileField;

+import org.ofbiz.widget.model.ModelFormField.HiddenField;

+import org.ofbiz.widget.model.ModelFormField.HyperlinkField;

+import org.ofbiz.widget.model.ModelFormField.IgnoredField;

+import org.ofbiz.widget.model.ModelFormField.ImageField;

+import org.ofbiz.widget.model.ModelFormField.LookupField;

+import org.ofbiz.widget.model.ModelFormField.PasswordField;

+import org.ofbiz.widget.model.ModelFormField.RadioField;

+import org.ofbiz.widget.model.ModelFormField.RangeFindField;

+import org.ofbiz.widget.model.ModelFormField.ResetField;

+import org.ofbiz.widget.model.ModelFormField.SubmitField;

+import org.ofbiz.widget.model.ModelFormField.TextField;

+import org.ofbiz.widget.model.ModelFormField.TextFindField;

+import org.ofbiz.widget.model.ModelFormField.TextareaField;

+import org.ofbiz.widget.model.ModelWidget;

+import org.ofbiz.widget.renderer.FormRenderer;

+import org.ofbiz.widget.renderer.FormStringRenderer;

+import org.ofbiz.widget.renderer.Paginator;

+import org.ofbiz.widget.renderer.UtilHelpText;

+import org.ofbiz.widget.renderer.macro.MacroFormRenderer;

+

+import freemarker.template.TemplateException;

+

+/**

+ * Widget Library - HTML Form Renderer implementation

+ */

+public class HtmlFormRenderer extends HtmlWidgetRenderer implements FormStringRenderer {

+

+    public static final String module = HtmlFormRenderer.class.getName();

+

+    protected HttpServletRequest request;

+    protected HttpServletResponse response;

+    protected RequestHandler rh;

+    protected String lastFieldGroupId = "";

+    protected boolean renderPagination = true;

+    protected boolean javaScriptEnabled = false;

+    private UtilCodec.SimpleEncoder internalEncoder;

+

+    protected HtmlFormRenderer() {}

+

+    public HtmlFormRenderer(HttpServletRequest request, HttpServletResponse response) {

+        this.request = request;

+        this.response = response;

+        ServletContext ctx = (ServletContext) request.getAttribute("servletContext");

+        this.rh = (RequestHandler) ctx.getAttribute("_REQUEST_HANDLER_");

+        this.javaScriptEnabled = UtilHttp.isJavaScriptEnabled(request);

+        internalEncoder = UtilCodec.getEncoder("string");

+    }

+

+    public boolean getRenderPagination() {

+        return this.renderPagination;

+    }

+

+    public void setRenderPagination(boolean renderPagination) {

+        this.renderPagination = renderPagination;

+    }

+

+    public void appendOfbizUrl(Appendable writer, String location) throws IOException {

+        writer.append(this.rh.makeLink(this.request, this.response, location));

+    }

+

+    public void appendContentUrl(Appendable writer, String location) throws IOException {

+        ContentUrlTag.appendContentPrefix(this.request, writer);

+        writer.append(location);

+    }

+

+    public void appendTooltip(Appendable writer, Map<String, Object> context, ModelFormField modelFormField) throws IOException {

+        // render the tooltip, in other methods too

+        String tooltip = modelFormField.getTooltip(context);

+        if (UtilValidate.isNotEmpty(tooltip)) {

+            writer.append("<span class=\"");

+            String tooltipStyle = modelFormField.getTooltipStyle();

+            if (UtilValidate.isNotEmpty(tooltipStyle)) {

+                writer.append(tooltipStyle);

+            } else {

+                writer.append("tooltip");

+            }

+            writer.append("\">");

+            writer.append(tooltip);

+            writer.append("</span>");

+        }

+    }

+

+    public void addAsterisks(Appendable writer, Map<String, Object> context, ModelFormField modelFormField) throws IOException {

+

+        boolean requiredField = modelFormField.getRequiredField();

+        if (requiredField) {

+            String requiredStyle = modelFormField.getRequiredFieldStyle();

+

+            if (UtilValidate.isEmpty(requiredStyle)) {

+               writer.append("*");

+            }

+        }

+    }

+

+    public void appendClassNames(Appendable writer, Map<String, Object> context, ModelFormField modelFormField) throws IOException {

+        String className = modelFormField.getWidgetStyle();

+        if (UtilValidate.isNotEmpty(className) || modelFormField.shouldBeRed(context)) {

+            writer.append(" class=\"");

+            writer.append(className);

+            // add a style of red if redWhen is true

+            if (modelFormField.shouldBeRed(context)) {

+                writer.append(" alert");

+            }

+            writer.append('"');

+        }

+    }

+

+    /* (non-Javadoc)

+     * @see org.ofbiz.widget.form.FormStringRenderer#renderDisplayField(java.io.Writer, java.util.Map, org.ofbiz.widget.model.ModelFormField.DisplayField)

+     */

+    public void renderDisplayField(Appendable writer, Map<String, Object> context, DisplayField displayField) throws IOException {

+        ModelFormField modelFormField = displayField.getModelFormField();

+

+        StringBuilder str = new StringBuilder();

+

+        String idName = modelFormField.getCurrentContainerId(context);

+

+        if (UtilValidate.isNotEmpty(modelFormField.getWidgetStyle()) || modelFormField.shouldBeRed(context)) {

+            str.append("<span class=\"");

+            str.append(modelFormField.getWidgetStyle());

+            // add a style of red if this is a date/time field and redWhen is true

+            if (modelFormField.shouldBeRed(context)) {

+                str.append(" alert");

+            }

+            str.append('"');

+            if (UtilValidate.isNotEmpty(idName)) {

+                str.append(" id=\"");

+                str.append(idName+"_sp");

+                str.append('"');

+            }

+            str.append('>');

+        }

+

+        if (str.length() > 0) {

+            writer.append(str.toString());

+        }

+        String description = displayField.getDescription(context);

+        //Replace new lines with <br/>

+        description = description.replaceAll("\n", "<br/>");

+

+        if (UtilValidate.isEmpty(description)) {

+            this.renderFormatEmptySpace(writer, context, modelFormField.getModelForm());

+        } else {

+            writer.append(description);

+        }

+

+        if (str.length() > 0) {

+            writer.append("</span>");

+        }

+

+        ModelFormField.InPlaceEditor inPlaceEditor = displayField.getInPlaceEditor();

+        boolean ajaxEnabled = inPlaceEditor != null && this.javaScriptEnabled;

+

+        if (ajaxEnabled) {

+            writer.append("<script language=\"JavaScript\" type=\"text/javascript\">");

+            StringBuilder url = new StringBuilder(inPlaceEditor.getUrl(context));

+            Map<String, Object> fieldMap = inPlaceEditor.getFieldMap(context);

+            if (fieldMap != null) {

+                url.append('?');

+                int count = 0;

+                for (Entry<String, Object> field: fieldMap.entrySet()) {

+                    count++;

+                    url.append(field.getKey()).append('=').append(field.getValue());

+                    if (count < fieldMap.size()) {

+                        url.append('&');

+                    }

+                }

+            }

+            writer.append("ajaxInPlaceEditDisplayField('");

+            writer.append(idName).append("', '").append(url).append("', {");

+            if (UtilValidate.isNotEmpty(inPlaceEditor.getParamName())) {

+                writer.append("name: '").append(inPlaceEditor.getParamName()).append("'");

+            } else {

+                writer.append("name: '").append(modelFormField.getFieldName()).append("'");

+            }

+            if (UtilValidate.isNotEmpty(inPlaceEditor.getCancelControl())) {

+                writer.append(", cancelControl: ");

+                if (!"false".equals(inPlaceEditor.getCancelControl())) {

+                    writer.append("'");

+                }

+                writer.append(inPlaceEditor.getCancelControl());

+                if (!"false".equals(inPlaceEditor.getCancelControl())) {

+                    writer.append("'");

+                }

+            }

+            if (UtilValidate.isNotEmpty(inPlaceEditor.getCancelText())) {

+                writer.append(", cancel: '").append(inPlaceEditor.getCancelText()).append("'");

+            }

+            if (UtilValidate.isNotEmpty(inPlaceEditor.getClickToEditText())) {

+                writer.append(", tooltip: '").append(inPlaceEditor.getClickToEditText()).append("'");

+            }

+            if (UtilValidate.isNotEmpty(inPlaceEditor.getFieldPostCreation())) {

+                writer.append(", fieldPostCreation: ");

+                if (!"false".equals(inPlaceEditor.getFieldPostCreation())) {

+                    writer.append("'");

+                }

+                writer.append(inPlaceEditor.getFieldPostCreation());

+                if (!"false".equals(inPlaceEditor.getFieldPostCreation())) {

+                    writer.append("'");

+                }

+            }

+            if (UtilValidate.isNotEmpty(inPlaceEditor.getFormClassName())) {

+                writer.append(", cssclass: '").append(inPlaceEditor.getFormClassName()).append("'");

+            }

+            if (UtilValidate.isNotEmpty(inPlaceEditor.getHighlightColor())) {

+                writer.append(", highlightColor: '").append(inPlaceEditor.getHighlightColor()).append("'");

+            }

+            if (UtilValidate.isNotEmpty(inPlaceEditor.getHighlightEndColor())) {

+                writer.append(", highlightEndColor: '").append(inPlaceEditor.getHighlightEndColor()).append("'");

+            }

+            if (UtilValidate.isNotEmpty(inPlaceEditor.getHoverClassName())) {

+                writer.append(", hoverClassName: '").append(inPlaceEditor.getHoverClassName()).append("'");

+            }

+            if (UtilValidate.isNotEmpty(inPlaceEditor.getHtmlResponse())) {

+                writer.append(", htmlResponse: ").append(inPlaceEditor.getHtmlResponse());

+            }

+            if (UtilValidate.isNotEmpty(inPlaceEditor.getLoadingClassName())) {

+                writer.append(", loadingClassName: '").append(inPlaceEditor.getLoadingClassName()).append("'");

+            }

+            if (UtilValidate.isNotEmpty(inPlaceEditor.getLoadingText())) {

+                writer.append(", indicator: '").append(inPlaceEditor.getLoadingText()).append("'");

+            }

+            if (UtilValidate.isNotEmpty(inPlaceEditor.getOkControl())) {

+                writer.append(", submit: ");

+                if (!"false".equals(inPlaceEditor.getOkControl())) {

+                    writer.append("'");

+                }

+                writer.append(inPlaceEditor.getOkControl());

+                if (!"false".equals(inPlaceEditor.getOkControl())) {

+                    writer.append("'");

+                }

+            }

+            if (UtilValidate.isNotEmpty(inPlaceEditor.getOkText())) {

+                writer.append(", okText: '").append(inPlaceEditor.getOkText()).append("'");

+            }

+            if (UtilValidate.isNotEmpty(inPlaceEditor.getSavingClassName())) {

+                writer.append(", savingClassName: '").append(inPlaceEditor.getSavingClassName()).append("', ");

+            }

+            if (UtilValidate.isNotEmpty(inPlaceEditor.getSavingText())) {

+                writer.append(", savingText: '").append(inPlaceEditor.getSavingText()).append("'");

+            }

+            if (UtilValidate.isNotEmpty(inPlaceEditor.getSubmitOnBlur())) {

+                writer.append(", submitOnBlur: ").append(inPlaceEditor.getSubmitOnBlur());

+            }

+            if (UtilValidate.isNotEmpty(inPlaceEditor.getTextBeforeControls())) {

+                writer.append(", textBeforeControls: '").append(inPlaceEditor.getTextBeforeControls()).append("'");

+            }

+            if (UtilValidate.isNotEmpty(inPlaceEditor.getTextAfterControls())) {

+                writer.append(", textAfterControls: '").append(inPlaceEditor.getTextAfterControls()).append("'");

+            }

+            if (UtilValidate.isNotEmpty(inPlaceEditor.getTextBetweenControls())) {

+                writer.append(", textBetweenControls: '").append(inPlaceEditor.getTextBetweenControls()).append("'");

+            }

+            if (UtilValidate.isNotEmpty(inPlaceEditor.getUpdateAfterRequestCall())) {

+                writer.append(", updateAfterRequestCall: ").append(inPlaceEditor.getUpdateAfterRequestCall());

+            }

+            if (UtilValidate.isNotEmpty(inPlaceEditor.getRows())) {

+                writer.append(", rows: '").append(inPlaceEditor.getRows()).append("'");

+            }

+            if (UtilValidate.isNotEmpty(inPlaceEditor.getCols())) {

+                writer.append(", cols: '").append(inPlaceEditor.getCols()).append("'");

+            }

+            writer.append("});");

+            writer.append("</script>");

+        }

+

+        if (displayField instanceof DisplayEntityField) {

+            this.makeHyperlinkString(writer, ((DisplayEntityField) displayField).getSubHyperlink(), context);

+        }

+

+        this.appendTooltip(writer, context, modelFormField);

+

+        //appendWhitespace(writer);

+    }

+

+    /* (non-Javadoc)

+     * @see org.ofbiz.widget.form.FormStringRenderer#renderHyperlinkField(java.io.Writer, java.util.Map, org.ofbiz.widget.model.ModelFormField.HyperlinkField)

+     */

+    public void renderHyperlinkField(Appendable writer, Map<String, Object> context, HyperlinkField hyperlinkField) throws IOException {

+        this.request.setAttribute("image", hyperlinkField.getImageLocation(context));

+        ModelFormField modelFormField = hyperlinkField.getModelFormField();

+        String description = encode(hyperlinkField.getDescription(context), modelFormField, context);

+        String confirmation = encode(hyperlinkField.getConfirmation(context), modelFormField, context);

+        WidgetWorker.makeHyperlinkByType(writer, hyperlinkField.getLinkType(), modelFormField.getWidgetStyle(), hyperlinkField.getUrlMode(), hyperlinkField.getTarget(context),

+                hyperlinkField.getParameterMap(context), description, hyperlinkField.getTargetWindow(context), confirmation, modelFormField,

+                this.request, this.response, context);

+        this.appendTooltip(writer, context, modelFormField);

+        //appendWhitespace(writer);

+    }

+

+    public void makeHyperlinkString(Appendable writer, ModelFormField.SubHyperlink subHyperlink, Map<String, Object> context) throws IOException {

+        if (subHyperlink == null) {

+            return;

+        }

+        if (subHyperlink.shouldUse(context)) {

+            writer.append(' ');

+            String description = encode(subHyperlink.getDescription(context), subHyperlink.getModelFormField(), context);

+            WidgetWorker.makeHyperlinkByType(writer, subHyperlink.getLinkType(), subHyperlink.getStyle(context), subHyperlink.getUrlMode(), subHyperlink.getTarget(context),

+                    subHyperlink.getParameterMap(context), description, subHyperlink.getTargetWindow(context), null, subHyperlink.getModelFormField(),

+                    this.request, this.response, context);

+        }

+    }

+

+    private String encode(String value, ModelFormField modelFormField, Map<String, Object> context) {

+        if (UtilValidate.isEmpty(value)) {

+            return value;

+        }

+        UtilCodec.SimpleEncoder encoder = (UtilCodec.SimpleEncoder)context.get("simpleEncoder");

+        if (modelFormField.getEncodeOutput() && encoder != null) {

+            value = encoder.encode(value);

+        } else {

+            value = internalEncoder.encode(value);

+        }

+        return value;

+    }

+

+    /* (non-Javadoc)

+     * @see org.ofbiz.widget.form.FormStringRenderer#renderTextField(java.io.Writer, java.util.Map, org.ofbiz.widget.model.ModelFormField.TextField)

+     */

+    public void renderTextField(Appendable writer, Map<String, Object> context, TextField textField) throws IOException {

+        ModelFormField modelFormField = textField.getModelFormField();

+

+        writer.append("<input type=\"text\"");

+

+        appendClassNames(writer, context, modelFormField);

+

+        writer.append(" name=\"");

+        writer.append(modelFormField.getParameterName(context));

+        writer.append('"');

+

+        String value = modelFormField.getEntry(context, textField.getDefaultValue(context));

+        if (UtilValidate.isNotEmpty(value)) {

+            writer.append(" value=\"");

+            writer.append(value);

+            writer.append('"');

+        }

+

+        writer.append(" size=\"");

+        writer.append(Integer.toString(textField.getSize()));

+        writer.append('"');

+

+        Integer maxlength = textField.getMaxlength();

+        if (maxlength != null) {

+            writer.append(" maxlength=\"");

+            writer.append(maxlength.toString());

+            writer.append('"');

+        }

+

+        String idName = modelFormField.getCurrentContainerId(context);

+        if (UtilValidate.isNotEmpty(idName)) {

+            writer.append(" id=\"");

+            writer.append(idName);

+            writer.append('"');

+        }

+

+        String event = modelFormField.getEvent();

+        String action = modelFormField.getAction(context);

+        if (UtilValidate.isNotEmpty(event) && UtilValidate.isNotEmpty(action)) {

+            writer.append(" ");

+            writer.append(event);

+            writer.append("=\"");

+            writer.append(action);

+            writer.append('"');

+        }

+

+        List<ModelForm.UpdateArea> updateAreas = modelFormField.getOnChangeUpdateAreas();

+        boolean ajaxEnabled = updateAreas != null && this.javaScriptEnabled;

+        if (!textField.getClientAutocompleteField() || ajaxEnabled) {

+            writer.append(" autocomplete=\"off\"");

+        }

+

+        writer.append("/>");

+

+        this.addAsterisks(writer, context, modelFormField);

+

+        this.makeHyperlinkString(writer, textField.getSubHyperlink(), context);

+

+        this.appendTooltip(writer, context, modelFormField);

+

+        if (ajaxEnabled) {

+            appendWhitespace(writer);

+            writer.append("<script language=\"JavaScript\" type=\"text/javascript\">");

+            appendWhitespace(writer);

+            writer.append("ajaxAutoCompleter('").append(createAjaxParamsFromUpdateAreas(updateAreas, null, context)).append("');");

+            appendWhitespace(writer);

+            writer.append("</script>");

+        }

+        appendWhitespace(writer);

+    }

+

+    /* (non-Javadoc)

+     * @see org.ofbiz.widget.form.FormStringRenderer#renderTextareaField(java.io.Writer, java.util.Map, org.ofbiz.widget.model.ModelFormField.TextareaField)

+     */

+    public void renderTextareaField(Appendable writer, Map<String, Object> context, TextareaField textareaField) throws IOException {

+        ModelFormField modelFormField = textareaField.getModelFormField();

+

+        writer.append("<textarea");

+

+        appendClassNames(writer, context, modelFormField);

+

+        writer.append(" name=\"");

+        writer.append(modelFormField.getParameterName(context));

+        writer.append('"');

+

+        writer.append(" cols=\"");

+        writer.append(Integer.toString(textareaField.getCols()));

+        writer.append('"');

+

+        writer.append(" rows=\"");

+        writer.append(Integer.toString(textareaField.getRows()));

+        writer.append('"');

+

+        String idName = modelFormField.getCurrentContainerId(context);

+        if (UtilValidate.isNotEmpty(idName)) {

+            writer.append(" id=\"");

+            writer.append(idName);

+            writer.append('"');

+        } else if (textareaField.getVisualEditorEnable()) {

+            writer.append(" id=\"");

+            writer.append("htmlEditArea");

+            writer.append('"');

+        }

+

+        if (textareaField.isReadOnly()) {

+            writer.append(" readonly");

+        }

+

+        writer.append('>');

+

+        String value = modelFormField.getEntry(context, textareaField.getDefaultValue(context));

+        if (UtilValidate.isNotEmpty(value)) {

+            writer.append(value);

+        }

+

+        writer.append("</textarea>");

+

+        if (textareaField.getVisualEditorEnable()) {

+            writer.append("<script language=\"javascript\" src=\"/images/jquery/plugins/elrte-1.3/js/elrte.min.js\" type=\"text/javascript\"></script>");

+            writer.append("<link href=\"/images/jquery/plugins/elrte-1.3/css/elrte.min.css\" rel=\"stylesheet\" type=\"text/css\">");

+            writer.append("<script language=\"javascript\" type=\"text/javascript\"> var opts = { cssClass : 'el-rte', toolbar : ");

+            // define the toolsbar

+            String buttons = textareaField.getVisualEditorButtons(context);

+            if (UtilValidate.isNotEmpty(buttons)) {

+                writer.append(buttons);

+            } else {

+                writer.append("maxi");

+            }

+            writer.append(", doctype  : '<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">', //'<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\">'");

+            writer.append(", cssfiles : ['/images/jquery/plugins/elrte-1.3/css/elrte-inner.css'] ");

+            writer.append("}");

+            // load the wysiwyg editor

+            writer.append("jQuery('#");

+            if (UtilValidate.isNotEmpty(idName)) {

+                writer.append(idName);

+            } else {

+                writer.append("htmlEditArea");

+            }

+            writer.append("').elrte(opts);");

+            writer.append("</script>");

+        }

+

+        this.addAsterisks(writer, context, modelFormField);

+

+        this.appendTooltip(writer, context, modelFormField);

+

+        //appendWhitespace(writer);

+    }

+

+    /* (non-Javadoc)

+     * @see org.ofbiz.widget.form.FormStringRenderer#renderDateTimeField(java.io.Writer, java.util.Map, org.ofbiz.widget.model.ModelFormField.DateTimeField)

+     */

+    public void renderDateTimeField(Appendable writer, Map<String, Object> context, DateTimeField dateTimeField) throws IOException {

+        String macroLibraryPath = UtilProperties.getPropertyValue("widget", "screen.formrenderer");

+        try {

+            MacroFormRenderer macroFormRenderer = new MacroFormRenderer(macroLibraryPath, this.request, this.response);

+            macroFormRenderer.renderDateTimeField(writer, context, dateTimeField);

+        } catch (TemplateException e) {

+            Debug.logError(e, "Error rendering screen thru ftl macro: renderDateTimeField", module);

+        } catch (IOException e) {

+            Debug.logError(e, "Error rendering screen thru ftl, macro: renderDateTimeField", module);

+        }

+    }

+

+    /* (non-Javadoc)

+     * @see org.ofbiz.widget.form.FormStringRenderer#renderDropDownField(java.io.Writer, java.util.Map, org.ofbiz.widget.model.ModelFormField.DropDownField)

+     */

+    public void renderDropDownField(Appendable writer, Map<String, Object> context, DropDownField dropDownField) throws IOException {

+        ModelFormField modelFormField = dropDownField.getModelFormField();

+        ModelForm modelForm = modelFormField.getModelForm();

+        ModelFormField.AutoComplete autoComplete = dropDownField.getAutoComplete();

+        boolean ajaxEnabled = autoComplete != null && this.javaScriptEnabled;

+        List<ModelFormField.OptionValue> allOptionValues = dropDownField.getAllOptionValues(context, WidgetWorker.getDelegator(context));

+

+        String event = modelFormField.getEvent();

+        String action = modelFormField.getAction(context);

+

+        String currentValue = modelFormField.getEntry(context);

+        // Get the current value's description from the option value. If there

+        // is a localized version it will be there.

+        String currentDescription = null;

+        if (UtilValidate.isNotEmpty(currentValue)) {

+            for (ModelFormField.OptionValue optionValue : allOptionValues) {

+                if (encode(optionValue.getKey(), modelFormField, context).equals(currentValue)) {

+                    currentDescription = optionValue.getDescription();

+                    break;

+                }

+            }

+        }

+

+        if (ajaxEnabled) {

+            writer.append("<input type=\"text\"");

+        } else {

+            writer.append("<select");

+        }

+

+        appendClassNames(writer, context, modelFormField);

+

+        writer.append(" name=\"");

+        writer.append(modelFormField.getParameterName(context));

+

+        String idName = modelFormField.getCurrentContainerId(context);

+

+        if (ajaxEnabled) {

+            writer.append("_description\"");

+

+            String textFieldIdName = idName;

+            if (UtilValidate.isNotEmpty(textFieldIdName)) {

+                textFieldIdName += "_description";

+                writer.append(" id=\"");

+                writer.append(textFieldIdName);

+                writer.append('"');

+            }

+

+            if (UtilValidate.isNotEmpty(currentValue)) {

+                writer.append(" value=\"");

+                String explicitDescription = null;

+                if (currentDescription != null) {

+                    explicitDescription = currentDescription;

+                } else {

+                    explicitDescription = dropDownField.getCurrentDescription(context);

+                }

+                if (UtilValidate.isEmpty(explicitDescription)) {

+                    explicitDescription = FieldInfoWithOptions.getDescriptionForOptionKey(currentValue, allOptionValues);

+                }

+                explicitDescription = encode(explicitDescription, modelFormField, context);

+                writer.append(explicitDescription);

+                writer.append('"');

+            }

+            writer.append("/>");

+

+            appendWhitespace(writer);

+            writer.append("<input type=\"hidden\" name=\"");

+            writer.append(modelFormField.getParameterName(context));

+            writer.append('"');

+            if (UtilValidate.isNotEmpty(idName)) {

+                writer.append(" id=\"");

+                writer.append(idName);

+                writer.append('"');

+            }

+

+            if (UtilValidate.isNotEmpty(currentValue)) {

+                writer.append(" value=\"");

+                //String explicitDescription = dropDownField.getCurrentDescription(context);

+                writer.append(currentValue);

+                writer.append('"');

+            }

+

+            writer.append("/>");

+

+            appendWhitespace(writer);

+            writer.append("<script language=\"JavaScript\" type=\"text/javascript\">");

+            appendWhitespace(writer);

+            writer.append("var data = {");

+            int count = 0;

+            for (ModelFormField.OptionValue optionValue: allOptionValues) {

+                count++;

+                writer.append(optionValue.getKey()).append(": ");

+                writer.append(" '").append(optionValue.getDescription()).append("'");

+                if (count != allOptionValues.size()) {

+                    writer.append(", ");

+                }

+            }

+            writer.append("};");

+            appendWhitespace(writer);

+            writer.append("ajaxAutoCompleteDropDown('").append(textFieldIdName).append("', '").append(idName).append("', data, {autoSelect: ").append(

+                    autoComplete.getAutoSelect()).append(", frequency: ").append(autoComplete.getFrequency()).append(", minChars: ").append(autoComplete.getMinChars()).append(

+                    ", choices: ").append(autoComplete.getChoices()).append(", partialSearch: ").append(autoComplete.getPartialSearch()).append(

+                    ", partialChars: ").append(autoComplete.getPartialChars()).append(", ignoreCase: ").append(autoComplete.getIgnoreCase()).append(

+                    ", fullSearch: ").append(autoComplete.getFullSearch()).append("});");

+            appendWhitespace(writer);

+            writer.append("</script>");

+        } else {

+            writer.append('"');

+

+            if (UtilValidate.isNotEmpty(idName)) {

+                writer.append(" id=\"");

+                writer.append(idName);

+                writer.append('"');

+            }

+

+            if (dropDownField.getAllowMultiple()) {

+                writer.append(" multiple=\"multiple\"");

+            }

+

+            int otherFieldSize = dropDownField.getOtherFieldSize();

+            String otherFieldName = dropDownField.getParameterNameOther(context);

+            if (otherFieldSize > 0) {

+                //writer.append(" onchange=\"alert('ONCHANGE, process_choice:' + process_choice)\"");

+                //writer.append(" onchange='test_js()' ");

+                writer.append(" onchange=\"process_choice(this,document.");

+                writer.append(modelForm.getName());

+                writer.append(".");

+                writer.append(otherFieldName);

+                writer.append(")\" ");

+            }

+

+            if (UtilValidate.isNotEmpty(event) && UtilValidate.isNotEmpty(action)) {

+                writer.append(" ");

+                writer.append(event);

+                writer.append("=\"");

+                writer.append(action);

+                writer.append('"');

+            }

+

+            writer.append(" size=\"").append(dropDownField.getSize()).append("\">");

+

+            // if the current value should go first, stick it in

+            if (UtilValidate.isNotEmpty(currentValue) && "first-in-list".equals(dropDownField.getCurrent())) {

+                writer.append("<option");

+                writer.append(" selected=\"selected\"");

+                writer.append(" value=\"");

+                writer.append(currentValue);

+                writer.append("\">");

+                String explicitDescription = (currentDescription != null ? currentDescription : dropDownField.getCurrentDescription(context));

+                if (UtilValidate.isNotEmpty(explicitDescription)) {

+                    writer.append(encode(explicitDescription, modelFormField, context));

+                } else {

+                    String description = FieldInfoWithOptions.getDescriptionForOptionKey(currentValue, allOptionValues);

+                    writer.append(encode(description, modelFormField, context));

+                }

+                writer.append("</option>");

+

+                // add a "separator" option

+                writer.append("<option value=\"");

+                writer.append(currentValue);

+                writer.append("\">---</option>");

+            }

+

+            // if allow empty is true, add an empty option

+            if (dropDownField.getAllowEmpty()) {

+                writer.append("<option value=\"\">&nbsp;</option>");

+            }

+

+            // list out all options according to the option list

+            for (ModelFormField.OptionValue optionValue: allOptionValues) {

+                String noCurrentSelectedKey = dropDownField.getNoCurrentSelectedKey(context);

+                writer.append("<option");

+                // if current value should be selected in the list, select it

+                if (UtilValidate.isNotEmpty(currentValue) && currentValue.equals(optionValue.getKey()) && "selected".equals(dropDownField.getCurrent())) {

+                    writer.append(" selected=\"selected\"");

+                } else if (UtilValidate.isEmpty(currentValue) && noCurrentSelectedKey != null && noCurrentSelectedKey.equals(optionValue.getKey())) {

+                    writer.append(" selected=\"selected\"");

+                }

+                writer.append(" value=\"");

+                writer.append(encode(optionValue.getKey(), modelFormField, context));

+                writer.append("\">");

+                writer.append(encode(optionValue.getDescription(), modelFormField, context));

+                writer.append("</option>");

+            }

+

+            writer.append("</select>");

+

+

+            // Adapted from work by Yucca Korpela

+            // http://www.cs.tut.fi/~jkorpela/forms/combo.html

+            if (otherFieldSize > 0) {

+

+                String fieldName = modelFormField.getParameterName(context);

+                Map<String, Object> dataMap = UtilGenerics.checkMap(modelFormField.getMap(context));

+                if (dataMap == null) {

+                    dataMap = context;

+                }

+                Object otherValueObj = dataMap.get(otherFieldName);

+                String otherValue = (otherValueObj == null) ? "" : otherValueObj.toString();

+

+                writer.append("<noscript>");

+                writer.append("<input type='text' name='");

+                writer.append(otherFieldName);

+                writer.append("'/> ");

+                writer.append("</noscript>");

+                writer.append("\n<script type='text/javascript' language='JavaScript'><!--");

+                writer.append("\ndisa = ' disabled';");

+                writer.append("\nif (other_choice(document.");

+                writer.append(modelForm.getName());

+                writer.append(".");

+                writer.append(fieldName);

+                writer.append(")) disa = '';");

+                writer.append("\ndocument.write(\"<input type=");

+                writer.append("'text' name='");

+                writer.append(otherFieldName);

+                writer.append("' value='");

+                writer.append(otherValue);

+                writer.append("' size='");

+                writer.append(Integer.toString(otherFieldSize));

+                writer.append("' ");

+                writer.append("\" +disa+ \" onfocus='check_choice(document.");

+                writer.append(modelForm.getName());

+                writer.append(".");

+                writer.append(fieldName);

+                writer.append(")'/>\");");

+                writer.append("\nif (disa && document.styleSheets)");

+                writer.append(" document.");

+                writer.append(modelForm.getName());

+                writer.append(".");

+                writer.append(otherFieldName);

+                writer.append(".style.visibility  = 'hidden';");

+                writer.append("\n//--></script>");

+            }

+        }

+

+        this.makeHyperlinkString(writer, dropDownField.getSubHyperlink(), context);

+

+        this.appendTooltip(writer, context, modelFormField);

+

+        //appendWhitespace(writer);

+    }

+

+    /* (non-Javadoc)

+     * @see org.ofbiz.widget.form.FormStringRenderer#renderCheckField(java.io.Writer, java.util.Map, org.ofbiz.widget.model.ModelFormField.CheckField)

+     */

+    public void renderCheckField(Appendable writer, Map<String, Object> context, CheckField checkField) throws IOException {

+        ModelFormField modelFormField = checkField.getModelFormField();

+        String currentValue = modelFormField.getEntry(context);

+        Boolean allChecked = checkField.isAllChecked(context);

+

+        List<ModelFormField.OptionValue> allOptionValues = checkField.getAllOptionValues(context, WidgetWorker.getDelegator(context));

+        String event = modelFormField.getEvent();

+        String action = modelFormField.getAction(context);

+

+        // list out all options according to the option list

+        for (ModelFormField.OptionValue optionValue: allOptionValues) {

+

+            writer.append("<input type=\"checkbox\"");

+

+            appendClassNames(writer, context, modelFormField);

+

+            // if current value should be selected in the list, select it

+            if (Boolean.TRUE.equals(allChecked)) {

+                writer.append(" checked=\"checked\"");

+            } else if (Boolean.FALSE.equals(allChecked)) {

+                // do nothing

+            } else if (UtilValidate.isNotEmpty(currentValue) && currentValue.equals(optionValue.getKey())) {

+                writer.append(" checked=\"checked\"");

+            }

+            writer.append(" name=\"");

+            writer.append(modelFormField.getParameterName(context));

+            writer.append('"');

+            writer.append(" value=\"");

+            writer.append(encode(optionValue.getKey(), modelFormField, context));

+            writer.append("\"");

+

+            if (UtilValidate.isNotEmpty(event) && UtilValidate.isNotEmpty(action)) {

+                writer.append(" ");

+                writer.append(event);

+                writer.append("=\"");

+                writer.append(action);

+                writer.append('"');

+            }

+

+            writer.append("/>");

+

+            writer.append(encode(optionValue.getDescription(), modelFormField, context));

+        }

+

+        this.appendTooltip(writer, context, modelFormField);

+

+        //appendWhitespace(writer);

+    }

+

+    /* (non-Javadoc)

+     * @see org.ofbiz.widget.form.FormStringRenderer#renderRadioField(java.io.Writer, java.util.Map, org.ofbiz.widget.model.ModelFormField.RadioField)

+     */

+    public void renderRadioField(Appendable writer, Map<String, Object> context, RadioField radioField) throws IOException {

+        ModelFormField modelFormField = radioField.getModelFormField();

+        List<ModelFormField.OptionValue> allOptionValues = radioField.getAllOptionValues(context, WidgetWorker.getDelegator(context));

+        String currentValue = modelFormField.getEntry(context);

+        String event = modelFormField.getEvent();

+        String action = modelFormField.getAction(context);

+

+        // list out all options according to the option list

+        for (ModelFormField.OptionValue optionValue: allOptionValues) {

+

+            writer.append("<span");

+

+            appendClassNames(writer, context, modelFormField);

+

+            writer.append("><input type=\"radio\"");

+

+            // if current value should be selected in the list, select it

+            String noCurrentSelectedKey = radioField.getNoCurrentSelectedKey(context);

+            if (UtilValidate.isNotEmpty(currentValue) && currentValue.equals(optionValue.getKey())) {

+                writer.append(" checked=\"checked\"");

+            } else if (UtilValidate.isEmpty(currentValue) && noCurrentSelectedKey != null && noCurrentSelectedKey.equals(optionValue.getKey())) {

+                writer.append(" checked=\"checked\"");

+            }

+            writer.append(" name=\"");

+            writer.append(modelFormField.getParameterName(context));

+            writer.append('"');

+            writer.append(" value=\"");

+            writer.append(encode(optionValue.getKey(), modelFormField, context));

+            writer.append("\"");

+

+            if (UtilValidate.isNotEmpty(event) && UtilValidate.isNotEmpty(action)) {

+                writer.append(" ");

+                writer.append(event);

+                writer.append("=\"");

+                writer.append(action);

+                writer.append('"');

+            }

+

+            writer.append("/>");

+

+            writer.append(encode(optionValue.getDescription(), modelFormField, context));

+            writer.append("</span>");

+        }

+

+        this.appendTooltip(writer, context, modelFormField);

+

+        //appendWhitespace(writer);

+    }

+

+    /* (non-Javadoc)

+     * @see org.ofbiz.widget.form.FormStringRenderer#renderSubmitField(java.io.Writer, java.util.Map, org.ofbiz.widget.model.ModelFormField.SubmitField)

+     */

+    public void renderSubmitField(Appendable writer, Map<String, Object> context, SubmitField submitField) throws IOException {

+        ModelFormField modelFormField = submitField.getModelFormField();

+        ModelForm modelForm = modelFormField.getModelForm();

+        String event = null;

+        String action = null;

+        String confirmation =  encode(submitField.getConfirmation(context), modelFormField, context);

+

+        if ("text-link".equals(submitField.getButtonType())) {

+            writer.append("<a");

+

+            appendClassNames(writer, context, modelFormField);

+            if (UtilValidate.isNotEmpty(confirmation)) {

+                writer.append(" onclick=\"return confirm('");

+                writer.append(confirmation);

+                writer.append("'); \" ");

+            }

+

+            writer.append(" href=\"javascript:document.");

+            writer.append(FormRenderer.getCurrentFormName(modelForm, context));

+            writer.append(".submit()\">");

+

+            writer.append(encode(modelFormField.getTitle(context), modelFormField, context));

+

+            writer.append("</a>");

+        } else if ("image".equals(submitField.getButtonType())) {

+            writer.append("<input type=\"image\"");

+

+            appendClassNames(writer, context, modelFormField);

+

+            writer.append(" name=\"");

+            writer.append(modelFormField.getParameterName(context));

+            writer.append('"');

+

+            String title = modelFormField.getTitle(context);

+            if (UtilValidate.isNotEmpty(title)) {

+                writer.append(" alt=\"");

+                writer.append(encode(title, modelFormField, context));

+                writer.append('"');

+            }

+

+            writer.append(" src=\"");

+            this.appendContentUrl(writer, submitField.getImageLocation(context));

+            writer.append('"');

+

+            event = modelFormField.getEvent();

+            action = modelFormField.getAction(context);

+            if (UtilValidate.isNotEmpty(event) && UtilValidate.isNotEmpty(action)) {

+                writer.append(" ");

+                writer.append(event);

+                writer.append("=\"");

+                writer.append(action);

+                writer.append('"');

+            }

+

+            if (UtilValidate.isNotEmpty(confirmation)) {

+                writer.append("onclick=\" return confirm('");

+                writer.append(confirmation);

+                writer.append("); \" ");

+            }

+

+            writer.append("/>");

+        } else {

+            // default to "button"

+

+            String formId = modelForm.getContainerId();

+            List<ModelForm.UpdateArea> updateAreas = modelForm.getOnSubmitUpdateAreas();

+            // This is here for backwards compatibility. Use on-event-update-area

+            // elements instead.

+            String backgroundSubmitRefreshTarget = submitField.getBackgroundSubmitRefreshTarget(context);

+            if (UtilValidate.isNotEmpty(backgroundSubmitRefreshTarget)) {

+                if (updateAreas == null) {

+                    updateAreas = new LinkedList<ModelForm.UpdateArea>();

+                }

+                updateAreas.add(new ModelForm.UpdateArea("submit", formId, backgroundSubmitRefreshTarget));

+            }

+

+            boolean ajaxEnabled = (UtilValidate.isNotEmpty(updateAreas) || UtilValidate.isNotEmpty(backgroundSubmitRefreshTarget)) && this.javaScriptEnabled;

+            if (ajaxEnabled) {

+                writer.append("<input type=\"button\"");

+            } else {

+                writer.append("<input type=\"submit\"");

+            }

+

+            appendClassNames(writer, context, modelFormField);

+

+            writer.append(" name=\"");

+            writer.append(modelFormField.getParameterName(context));

+            writer.append('"');

+

+            String title = modelFormField.getTitle(context);

+            if (UtilValidate.isNotEmpty(title)) {

+                writer.append(" value=\"");

+                writer.append(encode(title, modelFormField, context));

+                writer.append('"');

+            }

+

+

+            event = modelFormField.getEvent();

+            action = modelFormField.getAction(context);

+            if (UtilValidate.isNotEmpty(event) && UtilValidate.isNotEmpty(action)) {

+                writer.append(" ");

+                writer.append(event);

+                writer.append("=\"");

+                writer.append(action);

+                writer.append('"');

+            } else {

+                //add single click JS onclick

+                // disabling for now, using form onSubmit action instead: writer.append(singleClickAction);

+            }

+

+            if (ajaxEnabled) {

+                writer.append(" onclick=\"");

+                if (UtilValidate.isNotEmpty(confirmation)) {

+                    writer.append("if  (confirm('");

+                    writer.append(confirmation);

+                    writer.append(");) ");

+                }

+                writer.append("ajaxSubmitFormUpdateAreas('");

+                writer.append(formId);

+                writer.append("', '").append(createAjaxParamsFromUpdateAreas(updateAreas, null, context));

+                writer.append("')\"");

+            }

+

+            writer.append("/>");

+        }

+

+        this.appendTooltip(writer, context, modelFormField);

+

+        //appendWhitespace(writer);

+    }

+

+    /* (non-Javadoc)

+     * @see org.ofbiz.widget.form.FormStringRenderer#renderResetField(java.io.Writer, java.util.Map, org.ofbiz.widget.model.ModelFormField.ResetField)

+     */

+    public void renderResetField(Appendable writer, Map<String, Object> context, ResetField resetField) throws IOException {

+        ModelFormField modelFormField = resetField.getModelFormField();

+

+        writer.append("<input type=\"reset\"");

+

+        appendClassNames(writer, context, modelFormField);

+

+        writer.append(" name=\"");

+        writer.append(modelFormField.getParameterName(context));

+        writer.append('"');

+

+        String title = modelFormField.getTitle(context);

+        if (UtilValidate.isNotEmpty(title)) {

+            writer.append(" value=\"");

+            writer.append(encode(title, modelFormField, context));

+            writer.append('"');

+        }

+

+        writer.append("/>");

+

+        this.appendTooltip(writer, context, modelFormField);

+

+        //appendWhitespace(writer);

+    }

+

+    /* (non-Javadoc)

+     * @see org.ofbiz.widget.form.FormStringRenderer#renderHiddenField(java.io.Writer, java.util.Map, org.ofbiz.widget.model.ModelFormField.HiddenField)

+     */

+    public void renderHiddenField(Appendable writer, Map<String, Object> context, HiddenField hiddenField) throws IOException {

+        ModelFormField modelFormField = hiddenField.getModelFormField();

+        String value = hiddenField.getValue(context);

+        this.renderHiddenField(writer, context, modelFormField, value);

+    }

+

+    public void renderHiddenField(Appendable writer, Map<String, Object> context, ModelFormField modelFormField, String value) throws IOException {

+        writer.append("<input type=\"hidden\"");

+

+        writer.append(" name=\"");

+        writer.append(modelFormField.getParameterName(context));

+        writer.append('"');

+

+        if (UtilValidate.isNotEmpty(value)) {

+            writer.append(" value=\"");

+            writer.append(value);

+            writer.append('"');

+        }

+

+        writer.append("/>");

+        appendWhitespace(writer);

+    }

+

+    /* (non-Javadoc)

+     * @see org.ofbiz.widget.form.FormStringRenderer#renderIgnoredField(java.io.Writer, java.util.Map, org.ofbiz.widget.model.ModelFormField.IgnoredField)

+     */

+    public void renderIgnoredField(Appendable writer, Map<String, Object> context, IgnoredField ignoredField) throws IOException {

+        // do nothing, it's an ignored field; could add a comment or something if we wanted to

+    }

+

+    /* (non-Javadoc)

+     * @see org.ofbiz.widget.form.FormStringRenderer#renderFieldTitle(java.io.Writer, java.util.Map, org.ofbiz.widget.model.ModelFormField)

+     */

+    public void renderFieldTitle(Appendable writer, Map<String, Object> context, ModelFormField modelFormField) throws IOException {

+        String tempTitleText = modelFormField.getTitle(context);

+        String titleText = UtilHttp.encodeAmpersands(tempTitleText);

+

+        if (UtilValidate.isNotEmpty(titleText)) {

+            // copied from MacroFormRenderer renderFieldTitle

+            String displayHelpText = UtilProperties.getPropertyValue("widget.properties", "widget.form.displayhelpText");

+            String helpText = null;

+            if ("Y".equals(displayHelpText)) {

+                Delegator delegator = WidgetWorker.getDelegator(context);

+                Locale locale = (Locale)context.get("locale");

+                String entityName = modelFormField.getEntityName();

+                String fieldName = modelFormField.getFieldName();

+                helpText = UtilHelpText.getEntityFieldDescription(entityName, fieldName, delegator, locale);

+            }

+            if (UtilValidate.isNotEmpty(modelFormField.getTitleStyle()) || UtilValidate.isNotEmpty(helpText)) {

+                writer.append("<span");

+                if (UtilValidate.isNotEmpty(modelFormField.getTitleStyle())){

+                    writer.append(" class=\"");

+                    writer.append(modelFormField.getTitleStyle());

+                }

+                if (UtilValidate.isNotEmpty(helpText)){

+                    writer.append(" title=\"");

+                    writer.append(FreeMarkerWorker.encodeDoubleQuotes(helpText));

+                }

+                writer.append("\">");

+            }

+            if (" ".equals(titleText)) {

+                // If the title content is just a blank then render it colling renderFormatEmptySpace:

+                // the method will set its content to work fine in most browser

+                this.renderFormatEmptySpace(writer, context, modelFormField.getModelForm());

+            } else {

+                renderHyperlinkTitle(writer, context, modelFormField, titleText);

+            }

+

+            if (UtilValidate.isNotEmpty(modelFormField.getTitleStyle())) {

+                writer.append("</span>");

+            }

+

+            //appendWhitespace(writer);

+        }

+    }

+

+    /* (non-Javadoc)

+     * @see org.ofbiz.widget.form.FormStringRenderer#renderFieldTitle(java.io.Writer, java.util.Map, org.ofbiz.widget.model.ModelFormField)

+     */

+    public void renderSingleFormFieldTitle(Appendable writer, Map<String, Object> context, ModelFormField modelFormField) throws IOException {

+        boolean requiredField = modelFormField.getRequiredField();

+        if (requiredField) {

+

+            String requiredStyle = modelFormField.getRequiredFieldStyle();

+            if (UtilValidate.isEmpty(requiredStyle)) {

+                requiredStyle = modelFormField.getTitleStyle();

+            }

+

+            if (UtilValidate.isNotEmpty(requiredStyle)) {

+                writer.append("<span class=\"");

+                writer.append(requiredStyle);

+                writer.append("\">");

+            }

+            renderHyperlinkTitle(writer, context, modelFormField, modelFormField.getTitle(context));

+            if (UtilValidate.isNotEmpty(requiredStyle)) {

+                writer.append("</span>");

+            }

+

+            //appendWhitespace(writer);

+        } else {

+            renderFieldTitle(writer, context, modelFormField);

+        }

+    }

+

+    /* (non-Javadoc)

+     * @see org.ofbiz.widget.form.FormStringRenderer#renderFormOpen(java.io.Writer, java.util.Map, org.ofbiz.widget.form.model.ModelForm)

+     */

+    public void renderFormOpen(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {

+        this.widgetCommentsEnabled = ModelWidget.widgetBoundaryCommentsEnabled(context);

+        renderBeginningBoundaryComment(writer, "Form Widget - Form Element", modelForm);

+        writer.append("<form method=\"post\" ");

+        String targetType = modelForm.getTargetType();

+        String targ = modelForm.getTarget(context, targetType);

+        // The 'action' attribute is mandatory in a form definition,

+        // even if it is empty.

+        writer.append(" action=\"");

+        if (UtilValidate.isNotEmpty(targ)) {

+            //this.appendOfbizUrl(writer, "/" + targ);

+            WidgetWorker.buildHyperlinkUrl(writer, targ, targetType, null, null, false, false, true, request, response, context);

+        }

+        writer.append("\" ");

+

+        String formType = modelForm.getType();

+        if (formType.equals("upload")) {

+            writer.append(" enctype=\"multipart/form-data\"");

+        }

+

+        String targetWindow = modelForm.getTargetWindow(context);

+        if (UtilValidate.isNotEmpty(targetWindow)) {

+            writer.append(" target=\"");

+            writer.append(targetWindow);

+            writer.append("\"");

+        }

+

+        String containerId = FormRenderer.getCurrentContainerId(modelForm, context);

+        if (UtilValidate.isNotEmpty(containerId)) {

+            writer.append(" id=\"");

+            writer.append(containerId);

+            writer.append("\"");

+        }

+

+        writer.append(" class=\"");

+        String containerStyle =  modelForm.getContainerStyle();

+        if (UtilValidate.isNotEmpty(containerStyle)) {

+            writer.append(containerStyle);

+        } else {

+            writer.append("basic-form");

+        }

+        writer.append("\"");

+

+        writer.append(" onsubmit=\"javascript:submitFormDisableSubmits(this)\"");

+

+        if (!modelForm.getClientAutocompleteFields()) {

+            writer.append(" autocomplete=\"off\"");

+        }

+

+        writer.append(" name=\"");

+        writer.append(FormRenderer.getCurrentContainerId(modelForm, context));

+        writer.append("\">");

+

+        boolean useRowSubmit = modelForm.getUseRowSubmit();

+        if (useRowSubmit) {

+            writer.append("<input type=\"hidden\" name=\"_useRowSubmit\" value=\"Y\"/>");

+        }

+

+        appendWhitespace(writer);

+    }

+

+    /* (non-Javadoc)

+     * @see org.ofbiz.widget.form.FormStringRenderer#renderFormClose(java.io.Writer, java.util.Map, org.ofbiz.widget.form.model.ModelForm)

+     */

+    public void renderFormClose(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {

+        writer.append("</form>");

+        String focusFieldName = FormRenderer.getFocusFieldName(modelForm, context);

+        if (UtilValidate.isNotEmpty(focusFieldName)) {

+            appendWhitespace(writer);

+            writer.append("<script language=\"JavaScript\" type=\"text/javascript\">");

+            appendWhitespace(writer);

+            writer.append("document.").append(FormRenderer.getCurrentFormName(modelForm, context)).append(".");

+            writer.append(focusFieldName).append(".focus();");

+            appendWhitespace(writer);

+            writer.append("</script>");

+        }

+        appendWhitespace(writer);

+        renderEndingBoundaryComment(writer, "Form Widget - Form Element", modelForm);

+    }

+

+    /* (non-Javadoc)

+     * @see org.ofbiz.widget.form.FormStringRenderer#renderFormClose(java.io.Writer, java.util.Map, org.ofbiz.widget.form.model.ModelForm)

+     */

+    public void renderMultiFormClose(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {

+        for (ModelFormField submitField: modelForm.getMultiSubmitFields()) {

+            if (submitField != null) {

+

+                // Threw this in that as a hack to keep the submit button from expanding the first field

+                // Needs a more rugged solution

+                // WARNING: this method (renderMultiFormClose) must be called after the

+                // table that contains the list has been closed (to avoid validation errors) so

+                // we cannot call here the methods renderFormatItemRowCell*: for this reason

+                // they are now commented.

+

+                // this.renderFormatItemRowCellOpen(writer, context, modelForm, submitField);

+                // this.renderFormatItemRowCellClose(writer, context, modelForm, submitField);

+

+                // this.renderFormatItemRowCellOpen(writer, context, modelForm, submitField);

+

+                submitField.renderFieldString(writer, context, this);

+

+                // this.renderFormatItemRowCellClose(writer, context, modelForm, submitField);

+

+            }

+        }

+        writer.append("</form>");

+        appendWhitespace(writer);

+

+        // see if there is anything that needs to be added outside of the multi-form

+        Map<String, Object> wholeFormContext = UtilGenerics.checkMap(context.get("wholeFormContext"));

+        Appendable postMultiFormWriter = wholeFormContext != null ? (Appendable) wholeFormContext.get("postMultiFormWriter") : null;

+        if (postMultiFormWriter != null) {

+            writer.append(postMultiFormWriter.toString());

+            appendWhitespace(writer);

+        }

+

+        renderEndingBoundaryComment(writer, "Form Widget - Form Element (Multi)", modelForm);

+    }

+

+    public void renderFormatListWrapperOpen(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {

+

+        Map<String, Object> inputFields = UtilGenerics.checkMap(context.get("requestParameters"));

+        Map<String, Object> queryStringMap = UtilGenerics.toMap(context.get("queryStringMap"));

+        if (UtilValidate.isNotEmpty(queryStringMap)) {

+            inputFields.putAll(queryStringMap);

+        }

+        if (modelForm.getType().equals("multi")) {

+            inputFields = UtilHttp.removeMultiFormParameters(inputFields);

+        }

+        String queryString = UtilHttp.urlEncodeArgs(inputFields);

+        context.put("_QBESTRING_", queryString);

+

+        this.widgetCommentsEnabled = ModelWidget.widgetBoundaryCommentsEnabled(context);

+        renderBeginningBoundaryComment(writer, "Form Widget", modelForm);

+

+        if (this.renderPagination) {

+            this.renderNextPrev(writer, context, modelForm);

+        }

+        writer.append(" <table cellspacing=\"0\" class=\"");

+        if (UtilValidate.isNotEmpty(modelForm.getDefaultTableStyle())) {

+            writer.append(FlexibleStringExpander.expandString(modelForm.getDefaultTableStyle(), context));

+        } else {

+            writer.append("basic-table form-widget-table dark-grid");

+        }

+        writer.append("\">");

+        appendWhitespace(writer);

+    }

+

+    public void renderFormatListWrapperClose(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {

+        writer.append(" </table>");

+

+        appendWhitespace(writer);

+        if (this.renderPagination) {

+            this.renderNextPrev(writer, context, modelForm);

+        }

+        renderEndingBoundaryComment(writer, "Form Widget - Formal List Wrapper", modelForm);

+    }

+

+    /* (non-Javadoc)

+     * @see org.ofbiz.widget.form.FormStringRenderer#renderFormatHeaderRowOpen(java.io.Writer, java.util.Map, org.ofbiz.widget.form.model.ModelForm)

+     */

+    public void renderFormatHeaderRowOpen(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {

+        writer.append("  <tr");

+        String headerStyle = FlexibleStringExpander.expandString(modelForm.getHeaderRowStyle(), context);

+        writer.append(" class=\"");

+        if (UtilValidate.isNotEmpty(headerStyle)) {

+            writer.append(headerStyle);

+        } else {

+            writer.append("header-row");

+        }

+        writer.append("\">");

+        appendWhitespace(writer);

+    }

+

+    /* (non-Javadoc)

+     * @see org.ofbiz.widget.form.FormStringRenderer#renderFormatHeaderRowClose(java.io.Writer, java.util.Map, org.ofbiz.widget.form.model.ModelForm)

+     */

+    public void renderFormatHeaderRowClose(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {

+        writer.append("  </tr>");

+

+        appendWhitespace(writer);

+    }

+

+    /* (non-Javadoc)

+     * @see org.ofbiz.widget.form.FormStringRenderer#renderFormatHeaderRowCellOpen(java.io.Writer, java.util.Map, org.ofbiz.widget.form.model.ModelForm, org.ofbiz.widget.model.ModelFormField, int positionSpan)

+     */

+    public void renderFormatHeaderRowCellOpen(Appendable writer, Map<String, Object> context, ModelForm modelForm, ModelFormField modelFormField, int positionSpan) throws IOException {

+        writer.append("   <td");

+        String areaStyle = modelFormField.getTitleAreaStyle();

+        if (positionSpan > 1) {

+            writer.append(" colspan=\"");

+            writer.append(Integer.toString(positionSpan));

+            writer.append("\"");

+        }

+        if (UtilValidate.isNotEmpty(areaStyle)) {

+            writer.append(" class=\"");

+            writer.append(areaStyle);

+            writer.append("\"");

+        }

+        writer.append(">");

+        //appendWhitespace(writer);

+    }

+

+    /* (non-Javadoc)

+     * @see org.ofbiz.widget.form.FormStringRenderer#renderFormatHeaderRowCellClose(java.io.Writer, java.util.Map, org.ofbiz.widget.form.model.ModelForm, org.ofbiz.widget.model.ModelFormField)

+     */

+    public void renderFormatHeaderRowCellClose(Appendable writer, Map<String, Object> context, ModelForm modelForm, ModelFormField modelFormField) throws IOException {

+        writer.append("</td>");

+        appendWhitespace(writer);

+    }

+

+    public void renderFormatHeaderRowFormCellOpen(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {

+        writer.append("   <td");

+        String areaStyle = modelForm.getFormTitleAreaStyle();

+        if (UtilValidate.isNotEmpty(areaStyle)) {

+            writer.append(" class=\"");

+            writer.append(areaStyle);

+            writer.append("\"");

+        }

+        writer.append(">");

+        //appendWhitespace(writer);

+    }

+

+    /* (non-Javadoc)

+     * @see org.ofbiz.widget.form.FormStringRenderer#renderFormatHeaderRowFormCellClose(java.io.Writer, java.util.Map, org.ofbiz.widget.form.model.ModelForm)

+     */

+    public void renderFormatHeaderRowFormCellClose(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {

+        writer.append("</td>");

+        appendWhitespace(writer);

+    }

+

+    /* (non-Javadoc)

+     * @see org.ofbiz.widget.form.FormStringRenderer#renderFormatHeaderRowFormCellTitleSeparator(java.io.Writer, java.util.Map, org.ofbiz.widget.form.model.ModelForm, boolean)

+     */

+    public void renderFormatHeaderRowFormCellTitleSeparator(Appendable writer, Map<String, Object> context, ModelForm modelForm, ModelFormField modelFormField, boolean isLast) throws IOException {

+

+        String titleStyle = modelFormField.getTitleStyle();

+        if (UtilValidate.isNotEmpty(titleStyle)) {

+            writer.append("<span class=\"");

+            writer.append(titleStyle);

+            writer.append("\">");

+        }

+        if (isLast) {

+            writer.append(" - ");

+        } else {

+            writer.append(" - ");

+        }

+        if (UtilValidate.isNotEmpty(titleStyle)) {

+            writer.append("</span>");

+        }

+    }

+

+    /* (non-Javadoc)

+     * @see org.ofbiz.widget.form.FormStringRenderer#renderFormatItemRowOpen(java.io.Writer, java.util.Map, org.ofbiz.widget.form.model.ModelForm)

+     */

+    public void renderFormatItemRowOpen(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {

+        Integer itemIndex = (Integer)context.get("itemIndex");

+

+        writer.append("  <tr");

+        if (itemIndex!=null) {

+

+            String altRowStyles = modelForm.getStyleAltRowStyle(context);

+            if (itemIndex.intValue() % 2 == 0) {

+                String evenRowStyle = modelForm.getEvenRowStyle();

+                if (UtilValidate.isNotEmpty(evenRowStyle)) {

+                    writer.append(" class=\"");

+                    writer.append(evenRowStyle);

+                    if (UtilValidate.isNotEmpty(altRowStyles)) {

+                        writer.append(altRowStyles);

+                    }

+                    writer.append("\"");

+                } else {

+                    if (UtilValidate.isNotEmpty(altRowStyles)) {

+                        writer.append(" class=\"");

+                        writer.append(altRowStyles);

+                        writer.append("\"");

+                    }

+                }

+            } else {

+                String oddRowStyle = FlexibleStringExpander.expandString(modelForm.getOddRowStyle(), context);

+                if (UtilValidate.isNotEmpty(oddRowStyle)) {

+                    writer.append(" class=\"");

+                    writer.append(oddRowStyle);

+                    if (UtilValidate.isNotEmpty(altRowStyles)) {

+                        writer.append(altRowStyles);

+                    }

+                    writer.append("\"");

+                } else {

+                    if (UtilValidate.isNotEmpty(altRowStyles)) {

+                        writer.append(" class=\"");

+                        writer.append(altRowStyles);

+                        writer.append("\"");

+                    }

+                }

+            }

+        }

+        writer.append(">");

+        appendWhitespace(writer);

+    }

+

+    /* (non-Javadoc)

+     * @see org.ofbiz.widget.form.FormStringRenderer#renderFormatItemRowClose(java.io.Writer, java.util.Map, org.ofbiz.widget.form.model.ModelForm)

+     */

+    public void renderFormatItemRowClose(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {

+        writer.append("  </tr>");

+

+        appendWhitespace(writer);

+    }

+

+    /* (non-Javadoc)

+     * @see org.ofbiz.widget.form.FormStringRenderer#renderFormatItemRowCellOpen(java.io.Writer, java.util.Map, org.ofbiz.widget.form.model.ModelForm, org.ofbiz.widget.model.ModelFormField)

+     */

+    public void renderFormatItemRowCellOpen(Appendable writer, Map<String, Object> context, ModelForm modelForm, ModelFormField modelFormField, int positionSpan) throws IOException {

+        writer.append("   <td");

+        String areaStyle = modelFormField.getWidgetAreaStyle();

+        if (positionSpan > 1) {

+            writer.append(" colspan=\"");

+            writer.append(Integer.toString(positionSpan));

+            writer.append("\"");

+        }

+        if (UtilValidate.isNotEmpty(areaStyle)) {

+            writer.append(" class=\"");

+            writer.append(areaStyle);

+            writer.append("\"");

+        }

+        writer.append(">");

+        //appendWhitespace(writer);

+    }

+

+    /* (non-Javadoc)

+     * @see org.ofbiz.widget.form.FormStringRenderer#renderFormatItemRowCellClose(java.io.Writer, java.util.Map, org.ofbiz.widget.form.model.ModelForm, org.ofbiz.widget.model.ModelFormField)

+     */

+    public void renderFormatItemRowCellClose(Appendable writer, Map<String, Object> context, ModelForm modelForm, ModelFormField modelFormField) throws IOException {

+        writer.append("</td>");

+        appendWhitespace(writer);

+    }

+

+    /* (non-Javadoc)

+     * @see org.ofbiz.widget.form.FormStringRenderer#renderFormatItemRowFormCellOpen(java.io.Writer, java.util.Map, org.ofbiz.widget.form.model.ModelForm)

+     */

+    public void renderFormatItemRowFormCellOpen(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {

+        writer.append("   <td");

+        String areaStyle = modelForm.getFormWidgetAreaStyle();

+        if (UtilValidate.isNotEmpty(areaStyle)) {

+            writer.append(" class=\"");

+            writer.append(areaStyle);

+            writer.append("\"");

+        }

+        writer.append(">");

+        //appendWhitespace(writer);

+    }

+

+    /* (non-Javadoc)

+     * @see org.ofbiz.widget.form.FormStringRenderer#renderFormatItemRowFormCellClose(java.io.Writer, java.util.Map, org.ofbiz.widget.form.model.ModelForm)

+     */

+    public void renderFormatItemRowFormCellClose(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {

+        writer.append("</td>");

+        appendWhitespace(writer);

+    }

+

+    public void renderFormatSingleWrapperOpen(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {

+        writer.append(" <table cellspacing=\"0\"");

+        if (UtilValidate.isNotEmpty(modelForm.getDefaultTableStyle())) {

+            writer.append(" class=\"").append(FlexibleStringExpander.expandString(modelForm.getDefaultTableStyle(), context)).append("\"");

+        }

+        writer.append(">");

+        appendWhitespace(writer);

+    }

+

+    public void renderFormatSingleWrapperClose(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {

+        writer.append(" </table>");

+        appendWhitespace(writer);

+    }

+

+    /* (non-Javadoc)

+     * @see org.ofbiz.widget.form.FormStringRenderer#renderFormatFieldRowOpen(java.io.Writer, java.util.Map, org.ofbiz.widget.form.model.ModelForm)

+     */

+    public void renderFormatFieldRowOpen(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {

+        writer.append("  <tr>");

+        appendWhitespace(writer);

+    }

+

+    /* (non-Javadoc)

+     * @see org.ofbiz.widget.form.FormStringRenderer#renderFormatFieldRowClose(java.io.Writer, java.util.Map, org.ofbiz.widget.form.model.ModelForm)

+     */

+    public void renderFormatFieldRowClose(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {

+        writer.append("  </tr>");

+        appendWhitespace(writer);

+    }

+

+    /* (non-Javadoc)

+     * @see org.ofbiz.widget.form.FormStringRenderer#renderFormatFieldRowTitleCellOpen(java.io.Writer, java.util.Map, org.ofbiz.widget.model.ModelFormField)

+     */

+    public void renderFormatFieldRowTitleCellOpen(Appendable writer, Map<String, Object> context, ModelFormField modelFormField) throws IOException {

+        writer.append("   <td");

+        String areaStyle = modelFormField.getTitleAreaStyle();

+        if (UtilValidate.isNotEmpty(areaStyle)) {

+            writer.append(" class=\"");

+            writer.append(areaStyle);

+            writer.append("\"");

+        } else {

+            writer.append(" class=\"label\"");

+        }

+        writer.append(">");

+        //appendWhitespace(writer);

+    }

+

+    /* (non-Javadoc)

+     * @see org.ofbiz.widget.form.FormStringRenderer#renderFormatFieldRowTitleCellClose(java.io.Writer, java.util.Map, org.ofbiz.widget.model.ModelFormField)

+     */

+    public void renderFormatFieldRowTitleCellClose(Appendable writer, Map<String, Object> context, ModelFormField modelFormField) throws IOException {

+        writer.append("</td>");

+        appendWhitespace(writer);

+    }

+

+    /* (non-Javadoc)

+     * @see org.ofbiz.widget.form.FormStringRenderer#renderFormatFieldRowSpacerCell(java.io.Writer, java.util.Map, org.ofbiz.widget.model.ModelFormField)

+     */

+    public void renderFormatFieldRowSpacerCell(Appendable writer, Map<String, Object> context, ModelFormField modelFormField) throws IOException {

+        // Embedded styling - bad idea

+        //writer.append("<td>&nbsp;</td>");

+

+        //appendWhitespace(writer);

+    }

+

+    /* (non-Javadoc)

+     * @see org.ofbiz.widget.form.FormStringRenderer#renderFormatFieldRowWidgetCellOpen(java.io.Writer, java.util.Map, org.ofbiz.widget.model.ModelFormField, int)

+     */

+    public void renderFormatFieldRowWidgetCellOpen(Appendable writer, Map<String, Object> context, ModelFormField modelFormField, int positions, int positionSpan, Integer nextPositionInRow) throws IOException {

+//        writer.append("<td width=\"");

+//        if (nextPositionInRow != null || modelFormField.getPosition() > 1) {

+//            writer.append("30");

+//        } else {

+//            writer.append("80");

+//        }

+//        writer.append("%\"");

+        writer.append("   <td");

+        if (positionSpan > 0) {

+            writer.append(" colspan=\"");

+            // do a span of 1 for this column, plus 3 columns for each spanned

+            //position or each blank position that this will be filling in

+            writer.append(Integer.toString(1 + (positionSpan * 3)));

+            writer.append("\"");

+        }

+        String areaStyle = modelFormField.getWidgetAreaStyle();

+        if (UtilValidate.isNotEmpty(areaStyle)) {

+            writer.append(" class=\"");

+            writer.append(areaStyle);

+            writer.append("\"");

+        }

+        writer.append(">");

+

+        //appendWhitespace(writer);

+    }

+

+    /* (non-Javadoc)

+     * @see org.ofbiz.widget.form.FormStringRenderer#renderFormatFieldRowWidgetCellClose(java.io.Writer, java.util.Map, org.ofbiz.widget.model.ModelFormField, int)

+     */

+    public void renderFormatFieldRowWidgetCellClose(Appendable writer, Map<String, Object> context, ModelFormField modelFormField, int positions, int positionSpan, Integer nextPositionInRow) throws IOException {

+        writer.append("</td>");

+        appendWhitespace(writer);

+    }

+

+    public void renderFormatEmptySpace(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {

+        writer.append("&nbsp;");

+    }

+

+    /* (non-Javadoc)

+     * @see org.ofbiz.widget.form.FormStringRenderer#renderTextFindField(java.io.Writer, java.util.Map, org.ofbiz.widget.model.ModelFormField.TextFindField)

+     */

+    public void renderTextFindField(Appendable writer, Map<String, Object> context, TextFindField textFindField) throws IOException {

+

+        ModelFormField modelFormField = textFindField.getModelFormField();

+

+        String defaultOption = textFindField.getDefaultOption();

+        Locale locale = (Locale)context.get("locale");

+        if (!textFindField.getHideOptions()) {

+            String opEquals = UtilProperties.getMessage("conditional", "equals", locale);

+            String opBeginsWith = UtilProperties.getMessage("conditional", "begins_with", locale);

+            String opContains = UtilProperties.getMessage("conditional", "contains", locale);

+            String opIsEmpty = UtilProperties.getMessage("conditional", "is_empty", locale);

+            String opNotEqual = UtilProperties.getMessage("conditional", "not_equal", locale);

+            writer.append(" <select name=\"");

+            writer.append(modelFormField.getParameterName(context));

+            writer.append("_op\" class=\"selectBox\">");

+            writer.append("<option value=\"equals\"").append(("equals".equals(defaultOption)? " selected": "")).append(">").append(opEquals).append("</option>");

+            writer.append("<option value=\"like\"").append(("like".equals(defaultOption)? " selected": "")).append(">").append(opBeginsWith).append("</option>");

+            writer.append("<option value=\"contains\"").append(("contains".equals(defaultOption)? " selected": "")).append(">").append(opContains).append("</option>");

+            writer.append("<option value=\"empty\"").append(("empty".equals(defaultOption)? " selected": "")).append(">").append(opIsEmpty).append("</option>");

+            writer.append("<option value=\"notEqual\"").append(("notEqual".equals(defaultOption)? " selected": "")).append(">").append(opNotEqual).append("</option>");

+            writer.append("</select>");

+        } else {

+            writer.append(" <input type=\"hidden\" name=\"");

+            writer.append(modelFormField.getParameterName(context));

+            writer.append("_op\" value=\"").append(defaultOption).append("\"/>");

+        }

+

+        writer.append("<input type=\"text\"");

+

+        appendClassNames(writer, context, modelFormField);

+

+        writer.append(" name=\"");

+        writer.append(modelFormField.getParameterName(context));

+        writer.append('"');

+

+        String value = modelFormField.getEntry(context, textFindField.getDefaultValue(context));

+        if (UtilValidate.isNotEmpty(value)) {

+            writer.append(" value=\"");

+            writer.append(value);

+            writer.append('"');

+        }

+

+        writer.append(" size=\"");

+        writer.append(Integer.toString(textFindField.getSize()));

+        writer.append('"');

+

+        Integer maxlength = textFindField.getMaxlength();

+        if (maxlength != null) {

+            writer.append(" maxlength=\"");

+            writer.append(maxlength.toString());

+            writer.append('"');

+        }

+

+        if (!textFindField.getClientAutocompleteField()) {

+            writer.append(" autocomplete=\"off\"");

+        }

+

+        writer.append("/>");

+

+        if (UtilValidate.isNotEmpty(modelFormField.getTitleStyle())) {

+            writer.append(" <span class=\"");

+            writer.append(modelFormField.getTitleStyle());

+            writer.append("\">");

+        }

+

+        String ignoreCase = UtilProperties.getMessage("conditional", "ignore_case", locale);

+        boolean ignCase = textFindField.getIgnoreCase();

+

+        if (!textFindField.getHideIgnoreCase()) {

+            writer.append(" <input type=\"checkbox\" name=\"");

+            writer.append(modelFormField.getParameterName(context));

+            writer.append("_ic\" value=\"Y\"").append((ignCase ? " checked=\"checked\"" : "")).append("/>");

+            writer.append(ignoreCase);

+        } else {

+            writer.append("<input type=\"hidden\" name=\"");

+            writer.append(modelFormField.getParameterName(context));

+            writer.append("_ic\" value=\"").append((ignCase ? "Y" : "")).append("\"/>");

+        }

+

+        if (UtilValidate.isNotEmpty(modelFormField.getTitleStyle())) {

+            writer.append("</span>");

+        }

+

+        this.appendTooltip(writer, context, modelFormField);

+

+        //appendWhitespace(writer);

+    }

+

+    /* (non-Javadoc)

+     * @see org.ofbiz.widget.form.FormStringRenderer#renderRangeFindField(java.io.Writer, java.util.Map, org.ofbiz.widget.model.ModelFormField.RangeFindField)

+     */

+    public void renderRangeFindField(Appendable writer, Map<String, Object> context, RangeFindField rangeFindField) throws IOException {

+

+        ModelFormField modelFormField = rangeFindField.getModelFormField();

+        Locale locale = (Locale)context.get("locale");

+        String opEquals = UtilProperties.getMessage("conditional", "equals", locale);

+        String opGreaterThan = UtilProperties.getMessage("conditional", "greater_than", locale);

+        String opGreaterThanEquals = UtilProperties.getMessage("conditional", "greater_than_equals", locale);

+        String opLessThan = UtilProperties.getMessage("conditional", "less_than", locale);

+        String opLessThanEquals = UtilProperties.getMessage("conditional", "less_than_equals", locale);

+        //String opIsEmpty = UtilProperties.getMessage("conditional", "is_empty", locale);

+

+        writer.append("<input type=\"text\"");

+

+        appendClassNames(writer, context, modelFormField);

+

+        writer.append(" name=\"");

+        writer.append(modelFormField.getParameterName(context));

+        writer.append("_fld0_value\"");

+

+        String value = modelFormField.getEntry(context, rangeFindField.getDefaultValue(context));

+        if (UtilValidate.isNotEmpty(value)) {

+            writer.append(" value=\"");

+            writer.append(value);

+            writer.append('"');

+        }

+

+        writer.append(" size=\"");

+        writer.append(Integer.toString(rangeFindField.getSize()));

+        writer.append('"');

+

+        Integer maxlength = rangeFindField.getMaxlength();

+        if (maxlength != null) {

+            writer.append(" maxlength=\"");

+            writer.append(maxlength.toString());

+            writer.append('"');

+        }

+

+        if (!rangeFindField.getClientAutocompleteField()) {

+            writer.append(" autocomplete=\"off\"");

+        }

+

+        writer.append("/>");

+

+        if (UtilValidate.isNotEmpty(modelFormField.getTitleStyle())) {

+            writer.append(" <span class=\"");

+            writer.append(modelFormField.getTitleStyle());

+            writer.append("\">");

+        }

+

+        String defaultOptionFrom = rangeFindField.getDefaultOptionFrom();

+        writer.append(" <select name=\"");

+        writer.append(modelFormField.getParameterName(context));

+        writer.append("_fld0_op\" class=\"selectBox\">");

+        writer.append("<option value=\"equals\"").append(("equals".equals(defaultOptionFrom)? " selected": "")).append(">").append(opEquals).append("</option>");

+        writer.append("<option value=\"greaterThan\"").append(("greaterThan".equals(defaultOptionFrom)? " selected": "")).append(">").append(opGreaterThan).append("</option>");

+        writer.append("<option value=\"greaterThanEqualTo\"").append(("greaterThanEqualTo".equals(defaultOptionFrom)? " selected": "")).append(">").append(opGreaterThanEquals).append("</option>");

+        writer.append("</select>");

+

+        writer.append("</span>");

+

+        writer.append(" <br/> ");

+

+        writer.append("<input type=\"text\"");

+

+        appendClassNames(writer, context, modelFormField);

+

+        writer.append(" name=\"");

+        writer.append(modelFormField.getParameterName(context));

+        writer.append("_fld1_value\"");

+

+        value = modelFormField.getEntry(context);

+        if (UtilValidate.isNotEmpty(value)) {

+            writer.append(" value=\"");

+            writer.append(value);

+            writer.append('"');

+        }

+

+        writer.append(" size=\"");

+        writer.append(Integer.toString(rangeFindField.getSize()));

+        writer.append('"');

+

+        if (maxlength != null) {

+            writer.append(" maxlength=\"");

+            writer.append(maxlength.toString());

+            writer.append('"');

+        }

+

+        if (!rangeFindField.getClientAutocompleteField()) {

+            writer.append(" autocomplete=\"off\"");

+        }

+

+        writer.append("/>");

+

+        String defaultOptionThru = rangeFindField.getDefaultOptionThru();

+        writer.append(" <select name=\"");

+        writer.append(modelFormField.getParameterName(context));

+        writer.append("_fld1_op\" class=\"selectBox\">");

+        writer.append("<option value=\"lessThan\"").append(("lessThan".equals(defaultOptionThru)? " selected": "")).append(">").append(opLessThan).append("</option>");

+        writer.append("<option value=\"lessThanEqualTo\"").append(("lessThanEqualTo".equals(defaultOptionThru)? " selected": "")).append(">").append(opLessThanEquals).append("</option>");

+        writer.append("</select>");

+

+        if (UtilValidate.isNotEmpty(modelFormField.getTitleStyle())) {

+            writer.append("</span>");

+        }

+

+        this.appendTooltip(writer, context, modelFormField);

+

+        //appendWhitespace(writer);

+    }

+

+    /* (non-Javadoc)

+     * @see org.ofbiz.widget.form.FormStringRenderer#renderDateFindField(java.io.Writer, java.util.Map, org.ofbiz.widget.model.ModelFormField.DateFindField)

+     */

+    public void renderDateFindField(Appendable writer, Map<String, Object> context, DateFindField dateFindField) throws IOException {

+        ModelFormField modelFormField = dateFindField.getModelFormField();

+

+        Locale locale = (Locale)context.get("locale");

+        String opEquals = UtilProperties.getMessage("conditional", "equals", locale);

+        String opGreaterThan = UtilProperties.getMessage("conditional", "greater_than", locale);

+        String opSameDay = UtilProperties.getMessage("conditional", "same_day", locale);

+        String opGreaterThanFromDayStart = UtilProperties.getMessage("conditional",

+                                                "greater_than_from_day_start", locale);

+        String opLessThan = UtilProperties.getMessage("conditional", "less_than", locale);

+        String opUpToDay = UtilProperties.getMessage("conditional", "up_to_day", locale);

+        String opUpThruDay = UtilProperties.getMessage("conditional", "up_thru_day", locale);

+        String opIsEmpty = UtilProperties.getMessage("conditional", "is_empty", locale);

+

+        Map<String, String> uiLabelMap = UtilGenerics.checkMap(context.get("uiLabelMap"));

+        if (uiLabelMap == null) {

+            Debug.logWarning("Could not find uiLabelMap in context", module);

+        }

+        String localizedInputTitle = "", localizedIconTitle = "";

+

+        writer.append("<input type=\"text\"");

+

+        appendClassNames(writer, context, modelFormField);

+

+        writer.append(" name=\"");

+        writer.append(modelFormField.getParameterName(context));

+        writer.append("_fld0_value\"");

+

+        // the default values for a timestamp

+        int size = 25;

+        int maxlength = 30;

+

+        if ("date".equals(dateFindField.getType())) {

+            size = maxlength = 10;

+            if (uiLabelMap != null) {

+                localizedInputTitle = uiLabelMap.get("CommonFormatDate");

+            }

+        } else if ("time".equals(dateFindField.getType())) {

+            size = maxlength = 8;

+            if (uiLabelMap != null) {

+                localizedInputTitle = uiLabelMap.get("CommonFormatTime");

+            }

+        } else {

+            if (uiLabelMap != null) {

+                localizedInputTitle = uiLabelMap.get("CommonFormatDateTime");

+            }

+        }

+        writer.append(" title=\"");

+        writer.append(localizedInputTitle);

+        writer.append('"');

+

+        String value = modelFormField.getEntry(context, dateFindField.getDefaultValue(context));

+        if (UtilValidate.isNotEmpty(value)) {

+            if (value.length() > maxlength) {

+                value = value.substring(0, maxlength);

+            }

+            writer.append(" value=\"");

+            writer.append(value);

+            writer.append('"');

+        }

+

+        writer.append(" size=\"");

+        writer.append(Integer.toString(size));

+        writer.append('"');

+

+        writer.append(" maxlength=\"");

+        writer.append(Integer.toString(maxlength));

+        writer.append('"');

+

+        writer.append("/>");

+

+        // search for a localized label for the icon

+        if (uiLabelMap != null) {

+            localizedIconTitle = uiLabelMap.get("CommonViewCalendar");

+        }

+        ModelForm modelForm = modelFormField.getModelForm();

+        // add calendar pop-up button and seed data IF this is not a "time" type date-find

+        if (!"time".equals(dateFindField.getType())) {

+            if ("date".equals(dateFindField.getType())) {

+                writer.append("<a href=\"javascript:call_cal_notime(document.");

+            } else {

+                writer.append("<a href=\"javascript:call_cal(document.");

+            }

+            writer.append(FormRenderer.getCurrentFormName(modelForm, context));

+            writer.append('.');

+            writer.append(modelFormField.getParameterName(context));

+            writer.append("_fld0_value,'");

+            writer.append(UtilHttp.encodeBlanks(modelFormField.getEntry(context, dateFindField.getDefaultDateTimeString(context))));

+            writer.append("');\">");

+

+            writer.append("<img src=\"");

+            this.appendContentUrl(writer, "/images/cal.gif");

+            writer.append("\" width=\"16\" height=\"16\" border=\"0\" alt=\"");

+            writer.append(localizedIconTitle);

+            writer.append("\" title=\"");

+            writer.append(localizedIconTitle);

+            writer.append("\"/></a>");

+        }

+

+        if (UtilValidate.isNotEmpty(modelFormField.getTitleStyle())) {

+            writer.append(" <span class=\"");

+            writer.append(modelFormField.getTitleStyle());

+            writer.append("\">");

+        }

+

+        String defaultOptionFrom = dateFindField.getDefaultOptionFrom();

+        writer.append(" <select name=\"");

+        writer.append(modelFormField.getParameterName(context));

+        writer.append("_fld0_op\" class=\"selectBox\">");

+        writer.append("<option value=\"equals\"").append(("equals".equals(defaultOptionFrom)? " selected": "")).append(">").append(opEquals).append("</option>");

+        writer.append("<option value=\"sameDay\"").append(("sameDay".equals(defaultOptionFrom)? " selected": "")).append(">").append(opSameDay).append("</option>");

+        writer.append("<option value=\"greaterThanFromDayStart\"").append(("greaterThanFromDayStart".equals(defaultOptionFrom)? " selected": "")).append(">").append(opGreaterThanFromDayStart).append("</option>");

+        writer.append("<option value=\"greaterThan\"").append(("greaterThan".equals(defaultOptionFrom)? " selected": "")).append(">").append(opGreaterThan).append("</option>");

+        writer.append("</select>");

+

+        if (UtilValidate.isNotEmpty(modelFormField.getTitleStyle())) {

+            writer.append(" </span>");

+        }

+

+        writer.append(" <br/> ");

+

+        writer.append("<input type=\"text\"");

+

+        appendClassNames(writer, context, modelFormField);

+

+        writer.append(" name=\"");

+        writer.append(modelFormField.getParameterName(context));

+        writer.append("_fld1_value\"");

+

+        writer.append(" title=\"");

+        writer.append(localizedInputTitle);

+        writer.append('"');

+

+        value = modelFormField.getEntry(context);

+        if (UtilValidate.isNotEmpty(value)) {

+            if (value.length() > maxlength) {

+                value = value.substring(0, maxlength);

+            }

+            writer.append(" value=\"");

+            writer.append(value);

+            writer.append('"');

+        }

+

+        writer.append(" size=\"");

+        writer.append(Integer.toString(size));

+        writer.append('"');

+

+        writer.append(" maxlength=\"");

+        writer.append(Integer.toString(maxlength));

+        writer.append('"');

+

+        writer.append("/>");

+

+        // add calendar pop-up button and seed data IF this is not a "time" type date-find

+        if (!"time".equals(dateFindField.getType())) {

+            if ("date".equals(dateFindField.getType())) {

+                writer.append("<a href=\"javascript:call_cal_notime(document.");

+            } else {

+                writer.append("<a href=\"javascript:call_cal(document.");

+            }

+            writer.append(FormRenderer.getCurrentFormName(modelForm, context));

+            writer.append('.');

+            writer.append(modelFormField.getParameterName(context));

+            writer.append("_fld1_value,'");

+            writer.append(UtilHttp.encodeBlanks(modelFormField.getEntry(context, dateFindField.getDefaultDateTimeString(context))));

+            writer.append("');\">");

+

+            writer.append("<img src=\"");

+            this.appendContentUrl(writer, "/images/cal.gif");

+            writer.append("\" width=\"16\" height=\"16\" border=\"0\" alt=\"");

+            writer.append(localizedIconTitle);

+            writer.append("\" title=\"");

+            writer.append(localizedIconTitle);

+            writer.append("\"/></a>");

+        }

+

+        if (UtilValidate.isNotEmpty(modelFormField.getTitleStyle())) {

+            writer.append(" <span class=\"");

+            writer.append(modelFormField.getTitleStyle());

+            writer.append("\">");

+        }

+

+        String defaultOptionThru = dateFindField.getDefaultOptionThru();

+        writer.append(" <select name=\"");

+        writer.append(modelFormField.getParameterName(context));

+        writer.append("_fld1_op\" class=\"selectBox\">");

+        writer.append("<option value=\"lessThan\"").append(("lessThan".equals(defaultOptionThru)? " selected": "")).append(">").append(opLessThan).append("</option>");

+        writer.append("<option value=\"upToDay\"").append(("upToDay".equals(defaultOptionThru)? " selected": "")).append(">").append(opUpToDay).append("</option>");

+        writer.append("<option value=\"upThruDay\"").append(("upThruDay".equals(defaultOptionThru)? " selected": "")).append(">").append(opUpThruDay).append("</option>");

+        writer.append("<option value=\"empty\"").append(("empty".equals(defaultOptionThru)? " selected": "")).append(">").append(opIsEmpty).append("</option>");

+        writer.append("</select>");

+

+        if (UtilValidate.isNotEmpty(modelFormField.getTitleStyle())) {

+            writer.append("</span>");

+        }

+

+        this.appendTooltip(writer, context, modelFormField);

+

+        //appendWhitespace(writer);

+    }

+

+    /* (non-Javadoc)

+     * @see org.ofbiz.widget.form.FormStringRenderer#renderLookupField(java.io.Writer, java.util.Map, org.ofbiz.widget.model.ModelFormField.LookupField)

+     */

+    public void renderLookupField(Appendable writer, Map<String, Object> context, LookupField lookupField) throws IOException {

+        ModelFormField modelFormField = lookupField.getModelFormField();

+

+        writer.append("<input type=\"text\"");

+

+        appendClassNames(writer, context, modelFormField);

+

+        writer.append(" name=\"");

+        writer.append(modelFormField.getParameterName(context));

+        writer.append('"');

+

+        String value = modelFormField.getEntry(context, lookupField.getDefaultValue(context));

+        if (UtilValidate.isNotEmpty(value)) {

+            writer.append(" value=\"");

+            writer.append(value);

+            writer.append('"');

+        }

+

+        writer.append(" size=\"");

+        writer.append(Integer.toString(lookupField.getSize()));

+        writer.append('"');

+

+        Integer maxlength = lookupField.getMaxlength();

+        if (maxlength != null) {

+            writer.append(" maxlength=\"");

+            writer.append(maxlength.toString());

+            writer.append('"');

+        }

+

+        String idName = modelFormField.getCurrentContainerId(context);

+        if (UtilValidate.isNotEmpty(idName)) {

+            writer.append(" id=\"");

+            writer.append(idName);

+            writer.append('"');

+        }

+

+        List<ModelForm.UpdateArea> updateAreas = modelFormField.getOnChangeUpdateAreas();

+        boolean ajaxEnabled = updateAreas != null && this.javaScriptEnabled;

+        if (!lookupField.getClientAutocompleteField() || ajaxEnabled) {

+            writer.append(" autocomplete=\"off\"");

+        }

+

+        writer.append("/>");

+        ModelForm modelForm = modelFormField.getModelForm();

+        // add lookup pop-up button

+        String descriptionFieldName = lookupField.getDescriptionFieldName();

+        if (UtilValidate.isNotEmpty(descriptionFieldName)) {

+            writer.append("<a href=\"javascript:call_fieldlookup3(document.");

+            writer.append(FormRenderer.getCurrentFormName(modelForm, context));

+            writer.append('.');

+            writer.append(modelFormField.getParameterName(context));

+            writer.append(",'");

+            writer.append(descriptionFieldName);

+            writer.append(",'");

+        } else {

+            writer.append("<a href=\"javascript:call_fieldlookup2(document.");

+            writer.append(FormRenderer.getCurrentFormName(modelForm, context));

+            writer.append('.');

+            writer.append(modelFormField.getParameterName(context));

+            writer.append(",'");

+        }

+        writer.append(appendExternalLoginKey(lookupField.getFormName(context)));

+        writer.append("'");

+        List<String> targetParameterList = lookupField.getTargetParameterList();

+        for (String targetParameter: targetParameterList) {

+            // named like: document.${formName}.${targetParameter}.value

+            writer.append(", document.");

+            writer.append(FormRenderer.getCurrentFormName(modelForm, context));

+            writer.append(".");

+            writer.append(targetParameter);

+            writer.append(".value");

+        }

+        writer.append(");\">");

+        writer.append("<img src=\"");

+        this.appendContentUrl(writer, "/images/fieldlookup.gif");

+        writer.append("\" width=\"15\" height=\"14\" border=\"0\" alt=\"Lookup\"/></a>");

+

+        this.addAsterisks(writer, context, modelFormField);

+

+        this.makeHyperlinkString(writer, lookupField.getSubHyperlink(), context);

+        this.appendTooltip(writer, context, modelFormField);

+

+        if (ajaxEnabled) {

+            appendWhitespace(writer);

+            writer.append("<script language=\"JavaScript\" type=\"text/javascript\">");

+            appendWhitespace(writer);

+            writer.append("ajaxAutoCompleter('").append(createAjaxParamsFromUpdateAreas(updateAreas, null, context)).append("');");

+            appendWhitespace(writer);

+            writer.append("</script>");

+        }

+        appendWhitespace(writer);

+

+        //appendWhitespace(writer);

+    }

+

+    protected String appendExternalLoginKey(String target) {

+        String result = target;

+        String sessionId = ";jsessionid=" + request.getSession().getId();

+        int questionIndex = target.indexOf("?");

+        if (questionIndex == -1) {

+            result += sessionId;

+        } else {

+            result = result.replace("?", sessionId + "?");

+        }

+        return result;

+    }

+

+    private int getActualPageSize(Map<String, Object> context) {

+        Integer value = (Integer) context.get("actualPageSize");

+        return value != null ? value.intValue() : (getHighIndex(context) - getLowIndex(context));

+    }

+

+    private int getHighIndex(Map<String, Object> context) {

+        Integer value = (Integer) context.get("highIndex");

+        return value != null ? value.intValue() : 0;

+    }

+

+    private int getListSize(Map<String, Object> context) {

+        Integer value = (Integer) context.get("listSize");

+        return value != null ? value.intValue() : 0;

+    }

+

+    private int getLowIndex(Map<String, Object> context) {

+        Integer value = (Integer) context.get("lowIndex");

+        return value != null ? value.intValue() : 0;

+    }

+

+    public void renderNextPrev(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {

+        boolean ajaxEnabled = false;

+        List<ModelForm.UpdateArea> updateAreas = modelForm.getOnPaginateUpdateAreas();

+        String targetService = modelForm.getPaginateTarget(context);

+        if (this.javaScriptEnabled) {

+            if (UtilValidate.isNotEmpty(updateAreas)) {

+                ajaxEnabled = true;

+            }

+        }

+        if (targetService == null) {

+            targetService = "${targetService}";

+        }

+        if (UtilValidate.isEmpty(targetService) && updateAreas == null) {

+            Debug.logWarning("Cannot paginate because TargetService is empty for the form: " + modelForm.getName(), module);

+            return;

+        }

+

+        // get the parameterized pagination index and size fields

+        int paginatorNumber = WidgetWorker.getPaginatorNumber(context);

+        String viewIndexParam = modelForm.getMultiPaginateIndexField(context);

+        String viewSizeParam = modelForm.getMultiPaginateSizeField(context);

+

+        int viewIndex = Paginator.getViewIndex(modelForm, context);

+        int viewSize = Paginator.getViewSize(modelForm, context);

+        int listSize = getListSize(context);

+

+        int lowIndex = getLowIndex(context);

+        int highIndex = getHighIndex(context);

+        int actualPageSize = getActualPageSize(context);

+

+        // if this is all there seems to be (if listSize < 0, then size is unknown)

+        if (actualPageSize >= listSize && listSize >= 0) return;

+

+        // needed for the "Page" and "rows" labels

+        Map<String, String> uiLabelMap = UtilGenerics.checkMap(context.get("uiLabelMap"));

+        String pageLabel = "";

+        String commonDisplaying = "";

+        if (uiLabelMap == null) {

+            Debug.logWarning("Could not find uiLabelMap in context", module);

+        } else {

+            pageLabel = uiLabelMap.get("CommonPage");

+            Map<String, Integer> messageMap = UtilMisc.toMap("lowCount", Integer.valueOf(lowIndex + 1), "highCount", Integer.valueOf(lowIndex + actualPageSize), "total", Integer.valueOf(listSize));

+            commonDisplaying = UtilProperties.getMessage("CommonUiLabels", "CommonDisplaying", messageMap, (Locale) context.get("locale"));

+        }

+

+        // for legacy support, the viewSizeParam is VIEW_SIZE and viewIndexParam is VIEW_INDEX when the fields are "viewSize" and "viewIndex"

+        if (viewIndexParam.equals("viewIndex" + "_" + paginatorNumber)) viewIndexParam = "VIEW_INDEX" + "_" + paginatorNumber;

+        if (viewSizeParam.equals("viewSize" + "_" + paginatorNumber)) viewSizeParam = "VIEW_SIZE" + "_" + paginatorNumber;

+

+        String str = (String) context.get("_QBESTRING_");

+

+        // strip legacy viewIndex/viewSize params from the query string

+        String queryString = UtilHttp.stripViewParamsFromQueryString(str, "" + paginatorNumber);

+

+        // strip parametrized index/size params from the query string

+        HashSet<String> paramNames = new HashSet<String>();

+        paramNames.add(viewIndexParam);

+        paramNames.add(viewSizeParam);

+        queryString = UtilHttp.stripNamedParamsFromQueryString(queryString, paramNames);

+

+        String anchor = "";

+        String paginateAnchor = modelForm.getPaginateTargetAnchor();

+        if (paginateAnchor != null) anchor = "#" + paginateAnchor;

+

+        // Create separate url path String and request parameters String,

+        // add viewIndex/viewSize parameters to request parameter String

+        String urlPath = UtilHttp.removeQueryStringFromTarget(targetService);

+        StringBuilder prepLinkBuffer = new StringBuilder();

+        String prepLinkQueryString = UtilHttp.getQueryStringFromTarget(targetService);

+        if (prepLinkQueryString != null) {

+            prepLinkBuffer.append(prepLinkQueryString);

+        }

+        if (prepLinkBuffer.indexOf("?") < 0) {

+            prepLinkBuffer.append("?");

+        } else if (prepLinkBuffer.indexOf("?", prepLinkBuffer.length() - 1) > 0) {

+            prepLinkBuffer.append("&amp;");

+        }

+        if (!UtilValidate.isEmpty(queryString) && !queryString.equals("null")) {

+            prepLinkBuffer.append(queryString).append("&amp;");

+        }

+        prepLinkBuffer.append(viewSizeParam).append("=").append(viewSize).append("&amp;").append(viewIndexParam).append("=");

+        String prepLinkText = prepLinkBuffer.toString();

+        if (ajaxEnabled) {

+            // Prepare params for prototype.js

+            prepLinkText = prepLinkText.replace("?", "");

+            prepLinkText = prepLinkText.replace("&amp;", "&");

+        }

+

+        writer.append("<div class=\"").append(modelForm.getPaginateStyle()).append("\">");

+        appendWhitespace(writer);

+        writer.append(" <ul>");

+        appendWhitespace(writer);

+

+        String linkText;

+

+        // First button

+        writer.append("  <li class=\"").append(modelForm.getPaginateFirstStyle());

+        if (viewIndex > 0) {

+            writer.append("\"><a href=\"");

+            if (ajaxEnabled) {

+                writer.append("javascript:ajaxUpdateAreas('").append(createAjaxParamsFromUpdateAreas(updateAreas, prepLinkText + 0 + anchor, context)).append("')");

+            } else {

+                linkText = prepLinkText + 0 + anchor;

+                appendOfbizUrl(writer, urlPath + linkText);

+            }

+            writer.append("\">").append(modelForm.getPaginateFirstLabel(context)).append("</a>");

+        } else {

+            // disabled button

+            writer.append("-disabled\">").append(modelForm.getPaginateFirstLabel(context));

+        }

+        writer.append("</li>");

+        appendWhitespace(writer);

+

+        // Previous button

+        writer.append("  <li class=\"").append(modelForm.getPaginatePreviousStyle());

+        if (viewIndex > 0) {

+            writer.append("\"><a href=\"");

+            if (ajaxEnabled) {

+                writer.append("javascript:ajaxUpdateAreas('").append(createAjaxParamsFromUpdateAreas(updateAreas, prepLinkText + (viewIndex - 1) + anchor, context)).append("')");

+            } else {

+                linkText = prepLinkText + (viewIndex - 1) + anchor;

+                appendOfbizUrl(writer, urlPath + linkText);

+            }

+            writer.append("\">").append(modelForm.getPaginatePreviousLabel(context)).append("</a>");

+        } else {

+            // disabled button

+            writer.append("-disabled\">").append(modelForm.getPaginatePreviousLabel(context));

+        }

+        writer.append("</li>");

+        appendWhitespace(writer);

+

+        // Page select dropdown

+        if (listSize > 0 && this.javaScriptEnabled) {

+            writer.append("  <li>").append(pageLabel).append(" <select name=\"page\" size=\"1\" onchange=\"");

+            if (ajaxEnabled) {

+                writer.append("javascript:ajaxUpdateAreas('").append(createAjaxParamsFromUpdateAreas(updateAreas, prepLinkText + "' + this.value", context)).append(")");

+            } else {

+                linkText = prepLinkText;

+                if (linkText.startsWith("/")) {

+                    linkText = linkText.substring(1);

+                }

+                writer.append("location.href = '");

+                appendOfbizUrl(writer, urlPath + linkText);

+                writer.append("' + this.value;");

+            }

+            writer.append("\">");

+            // actual value

+            int page = 0;

+            for (int i = 0; i < listSize;) {

+                if (page == viewIndex) {

+                    writer.append("<option selected value=\"");

+                } else {

+                    writer.append("<option value=\"");

+                }

+                writer.append(Integer.toString(page));

+                writer.append("\">");

+                writer.append(Integer.toString(1 + page));

+                writer.append("</option>");

+                // increment page and calculate next index

+                page++;

+                i = page * viewSize;

+            }

+            writer.append("</select></li>");

+        }

+

+        //  show row count

+        writer.append("<li>");

+        writer.append(commonDisplaying);

+        writer.append("</li>");

+        appendWhitespace(writer);

+

+        // Next button

+        writer.append("  <li class=\"").append(modelForm.getPaginateNextStyle());

+        if (highIndex < listSize) {

+            writer.append("\"><a href=\"");

+            if (ajaxEnabled) {

+                writer.append("javascript:ajaxUpdateAreas('").append(createAjaxParamsFromUpdateAreas(updateAreas, prepLinkText + (viewIndex + 1) + anchor, context)).append("')");

+            } else {

+                linkText = prepLinkText + (viewIndex + 1) + anchor;

+                appendOfbizUrl(writer, urlPath + linkText);

+            }

+            writer.append("\">").append(modelForm.getPaginateNextLabel(context)).append("</a>");

+        } else {

+            // disabled button

+            writer.append("-disabled\">").append(modelForm.getPaginateNextLabel(context));

+        }

+        writer.append("</li>");

+        appendWhitespace(writer);

+

+        // Last button

+        writer.append("  <li class=\"").append(modelForm.getPaginateLastStyle());

+        if (highIndex < listSize) {

+            int lastIndex = UtilMisc.getViewLastIndex(listSize, viewSize);

+            writer.append("\"><a href=\"");

+            if (ajaxEnabled) {

+                writer.append("javascript:ajaxUpdateAreas('").append(createAjaxParamsFromUpdateAreas(updateAreas, prepLinkText + lastIndex + anchor, context)).append("')");

+            } else {

+                linkText = prepLinkText + lastIndex + anchor;

+                appendOfbizUrl(writer, urlPath + linkText);

+            }

+            writer.append("\">").append(modelForm.getPaginateLastLabel(context)).append("</a>");

+        } else {

+            // disabled button

+            writer.append("-disabled\">").append(modelForm.getPaginateLastLabel(context));

+        }

+        writer.append("</li>");

+        appendWhitespace(writer);

+

+        writer.append(" </ul>");

+        appendWhitespace(writer);

+        writer.append("</div>");

+        appendWhitespace(writer);

+    }

+

+    public void renderSortField(Appendable writer, Map<String, Object> context, ModelFormField modelFormField, String titleText) throws IOException {

+        boolean ajaxEnabled = false;

+        ModelForm modelForm = modelFormField.getModelForm();

+        List<ModelForm.UpdateArea> updateAreas = modelForm.getOnPaginateUpdateAreas();

+        String targetService = modelForm.getPaginateTarget(context);

+        if (this.javaScriptEnabled) {

+            if (UtilValidate.isNotEmpty(updateAreas)) {

+                ajaxEnabled = true;

+            }

+        }

+        if (targetService == null) {

+            targetService = "${targetService}";

+        }

+        if (UtilValidate.isEmpty(targetService) && updateAreas == null) {

+            Debug.logWarning("Cannot sort because TargetService is empty for the form: " + modelForm.getName(), module);

+            return;

+        }

+

+        String str = (String) context.get("_QBESTRING_");

+        String oldSortField = modelForm.getSortField(context);

+        String sortFieldStyle = modelFormField.getSortFieldStyle();

+

+        // if the entry-name is defined use this instead of field name

+        String columnField = modelFormField.getEntryName();

+        if (UtilValidate.isEmpty(columnField)) {

+            columnField = modelFormField.getFieldName();

+        }

+

+        // switch beetween asc/desc order

+        String newSortField = columnField;

+        if (UtilValidate.isNotEmpty(oldSortField)) {

+            if (oldSortField.equals(columnField)) {

+                newSortField = "-" + columnField;

+                sortFieldStyle = modelFormField.getSortFieldStyleDesc();

+            } else if (oldSortField.equals("-" + columnField)) {

+                newSortField = columnField;

+                sortFieldStyle = modelFormField.getSortFieldStyleAsc();

+            }

+        }

+

+        //  strip sortField param from the query string

+        HashSet<String> paramName = new HashSet<String>();

+        paramName.add("sortField");

+        String queryString = UtilHttp.stripNamedParamsFromQueryString(str, paramName);

+        String urlPath = UtilHttp.removeQueryStringFromTarget(targetService);

+        StringBuilder prepLinkBuffer = new StringBuilder();

+        String prepLinkQueryString = UtilHttp.getQueryStringFromTarget(targetService);

+        if (prepLinkQueryString != null) {

+            prepLinkBuffer.append(prepLinkQueryString);

+        }

+        if (prepLinkBuffer.indexOf("?") < 0) {

+            prepLinkBuffer.append("?");

+        } else if (prepLinkBuffer.indexOf("?", prepLinkBuffer.length() - 1) > 0) {

+            prepLinkBuffer.append("&amp;");

+        }

+        if (!UtilValidate.isEmpty(queryString) && !queryString.equals("null")) {

+            prepLinkBuffer.append(queryString).append("&amp;");

+        }

+        prepLinkBuffer.append("sortField").append("=").append(newSortField);

+        String prepLinkText = prepLinkBuffer.toString();

+        if (ajaxEnabled) {

+            prepLinkText = prepLinkText.replace("?", "");

+            prepLinkText = prepLinkText.replace("&amp;", "&");

+        }

+

+        writer.append("<a");

+        if (UtilValidate.isNotEmpty(sortFieldStyle)) {

+            writer.append(" class=\"");

+            writer.append(sortFieldStyle);

+            writer.append("\"");

+        }

+

+        writer.append(" href=\"");

+        if (ajaxEnabled) {

+            writer.append("javascript:ajaxUpdateAreas('").append(createAjaxParamsFromUpdateAreas(updateAreas, prepLinkText, context)).append("')");

+        } else {

+            appendOfbizUrl(writer, urlPath + prepLinkText);

+        }

+        writer.append("\">").append(titleText).append("</a>");

+    }

+

+    /* (non-Javadoc)

+     * @see org.ofbiz.widget.form.FormStringRenderer#renderFileField(java.io.Writer, java.util.Map, org.ofbiz.widget.model.ModelFormField.FileField)

+     */

+    public void renderFileField(Appendable writer, Map<String, Object> context, FileField textField) throws IOException {

+        ModelFormField modelFormField = textField.getModelFormField();

+

+        writer.append("<input type=\"file\"");

+

+        appendClassNames(writer, context, modelFormField);

+

+        writer.append(" name=\"");

+        writer.append(modelFormField.getParameterName(context));

+        writer.append('"');

+

+        String value = modelFormField.getEntry(context, textField.getDefaultValue(context));

+        if (UtilValidate.isNotEmpty(value)) {

+            writer.append(" value=\"");

+            writer.append(value);

+            writer.append('"');

+        }

+

+        writer.append(" size=\"");

+        writer.append(Integer.toString(textField.getSize()));

+        writer.append('"');

+

+        Integer maxlength = textField.getMaxlength();

+        if (maxlength != null) {

+            writer.append(" maxlength=\"");

+            writer.append(maxlength.toString());

+            writer.append('"');

+        }

+

+        if (!textField.getClientAutocompleteField()) {

+            writer.append(" autocomplete=\"off\"");

+        }

+

+        writer.append("/>");

+

+        this.makeHyperlinkString(writer, textField.getSubHyperlink(), context);

+

+        this.appendTooltip(writer, context, modelFormField);

+

+        //appendWhitespace(writer);

+    }

+

+    /* (non-Javadoc)

+     * @see org.ofbiz.widget.form.FormStringRenderer#renderPasswordField(java.io.Writer, java.util.Map, org.ofbiz.widget.model.ModelFormField.PasswordField)

+     */

+    public void renderPasswordField(Appendable writer, Map<String, Object> context, PasswordField passwordField) throws IOException {

+        ModelFormField modelFormField = passwordField.getModelFormField();

+

+        writer.append("<input type=\"password\"");

+

+        appendClassNames(writer, context, modelFormField);

+

+        writer.append(" name=\"");

+        writer.append(modelFormField.getParameterName(context));

+        writer.append('"');

+

+        String value = modelFormField.getEntry(context, passwordField.getDefaultValue(context));

+        if (UtilValidate.isNotEmpty(value)) {

+            writer.append(" value=\"");

+            writer.append(value);

+            writer.append('"');

+        }

+

+        writer.append(" size=\"");

+        writer.append(Integer.toString(passwordField.getSize()));

+        writer.append('"');

+

+        Integer maxlength = passwordField.getMaxlength();

+        if (maxlength != null) {

+            writer.append(" maxlength=\"");

+            writer.append(maxlength.toString());

+            writer.append('"');

+        }

+

+        String idName = modelFormField.getCurrentContainerId(context);

+        if (UtilValidate.isNotEmpty(idName)) {

+            writer.append(" id=\"");

+            writer.append(idName);

+            writer.append('"');

+        }

+

+        if (!passwordField.getClientAutocompleteField()) {

+            writer.append(" autocomplete=\"off\"");

+        }

+

+        writer.append("/>");

+

+        this.addAsterisks(writer, context, modelFormField);

+

+        this.makeHyperlinkString(writer, passwordField.getSubHyperlink(), context);

+

+        this.appendTooltip(writer, context, modelFormField);

+

+        //appendWhitespace(writer);

+    }

+

+    /* (non-Javadoc)

+     * @see org.ofbiz.widget.form.FormStringRenderer#renderImageField(java.io.Writer, java.util.Map, org.ofbiz.widget.model.ModelFormField.ImageField)

+     */

+    public void renderImageField(Appendable writer, Map<String, Object> context, ImageField imageField) throws IOException {

+        ModelFormField modelFormField = imageField.getModelFormField();

+

+        writer.append("<img ");

+

+        String value = modelFormField.getEntry(context, imageField.getValue(context));

+        if (UtilValidate.isNotEmpty(value)) {

+            writer.append(" src=\"");

+            appendContentUrl(writer, value);

+            writer.append('"');

+        }

+        

+        value = modelFormField.getEntry(context, imageField.getStyle(context));

+        if (UtilValidate.isNotEmpty(value)) {

+            writer.append(" class=\"");

+            appendContentUrl(writer, value);

+            writer.append('"');

+        }

+

+        String event = modelFormField.getEvent();

+        String action = modelFormField.getAction(context);

+        if (UtilValidate.isNotEmpty(event) && UtilValidate.isNotEmpty(action)) {

+            writer.append(" ");

+            writer.append(event);

+            writer.append("=\"");

+            writer.append(action);

+            writer.append('"');

+        }

+

+        writer.append("/>");

+

+        this.makeHyperlinkString(writer, imageField.getSubHyperlink(), context);

+

+        this.appendTooltip(writer, context, modelFormField);

+

+        //appendWhitespace(writer);

+    }

+

+    public void renderFieldGroupOpen(Appendable writer, Map<String, Object> context, ModelForm.FieldGroup fieldGroup) throws IOException {

+        String style = fieldGroup.getStyle();

+        String id = fieldGroup.getId();

+        FlexibleStringExpander titleNotExpanded = FlexibleStringExpander.getInstance(fieldGroup.getTitle());

+        String title = titleNotExpanded.expandString(context);

+        Boolean collapsed = fieldGroup.initiallyCollapsed();

+        String collapsibleAreaId = fieldGroup.getId() + "_body";

+

+        if (UtilValidate.isNotEmpty(style) || UtilValidate.isNotEmpty(id) || UtilValidate.isNotEmpty(title)) {

+

+            writer.append("<div class=\"fieldgroup");

+            if (UtilValidate.isNotEmpty(style)) {

+                writer.append(" ");

+                writer.append(style);

+            }

+            writer.append("\"");

+            if (UtilValidate.isNotEmpty(id)) {

+                writer.append(" id=\"");

+                writer.append(id);

+                writer.append("\"");

+            }

+            writer.append(">");

+

+            writer.append("<div class=\"fieldgroup-title-bar\"><table><tr><td class=\"collapse\">");

+

+            if (fieldGroup.collapsible()) {

+                String expandToolTip = null;

+                String collapseToolTip = null;

+                Map<String, Object> uiLabelMap = UtilGenerics.checkMap(context.get("uiLabelMap"));

+                //Map<String, Object> paramMap = UtilGenerics.checkMap(context.get("requestParameters"));

+                if (uiLabelMap != null) {

+                    expandToolTip = (String) uiLabelMap.get("CommonExpand");

+                    collapseToolTip = (String) uiLabelMap.get("CommonCollapse");

+                }

+

+                writer.append("<ul><li class=\"");

+                if (collapsed) {

+                    writer.append("collapsed\"><a ");

+                    writer.append("onclick=\"javascript:toggleCollapsiblePanel(this, '").append(collapsibleAreaId).append("', '").append(expandToolTip).append("', '").append(collapseToolTip).append("');\"");

+                } else {

+                    writer.append("expanded\"><a ");

+                    writer.append("onclick=\"javascript:toggleCollapsiblePanel(this, '").append(collapsibleAreaId).append("', '").append(expandToolTip).append("', '").append(collapseToolTip).append("');\"");

+                }

+                writer.append(">&nbsp&nbsp&nbsp</a></li></ul>");

+

+                appendWhitespace(writer);

+            }

+            writer.append("</td><td>");

+

+            if (UtilValidate.isNotEmpty(title)) {

+                writer.append("<div class=\"title\">");

+                writer.append(title);

+                writer.append("</div>");

+            }

+

+            writer.append("</td></tr></table></div>");

+

+            writer.append("<div id=\"").append(collapsibleAreaId).append("\" class=\"fieldgroup-body\"");

+            if (fieldGroup.collapsible() && collapsed) {

+                writer.append(" style=\"display: none;\"");

+            }

+            writer.append(">");

+        }

+    }

+

+    public void renderFieldGroupClose(Appendable writer, Map<String, Object> context, ModelForm.FieldGroup fieldGroup) throws IOException {

+        String style = fieldGroup.getStyle();

+        String id = fieldGroup.getId();

+        String title = fieldGroup.getTitle();

+        if (UtilValidate.isNotEmpty(style) || UtilValidate.isNotEmpty(id) || UtilValidate.isNotEmpty(title)) {

+            writer.append("</div>");

+            writer.append("</div>");

+        }

+    }

+

+    // TODO: Remove embedded styling

+    public void renderBanner(Appendable writer, Map<String, Object> context, ModelForm.Banner banner) throws IOException {

+        writer.append(" <table width=\"100%\">  <tr>");

+        String style = banner.getStyle(context);

+        String leftStyle = banner.getLeftTextStyle(context);

+        if (UtilValidate.isEmpty(leftStyle)) leftStyle = style;

+        String rightStyle = banner.getRightTextStyle(context);

+        if (UtilValidate.isEmpty(rightStyle)) rightStyle = style;

+

+        String leftText = banner.getLeftText(context);

+        if (UtilValidate.isNotEmpty(leftText)) {

+            writer.append("   <td align=\"left\">");

+            if (UtilValidate.isNotEmpty(leftStyle)) {

+               writer.append("<div");

+               writer.append(" class=\"");

+               writer.append(leftStyle);

+               writer.append("\"");

+               writer.append(">");

+            }

+            writer.append(leftText);

+            if (UtilValidate.isNotEmpty(leftStyle)) {

+                writer.append("</div>");

+            }

+            writer.append("</td>");

+        }

+

+        String text = banner.getText(context);

+        if (UtilValidate.isNotEmpty(text)) {

+            writer.append("   <td align=\"center\">");

+            if (UtilValidate.isNotEmpty(style)) {

+               writer.append("<div");

+               writer.append(" class=\"");

+               writer.append(style);

+               writer.append("\"");

+               writer.append(">");

+            }

+            writer.append(text);

+            if (UtilValidate.isNotEmpty(style)) {

+                writer.append("</div>");

+            }

+            writer.append("</td>");

+        }

+

+        String rightText = banner.getRightText(context);

+        if (UtilValidate.isNotEmpty(rightText)) {

+            writer.append("   <td align=\"right\">");

+            if (UtilValidate.isNotEmpty(rightStyle)) {

+               writer.append("<div");

+               writer.append(" class=\"");

+               writer.append(rightStyle);

+               writer.append("\"");

+               writer.append(">");

+            }

+            writer.append(rightText);

+            if (UtilValidate.isNotEmpty(rightStyle)) {

+                writer.append("</div>");

+            }

+            writer.append("</td>");

+        }

+        writer.append("</tr> </table>");

+    }

+

+    /**

+     * Renders a link for the column header fields when there is a header-link="" specified in the <field > tag, using

+     * style from header-link-style="".  Also renders a selectAll checkbox in multi forms.

+     * @param writer

+     * @param context

+     * @param modelFormField

+     * @param titleText

+     */

+    public void renderHyperlinkTitle(Appendable writer, Map<String, Object> context, ModelFormField modelFormField, String titleText) throws IOException {

+        if (UtilValidate.isNotEmpty(modelFormField.getHeaderLink())) {

+            StringBuilder targetBuffer = new StringBuilder();

+            FlexibleStringExpander target = FlexibleStringExpander.getInstance(modelFormField.getHeaderLink());

+            String fullTarget = target.expandString(context);

+            targetBuffer.append(fullTarget);

+            String targetType = CommonWidgetModels.Link.DEFAULT_URL_MODE;

+            if (UtilValidate.isNotEmpty(targetBuffer.toString()) && targetBuffer.toString().toLowerCase().startsWith("javascript:")) {

+                targetType="plain";

+            }

+            WidgetWorker.makeHyperlinkString(writer, modelFormField.getHeaderLinkStyle(), targetType, targetBuffer.toString(), null, titleText, null, modelFormField, this.request, this.response, null, null);

+        } else if (modelFormField.isSortField()) {

+            renderSortField (writer, context, modelFormField, titleText);

+        } else if (modelFormField.isRowSubmit()) {

+            if (UtilValidate.isNotEmpty(titleText)) writer.append(titleText).append("<br/>");

+            writer.append("<input type=\"checkbox\" name=\"selectAll\" value=\"Y\" onclick=\"javascript:toggleAll(this, '");

+            writer.append(modelFormField.getModelForm().getName());

+            writer.append("');\"/>");

+        } else {

+             writer.append(titleText);

+        }

+    }

+

+    public void renderContainerFindField(Appendable writer, Map<String, Object> context, ContainerField containerField) throws IOException {

+        writer.append("<div ");

+        String id = containerField.getModelFormField().getIdName();

+        if (UtilValidate.isNotEmpty(id)) {

+            writer.append("id=\"");

+            writer.append(id);

+            writer.append("\" ");

+        }

+        String className = containerField.getModelFormField().getWidgetStyle();

+        if (UtilValidate.isNotEmpty(className)) {

+            writer.append("class=\"");

+            writer.append(className);

+            writer.append("\" ");

+        }

+        writer.append("/>");

+    }

+

+    /** Create an ajaxXxxx JavaScript CSV string from a list of UpdateArea objects. See

+     * <code>selectall.js</code>.

+     * @param updateAreas

+     * @param extraParams Renderer-supplied additional target parameters

+     * @param context

+     * @return Parameter string or empty string if no UpdateArea objects were found

+     */

+    public String createAjaxParamsFromUpdateAreas(List<ModelForm.UpdateArea> updateAreas, String extraParams, Map<String, ? extends Object> context) {

+        if (updateAreas == null) {

+            return "";

+        }

+        StringBuilder ajaxUrl = new StringBuilder();

+        boolean firstLoop = true;

+        for (ModelForm.UpdateArea updateArea : updateAreas) {

+            if (firstLoop) {

+                firstLoop = false;

+            } else {

+                ajaxUrl.append(",");

+            }

+            String targetUrl = updateArea.getAreaTarget(context);

+            String ajaxParams = getAjaxParamsFromTarget(targetUrl);

+            if (UtilValidate.isNotEmpty(extraParams)) {

+                if (ajaxParams.length() > 0 && !extraParams.startsWith("&")) {

+                    ajaxParams += "&";

+                }

+                ajaxParams += extraParams;

+            }

+            ajaxUrl.append(updateArea.getAreaId()).append(",");

+            try {

+                appendOfbizUrl(ajaxUrl, UtilHttp.removeQueryStringFromTarget(targetUrl));

+            } catch (IOException e) {

+                throw UtilMisc.initCause(new InternalError(e.getMessage()), e);

+            }

+            ajaxUrl.append(",").append(ajaxParams);

+        }

+        return ajaxUrl.toString();

+    }

+}

diff --git a/framework/widget/src/org/ofbiz/widget/html/HtmlFormWrapper.java b/framework/widget/src/org/ofbiz/widget/renderer/html/HtmlFormWrapper.java
similarity index 96%
rename from framework/widget/src/org/ofbiz/widget/html/HtmlFormWrapper.java
rename to framework/widget/src/org/ofbiz/widget/renderer/html/HtmlFormWrapper.java
index 6b36db2..3718ea0 100644
--- a/framework/widget/src/org/ofbiz/widget/html/HtmlFormWrapper.java
+++ b/framework/widget/src/org/ofbiz/widget/renderer/html/HtmlFormWrapper.java
@@ -1,200 +1,200 @@
-/*******************************************************************************
- * 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.html;
-
-import java.io.IOException;
-import java.io.StringWriter;
-import java.util.HashMap;
-import java.util.Map;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import javax.xml.parsers.ParserConfigurationException;
-
-import org.ofbiz.base.util.Debug;
-import org.ofbiz.base.util.UtilGenerics;
-import org.ofbiz.base.util.UtilHttp;
-import org.ofbiz.base.util.UtilValidate;
-import org.ofbiz.base.util.collections.MapStack;
-import org.ofbiz.entity.Delegator;
-import org.ofbiz.service.LocalDispatcher;
-import org.ofbiz.widget.form.FormFactory;
-import org.ofbiz.widget.form.FormStringRenderer;
-import org.ofbiz.widget.form.ModelForm;
-import org.ofbiz.widget.form.FormRenderer;
-
-import org.xml.sax.SAXException;
-
-
-/**
- * Widget Library - HTML Form Wrapper class - makes it easy to do the setup and render of a form
- */
-public class HtmlFormWrapper {
-
-    public static final String module = HtmlFormWrapper.class.getName();
-
-    protected String resourceName;
-    protected String formName;
-    protected HttpServletRequest request;
-    protected HttpServletResponse response;
-    protected ModelForm modelForm;
-    protected FormStringRenderer renderer;
-    protected Map<String, Object> context;
-
-    protected HtmlFormWrapper() {}
-
-    public HtmlFormWrapper(String resourceName, String formName, HttpServletRequest request, HttpServletResponse response)
-            throws IOException, SAXException, ParserConfigurationException {
-        this.resourceName = resourceName;
-        this.formName = formName;
-        this.request = request;
-        this.response = response;
-        Delegator delegator = null;
-        try {
-            delegator = (Delegator) request.getAttribute("delegator");
-            LocalDispatcher dispatcher = (LocalDispatcher) request.getAttribute("dispatcher");
-            this.modelForm = FormFactory.getFormFromLocation(resourceName, formName, delegator.getModelReader(), dispatcher.getDispatchContext());
-        } catch (IllegalArgumentException iae) {
-            Debug.logWarning("Could not find form with name [" + formName + "] in class resource [" + resourceName + "], will try to load it using relative path syntax.", module);
-            this.modelForm = FormFactory.getFormFromWebappContext(resourceName, formName, request);
-        }
-
-        this.renderer = new HtmlFormRenderer(request, response);
-
-        this.context = new HashMap<String, Object>();
-        Map<String, Object> parameterMap = UtilHttp.getParameterMap(request);
-        context.put("parameters", parameterMap);
-
-        //make sure the locale is in the context
-        context.put("locale", UtilHttp.getLocale(request));
-        //make sure the timeZone is in the context
-        context.put("timeZone", UtilHttp.getTimeZone(request));
-
-        // if there was an error message, this is an error
-        if (UtilValidate.isNotEmpty(request.getAttribute("_ERROR_MESSAGE_"))) {
-            context.put("isError", Boolean.TRUE);
-        } else {
-            context.put("isError", Boolean.FALSE);
-        }
-
-        // if a parameter was passed saying this is an error, it is an error
-        if ("true".equals(parameterMap.get("isError"))) {
-            context.put("isError", Boolean.TRUE);
-        }
-
-        Map<String, String> uiLabelMap = UtilGenerics.cast(request.getAttribute("uiLabelMap"));
-        if (UtilValidate.isNotEmpty(uiLabelMap) && context.get("uiLabelMap") == null) {
-            Debug.logInfo("Got uiLabelMap: " + uiLabelMap, module);
-            context.put("uiLabelMap", uiLabelMap);
-        }
-        if (UtilValidate.isNotEmpty(delegator) && context.get("delegator") == null) {
-            context.put("delegator", delegator);
-        }
-    }
-
-    @SuppressWarnings("unchecked")
-    public StringWriter renderFormString(Object contextStack) throws Exception {
-        if (contextStack instanceof MapStack) {
-            return renderFormString((MapStack) contextStack);
-        } else {
-            Debug.logWarning("Call renderFormString with a non-MapStack: " + (contextStack == null ? "null" : contextStack.getClass().getName()), module);
-            return renderFormString();
-        }
-    }
-    public StringWriter renderFormString(MapStack<String> contextStack) throws Exception {
-        // create a new context with the current context on the bottom
-        contextStack.push(this.context);
-        StringWriter buffer = new StringWriter();
-        FormRenderer formRenderer = new FormRenderer(modelForm, renderer);
-        formRenderer.render(buffer, contextStack);
-        contextStack.pop();
-        return buffer;
-    }
-    public StringWriter renderFormString() throws Exception {
-        StringWriter buffer = new StringWriter();
-        FormRenderer formRenderer = new FormRenderer(modelForm, renderer);
-        formRenderer.render(buffer, context);
-        return buffer;
-    }
-
-    /**
-     * Tells the form library whether this is a response to an error or not.
-     * Defaults on initialization according to the presense of an errorMessage
-     * in the request or if an isError parameter was passed to the page with
-     * the value "true". If true then the prefilled values will come from the
-     * parameters Map instead of the value Map.
-     */
-    public void setIsError(boolean isError) {
-        this.context.put("isError", Boolean.valueOf(isError));
-    }
-
-    public boolean getIsError() {
-        Boolean isErrorBoolean = (Boolean) this.context.get("isError");
-        if (isErrorBoolean == null) {
-            return false;
-        } else {
-            return isErrorBoolean.booleanValue();
-        }
-    }
-
-    /**
-     * The "useRequestParameters" value in the form context tells the form library
-     * to use the request parameters to fill in values instead of the value map.
-     * This is generally used when it is an empty form to pre-set inital values.
-     * This is automatically set to false for list and multi forms. For related
-     * functionality see the setIsError method.
-     *
-     * @param useRequestParameters
-     */
-    public void setUseRequestParameters(boolean useRequestParameters) {
-        this.context.put("useRequestParameters", Boolean.valueOf(useRequestParameters));
-    }
-
-    public boolean getUseRequestParameters() {
-        Boolean useRequestParametersBoolean = (Boolean) this.context.get("useRequestParameters");
-        if (useRequestParametersBoolean == null) {
-            return false;
-        } else {
-            return useRequestParametersBoolean.booleanValue();
-        }
-    }
-
-    public void setFormOverrideName(String formName) {
-        this.context.put("formName", formName);
-    }
-
-    public void putInContext(String name, Object value) {
-        this.context.put(name, value);
-    }
-
-    public Object getFromContext(String name) {
-        return this.context.get(name);
-    }
-
-    public ModelForm getModelForm() {
-        return modelForm;
-    }
-
-    public FormStringRenderer getRenderer() {
-        return renderer;
-    }
-
-    public void setRenderer(FormStringRenderer renderer) {
-        this.renderer = renderer;
-    }
-}
+/*******************************************************************************

+ * 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.renderer.html;

+

+import java.io.IOException;

+import java.io.StringWriter;

+import java.util.HashMap;

+import java.util.Map;

+

+import javax.servlet.http.HttpServletRequest;

+import javax.servlet.http.HttpServletResponse;

+import javax.xml.parsers.ParserConfigurationException;

+

+import org.ofbiz.base.util.Debug;

+import org.ofbiz.base.util.UtilGenerics;

+import org.ofbiz.base.util.UtilHttp;

+import org.ofbiz.base.util.UtilValidate;

+import org.ofbiz.base.util.collections.MapStack;

+import org.ofbiz.entity.Delegator;

+import org.ofbiz.service.LocalDispatcher;

+import org.ofbiz.widget.model.FormFactory;

+import org.ofbiz.widget.model.ModelForm;

+import org.ofbiz.widget.renderer.FormRenderer;

+import org.ofbiz.widget.renderer.FormStringRenderer;

+import org.xml.sax.SAXException;

+

+

+/**

+ * Widget Library - HTML Form Wrapper class - makes it easy to do the setup and render of a form

+ */

+public class HtmlFormWrapper {

+

+    public static final String module = HtmlFormWrapper.class.getName();

+

+    protected String resourceName;

+    protected String formName;

+    protected HttpServletRequest request;

+    protected HttpServletResponse response;

+    protected ModelForm modelForm;

+    protected FormStringRenderer renderer;

+    protected Map<String, Object> context;

+

+    protected HtmlFormWrapper() {}

+

+    public HtmlFormWrapper(String resourceName, String formName, HttpServletRequest request, HttpServletResponse response)

+            throws IOException, SAXException, ParserConfigurationException {

+        this.resourceName = resourceName;

+        this.formName = formName;

+        this.request = request;

+        this.response = response;

+        Delegator delegator = null;

+        try {

+            delegator = (Delegator) request.getAttribute("delegator");

+            LocalDispatcher dispatcher = (LocalDispatcher) request.getAttribute("dispatcher");

+            this.modelForm = FormFactory.getFormFromLocation(resourceName, formName, delegator.getModelReader(), dispatcher.getDispatchContext());

+        } catch (IllegalArgumentException iae) {

+            Debug.logWarning("Could not find form with name [" + formName + "] in class resource [" + resourceName + "], will try to load it using relative path syntax.", module);

+            this.modelForm = FormFactory.getFormFromWebappContext(resourceName, formName, request);

+        }

+

+        this.renderer = new HtmlFormRenderer(request, response);

+

+        this.context = new HashMap<String, Object>();

+        Map<String, Object> parameterMap = UtilHttp.getParameterMap(request);

+        context.put("parameters", parameterMap);

+

+        //make sure the locale is in the context

+        context.put("locale", UtilHttp.getLocale(request));

+        //make sure the timeZone is in the context

+        context.put("timeZone", UtilHttp.getTimeZone(request));

+

+        // if there was an error message, this is an error

+        if (UtilValidate.isNotEmpty(request.getAttribute("_ERROR_MESSAGE_"))) {

+            context.put("isError", Boolean.TRUE);

+        } else {

+            context.put("isError", Boolean.FALSE);

+        }

+

+        // if a parameter was passed saying this is an error, it is an error

+        if ("true".equals(parameterMap.get("isError"))) {

+            context.put("isError", Boolean.TRUE);

+        }

+

+        Map<String, String> uiLabelMap = UtilGenerics.cast(request.getAttribute("uiLabelMap"));

+        if (UtilValidate.isNotEmpty(uiLabelMap) && context.get("uiLabelMap") == null) {

+            Debug.logInfo("Got uiLabelMap: " + uiLabelMap, module);

+            context.put("uiLabelMap", uiLabelMap);

+        }

+        if (UtilValidate.isNotEmpty(delegator) && context.get("delegator") == null) {

+            context.put("delegator", delegator);

+        }

+    }

+

+    @SuppressWarnings("unchecked")

+    public StringWriter renderFormString(Object contextStack) throws Exception {

+        if (contextStack instanceof MapStack) {

+            return renderFormString((MapStack) contextStack);

+        } else {

+            Debug.logWarning("Call renderFormString with a non-MapStack: " + (contextStack == null ? "null" : contextStack.getClass().getName()), module);

+            return renderFormString();

+        }

+    }

+    public StringWriter renderFormString(MapStack<String> contextStack) throws Exception {

+        // create a new context with the current context on the bottom

+        contextStack.push(this.context);

+        StringWriter buffer = new StringWriter();

+        FormRenderer formRenderer = new FormRenderer(modelForm, renderer);

+        formRenderer.render(buffer, contextStack);

+        contextStack.pop();

+        return buffer;

+    }

+    public StringWriter renderFormString() throws Exception {

+        StringWriter buffer = new StringWriter();

+        FormRenderer formRenderer = new FormRenderer(modelForm, renderer);

+        formRenderer.render(buffer, context);

+        return buffer;

+    }

+

+    /**

+     * Tells the form library whether this is a response to an error or not.

+     * Defaults on initialization according to the presense of an errorMessage

+     * in the request or if an isError parameter was passed to the page with

+     * the value "true". If true then the prefilled values will come from the

+     * parameters Map instead of the value Map.

+     */

+    public void setIsError(boolean isError) {

+        this.context.put("isError", Boolean.valueOf(isError));

+    }

+

+    public boolean getIsError() {

+        Boolean isErrorBoolean = (Boolean) this.context.get("isError");

+        if (isErrorBoolean == null) {

+            return false;

+        } else {

+            return isErrorBoolean.booleanValue();

+        }

+    }

+

+    /**

+     * The "useRequestParameters" value in the form context tells the form library

+     * to use the request parameters to fill in values instead of the value map.

+     * This is generally used when it is an empty form to pre-set inital values.

+     * This is automatically set to false for list and multi forms. For related

+     * functionality see the setIsError method.

+     *

+     * @param useRequestParameters

+     */

+    public void setUseRequestParameters(boolean useRequestParameters) {

+        this.context.put("useRequestParameters", Boolean.valueOf(useRequestParameters));

+    }

+

+    public boolean getUseRequestParameters() {

+        Boolean useRequestParametersBoolean = (Boolean) this.context.get("useRequestParameters");

+        if (useRequestParametersBoolean == null) {

+            return false;

+        } else {

+            return useRequestParametersBoolean.booleanValue();

+        }

+    }

+

+    public void setFormOverrideName(String formName) {

+        this.context.put("formName", formName);

+    }

+

+    public void putInContext(String name, Object value) {

+        this.context.put(name, value);

+    }

+

+    public Object getFromContext(String name) {

+        return this.context.get(name);

+    }

+

+    public ModelForm getModelForm() {

+        return modelForm;

+    }

+

+    public FormStringRenderer getRenderer() {

+        return renderer;

+    }

+

+    public void setRenderer(FormStringRenderer renderer) {

+        this.renderer = renderer;

+    }

+}

diff --git a/framework/widget/src/org/ofbiz/widget/html/HtmlMenuRenderer.java b/framework/widget/src/org/ofbiz/widget/renderer/html/HtmlMenuRenderer.java
similarity index 98%
rename from framework/widget/src/org/ofbiz/widget/html/HtmlMenuRenderer.java
rename to framework/widget/src/org/ofbiz/widget/renderer/html/HtmlMenuRenderer.java
index 77b36c1..15531a3 100644
--- a/framework/widget/src/org/ofbiz/widget/html/HtmlMenuRenderer.java
+++ b/framework/widget/src/org/ofbiz/widget/renderer/html/HtmlMenuRenderer.java
@@ -1,592 +1,592 @@
-/*******************************************************************************
- * 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.html;
-
-import java.io.IOException;
-import java.math.BigDecimal;
-import java.util.List;
-import java.util.Map;
-
-import javax.servlet.ServletContext;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import javax.servlet.http.HttpSession;
-
-import org.ofbiz.base.util.StringUtil;
-import org.ofbiz.base.util.UtilCodec;
-import org.ofbiz.base.util.UtilMisc;
-import org.ofbiz.base.util.UtilValidate;
-import org.ofbiz.entity.Delegator;
-import org.ofbiz.entity.GenericValue;
-import org.ofbiz.webapp.control.RequestHandler;
-import org.ofbiz.webapp.taglib.ContentUrlTag;
-import org.ofbiz.widget.ModelWidget;
-import org.ofbiz.widget.WidgetWorker;
-import org.ofbiz.widget.menu.MenuStringRenderer;
-import org.ofbiz.widget.menu.ModelMenu;
-import org.ofbiz.widget.menu.ModelMenuItem;
-import org.ofbiz.widget.CommonWidgetModels.*;
-import org.ofbiz.widget.menu.ModelMenuItem.MenuLink;
-
-/**
- * Widget Library - HTML Menu Renderer implementation
- */
-public class HtmlMenuRenderer extends HtmlWidgetRenderer implements MenuStringRenderer {
-
-    HttpServletRequest request;
-    HttpServletResponse response;
-    protected String userLoginIdAtPermGrant;
-    protected String permissionErrorMessage = "";
-
-    public static final String module = HtmlMenuRenderer.class.getName();
-
-    protected HtmlMenuRenderer() {}
-
-    public HtmlMenuRenderer(HttpServletRequest request, HttpServletResponse response) {
-        this.request = request;
-        this.response = response;
-    }
-
-    public void appendOfbizUrl(Appendable writer, String location) throws IOException {
-        ServletContext ctx = (ServletContext) request.getAttribute("servletContext");
-        if (ctx == null) {
-            //if (Debug.infoOn()) Debug.logInfo("in appendOfbizUrl, ctx is null(0): buffer=" + buffer.toString() + " location:" + location, "");
-            HttpSession session = request.getSession();
-            if (session != null) {
-                ctx = session.getServletContext();
-            } else {
-                //if (Debug.infoOn()) Debug.logInfo("in appendOfbizUrl, session is null(1)", "");
-            }
-            if (ctx == null) {
-                throw new RuntimeException("ctx is null. location:" + location);
-            }
-                //if (Debug.infoOn()) Debug.logInfo("in appendOfbizUrl, ctx is NOT null(2)", "");
-        }
-        Delegator delegator = (Delegator)request.getAttribute("delegator");
-        if (delegator == null) {
-                //if (Debug.infoOn()) Debug.logInfo("in appendOfbizUrl, delegator is null(5)", "");
-        }
-        RequestHandler rh = (RequestHandler) ctx.getAttribute("_REQUEST_HANDLER_");
-        // make and append the link
-        String s = rh.makeLink(this.request, this.response, location);
-        if (s.indexOf("null") >= 0) {
-            //if (Debug.infoOn()) Debug.logInfo("in appendOfbizUrl(3), url: " + s, "");
-        }
-        writer.append(s);
-    }
-
-    public void appendContentUrl(Appendable writer, String location) throws IOException {
-        ServletContext ctx = (ServletContext) this.request.getAttribute("servletContext");
-        if (ctx == null) {
-            //if (Debug.infoOn()) Debug.logInfo("in appendContentUrl, ctx is null(0): buffer=" + buffer.toString() + " location:" + location, "");
-            HttpSession session = request.getSession();
-            if (session != null) {
-                ctx = session.getServletContext();
-            } else {
-                //if (Debug.infoOn()) Debug.logInfo("in appendContentUrl, session is null(1)", "");
-            }
-            if (ctx == null) {
-                throw new RuntimeException("ctx is null. location:" + location);
-            }
-            //if (Debug.infoOn()) Debug.logInfo("in appendContentUrl, ctx is NOT null(2)", "");
-            this.request.setAttribute("servletContext", ctx);
-        }
-        Delegator delegator = (Delegator) request.getAttribute("delegator");
-        if (delegator == null) {
-                //if (Debug.infoOn()) Debug.logInfo("in appendContentUrl, delegator is null(6)", "");
-        }
-        StringBuilder buffer = new StringBuilder();
-        ContentUrlTag.appendContentPrefix(this.request, buffer);
-        writer.append(buffer.toString());
-        writer.append(location);
-    }
-
-    public void appendTooltip(Appendable writer, Map<String, Object> context, ModelMenuItem modelMenuItem) throws IOException {
-        // render the tooltip
-        String tooltip = modelMenuItem.getTooltip(context);
-        if (UtilValidate.isNotEmpty(tooltip)) {
-            writer.append("<span class=\"");
-            String tooltipStyle = modelMenuItem.getTooltipStyle();
-            if (UtilValidate.isNotEmpty(tooltipStyle)) {
-                writer.append(tooltipStyle);
-            } else {
-                writer.append("tooltip");
-            }
-            writer.append("\"");
-            writer.append(tooltip);
-            writer.append("</span>");
-        }
-    }
-
-    public void renderFormatSimpleWrapperRows(Appendable writer, Map<String, Object> context, Object menuObj) throws IOException {
-        List<ModelMenuItem> menuItemList = ((ModelMenu) menuObj).getMenuItemList();
-        for (ModelMenuItem currentMenuItem: menuItemList) {
-            renderMenuItem(writer, context, currentMenuItem);
-        }
-    }
-
-    public void renderMenuItem(Appendable writer, Map<String, Object> context, ModelMenuItem menuItem) throws IOException {
-
-        //Debug.logInfo("in renderMenuItem, menuItem:" + menuItem.getName() + " context:" + context ,"");
-        boolean hideThisItem = isHideIfSelected(menuItem, context);
-        //if (Debug.infoOn()) Debug.logInfo("in HtmlMenuRendererImage, hideThisItem:" + hideThisItem,"");
-        if (hideThisItem)
-            return;
-
-        String style = menuItem.getWidgetStyle();
-
-        if (menuItem.isSelected(context)) {
-            style = menuItem.getSelectedStyle();
-            if (UtilValidate.isEmpty(style)) {
-                style = "selected";
-            }
-        }
-
-        if (this.isDisableIfEmpty(menuItem, context)) {
-            style = menuItem.getDisabledTitleStyle();
-        }
-
-        writer.append("  <li");
-        String alignStyle = menuItem.getAlignStyle();
-        if (UtilValidate.isNotEmpty(style) || UtilValidate.isNotEmpty(alignStyle)) {
-            writer.append(" class=\"");
-            if (UtilValidate.isNotEmpty(style)) {
-                writer.append(style).append(" ");
-            }
-            if (UtilValidate.isNotEmpty(alignStyle)) {
-                writer.append(alignStyle);
-            }
-            writer.append("\"");
-        }
-        String toolTip = menuItem.getTooltip(context);
-        if (UtilValidate.isNotEmpty(toolTip)) {
-            writer.append(" title=\"").append(toolTip).append("\"");
-        }
-        writer.append(">");
-
-        MenuLink link = menuItem.getLink();
-        //if (Debug.infoOn()) Debug.logInfo("in HtmlMenuRendererImage, link(0):" + link,"");
-        if (link != null) {
-            renderLink(writer, context, link);
-        } else {
-            String txt = menuItem.getTitle(context);
-            UtilCodec.SimpleEncoder simpleEncoder = (UtilCodec.SimpleEncoder) context.get("simpleEncoder");
-            if (simpleEncoder != null) {
-                txt = simpleEncoder.encode(txt);
-            }
-            writer.append(txt);
-
-        }
-        if (!menuItem.getMenuItemList().isEmpty()) {
-            appendWhitespace(writer);
-            writer.append("    <ul>");
-            appendWhitespace(writer);
-            for (ModelMenuItem childMenuItem : menuItem.getMenuItemList()) {
-                childMenuItem.renderMenuItemString(writer, context, this);
-            }
-            writer.append("    </ul>");
-            appendWhitespace(writer);
-        }
-
-        writer.append("</li>");
-
-        appendWhitespace(writer);
-    }
-
-    public boolean isDisableIfEmpty(ModelMenuItem menuItem, Map<String, Object> context) {
-        boolean disabled = false;
-        String disableIfEmpty = menuItem.getDisableIfEmpty();
-        if (UtilValidate.isNotEmpty(disableIfEmpty)) {
-            List<String> keys = StringUtil.split(disableIfEmpty, "|");
-            for (String key: keys) {
-                Object obj = context.get(key);
-                if (obj == null) {
-                    disabled = true;
-                    break;
-                }
-            }
-        }
-        return disabled;
-    }
-
-/*
-    public String buildDivStr(ModelMenuItem menuItem, Map<String, Object> context) {
-        String divStr = "";
-        divStr =  menuItem.getTitle(context);
-        return divStr;
-    }
-*/
-    public void renderMenuOpen(Appendable writer, Map<String, Object> context, ModelMenu modelMenu) throws IOException {
-
-            //Debug.logInfo("in HtmlMenuRenderer, userLoginIdHasChanged:" + userLoginIdHasChanged,"");
-        this.widgetCommentsEnabled = ModelWidget.widgetBoundaryCommentsEnabled(context);
-        renderBeginningBoundaryComment(writer, "Menu Widget", modelMenu);
-        writer.append("<div");
-        String menuId = modelMenu.getId();
-        if (UtilValidate.isNotEmpty(menuId)) {
-            writer.append(" id=\"").append(menuId).append("\"");
-        } else {
-            // TODO: Remove else after UI refactor - allow both id and style
-            String menuContainerStyle = modelMenu.getMenuContainerStyle(context);
-            if (UtilValidate.isNotEmpty(menuContainerStyle)) {
-                writer.append(" class=\"").append(menuContainerStyle).append("\"");
-            }
-        }
-        String menuWidth = modelMenu.getMenuWidth();
-        // TODO: Eliminate embedded styling after refactor
-        if (UtilValidate.isNotEmpty(menuWidth)) {
-            writer.append(" style=\"width:").append(menuWidth).append(";\"");
-        }
-        writer.append(">");
-        appendWhitespace(writer);
-        String menuTitle = modelMenu.getTitle(context);
-        if (UtilValidate.isNotEmpty(menuTitle)) {
-            writer.append("<h2>").append(menuTitle).append("</h2>");
-            appendWhitespace(writer);
-        }
-        if (modelMenu.renderedMenuItemCount(context) > 0) {
-            writer.append("<ul>");
-            appendWhitespace(writer);
-            writer.append("<li>");
-            appendWhitespace(writer);
-            writer.append(" <ul>");
-            appendWhitespace(writer);
-        }
-    }
-
-    /* (non-Javadoc)
-     * @see org.ofbiz.widget.menu.MenuStringRenderer#renderMenuClose(java.io.Writer, java.util.Map, org.ofbiz.widget.menu.ModelMenu)
-     */
-    public void renderMenuClose(Appendable writer, Map<String, Object> context, ModelMenu modelMenu) throws IOException {
-        // TODO: div can't be directly inside an UL
-        String fillStyle = modelMenu.getFillStyle();
-        if (UtilValidate.isNotEmpty(fillStyle)) {
-            writer.append("<div class=\"").append(fillStyle).append("\">&nbsp;</div>");
-        }
-        //String menuContainerStyle = modelMenu.getMenuContainerStyle(context);
-        if (modelMenu.renderedMenuItemCount(context) > 0) {      
-            writer.append(" </ul>");
-            appendWhitespace(writer);
-            writer.append("</li>");
-            appendWhitespace(writer);
-            writer.append("</ul>");
-            appendWhitespace(writer);
-        }
-        writer.append(" <br class=\"clear\"/>");
-        appendWhitespace(writer);
-        writer.append("</div>");
-        appendWhitespace(writer);
-        renderEndingBoundaryComment(writer, "Menu Widget", modelMenu);
-
-        GenericValue userLogin = (GenericValue)request.getSession().getAttribute("userLogin");
-        if (userLogin != null) {
-            String userLoginId = userLogin.getString("userLoginId");
-            //request.getSession().setAttribute("userLoginIdAtPermGrant", userLoginId);
-            setUserLoginIdAtPermGrant(userLoginId);
-            //Debug.logInfo("in HtmlMenuRenderer, userLoginId(Close):" + userLoginId + " userLoginIdAtPermGrant:" + request.getSession().getAttribute("userLoginIdAtPermGrant"),"");
-        } else {
-            request.getSession().setAttribute("userLoginIdAtPermGrant", null);
-        }
-    }
-
-    public void renderFormatSimpleWrapperOpen(Appendable writer, Map<String, Object> context, ModelMenu modelMenu) throws IOException {
-        //appendWhitespace(writer);
-    }
-
-    public void renderFormatSimpleWrapperClose(Appendable writer, Map<String, Object> context, ModelMenu modelMenu) throws IOException {
-        //appendWhitespace(writer);
-    }
-
-    public void setRequest(HttpServletRequest request) {
-        this.request = request;
-    }
-
-    public void setResponse(HttpServletResponse response) {
-        this.response = response;
-    }
-
-
-    /**
-     * @param string
-     */
-    public void setUserLoginIdAtPermGrant(String string) {
-            //Debug.logInfo("in HtmlMenuRenderer,  userLoginIdAtPermGrant(setUserLoginIdAtPermGrant):" + string,"");
-        this.userLoginIdAtPermGrant = string;
-    }
-
-    public String getUserLoginIdAtPermGrant() {
-        return this.userLoginIdAtPermGrant;
-    }
-
-    public boolean isHideIfSelected(ModelMenuItem menuItem, Map<String, Object> context) {
-        ModelMenu menu = menuItem.getModelMenu();
-        String currentMenuItemName = menu.getSelectedMenuItemContextFieldName(context);
-        String currentItemName = menuItem.getName();
-        Boolean hideIfSelected = menuItem.getHideIfSelected();
-            //Debug.logInfo("in HtmlMenuRenderer, currentMenuItemName:" + currentMenuItemName + " currentItemName:" + currentItemName + " hideIfSelected:" + hideIfSelected,"");
-        return (hideIfSelected != null && hideIfSelected.booleanValue() && currentMenuItemName != null && currentMenuItemName.equals(currentItemName));
-    }
-
-
-    public boolean userLoginIdHasChanged() {
-        boolean hasChanged = false;
-        GenericValue userLogin = (GenericValue)request.getSession().getAttribute("userLogin");
-        userLoginIdAtPermGrant = getUserLoginIdAtPermGrant();
-        //userLoginIdAtPermGrant = (String)request.getSession().getAttribute("userLoginIdAtPermGrant");
-        String userLoginId = null;
-        if (userLogin != null)
-            userLoginId = userLogin.getString("userLoginId");
-            //Debug.logInfo("in HtmlMenuRenderer, userLoginId:" + userLoginId + " userLoginIdAtPermGrant:" + userLoginIdAtPermGrant ,"");
-        if ((userLoginId == null && userLoginIdAtPermGrant != null)
-           || (userLoginId != null && userLoginIdAtPermGrant == null)
-           || ((userLoginId != null && userLoginIdAtPermGrant != null)
-              && !userLoginId.equals(userLoginIdAtPermGrant))) {
-            hasChanged = true;
-        } else {
-            if (userLoginIdAtPermGrant != null)
-               hasChanged = true;
-            else
-               hasChanged = false;
-
-            userLoginIdAtPermGrant = null;
-        }
-        return hasChanged;
-    }
-
-    public String getTitle(ModelMenuItem menuItem, Map<String, Object> context) {
-        String title = null;
-        title = menuItem.getTitle(context);
-        return title;
-    }
-
-    public void renderLink(Appendable writer, Map<String, Object> context, ModelMenuItem.MenuLink link) throws IOException {
-        String target = link.getTarget(context);
-        ModelMenuItem menuItem = link.getLinkMenuItem();
-        if (isDisableIfEmpty(menuItem, context)) {
-            target = null;
-        }
-
-        if (UtilValidate.isNotEmpty(target)) {
-            HttpServletResponse response = (HttpServletResponse) context.get("response");
-            HttpServletRequest request = (HttpServletRequest) context.get("request");
-
-            String targetWindow = link.getTargetWindow(context);
-            String uniqueItemName = menuItem.getModelMenu().getName() + "_" + menuItem.getName() + "_LF_" + UtilMisc.<String>addToBigDecimalInMap(context, "menuUniqueItemIndex", BigDecimal.ONE);
-
-            String linkType = WidgetWorker.determineAutoLinkType(link.getLinkType(), target, link.getUrlMode(), request);
-            if ("hidden-form".equals(linkType)) {
-                writer.append("<form method=\"post\"");
-                writer.append(" action=\"");
-                // note that this passes null for the parameterList on purpose so they won't be put into the URL
-                WidgetWorker.buildHyperlinkUrl(writer, target, link.getUrlMode(), null, link.getPrefix(context),
-                        link.getFullPath(), link.getSecure(), link.getEncode(), request, response, context);
-                writer.append("\"");
-
-                if (UtilValidate.isNotEmpty(targetWindow)) {
-                    writer.append(" target=\"");
-                    writer.append(targetWindow);
-                    writer.append("\"");
-                }
-
-                writer.append(" name=\"");
-                writer.append(uniqueItemName);
-                writer.append("\">");
-
-                UtilCodec.SimpleEncoder simpleEncoder = (UtilCodec.SimpleEncoder) context.get("simpleEncoder");
-                for (Map.Entry<String, String> parameter: link.getParameterMap(context).entrySet()) {
-                    writer.append("<input name=\"");
-                    writer.append(parameter.getKey());
-                    writer.append("\" value=\"");
-                    if (simpleEncoder != null) {
-                        writer.append(simpleEncoder.encode(parameter.getValue()));
-                    } else {
-                        writer.append(parameter.getValue());
-                    }
-                    writer.append("\" type=\"hidden\"/>");
-                }
-
-                writer.append("</form>");
-            }
-
-            writer.append("<a");
-            String id = link.getId(context);
-            if (UtilValidate.isNotEmpty(id)) {
-                writer.append(" id=\"");
-                writer.append(id);
-                writer.append("\"");
-            }
-
-            String style = link.getStyle(context);
-            if (UtilValidate.isNotEmpty(style)) {
-                writer.append(" class=\"");
-                writer.append(style);
-                writer.append("\"");
-            }
-            String name = link.getName(context);
-            if (UtilValidate.isNotEmpty(name)) {
-                writer.append(" name=\"");
-                writer.append(name);
-                writer.append("\"");
-            }
-            if (!"hidden-form".equals(linkType)) {
-                if (UtilValidate.isNotEmpty(targetWindow)) {
-                    writer.append(" target=\"");
-                    writer.append(targetWindow);
-                    writer.append("\"");
-                }
-            }
-
-            writer.append(" href=\"");
-            String confirmationMsg = null;
-            if ("hidden-form".equals(linkType)) {
-                if (UtilValidate.isNotEmpty(confirmationMsg)) {
-                    writer.append("javascript:confirmActionFormLink('");
-                    writer.append(confirmationMsg);
-                    writer.append("', '");
-                    writer.append(uniqueItemName);
-                    writer.append("')");
-                } else {
-                    writer.append("javascript:document.");
-                    writer.append(uniqueItemName);
-                    writer.append(".submit()");
-                }
-            } else {
-                if (UtilValidate.isNotEmpty(confirmationMsg)) {
-                    writer.append("javascript:confirmActionLink('");
-                    writer.append(confirmationMsg);
-                    writer.append("', '");
-                    WidgetWorker.buildHyperlinkUrl(writer, target, link.getUrlMode(), link.getParameterMap(context), link.getPrefix(context),
-                            link.getFullPath(), link.getSecure(), link.getEncode(), request, response, context);
-                    writer.append("')");
-                } else {
-                WidgetWorker.buildHyperlinkUrl(writer, target, link.getUrlMode(), link.getParameterMap(context), link.getPrefix(context),
-                        link.getFullPath(), link.getSecure(), link.getEncode(), request, response, context);
-                }
-            }
-            writer.append("\">");
-        }
-
-        // the text
-        Image img = link.getImage();
-        if (img != null) {
-            renderImage(writer, context, img);
-            writer.append("&nbsp;" + link.getText(context));
-        } else {
-            writer.append(link.getText(context));
-        }
-
-        if (UtilValidate.isNotEmpty(target)) {
-            // close tag
-            writer.append("</a>");
-        }
-
-        /* NOTE DEJ20090316: This was here as a comment and not sure what it is for or if it is useful... can probably be safely removed in the future if still not used/needed
-        boolean isSelected = menuItem.isSelected(context);
-
-        String style = null;
-
-        if (isSelected) {
-        style = menuItem.getSelectedStyle();
-        } else {
-        style = link.getStyle(context);
-        if (UtilValidate.isEmpty(style))
-        style = menuItem.getTitleStyle();
-        if (UtilValidate.isEmpty(style))
-        style = menuItem.getWidgetStyle();
-        }
-
-        if (menuItem.getDisabled()) {
-        style = menuItem.getDisabledTitleStyle();
-        }
-
-        if (UtilValidate.isNotEmpty(style)) {
-        writer.append(" class=\"");
-        writer.append(style);
-        writer.append("\"");
-        }
-        */
-    }
-
-    public void renderImage(Appendable writer, Map<String, Object> context, Image image) throws IOException {
-        // open tag
-        writer.append("<img ");
-        String id = image.getId(context);
-        if (UtilValidate.isNotEmpty(id)) {
-            writer.append(" id=\"");
-            writer.append(id);
-            writer.append("\"");
-        }
-        String style = image.getStyle(context);
-        if (UtilValidate.isNotEmpty(style)) {
-            writer.append(" class=\"");
-            writer.append(style);
-            writer.append("\"");
-        }
-        String wid = image.getWidth(context);
-        if (UtilValidate.isNotEmpty(wid)) {
-            writer.append(" width=\"");
-            writer.append(wid);
-            writer.append("\"");
-        }
-        String hgt = image.getHeight(context);
-        if (UtilValidate.isNotEmpty(hgt)) {
-            writer.append(" height=\"");
-            writer.append(hgt);
-            writer.append("\"");
-        }
-        String border = image.getBorder(context);
-        if (UtilValidate.isNotEmpty(border)) {
-            writer.append(" border=\"");
-            writer.append(border);
-            writer.append("\"");
-        }
-        String src = image.getSrc(context);
-        if (UtilValidate.isNotEmpty(src)) {
-            writer.append(" src=\"");
-            String urlMode = image.getUrlMode();
-            boolean fullPath = false;
-            boolean secure = false;
-            boolean encode = false;
-            HttpServletResponse response = (HttpServletResponse) context.get("response");
-            HttpServletRequest request = (HttpServletRequest) context.get("request");
-            if (urlMode != null && urlMode.equalsIgnoreCase("ofbiz")) {
-                if (request != null && response != null) {
-                    ServletContext ctx = (ServletContext) request.getAttribute("servletContext");
-                    RequestHandler rh = (RequestHandler) ctx.getAttribute("_REQUEST_HANDLER_");
-                    String urlString = rh.makeLink(request, response, src, fullPath, secure, encode);
-                    writer.append(urlString);
-                } else {
-                    writer.append(src);
-                }
-            } else  if (urlMode != null && urlMode.equalsIgnoreCase("content")) {
-                if (request != null && response != null) {
-                    StringBuilder newURL = new StringBuilder();
-                    ContentUrlTag.appendContentPrefix(request, newURL);
-                    newURL.append(src);
-                    writer.append(newURL.toString());
-                }
-            } else {
-                writer.append(src);
-            }
-
-            writer.append("\"");
-        }
-        writer.append("/>");
-    }
-}
+/*******************************************************************************

+ * 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.renderer.html;

+

+import java.io.IOException;

+import java.math.BigDecimal;

+import java.util.List;

+import java.util.Map;

+

+import javax.servlet.ServletContext;

+import javax.servlet.http.HttpServletRequest;

+import javax.servlet.http.HttpServletResponse;

+import javax.servlet.http.HttpSession;

+

+import org.ofbiz.base.util.StringUtil;

+import org.ofbiz.base.util.UtilCodec;

+import org.ofbiz.base.util.UtilMisc;

+import org.ofbiz.base.util.UtilValidate;

+import org.ofbiz.entity.Delegator;

+import org.ofbiz.entity.GenericValue;

+import org.ofbiz.webapp.control.RequestHandler;

+import org.ofbiz.webapp.taglib.ContentUrlTag;

+import org.ofbiz.widget.WidgetWorker;

+import org.ofbiz.widget.model.CommonWidgetModels.Image;

+import org.ofbiz.widget.model.ModelMenu;

+import org.ofbiz.widget.model.ModelMenuItem;

+import org.ofbiz.widget.model.ModelMenuItem.MenuLink;

+import org.ofbiz.widget.model.ModelWidget;

+import org.ofbiz.widget.renderer.MenuStringRenderer;

+

+/**

+ * Widget Library - HTML Menu Renderer implementation

+ */

+public class HtmlMenuRenderer extends HtmlWidgetRenderer implements MenuStringRenderer {

+

+    HttpServletRequest request;

+    HttpServletResponse response;

+    protected String userLoginIdAtPermGrant;

+    protected String permissionErrorMessage = "";

+

+    public static final String module = HtmlMenuRenderer.class.getName();

+

+    protected HtmlMenuRenderer() {}

+

+    public HtmlMenuRenderer(HttpServletRequest request, HttpServletResponse response) {

+        this.request = request;

+        this.response = response;

+    }

+

+    public void appendOfbizUrl(Appendable writer, String location) throws IOException {

+        ServletContext ctx = (ServletContext) request.getAttribute("servletContext");

+        if (ctx == null) {

+            //if (Debug.infoOn()) Debug.logInfo("in appendOfbizUrl, ctx is null(0): buffer=" + buffer.toString() + " location:" + location, "");

+            HttpSession session = request.getSession();

+            if (session != null) {

+                ctx = session.getServletContext();

+            } else {

+                //if (Debug.infoOn()) Debug.logInfo("in appendOfbizUrl, session is null(1)", "");

+            }

+            if (ctx == null) {

+                throw new RuntimeException("ctx is null. location:" + location);

+            }

+                //if (Debug.infoOn()) Debug.logInfo("in appendOfbizUrl, ctx is NOT null(2)", "");

+        }

+        Delegator delegator = (Delegator)request.getAttribute("delegator");

+        if (delegator == null) {

+                //if (Debug.infoOn()) Debug.logInfo("in appendOfbizUrl, delegator is null(5)", "");

+        }

+        RequestHandler rh = (RequestHandler) ctx.getAttribute("_REQUEST_HANDLER_");

+        // make and append the link

+        String s = rh.makeLink(this.request, this.response, location);

+        if (s.indexOf("null") >= 0) {

+            //if (Debug.infoOn()) Debug.logInfo("in appendOfbizUrl(3), url: " + s, "");

+        }

+        writer.append(s);

+    }

+

+    public void appendContentUrl(Appendable writer, String location) throws IOException {

+        ServletContext ctx = (ServletContext) this.request.getAttribute("servletContext");

+        if (ctx == null) {

+            //if (Debug.infoOn()) Debug.logInfo("in appendContentUrl, ctx is null(0): buffer=" + buffer.toString() + " location:" + location, "");

+            HttpSession session = request.getSession();

+            if (session != null) {

+                ctx = session.getServletContext();

+            } else {

+                //if (Debug.infoOn()) Debug.logInfo("in appendContentUrl, session is null(1)", "");

+            }

+            if (ctx == null) {

+                throw new RuntimeException("ctx is null. location:" + location);

+            }

+            //if (Debug.infoOn()) Debug.logInfo("in appendContentUrl, ctx is NOT null(2)", "");

+            this.request.setAttribute("servletContext", ctx);

+        }

+        Delegator delegator = (Delegator) request.getAttribute("delegator");

+        if (delegator == null) {

+                //if (Debug.infoOn()) Debug.logInfo("in appendContentUrl, delegator is null(6)", "");

+        }

+        StringBuilder buffer = new StringBuilder();

+        ContentUrlTag.appendContentPrefix(this.request, buffer);

+        writer.append(buffer.toString());

+        writer.append(location);

+    }

+

+    public void appendTooltip(Appendable writer, Map<String, Object> context, ModelMenuItem modelMenuItem) throws IOException {

+        // render the tooltip

+        String tooltip = modelMenuItem.getTooltip(context);

+        if (UtilValidate.isNotEmpty(tooltip)) {

+            writer.append("<span class=\"");

+            String tooltipStyle = modelMenuItem.getTooltipStyle();

+            if (UtilValidate.isNotEmpty(tooltipStyle)) {

+                writer.append(tooltipStyle);

+            } else {

+                writer.append("tooltip");

+            }

+            writer.append("\"");

+            writer.append(tooltip);

+            writer.append("</span>");

+        }

+    }

+

+    public void renderFormatSimpleWrapperRows(Appendable writer, Map<String, Object> context, Object menuObj) throws IOException {

+        List<ModelMenuItem> menuItemList = ((ModelMenu) menuObj).getMenuItemList();

+        for (ModelMenuItem currentMenuItem: menuItemList) {

+            renderMenuItem(writer, context, currentMenuItem);

+        }

+    }

+

+    public void renderMenuItem(Appendable writer, Map<String, Object> context, ModelMenuItem menuItem) throws IOException {

+

+        //Debug.logInfo("in renderMenuItem, menuItem:" + menuItem.getName() + " context:" + context ,"");

+        boolean hideThisItem = isHideIfSelected(menuItem, context);

+        //if (Debug.infoOn()) Debug.logInfo("in HtmlMenuRendererImage, hideThisItem:" + hideThisItem,"");

+        if (hideThisItem)

+            return;

+

+        String style = menuItem.getWidgetStyle();

+

+        if (menuItem.isSelected(context)) {

+            style = menuItem.getSelectedStyle();

+            if (UtilValidate.isEmpty(style)) {

+                style = "selected";

+            }

+        }

+

+        if (this.isDisableIfEmpty(menuItem, context)) {

+            style = menuItem.getDisabledTitleStyle();

+        }

+

+        writer.append("  <li");

+        String alignStyle = menuItem.getAlignStyle();

+        if (UtilValidate.isNotEmpty(style) || UtilValidate.isNotEmpty(alignStyle)) {

+            writer.append(" class=\"");

+            if (UtilValidate.isNotEmpty(style)) {

+                writer.append(style).append(" ");

+            }

+            if (UtilValidate.isNotEmpty(alignStyle)) {

+                writer.append(alignStyle);

+            }

+            writer.append("\"");

+        }

+        String toolTip = menuItem.getTooltip(context);

+        if (UtilValidate.isNotEmpty(toolTip)) {

+            writer.append(" title=\"").append(toolTip).append("\"");

+        }

+        writer.append(">");

+

+        MenuLink link = menuItem.getLink();

+        //if (Debug.infoOn()) Debug.logInfo("in HtmlMenuRendererImage, link(0):" + link,"");

+        if (link != null) {

+            renderLink(writer, context, link);

+        } else {

+            String txt = menuItem.getTitle(context);

+            UtilCodec.SimpleEncoder simpleEncoder = (UtilCodec.SimpleEncoder) context.get("simpleEncoder");

+            if (simpleEncoder != null) {

+                txt = simpleEncoder.encode(txt);

+            }

+            writer.append(txt);

+

+        }

+        if (!menuItem.getMenuItemList().isEmpty()) {

+            appendWhitespace(writer);

+            writer.append("    <ul>");

+            appendWhitespace(writer);

+            for (ModelMenuItem childMenuItem : menuItem.getMenuItemList()) {

+                childMenuItem.renderMenuItemString(writer, context, this);

+            }

+            writer.append("    </ul>");

+            appendWhitespace(writer);

+        }

+

+        writer.append("</li>");

+

+        appendWhitespace(writer);

+    }

+

+    public boolean isDisableIfEmpty(ModelMenuItem menuItem, Map<String, Object> context) {

+        boolean disabled = false;

+        String disableIfEmpty = menuItem.getDisableIfEmpty();

+        if (UtilValidate.isNotEmpty(disableIfEmpty)) {

+            List<String> keys = StringUtil.split(disableIfEmpty, "|");

+            for (String key: keys) {

+                Object obj = context.get(key);

+                if (obj == null) {

+                    disabled = true;

+                    break;

+                }

+            }

+        }

+        return disabled;

+    }

+

+/*

+    public String buildDivStr(ModelMenuItem menuItem, Map<String, Object> context) {

+        String divStr = "";

+        divStr =  menuItem.getTitle(context);

+        return divStr;

+    }

+*/

+    public void renderMenuOpen(Appendable writer, Map<String, Object> context, ModelMenu modelMenu) throws IOException {

+

+            //Debug.logInfo("in HtmlMenuRenderer, userLoginIdHasChanged:" + userLoginIdHasChanged,"");

+        this.widgetCommentsEnabled = ModelWidget.widgetBoundaryCommentsEnabled(context);

+        renderBeginningBoundaryComment(writer, "Menu Widget", modelMenu);

+        writer.append("<div");

+        String menuId = modelMenu.getId();

+        if (UtilValidate.isNotEmpty(menuId)) {

+            writer.append(" id=\"").append(menuId).append("\"");

+        } else {

+            // TODO: Remove else after UI refactor - allow both id and style

+            String menuContainerStyle = modelMenu.getMenuContainerStyle(context);

+            if (UtilValidate.isNotEmpty(menuContainerStyle)) {

+                writer.append(" class=\"").append(menuContainerStyle).append("\"");

+            }

+        }

+        String menuWidth = modelMenu.getMenuWidth();

+        // TODO: Eliminate embedded styling after refactor

+        if (UtilValidate.isNotEmpty(menuWidth)) {

+            writer.append(" style=\"width:").append(menuWidth).append(";\"");

+        }

+        writer.append(">");

+        appendWhitespace(writer);

+        String menuTitle = modelMenu.getTitle(context);

+        if (UtilValidate.isNotEmpty(menuTitle)) {

+            writer.append("<h2>").append(menuTitle).append("</h2>");

+            appendWhitespace(writer);

+        }

+        if (modelMenu.renderedMenuItemCount(context) > 0) {

+            writer.append("<ul>");

+            appendWhitespace(writer);

+            writer.append("<li>");

+            appendWhitespace(writer);

+            writer.append(" <ul>");

+            appendWhitespace(writer);

+        }

+    }

+

+    /* (non-Javadoc)

+     * @see org.ofbiz.widget.menu.MenuStringRenderer#renderMenuClose(java.io.Writer, java.util.Map, org.ofbiz.widget.menu.ModelMenu)

+     */

+    public void renderMenuClose(Appendable writer, Map<String, Object> context, ModelMenu modelMenu) throws IOException {

+        // TODO: div can't be directly inside an UL

+        String fillStyle = modelMenu.getFillStyle();

+        if (UtilValidate.isNotEmpty(fillStyle)) {

+            writer.append("<div class=\"").append(fillStyle).append("\">&nbsp;</div>");

+        }

+        //String menuContainerStyle = modelMenu.getMenuContainerStyle(context);

+        if (modelMenu.renderedMenuItemCount(context) > 0) {      

+            writer.append(" </ul>");

+            appendWhitespace(writer);

+            writer.append("</li>");

+            appendWhitespace(writer);

+            writer.append("</ul>");

+            appendWhitespace(writer);

+        }

+        writer.append(" <br class=\"clear\"/>");

+        appendWhitespace(writer);

+        writer.append("</div>");

+        appendWhitespace(writer);

+        renderEndingBoundaryComment(writer, "Menu Widget", modelMenu);

+

+        GenericValue userLogin = (GenericValue)request.getSession().getAttribute("userLogin");

+        if (userLogin != null) {

+            String userLoginId = userLogin.getString("userLoginId");

+            //request.getSession().setAttribute("userLoginIdAtPermGrant", userLoginId);

+            setUserLoginIdAtPermGrant(userLoginId);

+            //Debug.logInfo("in HtmlMenuRenderer, userLoginId(Close):" + userLoginId + " userLoginIdAtPermGrant:" + request.getSession().getAttribute("userLoginIdAtPermGrant"),"");

+        } else {

+            request.getSession().setAttribute("userLoginIdAtPermGrant", null);

+        }

+    }

+

+    public void renderFormatSimpleWrapperOpen(Appendable writer, Map<String, Object> context, ModelMenu modelMenu) throws IOException {

+        //appendWhitespace(writer);

+    }

+

+    public void renderFormatSimpleWrapperClose(Appendable writer, Map<String, Object> context, ModelMenu modelMenu) throws IOException {

+        //appendWhitespace(writer);

+    }

+

+    public void setRequest(HttpServletRequest request) {

+        this.request = request;

+    }

+

+    public void setResponse(HttpServletResponse response) {

+        this.response = response;

+    }

+

+

+    /**

+     * @param string

+     */

+    public void setUserLoginIdAtPermGrant(String string) {

+            //Debug.logInfo("in HtmlMenuRenderer,  userLoginIdAtPermGrant(setUserLoginIdAtPermGrant):" + string,"");

+        this.userLoginIdAtPermGrant = string;

+    }

+

+    public String getUserLoginIdAtPermGrant() {

+        return this.userLoginIdAtPermGrant;

+    }

+

+    public boolean isHideIfSelected(ModelMenuItem menuItem, Map<String, Object> context) {

+        ModelMenu menu = menuItem.getModelMenu();

+        String currentMenuItemName = menu.getSelectedMenuItemContextFieldName(context);

+        String currentItemName = menuItem.getName();

+        Boolean hideIfSelected = menuItem.getHideIfSelected();

+            //Debug.logInfo("in HtmlMenuRenderer, currentMenuItemName:" + currentMenuItemName + " currentItemName:" + currentItemName + " hideIfSelected:" + hideIfSelected,"");

+        return (hideIfSelected != null && hideIfSelected.booleanValue() && currentMenuItemName != null && currentMenuItemName.equals(currentItemName));

+    }

+

+

+    public boolean userLoginIdHasChanged() {

+        boolean hasChanged = false;

+        GenericValue userLogin = (GenericValue)request.getSession().getAttribute("userLogin");

+        userLoginIdAtPermGrant = getUserLoginIdAtPermGrant();

+        //userLoginIdAtPermGrant = (String)request.getSession().getAttribute("userLoginIdAtPermGrant");

+        String userLoginId = null;

+        if (userLogin != null)

+            userLoginId = userLogin.getString("userLoginId");

+            //Debug.logInfo("in HtmlMenuRenderer, userLoginId:" + userLoginId + " userLoginIdAtPermGrant:" + userLoginIdAtPermGrant ,"");

+        if ((userLoginId == null && userLoginIdAtPermGrant != null)

+           || (userLoginId != null && userLoginIdAtPermGrant == null)

+           || ((userLoginId != null && userLoginIdAtPermGrant != null)

+              && !userLoginId.equals(userLoginIdAtPermGrant))) {

+            hasChanged = true;

+        } else {

+            if (userLoginIdAtPermGrant != null)

+               hasChanged = true;

+            else

+               hasChanged = false;

+

+            userLoginIdAtPermGrant = null;

+        }

+        return hasChanged;

+    }

+

+    public String getTitle(ModelMenuItem menuItem, Map<String, Object> context) {

+        String title = null;

+        title = menuItem.getTitle(context);

+        return title;

+    }

+

+    public void renderLink(Appendable writer, Map<String, Object> context, ModelMenuItem.MenuLink link) throws IOException {

+        String target = link.getTarget(context);

+        ModelMenuItem menuItem = link.getLinkMenuItem();

+        if (isDisableIfEmpty(menuItem, context)) {

+            target = null;

+        }

+

+        if (UtilValidate.isNotEmpty(target)) {

+            HttpServletResponse response = (HttpServletResponse) context.get("response");

+            HttpServletRequest request = (HttpServletRequest) context.get("request");

+

+            String targetWindow = link.getTargetWindow(context);

+            String uniqueItemName = menuItem.getModelMenu().getName() + "_" + menuItem.getName() + "_LF_" + UtilMisc.<String>addToBigDecimalInMap(context, "menuUniqueItemIndex", BigDecimal.ONE);

+

+            String linkType = WidgetWorker.determineAutoLinkType(link.getLinkType(), target, link.getUrlMode(), request);

+            if ("hidden-form".equals(linkType)) {

+                writer.append("<form method=\"post\"");

+                writer.append(" action=\"");

+                // note that this passes null for the parameterList on purpose so they won't be put into the URL

+                WidgetWorker.buildHyperlinkUrl(writer, target, link.getUrlMode(), null, link.getPrefix(context),

+                        link.getFullPath(), link.getSecure(), link.getEncode(), request, response, context);

+                writer.append("\"");

+

+                if (UtilValidate.isNotEmpty(targetWindow)) {

+                    writer.append(" target=\"");

+                    writer.append(targetWindow);

+                    writer.append("\"");

+                }

+

+                writer.append(" name=\"");

+                writer.append(uniqueItemName);

+                writer.append("\">");

+

+                UtilCodec.SimpleEncoder simpleEncoder = (UtilCodec.SimpleEncoder) context.get("simpleEncoder");

+                for (Map.Entry<String, String> parameter: link.getParameterMap(context).entrySet()) {

+                    writer.append("<input name=\"");

+                    writer.append(parameter.getKey());

+                    writer.append("\" value=\"");

+                    if (simpleEncoder != null) {

+                        writer.append(simpleEncoder.encode(parameter.getValue()));

+                    } else {

+                        writer.append(parameter.getValue());

+                    }

+                    writer.append("\" type=\"hidden\"/>");

+                }

+

+                writer.append("</form>");

+            }

+

+            writer.append("<a");

+            String id = link.getId(context);

+            if (UtilValidate.isNotEmpty(id)) {

+                writer.append(" id=\"");

+                writer.append(id);

+                writer.append("\"");

+            }

+

+            String style = link.getStyle(context);

+            if (UtilValidate.isNotEmpty(style)) {

+                writer.append(" class=\"");

+                writer.append(style);

+                writer.append("\"");

+            }

+            String name = link.getName(context);

+            if (UtilValidate.isNotEmpty(name)) {

+                writer.append(" name=\"");

+                writer.append(name);

+                writer.append("\"");

+            }

+            if (!"hidden-form".equals(linkType)) {

+                if (UtilValidate.isNotEmpty(targetWindow)) {

+                    writer.append(" target=\"");

+                    writer.append(targetWindow);

+                    writer.append("\"");

+                }

+            }

+

+            writer.append(" href=\"");

+            String confirmationMsg = null;

+            if ("hidden-form".equals(linkType)) {

+                if (UtilValidate.isNotEmpty(confirmationMsg)) {

+                    writer.append("javascript:confirmActionFormLink('");

+                    writer.append(confirmationMsg);

+                    writer.append("', '");

+                    writer.append(uniqueItemName);

+                    writer.append("')");

+                } else {

+                    writer.append("javascript:document.");

+                    writer.append(uniqueItemName);

+                    writer.append(".submit()");

+                }

+            } else {

+                if (UtilValidate.isNotEmpty(confirmationMsg)) {

+                    writer.append("javascript:confirmActionLink('");

+                    writer.append(confirmationMsg);

+                    writer.append("', '");

+                    WidgetWorker.buildHyperlinkUrl(writer, target, link.getUrlMode(), link.getParameterMap(context), link.getPrefix(context),

+                            link.getFullPath(), link.getSecure(), link.getEncode(), request, response, context);

+                    writer.append("')");

+                } else {

+                WidgetWorker.buildHyperlinkUrl(writer, target, link.getUrlMode(), link.getParameterMap(context), link.getPrefix(context),

+                        link.getFullPath(), link.getSecure(), link.getEncode(), request, response, context);

+                }

+            }

+            writer.append("\">");

+        }

+

+        // the text

+        Image img = link.getImage();

+        if (img != null) {

+            renderImage(writer, context, img);

+            writer.append("&nbsp;" + link.getText(context));

+        } else {

+            writer.append(link.getText(context));

+        }

+

+        if (UtilValidate.isNotEmpty(target)) {

+            // close tag

+            writer.append("</a>");

+        }

+

+        /* NOTE DEJ20090316: This was here as a comment and not sure what it is for or if it is useful... can probably be safely removed in the future if still not used/needed

+        boolean isSelected = menuItem.isSelected(context);

+

+        String style = null;

+

+        if (isSelected) {

+        style = menuItem.getSelectedStyle();

+        } else {

+        style = link.getStyle(context);

+        if (UtilValidate.isEmpty(style))

+        style = menuItem.getTitleStyle();

+        if (UtilValidate.isEmpty(style))

+        style = menuItem.getWidgetStyle();

+        }

+

+        if (menuItem.getDisabled()) {

+        style = menuItem.getDisabledTitleStyle();

+        }

+

+        if (UtilValidate.isNotEmpty(style)) {

+        writer.append(" class=\"");

+        writer.append(style);

+        writer.append("\"");

+        }

+        */

+    }

+

+    public void renderImage(Appendable writer, Map<String, Object> context, Image image) throws IOException {

+        // open tag

+        writer.append("<img ");

+        String id = image.getId(context);

+        if (UtilValidate.isNotEmpty(id)) {

+            writer.append(" id=\"");

+            writer.append(id);

+            writer.append("\"");

+        }

+        String style = image.getStyle(context);

+        if (UtilValidate.isNotEmpty(style)) {

+            writer.append(" class=\"");

+            writer.append(style);

+            writer.append("\"");

+        }

+        String wid = image.getWidth(context);

+        if (UtilValidate.isNotEmpty(wid)) {

+            writer.append(" width=\"");

+            writer.append(wid);

+            writer.append("\"");

+        }

+        String hgt = image.getHeight(context);

+        if (UtilValidate.isNotEmpty(hgt)) {

+            writer.append(" height=\"");

+            writer.append(hgt);

+            writer.append("\"");

+        }

+        String border = image.getBorder(context);

+        if (UtilValidate.isNotEmpty(border)) {

+            writer.append(" border=\"");

+            writer.append(border);

+            writer.append("\"");

+        }

+        String src = image.getSrc(context);

+        if (UtilValidate.isNotEmpty(src)) {

+            writer.append(" src=\"");

+            String urlMode = image.getUrlMode();

+            boolean fullPath = false;

+            boolean secure = false;

+            boolean encode = false;

+            HttpServletResponse response = (HttpServletResponse) context.get("response");

+            HttpServletRequest request = (HttpServletRequest) context.get("request");

+            if (urlMode != null && urlMode.equalsIgnoreCase("ofbiz")) {

+                if (request != null && response != null) {

+                    ServletContext ctx = (ServletContext) request.getAttribute("servletContext");

+                    RequestHandler rh = (RequestHandler) ctx.getAttribute("_REQUEST_HANDLER_");

+                    String urlString = rh.makeLink(request, response, src, fullPath, secure, encode);

+                    writer.append(urlString);

+                } else {

+                    writer.append(src);

+                }

+            } else  if (urlMode != null && urlMode.equalsIgnoreCase("content")) {

+                if (request != null && response != null) {

+                    StringBuilder newURL = new StringBuilder();

+                    ContentUrlTag.appendContentPrefix(request, newURL);

+                    newURL.append(src);

+                    writer.append(newURL.toString());

+                }

+            } else {

+                writer.append(src);

+            }

+

+            writer.append("\"");

+        }

+        writer.append("/>");

+    }

+}

diff --git a/framework/widget/src/org/ofbiz/widget/html/HtmlMenuRendererImage.java b/framework/widget/src/org/ofbiz/widget/renderer/html/HtmlMenuRendererImage.java
similarity index 95%
rename from framework/widget/src/org/ofbiz/widget/html/HtmlMenuRendererImage.java
rename to framework/widget/src/org/ofbiz/widget/renderer/html/HtmlMenuRendererImage.java
index e521b90..d0a51c6 100644
--- a/framework/widget/src/org/ofbiz/widget/html/HtmlMenuRendererImage.java
+++ b/framework/widget/src/org/ofbiz/widget/renderer/html/HtmlMenuRendererImage.java
@@ -1,80 +1,80 @@
-/*******************************************************************************
- * 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.html;
-
-import java.io.IOException;
-import java.io.StringWriter;
-import java.util.Map;
-
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.ofbiz.base.util.Debug;
-import org.ofbiz.base.util.UtilValidate;
-import org.ofbiz.entity.Delegator;
-import org.ofbiz.entity.GenericEntityException;
-import org.ofbiz.entity.GenericValue;
-import org.ofbiz.widget.WidgetContentWorker;
-import org.ofbiz.widget.menu.ModelMenuItem;
-
-/**
- * Widget Library - HTML Menu Renderer implementation
- */
-
-public class HtmlMenuRendererImage extends HtmlMenuRenderer {
-
-    protected HtmlMenuRendererImage() {}
-
-    public HtmlMenuRendererImage(HttpServletRequest request, HttpServletResponse response) {
-        super(request, response);
-    }
-
-
-    public String buildDivStr(ModelMenuItem menuItem, Map<String, Object> context) throws IOException {
-
-        StringBuilder imgStr = new StringBuilder("<img src=\"");
-        String contentId = menuItem.getAssociatedContentId(context);
-        Delegator delegator = (Delegator)request.getAttribute("delegator");
-        GenericValue webSitePublishPoint = null;
-                //Debug.logInfo("in HtmlMenuRendererImage, contentId:" + contentId,"");
-        try {
-            if (WidgetContentWorker.contentWorker != null) {
-                webSitePublishPoint = WidgetContentWorker.contentWorker.getWebSitePublishPointExt(delegator, contentId, false);
-            } else {
-                Debug.logError("Not rendering image because can't get WebSitePublishPoint, not ContentWorker found.", module);
-            }
-        } catch (GenericEntityException e) {
-                //Debug.logInfo("in HtmlMenuRendererImage, GEException:" + e.getMessage(),"");
-            throw new RuntimeException(e.getMessage());
-        }
-        String medallionLogoStr = webSitePublishPoint.getString("medallionLogo");
-        StringWriter buf = new StringWriter();
-        appendContentUrl(buf, medallionLogoStr);
-        imgStr.append(buf.toString());
-                //Debug.logInfo("in HtmlMenuRendererImage, imgStr:" + imgStr,"");
-        String cellWidth = menuItem.getCellWidth();
-        imgStr.append("\"");
-        if (UtilValidate.isNotEmpty(cellWidth))
-            imgStr.append(" width=\"").append(cellWidth).append("\" ");
-
-        imgStr.append(" border=\"0\" />");
-        return imgStr.toString();
-    }
-
-}
+/*******************************************************************************

+ * 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.renderer.html;

+

+import java.io.IOException;

+import java.io.StringWriter;

+import java.util.Map;

+

+import javax.servlet.http.HttpServletRequest;

+import javax.servlet.http.HttpServletResponse;

+

+import org.ofbiz.base.util.Debug;

+import org.ofbiz.base.util.UtilValidate;

+import org.ofbiz.entity.Delegator;

+import org.ofbiz.entity.GenericEntityException;

+import org.ofbiz.entity.GenericValue;

+import org.ofbiz.widget.content.WidgetContentWorker;

+import org.ofbiz.widget.model.ModelMenuItem;

+

+/**

+ * Widget Library - HTML Menu Renderer implementation

+ */

+

+public class HtmlMenuRendererImage extends HtmlMenuRenderer {

+

+    protected HtmlMenuRendererImage() {}

+

+    public HtmlMenuRendererImage(HttpServletRequest request, HttpServletResponse response) {

+        super(request, response);

+    }

+

+

+    public String buildDivStr(ModelMenuItem menuItem, Map<String, Object> context) throws IOException {

+

+        StringBuilder imgStr = new StringBuilder("<img src=\"");

+        String contentId = menuItem.getAssociatedContentId(context);

+        Delegator delegator = (Delegator)request.getAttribute("delegator");

+        GenericValue webSitePublishPoint = null;

+                //Debug.logInfo("in HtmlMenuRendererImage, contentId:" + contentId,"");

+        try {

+            if (WidgetContentWorker.contentWorker != null) {

+                webSitePublishPoint = WidgetContentWorker.contentWorker.getWebSitePublishPointExt(delegator, contentId, false);

+            } else {

+                Debug.logError("Not rendering image because can't get WebSitePublishPoint, not ContentWorker found.", module);

+            }

+        } catch (GenericEntityException e) {

+                //Debug.logInfo("in HtmlMenuRendererImage, GEException:" + e.getMessage(),"");

+            throw new RuntimeException(e.getMessage());

+        }

+        String medallionLogoStr = webSitePublishPoint.getString("medallionLogo");

+        StringWriter buf = new StringWriter();

+        appendContentUrl(buf, medallionLogoStr);

+        imgStr.append(buf.toString());

+                //Debug.logInfo("in HtmlMenuRendererImage, imgStr:" + imgStr,"");

+        String cellWidth = menuItem.getCellWidth();

+        imgStr.append("\"");

+        if (UtilValidate.isNotEmpty(cellWidth))

+            imgStr.append(" width=\"").append(cellWidth).append("\" ");

+

+        imgStr.append(" border=\"0\" />");

+        return imgStr.toString();

+    }

+

+}

diff --git a/framework/widget/src/org/ofbiz/widget/html/HtmlMenuWrapper.java b/framework/widget/src/org/ofbiz/widget/renderer/html/HtmlMenuWrapper.java
similarity index 97%
rename from framework/widget/src/org/ofbiz/widget/html/HtmlMenuWrapper.java
rename to framework/widget/src/org/ofbiz/widget/renderer/html/HtmlMenuWrapper.java
index dcb5898..54cb8d5 100644
--- a/framework/widget/src/org/ofbiz/widget/html/HtmlMenuWrapper.java
+++ b/framework/widget/src/org/ofbiz/widget/renderer/html/HtmlMenuWrapper.java
@@ -1,252 +1,252 @@
-/*******************************************************************************
- * 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.html;
-
-import java.io.IOException;
-import java.io.StringWriter;
-import java.io.Writer;
-import java.util.HashMap;
-import java.util.Map;
-
-import javax.servlet.ServletContext;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import javax.servlet.http.HttpSession;
-import javax.xml.parsers.ParserConfigurationException;
-
-import org.ofbiz.base.util.Debug;
-import org.ofbiz.base.util.UtilGenerics;
-import org.ofbiz.base.util.UtilHttp;
-import org.ofbiz.base.util.UtilValidate;
-import org.ofbiz.entity.GenericValue;
-import org.ofbiz.widget.menu.MenuFactory;
-import org.ofbiz.widget.menu.MenuStringRenderer;
-import org.ofbiz.widget.menu.ModelMenu;
-import org.xml.sax.SAXException;
-
-
-/**
- * Widget Library - HTML Menu Wrapper class - makes it easy to do the setup and render of a menu
- */
-public class HtmlMenuWrapper {
-
-    public static final String module = HtmlMenuWrapper.class.getName();
-
-    protected String resourceName;
-    protected String menuName;
-    protected HttpServletRequest request;
-    protected HttpServletResponse response;
-    protected ModelMenu modelMenu;
-    protected MenuStringRenderer renderer;
-    protected Map<String, Object> context;
-
-    protected HtmlMenuWrapper() {}
-
-    public HtmlMenuWrapper(String resourceName, String menuName, HttpServletRequest request, HttpServletResponse response)
-            throws IOException, SAXException, ParserConfigurationException {
-        init(resourceName, menuName, request, response);
-    }
-
-    public void init(String resourceName, String menuName, HttpServletRequest request, HttpServletResponse response)
-            throws IOException, SAXException, ParserConfigurationException {
-        this.resourceName = resourceName;
-        this.menuName = menuName;
-        this.request = request;
-        this.response = response;
-
-        this.modelMenu = MenuFactory.getMenuFromWebappContext(resourceName, menuName, request);
-
-        this.renderer = getMenuRenderer();
-
-        this.context = new HashMap<String, Object>();
-        Map<String, Object> parameterMap = UtilHttp.getParameterMap(request);
-        context.put("parameters", parameterMap);
-
-        HttpSession session = request.getSession();
-        GenericValue userLogin = (GenericValue)session.getAttribute("userLogin");
-        context.put("userLogin", userLogin);
-
-        //make sure the locale is in the context
-        context.put("locale", UtilHttp.getLocale(request));
-
-        // if there was an error message, this is an error
-        if (UtilValidate.isNotEmpty(request.getAttribute("_ERROR_MESSAGE_"))) {
-            context.put("isError", Boolean.TRUE);
-        } else {
-            context.put("isError", Boolean.FALSE);
-        }
-
-        // if a parameter was passed saying this is an error, it is an error
-        if ("true".equals(parameterMap.get("isError"))) {
-            context.put("isError", Boolean.TRUE);
-        }
-    }
-
-    public MenuStringRenderer getMenuRenderer() {
-        return new HtmlMenuRenderer(request, response);
-    }
-
-    public String renderMenuString() throws IOException {
-        HttpServletRequest req = ((HtmlMenuRenderer)renderer).request;
-        ServletContext ctx = (ServletContext) req.getAttribute("servletContext");
-        if (ctx == null) {
-            if (Debug.infoOn()) Debug.logInfo("in renderMenuString, ctx is null(0)" , "");
-        }
-
-        Writer writer = new StringWriter();
-        modelMenu.renderMenuString(writer, context, renderer);
-
-        HttpServletRequest req2 = ((HtmlMenuRenderer)renderer).request;
-        ServletContext ctx2 = (ServletContext) req2.getAttribute("servletContext");
-        if (ctx2 == null) {
-            if (Debug.infoOn()) Debug.logInfo("in renderMenuString, ctx is null(2)" , "");
-        }
-
-        return writer.toString();
-    }
-
-    /**
-     * Tells the menu library whether this is a response to an error or not.
-     * Defaults on initialization according to the presense of an errorMessage
-     * in the request or if an isError parameter was passed to the page with
-     * the value "true". If true then the prefilled values will come from the
-     * parameters Map instead of the value Map.
-     */
-    public void setIsError(boolean isError) {
-        this.context.put("isError", Boolean.valueOf(isError));
-    }
-
-    public boolean getIsError() {
-        Boolean isErrorBoolean = (Boolean) this.context.get("isError");
-        if (isErrorBoolean == null) {
-            return false;
-        } else {
-            return isErrorBoolean.booleanValue();
-        }
-    }
-
-    public void setMenuOverrideName(String menuName) {
-        this.context.put("menuName", menuName);
-    }
-
-    public void putInContext(String name, Object value) {
-        this.context.put(name, value);
-    }
-
-    public void putInContext(String menuItemName, String valueName,  Object value) {
-        Map<String, Object> valueMap = UtilGenerics.toMap(context.get(menuItemName));
-        if (valueMap == null) {
-            valueMap = new HashMap<String, Object>();
-            context.put(menuItemName, valueMap);
-        }
-        valueMap.put(valueName, value);
-    }
-
-    public Object getFromContext(String name) {
-        return this.context.get(name);
-    }
-
-    public Object getFromContext(String menuItemName, String valueName) {
-        Map<String, Object> valueMap = UtilGenerics.toMap(context.get(menuItemName));
-        if (valueMap == null) {
-            valueMap = new HashMap<String, Object>();
-            context.put(menuItemName, valueMap);
-        }
-        return valueMap.get(valueName);
-    }
-
-    public ModelMenu getModelMenu() {
-        return modelMenu;
-    }
-
-    public MenuStringRenderer getRenderer() {
-        return renderer;
-    }
-
-    public void setRenderer(MenuStringRenderer renderer) {
-        this.renderer = renderer;
-    }
-
-    public void setRequest(HttpServletRequest request) {
-        this.request = request;
-        ((HtmlMenuRenderer)renderer).setRequest(request);
-    }
-
-    public void setResponse(HttpServletResponse response) {
-        this.response = response;
-        ((HtmlMenuRenderer)renderer).setResponse(response);
-    }
-
-    public HttpServletRequest getRequest() {
-        return ((HtmlMenuRenderer)renderer).request;
-    }
-
-    public HttpServletResponse getResponse() {
-        return ((HtmlMenuRenderer)renderer).response;
-    }
-
-    public static HtmlMenuWrapper getMenuWrapper(HttpServletRequest request, HttpServletResponse response, HttpSession session, String menuDefFile, String menuName, String menuWrapperClassName) {
-
-        HtmlMenuWrapper menuWrapper = null;
-
-        String menuSig = menuDefFile + "__" + menuName;
-        if (session != null) {
-             menuWrapper = (HtmlMenuWrapper)session.getAttribute(menuSig);
-        }
-
-        if (menuWrapper == null) {
-            try {
-                Class<?> cls = Class.forName("org.ofbiz.widget.html." + menuWrapperClassName);
-                menuWrapper = (HtmlMenuWrapper)cls.newInstance();
-                menuWrapper.init(menuDefFile, menuName, request, response);
-            } catch (InstantiationException e) {
-                throw new RuntimeException(e.getMessage());
-            } catch (IllegalAccessException e2) {
-                throw new RuntimeException(e2.getMessage());
-            } catch (ClassNotFoundException e3) {
-                throw new RuntimeException("Class not found:" + e3.getMessage());
-            } catch (IOException e4) {
-                throw new RuntimeException(e4.getMessage());
-            } catch (SAXException e5) {
-                throw new RuntimeException(e5.getMessage());
-            } catch (ParserConfigurationException e6) {
-                throw new RuntimeException(e6.getMessage());
-            }
-        } else {
-            menuWrapper.setRequest(request);
-            menuWrapper.setResponse(response);
-            Map<String, Object> parameterMap = UtilHttp.getParameterMap(request);
-            menuWrapper.setParameters(parameterMap);
-
-            GenericValue userLogin = (GenericValue)session.getAttribute("userLogin");
-            menuWrapper.putInContext("userLogin", userLogin);
-
-        }
-
-        if (session != null) {
-            session.setAttribute(menuSig, menuWrapper);
-        }
-        return menuWrapper;
-    }
-
-    public void setParameters(Map<String, Object> paramMap) {
-        context.put("parameters", paramMap);
-    }
-
-}
+/*******************************************************************************

+ * 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.renderer.html;

+

+import java.io.IOException;

+import java.io.StringWriter;

+import java.io.Writer;

+import java.util.HashMap;

+import java.util.Map;

+

+import javax.servlet.ServletContext;

+import javax.servlet.http.HttpServletRequest;

+import javax.servlet.http.HttpServletResponse;

+import javax.servlet.http.HttpSession;

+import javax.xml.parsers.ParserConfigurationException;

+

+import org.ofbiz.base.util.Debug;

+import org.ofbiz.base.util.UtilGenerics;

+import org.ofbiz.base.util.UtilHttp;

+import org.ofbiz.base.util.UtilValidate;

+import org.ofbiz.entity.GenericValue;

+import org.ofbiz.widget.model.MenuFactory;

+import org.ofbiz.widget.model.ModelMenu;

+import org.ofbiz.widget.renderer.MenuStringRenderer;

+import org.xml.sax.SAXException;

+

+

+/**

+ * Widget Library - HTML Menu Wrapper class - makes it easy to do the setup and render of a menu

+ */

+public class HtmlMenuWrapper {

+

+    public static final String module = HtmlMenuWrapper.class.getName();

+

+    protected String resourceName;

+    protected String menuName;

+    protected HttpServletRequest request;

+    protected HttpServletResponse response;

+    protected ModelMenu modelMenu;

+    protected MenuStringRenderer renderer;

+    protected Map<String, Object> context;

+

+    protected HtmlMenuWrapper() {}

+

+    public HtmlMenuWrapper(String resourceName, String menuName, HttpServletRequest request, HttpServletResponse response)

+            throws IOException, SAXException, ParserConfigurationException {

+        init(resourceName, menuName, request, response);

+    }

+

+    public void init(String resourceName, String menuName, HttpServletRequest request, HttpServletResponse response)

+            throws IOException, SAXException, ParserConfigurationException {

+        this.resourceName = resourceName;

+        this.menuName = menuName;

+        this.request = request;

+        this.response = response;

+

+        this.modelMenu = MenuFactory.getMenuFromWebappContext(resourceName, menuName, request);

+

+        this.renderer = getMenuRenderer();

+

+        this.context = new HashMap<String, Object>();

+        Map<String, Object> parameterMap = UtilHttp.getParameterMap(request);

+        context.put("parameters", parameterMap);

+

+        HttpSession session = request.getSession();

+        GenericValue userLogin = (GenericValue)session.getAttribute("userLogin");

+        context.put("userLogin", userLogin);

+

+        //make sure the locale is in the context

+        context.put("locale", UtilHttp.getLocale(request));

+

+        // if there was an error message, this is an error

+        if (UtilValidate.isNotEmpty(request.getAttribute("_ERROR_MESSAGE_"))) {

+            context.put("isError", Boolean.TRUE);

+        } else {

+            context.put("isError", Boolean.FALSE);

+        }

+

+        // if a parameter was passed saying this is an error, it is an error

+        if ("true".equals(parameterMap.get("isError"))) {

+            context.put("isError", Boolean.TRUE);

+        }

+    }

+

+    public MenuStringRenderer getMenuRenderer() {

+        return new HtmlMenuRenderer(request, response);

+    }

+

+    public String renderMenuString() throws IOException {

+        HttpServletRequest req = ((HtmlMenuRenderer)renderer).request;

+        ServletContext ctx = (ServletContext) req.getAttribute("servletContext");

+        if (ctx == null) {

+            if (Debug.infoOn()) Debug.logInfo("in renderMenuString, ctx is null(0)" , "");

+        }

+

+        Writer writer = new StringWriter();

+        modelMenu.renderMenuString(writer, context, renderer);

+

+        HttpServletRequest req2 = ((HtmlMenuRenderer)renderer).request;

+        ServletContext ctx2 = (ServletContext) req2.getAttribute("servletContext");

+        if (ctx2 == null) {

+            if (Debug.infoOn()) Debug.logInfo("in renderMenuString, ctx is null(2)" , "");

+        }

+

+        return writer.toString();

+    }

+

+    /**

+     * Tells the menu library whether this is a response to an error or not.

+     * Defaults on initialization according to the presense of an errorMessage

+     * in the request or if an isError parameter was passed to the page with

+     * the value "true". If true then the prefilled values will come from the

+     * parameters Map instead of the value Map.

+     */

+    public void setIsError(boolean isError) {

+        this.context.put("isError", Boolean.valueOf(isError));

+    }

+

+    public boolean getIsError() {

+        Boolean isErrorBoolean = (Boolean) this.context.get("isError");

+        if (isErrorBoolean == null) {

+            return false;

+        } else {

+            return isErrorBoolean.booleanValue();

+        }

+    }

+

+    public void setMenuOverrideName(String menuName) {

+        this.context.put("menuName", menuName);

+    }

+

+    public void putInContext(String name, Object value) {

+        this.context.put(name, value);

+    }

+

+    public void putInContext(String menuItemName, String valueName,  Object value) {

+        Map<String, Object> valueMap = UtilGenerics.toMap(context.get(menuItemName));

+        if (valueMap == null) {

+            valueMap = new HashMap<String, Object>();

+            context.put(menuItemName, valueMap);

+        }

+        valueMap.put(valueName, value);

+    }

+

+    public Object getFromContext(String name) {

+        return this.context.get(name);

+    }

+

+    public Object getFromContext(String menuItemName, String valueName) {

+        Map<String, Object> valueMap = UtilGenerics.toMap(context.get(menuItemName));

+        if (valueMap == null) {

+            valueMap = new HashMap<String, Object>();

+            context.put(menuItemName, valueMap);

+        }

+        return valueMap.get(valueName);

+    }

+

+    public ModelMenu getModelMenu() {

+        return modelMenu;

+    }

+

+    public MenuStringRenderer getRenderer() {

+        return renderer;

+    }

+

+    public void setRenderer(MenuStringRenderer renderer) {

+        this.renderer = renderer;

+    }

+

+    public void setRequest(HttpServletRequest request) {

+        this.request = request;

+        ((HtmlMenuRenderer)renderer).setRequest(request);

+    }

+

+    public void setResponse(HttpServletResponse response) {

+        this.response = response;

+        ((HtmlMenuRenderer)renderer).setResponse(response);

+    }

+

+    public HttpServletRequest getRequest() {

+        return ((HtmlMenuRenderer)renderer).request;

+    }

+

+    public HttpServletResponse getResponse() {

+        return ((HtmlMenuRenderer)renderer).response;

+    }

+

+    public static HtmlMenuWrapper getMenuWrapper(HttpServletRequest request, HttpServletResponse response, HttpSession session, String menuDefFile, String menuName, String menuWrapperClassName) {

+

+        HtmlMenuWrapper menuWrapper = null;

+

+        String menuSig = menuDefFile + "__" + menuName;

+        if (session != null) {

+             menuWrapper = (HtmlMenuWrapper)session.getAttribute(menuSig);

+        }

+

+        if (menuWrapper == null) {

+            try {

+                Class<?> cls = Class.forName("org.ofbiz.widget.html." + menuWrapperClassName);

+                menuWrapper = (HtmlMenuWrapper)cls.newInstance();

+                menuWrapper.init(menuDefFile, menuName, request, response);

+            } catch (InstantiationException e) {

+                throw new RuntimeException(e.getMessage());

+            } catch (IllegalAccessException e2) {

+                throw new RuntimeException(e2.getMessage());

+            } catch (ClassNotFoundException e3) {

+                throw new RuntimeException("Class not found:" + e3.getMessage());

+            } catch (IOException e4) {

+                throw new RuntimeException(e4.getMessage());

+            } catch (SAXException e5) {

+                throw new RuntimeException(e5.getMessage());

+            } catch (ParserConfigurationException e6) {

+                throw new RuntimeException(e6.getMessage());

+            }

+        } else {

+            menuWrapper.setRequest(request);

+            menuWrapper.setResponse(response);

+            Map<String, Object> parameterMap = UtilHttp.getParameterMap(request);

+            menuWrapper.setParameters(parameterMap);

+

+            GenericValue userLogin = (GenericValue)session.getAttribute("userLogin");

+            menuWrapper.putInContext("userLogin", userLogin);

+

+        }

+

+        if (session != null) {

+            session.setAttribute(menuSig, menuWrapper);

+        }

+        return menuWrapper;

+    }

+

+    public void setParameters(Map<String, Object> paramMap) {

+        context.put("parameters", paramMap);

+    }

+

+}

diff --git a/framework/widget/src/org/ofbiz/widget/html/HtmlMenuWrapperImage.java b/framework/widget/src/org/ofbiz/widget/renderer/html/HtmlMenuWrapperImage.java
similarity index 95%
rename from framework/widget/src/org/ofbiz/widget/html/HtmlMenuWrapperImage.java
rename to framework/widget/src/org/ofbiz/widget/renderer/html/HtmlMenuWrapperImage.java
index 6346ef4..c41f2ac 100644
--- a/framework/widget/src/org/ofbiz/widget/html/HtmlMenuWrapperImage.java
+++ b/framework/widget/src/org/ofbiz/widget/renderer/html/HtmlMenuWrapperImage.java
@@ -1,81 +1,80 @@
-/*******************************************************************************
- * 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.html;
-
-import java.io.IOException;
-import java.util.HashMap;
-import java.util.Map;
-
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import javax.xml.parsers.ParserConfigurationException;
-
-import org.ofbiz.base.util.UtilMisc;
-import org.ofbiz.entity.Delegator;
-import org.ofbiz.entity.GenericEntityException;
-import org.ofbiz.entity.GenericValue;
-import org.ofbiz.entity.util.EntityQuery;
-import org.ofbiz.widget.menu.MenuStringRenderer;
-import org.ofbiz.widget.menu.ModelMenuItem;
-import org.xml.sax.SAXException;
-
-/**
- * Widget Library - HTML Menu Wrapper class - makes it easy to do the setup and render of a menu
- */
-public class HtmlMenuWrapperImage extends HtmlMenuWrapper {
-
-    public static final String module = HtmlMenuWrapperImage.class.getName();
-
-    protected HtmlMenuWrapperImage() {}
-
-    public HtmlMenuWrapperImage(String resourceName, String menuName, HttpServletRequest request, HttpServletResponse response)
-            throws IOException, SAXException, ParserConfigurationException {
-        super(resourceName, menuName, request, response);
-    }
-
-    @Override
-    public MenuStringRenderer getMenuRenderer() {
-        return new HtmlMenuRendererImage(request, response);
-    }
-
-    @Override
-    public void init(String resourceName, String menuName, HttpServletRequest request, HttpServletResponse response)
-            throws IOException, SAXException, ParserConfigurationException {
-
-        super.init(resourceName, menuName, request, response);
-        //String pubPt = (String)request.getAttribute("pubPt");
-        //if (Debug.infoOn()) Debug.logInfo("in init, pubPt:" + pubPt, module);
-        Map<String, Object> dummyMap = new HashMap<String, Object>();
-        Delegator delegator = (Delegator)request.getAttribute("delegator");
-        //if (Debug.infoOn()) Debug.logInfo("in init, delegator:" + delegator, module);
-        try {
-            for (ModelMenuItem menuItem : modelMenu.getMenuItemList()) {
-               String contentId = menuItem.getAssociatedContentId(dummyMap);
-               //if (Debug.infoOn()) Debug.logInfo("in init, contentId:" + contentId, module);
-               GenericValue webSitePublishPoint = EntityQuery.use(delegator).from("WebSitePublishPoint").where("contentId", contentId).cache().queryOne();
-               String menuItemName = menuItem.getName();
-               //if (Debug.infoOn()) Debug.logInfo("in init, menuItemName:" + menuItemName, module);
-               //if (Debug.infoOn()) Debug.logInfo("in init, webSitePublishPoint:" + webSitePublishPoint, module);
-               putInContext(menuItemName, "WebSitePublishPoint", webSitePublishPoint);
-            }
-        } catch (GenericEntityException e) {
-            return;
-        }
-    }
-}
+/*******************************************************************************

+ * 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.renderer.html;

+

+import java.io.IOException;

+import java.util.HashMap;

+import java.util.Map;

+

+import javax.servlet.http.HttpServletRequest;

+import javax.servlet.http.HttpServletResponse;

+import javax.xml.parsers.ParserConfigurationException;

+

+import org.ofbiz.entity.Delegator;

+import org.ofbiz.entity.GenericEntityException;

+import org.ofbiz.entity.GenericValue;

+import org.ofbiz.entity.util.EntityQuery;

+import org.ofbiz.widget.model.ModelMenuItem;

+import org.ofbiz.widget.renderer.MenuStringRenderer;

+import org.xml.sax.SAXException;

+

+/**

+ * Widget Library - HTML Menu Wrapper class - makes it easy to do the setup and render of a menu

+ */

+public class HtmlMenuWrapperImage extends HtmlMenuWrapper {

+

+    public static final String module = HtmlMenuWrapperImage.class.getName();

+

+    protected HtmlMenuWrapperImage() {}

+

+    public HtmlMenuWrapperImage(String resourceName, String menuName, HttpServletRequest request, HttpServletResponse response)

+            throws IOException, SAXException, ParserConfigurationException {

+        super(resourceName, menuName, request, response);

+    }

+

+    @Override

+    public MenuStringRenderer getMenuRenderer() {

+        return new HtmlMenuRendererImage(request, response);

+    }

+

+    @Override

+    public void init(String resourceName, String menuName, HttpServletRequest request, HttpServletResponse response)

+            throws IOException, SAXException, ParserConfigurationException {

+

+        super.init(resourceName, menuName, request, response);

+        //String pubPt = (String)request.getAttribute("pubPt");

+        //if (Debug.infoOn()) Debug.logInfo("in init, pubPt:" + pubPt, module);

+        Map<String, Object> dummyMap = new HashMap<String, Object>();

+        Delegator delegator = (Delegator)request.getAttribute("delegator");

+        //if (Debug.infoOn()) Debug.logInfo("in init, delegator:" + delegator, module);

+        try {

+            for (ModelMenuItem menuItem : modelMenu.getMenuItemList()) {

+               String contentId = menuItem.getAssociatedContentId(dummyMap);

+               //if (Debug.infoOn()) Debug.logInfo("in init, contentId:" + contentId, module);

+               GenericValue webSitePublishPoint = EntityQuery.use(delegator).from("WebSitePublishPoint").where("contentId", contentId).cache().queryOne();

+               String menuItemName = menuItem.getName();

+               //if (Debug.infoOn()) Debug.logInfo("in init, menuItemName:" + menuItemName, module);

+               //if (Debug.infoOn()) Debug.logInfo("in init, webSitePublishPoint:" + webSitePublishPoint, module);

+               putInContext(menuItemName, "WebSitePublishPoint", webSitePublishPoint);

+            }

+        } catch (GenericEntityException e) {

+            return;

+        }

+    }

+}

diff --git a/framework/widget/src/org/ofbiz/widget/html/HtmlScreenRenderer.java b/framework/widget/src/org/ofbiz/widget/renderer/html/HtmlScreenRenderer.java
similarity index 96%
rename from framework/widget/src/org/ofbiz/widget/html/HtmlScreenRenderer.java
rename to framework/widget/src/org/ofbiz/widget/renderer/html/HtmlScreenRenderer.java
index 90c05b1..04a81cb 100644
--- a/framework/widget/src/org/ofbiz/widget/html/HtmlScreenRenderer.java
+++ b/framework/widget/src/org/ofbiz/widget/renderer/html/HtmlScreenRenderer.java
@@ -1,932 +1,944 @@
-/*******************************************************************************
- * 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.html;
-
-import java.io.IOException;
-import java.math.BigDecimal;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Locale;
-import java.util.Map;
-
-import javax.servlet.ServletContext;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.ofbiz.base.util.Debug;
-import org.ofbiz.base.util.GeneralException;
-import org.ofbiz.base.util.UtilFormatOut;
-import org.ofbiz.base.util.UtilGenerics;
-import org.ofbiz.base.util.UtilHttp;
-import org.ofbiz.base.util.UtilMisc;
-import org.ofbiz.base.util.UtilValidate;
-import org.ofbiz.entity.Delegator;
-import org.ofbiz.entity.GenericValue;
-import org.ofbiz.service.LocalDispatcher;
-import org.ofbiz.webapp.control.RequestHandler;
-import org.ofbiz.webapp.taglib.ContentUrlTag;
-import org.ofbiz.widget.ModelWidget;
-import org.ofbiz.widget.WidgetContentWorker;
-import org.ofbiz.widget.WidgetDataResourceWorker;
-import org.ofbiz.widget.WidgetWorker;
-import org.ofbiz.widget.form.FormStringRenderer;
-import org.ofbiz.widget.form.ModelForm;
-import org.ofbiz.widget.form.Paginator;
-import org.ofbiz.widget.menu.MenuStringRenderer;
-import org.ofbiz.widget.menu.ModelMenu;
-import org.ofbiz.widget.screen.ModelScreenWidget;
-import org.ofbiz.widget.screen.ModelScreenWidget.*;
-import org.ofbiz.widget.screen.ScreenStringRenderer;
-
-/**
- * Widget Library - HTML Form Renderer implementation
- * @deprecated Use MacroScreenRenderer.
- */
-public class HtmlScreenRenderer extends HtmlWidgetRenderer implements ScreenStringRenderer {
-
-    public static final String module = HtmlScreenRenderer.class.getName();
-    protected int elementId = 999;
-
-    public HtmlScreenRenderer() {}
-
-    protected String getNextElementId() {
-        elementId++;
-        return "hsr" + elementId;
-    }
-
-    public String getRendererName() {
-        return "html";
-    }
-
-    public void renderScreenBegin(Appendable writer, Map<String, Object> context) throws IOException {
-        writer.append("<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">");
-        appendWhitespace(writer);
-    }
-
-    public void renderScreenEnd(Appendable writer, Map<String, Object> context) throws IOException {
-    }
-
-    public void renderSectionBegin(Appendable writer, Map<String, Object> context, Section section) throws IOException {
-        if (section.isMainSection()) {
-            this.widgetCommentsEnabled = ModelWidget.widgetBoundaryCommentsEnabled(context);
-        }
-        renderBeginningBoundaryComment(writer, section.isMainSection()?"Screen":"Section Widget", section);
-    }
-
-    public void renderSectionEnd(Appendable writer, Map<String, Object> context, Section section) throws IOException {
-        renderEndingBoundaryComment(writer, section.isMainSection()?"Screen":"Section Widget", section);
-    }
-
-    public void renderContainerBegin(Appendable writer, Map<String, Object> context, Container container) throws IOException {
-        String containerId = container.getId(context);
-        String autoUpdateTarget = container.getAutoUpdateTargetExdr(context);
-        HttpServletRequest request = (HttpServletRequest) context.get("request");
-        if (UtilValidate.isNotEmpty(autoUpdateTarget) && UtilHttp.isJavaScriptEnabled(request)) {
-            if (UtilValidate.isEmpty(containerId)) {
-                containerId = getNextElementId();
-            }
-            HttpServletResponse response = (HttpServletResponse) context.get("response");
-            ServletContext ctx = (ServletContext) request.getAttribute("servletContext");
-            RequestHandler rh = (RequestHandler) ctx.getAttribute("_REQUEST_HANDLER_");
-
-            writer.append("<script type=\"text/javascript\">ajaxUpdateAreaPeriodic('");
-            writer.append(containerId);
-            writer.append("', '");
-            writer.append(rh.makeLink(request, response, autoUpdateTarget));
-            writer.append("', '");
-            writer.append("', '").append(container.getAutoUpdateInterval(context)).append("');</script>");
-            appendWhitespace(writer);
-        }
-        writer.append("<div");
-
-        if (UtilValidate.isNotEmpty(containerId)) {
-            writer.append(" id=\"");
-            writer.append(containerId);
-            writer.append("\"");
-        }
-
-        String style = container.getStyle(context);
-        if (UtilValidate.isNotEmpty(style)) {
-            writer.append(" class=\"");
-            writer.append(style);
-            writer.append("\"");
-        }
-
-        writer.append(">");
-        appendWhitespace(writer);
-    }
-    public void renderContainerEnd(Appendable writer, Map<String, Object> context, Container container) throws IOException {
-        writer.append("</div>");
-        appendWhitespace(writer);
-    }
-
-    public void renderHorizontalSeparator(Appendable writer, Map<String, Object> context, HorizontalSeparator separator) throws IOException {
-        writer.append("<hr");
-        String className = separator.getStyle(context);
-        if (UtilValidate.isNotEmpty(className)) {
-            writer.append(" class=\"").append(className).append("\"");
-        }
-        String idName = separator.getId(context);
-        if (UtilValidate.isNotEmpty(idName)) {
-            writer.append(" id=\"").append(idName).append("\"");
-        }
-        writer.append("/>");
-        appendWhitespace(writer);
-    }
-
-    public void renderScreenletBegin(Appendable writer, Map<String, Object> context, boolean collapsed, Screenlet screenlet) throws IOException {
-        HttpServletRequest request = (HttpServletRequest) context.get("request");
-        HttpServletResponse response = (HttpServletResponse) context.get("response");
-        boolean javaScriptEnabled = UtilHttp.isJavaScriptEnabled(request);
-        Menu tabMenu = screenlet.getTabMenu();
-        if (tabMenu != null) {
-            tabMenu.renderWidgetString(writer, context, this);
-        }
-        writer.append("<div class=\"screenlet\"");
-        String id = screenlet.getId(context);
-        if (UtilValidate.isNotEmpty(id)) {
-            writer.append(" id=\"");
-            writer.append(id);
-            writer.append("\"");
-        }
-        writer.append(">");
-        appendWhitespace(writer);
-
-        String title = screenlet.getTitle(context);
-        Menu navMenu = screenlet.getNavigationMenu();
-        Form navForm = screenlet.getNavigationForm();
-        String collapsibleAreaId = null;
-        if (UtilValidate.isNotEmpty(title) || navMenu != null || navForm != null || screenlet.collapsible()) {
-            writer.append("<div class=\"screenlet-title-bar\">");
-            appendWhitespace(writer);
-            writer.append("<ul>");
-            appendWhitespace(writer);
-            if (UtilValidate.isNotEmpty(title)) {
-                writer.append("<li class=\"h3\">");
-                writer.append(title);
-                writer.append("</li>");
-                appendWhitespace(writer);
-            }
-            if (screenlet.collapsible()) {
-                collapsibleAreaId = this.getNextElementId();
-                String expandToolTip = null;
-                String collapseToolTip = null;
-                Map<String, Object> uiLabelMap = UtilGenerics.checkMap(context.get("uiLabelMap"));
-                Map<String, Object> paramMap = UtilGenerics.checkMap(context.get("requestParameters"));
-                Map<String, Object> requestParameters = new HashMap<String, Object>(paramMap);
-                if (uiLabelMap != null) {
-                    expandToolTip = (String) uiLabelMap.get("CommonExpand");
-                    collapseToolTip = (String) uiLabelMap.get("CommonCollapse");
-                }
-                writer.append("<li class=\"");
-                if (collapsed) {
-                    writer.append("collapsed\"><a ");
-                    if (javaScriptEnabled) {
-                        writer.append("onclick=\"javascript:toggleScreenlet(this, '").append(collapsibleAreaId).append("', '").append(expandToolTip).append("', '").append(collapseToolTip).append("');\"");
-                    } else {
-                        requestParameters.put(screenlet.getPreferenceKey(context) + "_collapsed", "false");
-                        String queryString = UtilHttp.urlEncodeArgs(requestParameters);
-                        writer.append("href=\"").append(request.getRequestURI()).append("?").append(queryString).append("\"");
-                    }
-                    if (UtilValidate.isNotEmpty(expandToolTip)) {
-                        writer.append(" title=\"").append(expandToolTip).append("\"");
-                    }
-                } else {
-                    writer.append("expanded\"><a ");
-                    if (javaScriptEnabled) {
-                        writer.append("onclick=\"javascript:toggleScreenlet(this, '").append(collapsibleAreaId).append("', '").append(expandToolTip).append("', '").append(collapseToolTip).append("');\"");
-                    } else {
-                        requestParameters.put(screenlet.getPreferenceKey(context) + "_collapsed", "true");
-                        String queryString = UtilHttp.urlEncodeArgs(requestParameters);
-                        writer.append("href=\"").append(request.getRequestURI()).append("?").append(queryString).append("\"");
-                    }
-                    if (UtilValidate.isNotEmpty(collapseToolTip)) {
-                        writer.append(" title=\"").append(collapseToolTip).append("\"");
-                    }
-                }
-                writer.append(">&nbsp</a></li>");
-                appendWhitespace(writer);
-            }
-            if (!collapsed) {
-                if (navMenu != null) {
-                    MenuStringRenderer savedRenderer = (MenuStringRenderer) context.get("menuStringRenderer");
-                    MenuStringRenderer renderer = new ScreenletMenuRenderer(request, response);
-                    context.put("menuStringRenderer", renderer);
-                    navMenu.renderWidgetString(writer, context, this);
-                    context.put("menuStringRenderer", savedRenderer);
-                } else if (navForm != null) {
-                    renderScreenletPaginateMenu(writer, context, navForm);
-                }
-            }
-            writer.append("</ul>");
-            appendWhitespace(writer);
-            writer.append("<br class=\"clear\" />");
-            appendWhitespace(writer);
-            writer.append("</div>");
-            appendWhitespace(writer);
-            writer.append("<div");
-            if (UtilValidate.isNotEmpty(collapsibleAreaId)) {
-                writer.append(" id=\"").append(collapsibleAreaId).append("\"");
-                if (collapsed) {
-                    writer.append(" style=\"display: none;\"");
-                }
-            }
-            if (screenlet.padded()) {
-                writer.append(" class=\"screenlet-body\"");
-            }
-            writer.append(">");
-            appendWhitespace(writer);
-        }
-    }
-
-    private int getActualPageSize(Map<String, Object> context) {
-        Integer value = (Integer) context.get("actualPageSize");
-        return value != null ? value.intValue() : (getHighIndex(context) - getLowIndex(context));
-    }
-
-    private int getHighIndex(Map<String, Object> context) {
-        Integer value = (Integer) context.get("highIndex");
-        return value != null ? value.intValue() : 0;
-    }
-
-    private int getListSize(Map<String, Object> context) {
-        Integer value = (Integer) context.get("listSize");
-        return value != null ? value.intValue() : 0;
-    }
-
-    private int getLowIndex(Map<String, Object> context) {
-        Integer value = (Integer) context.get("lowIndex");
-        return value != null ? value.intValue() : 0;
-    }
-
-    protected void renderScreenletPaginateMenu(Appendable writer, Map<String, Object> context, Form form) throws IOException {
-        HttpServletResponse response = (HttpServletResponse) context.get("response");
-        HttpServletRequest request = (HttpServletRequest) context.get("request");
-        ModelForm modelForm = form.getModelForm(context);
-        modelForm.runFormActions(context);
-        Paginator.preparePager(modelForm, context);
-        String targetService = modelForm.getPaginateTarget(context);
-        if (targetService == null) {
-            targetService = "${targetService}";
-        }
-
-        // get the parametrized pagination index and size fields
-        int paginatorNumber = WidgetWorker.getPaginatorNumber(context);
-        String viewIndexParam = modelForm.getMultiPaginateIndexField(context);
-        String viewSizeParam = modelForm.getMultiPaginateSizeField(context);
-
-        int viewIndex = Paginator.getViewIndex(modelForm, context);
-        int viewSize = Paginator.getViewSize(modelForm, context);
-        int listSize = getListSize(context);
-
-        int lowIndex = getLowIndex(context);
-        int highIndex = getHighIndex(context);
-        int actualPageSize = getActualPageSize(context);
-
-        // if this is all there seems to be (if listSize < 0, then size is unknown)
-        if (actualPageSize >= listSize && listSize >= 0) return;
-
-        // needed for the "Page" and "rows" labels
-        Map<String, String> uiLabelMap = UtilGenerics.cast(context.get("uiLabelMap"));
-        String ofLabel = "";
-        if (uiLabelMap == null) {
-            Debug.logWarning("Could not find uiLabelMap in context", module);
-        } else {
-            ofLabel = uiLabelMap.get("CommonOf");
-            ofLabel = ofLabel.toLowerCase();
-        }
-
-        // for legacy support, the viewSizeParam is VIEW_SIZE and viewIndexParam is VIEW_INDEX when the fields are "viewSize" and "viewIndex"
-        if (viewIndexParam.equals("viewIndex" + "_" + paginatorNumber)) viewIndexParam = "VIEW_INDEX" + "_" + paginatorNumber;
-        if (viewSizeParam.equals("viewSize" + "_" + paginatorNumber)) viewSizeParam = "VIEW_SIZE" + "_" + paginatorNumber;
-
-        ServletContext ctx = (ServletContext) request.getAttribute("servletContext");
-        RequestHandler rh = (RequestHandler) ctx.getAttribute("_REQUEST_HANDLER_");
-
-        Map<String, Object> inputFields = UtilGenerics.toMap(context.get("requestParameters"));
-        // strip out any multi form fields if the form is of type multi
-        if (modelForm.getType().equals("multi")) {
-            inputFields = UtilHttp.removeMultiFormParameters(inputFields);
-        }
-        String queryString = UtilHttp.urlEncodeArgs(inputFields);
-        // strip legacy viewIndex/viewSize params from the query string
-        queryString = UtilHttp.stripViewParamsFromQueryString(queryString, "" + paginatorNumber);
-        // strip parametrized index/size params from the query string
-        HashSet<String> paramNames = new HashSet<String>();
-        paramNames.add(viewIndexParam);
-        paramNames.add(viewSizeParam);
-        queryString = UtilHttp.stripNamedParamsFromQueryString(queryString, paramNames);
-
-        String anchor = "";
-        String paginateAnchor = modelForm.getPaginateTargetAnchor();
-        if (paginateAnchor != null) anchor = "#" + paginateAnchor;
-
-        // preparing the link text, so that later in the code we can reuse this and just add the viewIndex
-        StringBuilder prepLinkTextBuffer = new StringBuilder(targetService);
-        if (prepLinkTextBuffer.indexOf("?") < 0) {
-            prepLinkTextBuffer.append("?");
-        } else if (prepLinkTextBuffer.indexOf("?", prepLinkTextBuffer.length() - 1) > 0) {
-            prepLinkTextBuffer.append("&amp;");
-        }
-        if (!UtilValidate.isEmpty(queryString) && !queryString.equals("null")) {
-            prepLinkTextBuffer.append(queryString).append("&amp;");
-        }
-        prepLinkTextBuffer.append(viewSizeParam).append("=").append(viewSize).append("&amp;").append(viewIndexParam).append("=");
-        String prepLinkText = prepLinkTextBuffer.toString();
-
-        String linkText;
-
-        appendWhitespace(writer);
-        // The current screenlet title bar navigation syling requires rendering
-        // these links in reverse order
-        // Last button
-        writer.append("<li class=\"").append(modelForm.getPaginateLastStyle());
-        if (highIndex < listSize) {
-            writer.append("\"><a href=\"");
-            int lastIndex = UtilMisc.getViewLastIndex(listSize, viewSize);
-            linkText = prepLinkText + lastIndex + anchor;
-            // - make the link
-            writer.append(rh.makeLink(request, response, linkText));
-            writer.append("\">").append(modelForm.getPaginateLastLabel(context)).append("</a>");
-        } else {
-            // disabled button
-            writer.append(" disabled\">").append(modelForm.getPaginateLastLabel(context));
-        }
-        writer.append("</li>");
-        appendWhitespace(writer);
-        // Next button
-        writer.append("<li class=\"").append(modelForm.getPaginateNextStyle());
-        if (highIndex < listSize) {
-            writer.append("\"><a href=\"");
-            linkText = prepLinkText + (viewIndex + 1) + anchor;
-            // - make the link
-            writer.append(rh.makeLink(request, response, linkText));
-            writer.append("\">").append(modelForm.getPaginateNextLabel(context)).append("</a>");
-        } else {
-            // disabled button
-            writer.append(" disabled\">").append(modelForm.getPaginateNextLabel(context));
-        }
-        writer.append("</li>");
-        appendWhitespace(writer);
-        if (listSize > 0) {
-            writer.append("<li>");
-            writer.append(Integer.toString(lowIndex + 1)).append(" - ").append(Integer.toString(lowIndex + actualPageSize)).append(" ").append(ofLabel).append(" ").append(Integer.toString(listSize));
-            writer.append("</li>");
-            appendWhitespace(writer);
-        }
-        // Previous button
-        writer.append("<li class=\"nav-previous");
-        if (viewIndex > 0) {
-            writer.append("\"><a href=\"");
-            linkText = prepLinkText + (viewIndex - 1) + anchor;
-            // - make the link
-            writer.append(rh.makeLink(request, response, linkText));
-            writer.append("\">").append(modelForm.getPaginatePreviousLabel(context)).append("</a>");
-        } else {
-            // disabled button
-            writer.append(" disabled\">").append(modelForm.getPaginatePreviousLabel(context));
-        }
-        writer.append("</li>");
-        appendWhitespace(writer);
-        // First button
-        writer.append("<li class=\"nav-first");
-        if (viewIndex > 0) {
-            writer.append("\"><a href=\"");
-            linkText = prepLinkText + 0 + anchor;
-            writer.append(rh.makeLink(request, response, linkText));
-            writer.append("\">").append(modelForm.getPaginateFirstLabel(context)).append("</a>");
-        } else {
-            writer.append(" disabled\">").append(modelForm.getPaginateFirstLabel(context));
-        }
-        writer.append("</li>");
-        appendWhitespace(writer);
-    }
-
-    public void renderScreenletSubWidget(Appendable writer, Map<String, Object> context, ModelScreenWidget subWidget, Screenlet screenlet) throws GeneralException, IOException {
-        if (subWidget.equals(screenlet.getNavigationForm())) {
-            HttpServletRequest request = (HttpServletRequest) context.get("request");
-            HttpServletResponse response = (HttpServletResponse) context.get("response");
-            if (request != null && response != null) {
-                Map<String, Object> globalCtx = UtilGenerics.checkMap(context.get("globalContext"));
-                globalCtx.put("NO_PAGINATOR", true);
-                FormStringRenderer savedRenderer = (FormStringRenderer) context.get("formStringRenderer");
-                HtmlFormRenderer renderer = new HtmlFormRenderer(request, response);
-                renderer.setRenderPagination(false);
-                context.put("formStringRenderer", renderer);
-                subWidget.renderWidgetString(writer, context, this);
-                context.put("formStringRenderer", savedRenderer);
-            }
-        } else {
-            subWidget.renderWidgetString(writer, context, this);
-        }
-    }
-
-    public void renderScreenletEnd(Appendable writer, Map<String, Object> context, Screenlet screenlet) throws IOException {
-        writer.append("</div>");
-        appendWhitespace(writer);
-        writer.append("</div>");
-        appendWhitespace(writer);
-    }
-
-    public static class ScreenletMenuRenderer extends HtmlMenuRenderer {
-        public ScreenletMenuRenderer(HttpServletRequest request, HttpServletResponse response) {
-            super(request, response);
-        }
-        @Override
-        public void renderMenuOpen(Appendable writer, Map<String, Object> context, ModelMenu modelMenu) {}
-        @Override
-        public void renderMenuClose(Appendable writer, Map<String, Object> context, ModelMenu modelMenu) {}
-    }
-
-    public void renderLabel(Appendable writer, Map<String, Object> context, Label label) throws IOException {
-        String labelText = label.getText(context);
-        if (UtilValidate.isEmpty(labelText)) {
-            // nothing to render
-            return;
-        }
-        // open tag
-        String style = label.getStyle(context);
-        String id = label.getId(context);
-        if (UtilValidate.isNotEmpty(style) || UtilValidate.isNotEmpty(id)) {
-               writer.append("<span");
-
-            if (UtilValidate.isNotEmpty(id)) {
-                writer.append(" id=\"");
-                writer.append(id);
-                writer.append("\"");
-            }
-            if (UtilValidate.isNotEmpty(style)) {
-                writer.append(" class=\"");
-                writer.append(style);
-                writer.append("\"");
-            }
-            writer.append(">");
-
-            // the text
-            writer.append(labelText);
-
-            // close tag
-               writer.append("</span>");
-
-        } else {
-            writer.append(labelText);
-        }
-
-        appendWhitespace(writer);
-    }
-
-    public void renderLink(Appendable writer, Map<String, Object> context, ScreenLink link) throws IOException {
-        HttpServletResponse response = (HttpServletResponse) context.get("response");
-        HttpServletRequest request = (HttpServletRequest) context.get("request");
-
-        String targetWindow = link.getTargetWindow(context);
-        String target = link.getTarget(context);
-
-        String uniqueItemName = link.getModelScreen().getName() + "_LF_" + UtilMisc.<String>addToBigDecimalInMap(context, "screenUniqueItemIndex", BigDecimal.ONE);
-
-        String linkType = WidgetWorker.determineAutoLinkType(link.getLinkType(), target, link.getUrlMode(), request);
-        if ("hidden-form".equals(linkType)) {
-            writer.append("<form method=\"post\"");
-            writer.append(" action=\"");
-            // note that this passes null for the parameterList on purpose so they won't be put into the URL
-            WidgetWorker.buildHyperlinkUrl(writer, target, link.getUrlMode(), null, link.getPrefix(context),
-                    link.getFullPath(), link.getSecure(), link.getEncode(), request, response, context);
-            writer.append("\"");
-
-            if (UtilValidate.isNotEmpty(targetWindow)) {
-                writer.append(" target=\"");
-                writer.append(targetWindow);
-                writer.append("\"");
-            }
-
-            writer.append(" onsubmit=\"javascript:submitFormDisableSubmits(this)\"");
-
-            writer.append(" name=\"");
-            writer.append(uniqueItemName);
-            writer.append("\">");
-
-            for (Map.Entry<String, String> parameter: link.getParameterMap(context).entrySet()) {
-                writer.append("<input name=\"");
-                writer.append(parameter.getKey());
-                writer.append("\" value=\"");
-                writer.append(parameter.getValue());
-                writer.append("\" type=\"hidden\"/>");
-            }
-
-            writer.append("</form>");
-        }
-
-        writer.append("<a");
-        String id = link.getId(context);
-        if (UtilValidate.isNotEmpty(id)) {
-            writer.append(" id=\"");
-            writer.append(id);
-            writer.append("\"");
-        }
-        String style = link.getStyle(context);
-        if (UtilValidate.isNotEmpty(style)) {
-            writer.append(" class=\"");
-            writer.append(style);
-            writer.append("\"");
-        }
-        String name = link.getName(context);
-        if (UtilValidate.isNotEmpty(name)) {
-            writer.append(" name=\"");
-            writer.append(name);
-            writer.append("\"");
-        }
-        if (UtilValidate.isNotEmpty(targetWindow)) {
-            writer.append(" target=\"");
-            writer.append(targetWindow);
-            writer.append("\"");
-        }
-        if (UtilValidate.isNotEmpty(target)) {
-            writer.append(" href=\"");
-            if ("hidden-form".equals(linkType)) {
-                writer.append("javascript:document.");
-                writer.append(uniqueItemName);
-                writer.append(".submit()");
-            } else {
-                WidgetWorker.buildHyperlinkUrl(writer, target, link.getUrlMode(), link.getParameterMap(context), link.getPrefix(context),
-                        link.getFullPath(), link.getSecure(), link.getEncode(), request, response, context);
-            }
-            writer.append("\"");
-        }
-        writer.append(">");
-
-        // the text
-        ScreenImage img = link.getImage();
-        if (img == null) {
-            writer.append(link.getText(context));
-        } else {
-            renderImage(writer, context, img);
-        }
-
-        // close tag
-        writer.append("</a>");
-
-        appendWhitespace(writer);
-    }
-
-    public void renderImage(Appendable writer, Map<String, Object> context, ScreenImage image) throws IOException {
-        // open tag
-        String src = image.getSrc(context);
-        if (UtilValidate.isEmpty(src)) {
-            return;
-        }
-        writer.append("<img ");
-        String id = image.getId(context);
-        if (UtilValidate.isNotEmpty(id)) {
-            writer.append(" id=\"");
-            writer.append(id);
-            writer.append("\"");
-        }
-        String style = image.getStyle(context);
-        if (UtilValidate.isNotEmpty(style)) {
-            writer.append(" class=\"");
-            writer.append(style);
-            writer.append("\"");
-        }
-        String wid = image.getWidth(context);
-        if (UtilValidate.isNotEmpty(wid)) {
-            writer.append(" width=\"");
-            writer.append(wid);
-            writer.append("\"");
-        }
-        String hgt = image.getHeight(context);
-        if (UtilValidate.isNotEmpty(hgt)) {
-            writer.append(" height=\"");
-            writer.append(hgt);
-            writer.append("\"");
-        }
-        String border = image.getBorder(context);
-        if (UtilValidate.isNotEmpty(border)) {
-            writer.append(" border=\"");
-            writer.append(border);
-            writer.append("\"");
-        }
-        String alt = image.getAlt(context);
-        if (UtilValidate.isNotEmpty(alt)) {
-            writer.append(" alt=\"");
-            writer.append(alt);
-            writer.append("\"");
-        }
-
-        writer.append(" src=\"");
-        String urlMode = image.getUrlMode();
-        boolean fullPath = false;
-        boolean secure = false;
-        boolean encode = false;
-        HttpServletResponse response = (HttpServletResponse) context.get("response");
-        HttpServletRequest request = (HttpServletRequest) context.get("request");
-        if (urlMode != null && urlMode.equalsIgnoreCase("intra-app")) {
-            if (request != null && response != null) {
-                ServletContext ctx = (ServletContext) request.getAttribute("servletContext");
-                RequestHandler rh = (RequestHandler) ctx.getAttribute("_REQUEST_HANDLER_");
-                String urlString = rh.makeLink(request, response, src, fullPath, secure, encode);
-                writer.append(urlString);
-            } else {
-                writer.append(src);
-            }
-        } else  if (urlMode != null && urlMode.equalsIgnoreCase("content")) {
-            if (request != null && response != null) {
-                StringBuilder newURL = new StringBuilder();
-                ContentUrlTag.appendContentPrefix(request, newURL);
-                newURL.append(src);
-                writer.append(newURL.toString());
-            }
-        } else {
-            writer.append(src);
-        }
-
-        writer.append("\"/>");
-
-        appendWhitespace(writer);
-    }
-
-    public void renderContentBegin(Appendable writer, Map<String, Object> context, Content content) throws IOException {
-        String editRequest = content.getEditRequest(context);
-        String editContainerStyle = content.getEditContainerStyle(context);
-        String enableEditName = content.getEnableEditName(context);
-        String enableEditValue = (String)context.get(enableEditName);
-
-        if (Debug.verboseOn()) Debug.logVerbose("directEditRequest:" + editRequest, module);
-
-        if (UtilValidate.isNotEmpty(editRequest) && "true".equals(enableEditValue)) {
-            writer.append("<div");
-            writer.append(" class=\"").append(editContainerStyle).append("\"> ");
-            appendWhitespace(writer);
-        }
-    }
-
-    public void renderContentBody(Appendable writer, Map<String, Object> context, Content content) throws IOException {
-        Locale locale = UtilMisc.ensureLocale(context.get("locale"));
-        //Boolean nullThruDatesOnly = Boolean.valueOf(false);
-        String mimeTypeId = "text/html";
-        String expandedContentId = content.getContentId(context);
-        String expandedDataResourceId = content.getDataResourceId(context);
-        String renderedContent = null;
-        LocalDispatcher dispatcher = (LocalDispatcher) context.get("dispatcher");
-        Delegator delegator = (Delegator) context.get("delegator");
-
-        // make a new map for content rendering; so our current map does not get clobbered
-        Map<String, Object> contentContext = new HashMap<String, Object>();
-        contentContext.putAll(context);
-        String dataResourceId = (String)contentContext.get("dataResourceId");
-        if (Debug.verboseOn()) Debug.logVerbose("expandedContentId:" + expandedContentId, module);
-
-        try {
-            if (UtilValidate.isNotEmpty(dataResourceId)) {
-                if (WidgetDataResourceWorker.dataresourceWorker != null) {
-                    renderedContent = WidgetDataResourceWorker.dataresourceWorker.renderDataResourceAsTextExt(delegator, dataResourceId, contentContext, locale, mimeTypeId, false);
-                } else {
-                    Debug.logError("Not rendering content, WidgetDataResourceWorker.dataresourceWorker not found.", module);
-                }
-            } else if (UtilValidate.isNotEmpty(expandedContentId)) {
-                if (WidgetContentWorker.contentWorker != null) {
-                    renderedContent = WidgetContentWorker.contentWorker.renderContentAsTextExt(dispatcher, delegator, expandedContentId, contentContext, locale, mimeTypeId, true);
-                } else {
-                    Debug.logError("Not rendering content, WidgetContentWorker.contentWorker not found.", module);
-                }
-            } else if (UtilValidate.isNotEmpty(expandedDataResourceId)) {
-                if (WidgetDataResourceWorker.dataresourceWorker != null) {
-                    renderedContent = WidgetDataResourceWorker.dataresourceWorker.renderDataResourceAsTextExt(delegator, expandedDataResourceId, contentContext, locale, mimeTypeId, false);
-                } else {
-                    Debug.logError("Not rendering content, WidgetDataResourceWorker.dataresourceWorker not found.", module);
-                }
-            }
-            if (UtilValidate.isEmpty(renderedContent)) {
-                String editRequest = content.getEditRequest(context);
-                if (UtilValidate.isNotEmpty(editRequest)) {
-                    if (WidgetContentWorker.contentWorker != null) {
-                        WidgetContentWorker.contentWorker.renderContentAsTextExt(dispatcher, delegator, "NOCONTENTFOUND", writer, contentContext, locale, mimeTypeId, true);
-                    } else {
-                        Debug.logError("Not rendering content, WidgetContentWorker.contentWorker not found.", module);
-                    }
-                }
-            } else {
-                if (content.xmlEscape()) {
-                    renderedContent = UtilFormatOut.encodeXmlValue(renderedContent);
-                }
-
-                writer.append(renderedContent);
-            }
-
-        } catch (GeneralException e) {
-            String errMsg = "Error rendering included content with id [" + expandedContentId + "] : " + e.toString();
-            Debug.logError(e, errMsg, module);
-            //throw new RuntimeException(errMsg);
-        } catch (IOException e2) {
-            String errMsg = "Error rendering included content with id [" + expandedContentId + "] : " + e2.toString();
-            Debug.logError(e2, errMsg, module);
-            //throw new RuntimeException(errMsg);
-        }
-    }
-
-    public void renderContentEnd(Appendable writer, Map<String, Object> context, Content content) throws IOException {
-
-                //Debug.logInfo("renderContentEnd, context:" + context, module);
-        String expandedContentId = content.getContentId(context);
-        String editMode = "Edit";
-        String editRequest = content.getEditRequest(context);
-        String editContainerStyle = content.getEditContainerStyle(context);
-        String enableEditName = content.getEnableEditName(context);
-        String enableEditValue = (String)context.get(enableEditName);
-        if (editRequest != null && editRequest.toUpperCase().indexOf("IMAGE") > 0) {
-            editMode += " Image";
-        }
-        //String editRequestWithParams = editRequest + "?contentId=${currentValue.contentId}&drDataResourceId=${currentValue.drDataResourceId}&directEditRequest=${directEditRequest}&indirectEditRequest=${indirectEditRequest}&caContentIdTo=${currentValue.caContentIdTo}&caFromDate=${currentValue.caFromDate}&caContentAssocTypeId=${currentValue.caContentAssocTypeId}";
-
-        if (UtilValidate.isNotEmpty(editRequest) && "true".equals(enableEditValue)) {
-            HttpServletResponse response = (HttpServletResponse) context.get("response");
-            HttpServletRequest request = (HttpServletRequest) context.get("request");
-            if (request != null && response != null) {
-                if (editRequest.indexOf("?") < 0)  editRequest += "?";
-                else editRequest += "&amp;";
-                editRequest += "contentId=" + expandedContentId;
-                ServletContext ctx = (ServletContext) request.getAttribute("servletContext");
-                RequestHandler rh = (RequestHandler) ctx.getAttribute("_REQUEST_HANDLER_");
-                writer.append("<a href=\"").append(rh.makeLink(request, response, editRequest, false, false, false)).append("\">").append(editMode).append("</a>");
-            }
-            if (UtilValidate.isNotEmpty(editContainerStyle)) {
-                writer.append("</div>");
-            }
-            appendWhitespace(writer);
-        }
-    }
-
-    public void renderContentFrame(Appendable writer, Map<String, Object> context, Content content) throws IOException {
-
-
-        HttpServletRequest request = (HttpServletRequest) context.get("request");
-        HttpServletResponse response = (HttpServletResponse) context.get("response");
-        if (request != null && response != null) {
-            ServletContext ctx = (ServletContext) request.getAttribute("servletContext");
-            RequestHandler rh = (RequestHandler) ctx.getAttribute("_REQUEST_HANDLER_");
-            String dataResourceId = content.getDataResourceId(context);
-//          String urlString = "/content/control/ViewSimpleContent?dataResourceId=" + dataResourceId;
-            String urlString = "/ViewSimpleContent?dataResourceId=" + dataResourceId;
-
-            writer.append("<iframe src=\"").append(rh.makeLink(request, response, urlString, true, false, false)).append("\" ");
-            writer.append(" width=\"").append(content.getWidth()).append("\"");
-            writer.append(" height=\"").append(content.getHeight()).append("\"");
-            String border = content.getBorder();
-            if (UtilValidate.isNotEmpty(border)) {
-                writer.append(" border=\"").append(border).append("\"");
-            }
-            writer.append(" />");
-        }
-
-    }
-
-    public void renderSubContentBegin(Appendable writer, Map<String, Object> context, SubContent content) throws IOException {
-
-        String editRequest = content.getEditRequest(context);
-        String editContainerStyle = content.getEditContainerStyle(context);
-        String enableEditName = content.getEnableEditName(context);
-        String enableEditValue = (String)context.get(enableEditName);
-        if (UtilValidate.isNotEmpty(editRequest) && "true".equals(enableEditValue)) {
-            writer.append("<div");
-            writer.append(" class=\"").append(editContainerStyle).append("\"> ");
-
-            appendWhitespace(writer);
-        }
-    }
-
-    public void renderSubContentBody(Appendable writer, Map<String, Object> context, SubContent content) throws IOException {
-            Locale locale = Locale.getDefault();
-            String mimeTypeId = "text/html";
-            String expandedContentId = content.getContentId(context);
-            String expandedMapKey = content.getMapKey(context);
-            String renderedContent = null;
-            LocalDispatcher dispatcher = (LocalDispatcher) context.get("dispatcher");
-            Delegator delegator = (Delegator) context.get("delegator");
-
-            // create a new map for the content rendering; so our current context does not get overwritten!
-            Map<String, Object> contentContext = new HashMap<String, Object>();
-            contentContext.putAll(context);
-
-            try {
-                if (WidgetContentWorker.contentWorker != null) {
-                    renderedContent = WidgetContentWorker.contentWorker.renderSubContentAsTextExt(dispatcher, delegator, expandedContentId, expandedMapKey, contentContext, locale, mimeTypeId, true);
-                    //Debug.logInfo("renderedContent=" + renderedContent, module);
-                } else {
-                    Debug.logError("Not rendering content, WidgetContentWorker.contentWorker not found.", module);
-                }
-                if (UtilValidate.isEmpty(renderedContent)) {
-                    String editRequest = content.getEditRequest(context);
-                    if (UtilValidate.isNotEmpty(editRequest)) {
-                        if (WidgetContentWorker.contentWorker != null) {
-                            WidgetContentWorker.contentWorker.renderContentAsTextExt(dispatcher, delegator, "NOCONTENTFOUND", writer, contentContext, locale, mimeTypeId, true);
-                        } else {
-                            Debug.logError("Not rendering content, WidgetContentWorker.contentWorker not found.", module);
-                        }
-                    }
-                } else {
-                    if (content.xmlEscape()) {
-                        renderedContent = UtilFormatOut.encodeXmlValue(renderedContent);
-                    }
-
-                    writer.append(renderedContent);
-                }
-
-            } catch (GeneralException e) {
-                String errMsg = "Error rendering included content with id [" + expandedContentId + "] : " + e.toString();
-                Debug.logError(e, errMsg, module);
-                //throw new RuntimeException(errMsg);
-            } catch (IOException e2) {
-                String errMsg = "Error rendering included content with id [" + expandedContentId + "] : " + e2.toString();
-                Debug.logError(e2, errMsg, module);
-                //throw new RuntimeException(errMsg);
-            }
-    }
-
-    public void renderSubContentEnd(Appendable writer, Map<String, Object> context, SubContent content) throws IOException {
-
-        String editMode = "Edit";
-        String editRequest = content.getEditRequest(context);
-        String editContainerStyle = content.getEditContainerStyle(context);
-        String enableEditName = content.getEnableEditName(context);
-        String enableEditValue = (String)context.get(enableEditName);
-        String expandedContentId = content.getContentId(context);
-        String expandedMapKey = content.getMapKey(context);
-        if (editRequest != null && editRequest.toUpperCase().indexOf("IMAGE") > 0) {
-            editMode += " Image";
-        }
-        if (UtilValidate.isNotEmpty(editRequest) && "true".equals(enableEditValue)) {
-            HttpServletResponse response = (HttpServletResponse) context.get("response");
-            HttpServletRequest request = (HttpServletRequest) context.get("request");
-            if (request != null && response != null) {
-                if (editRequest.indexOf("?") < 0)  editRequest += "?";
-                else editRequest += "&amp;";
-                editRequest += "contentId=" + expandedContentId;
-                if (UtilValidate.isNotEmpty(expandedMapKey)) {
-                    editRequest += "&amp;mapKey=" + expandedMapKey;
-                }
-                //HttpSession session = request.getSession();
-                //GenericValue userLogin = (GenericValue)session.getAttribute("userLogin");
-                /* don't know why this is here. might come to me later. -amb
-                Delegator delegator = (Delegator)request.getAttribute("delegator");
-                String contentIdTo = content.getContentId(context);
-                String mapKey = content.getAssocName(context);
-                GenericValue view = null;
-                try {
-                    view = ContentWorker.getSubContentCache(delegator, contentIdTo, mapKey, userLogin, null, UtilDateTime.nowTimestamp(), Boolean.valueOf(false), null);
-                } catch (GenericEntityException e) {
-                    throw new IOException("Originally a GenericEntityException. " + e.getMessage());
-                }
-                */
-                ServletContext ctx = (ServletContext) request.getAttribute("servletContext");
-                RequestHandler rh = (RequestHandler) ctx.getAttribute("_REQUEST_HANDLER_");
-                writer.append("<a href=\"").append(rh.makeLink(request, response, editRequest, false, false, false)).append("\">").append(editMode).append("</a>");
-            }
-            if (UtilValidate.isNotEmpty(editContainerStyle)) {
-                writer.append("</div>");
-            }
-            appendWhitespace(writer);
-        }
-    }
-
-    public void renderPortalPageBegin(Appendable writer, Map<String, Object> context, PortalPage portalPage) throws GeneralException, IOException {
-        // TODO: not implemented
-    }
-    public void renderPortalPageEnd(Appendable writer, Map<String, Object> context, PortalPage portalPage) throws GeneralException, IOException {
-        // TODO: not implemented
-    }
-    public void renderPortalPageColumnBegin(Appendable writer, Map<String, Object> context, PortalPage portalPage, GenericValue portalPageColumn) throws GeneralException, IOException {
-        // TODO: not implemented
-    }
-    public void renderPortalPageColumnEnd(Appendable writer, Map<String, Object> context, PortalPage portalPage, GenericValue portalPageColumn) throws GeneralException, IOException {
-        // TODO: not implemented
-    }
-    public void renderPortalPagePortletBegin(Appendable writer, Map<String, Object> context, PortalPage portalPage, GenericValue portalPortlet) throws GeneralException, IOException {
-        // TODO: not implemented
-    }
-    public void renderPortalPagePortletEnd(Appendable writer, Map<String, Object> context, PortalPage portalPage, GenericValue portalPortlet) throws GeneralException, IOException {
-        // TODO: not implemented
-    }
-    public void renderPortalPagePortletBody(Appendable writer, Map<String, Object> context, PortalPage portalPage, GenericValue portalPortlet) throws GeneralException, IOException {
-        // TODO: not implemented
-    }
-
-    @Override
-    public void renderColumnContainer(Appendable writer, Map<String, Object> context, ColumnContainer columnContainer) throws IOException {
-        // TODO: not implemented
-    }
-}
+/*******************************************************************************

+ * 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.renderer.html;

+

+import java.io.IOException;

+import java.math.BigDecimal;

+import java.util.HashMap;

+import java.util.HashSet;

+import java.util.Locale;

+import java.util.Map;

+

+import javax.servlet.ServletContext;

+import javax.servlet.http.HttpServletRequest;

+import javax.servlet.http.HttpServletResponse;

+

+import org.ofbiz.base.util.Debug;

+import org.ofbiz.base.util.GeneralException;

+import org.ofbiz.base.util.UtilFormatOut;

+import org.ofbiz.base.util.UtilGenerics;

+import org.ofbiz.base.util.UtilHttp;

+import org.ofbiz.base.util.UtilMisc;

+import org.ofbiz.base.util.UtilValidate;

+import org.ofbiz.entity.Delegator;

+import org.ofbiz.entity.GenericValue;

+import org.ofbiz.service.LocalDispatcher;

+import org.ofbiz.webapp.control.RequestHandler;

+import org.ofbiz.webapp.taglib.ContentUrlTag;

+import org.ofbiz.widget.WidgetWorker;

+import org.ofbiz.widget.content.WidgetContentWorker;

+import org.ofbiz.widget.content.WidgetDataResourceWorker;

+import org.ofbiz.widget.model.ModelForm;

+import org.ofbiz.widget.model.ModelMenu;

+import org.ofbiz.widget.model.ModelScreenWidget;

+import org.ofbiz.widget.model.ModelScreenWidget.ColumnContainer;

+import org.ofbiz.widget.model.ModelScreenWidget.Container;

+import org.ofbiz.widget.model.ModelScreenWidget.Content;

+import org.ofbiz.widget.model.ModelScreenWidget.Form;

+import org.ofbiz.widget.model.ModelScreenWidget.HorizontalSeparator;

+import org.ofbiz.widget.model.ModelScreenWidget.Label;

+import org.ofbiz.widget.model.ModelScreenWidget.Menu;

+import org.ofbiz.widget.model.ModelScreenWidget.PortalPage;

+import org.ofbiz.widget.model.ModelScreenWidget.ScreenImage;

+import org.ofbiz.widget.model.ModelScreenWidget.ScreenLink;

+import org.ofbiz.widget.model.ModelScreenWidget.Screenlet;

+import org.ofbiz.widget.model.ModelScreenWidget.Section;

+import org.ofbiz.widget.model.ModelScreenWidget.SubContent;

+import org.ofbiz.widget.model.ModelWidget;

+import org.ofbiz.widget.renderer.FormStringRenderer;

+import org.ofbiz.widget.renderer.MenuStringRenderer;

+import org.ofbiz.widget.renderer.Paginator;

+import org.ofbiz.widget.renderer.ScreenStringRenderer;

+

+/**

+ * Widget Library - HTML Form Renderer implementation

+ * @deprecated Use MacroScreenRenderer.

+ */

+public class HtmlScreenRenderer extends HtmlWidgetRenderer implements ScreenStringRenderer {

+

+    public static final String module = HtmlScreenRenderer.class.getName();

+    protected int elementId = 999;

+

+    public HtmlScreenRenderer() {}

+

+    protected String getNextElementId() {

+        elementId++;

+        return "hsr" + elementId;

+    }

+

+    public String getRendererName() {

+        return "html";

+    }

+

+    public void renderScreenBegin(Appendable writer, Map<String, Object> context) throws IOException {

+        writer.append("<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">");

+        appendWhitespace(writer);

+    }

+

+    public void renderScreenEnd(Appendable writer, Map<String, Object> context) throws IOException {

+    }

+

+    public void renderSectionBegin(Appendable writer, Map<String, Object> context, Section section) throws IOException {

+        if (section.isMainSection()) {

+            this.widgetCommentsEnabled = ModelWidget.widgetBoundaryCommentsEnabled(context);

+        }

+        renderBeginningBoundaryComment(writer, section.isMainSection()?"Screen":"Section Widget", section);

+    }

+

+    public void renderSectionEnd(Appendable writer, Map<String, Object> context, Section section) throws IOException {

+        renderEndingBoundaryComment(writer, section.isMainSection()?"Screen":"Section Widget", section);

+    }

+

+    public void renderContainerBegin(Appendable writer, Map<String, Object> context, Container container) throws IOException {

+        String containerId = container.getId(context);

+        String autoUpdateTarget = container.getAutoUpdateTargetExdr(context);

+        HttpServletRequest request = (HttpServletRequest) context.get("request");

+        if (UtilValidate.isNotEmpty(autoUpdateTarget) && UtilHttp.isJavaScriptEnabled(request)) {

+            if (UtilValidate.isEmpty(containerId)) {

+                containerId = getNextElementId();

+            }

+            HttpServletResponse response = (HttpServletResponse) context.get("response");

+            ServletContext ctx = (ServletContext) request.getAttribute("servletContext");

+            RequestHandler rh = (RequestHandler) ctx.getAttribute("_REQUEST_HANDLER_");

+

+            writer.append("<script type=\"text/javascript\">ajaxUpdateAreaPeriodic('");

+            writer.append(containerId);

+            writer.append("', '");

+            writer.append(rh.makeLink(request, response, autoUpdateTarget));

+            writer.append("', '");

+            writer.append("', '").append(container.getAutoUpdateInterval(context)).append("');</script>");

+            appendWhitespace(writer);

+        }

+        writer.append("<div");

+

+        if (UtilValidate.isNotEmpty(containerId)) {

+            writer.append(" id=\"");

+            writer.append(containerId);

+            writer.append("\"");

+        }

+

+        String style = container.getStyle(context);

+        if (UtilValidate.isNotEmpty(style)) {

+            writer.append(" class=\"");

+            writer.append(style);

+            writer.append("\"");

+        }

+

+        writer.append(">");

+        appendWhitespace(writer);

+    }

+    public void renderContainerEnd(Appendable writer, Map<String, Object> context, Container container) throws IOException {

+        writer.append("</div>");

+        appendWhitespace(writer);

+    }

+

+    public void renderHorizontalSeparator(Appendable writer, Map<String, Object> context, HorizontalSeparator separator) throws IOException {

+        writer.append("<hr");

+        String className = separator.getStyle(context);

+        if (UtilValidate.isNotEmpty(className)) {

+            writer.append(" class=\"").append(className).append("\"");

+        }

+        String idName = separator.getId(context);

+        if (UtilValidate.isNotEmpty(idName)) {

+            writer.append(" id=\"").append(idName).append("\"");

+        }

+        writer.append("/>");

+        appendWhitespace(writer);

+    }

+

+    public void renderScreenletBegin(Appendable writer, Map<String, Object> context, boolean collapsed, Screenlet screenlet) throws IOException {

+        HttpServletRequest request = (HttpServletRequest) context.get("request");

+        HttpServletResponse response = (HttpServletResponse) context.get("response");

+        boolean javaScriptEnabled = UtilHttp.isJavaScriptEnabled(request);

+        Menu tabMenu = screenlet.getTabMenu();

+        if (tabMenu != null) {

+            tabMenu.renderWidgetString(writer, context, this);

+        }

+        writer.append("<div class=\"screenlet\"");

+        String id = screenlet.getId(context);

+        if (UtilValidate.isNotEmpty(id)) {

+            writer.append(" id=\"");

+            writer.append(id);

+            writer.append("\"");

+        }

+        writer.append(">");

+        appendWhitespace(writer);

+

+        String title = screenlet.getTitle(context);

+        Menu navMenu = screenlet.getNavigationMenu();

+        Form navForm = screenlet.getNavigationForm();

+        String collapsibleAreaId = null;

+        if (UtilValidate.isNotEmpty(title) || navMenu != null || navForm != null || screenlet.collapsible()) {

+            writer.append("<div class=\"screenlet-title-bar\">");

+            appendWhitespace(writer);

+            writer.append("<ul>");

+            appendWhitespace(writer);

+            if (UtilValidate.isNotEmpty(title)) {

+                writer.append("<li class=\"h3\">");

+                writer.append(title);

+                writer.append("</li>");

+                appendWhitespace(writer);

+            }

+            if (screenlet.collapsible()) {

+                collapsibleAreaId = this.getNextElementId();

+                String expandToolTip = null;

+                String collapseToolTip = null;

+                Map<String, Object> uiLabelMap = UtilGenerics.checkMap(context.get("uiLabelMap"));

+                Map<String, Object> paramMap = UtilGenerics.checkMap(context.get("requestParameters"));

+                Map<String, Object> requestParameters = new HashMap<String, Object>(paramMap);

+                if (uiLabelMap != null) {

+                    expandToolTip = (String) uiLabelMap.get("CommonExpand");

+                    collapseToolTip = (String) uiLabelMap.get("CommonCollapse");

+                }

+                writer.append("<li class=\"");

+                if (collapsed) {

+                    writer.append("collapsed\"><a ");

+                    if (javaScriptEnabled) {

+                        writer.append("onclick=\"javascript:toggleScreenlet(this, '").append(collapsibleAreaId).append("', '").append(expandToolTip).append("', '").append(collapseToolTip).append("');\"");

+                    } else {

+                        requestParameters.put(screenlet.getPreferenceKey(context) + "_collapsed", "false");

+                        String queryString = UtilHttp.urlEncodeArgs(requestParameters);

+                        writer.append("href=\"").append(request.getRequestURI()).append("?").append(queryString).append("\"");

+                    }

+                    if (UtilValidate.isNotEmpty(expandToolTip)) {

+                        writer.append(" title=\"").append(expandToolTip).append("\"");

+                    }

+                } else {

+                    writer.append("expanded\"><a ");

+                    if (javaScriptEnabled) {

+                        writer.append("onclick=\"javascript:toggleScreenlet(this, '").append(collapsibleAreaId).append("', '").append(expandToolTip).append("', '").append(collapseToolTip).append("');\"");

+                    } else {

+                        requestParameters.put(screenlet.getPreferenceKey(context) + "_collapsed", "true");

+                        String queryString = UtilHttp.urlEncodeArgs(requestParameters);

+                        writer.append("href=\"").append(request.getRequestURI()).append("?").append(queryString).append("\"");

+                    }

+                    if (UtilValidate.isNotEmpty(collapseToolTip)) {

+                        writer.append(" title=\"").append(collapseToolTip).append("\"");

+                    }

+                }

+                writer.append(">&nbsp</a></li>");

+                appendWhitespace(writer);

+            }

+            if (!collapsed) {

+                if (navMenu != null) {

+                    MenuStringRenderer savedRenderer = (MenuStringRenderer) context.get("menuStringRenderer");

+                    MenuStringRenderer renderer = new ScreenletMenuRenderer(request, response);

+                    context.put("menuStringRenderer", renderer);

+                    navMenu.renderWidgetString(writer, context, this);

+                    context.put("menuStringRenderer", savedRenderer);

+                } else if (navForm != null) {

+                    renderScreenletPaginateMenu(writer, context, navForm);

+                }

+            }

+            writer.append("</ul>");

+            appendWhitespace(writer);

+            writer.append("<br class=\"clear\" />");

+            appendWhitespace(writer);

+            writer.append("</div>");

+            appendWhitespace(writer);

+            writer.append("<div");

+            if (UtilValidate.isNotEmpty(collapsibleAreaId)) {

+                writer.append(" id=\"").append(collapsibleAreaId).append("\"");

+                if (collapsed) {

+                    writer.append(" style=\"display: none;\"");

+                }

+            }

+            if (screenlet.padded()) {

+                writer.append(" class=\"screenlet-body\"");

+            }

+            writer.append(">");

+            appendWhitespace(writer);

+        }

+    }

+

+    private int getActualPageSize(Map<String, Object> context) {

+        Integer value = (Integer) context.get("actualPageSize");

+        return value != null ? value.intValue() : (getHighIndex(context) - getLowIndex(context));

+    }

+

+    private int getHighIndex(Map<String, Object> context) {

+        Integer value = (Integer) context.get("highIndex");

+        return value != null ? value.intValue() : 0;

+    }

+

+    private int getListSize(Map<String, Object> context) {

+        Integer value = (Integer) context.get("listSize");

+        return value != null ? value.intValue() : 0;

+    }

+

+    private int getLowIndex(Map<String, Object> context) {

+        Integer value = (Integer) context.get("lowIndex");

+        return value != null ? value.intValue() : 0;

+    }

+

+    protected void renderScreenletPaginateMenu(Appendable writer, Map<String, Object> context, Form form) throws IOException {

+        HttpServletResponse response = (HttpServletResponse) context.get("response");

+        HttpServletRequest request = (HttpServletRequest) context.get("request");

+        ModelForm modelForm = form.getModelForm(context);

+        modelForm.runFormActions(context);

+        Paginator.preparePager(modelForm, context);

+        String targetService = modelForm.getPaginateTarget(context);

+        if (targetService == null) {

+            targetService = "${targetService}";

+        }

+

+        // get the parametrized pagination index and size fields

+        int paginatorNumber = WidgetWorker.getPaginatorNumber(context);

+        String viewIndexParam = modelForm.getMultiPaginateIndexField(context);

+        String viewSizeParam = modelForm.getMultiPaginateSizeField(context);

+

+        int viewIndex = Paginator.getViewIndex(modelForm, context);

+        int viewSize = Paginator.getViewSize(modelForm, context);

+        int listSize = getListSize(context);

+

+        int lowIndex = getLowIndex(context);

+        int highIndex = getHighIndex(context);

+        int actualPageSize = getActualPageSize(context);

+

+        // if this is all there seems to be (if listSize < 0, then size is unknown)

+        if (actualPageSize >= listSize && listSize >= 0) return;

+

+        // needed for the "Page" and "rows" labels

+        Map<String, String> uiLabelMap = UtilGenerics.cast(context.get("uiLabelMap"));

+        String ofLabel = "";

+        if (uiLabelMap == null) {

+            Debug.logWarning("Could not find uiLabelMap in context", module);

+        } else {

+            ofLabel = uiLabelMap.get("CommonOf");

+            ofLabel = ofLabel.toLowerCase();

+        }

+

+        // for legacy support, the viewSizeParam is VIEW_SIZE and viewIndexParam is VIEW_INDEX when the fields are "viewSize" and "viewIndex"

+        if (viewIndexParam.equals("viewIndex" + "_" + paginatorNumber)) viewIndexParam = "VIEW_INDEX" + "_" + paginatorNumber;

+        if (viewSizeParam.equals("viewSize" + "_" + paginatorNumber)) viewSizeParam = "VIEW_SIZE" + "_" + paginatorNumber;

+

+        ServletContext ctx = (ServletContext) request.getAttribute("servletContext");

+        RequestHandler rh = (RequestHandler) ctx.getAttribute("_REQUEST_HANDLER_");

+

+        Map<String, Object> inputFields = UtilGenerics.toMap(context.get("requestParameters"));

+        // strip out any multi form fields if the form is of type multi

+        if (modelForm.getType().equals("multi")) {

+            inputFields = UtilHttp.removeMultiFormParameters(inputFields);

+        }

+        String queryString = UtilHttp.urlEncodeArgs(inputFields);

+        // strip legacy viewIndex/viewSize params from the query string

+        queryString = UtilHttp.stripViewParamsFromQueryString(queryString, "" + paginatorNumber);

+        // strip parametrized index/size params from the query string

+        HashSet<String> paramNames = new HashSet<String>();

+        paramNames.add(viewIndexParam);

+        paramNames.add(viewSizeParam);

+        queryString = UtilHttp.stripNamedParamsFromQueryString(queryString, paramNames);

+

+        String anchor = "";

+        String paginateAnchor = modelForm.getPaginateTargetAnchor();

+        if (paginateAnchor != null) anchor = "#" + paginateAnchor;

+

+        // preparing the link text, so that later in the code we can reuse this and just add the viewIndex

+        StringBuilder prepLinkTextBuffer = new StringBuilder(targetService);

+        if (prepLinkTextBuffer.indexOf("?") < 0) {

+            prepLinkTextBuffer.append("?");

+        } else if (prepLinkTextBuffer.indexOf("?", prepLinkTextBuffer.length() - 1) > 0) {

+            prepLinkTextBuffer.append("&amp;");

+        }

+        if (!UtilValidate.isEmpty(queryString) && !queryString.equals("null")) {

+            prepLinkTextBuffer.append(queryString).append("&amp;");

+        }

+        prepLinkTextBuffer.append(viewSizeParam).append("=").append(viewSize).append("&amp;").append(viewIndexParam).append("=");

+        String prepLinkText = prepLinkTextBuffer.toString();

+

+        String linkText;

+

+        appendWhitespace(writer);

+        // The current screenlet title bar navigation syling requires rendering

+        // these links in reverse order

+        // Last button

+        writer.append("<li class=\"").append(modelForm.getPaginateLastStyle());

+        if (highIndex < listSize) {

+            writer.append("\"><a href=\"");

+            int lastIndex = UtilMisc.getViewLastIndex(listSize, viewSize);

+            linkText = prepLinkText + lastIndex + anchor;

+            // - make the link

+            writer.append(rh.makeLink(request, response, linkText));

+            writer.append("\">").append(modelForm.getPaginateLastLabel(context)).append("</a>");

+        } else {

+            // disabled button

+            writer.append(" disabled\">").append(modelForm.getPaginateLastLabel(context));

+        }

+        writer.append("</li>");

+        appendWhitespace(writer);

+        // Next button

+        writer.append("<li class=\"").append(modelForm.getPaginateNextStyle());

+        if (highIndex < listSize) {

+            writer.append("\"><a href=\"");

+            linkText = prepLinkText + (viewIndex + 1) + anchor;

+            // - make the link

+            writer.append(rh.makeLink(request, response, linkText));

+            writer.append("\">").append(modelForm.getPaginateNextLabel(context)).append("</a>");

+        } else {

+            // disabled button

+            writer.append(" disabled\">").append(modelForm.getPaginateNextLabel(context));

+        }

+        writer.append("</li>");

+        appendWhitespace(writer);

+        if (listSize > 0) {

+            writer.append("<li>");

+            writer.append(Integer.toString(lowIndex + 1)).append(" - ").append(Integer.toString(lowIndex + actualPageSize)).append(" ").append(ofLabel).append(" ").append(Integer.toString(listSize));

+            writer.append("</li>");

+            appendWhitespace(writer);

+        }

+        // Previous button

+        writer.append("<li class=\"nav-previous");

+        if (viewIndex > 0) {

+            writer.append("\"><a href=\"");

+            linkText = prepLinkText + (viewIndex - 1) + anchor;

+            // - make the link

+            writer.append(rh.makeLink(request, response, linkText));

+            writer.append("\">").append(modelForm.getPaginatePreviousLabel(context)).append("</a>");

+        } else {

+            // disabled button

+            writer.append(" disabled\">").append(modelForm.getPaginatePreviousLabel(context));

+        }

+        writer.append("</li>");

+        appendWhitespace(writer);

+        // First button

+        writer.append("<li class=\"nav-first");

+        if (viewIndex > 0) {

+            writer.append("\"><a href=\"");

+            linkText = prepLinkText + 0 + anchor;

+            writer.append(rh.makeLink(request, response, linkText));

+            writer.append("\">").append(modelForm.getPaginateFirstLabel(context)).append("</a>");

+        } else {

+            writer.append(" disabled\">").append(modelForm.getPaginateFirstLabel(context));

+        }

+        writer.append("</li>");

+        appendWhitespace(writer);

+    }

+

+    public void renderScreenletSubWidget(Appendable writer, Map<String, Object> context, ModelScreenWidget subWidget, Screenlet screenlet) throws GeneralException, IOException {

+        if (subWidget.equals(screenlet.getNavigationForm())) {

+            HttpServletRequest request = (HttpServletRequest) context.get("request");

+            HttpServletResponse response = (HttpServletResponse) context.get("response");

+            if (request != null && response != null) {

+                Map<String, Object> globalCtx = UtilGenerics.checkMap(context.get("globalContext"));

+                globalCtx.put("NO_PAGINATOR", true);

+                FormStringRenderer savedRenderer = (FormStringRenderer) context.get("formStringRenderer");

+                HtmlFormRenderer renderer = new HtmlFormRenderer(request, response);

+                renderer.setRenderPagination(false);

+                context.put("formStringRenderer", renderer);

+                subWidget.renderWidgetString(writer, context, this);

+                context.put("formStringRenderer", savedRenderer);

+            }

+        } else {

+            subWidget.renderWidgetString(writer, context, this);

+        }

+    }

+

+    public void renderScreenletEnd(Appendable writer, Map<String, Object> context, Screenlet screenlet) throws IOException {

+        writer.append("</div>");

+        appendWhitespace(writer);

+        writer.append("</div>");

+        appendWhitespace(writer);

+    }

+

+    public static class ScreenletMenuRenderer extends HtmlMenuRenderer {

+        public ScreenletMenuRenderer(HttpServletRequest request, HttpServletResponse response) {

+            super(request, response);

+        }

+        @Override

+        public void renderMenuOpen(Appendable writer, Map<String, Object> context, ModelMenu modelMenu) {}

+        @Override

+        public void renderMenuClose(Appendable writer, Map<String, Object> context, ModelMenu modelMenu) {}

+    }

+

+    public void renderLabel(Appendable writer, Map<String, Object> context, Label label) throws IOException {

+        String labelText = label.getText(context);

+        if (UtilValidate.isEmpty(labelText)) {

+            // nothing to render

+            return;

+        }

+        // open tag

+        String style = label.getStyle(context);

+        String id = label.getId(context);

+        if (UtilValidate.isNotEmpty(style) || UtilValidate.isNotEmpty(id)) {

+               writer.append("<span");

+

+            if (UtilValidate.isNotEmpty(id)) {

+                writer.append(" id=\"");

+                writer.append(id);

+                writer.append("\"");

+            }

+            if (UtilValidate.isNotEmpty(style)) {

+                writer.append(" class=\"");

+                writer.append(style);

+                writer.append("\"");

+            }

+            writer.append(">");

+

+            // the text

+            writer.append(labelText);

+

+            // close tag

+               writer.append("</span>");

+

+        } else {

+            writer.append(labelText);

+        }

+

+        appendWhitespace(writer);

+    }

+

+    public void renderLink(Appendable writer, Map<String, Object> context, ScreenLink link) throws IOException {

+        HttpServletResponse response = (HttpServletResponse) context.get("response");

+        HttpServletRequest request = (HttpServletRequest) context.get("request");

+

+        String targetWindow = link.getTargetWindow(context);

+        String target = link.getTarget(context);

+

+        String uniqueItemName = link.getModelScreen().getName() + "_LF_" + UtilMisc.<String>addToBigDecimalInMap(context, "screenUniqueItemIndex", BigDecimal.ONE);

+

+        String linkType = WidgetWorker.determineAutoLinkType(link.getLinkType(), target, link.getUrlMode(), request);

+        if ("hidden-form".equals(linkType)) {

+            writer.append("<form method=\"post\"");

+            writer.append(" action=\"");

+            // note that this passes null for the parameterList on purpose so they won't be put into the URL

+            WidgetWorker.buildHyperlinkUrl(writer, target, link.getUrlMode(), null, link.getPrefix(context),

+                    link.getFullPath(), link.getSecure(), link.getEncode(), request, response, context);

+            writer.append("\"");

+

+            if (UtilValidate.isNotEmpty(targetWindow)) {

+                writer.append(" target=\"");

+                writer.append(targetWindow);

+                writer.append("\"");

+            }

+

+            writer.append(" onsubmit=\"javascript:submitFormDisableSubmits(this)\"");

+

+            writer.append(" name=\"");

+            writer.append(uniqueItemName);

+            writer.append("\">");

+

+            for (Map.Entry<String, String> parameter: link.getParameterMap(context).entrySet()) {

+                writer.append("<input name=\"");

+                writer.append(parameter.getKey());

+                writer.append("\" value=\"");

+                writer.append(parameter.getValue());

+                writer.append("\" type=\"hidden\"/>");

+            }

+

+            writer.append("</form>");

+        }

+

+        writer.append("<a");

+        String id = link.getId(context);

+        if (UtilValidate.isNotEmpty(id)) {

+            writer.append(" id=\"");

+            writer.append(id);

+            writer.append("\"");

+        }

+        String style = link.getStyle(context);

+        if (UtilValidate.isNotEmpty(style)) {

+            writer.append(" class=\"");

+            writer.append(style);

+            writer.append("\"");

+        }

+        String name = link.getName(context);

+        if (UtilValidate.isNotEmpty(name)) {

+            writer.append(" name=\"");

+            writer.append(name);

+            writer.append("\"");

+        }

+        if (UtilValidate.isNotEmpty(targetWindow)) {

+            writer.append(" target=\"");

+            writer.append(targetWindow);

+            writer.append("\"");

+        }

+        if (UtilValidate.isNotEmpty(target)) {

+            writer.append(" href=\"");

+            if ("hidden-form".equals(linkType)) {

+                writer.append("javascript:document.");

+                writer.append(uniqueItemName);

+                writer.append(".submit()");

+            } else {

+                WidgetWorker.buildHyperlinkUrl(writer, target, link.getUrlMode(), link.getParameterMap(context), link.getPrefix(context),

+                        link.getFullPath(), link.getSecure(), link.getEncode(), request, response, context);

+            }

+            writer.append("\"");

+        }

+        writer.append(">");

+

+        // the text

+        ScreenImage img = link.getImage();

+        if (img == null) {

+            writer.append(link.getText(context));

+        } else {

+            renderImage(writer, context, img);

+        }

+

+        // close tag

+        writer.append("</a>");

+

+        appendWhitespace(writer);

+    }

+

+    public void renderImage(Appendable writer, Map<String, Object> context, ScreenImage image) throws IOException {

+        // open tag

+        String src = image.getSrc(context);

+        if (UtilValidate.isEmpty(src)) {

+            return;

+        }

+        writer.append("<img ");

+        String id = image.getId(context);

+        if (UtilValidate.isNotEmpty(id)) {

+            writer.append(" id=\"");

+            writer.append(id);

+            writer.append("\"");

+        }

+        String style = image.getStyle(context);

+        if (UtilValidate.isNotEmpty(style)) {

+            writer.append(" class=\"");

+            writer.append(style);

+            writer.append("\"");

+        }

+        String wid = image.getWidth(context);

+        if (UtilValidate.isNotEmpty(wid)) {

+            writer.append(" width=\"");

+            writer.append(wid);

+            writer.append("\"");

+        }

+        String hgt = image.getHeight(context);

+        if (UtilValidate.isNotEmpty(hgt)) {

+            writer.append(" height=\"");

+            writer.append(hgt);

+            writer.append("\"");

+        }

+        String border = image.getBorder(context);

+        if (UtilValidate.isNotEmpty(border)) {

+            writer.append(" border=\"");

+            writer.append(border);

+            writer.append("\"");

+        }

+        String alt = image.getAlt(context);

+        if (UtilValidate.isNotEmpty(alt)) {

+            writer.append(" alt=\"");

+            writer.append(alt);

+            writer.append("\"");

+        }

+

+        writer.append(" src=\"");

+        String urlMode = image.getUrlMode();

+        boolean fullPath = false;

+        boolean secure = false;

+        boolean encode = false;

+        HttpServletResponse response = (HttpServletResponse) context.get("response");

+        HttpServletRequest request = (HttpServletRequest) context.get("request");

+        if (urlMode != null && urlMode.equalsIgnoreCase("intra-app")) {

+            if (request != null && response != null) {

+                ServletContext ctx = (ServletContext) request.getAttribute("servletContext");

+                RequestHandler rh = (RequestHandler) ctx.getAttribute("_REQUEST_HANDLER_");

+                String urlString = rh.makeLink(request, response, src, fullPath, secure, encode);

+                writer.append(urlString);

+            } else {

+                writer.append(src);

+            }

+        } else  if (urlMode != null && urlMode.equalsIgnoreCase("content")) {

+            if (request != null && response != null) {

+                StringBuilder newURL = new StringBuilder();

+                ContentUrlTag.appendContentPrefix(request, newURL);

+                newURL.append(src);

+                writer.append(newURL.toString());

+            }

+        } else {

+            writer.append(src);

+        }

+

+        writer.append("\"/>");

+

+        appendWhitespace(writer);

+    }

+

+    public void renderContentBegin(Appendable writer, Map<String, Object> context, Content content) throws IOException {

+        String editRequest = content.getEditRequest(context);

+        String editContainerStyle = content.getEditContainerStyle(context);

+        String enableEditName = content.getEnableEditName(context);

+        String enableEditValue = (String)context.get(enableEditName);

+

+        if (Debug.verboseOn()) Debug.logVerbose("directEditRequest:" + editRequest, module);

+

+        if (UtilValidate.isNotEmpty(editRequest) && "true".equals(enableEditValue)) {

+            writer.append("<div");

+            writer.append(" class=\"").append(editContainerStyle).append("\"> ");

+            appendWhitespace(writer);

+        }

+    }

+

+    public void renderContentBody(Appendable writer, Map<String, Object> context, Content content) throws IOException {

+        Locale locale = UtilMisc.ensureLocale(context.get("locale"));

+        //Boolean nullThruDatesOnly = Boolean.valueOf(false);

+        String mimeTypeId = "text/html";

+        String expandedContentId = content.getContentId(context);

+        String expandedDataResourceId = content.getDataResourceId(context);

+        String renderedContent = null;

+        LocalDispatcher dispatcher = (LocalDispatcher) context.get("dispatcher");

+        Delegator delegator = (Delegator) context.get("delegator");

+

+        // make a new map for content rendering; so our current map does not get clobbered

+        Map<String, Object> contentContext = new HashMap<String, Object>();

+        contentContext.putAll(context);

+        String dataResourceId = (String)contentContext.get("dataResourceId");

+        if (Debug.verboseOn()) Debug.logVerbose("expandedContentId:" + expandedContentId, module);

+

+        try {

+            if (UtilValidate.isNotEmpty(dataResourceId)) {

+                if (WidgetDataResourceWorker.dataresourceWorker != null) {

+                    renderedContent = WidgetDataResourceWorker.dataresourceWorker.renderDataResourceAsTextExt(delegator, dataResourceId, contentContext, locale, mimeTypeId, false);

+                } else {

+                    Debug.logError("Not rendering content, WidgetDataResourceWorker.dataresourceWorker not found.", module);

+                }

+            } else if (UtilValidate.isNotEmpty(expandedContentId)) {

+                if (WidgetContentWorker.contentWorker != null) {

+                    renderedContent = WidgetContentWorker.contentWorker.renderContentAsTextExt(dispatcher, delegator, expandedContentId, contentContext, locale, mimeTypeId, true);

+                } else {

+                    Debug.logError("Not rendering content, WidgetContentWorker.contentWorker not found.", module);

+                }

+            } else if (UtilValidate.isNotEmpty(expandedDataResourceId)) {

+                if (WidgetDataResourceWorker.dataresourceWorker != null) {

+                    renderedContent = WidgetDataResourceWorker.dataresourceWorker.renderDataResourceAsTextExt(delegator, expandedDataResourceId, contentContext, locale, mimeTypeId, false);

+                } else {

+                    Debug.logError("Not rendering content, WidgetDataResourceWorker.dataresourceWorker not found.", module);

+                }

+            }

+            if (UtilValidate.isEmpty(renderedContent)) {

+                String editRequest = content.getEditRequest(context);

+                if (UtilValidate.isNotEmpty(editRequest)) {

+                    if (WidgetContentWorker.contentWorker != null) {

+                        WidgetContentWorker.contentWorker.renderContentAsTextExt(dispatcher, delegator, "NOCONTENTFOUND", writer, contentContext, locale, mimeTypeId, true);

+                    } else {

+                        Debug.logError("Not rendering content, WidgetContentWorker.contentWorker not found.", module);

+                    }

+                }

+            } else {

+                if (content.xmlEscape()) {

+                    renderedContent = UtilFormatOut.encodeXmlValue(renderedContent);

+                }

+

+                writer.append(renderedContent);

+            }

+

+        } catch (GeneralException e) {

+            String errMsg = "Error rendering included content with id [" + expandedContentId + "] : " + e.toString();

+            Debug.logError(e, errMsg, module);

+            //throw new RuntimeException(errMsg);

+        } catch (IOException e2) {

+            String errMsg = "Error rendering included content with id [" + expandedContentId + "] : " + e2.toString();

+            Debug.logError(e2, errMsg, module);

+            //throw new RuntimeException(errMsg);

+        }

+    }

+

+    public void renderContentEnd(Appendable writer, Map<String, Object> context, Content content) throws IOException {

+

+                //Debug.logInfo("renderContentEnd, context:" + context, module);

+        String expandedContentId = content.getContentId(context);

+        String editMode = "Edit";

+        String editRequest = content.getEditRequest(context);

+        String editContainerStyle = content.getEditContainerStyle(context);

+        String enableEditName = content.getEnableEditName(context);

+        String enableEditValue = (String)context.get(enableEditName);

+        if (editRequest != null && editRequest.toUpperCase().indexOf("IMAGE") > 0) {

+            editMode += " Image";

+        }

+        //String editRequestWithParams = editRequest + "?contentId=${currentValue.contentId}&drDataResourceId=${currentValue.drDataResourceId}&directEditRequest=${directEditRequest}&indirectEditRequest=${indirectEditRequest}&caContentIdTo=${currentValue.caContentIdTo}&caFromDate=${currentValue.caFromDate}&caContentAssocTypeId=${currentValue.caContentAssocTypeId}";

+

+        if (UtilValidate.isNotEmpty(editRequest) && "true".equals(enableEditValue)) {

+            HttpServletResponse response = (HttpServletResponse) context.get("response");

+            HttpServletRequest request = (HttpServletRequest) context.get("request");

+            if (request != null && response != null) {

+                if (editRequest.indexOf("?") < 0)  editRequest += "?";

+                else editRequest += "&amp;";

+                editRequest += "contentId=" + expandedContentId;

+                ServletContext ctx = (ServletContext) request.getAttribute("servletContext");

+                RequestHandler rh = (RequestHandler) ctx.getAttribute("_REQUEST_HANDLER_");

+                writer.append("<a href=\"").append(rh.makeLink(request, response, editRequest, false, false, false)).append("\">").append(editMode).append("</a>");

+            }

+            if (UtilValidate.isNotEmpty(editContainerStyle)) {

+                writer.append("</div>");

+            }

+            appendWhitespace(writer);

+        }

+    }

+

+    public void renderContentFrame(Appendable writer, Map<String, Object> context, Content content) throws IOException {

+

+

+        HttpServletRequest request = (HttpServletRequest) context.get("request");

+        HttpServletResponse response = (HttpServletResponse) context.get("response");

+        if (request != null && response != null) {

+            ServletContext ctx = (ServletContext) request.getAttribute("servletContext");

+            RequestHandler rh = (RequestHandler) ctx.getAttribute("_REQUEST_HANDLER_");

+            String dataResourceId = content.getDataResourceId(context);

+//          String urlString = "/content/control/ViewSimpleContent?dataResourceId=" + dataResourceId;

+            String urlString = "/ViewSimpleContent?dataResourceId=" + dataResourceId;

+

+            writer.append("<iframe src=\"").append(rh.makeLink(request, response, urlString, true, false, false)).append("\" ");

+            writer.append(" width=\"").append(content.getWidth()).append("\"");

+            writer.append(" height=\"").append(content.getHeight()).append("\"");

+            String border = content.getBorder();

+            if (UtilValidate.isNotEmpty(border)) {

+                writer.append(" border=\"").append(border).append("\"");

+            }

+            writer.append(" />");

+        }

+

+    }

+

+    public void renderSubContentBegin(Appendable writer, Map<String, Object> context, SubContent content) throws IOException {

+

+        String editRequest = content.getEditRequest(context);

+        String editContainerStyle = content.getEditContainerStyle(context);

+        String enableEditName = content.getEnableEditName(context);

+        String enableEditValue = (String)context.get(enableEditName);

+        if (UtilValidate.isNotEmpty(editRequest) && "true".equals(enableEditValue)) {

+            writer.append("<div");

+            writer.append(" class=\"").append(editContainerStyle).append("\"> ");

+

+            appendWhitespace(writer);

+        }

+    }

+

+    public void renderSubContentBody(Appendable writer, Map<String, Object> context, SubContent content) throws IOException {

+            Locale locale = Locale.getDefault();

+            String mimeTypeId = "text/html";

+            String expandedContentId = content.getContentId(context);

+            String expandedMapKey = content.getMapKey(context);

+            String renderedContent = null;

+            LocalDispatcher dispatcher = (LocalDispatcher) context.get("dispatcher");

+            Delegator delegator = (Delegator) context.get("delegator");

+

+            // create a new map for the content rendering; so our current context does not get overwritten!

+            Map<String, Object> contentContext = new HashMap<String, Object>();

+            contentContext.putAll(context);

+

+            try {

+                if (WidgetContentWorker.contentWorker != null) {

+                    renderedContent = WidgetContentWorker.contentWorker.renderSubContentAsTextExt(dispatcher, delegator, expandedContentId, expandedMapKey, contentContext, locale, mimeTypeId, true);

+                    //Debug.logInfo("renderedContent=" + renderedContent, module);

+                } else {

+                    Debug.logError("Not rendering content, WidgetContentWorker.contentWorker not found.", module);

+                }

+                if (UtilValidate.isEmpty(renderedContent)) {

+                    String editRequest = content.getEditRequest(context);

+                    if (UtilValidate.isNotEmpty(editRequest)) {

+                        if (WidgetContentWorker.contentWorker != null) {

+                            WidgetContentWorker.contentWorker.renderContentAsTextExt(dispatcher, delegator, "NOCONTENTFOUND", writer, contentContext, locale, mimeTypeId, true);

+                        } else {

+                            Debug.logError("Not rendering content, WidgetContentWorker.contentWorker not found.", module);

+                        }

+                    }

+                } else {

+                    if (content.xmlEscape()) {

+                        renderedContent = UtilFormatOut.encodeXmlValue(renderedContent);

+                    }

+

+                    writer.append(renderedContent);

+                }

+

+            } catch (GeneralException e) {

+                String errMsg = "Error rendering included content with id [" + expandedContentId + "] : " + e.toString();

+                Debug.logError(e, errMsg, module);

+                //throw new RuntimeException(errMsg);

+            } catch (IOException e2) {

+                String errMsg = "Error rendering included content with id [" + expandedContentId + "] : " + e2.toString();

+                Debug.logError(e2, errMsg, module);

+                //throw new RuntimeException(errMsg);

+            }

+    }

+

+    public void renderSubContentEnd(Appendable writer, Map<String, Object> context, SubContent content) throws IOException {

+

+        String editMode = "Edit";

+        String editRequest = content.getEditRequest(context);

+        String editContainerStyle = content.getEditContainerStyle(context);

+        String enableEditName = content.getEnableEditName(context);

+        String enableEditValue = (String)context.get(enableEditName);

+        String expandedContentId = content.getContentId(context);

+        String expandedMapKey = content.getMapKey(context);

+        if (editRequest != null && editRequest.toUpperCase().indexOf("IMAGE") > 0) {

+            editMode += " Image";

+        }

+        if (UtilValidate.isNotEmpty(editRequest) && "true".equals(enableEditValue)) {

+            HttpServletResponse response = (HttpServletResponse) context.get("response");

+            HttpServletRequest request = (HttpServletRequest) context.get("request");

+            if (request != null && response != null) {

+                if (editRequest.indexOf("?") < 0)  editRequest += "?";

+                else editRequest += "&amp;";

+                editRequest += "contentId=" + expandedContentId;

+                if (UtilValidate.isNotEmpty(expandedMapKey)) {

+                    editRequest += "&amp;mapKey=" + expandedMapKey;

+                }

+                //HttpSession session = request.getSession();

+                //GenericValue userLogin = (GenericValue)session.getAttribute("userLogin");

+                /* don't know why this is here. might come to me later. -amb

+                Delegator delegator = (Delegator)request.getAttribute("delegator");

+                String contentIdTo = content.getContentId(context);

+                String mapKey = content.getAssocName(context);

+                GenericValue view = null;

+                try {

+                    view = ContentWorker.getSubContentCache(delegator, contentIdTo, mapKey, userLogin, null, UtilDateTime.nowTimestamp(), Boolean.valueOf(false), null);

+                } catch (GenericEntityException e) {

+                    throw new IOException("Originally a GenericEntityException. " + e.getMessage());

+                }

+                */

+                ServletContext ctx = (ServletContext) request.getAttribute("servletContext");

+                RequestHandler rh = (RequestHandler) ctx.getAttribute("_REQUEST_HANDLER_");

+                writer.append("<a href=\"").append(rh.makeLink(request, response, editRequest, false, false, false)).append("\">").append(editMode).append("</a>");

+            }

+            if (UtilValidate.isNotEmpty(editContainerStyle)) {

+                writer.append("</div>");

+            }

+            appendWhitespace(writer);

+        }

+    }

+

+    public void renderPortalPageBegin(Appendable writer, Map<String, Object> context, PortalPage portalPage) throws GeneralException, IOException {

+        // TODO: not implemented

+    }

+    public void renderPortalPageEnd(Appendable writer, Map<String, Object> context, PortalPage portalPage) throws GeneralException, IOException {

+        // TODO: not implemented

+    }

+    public void renderPortalPageColumnBegin(Appendable writer, Map<String, Object> context, PortalPage portalPage, GenericValue portalPageColumn) throws GeneralException, IOException {

+        // TODO: not implemented

+    }

+    public void renderPortalPageColumnEnd(Appendable writer, Map<String, Object> context, PortalPage portalPage, GenericValue portalPageColumn) throws GeneralException, IOException {

+        // TODO: not implemented

+    }

+    public void renderPortalPagePortletBegin(Appendable writer, Map<String, Object> context, PortalPage portalPage, GenericValue portalPortlet) throws GeneralException, IOException {

+        // TODO: not implemented

+    }

+    public void renderPortalPagePortletEnd(Appendable writer, Map<String, Object> context, PortalPage portalPage, GenericValue portalPortlet) throws GeneralException, IOException {

+        // TODO: not implemented

+    }

+    public void renderPortalPagePortletBody(Appendable writer, Map<String, Object> context, PortalPage portalPage, GenericValue portalPortlet) throws GeneralException, IOException {

+        // TODO: not implemented

+    }

+

+    @Override

+    public void renderColumnContainer(Appendable writer, Map<String, Object> context, ColumnContainer columnContainer) throws IOException {

+        // TODO: not implemented

+    }

+}

diff --git a/framework/widget/src/org/ofbiz/widget/html/HtmlTreeRenderer.java b/framework/widget/src/org/ofbiz/widget/renderer/html/HtmlTreeRenderer.java
similarity index 97%
rename from framework/widget/src/org/ofbiz/widget/html/HtmlTreeRenderer.java
rename to framework/widget/src/org/ofbiz/widget/renderer/html/HtmlTreeRenderer.java
index d3a3d4a..ba509a5 100644
--- a/framework/widget/src/org/ofbiz/widget/html/HtmlTreeRenderer.java
+++ b/framework/widget/src/org/ofbiz/widget/renderer/html/HtmlTreeRenderer.java
@@ -1,342 +1,342 @@
-/*******************************************************************************
- * 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.html;
-
-import java.io.IOException;
-import java.util.List;
-import java.util.Map;
-
-import javax.servlet.ServletContext;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.ofbiz.base.util.StringUtil;
-import org.ofbiz.base.util.UtilGenerics;
-import org.ofbiz.base.util.UtilValidate;
-import org.ofbiz.webapp.control.RequestHandler;
-import org.ofbiz.webapp.taglib.ContentUrlTag;
-import org.ofbiz.widget.ModelWidget;
-import org.ofbiz.widget.WidgetWorker;
-import org.ofbiz.widget.screen.ScreenRenderer;
-import org.ofbiz.widget.screen.ScreenStringRenderer;
-import org.ofbiz.widget.tree.ModelTree;
-import org.ofbiz.widget.tree.TreeStringRenderer;
-
-
-/**
- * Widget Library - HTML Tree Renderer implementation
- */
-public class HtmlTreeRenderer extends HtmlWidgetRenderer implements TreeStringRenderer {
-
-    ScreenStringRenderer screenStringRenderer = null;
-    public static final String module = HtmlTreeRenderer.class.getName();
-
-    public HtmlTreeRenderer() {}
-
-    public void renderNodeBegin(Appendable writer, Map<String, Object> context, ModelTree.ModelNode node, int depth) throws IOException {
-        String currentNodeTrailPiped = null;
-        List<String> currentNodeTrail = UtilGenerics.toList(context.get("currentNodeTrail"));
-        if (node.isRootNode()) {
-            appendWhitespace(writer);
-            this.widgetCommentsEnabled = ModelWidget.widgetBoundaryCommentsEnabled(context);
-            renderBeginningBoundaryComment(writer, "Tree Widget", node.getModelTree());
-            writer.append("<ul class=\"basic-tree\">");
-        }
-        appendWhitespace(writer);
-        writer.append("<li>");
-
-        String pkName = node.getPkName(context);
-        String entityId = null;
-        String entryName = node.getEntryName();
-        if (UtilValidate.isNotEmpty(entryName)) {
-            entityId = UtilGenerics.<Map<String, String>>cast(context.get(entryName)).get(pkName);
-        } else {
-            entityId = (String) context.get(pkName);
-        }
-        boolean hasChildren = node.hasChildren(context);
-
-        // check to see if this node needs to be expanded.
-        if (hasChildren && node.isExpandCollapse()) {
-            String targetEntityId = null;
-            List<String> targetNodeTrail = UtilGenerics.toList(context.get("targetNodeTrail"));
-            if (depth < targetNodeTrail.size()) {
-                targetEntityId = targetNodeTrail.get(depth);
-            }
-            // FIXME: Using a widget model in this way is an ugly hack.
-            ModelTree.ModelNode.Link expandCollapseLink = null;
-            int openDepth = node.getModelTree().getOpenDepth();
-            if (depth >= openDepth && (targetEntityId == null || !targetEntityId.equals(entityId))) {
-                // Not on the trail
-                if (node.showPeers(depth, context)) {
-                    context.put("processChildren", Boolean.FALSE);
-                    //expandCollapseLink.setText("&nbsp;+&nbsp;");
-                    currentNodeTrailPiped = StringUtil.join(currentNodeTrail, "|");
-                    StringBuilder target = new StringBuilder(node.getModelTree().getExpandCollapseRequest(context));
-                    String trailName = node.getModelTree().getTrailName(context);
-                    if (target.indexOf("?") < 0) {
-                        target.append("?");
-                    } else {
-                        target.append("&");
-                    }
-                    target.append(trailName).append("=").append(currentNodeTrailPiped);
-                    expandCollapseLink = new ModelTree.ModelNode.Link("collapsed", target.toString(), " ");
-                }
-            } else {
-                context.put("processChildren", Boolean.TRUE);
-                //expandCollapseLink.setText("&nbsp;-&nbsp;");
-                String lastContentId = currentNodeTrail.remove(currentNodeTrail.size() - 1);
-                currentNodeTrailPiped = StringUtil.join(currentNodeTrail, "|");
-                if (currentNodeTrailPiped == null) {
-                    currentNodeTrailPiped = "";
-                }
-                StringBuilder target = new StringBuilder(node.getModelTree().getExpandCollapseRequest(context));
-                String trailName = node.getModelTree().getTrailName(context);
-                if (target.indexOf("?") < 0) {
-                    target.append("?");
-                } else {
-                    target.append("&");
-                }
-                target.append(trailName).append("=").append(currentNodeTrailPiped);
-                expandCollapseLink = new ModelTree.ModelNode.Link("expanded", target.toString(), " ");
-                // add it so it can be remove in renderNodeEnd
-                currentNodeTrail.add(lastContentId);
-            }
-            if (expandCollapseLink != null) {
-                renderLink(writer, context, expandCollapseLink);
-            }
-        } else if (!hasChildren) {
-            context.put("processChildren", Boolean.FALSE);
-            ModelTree.ModelNode.Link expandCollapseLink = new ModelTree.ModelNode.Link("leafnode", "", " ");
-            renderLink(writer, context, expandCollapseLink);
-        }
-    }
-
-    public void renderNodeEnd(Appendable writer, Map<String, Object> context, ModelTree.ModelNode node) throws IOException {
-        Boolean processChildren = (Boolean) context.get("processChildren");
-        if (processChildren.booleanValue()) {
-            appendWhitespace(writer);
-            writer.append("</ul>");
-        }
-        appendWhitespace(writer);
-        writer.append("</li>");
-        if (node.isRootNode()) {
-            appendWhitespace(writer);
-            writer.append("</ul>");
-            appendWhitespace(writer);
-            renderEndingBoundaryComment(writer, "Tree Widget", node.getModelTree());
-        }
-    }
-
-    public void renderLastElement(Appendable writer, Map<String, Object> context, ModelTree.ModelNode node) throws IOException {
-        Boolean processChildren = (Boolean) context.get("processChildren");
-        if (processChildren.booleanValue()) {
-            appendWhitespace(writer);
-            writer.append("<ul class=\"basic-tree\">");
-        }
-    }
-
-    public void renderLabel(Appendable writer, Map<String, Object> context, ModelTree.ModelNode.Label label) throws IOException {
-        // open tag
-        writer.append("<span");
-        String id = label.getId(context);
-        if (UtilValidate.isNotEmpty(id)) {
-            writer.append(" id=\"");
-            writer.append(id);
-            writer.append("\"");
-        }
-        String style = label.getStyle(context);
-        if (UtilValidate.isNotEmpty(style)) {
-            writer.append(" class=\"");
-            writer.append(style);
-            writer.append("\"");
-        }
-        writer.append(">");
-
-        // the text
-        writer.append(label.getText(context));
-
-        // close tag
-        writer.append("</span>");
-
-        appendWhitespace(writer);
-    }
-
-
-    public void renderLink(Appendable writer, Map<String, Object> context, ModelTree.ModelNode.Link link) throws IOException {
-        // open tag
-        writer.append("<a");
-        String id = link.getId(context);
-        if (UtilValidate.isNotEmpty(id)) {
-            writer.append(" id=\"");
-            writer.append(id);
-            writer.append("\"");
-        }
-        String style = link.getStyle(context);
-        if (UtilValidate.isNotEmpty(style)) {
-            writer.append(" class=\"");
-            writer.append(style);
-            writer.append("\"");
-        }
-        String name = link.getName(context);
-        if (UtilValidate.isNotEmpty(name)) {
-            writer.append(" name=\"");
-            writer.append(name);
-            writer.append("\"");
-        }
-        String title = link.getTitle(context);
-        if (UtilValidate.isNotEmpty(title)) {
-            writer.append(" title=\"");
-            writer.append(title);
-            writer.append("\"");
-        }
-        String targetWindow = link.getTargetWindow(context);
-        if (UtilValidate.isNotEmpty(targetWindow)) {
-            writer.append(" target=\"");
-            writer.append(targetWindow);
-            writer.append("\"");
-        }
-        String target = link.getTarget(context);
-        if (UtilValidate.isNotEmpty(target)) {
-            writer.append(" href=\"");
-            String urlMode = link.getUrlMode();
-            String prefix = link.getPrefix(context);
-            HttpServletResponse res = (HttpServletResponse) context.get("response");
-            HttpServletRequest req = (HttpServletRequest) context.get("request");
-            if (urlMode != null && urlMode.equalsIgnoreCase("intra-app")) {
-                if (req != null && res != null) {
-                    WidgetWorker.buildHyperlinkUrl(writer, target, link.getUrlMode(), link.getParameterMap(context), link.getPrefix(context),
-                        link.getFullPath(), link.getSecure(), link.getEncode(), req, res, context);
-                } else if (prefix != null) {
-                    writer.append(prefix).append(target);
-                } else {
-                    writer.append(target);
-                }
-            } else if (urlMode != null && urlMode.equalsIgnoreCase("content")) {
-                StringBuilder newURL = new StringBuilder();
-                ContentUrlTag.appendContentPrefix(req, newURL);
-                newURL.append(target);
-                writer.append(newURL.toString());
-            } else if ("inter-app".equalsIgnoreCase(urlMode) && req != null) {
-                String externalLoginKey = (String) req.getAttribute("externalLoginKey");
-                if (UtilValidate.isNotEmpty(externalLoginKey)) {
-                    writer.append(target);
-                    if (target.contains("?")) {
-                        writer.append("&externalLoginKey=");
-                    } else {
-                        writer.append("?externalLoginKey=");
-                    }
-                    writer.append(externalLoginKey);
-                }
-            } else {
-                writer.append(target);
-            }
-            writer.append("\"");
-        }
-        writer.append(">");
-
-        // the text
-        ModelTree.ModelNode.Image img = link.getImage();
-        if (img == null) {
-            writer.append(link.getText(context));
-        } else {
-            renderImage(writer, context, img);
-        }
-        // close tag
-        writer.append("</a>");
-    }
-
-    public void renderImage(Appendable writer, Map<String, Object> context, ModelTree.ModelNode.Image image) throws IOException {
-        // open tag
-        writer.append("<img ");
-        String id = image.getId(context);
-        if (UtilValidate.isNotEmpty(id)) {
-            writer.append(" id=\"");
-            writer.append(id);
-            writer.append("\"");
-        }
-        String style = image.getStyle(context);
-        if (UtilValidate.isNotEmpty(style)) {
-            writer.append(" class=\"");
-            writer.append(style);
-            writer.append("\"");
-        }
-        String wid = image.getWidth(context);
-        if (UtilValidate.isNotEmpty(wid)) {
-            writer.append(" width=\"");
-            writer.append(wid);
-            writer.append("\"");
-        }
-        String hgt = image.getHeight(context);
-        if (UtilValidate.isNotEmpty(hgt)) {
-            writer.append(" height=\"");
-            writer.append(hgt);
-            writer.append("\"");
-        }
-        String border = image.getBorder(context);
-        if (UtilValidate.isNotEmpty(border)) {
-            writer.append(" border=\"");
-            writer.append(border);
-            writer.append("\"");
-        }
-        String src = image.getSrc(context);
-        if (UtilValidate.isNotEmpty(src)) {
-            writer.append(" src=\"");
-            String urlMode = image.getUrlMode();
-            boolean fullPath = false;
-            boolean secure = false;
-            boolean encode = false;
-            HttpServletResponse response = (HttpServletResponse) context.get("response");
-            HttpServletRequest request = (HttpServletRequest) context.get("request");
-            if (urlMode != null && urlMode.equalsIgnoreCase("intra-app")) {
-                if (request != null && response != null) {
-                    ServletContext ctx = (ServletContext) request.getAttribute("servletContext");
-                    RequestHandler rh = (RequestHandler) ctx.getAttribute("_REQUEST_HANDLER_");
-                    String urlString = rh.makeLink(request, response, src, fullPath, secure, encode);
-                    writer.append(urlString);
-                } else {
-                    writer.append(src);
-                }
-            } else  if (urlMode != null && urlMode.equalsIgnoreCase("content")) {
-                if (request != null && response != null) {
-                    StringBuilder newURL = new StringBuilder();
-                    ContentUrlTag.appendContentPrefix(request, newURL);
-                    newURL.append(src);
-                    writer.append(newURL.toString());
-                }
-            } else {
-                writer.append(src);
-            }
-            writer.append("\"");
-        }
-        writer.append("/>");
-
-    }
-
-    public ScreenStringRenderer getScreenStringRenderer(Map<String, Object> context) {
-        ScreenRenderer screenRenderer = (ScreenRenderer)context.get("screens");
-        if (screenRenderer != null) {
-            screenStringRenderer = screenRenderer.getScreenStringRenderer();
-        } else {
-            if (screenStringRenderer == null) {
-                screenStringRenderer = new HtmlScreenRenderer();
-            }
-        }
-        return screenStringRenderer;
-    }
-}
+/*******************************************************************************

+ * 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.renderer.html;

+

+import java.io.IOException;

+import java.util.List;

+import java.util.Map;

+

+import javax.servlet.ServletContext;

+import javax.servlet.http.HttpServletRequest;

+import javax.servlet.http.HttpServletResponse;

+

+import org.ofbiz.base.util.StringUtil;

+import org.ofbiz.base.util.UtilGenerics;

+import org.ofbiz.base.util.UtilValidate;

+import org.ofbiz.webapp.control.RequestHandler;

+import org.ofbiz.webapp.taglib.ContentUrlTag;

+import org.ofbiz.widget.WidgetWorker;

+import org.ofbiz.widget.model.ModelTree;

+import org.ofbiz.widget.model.ModelWidget;

+import org.ofbiz.widget.renderer.ScreenRenderer;

+import org.ofbiz.widget.renderer.ScreenStringRenderer;

+import org.ofbiz.widget.renderer.TreeStringRenderer;

+

+

+/**

+ * Widget Library - HTML Tree Renderer implementation

+ */

+public class HtmlTreeRenderer extends HtmlWidgetRenderer implements TreeStringRenderer {

+

+    ScreenStringRenderer screenStringRenderer = null;

+    public static final String module = HtmlTreeRenderer.class.getName();

+

+    public HtmlTreeRenderer() {}

+

+    public void renderNodeBegin(Appendable writer, Map<String, Object> context, ModelTree.ModelNode node, int depth) throws IOException {

+        String currentNodeTrailPiped = null;

+        List<String> currentNodeTrail = UtilGenerics.toList(context.get("currentNodeTrail"));

+        if (node.isRootNode()) {

+            appendWhitespace(writer);

+            this.widgetCommentsEnabled = ModelWidget.widgetBoundaryCommentsEnabled(context);

+            renderBeginningBoundaryComment(writer, "Tree Widget", node.getModelTree());

+            writer.append("<ul class=\"basic-tree\">");

+        }

+        appendWhitespace(writer);

+        writer.append("<li>");

+

+        String pkName = node.getPkName(context);

+        String entityId = null;

+        String entryName = node.getEntryName();

+        if (UtilValidate.isNotEmpty(entryName)) {

+            entityId = UtilGenerics.<Map<String, String>>cast(context.get(entryName)).get(pkName);

+        } else {

+            entityId = (String) context.get(pkName);

+        }

+        boolean hasChildren = node.hasChildren(context);

+

+        // check to see if this node needs to be expanded.

+        if (hasChildren && node.isExpandCollapse()) {

+            String targetEntityId = null;

+            List<String> targetNodeTrail = UtilGenerics.toList(context.get("targetNodeTrail"));

+            if (depth < targetNodeTrail.size()) {

+                targetEntityId = targetNodeTrail.get(depth);

+            }

+            // FIXME: Using a widget model in this way is an ugly hack.

+            ModelTree.ModelNode.Link expandCollapseLink = null;

+            int openDepth = node.getModelTree().getOpenDepth();

+            if (depth >= openDepth && (targetEntityId == null || !targetEntityId.equals(entityId))) {

+                // Not on the trail

+                if (node.showPeers(depth, context)) {

+                    context.put("processChildren", Boolean.FALSE);

+                    //expandCollapseLink.setText("&nbsp;+&nbsp;");

+                    currentNodeTrailPiped = StringUtil.join(currentNodeTrail, "|");

+                    StringBuilder target = new StringBuilder(node.getModelTree().getExpandCollapseRequest(context));

+                    String trailName = node.getModelTree().getTrailName(context);

+                    if (target.indexOf("?") < 0) {

+                        target.append("?");

+                    } else {

+                        target.append("&");

+                    }

+                    target.append(trailName).append("=").append(currentNodeTrailPiped);

+                    expandCollapseLink = new ModelTree.ModelNode.Link("collapsed", target.toString(), " ");

+                }

+            } else {

+                context.put("processChildren", Boolean.TRUE);

+                //expandCollapseLink.setText("&nbsp;-&nbsp;");

+                String lastContentId = currentNodeTrail.remove(currentNodeTrail.size() - 1);

+                currentNodeTrailPiped = StringUtil.join(currentNodeTrail, "|");

+                if (currentNodeTrailPiped == null) {

+                    currentNodeTrailPiped = "";

+                }

+                StringBuilder target = new StringBuilder(node.getModelTree().getExpandCollapseRequest(context));

+                String trailName = node.getModelTree().getTrailName(context);

+                if (target.indexOf("?") < 0) {

+                    target.append("?");

+                } else {

+                    target.append("&");

+                }

+                target.append(trailName).append("=").append(currentNodeTrailPiped);

+                expandCollapseLink = new ModelTree.ModelNode.Link("expanded", target.toString(), " ");

+                // add it so it can be remove in renderNodeEnd

+                currentNodeTrail.add(lastContentId);

+            }

+            if (expandCollapseLink != null) {

+                renderLink(writer, context, expandCollapseLink);

+            }

+        } else if (!hasChildren) {

+            context.put("processChildren", Boolean.FALSE);

+            ModelTree.ModelNode.Link expandCollapseLink = new ModelTree.ModelNode.Link("leafnode", "", " ");

+            renderLink(writer, context, expandCollapseLink);

+        }

+    }

+

+    public void renderNodeEnd(Appendable writer, Map<String, Object> context, ModelTree.ModelNode node) throws IOException {

+        Boolean processChildren = (Boolean) context.get("processChildren");

+        if (processChildren.booleanValue()) {

+            appendWhitespace(writer);

+            writer.append("</ul>");

+        }

+        appendWhitespace(writer);

+        writer.append("</li>");

+        if (node.isRootNode()) {

+            appendWhitespace(writer);

+            writer.append("</ul>");

+            appendWhitespace(writer);

+            renderEndingBoundaryComment(writer, "Tree Widget", node.getModelTree());

+        }

+    }

+

+    public void renderLastElement(Appendable writer, Map<String, Object> context, ModelTree.ModelNode node) throws IOException {

+        Boolean processChildren = (Boolean) context.get("processChildren");

+        if (processChildren.booleanValue()) {

+            appendWhitespace(writer);

+            writer.append("<ul class=\"basic-tree\">");

+        }

+    }

+

+    public void renderLabel(Appendable writer, Map<String, Object> context, ModelTree.ModelNode.Label label) throws IOException {

+        // open tag

+        writer.append("<span");

+        String id = label.getId(context);

+        if (UtilValidate.isNotEmpty(id)) {

+            writer.append(" id=\"");

+            writer.append(id);

+            writer.append("\"");

+        }

+        String style = label.getStyle(context);

+        if (UtilValidate.isNotEmpty(style)) {

+            writer.append(" class=\"");

+            writer.append(style);

+            writer.append("\"");

+        }

+        writer.append(">");

+

+        // the text

+        writer.append(label.getText(context));

+

+        // close tag

+        writer.append("</span>");

+

+        appendWhitespace(writer);

+    }

+

+

+    public void renderLink(Appendable writer, Map<String, Object> context, ModelTree.ModelNode.Link link) throws IOException {

+        // open tag

+        writer.append("<a");

+        String id = link.getId(context);

+        if (UtilValidate.isNotEmpty(id)) {

+            writer.append(" id=\"");

+            writer.append(id);

+            writer.append("\"");

+        }

+        String style = link.getStyle(context);

+        if (UtilValidate.isNotEmpty(style)) {

+            writer.append(" class=\"");

+            writer.append(style);

+            writer.append("\"");

+        }

+        String name = link.getName(context);

+        if (UtilValidate.isNotEmpty(name)) {

+            writer.append(" name=\"");

+            writer.append(name);

+            writer.append("\"");

+        }

+        String title = link.getTitle(context);

+        if (UtilValidate.isNotEmpty(title)) {

+            writer.append(" title=\"");

+            writer.append(title);

+            writer.append("\"");

+        }

+        String targetWindow = link.getTargetWindow(context);

+        if (UtilValidate.isNotEmpty(targetWindow)) {

+            writer.append(" target=\"");

+            writer.append(targetWindow);

+            writer.append("\"");

+        }

+        String target = link.getTarget(context);

+        if (UtilValidate.isNotEmpty(target)) {

+            writer.append(" href=\"");

+            String urlMode = link.getUrlMode();

+            String prefix = link.getPrefix(context);

+            HttpServletResponse res = (HttpServletResponse) context.get("response");

+            HttpServletRequest req = (HttpServletRequest) context.get("request");

+            if (urlMode != null && urlMode.equalsIgnoreCase("intra-app")) {

+                if (req != null && res != null) {

+                    WidgetWorker.buildHyperlinkUrl(writer, target, link.getUrlMode(), link.getParameterMap(context), link.getPrefix(context),

+                        link.getFullPath(), link.getSecure(), link.getEncode(), req, res, context);

+                } else if (prefix != null) {

+                    writer.append(prefix).append(target);

+                } else {

+                    writer.append(target);

+                }

+            } else if (urlMode != null && urlMode.equalsIgnoreCase("content")) {

+                StringBuilder newURL = new StringBuilder();

+                ContentUrlTag.appendContentPrefix(req, newURL);

+                newURL.append(target);

+                writer.append(newURL.toString());

+            } else if ("inter-app".equalsIgnoreCase(urlMode) && req != null) {

+                String externalLoginKey = (String) req.getAttribute("externalLoginKey");

+                if (UtilValidate.isNotEmpty(externalLoginKey)) {

+                    writer.append(target);

+                    if (target.contains("?")) {

+                        writer.append("&externalLoginKey=");

+                    } else {

+                        writer.append("?externalLoginKey=");

+                    }

+                    writer.append(externalLoginKey);

+                }

+            } else {

+                writer.append(target);

+            }

+            writer.append("\"");

+        }

+        writer.append(">");

+

+        // the text

+        ModelTree.ModelNode.Image img = link.getImage();

+        if (img == null) {

+            writer.append(link.getText(context));

+        } else {

+            renderImage(writer, context, img);

+        }

+        // close tag

+        writer.append("</a>");

+    }

+

+    public void renderImage(Appendable writer, Map<String, Object> context, ModelTree.ModelNode.Image image) throws IOException {

+        // open tag

+        writer.append("<img ");

+        String id = image.getId(context);

+        if (UtilValidate.isNotEmpty(id)) {

+            writer.append(" id=\"");

+            writer.append(id);

+            writer.append("\"");

+        }

+        String style = image.getStyle(context);

+        if (UtilValidate.isNotEmpty(style)) {

+            writer.append(" class=\"");

+            writer.append(style);

+            writer.append("\"");

+        }

+        String wid = image.getWidth(context);

+        if (UtilValidate.isNotEmpty(wid)) {

+            writer.append(" width=\"");

+            writer.append(wid);

+            writer.append("\"");

+        }

+        String hgt = image.getHeight(context);

+        if (UtilValidate.isNotEmpty(hgt)) {

+            writer.append(" height=\"");

+            writer.append(hgt);

+            writer.append("\"");

+        }

+        String border = image.getBorder(context);

+        if (UtilValidate.isNotEmpty(border)) {

+            writer.append(" border=\"");

+            writer.append(border);

+            writer.append("\"");

+        }

+        String src = image.getSrc(context);

+        if (UtilValidate.isNotEmpty(src)) {

+            writer.append(" src=\"");

+            String urlMode = image.getUrlMode();

+            boolean fullPath = false;

+            boolean secure = false;

+            boolean encode = false;

+            HttpServletResponse response = (HttpServletResponse) context.get("response");

+            HttpServletRequest request = (HttpServletRequest) context.get("request");

+            if (urlMode != null && urlMode.equalsIgnoreCase("intra-app")) {

+                if (request != null && response != null) {

+                    ServletContext ctx = (ServletContext) request.getAttribute("servletContext");

+                    RequestHandler rh = (RequestHandler) ctx.getAttribute("_REQUEST_HANDLER_");

+                    String urlString = rh.makeLink(request, response, src, fullPath, secure, encode);

+                    writer.append(urlString);

+                } else {

+                    writer.append(src);

+                }

+            } else  if (urlMode != null && urlMode.equalsIgnoreCase("content")) {

+                if (request != null && response != null) {

+                    StringBuilder newURL = new StringBuilder();

+                    ContentUrlTag.appendContentPrefix(request, newURL);

+                    newURL.append(src);

+                    writer.append(newURL.toString());

+                }

+            } else {

+                writer.append(src);

+            }

+            writer.append("\"");

+        }

+        writer.append("/>");

+

+    }

+

+    public ScreenStringRenderer getScreenStringRenderer(Map<String, Object> context) {

+        ScreenRenderer screenRenderer = (ScreenRenderer)context.get("screens");

+        if (screenRenderer != null) {

+            screenStringRenderer = screenRenderer.getScreenStringRenderer();

+        } else {

+            if (screenStringRenderer == null) {

+                screenStringRenderer = new HtmlScreenRenderer();

+            }

+        }

+        return screenStringRenderer;

+    }

+}

diff --git a/framework/widget/src/org/ofbiz/widget/html/HtmlWidgetRenderer.java b/framework/widget/src/org/ofbiz/widget/renderer/html/HtmlWidgetRenderer.java
similarity index 97%
rename from framework/widget/src/org/ofbiz/widget/html/HtmlWidgetRenderer.java
rename to framework/widget/src/org/ofbiz/widget/renderer/html/HtmlWidgetRenderer.java
index 21d7be1..b4a8e32 100644
--- a/framework/widget/src/org/ofbiz/widget/html/HtmlWidgetRenderer.java
+++ b/framework/widget/src/org/ofbiz/widget/renderer/html/HtmlWidgetRenderer.java
@@ -1,99 +1,99 @@
-/*******************************************************************************
- * 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.html;
-
-import java.io.IOException;
-
-import org.ofbiz.base.util.UtilHttp;
-import org.ofbiz.widget.ModelWidget;
-
-/**
- * Widget Library - HTML Widget Renderer implementation. HtmlWidgetRenderer
- * is a base class that is extended by other widget HTML rendering classes.
- */
-public class HtmlWidgetRenderer {
-    public static final String module = HtmlWidgetRenderer.class.getName();
-
-    /**
-     * Characters that are appended to the end of each rendered element. Currently set to
-     * CR/LF.
-     */
-    public static final String whiteSpace = "\r\n";
-
-    protected boolean widgetCommentsEnabled = false;
-
-    /**
-     * Helper method used to append whitespace characters to the end of each rendered element.
-     * @param writer The writer to write to
-     */
-    public void appendWhitespace(Appendable writer) throws IOException {
-        writer.append(whiteSpace);
-    }
-
-    /**
-     * Helper method used to build the boundary comment string.
-     * @param boundaryType The boundary type: "Begin" or "End"
-     * @param widgetType The widget type: "Screen Widget", "Form Widget", etc.
-     * @param widgetName The widget name
-     */
-    public String buildBoundaryComment(String boundaryType, String widgetType, String widgetName) {
-        return formatBoundaryComment(boundaryType, widgetType, widgetName);
-    }
-
-    public static String formatBoundaryComment(String boundaryType, String widgetType, String widgetName) {
-        return "<!-- " + boundaryType + " " + widgetType + " " + widgetName + " -->" + whiteSpace;
-    }
-
-    /**
-     * Renders the beginning boundary comment string.
-     * @param writer The writer to write to
-     * @param widgetType The widget type: "Screen Widget", "Form Widget", etc.
-     * @param modelWidget The widget
-     */
-    public void renderBeginningBoundaryComment(Appendable writer, String widgetType, ModelWidget modelWidget) throws IOException {
-        if (this.widgetCommentsEnabled) {
-            writer.append(this.buildBoundaryComment("Begin", widgetType, modelWidget.getBoundaryCommentName()));
-        }
-    }
-
-    /**
-     * Renders the ending boundary comment string.
-     * @param writer The writer to write to
-     * @param widgetType The widget type: "Screen Widget", "Form Widget", etc.
-     * @param modelWidget The widget
-     */
-    public void renderEndingBoundaryComment(Appendable writer, String widgetType, ModelWidget modelWidget) throws IOException {
-        if (this.widgetCommentsEnabled) {
-            writer.append(this.buildBoundaryComment("End", widgetType, modelWidget.getBoundaryCommentName()));
-        }
-    }
-
-    /** Extracts parameters from a target URL string, prepares them for an Ajax
-     * JavaScript call. This method is currently set to return a parameter string
-     * suitable for the Prototype.js library.
-     * @param target Target URL string
-     * @return Parameter string
-     */
-    public static String getAjaxParamsFromTarget(String target) {
-        String targetParams = UtilHttp.getQueryStringFromTarget(target);
-        targetParams = targetParams.replace("?", "");
-        targetParams = targetParams.replace("&amp;", "&");
-        return targetParams;
-    }
-}
+/*******************************************************************************

+ * 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.renderer.html;

+

+import java.io.IOException;

+

+import org.ofbiz.base.util.UtilHttp;

+import org.ofbiz.widget.model.ModelWidget;

+

+/**

+ * Widget Library - HTML Widget Renderer implementation. HtmlWidgetRenderer

+ * is a base class that is extended by other widget HTML rendering classes.

+ */

+public class HtmlWidgetRenderer {

+    public static final String module = HtmlWidgetRenderer.class.getName();

+

+    /**

+     * Characters that are appended to the end of each rendered element. Currently set to

+     * CR/LF.

+     */

+    public static final String whiteSpace = "\r\n";

+

+    protected boolean widgetCommentsEnabled = false;

+

+    /**

+     * Helper method used to append whitespace characters to the end of each rendered element.

+     * @param writer The writer to write to

+     */

+    public void appendWhitespace(Appendable writer) throws IOException {

+        writer.append(whiteSpace);

+    }

+

+    /**

+     * Helper method used to build the boundary comment string.

+     * @param boundaryType The boundary type: "Begin" or "End"

+     * @param widgetType The widget type: "Screen Widget", "Form Widget", etc.

+     * @param widgetName The widget name

+     */

+    public String buildBoundaryComment(String boundaryType, String widgetType, String widgetName) {

+        return formatBoundaryComment(boundaryType, widgetType, widgetName);

+    }

+

+    public static String formatBoundaryComment(String boundaryType, String widgetType, String widgetName) {

+        return "<!-- " + boundaryType + " " + widgetType + " " + widgetName + " -->" + whiteSpace;

+    }

+

+    /**

+     * Renders the beginning boundary comment string.

+     * @param writer The writer to write to

+     * @param widgetType The widget type: "Screen Widget", "Form Widget", etc.

+     * @param modelWidget The widget

+     */

+    public void renderBeginningBoundaryComment(Appendable writer, String widgetType, ModelWidget modelWidget) throws IOException {

+        if (this.widgetCommentsEnabled) {

+            writer.append(this.buildBoundaryComment("Begin", widgetType, modelWidget.getBoundaryCommentName()));

+        }

+    }

+

+    /**

+     * Renders the ending boundary comment string.

+     * @param writer The writer to write to

+     * @param widgetType The widget type: "Screen Widget", "Form Widget", etc.

+     * @param modelWidget The widget

+     */

+    public void renderEndingBoundaryComment(Appendable writer, String widgetType, ModelWidget modelWidget) throws IOException {

+        if (this.widgetCommentsEnabled) {

+            writer.append(this.buildBoundaryComment("End", widgetType, modelWidget.getBoundaryCommentName()));

+        }

+    }

+

+    /** Extracts parameters from a target URL string, prepares them for an Ajax

+     * JavaScript call. This method is currently set to return a parameter string

+     * suitable for the Prototype.js library.

+     * @param target Target URL string

+     * @return Parameter string

+     */

+    public static String getAjaxParamsFromTarget(String target) {

+        String targetParams = UtilHttp.getQueryStringFromTarget(target);

+        targetParams = targetParams.replace("?", "");

+        targetParams = targetParams.replace("&amp;", "&");

+        return targetParams;

+    }

+}

diff --git a/framework/widget/src/org/ofbiz/widget/form/MacroFormRenderer.java b/framework/widget/src/org/ofbiz/widget/renderer/macro/MacroFormRenderer.java
similarity index 98%
rename from framework/widget/src/org/ofbiz/widget/form/MacroFormRenderer.java
rename to framework/widget/src/org/ofbiz/widget/renderer/macro/MacroFormRenderer.java
index 742f471..a369bea 100644
--- a/framework/widget/src/org/ofbiz/widget/form/MacroFormRenderer.java
+++ b/framework/widget/src/org/ofbiz/widget/renderer/macro/MacroFormRenderer.java
@@ -1,3124 +1,3132 @@
-/*******************************************************************************
- * 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.io.Reader;
-import java.io.StringReader;
-import java.io.StringWriter;
-import java.rmi.server.UID;
-import java.sql.Timestamp;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Set;
-import java.util.WeakHashMap;
-
-import javax.servlet.ServletContext;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.ofbiz.base.util.Debug;
-import org.ofbiz.base.util.StringUtil;
-import org.ofbiz.base.util.UtilCodec;
-import org.ofbiz.base.util.UtilFormatOut;
-import org.ofbiz.base.util.UtilGenerics;
-import org.ofbiz.base.util.UtilHttp;
-import org.ofbiz.base.util.UtilMisc;
-import org.ofbiz.base.util.UtilProperties;
-import org.ofbiz.base.util.UtilValidate;
-import org.ofbiz.base.util.string.FlexibleStringExpander;
-import org.ofbiz.base.util.template.FreeMarkerWorker;
-import org.ofbiz.entity.Delegator;
-import org.ofbiz.webapp.control.RequestHandler;
-import org.ofbiz.webapp.taglib.ContentUrlTag;
-import org.ofbiz.widget.CommonWidgetModels;
-import org.ofbiz.widget.ModelWidget;
-import org.ofbiz.widget.WidgetWorker;
-import org.ofbiz.widget.form.ModelFormField.CheckField;
-import org.ofbiz.widget.form.ModelFormField.ContainerField;
-import org.ofbiz.widget.form.ModelFormField.DateFindField;
-import org.ofbiz.widget.form.ModelFormField.DateTimeField;
-import org.ofbiz.widget.form.ModelFormField.DisplayEntityField;
-import org.ofbiz.widget.form.ModelFormField.DisplayField;
-import org.ofbiz.widget.form.ModelFormField.DropDownField;
-import org.ofbiz.widget.form.ModelFormField.FieldInfoWithOptions;
-import org.ofbiz.widget.form.ModelFormField.FileField;
-import org.ofbiz.widget.form.ModelFormField.HiddenField;
-import org.ofbiz.widget.form.ModelFormField.HyperlinkField;
-import org.ofbiz.widget.form.ModelFormField.IgnoredField;
-import org.ofbiz.widget.form.ModelFormField.ImageField;
-import org.ofbiz.widget.form.ModelFormField.LookupField;
-import org.ofbiz.widget.form.ModelFormField.PasswordField;
-import org.ofbiz.widget.form.ModelFormField.RadioField;
-import org.ofbiz.widget.form.ModelFormField.RangeFindField;
-import org.ofbiz.widget.form.ModelFormField.ResetField;
-import org.ofbiz.widget.form.ModelFormField.SubmitField;
-import org.ofbiz.widget.form.ModelFormField.TextField;
-import org.ofbiz.widget.form.ModelFormField.TextFindField;
-import org.ofbiz.widget.form.ModelFormField.TextareaField;
-import org.ofbiz.widget.screen.ModelScreenWidget;
-
-import com.ibm.icu.util.Calendar;
-
-import freemarker.core.Environment;
-import freemarker.template.Template;
-import freemarker.template.TemplateException;
-
-/**
- * Widget Library - Form Renderer implementation based on Freemarker macros
- *
- */
-public final class MacroFormRenderer implements FormStringRenderer {
-
-    public static final String module = MacroFormRenderer.class.getName();
-    private final Template macroLibrary;
-    private final WeakHashMap<Appendable, Environment> environments = new WeakHashMap<Appendable, Environment>();
-    private final UtilCodec.SimpleEncoder internalEncoder;
-    private final RequestHandler rh;
-    private final HttpServletRequest request;
-    private final HttpServletResponse response;
-    private final boolean javaScriptEnabled;
-    private boolean renderPagination = true;
-    private boolean widgetCommentsEnabled = false;
-
-    public MacroFormRenderer(String macroLibraryPath, HttpServletRequest request, HttpServletResponse response) throws TemplateException, IOException {
-        macroLibrary = FreeMarkerWorker.getTemplate(macroLibraryPath);
-        this.request = request;
-        this.response = response;
-        ServletContext ctx = (ServletContext) request.getAttribute("servletContext");
-        this.rh = (RequestHandler) ctx.getAttribute("_REQUEST_HANDLER_");
-        this.javaScriptEnabled = UtilHttp.isJavaScriptEnabled(request);
-        internalEncoder = UtilCodec.getEncoder("string");
-    }
-
-    @Deprecated
-    public MacroFormRenderer(String macroLibraryPath, Appendable writer, HttpServletRequest request, HttpServletResponse response) throws TemplateException, IOException {
-        this(macroLibraryPath, request, response);
-    }
-
-    public boolean getRenderPagination() {
-        return this.renderPagination;
-    }
-
-    public void setRenderPagination(boolean renderPagination) {
-        this.renderPagination = renderPagination;
-    }
-
-    private void executeMacro(Appendable writer, String macro) throws IOException {
-        try {
-            Environment environment = getEnvironment(writer);
-            Reader templateReader = new StringReader(macro);
-            Template template = new Template(new UID().toString(), templateReader, FreeMarkerWorker.getDefaultOfbizConfig());
-            templateReader.close();
-            environment.include(template);
-        } catch (TemplateException e) {
-            Debug.logError(e, "Error rendering screen thru ftl macro: " + macro, module);
-        } catch (IOException e) {
-            Debug.logError(e, "Error rendering screen thru ftl, macro: " + macro, module);
-        }
-    }
-
-    private Environment getEnvironment(Appendable writer) throws TemplateException, IOException {
-        Environment environment = environments.get(writer);
-        if (environment == null) {
-            Map<String, Object> input = UtilMisc.toMap("key", null);
-            environment = FreeMarkerWorker.renderTemplate(macroLibrary, input, writer);
-            environments.put(writer, environment);
-        }
-        return environment;
-    }
-
-    private void appendWhitespace(Appendable writer) throws IOException {
-        // appending line ends for now, but this could be replaced with a simple space or something
-        writer.append("\r\n");
-        //writer.append(' ');
-    }
-
-    private String encode(String value, ModelFormField modelFormField, Map<String, Object> context) {
-        if (UtilValidate.isEmpty(value)) {
-            return value;
-        }
-        UtilCodec.SimpleEncoder encoder = (UtilCodec.SimpleEncoder) context.get("simpleEncoder");
-        if (modelFormField.getEncodeOutput() && encoder != null) {
-            value = encoder.encode(value);
-        } else {
-            value = internalEncoder.encode(value);
-        }
-        return value;
-    }
-
-    public void renderLabel(Appendable writer, Map<String, Object> context, ModelScreenWidget.Label label) throws IOException {
-        String labelText = label.getText(context);
-        if (UtilValidate.isEmpty(labelText)) {
-            // nothing to render
-            return;
-        }
-        StringWriter sr = new StringWriter();
-        sr.append("<@renderLabel ");
-        sr.append("text=\"");
-        sr.append(labelText);
-        sr.append("\"");
-        sr.append(" />");
-        executeMacro(writer, sr.toString());
-    }
-
-    public void renderDisplayField(Appendable writer, Map<String, Object> context, DisplayField displayField) throws IOException {
-        ModelFormField modelFormField = displayField.getModelFormField();
-        String idName = modelFormField.getCurrentContainerId(context);
-        String description = displayField.getDescription(context);
-        String type = displayField.getType();
-        String imageLocation = displayField.getImageLocation(context);
-        Integer size = Integer.valueOf("0");
-        String title = "";
-        if (UtilValidate.isNotEmpty(displayField.getSize())) {
-            try {
-                size = Integer.parseInt(displayField.getSize());
-            } catch (NumberFormatException nfe) {
-                Debug.logError(nfe, "Error reading size of a field fieldName=" + displayField.getModelFormField().getFieldName() + " FormName= " + displayField.getModelFormField().getModelForm().getName(), module);
-            }
-        }
-        ModelFormField.InPlaceEditor inPlaceEditor = displayField.getInPlaceEditor();
-        boolean ajaxEnabled = inPlaceEditor != null && this.javaScriptEnabled;
-        if (UtilValidate.isNotEmpty(description) && size > 0 && description.length() > size) {
-            title = description;
-            description = description.substring(0, size - 8) + "..." + description.substring(description.length() - 5);
-        }
-        StringWriter sr = new StringWriter();
-        sr.append("<@renderDisplayField ");
-        sr.append("type=\"");
-        sr.append(type);
-        sr.append("\" imageLocation=\"");
-        sr.append(imageLocation);
-        sr.append("\" idName=\"");
-        sr.append(idName);
-        sr.append("\" description=\"");
-        sr.append(FreeMarkerWorker.encodeDoubleQuotes(description));
-        sr.append("\" title=\"");
-        sr.append(title);
-        sr.append("\" class=\"");
-        sr.append(modelFormField.getWidgetStyle());
-        sr.append("\" alert=\"");
-        sr.append(modelFormField.shouldBeRed(context) ? "true" : "false");
-        if (ajaxEnabled) {
-            String url = inPlaceEditor.getUrl(context);
-            String extraParameter = "{";
-            Map<String, Object> fieldMap = inPlaceEditor.getFieldMap(context);
-            if (fieldMap != null) {
-                Set<Entry<String, Object>> fieldSet = fieldMap.entrySet();
-                Iterator<Entry<String, Object>> fieldIterator = fieldSet.iterator();
-                int count = 0;
-                while (fieldIterator.hasNext()) {
-                    count++;
-                    Entry<String, Object> field = fieldIterator.next();
-                    extraParameter += field.getKey() + ":'" + (String) field.getValue() + "'";
-                    if (count < fieldSet.size()) {
-                        extraParameter += ',';
-                    }
-                }
-
-            }
-            extraParameter += "}";
-            sr.append("\" inPlaceEditorUrl=\"");
-            sr.append(url);
-            sr.append("\" inPlaceEditorParams=\"");
-            StringWriter inPlaceEditorParams = new StringWriter();
-            inPlaceEditorParams.append("{name: '");
-            if (UtilValidate.isNotEmpty(inPlaceEditor.getParamName())) {
-                inPlaceEditorParams.append(inPlaceEditor.getParamName());
-            } else {
-                inPlaceEditorParams.append(modelFormField.getFieldName());
-            }
-            inPlaceEditorParams.append("'");
-            inPlaceEditorParams.append(", method: 'POST'");
-            inPlaceEditorParams.append(", submitdata: " + extraParameter);
-            inPlaceEditorParams.append(", type: 'textarea'");
-            inPlaceEditorParams.append(", select: 'true'");
-            inPlaceEditorParams.append(", onreset: function(){jQuery('#cc_" + idName + "').css('background-color', 'transparent');}");
-            if (UtilValidate.isNotEmpty(inPlaceEditor.getCancelText())) {
-                inPlaceEditorParams.append(", cancel: '" + inPlaceEditor.getCancelText() + "'");
-            } else {
-                inPlaceEditorParams.append(", cancel: 'Cancel'");
-            }
-            if (UtilValidate.isNotEmpty(inPlaceEditor.getClickToEditText())) {
-                inPlaceEditorParams.append(", tooltip: '" + inPlaceEditor.getClickToEditText() + "'");
-            }
-            if (UtilValidate.isNotEmpty(inPlaceEditor.getFormClassName())) {
-                inPlaceEditorParams.append(", cssclass: '" + inPlaceEditor.getFormClassName() + "'");
-            } else {
-                inPlaceEditorParams.append(", cssclass: 'inplaceeditor-form'");
-            }
-            if (UtilValidate.isNotEmpty(inPlaceEditor.getLoadingText())) {
-                inPlaceEditorParams.append(", indicator: '" + inPlaceEditor.getLoadingText() + "'");
-            }
-            if (UtilValidate.isNotEmpty(inPlaceEditor.getOkControl())) {
-                inPlaceEditorParams.append(", submit: ");
-                if (!"false".equals(inPlaceEditor.getOkControl())) {
-                    inPlaceEditorParams.append("'");
-                }
-                inPlaceEditorParams.append(inPlaceEditor.getOkControl());
-                if (!"false".equals(inPlaceEditor.getOkControl())) {
-                    inPlaceEditorParams.append("'");
-                }
-            } else {
-                inPlaceEditorParams.append(", submit: 'OK'");
-            }
-            if (UtilValidate.isNotEmpty(inPlaceEditor.getRows())) {
-                inPlaceEditorParams.append(", rows: '" + inPlaceEditor.getRows() + "'");
-            }
-            if (UtilValidate.isNotEmpty(inPlaceEditor.getCols())) {
-                inPlaceEditorParams.append(", cols: '" + inPlaceEditor.getCols() + "'");
-            }
-            inPlaceEditorParams.append("}");
-            sr.append(inPlaceEditorParams.toString());
-        }
-        sr.append("\" />");
-        executeMacro(writer, sr.toString());
-        if (displayField instanceof DisplayEntityField) {
-            makeHyperlinkString(writer, ((DisplayEntityField) displayField).getSubHyperlink(), context);
-        }
-        this.appendTooltip(writer, context, modelFormField);
-    }
-
-    public void renderHyperlinkField(Appendable writer, Map<String, Object> context, HyperlinkField hyperlinkField) throws IOException {
-        this.request.setAttribute("image", hyperlinkField.getImageLocation(context));
-        ModelFormField modelFormField = hyperlinkField.getModelFormField();
-        String encodedAlternate = encode(hyperlinkField.getAlternate(context), modelFormField, context);
-        String encodedImageTitle = encode(hyperlinkField.getImageTitle(context), modelFormField, context);
-        this.request.setAttribute("alternate", encodedAlternate);
-        this.request.setAttribute("imageTitle", encodedImageTitle);
-        this.request.setAttribute("descriptionSize", hyperlinkField.getSize());
-        makeHyperlinkByType(writer, hyperlinkField.getLinkType(), modelFormField.getWidgetStyle(), hyperlinkField.getUrlMode(), hyperlinkField.getTarget(context), hyperlinkField.getParameterMap(context), hyperlinkField.getDescription(context), hyperlinkField.getTargetWindow(context),
-                hyperlinkField.getConfirmation(context), modelFormField, this.request, this.response, context);
-        this.appendTooltip(writer, context, modelFormField);
-        this.request.removeAttribute("image");
-        this.request.removeAttribute("descriptionSize");
-    }
-
-    public void renderTextField(Appendable writer, Map<String, Object> context, TextField textField) throws IOException {
-        ModelFormField modelFormField = textField.getModelFormField();
-        String name = modelFormField.getParameterName(context);
-        String className = "";
-        String alert = "false";
-        String mask = "";
-        String placeholder = textField.getPlaceholder(context);
-        if (UtilValidate.isNotEmpty(modelFormField.getWidgetStyle())) {
-            className = modelFormField.getWidgetStyle();
-            if (modelFormField.shouldBeRed(context)) {
-                alert = "true";
-            }
-        }
-        String value = modelFormField.getEntry(context, textField.getDefaultValue(context));
-        String textSize = Integer.toString(textField.getSize());
-        String maxlength = "";
-        if (textField.getMaxlength() != null) {
-            maxlength = Integer.toString(textField.getMaxlength());
-        }
-        String event = modelFormField.getEvent();
-        String action = modelFormField.getAction(context);
-        String id = modelFormField.getCurrentContainerId(context);
-        String clientAutocomplete = "false";
-        //check for required field style on single forms
-        if ("single".equals(modelFormField.getModelForm().getType()) && modelFormField.getRequiredField()) {
-            String requiredStyle = modelFormField.getRequiredFieldStyle();
-            if (UtilValidate.isEmpty(requiredStyle))
-                requiredStyle = "required";
-            if (UtilValidate.isEmpty(className))
-                className = requiredStyle;
-            else
-                className = requiredStyle + " " + className;
-        }
-        List<ModelForm.UpdateArea> updateAreas = modelFormField.getOnChangeUpdateAreas();
-        boolean ajaxEnabled = updateAreas != null && this.javaScriptEnabled;
-        if (textField.getClientAutocompleteField() || ajaxEnabled) {
-            clientAutocomplete = "true";
-        }
-        if (UtilValidate.isNotEmpty(textField.getMask())) {
-            mask = textField.getMask();
-        }
-        String ajaxUrl = createAjaxParamsFromUpdateAreas(updateAreas, "", context);
-        boolean disabled = textField.getDisabled();
-        StringWriter sr = new StringWriter();
-        sr.append("<@renderTextField ");
-        sr.append("name=\"");
-        sr.append(name);
-        sr.append("\" className=\"");
-        sr.append(className);
-        sr.append("\" alert=\"");
-        sr.append(alert);
-        sr.append("\" value=\"");
-        sr.append(value);
-        sr.append("\" textSize=\"");
-        sr.append(textSize);
-        sr.append("\" maxlength=\"");
-        sr.append(maxlength);
-        sr.append("\" id=\"");
-        sr.append(id);
-        sr.append("\" event=\"");
-        if (event != null) {
-            sr.append(event);
-        }
-        sr.append("\" action=\"");
-        if (action != null) {
-            sr.append(action);
-        }
-        sr.append("\" disabled=");
-        sr.append(Boolean.toString(disabled));
-        sr.append(" clientAutocomplete=\"");
-        sr.append(clientAutocomplete);
-        sr.append("\" ajaxUrl=\"");
-        sr.append(ajaxUrl);
-        sr.append("\" ajaxEnabled=");
-        sr.append(Boolean.toString(ajaxEnabled));
-        sr.append(" mask=\"");
-        sr.append(mask);
-        sr.append("\" placeholder=\"");
-        sr.append(placeholder);
-        sr.append("\" />");
-        executeMacro(writer, sr.toString());
-        ModelFormField.SubHyperlink subHyperlink = textField.getSubHyperlink();
-        if (subHyperlink != null && subHyperlink.shouldUse(context)) {
-            makeHyperlinkString(writer, subHyperlink, context);
-        }
-        this.addAsterisks(writer, context, modelFormField);
-        this.appendTooltip(writer, context, modelFormField);
-    }
-
-    public void renderTextareaField(Appendable writer, Map<String, Object> context, TextareaField textareaField) throws IOException {
-        ModelFormField modelFormField = textareaField.getModelFormField();
-        String name = modelFormField.getParameterName(context);
-        String cols = Integer.toString(textareaField.getCols());
-        String rows = Integer.toString(textareaField.getRows());
-        String id = modelFormField.getCurrentContainerId(context);
-        String className = "";
-        String alert = "false";
-        if (UtilValidate.isNotEmpty(modelFormField.getWidgetStyle())) {
-            className = modelFormField.getWidgetStyle();
-            if (modelFormField.shouldBeRed(context)) {
-                alert = "true";
-            }
-        }
-        //check for required field style on single forms
-        if ("single".equals(modelFormField.getModelForm().getType()) && modelFormField.getRequiredField()) {
-            String requiredStyle = modelFormField.getRequiredFieldStyle();
-            if (UtilValidate.isEmpty(requiredStyle))
-                requiredStyle = "required";
-            if (UtilValidate.isEmpty(className))
-                className = requiredStyle;
-            else
-                className = requiredStyle + " " + className;
-        }
-        String visualEditorEnable = "";
-        String buttons = "";
-        if (textareaField.getVisualEditorEnable()) {
-            visualEditorEnable = "true";
-            buttons = textareaField.getVisualEditorButtons(context);
-            if (UtilValidate.isEmpty(buttons)) {
-                buttons = "maxi";
-            }
-        }
-        String readonly = "";
-        if (textareaField.isReadOnly()) {
-            readonly = "readonly";
-        }
-        Map<String, Object> userLogin = UtilGenerics.checkMap(context.get("userLogin"));
-        String language = "en";
-        if (userLogin != null) {
-            language = UtilValidate.isEmpty((String) userLogin.get("lastLocale")) ? "en" : (String) userLogin.get("lastLocale");
-        }
-        String value = modelFormField.getEntry(context, textareaField.getDefaultValue(context));
-        StringWriter sr = new StringWriter();
-        sr.append("<@renderTextareaField ");
-        sr.append("name=\"");
-        sr.append(name);
-        sr.append("\" className=\"");
-        sr.append(className);
-        sr.append("\" alert=\"");
-        sr.append(alert);
-        sr.append("\" value=\"");
-        sr.append(value);
-        sr.append("\" cols=\"");
-        sr.append(cols);
-        sr.append("\" rows=\"");
-        sr.append(rows);
-        sr.append("\" id=\"");
-        sr.append(id);
-        sr.append("\" readonly=\"");
-        sr.append(readonly);
-        sr.append("\" visualEditorEnable=\"");
-        sr.append(visualEditorEnable);
-        sr.append("\" language=\"");
-        sr.append(language);
-        sr.append("\" buttons=\"");
-        sr.append(buttons);
-        sr.append("\" />");
-        executeMacro(writer, sr.toString());
-        this.addAsterisks(writer, context, modelFormField);
-        this.appendTooltip(writer, context, modelFormField);
-    }
-
-    public void renderDateTimeField(Appendable writer, Map<String, Object> context, DateTimeField dateTimeField) throws IOException {
-        ModelFormField modelFormField = dateTimeField.getModelFormField();
-        String paramName = modelFormField.getParameterName(context);
-        String defaultDateTimeString = dateTimeField.getDefaultDateTimeString(context);
-        String className = "";
-        String alert = "false";
-        String name = "";
-        String formattedMask = "";
-        String event = modelFormField.getEvent();
-        String action = modelFormField.getAction(context);
-        if (UtilValidate.isNotEmpty(modelFormField.getWidgetStyle())) {
-            className = modelFormField.getWidgetStyle();
-            if (modelFormField.shouldBeRed(context)) {
-                alert = "true";
-            }
-        }
-        boolean useTimeDropDown = "time-dropdown".equals(dateTimeField.getInputMethod());
-        String stepString = dateTimeField.getStep();
-        int step = 1;
-        StringBuilder timeValues = new StringBuilder();
-        if (useTimeDropDown && UtilValidate.isNotEmpty(step)) {
-            try {
-                step = Integer.valueOf(stepString).intValue();
-            } catch (IllegalArgumentException e) {
-                Debug.logWarning("Inavalid value for step property for field[" + paramName + "] with input-method=\"time-dropdown\" " + " Found Value [" + stepString + "]  " + e.getMessage(), module);
-            }
-            timeValues.append("[");
-            for (int i = 0; i <= 59;) {
-                if (i != 0) {
-                    timeValues.append(", ");
-                }
-                timeValues.append(i);
-                i += step;
-            }
-            timeValues.append("]");
-        }
-        Map<String, String> uiLabelMap = UtilGenerics.checkMap(context.get("uiLabelMap"));
-        if (uiLabelMap == null) {
-            Debug.logWarning("Could not find uiLabelMap in context", module);
-        }
-        String localizedInputTitle = "", localizedIconTitle = "";
-        // whether the date field is short form, yyyy-mm-dd
-        boolean shortDateInput = ("date".equals(dateTimeField.getType()) || useTimeDropDown ? true : false);
-        if (useTimeDropDown) {
-            name = UtilHttp.makeCompositeParam(paramName, "date");
-        } else {
-            name = paramName;
-        }
-        // the default values for a timestamp
-        int size = 25;
-        int maxlength = 30;
-        if (shortDateInput) {
-            size = maxlength = 10;
-            if (uiLabelMap != null) {
-                localizedInputTitle = uiLabelMap.get("CommonFormatDate");
-            }
-        } else if ("time".equals(dateTimeField.getType())) {
-            size = maxlength = 8;
-            if (uiLabelMap != null) {
-                localizedInputTitle = uiLabelMap.get("CommonFormatTime");
-            }
-        } else {
-            if (uiLabelMap != null) {
-                localizedInputTitle = uiLabelMap.get("CommonFormatDateTime");
-            }
-        }
-        /*
-         * FIXME: Using a builder here is a hack. Replace the builder with appropriate code.
-         */
-        ModelFormFieldBuilder builder = new ModelFormFieldBuilder(modelFormField);
-        boolean memEncodeOutput = modelFormField.getEncodeOutput();
-        if (useTimeDropDown)
-            // If time-dropdown deactivate encodingOutput for found hour and minutes
-            // FIXME: Encoding should be controlled by the renderer, not by the model.
-            builder.setEncodeOutput(false);
-        // FIXME: modelFormField.getEntry ignores shortDateInput when converting Date objects to Strings.
-        if (useTimeDropDown) {
-            builder.setEncodeOutput(memEncodeOutput);
-        }
-        modelFormField = builder.build();
-        String contextValue = modelFormField.getEntry(context, dateTimeField.getDefaultValue(context));
-        String value = contextValue;
-        if (UtilValidate.isNotEmpty(value)) {
-            if (value.length() > maxlength) {
-                value = value.substring(0, maxlength);
-            }
-        }
-        String id = modelFormField.getCurrentContainerId(context);
-        ModelForm modelForm = modelFormField.getModelForm();
-        String formName = FormRenderer.getCurrentFormName(modelForm, context);
-        String timeDropdown = dateTimeField.getInputMethod();
-        String timeDropdownParamName = "";
-        String classString = "";
-        boolean isTwelveHour = false;
-        String timeHourName = "";
-        int hour2 = 0, hour1 = 0, minutes = 0;
-        String timeMinutesName = "";
-        String amSelected = "", pmSelected = "", ampmName = "";
-        String compositeType = "";
-        // search for a localized label for the icon
-        if (uiLabelMap != null) {
-            localizedIconTitle = uiLabelMap.get("CommonViewCalendar");
-        }
-        if (!"time".equals(dateTimeField.getType())) {
-            String tempParamName;
-            if (useTimeDropDown) {
-                tempParamName = UtilHttp.makeCompositeParam(paramName, "date");
-            } else {
-                tempParamName = paramName;
-            }
-            timeDropdownParamName = tempParamName;
-            defaultDateTimeString = UtilHttp.encodeBlanks(modelFormField.getEntry(context, defaultDateTimeString));
-        }
-        // if we have an input method of time-dropdown, then render two
-        // dropdowns
-        if (useTimeDropDown) {
-            className = modelFormField.getWidgetStyle();
-            classString = (className != null ? className : "");
-            isTwelveHour = "12".equals(dateTimeField.getClock());
-            // set the Calendar to the default time of the form or now()
-            Calendar cal = null;
-            try {
-                Timestamp defaultTimestamp = Timestamp.valueOf(contextValue);
-                cal = Calendar.getInstance();
-                cal.setTime(defaultTimestamp);
-            } catch (IllegalArgumentException e) {
-                Debug.logWarning("Form widget field [" + paramName + "] with input-method=\"time-dropdown\" was not able to understand the default time [" + defaultDateTimeString + "]. The parsing error was: " + e.getMessage(), module);
-            }
-            timeHourName = UtilHttp.makeCompositeParam(paramName, "hour");
-            if (cal != null) {
-                int hour = cal.get(Calendar.HOUR_OF_DAY);
-                hour2 = hour;
-                if (hour == 0) {
-                    hour = 12;
-                }
-                if (hour > 12) {
-                    hour -= 12;
-                }
-                hour1 = hour;
-                minutes = cal.get(Calendar.MINUTE);
-            }
-            timeMinutesName = UtilHttp.makeCompositeParam(paramName, "minutes");
-            compositeType = UtilHttp.makeCompositeParam(paramName, "compositeType");
-            // if 12 hour clock, write the AM/PM selector
-            if (isTwelveHour) {
-                amSelected = ((cal != null && cal.get(Calendar.AM_PM) == Calendar.AM) ? "selected" : "");
-                pmSelected = ((cal != null && cal.get(Calendar.AM_PM) == Calendar.PM) ? "selected" : "");
-                ampmName = UtilHttp.makeCompositeParam(paramName, "ampm");
-            }
-        }
-        //check for required field style on single forms
-        if ("single".equals(modelFormField.getModelForm().getType()) && modelFormField.getRequiredField()) {
-            String requiredStyle = modelFormField.getRequiredFieldStyle();
-            if (UtilValidate.isEmpty(requiredStyle))
-                requiredStyle = "required";
-            if (UtilValidate.isEmpty(className))
-                className = requiredStyle;
-            else
-                className = requiredStyle + " " + className;
-        }
-        String mask = dateTimeField.getMask();
-        if ("Y".equals(mask)) {
-            if ("date".equals(dateTimeField.getType())) {
-                formattedMask = "9999-99-99";
-            } else if ("time".equals(dateTimeField.getType())) {
-                formattedMask = "99:99:99";
-            } else if ("timestamp".equals(dateTimeField.getType())) {
-                formattedMask = "9999-99-99 99:99:99";
-            }
-        }
-        StringWriter sr = new StringWriter();
-        sr.append("<@renderDateTimeField ");
-        sr.append("name=\"");
-        sr.append(name);
-        sr.append("\" className=\"");
-        sr.append(className);
-        sr.append("\" alert=\"");
-        sr.append(alert);
-        sr.append("\" value=\"");
-        sr.append(value);
-        sr.append("\" title=\"");
-        sr.append(localizedInputTitle);
-        sr.append("\" size=\"");
-        sr.append(Integer.toString(size));
-        sr.append("\" maxlength=\"");
-        sr.append(Integer.toString(maxlength));
-        sr.append("\" step=\"");
-        sr.append(Integer.toString(step));
-        sr.append("\" timeValues=\"");
-        sr.append(timeValues.toString());
-        sr.append("\" id=\"");
-        sr.append(id);
-        sr.append("\" event=\"");
-        sr.append(event);
-        sr.append("\" action=\"");
-        sr.append(action);
-        sr.append("\" dateType=\"");
-        sr.append(dateTimeField.getType());
-        sr.append("\" shortDateInput=");
-        sr.append(Boolean.toString(shortDateInput));
-        sr.append(" timeDropdownParamName=\"");
-        sr.append(timeDropdownParamName);
-        sr.append("\" defaultDateTimeString=\"");
-        sr.append(defaultDateTimeString);
-        sr.append("\" localizedIconTitle=\"");
-        sr.append(localizedIconTitle);
-        sr.append("\" timeDropdown=\"");
-        sr.append(timeDropdown);
-        sr.append("\" timeHourName=\"");
-        sr.append(timeHourName);
-        sr.append("\" classString=\"");
-        sr.append(classString);
-        sr.append("\" hour1=");
-        sr.append(Integer.toString(hour1));
-        sr.append(" hour2=");
-        sr.append(Integer.toString(hour2));
-        sr.append(" timeMinutesName=\"");
-        sr.append(timeMinutesName);
-        sr.append("\" minutes=");
-        sr.append(Integer.toString(minutes));
-        sr.append(" isTwelveHour=");
-        sr.append(Boolean.toString(isTwelveHour));
-        sr.append(" ampmName=\"");
-        sr.append(ampmName);
-        sr.append("\" amSelected=\"");
-        sr.append(amSelected);
-        sr.append("\" pmSelected=\"");
-        sr.append(pmSelected);
-        sr.append("\" compositeType=\"");
-        sr.append(compositeType);
-        sr.append("\" formName=\"");
-        sr.append(formName);
-        sr.append("\" mask=\"");
-        sr.append(formattedMask);
-        sr.append("\" />");
-        executeMacro(writer, sr.toString());
-        this.addAsterisks(writer, context, modelFormField);
-        this.appendTooltip(writer, context, modelFormField);
-    }
-
-    public void renderDropDownField(Appendable writer, Map<String, Object> context, DropDownField dropDownField) throws IOException {
-        ModelFormField modelFormField = dropDownField.getModelFormField();
-        ModelForm modelForm = modelFormField.getModelForm();
-        String currentValue = modelFormField.getEntry(context);
-        List<ModelFormField.OptionValue> allOptionValues = dropDownField.getAllOptionValues(context, WidgetWorker.getDelegator(context));
-        ModelFormField.AutoComplete autoComplete = dropDownField.getAutoComplete();
-        String event = modelFormField.getEvent();
-        String action = modelFormField.getAction(context);
-        Integer textSize = Integer.valueOf(0);
-        if (UtilValidate.isNotEmpty(dropDownField.getTextSize())) {
-            try {
-                textSize = Integer.parseInt(dropDownField.getTextSize());
-            } catch (NumberFormatException nfe) {
-                Debug.logError(nfe, "Error reading size of a field fieldName=" + dropDownField.getModelFormField().getFieldName() + " FormName= " + dropDownField.getModelFormField().getModelForm().getName(), module);
-            }
-            if (textSize > 0 && UtilValidate.isNotEmpty(currentValue) && currentValue.length() > textSize) {
-                currentValue = currentValue.substring(0, textSize - 8) + "..." + currentValue.substring(currentValue.length() - 5);
-            }
-        }
-        boolean ajaxEnabled = autoComplete != null && this.javaScriptEnabled;
-        String className = "";
-        String alert = "false";
-        String name = modelFormField.getParameterName(context);
-        String id = modelFormField.getCurrentContainerId(context);
-        String multiple = dropDownField.getAllowMultiple() ? "multiple" : "";
-        String otherFieldName = "";
-        String formName = modelForm.getName();
-        String size = dropDownField.getSize();
-        String dDFCurrent = dropDownField.getCurrent();
-        String firstInList = "";
-        String explicitDescription = "";
-        String allowEmpty = "";
-        StringBuilder options = new StringBuilder();
-        StringBuilder ajaxOptions = new StringBuilder();
-        if (UtilValidate.isNotEmpty(modelFormField.getWidgetStyle())) {
-            className = modelFormField.getWidgetStyle();
-            if (modelFormField.shouldBeRed(context)) {
-                alert = "true";
-            }
-        }
-        //check for required field style on single forms
-        if ("single".equals(modelFormField.getModelForm().getType()) && modelFormField.getRequiredField()) {
-            String requiredStyle = modelFormField.getRequiredFieldStyle();
-            if (UtilValidate.isEmpty(requiredStyle))
-                requiredStyle = "required";
-            if (UtilValidate.isEmpty(className))
-                className = requiredStyle;
-            else
-                className = requiredStyle + " " + className;
-        }
-        String currentDescription = null;
-        if (UtilValidate.isNotEmpty(currentValue)) {
-            for (ModelFormField.OptionValue optionValue : allOptionValues) {
-                if (optionValue.getKey().equals(currentValue)) {
-                    currentDescription = optionValue.getDescription();
-                    break;
-                }
-            }
-        }
-        int otherFieldSize = dropDownField.getOtherFieldSize();
-        if (otherFieldSize > 0) {
-            otherFieldName = dropDownField.getParameterNameOther(context);
-        }
-        // if the current value should go first, stick it in
-        if (UtilValidate.isNotEmpty(currentValue) && "first-in-list".equals(dropDownField.getCurrent())) {
-            firstInList = "first-in-list";
-        }
-        explicitDescription = (currentDescription != null ? currentDescription : dropDownField.getCurrentDescription(context));
-        if (UtilValidate.isEmpty(explicitDescription)) {
-            explicitDescription = (FieldInfoWithOptions.getDescriptionForOptionKey(currentValue, allOptionValues));
-        }
-        if (textSize > 0 && UtilValidate.isNotEmpty(explicitDescription) && explicitDescription.length() > textSize) {
-            explicitDescription = explicitDescription.substring(0, textSize - 8) + "..." + explicitDescription.substring(explicitDescription.length() - 5);
-        }
-        explicitDescription = encode(explicitDescription, modelFormField, context);
-        // if allow empty is true, add an empty option
-        if (dropDownField.getAllowEmpty()) {
-            allowEmpty = "Y";
-        }
-        List<String> currentValueList = null;
-        if (UtilValidate.isNotEmpty(currentValue) && dropDownField.getAllowMultiple()) {
-            // If currentValue is Array, it will start with [
-            if (currentValue.startsWith("[")) {
-                currentValueList = StringUtil.toList(currentValue);
-            } else {
-                currentValueList = UtilMisc.toList(currentValue);
-            }
-        }
-        options.append("[");
-        Iterator<ModelFormField.OptionValue> optionValueIter = allOptionValues.iterator();
-        int count = 0;
-        while (optionValueIter.hasNext()) {
-            ModelFormField.OptionValue optionValue = optionValueIter.next();
-            if (options.length() > 1) {
-                options.append(",");
-            }
-            options.append("{'key':'");
-            String key = encode(optionValue.getKey(), modelFormField, context);
-            options.append(key);
-            options.append("'");
-            options.append(",'description':'");
-            String description = optionValue.getDescription();
-            if (textSize > 0 && description.length() > textSize) {
-                description = description.substring(0, textSize - 8) + "..." + description.substring(description.length() - 5);
-            }
-            options.append(encode(description, modelFormField, context));
-
-            if (UtilValidate.isNotEmpty(currentValueList)) {
-                options.append("'");
-                options.append(",'selected':'");
-                if (currentValueList.contains(optionValue.getKey())) {
-                    options.append("selected");
-                } else {
-                    options.append("");
-                }
-            }
-
-            options.append("'}");
-            if (ajaxEnabled) {
-                count++;
-                ajaxOptions.append(optionValue.getKey()).append(": ");
-                ajaxOptions.append(" '").append(optionValue.getDescription()).append("'");
-                if (count != allOptionValues.size()) {
-                    ajaxOptions.append(", ");
-                }
-            }
-        }
-        options.append("]");
-        String noCurrentSelectedKey = dropDownField.getNoCurrentSelectedKey(context);
-        String otherValue = "", fieldName = "";
-        // Adapted from work by Yucca Korpela
-        // http://www.cs.tut.fi/~jkorpela/forms/combo.html
-        if (otherFieldSize > 0) {
-            fieldName = modelFormField.getParameterName(context);
-            Map<String, ? extends Object> dataMap = modelFormField.getMap(context);
-            if (dataMap == null) {
-                dataMap = context;
-            }
-            Object otherValueObj = dataMap.get(otherFieldName);
-            otherValue = (otherValueObj == null) ? "" : otherValueObj.toString();
-        }
-        String frequency = "";
-        String minChars = "";
-        String choices = "";
-        String autoSelect = "";
-        String partialSearch = "";
-        String partialChars = "";
-        String ignoreCase = "";
-        String fullSearch = "";
-        if (ajaxEnabled) {
-            frequency = autoComplete.getFrequency();
-            minChars = autoComplete.getMinChars();
-            choices = autoComplete.getChoices();
-            autoSelect = autoComplete.getAutoSelect();
-            partialSearch = autoComplete.getPartialSearch();
-            partialChars = autoComplete.getPartialChars();
-            ignoreCase = autoComplete.getIgnoreCase();
-            fullSearch = autoComplete.getFullSearch();
-        }
-        StringWriter sr = new StringWriter();
-        sr.append("<@renderDropDownField ");
-        sr.append("name=\"");
-        sr.append(name);
-        sr.append("\" className=\"");
-        sr.append(className);
-        sr.append("\" alert=\"");
-        sr.append(alert);
-        sr.append("\" id=\"");
-        sr.append(id);
-        sr.append("\" multiple=\"");
-        sr.append(multiple);
-        sr.append("\" formName=\"");
-        sr.append(formName);
-        sr.append("\" otherFieldName=\"");
-        sr.append(otherFieldName);
-        sr.append("\" event=\"");
-        if (event != null) {
-            sr.append(event);
-        }
-        sr.append("\" action=\"");
-        if (action != null) {
-            sr.append(action);
-        }
-        sr.append("\" size=\"");
-        sr.append(size);
-        sr.append("\" firstInList=\"");
-        sr.append(firstInList);
-        sr.append("\" currentValue=\"");
-        sr.append(currentValue);
-        sr.append("\" explicitDescription=\"");
-        sr.append(explicitDescription);
-        sr.append("\" allowEmpty=\"");
-        sr.append(allowEmpty);
-        sr.append("\" options=");
-        sr.append(options.toString());
-        sr.append(" fieldName=\"");
-        sr.append(fieldName);
-        sr.append("\" otherFieldName=\"");
-        sr.append(otherFieldName);
-        sr.append("\" otherValue=\"");
-        sr.append(otherValue);
-        sr.append("\" otherFieldSize=");
-        sr.append(Integer.toString(otherFieldSize));
-        sr.append(" dDFCurrent=\"");
-        sr.append(dDFCurrent);
-        sr.append("\" ajaxEnabled=");
-        sr.append(Boolean.toString(ajaxEnabled));
-        sr.append(" noCurrentSelectedKey=\"");
-        sr.append(noCurrentSelectedKey);
-        sr.append("\" ajaxOptions=\"");
-        sr.append(ajaxOptions.toString());
-        sr.append("\" frequency=\"");
-        sr.append(frequency);
-        sr.append("\" minChars=\"");
-        sr.append(minChars);
-        sr.append("\" choices=\"");
-        sr.append(choices);
-        sr.append("\" autoSelect=\"");
-        sr.append(autoSelect);
-        sr.append("\" partialSearch=\"");
-        sr.append(partialSearch);
-        sr.append("\" partialChars=\"");
-        sr.append(partialChars);
-        sr.append("\" ignoreCase=\"");
-        sr.append(ignoreCase);
-        sr.append("\" fullSearch=\"");
-        sr.append(fullSearch);
-        sr.append("\" />");
-        executeMacro(writer, sr.toString());
-        ModelFormField.SubHyperlink subHyperlink = dropDownField.getSubHyperlink();
-        if (subHyperlink != null && subHyperlink.shouldUse(context)) {
-            makeHyperlinkString(writer, subHyperlink, context);
-        }
-        this.appendTooltip(writer, context, modelFormField);
-    }
-
-    public void renderCheckField(Appendable writer, Map<String, Object> context, CheckField checkField) throws IOException {
-        ModelFormField modelFormField = checkField.getModelFormField();
-        modelFormField.getModelForm();
-        String currentValue = modelFormField.getEntry(context);
-        Boolean allChecked = checkField.isAllChecked(context);
-        String id = modelFormField.getCurrentContainerId(context);
-        String className = "";
-        String alert = "false";
-        String name = modelFormField.getParameterName(context);
-        String event = modelFormField.getEvent();
-        String action = modelFormField.getAction(context);
-        StringBuilder items = new StringBuilder();
-        if (UtilValidate.isNotEmpty(modelFormField.getWidgetStyle())) {
-            className = modelFormField.getWidgetStyle();
-            if (modelFormField.shouldBeRed(context)) {
-                alert = "true";
-            }
-        }
-        List<ModelFormField.OptionValue> allOptionValues = checkField.getAllOptionValues(context, WidgetWorker.getDelegator(context));
-        items.append("[");
-        for (ModelFormField.OptionValue optionValue : allOptionValues) {
-            if (items.length() > 1) {
-                items.append(",");
-            }
-            items.append("{'value':'");
-            items.append(optionValue.getKey());
-            items.append("', 'description':'" + encode(optionValue.getDescription(), modelFormField, context));
-            items.append("'}");
-        }
-        items.append("]");
-        StringWriter sr = new StringWriter();
-        sr.append("<@renderCheckField ");
-        sr.append("items=");
-        sr.append(items.toString());
-        sr.append(" className=\"");
-        sr.append(className);
-        sr.append("\" alert=\"");
-        sr.append(alert);
-        sr.append("\" id=\"");
-        sr.append(id);
-        sr.append("\" allChecked=");
-        sr.append((allChecked != null ? Boolean.toString(allChecked) : "\"\""));
-        sr.append(" currentValue=\"");
-        sr.append(currentValue);
-        sr.append("\" name=\"");
-        sr.append(name);
-        sr.append("\" event=\"");
-        if (event != null) {
-            sr.append(event);
-        }
-        sr.append("\" action=\"");
-        if (action != null) {
-            sr.append(action);
-        }
-        sr.append("\" />");
-        executeMacro(writer, sr.toString());
-        this.appendTooltip(writer, context, modelFormField);
-    }
-
-    public void renderRadioField(Appendable writer, Map<String, Object> context, RadioField radioField) throws IOException {
-        ModelFormField modelFormField = radioField.getModelFormField();
-        modelFormField.getModelForm();
-        List<ModelFormField.OptionValue> allOptionValues = radioField.getAllOptionValues(context, WidgetWorker.getDelegator(context));
-        String currentValue = modelFormField.getEntry(context);
-        String className = "";
-        String alert = "false";
-        String name = modelFormField.getParameterName(context);
-        String event = modelFormField.getEvent();
-        String action = modelFormField.getAction(context);
-        StringBuilder items = new StringBuilder();
-        if (UtilValidate.isNotEmpty(modelFormField.getWidgetStyle())) {
-            className = modelFormField.getWidgetStyle();
-            if (modelFormField.shouldBeRed(context)) {
-                alert = "true";
-            }
-        }
-        String noCurrentSelectedKey = radioField.getNoCurrentSelectedKey(context);
-        items.append("[");
-        for (ModelFormField.OptionValue optionValue : allOptionValues) {
-            if (items.length() > 1) {
-                items.append(",");
-            }
-            items.append("{'key':'");
-            items.append(optionValue.getKey());
-            items.append("', 'description':'" + encode(optionValue.getDescription(), modelFormField, context));
-            items.append("'}");
-        }
-        items.append("]");
-        StringWriter sr = new StringWriter();
-        sr.append("<@renderRadioField ");
-        sr.append("items=");
-        sr.append(items.toString());
-        sr.append(" className=\"");
-        sr.append(className);
-        sr.append("\" alert=\"");
-        sr.append(alert);
-        sr.append("\" currentValue=\"");
-        sr.append(currentValue);
-        sr.append("\" noCurrentSelectedKey=\"");
-        sr.append(noCurrentSelectedKey);
-        sr.append("\" name=\"");
-        sr.append(name);
-        sr.append("\" event=\"");
-        if (event != null) {
-            sr.append(event);
-        }
-        sr.append("\" action=\"");
-        if (action != null) {
-            sr.append(action);
-        }
-        sr.append("\" />");
-        executeMacro(writer, sr.toString());
-        this.appendTooltip(writer, context, modelFormField);
-    }
-
-    public void renderSubmitField(Appendable writer, Map<String, Object> context, SubmitField submitField) throws IOException {
-        ModelFormField modelFormField = submitField.getModelFormField();
-        ModelForm modelForm = modelFormField.getModelForm();
-        String event = modelFormField.getEvent();
-        String action = modelFormField.getAction(context);
-        String title = modelFormField.getTitle(context);
-        String name = modelFormField.getParameterName(context);
-        String buttonType = submitField.getButtonType();
-        String formName = FormRenderer.getCurrentFormName(modelForm, context);
-        String imgSrc = submitField.getImageLocation(context);
-        String confirmation = submitField.getConfirmation(context);
-        String className = "";
-        String alert = "false";
-        if (UtilValidate.isNotEmpty(modelFormField.getWidgetStyle())) {
-            className = modelFormField.getWidgetStyle();
-            if (modelFormField.shouldBeRed(context)) {
-                alert = "true";
-            }
-        }
-        String formId = FormRenderer.getCurrentContainerId(modelForm, context);
-        List<ModelForm.UpdateArea> updateAreas = modelForm.getOnSubmitUpdateAreas();
-        // This is here for backwards compatibility. Use on-event-update-area
-        // elements instead.
-        String backgroundSubmitRefreshTarget = submitField.getBackgroundSubmitRefreshTarget(context);
-        if (UtilValidate.isNotEmpty(backgroundSubmitRefreshTarget)) {
-            if (updateAreas == null) {
-                updateAreas = new LinkedList<ModelForm.UpdateArea>();
-            }
-            updateAreas.add(new ModelForm.UpdateArea("submit", formId, backgroundSubmitRefreshTarget));
-        }
-        boolean ajaxEnabled = (UtilValidate.isNotEmpty(updateAreas) || UtilValidate.isNotEmpty(backgroundSubmitRefreshTarget)) && this.javaScriptEnabled;
-        String ajaxUrl = "";
-        if (ajaxEnabled) {
-            ajaxUrl = createAjaxParamsFromUpdateAreas(updateAreas, "", context);
-        }
-        StringWriter sr = new StringWriter();
-        sr.append("<@renderSubmitField ");
-        sr.append("buttonType=\"");
-        sr.append(buttonType);
-        sr.append("\" className=\"");
-        sr.append(className);
-        sr.append("\" alert=\"");
-        sr.append(alert);
-        sr.append("\" formName=\"");
-        sr.append(formName);
-        sr.append("\" title=\"");
-        sr.append(encode(title, modelFormField, context));
-        sr.append("\" name=\"");
-        sr.append(name);
-        sr.append("\" event=\"");
-        if (event != null) {
-            sr.append(event);
-        }
-        sr.append("\" action=\"");
-        if (action != null) {
-            sr.append(action);
-        }
-        sr.append("\" imgSrc=\"");
-        sr.append(imgSrc);
-        sr.append("\" containerId=\"");
-        if (ajaxEnabled) {
-            sr.append(formId);
-        }
-        sr.append("\" confirmation =\"");
-        sr.append(confirmation);
-        sr.append("\" ajaxUrl=\"");
-        if (ajaxEnabled) {
-            sr.append(ajaxUrl);
-        }
-        sr.append("\" />");
-        executeMacro(writer, sr.toString());
-        this.appendTooltip(writer, context, modelFormField);
-    }
-
-    public void renderResetField(Appendable writer, Map<String, Object> context, ResetField resetField) throws IOException {
-        ModelFormField modelFormField = resetField.getModelFormField();
-        String name = modelFormField.getParameterName(context);
-        String className = "";
-        String alert = "false";
-        if (UtilValidate.isNotEmpty(modelFormField.getWidgetStyle())) {
-            className = modelFormField.getWidgetStyle();
-            if (modelFormField.shouldBeRed(context)) {
-                alert = "true";
-            }
-        }
-        String title = modelFormField.getTitle(context);
-        StringWriter sr = new StringWriter();
-        sr.append("<@renderResetField ");
-        sr.append(" className=\"");
-        sr.append(className);
-        sr.append("\" alert=\"");
-        sr.append(alert);
-        sr.append("\" name=\"");
-        sr.append(name);
-        sr.append("\" title=\"");
-        sr.append(title);
-        sr.append("\" />");
-        executeMacro(writer, sr.toString());
-        this.appendTooltip(writer, context, modelFormField);
-    }
-
-    public void renderHiddenField(Appendable writer, Map<String, Object> context, HiddenField hiddenField) throws IOException {
-        ModelFormField modelFormField = hiddenField.getModelFormField();
-        String value = hiddenField.getValue(context);
-        this.renderHiddenField(writer, context, modelFormField, value);
-    }
-
-    public void renderHiddenField(Appendable writer, Map<String, Object> context, ModelFormField modelFormField, String value) throws IOException {
-        String name = modelFormField.getParameterName(context);
-        String action = modelFormField.getAction(context);
-        String event = modelFormField.getEvent();
-        String id = modelFormField.getCurrentContainerId(context);
-        StringWriter sr = new StringWriter();
-        sr.append("<@renderHiddenField ");
-        sr.append(" name=\"");
-        sr.append(name);
-        sr.append("\" value=\"");
-        sr.append(value);
-        sr.append("\" id=\"");
-        sr.append(id);
-        sr.append("\" event=\"");
-        if (event != null) {
-            sr.append(event);
-        }
-        sr.append("\" action=\"");
-        if (action != null) {
-            sr.append(action);
-        }
-        sr.append("\" />");
-        executeMacro(writer, sr.toString());
-    }
-
-    public void renderIgnoredField(Appendable writer, Map<String, Object> context, IgnoredField ignoredField) {
-        // do nothing, it's an ignored field; could add a comment or something if we wanted to
-    }
-
-    public void renderFieldTitle(Appendable writer, Map<String, Object> context, ModelFormField modelFormField) throws IOException {
-        String titleText = modelFormField.getTitle(context);
-        String style = modelFormField.getTitleStyle();
-        String id = modelFormField.getCurrentContainerId(context);
-        StringBuilder sb = new StringBuilder();
-        if (UtilValidate.isNotEmpty(titleText)) {
-            if (" ".equals(titleText)) {
-                executeMacro(writer, "<@renderFormatEmptySpace />");
-            } else {
-                titleText = UtilHttp.encodeAmpersands(titleText);
-                titleText = encode(titleText, modelFormField, context);
-                if (UtilValidate.isNotEmpty(modelFormField.getHeaderLink())) {
-                    StringBuilder targetBuffer = new StringBuilder();
-                    FlexibleStringExpander target = FlexibleStringExpander.getInstance(modelFormField.getHeaderLink());
-                    String fullTarget = target.expandString(context);
-                    targetBuffer.append(fullTarget);
-                    String targetType = CommonWidgetModels.Link.DEFAULT_URL_MODE;
-                    if (UtilValidate.isNotEmpty(targetBuffer.toString()) && targetBuffer.toString().toLowerCase().startsWith("javascript:")) {
-                        targetType = "plain";
-                    }
-                    StringWriter sr = new StringWriter();
-                    makeHyperlinkString(sr, modelFormField.getHeaderLinkStyle(), targetType, targetBuffer.toString(), null, titleText, "", modelFormField, this.request, this.response, context, "");
-                    String title = sr.toString().replace("\"", "\'");
-                    sr = new StringWriter();
-                    sr.append("<@renderHyperlinkTitle ");
-                    sr.append(" name=\"");
-                    sr.append(modelFormField.getModelForm().getName());
-                    sr.append("\" title=\"");
-                    sr.append(FreeMarkerWorker.encodeDoubleQuotes(title));
-                    sr.append("\" />");
-                    executeMacro(writer, sr.toString());
-                } else if (modelFormField.isSortField()) {
-                    renderSortField(writer, context, modelFormField, titleText);
-                } else if (modelFormField.isRowSubmit()) {
-                    StringWriter sr = new StringWriter();
-                    sr.append("<@renderHyperlinkTitle ");
-                    sr.append(" name=\"");
-                    sr.append(modelFormField.getModelForm().getName());
-                    sr.append("\" title=\"");
-                    sr.append(titleText);
-                    sr.append("\" showSelectAll=\"Y\"/>");
-                    executeMacro(writer, sr.toString());
-                } else {
-                    sb.append(titleText);
-                }
-            }
-        }
-        if (!sb.toString().isEmpty()) {
-            //check for required field style on single forms
-            if ("single".equals(modelFormField.getModelForm().getType()) && modelFormField.getRequiredField()) {
-                String requiredStyle = modelFormField.getRequiredFieldStyle();
-                if (UtilValidate.isNotEmpty(requiredStyle)) {
-                    style = requiredStyle;
-                }
-            }
-            StringWriter sr = new StringWriter();
-            sr.append("<@renderFieldTitle ");
-            sr.append(" style=\"");
-            sr.append(style);
-            String displayHelpText = UtilProperties.getPropertyValue("widget.properties", "widget.form.displayhelpText");
-            if ("Y".equals(displayHelpText)) {
-                Delegator delegator = WidgetWorker.getDelegator(context);
-                Locale locale = (Locale) context.get("locale");
-                String entityName = modelFormField.getEntityName();
-                String fieldName = modelFormField.getFieldName();
-                String helpText = UtilHelpText.getEntityFieldDescription(entityName, fieldName, delegator, locale);
-
-                sr.append("\" fieldHelpText=\"");
-                sr.append(FreeMarkerWorker.encodeDoubleQuotes(helpText));
-            }
-            sr.append("\" title=\"");
-            sr.append(sb.toString());
-            if (UtilValidate.isNotEmpty(id)) {
-                sr.append("\" id=\"");
-                sr.append(id);
-                sr.append("_title");
-                // Render "for"
-                sr.append("\" for=\"");
-                sr.append(id);
-            }
-            sr.append("\" />");
-            executeMacro(writer, sr.toString());
-        }
-    }
-
-    public void renderSingleFormFieldTitle(Appendable writer, Map<String, Object> context, ModelFormField modelFormField) throws IOException {
-        renderFieldTitle(writer, context, modelFormField);
-    }
-
-    public void renderFormOpen(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {
-        this.widgetCommentsEnabled = ModelWidget.widgetBoundaryCommentsEnabled(context);
-        renderBeginningBoundaryComment(writer, "Form Widget - Form Element", modelForm);
-        String targetType = modelForm.getTargetType();
-        String targ = modelForm.getTarget(context, targetType);
-        StringBuilder linkUrl = new StringBuilder();
-        if (UtilValidate.isNotEmpty(targ)) {
-            //this.appendOfbizUrl(writer, "/" + targ);
-            WidgetWorker.buildHyperlinkUrl(linkUrl, targ, targetType, null, null, false, false, true, request, response, context);
-        }
-        String formType = modelForm.getType();
-        String targetWindow = modelForm.getTargetWindow(context);
-        String containerId = FormRenderer.getCurrentContainerId(modelForm, context);
-        String containerStyle = modelForm.getContainerStyle();
-        String autocomplete = "";
-        String name = FormRenderer.getCurrentFormName(modelForm, context);
-        String viewIndexField = modelForm.getMultiPaginateIndexField(context);
-        String viewSizeField = modelForm.getMultiPaginateSizeField(context);
-        int viewIndex = Paginator.getViewIndex(modelForm, context);
-        int viewSize = Paginator.getViewSize(modelForm, context);
-        boolean useRowSubmit = modelForm.getUseRowSubmit();
-        if (!modelForm.getClientAutocompleteFields()) {
-            autocomplete = "off";
-        }
-        StringWriter sr = new StringWriter();
-        sr.append("<@renderFormOpen ");
-        sr.append(" linkUrl=\"");
-        sr.append(linkUrl);
-        sr.append("\" formType=\"");
-        sr.append(formType);
-        sr.append("\" targetWindow=\"");
-        sr.append(targetWindow);
-        sr.append("\" containerId=\"");
-        sr.append(containerId);
-        sr.append("\" containerStyle=\"");
-        sr.append(containerStyle);
-        sr.append("\" autocomplete=\"");
-        sr.append(autocomplete);
-        sr.append("\" name=\"");
-        sr.append(name);
-        sr.append("\" viewIndexField=\"");
-        sr.append(viewIndexField);
-        sr.append("\" viewSizeField=\"");
-        sr.append(viewSizeField);
-        sr.append("\" viewIndex=\"");
-        sr.append(Integer.toString(viewIndex));
-        sr.append("\" viewSize=\"");
-        sr.append(Integer.toString(viewSize));
-        sr.append("\" useRowSubmit=");
-        sr.append(Boolean.toString(useRowSubmit));
-        sr.append(" />");
-        executeMacro(writer, sr.toString());
-    }
-
-    public void renderFormClose(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {
-        String focusFieldName = FormRenderer.getFocusFieldName(modelForm, context);
-        String formName = FormRenderer.getCurrentFormName(modelForm, context);
-        String containerId = FormRenderer.getCurrentContainerId(modelForm, context);
-        String hasRequiredField = "";
-        for (ModelFormField formField : modelForm.getFieldList()) {
-            if (formField.getRequiredField()) {
-                hasRequiredField = "Y";
-                break;
-            }
-        }
-        StringWriter sr = new StringWriter();
-        sr.append("<@renderFormClose ");
-        sr.append(" focusFieldName=\"");
-        sr.append(focusFieldName);
-        sr.append("\" formName=\"");
-        sr.append(formName);
-        sr.append("\" containerId=\"");
-        sr.append(containerId);
-        sr.append("\" hasRequiredField=\"");
-        sr.append(hasRequiredField);
-        sr.append("\" />");
-        executeMacro(writer, sr.toString());
-        renderEndingBoundaryComment(writer, "Form Widget - Form Element", modelForm);
-    }
-
-    public void renderMultiFormClose(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {
-        //FIXME copy from HtmlFormRenderer.java (except for the closing form tag itself, that is now converted)
-        Iterator<ModelFormField> submitFields = modelForm.getMultiSubmitFields().iterator();
-        while (submitFields.hasNext()) {
-            ModelFormField submitField = submitFields.next();
-            if (submitField != null && submitField.shouldUse(context)) {
-                // Threw this in that as a hack to keep the submit button from expanding the first field
-                // Needs a more rugged solution
-                // WARNING: this method (renderMultiFormClose) must be called after the
-                // table that contains the list has been closed (to avoid validation errors) so
-                // we cannot call here the methods renderFormatItemRowCell*: for this reason
-                // they are now commented.
-                // this.renderFormatItemRowCellOpen(writer, context, modelForm, submitField);
-                // this.renderFormatItemRowCellClose(writer, context, modelForm, submitField);
-                // this.renderFormatItemRowCellOpen(writer, context, modelForm, submitField);
-                submitField.renderFieldString(writer, context, this);
-                // this.renderFormatItemRowCellClose(writer, context, modelForm, submitField);
-            }
-        }
-        StringWriter sr = new StringWriter();
-        sr.append("<@renderMultiFormClose />");
-        executeMacro(writer, sr.toString());
-        // see if there is anything that needs to be added outside of the multi-form
-        Map<String, Object> wholeFormContext = UtilGenerics.checkMap(context.get("wholeFormContext"));
-        Appendable postMultiFormWriter = wholeFormContext != null ? (Appendable) wholeFormContext.get("postMultiFormWriter") : null;
-        if (postMultiFormWriter != null) {
-            writer.append(postMultiFormWriter.toString());
-            appendWhitespace(writer);
-        }
-        renderEndingBoundaryComment(writer, "Form Widget - Form Element (Multi)", modelForm);
-    }
-
-    public void renderFormatListWrapperOpen(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {
-        Map<String, Object> inputFields = UtilGenerics.checkMap(context.get("requestParameters"));
-        Map<String, Object> queryStringMap = UtilGenerics.toMap(context.get("queryStringMap"));
-        if (UtilValidate.isNotEmpty(queryStringMap)) {
-            inputFields.putAll(queryStringMap);
-        }
-        if (modelForm.getType().equals("multi")) {
-            inputFields = UtilHttp.removeMultiFormParameters(inputFields);
-        }
-        String queryString = UtilHttp.urlEncodeArgs(inputFields);
-        context.put("_QBESTRING_", queryString);
-        renderBeginningBoundaryComment(writer, "Form Widget", modelForm);
-        if (this.renderPagination) {
-            this.renderNextPrev(writer, context, modelForm);
-        }
-        List<ModelFormField> childFieldList = modelForm.getFieldList();
-        List<String> columnStyleList = new LinkedList<String>();
-        List<String> fieldNameList = new LinkedList<String>();
-        for (ModelFormField childField : childFieldList) {
-            int childFieldType = childField.getFieldInfo().getFieldType();
-            if (childFieldType == FieldInfo.HIDDEN || childFieldType == FieldInfo.IGNORED) {
-                continue;
-            }
-            String areaStyle = childField.getTitleAreaStyle();
-            if (UtilValidate.isEmpty(areaStyle)) {
-                areaStyle = "";
-            }
-            if (fieldNameList.contains(childField.getName())) {
-                if (UtilValidate.isNotEmpty(areaStyle)) {
-                    columnStyleList.set(fieldNameList.indexOf(childField.getName()), areaStyle);
-                }
-            } else {
-                columnStyleList.add(areaStyle);
-                fieldNameList.add(childField.getName());
-            }
-        }
-        columnStyleList = StringUtil.quoteStrList(columnStyleList);
-        String columnStyleListString = StringUtil.join(columnStyleList, ", ");
-        StringWriter sr = new StringWriter();
-        sr.append("<@renderFormatListWrapperOpen ");
-        sr.append(" formName=\"");
-        sr.append(modelForm.getName());
-        sr.append("\" style=\"");
-        sr.append(FlexibleStringExpander.expandString(modelForm.getDefaultTableStyle(), context));
-        sr.append("\" columnStyles=[");
-        if (UtilValidate.isNotEmpty(columnStyleListString)) {
-            // this is a fix for forms with no fields
-            sr.append(columnStyleListString);
-        }
-        sr.append("] />");
-        executeMacro(writer, sr.toString());
-
-    }
-
-    public void renderFormatListWrapperClose(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {
-        StringWriter sr = new StringWriter();
-        sr.append("<@renderFormatListWrapperClose");
-        sr.append(" formName=\"");
-        sr.append(modelForm.getName());
-        sr.append("\" />");
-        executeMacro(writer, sr.toString());
-        if (this.renderPagination) {
-            this.renderNextPrev(writer, context, modelForm);
-        }
-        renderEndingBoundaryComment(writer, "Form Widget - Formal List Wrapper", modelForm);
-    }
-
-    public void renderFormatHeaderRowOpen(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {
-        String headerStyle = FlexibleStringExpander.expandString(modelForm.getHeaderRowStyle(), context);
-        StringWriter sr = new StringWriter();
-        sr.append("<@renderFormatHeaderRowOpen ");
-        sr.append(" style=\"");
-        sr.append(headerStyle);
-        sr.append("\" />");
-        executeMacro(writer, sr.toString());
-    }
-
-    public void renderFormatHeaderRowClose(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {
-        StringWriter sr = new StringWriter();
-        sr.append("<@renderFormatHeaderRowClose />");
-        executeMacro(writer, sr.toString());
-    }
-
-    public void renderFormatHeaderRowCellOpen(Appendable writer, Map<String, Object> context, ModelForm modelForm, ModelFormField modelFormField, int positionSpan) throws IOException {
-        String areaStyle = modelFormField.getTitleAreaStyle();
-        StringWriter sr = new StringWriter();
-        sr.append("<@renderFormatHeaderRowCellOpen ");
-        sr.append(" style=\"");
-        sr.append(areaStyle);
-        sr.append("\" positionSpan=");
-        sr.append(Integer.toString(positionSpan));
-        sr.append(" />");
-        executeMacro(writer, sr.toString());
-    }
-
-    public void renderFormatHeaderRowCellClose(Appendable writer, Map<String, Object> context, ModelForm modelForm, ModelFormField modelFormField) throws IOException {
-        StringWriter sr = new StringWriter();
-        sr.append("<@renderFormatHeaderRowCellClose />");
-        executeMacro(writer, sr.toString());
-    }
-
-    public void renderFormatHeaderRowFormCellOpen(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {
-        String areaStyle = modelForm.getFormTitleAreaStyle();
-        StringWriter sr = new StringWriter();
-        sr.append("<@renderFormatHeaderRowFormCellOpen ");
-        sr.append(" style=\"");
-        sr.append(areaStyle);
-        sr.append("\" />");
-        executeMacro(writer, sr.toString());
-    }
-
-    public void renderFormatHeaderRowFormCellClose(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {
-        StringWriter sr = new StringWriter();
-        sr.append("<@renderFormatHeaderRowFormCellClose />");
-        executeMacro(writer, sr.toString());
-    }
-
-    public void renderFormatHeaderRowFormCellTitleSeparator(Appendable writer, Map<String, Object> context, ModelForm modelForm, ModelFormField modelFormField, boolean isLast) throws IOException {
-        String titleStyle = modelFormField.getTitleStyle();
-        StringWriter sr = new StringWriter();
-        sr.append("<@renderFormatHeaderRowFormCellTitleSeparator ");
-        sr.append(" style=\"");
-        sr.append(titleStyle);
-        sr.append("\" isLast=");
-        sr.append(Boolean.toString(isLast));
-        sr.append(" />");
-        executeMacro(writer, sr.toString());
-    }
-
-    public void renderFormatItemRowOpen(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {
-        Integer itemIndex = (Integer) context.get("itemIndex");
-        String altRowStyles = "";
-        String evenRowStyle = "";
-        String oddRowStyle = "";
-        if (itemIndex != null) {
-            altRowStyles = modelForm.getStyleAltRowStyle(context);
-            if (itemIndex.intValue() % 2 == 0) {
-                evenRowStyle = modelForm.getEvenRowStyle();
-            } else {
-                oddRowStyle = FlexibleStringExpander.expandString(modelForm.getOddRowStyle(), context);
-            }
-        }
-        StringWriter sr = new StringWriter();
-        sr.append("<@renderFormatItemRowOpen ");
-        sr.append(" formName=\"");
-        sr.append(modelForm.getName());
-        sr.append("\" itemIndex=");
-        sr.append(Integer.toString(itemIndex));
-        sr.append(" altRowStyles=\"");
-        sr.append(altRowStyles);
-        sr.append("\" evenRowStyle=\"");
-        sr.append(evenRowStyle);
-        sr.append("\" oddRowStyle=\"");
-        sr.append(oddRowStyle);
-        sr.append("\" />");
-        executeMacro(writer, sr.toString());
-    }
-
-    public void renderFormatItemRowClose(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {
-        StringWriter sr = new StringWriter();
-        sr.append("<@renderFormatItemRowClose ");
-        sr.append(" formName=\"");
-        sr.append(modelForm.getName());
-        sr.append("\"/>");
-        executeMacro(writer, sr.toString());
-    }
-
-    public void renderFormatItemRowCellOpen(Appendable writer, Map<String, Object> context, ModelForm modelForm, ModelFormField modelFormField, int positionSpan) throws IOException {
-        String areaStyle = modelFormField.getWidgetAreaStyle();
-        StringWriter sr = new StringWriter();
-        sr.append("<@renderFormatItemRowCellOpen ");
-        sr.append(" fieldName=\"");
-        sr.append(modelFormField.getName());
-        sr.append("\" style=\"");
-        sr.append(areaStyle);
-        sr.append("\" positionSpan=");
-        sr.append(Integer.toString(positionSpan));
-        sr.append(" />");
-        executeMacro(writer, sr.toString());
-    }
-
-    public void renderFormatItemRowCellClose(Appendable writer, Map<String, Object> context, ModelForm modelForm, ModelFormField modelFormField) throws IOException {
-        StringWriter sr = new StringWriter();
-        sr.append("<@renderFormatItemRowCellClose");
-        sr.append(" fieldName=\"");
-        sr.append(modelFormField.getName());
-        sr.append("\"/>");
-        executeMacro(writer, sr.toString());
-    }
-
-    public void renderFormatItemRowFormCellOpen(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {
-        String areaStyle = modelForm.getFormTitleAreaStyle();
-        StringWriter sr = new StringWriter();
-        sr.append("<@renderFormatItemRowFormCellOpen ");
-        sr.append(" style=\"");
-        sr.append(areaStyle);
-        sr.append("\" />");
-        executeMacro(writer, sr.toString());
-    }
-
-    public void renderFormatItemRowFormCellClose(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {
-        StringWriter sr = new StringWriter();
-        sr.append("<@renderFormatItemRowFormCellClose />");
-        executeMacro(writer, sr.toString());
-    }
-
-    public void renderFormatSingleWrapperOpen(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {
-        String style = FlexibleStringExpander.expandString(modelForm.getDefaultTableStyle(), context);
-        StringWriter sr = new StringWriter();
-        sr.append("<@renderFormatSingleWrapperOpen ");
-        sr.append(" formName=\"");
-        sr.append(modelForm.getName());
-        sr.append("\" style=\"");
-        sr.append(style);
-        sr.append("\" />");
-        executeMacro(writer, sr.toString());
-    }
-
-    public void renderFormatSingleWrapperClose(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {
-        StringWriter sr = new StringWriter();
-        sr.append("<@renderFormatSingleWrapperClose");
-        sr.append(" formName=\"");
-        sr.append(modelForm.getName());
-        sr.append("\"/>");
-        executeMacro(writer, sr.toString());
-    }
-
-    public void renderFormatFieldRowOpen(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {
-        StringWriter sr = new StringWriter();
-        sr.append("<@renderFormatFieldRowOpen />");
-        executeMacro(writer, sr.toString());
-    }
-
-    public void renderFormatFieldRowClose(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {
-        StringWriter sr = new StringWriter();
-        sr.append("<@renderFormatFieldRowClose />");
-        executeMacro(writer, sr.toString());
-    }
-
-    public void renderFormatFieldRowTitleCellOpen(Appendable writer, Map<String, Object> context, ModelFormField modelFormField) throws IOException {
-        String style = modelFormField.getTitleAreaStyle();
-        StringWriter sr = new StringWriter();
-        sr.append("<@renderFormatFieldRowTitleCellOpen ");
-        sr.append(" style=\"");
-        sr.append(style);
-        sr.append("\" />");
-        executeMacro(writer, sr.toString());
-    }
-
-    public void renderFormatFieldRowTitleCellClose(Appendable writer, Map<String, Object> context, ModelFormField modelFormField) throws IOException {
-        StringWriter sr = new StringWriter();
-        sr.append("<@renderFormatFieldRowTitleCellClose />");
-        executeMacro(writer, sr.toString());
-    }
-
-    public void renderFormatFieldRowSpacerCell(Appendable writer, Map<String, Object> context, ModelFormField modelFormField) throws IOException {
-    }
-
-    public void renderFormatFieldRowWidgetCellOpen(Appendable writer, Map<String, Object> context, ModelFormField modelFormField, int positions, int positionSpan, Integer nextPositionInRow) throws IOException {
-        String areaStyle = modelFormField.getWidgetAreaStyle();
-        StringWriter sr = new StringWriter();
-        sr.append("<@renderFormatFieldRowWidgetCellOpen ");
-        sr.append(" positionSpan=");
-        sr.append(Integer.toString(positionSpan));
-        sr.append(" style=\"");
-        sr.append(areaStyle);
-        sr.append("\" />");
-        executeMacro(writer, sr.toString());
-    }
-
-    public void renderFormatFieldRowWidgetCellClose(Appendable writer, Map<String, Object> context, ModelFormField modelFormField, int positions, int positionSpan, Integer nextPositionInRow) throws IOException {
-        StringWriter sr = new StringWriter();
-        sr.append("<@renderFormatFieldRowWidgetCellClose />");
-        executeMacro(writer, sr.toString());
-    }
-
-    public void renderFormatEmptySpace(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {
-        StringWriter sr = new StringWriter();
-        sr.append("<@renderFormatEmptySpace />");
-        executeMacro(writer, sr.toString());
-    }
-
-    public void renderTextFindField(Appendable writer, Map<String, Object> context, TextFindField textFindField) throws IOException {
-        ModelFormField modelFormField = textFindField.getModelFormField();
-        String defaultOption = textFindField.getDefaultOption();
-        String className = "";
-        String alert = "false";
-        String opEquals = "";
-        String opBeginsWith = "";
-        String opContains = "";
-        String opIsEmpty = "";
-        String opNotEqual = "";
-        String name = modelFormField.getParameterName(context);
-        String size = Integer.toString(textFindField.getSize());
-        String maxlength = "";
-        String autocomplete = "";
-        if (UtilValidate.isNotEmpty(modelFormField.getWidgetStyle())) {
-            className = modelFormField.getWidgetStyle();
-            if (modelFormField.shouldBeRed(context)) {
-                alert = "true";
-            }
-        }
-        Locale locale = (Locale) context.get("locale");
-        if (!textFindField.getHideOptions()) {
-            opEquals = UtilProperties.getMessage("conditional", "equals", locale);
-            opBeginsWith = UtilProperties.getMessage("conditional", "begins_with", locale);
-            opContains = UtilProperties.getMessage("conditional", "contains", locale);
-            opIsEmpty = UtilProperties.getMessage("conditional", "is_empty", locale);
-            opNotEqual = UtilProperties.getMessage("conditional", "not_equal", locale);
-        }
-        String value = modelFormField.getEntry(context, textFindField.getDefaultValue(context));
-        if (value == null) {
-            value = "";
-        }
-        if (textFindField.getMaxlength() != null) {
-            maxlength = textFindField.getMaxlength().toString();
-        }
-        if (!textFindField.getClientAutocompleteField()) {
-            autocomplete = "off";
-        }
-        String titleStyle = "";
-        if (UtilValidate.isNotEmpty(modelFormField.getTitleStyle())) {
-            titleStyle = modelFormField.getTitleStyle();
-        }
-        String ignoreCase = UtilProperties.getMessage("conditional", "ignore_case", locale);
-        boolean ignCase = textFindField.getIgnoreCase();
-        boolean hideIgnoreCase = textFindField.getHideIgnoreCase();
-        StringWriter sr = new StringWriter();
-        sr.append("<@renderTextFindField ");
-        sr.append(" name=\"");
-        sr.append(name);
-        sr.append("\" value=\"");
-        sr.append(value);
-        sr.append("\" defaultOption=\"");
-        sr.append(defaultOption);
-        sr.append("\" opEquals=\"");
-        sr.append(opEquals);
-        sr.append("\" opBeginsWith=\"");
-        sr.append(opBeginsWith);
-        sr.append("\" opContains=\"");
-        sr.append(opContains);
-        sr.append("\" opIsEmpty=\"");
-        sr.append(opIsEmpty);
-        sr.append("\" opNotEqual=\"");
-        sr.append(opNotEqual);
-        sr.append("\" className=\"");
-        sr.append(className);
-        sr.append("\" alert=\"");
-        sr.append(alert);
-        sr.append("\" size=\"");
-        sr.append(size);
-        sr.append("\" maxlength=\"");
-        sr.append(maxlength);
-        sr.append("\" autocomplete=\"");
-        sr.append(autocomplete);
-        sr.append("\" titleStyle=\"");
-        sr.append(titleStyle);
-        sr.append("\" hideIgnoreCase=");
-        sr.append(Boolean.toString(hideIgnoreCase));
-        sr.append(" ignCase=");
-        sr.append(Boolean.toString(ignCase));
-        sr.append(" ignoreCase=\"");
-        sr.append(ignoreCase);
-        sr.append("\" />");
-        executeMacro(writer, sr.toString());
-        this.appendTooltip(writer, context, modelFormField);
-    }
-
-    public void renderRangeFindField(Appendable writer, Map<String, Object> context, RangeFindField rangeFindField) throws IOException {
-        ModelFormField modelFormField = rangeFindField.getModelFormField();
-        Locale locale = (Locale) context.get("locale");
-        String opEquals = UtilProperties.getMessage("conditional", "equals", locale);
-        String opGreaterThan = UtilProperties.getMessage("conditional", "greater_than", locale);
-        String opGreaterThanEquals = UtilProperties.getMessage("conditional", "greater_than_equals", locale);
-        String opLessThan = UtilProperties.getMessage("conditional", "less_than", locale);
-        String opLessThanEquals = UtilProperties.getMessage("conditional", "less_than_equals", locale);
-        //String opIsEmpty = UtilProperties.getMessage("conditional", "is_empty", locale);
-        String className = "";
-        String alert = "false";
-        if (UtilValidate.isNotEmpty(modelFormField.getWidgetStyle())) {
-            className = modelFormField.getWidgetStyle();
-            if (modelFormField.shouldBeRed(context)) {
-                alert = "true";
-            }
-        }
-        String name = modelFormField.getParameterName(context);
-        String size = Integer.toString(rangeFindField.getSize());
-        String value = modelFormField.getEntry(context, rangeFindField.getDefaultValue(context));
-        if (value == null) {
-            value = "";
-        }
-        Integer maxlength = rangeFindField.getMaxlength();
-        String autocomplete = "";
-
-        if (!rangeFindField.getClientAutocompleteField()) {
-            autocomplete = "off";
-        }
-        String titleStyle = modelFormField.getTitleStyle();
-
-        if (titleStyle == null) {
-            titleStyle = "";
-        }
-        String defaultOptionFrom = rangeFindField.getDefaultOptionFrom();
-        String value2 = modelFormField.getEntry(context);
-        if (value2 == null) {
-            value2 = "";
-        }
-        String defaultOptionThru = rangeFindField.getDefaultOptionThru();
-        StringWriter sr = new StringWriter();
-        sr.append("<@renderRangeFindField ");
-        sr.append(" className=\"");
-        sr.append(className);
-        sr.append("\" alert=\"");
-        sr.append(alert);
-        sr.append("\" name=\"");
-        sr.append(name);
-        sr.append("\" value=\"");
-        sr.append(value);
-        sr.append("\" size=\"");
-        sr.append(size);
-        sr.append("\" maxlength=\"");
-        if (maxlength != null) {
-            sr.append(Integer.toString(maxlength));
-        }
-        sr.append("\" autocomplete=\"");
-        sr.append(autocomplete);
-        sr.append("\" titleStyle=\"");
-        sr.append(titleStyle);
-        sr.append("\" defaultOptionFrom=\"");
-        sr.append(defaultOptionFrom);
-        sr.append("\" opEquals=\"");
-        sr.append(opEquals);
-        sr.append("\" opGreaterThan=\"");
-        sr.append(opGreaterThan);
-        sr.append("\" opGreaterThanEquals=\"");
-        sr.append(opGreaterThanEquals);
-        sr.append("\" opLessThan=\"");
-        sr.append(opLessThan);
-        sr.append("\" opLessThanEquals=\"");
-        sr.append(opLessThanEquals);
-        sr.append("\" value2=\"");
-        sr.append(value2);
-        sr.append("\" defaultOptionThru=\"");
-        sr.append(defaultOptionThru);
-        sr.append("\" />");
-        executeMacro(writer, sr.toString());
-        this.appendTooltip(writer, context, modelFormField);
-    }
-
-    public void renderDateFindField(Appendable writer, Map<String, Object> context, DateFindField dateFindField) throws IOException {
-        ModelFormField modelFormField = dateFindField.getModelFormField();
-        Locale locale = (Locale) context.get("locale");
-        String opEquals = UtilProperties.getMessage("conditional", "equals", locale);
-        String opGreaterThan = UtilProperties.getMessage("conditional", "greater_than", locale);
-        String opSameDay = UtilProperties.getMessage("conditional", "same_day", locale);
-        String opGreaterThanFromDayStart = UtilProperties.getMessage("conditional", "greater_than_from_day_start", locale);
-        String opLessThan = UtilProperties.getMessage("conditional", "less_than", locale);
-        String opUpToDay = UtilProperties.getMessage("conditional", "up_to_day", locale);
-        String opUpThruDay = UtilProperties.getMessage("conditional", "up_thru_day", locale);
-        String opIsEmpty = UtilProperties.getMessage("conditional", "is_empty", locale);
-        Map<String, String> uiLabelMap = UtilGenerics.checkMap(context.get("uiLabelMap"));
-        if (uiLabelMap == null) {
-            Debug.logWarning("Could not find uiLabelMap in context", module);
-        }
-        String localizedInputTitle = "", localizedIconTitle = "";
-        String className = "";
-        String alert = "false";
-        if (UtilValidate.isNotEmpty(modelFormField.getWidgetStyle())) {
-            className = modelFormField.getWidgetStyle();
-            if (modelFormField.shouldBeRed(context)) {
-                alert = "true";
-            }
-        }
-        String name = modelFormField.getParameterName(context);
-        // the default values for a timestamp
-        int size = 25;
-        int maxlength = 30;
-        String dateType = dateFindField.getType();
-        if ("date".equals(dateType)) {
-            size = maxlength = 10;
-            if (uiLabelMap != null) {
-                localizedInputTitle = uiLabelMap.get("CommonFormatDate");
-            }
-        } else if ("time".equals(dateFindField.getType())) {
-            size = maxlength = 8;
-            if (uiLabelMap != null) {
-                localizedInputTitle = uiLabelMap.get("CommonFormatTime");
-            }
-        } else {
-            if (uiLabelMap != null) {
-                localizedInputTitle = uiLabelMap.get("CommonFormatDateTime");
-            }
-        }
-        String value = modelFormField.getEntry(context, dateFindField.getDefaultValue(context));
-        if (value == null) {
-            value = "";
-        }
-        // search for a localized label for the icon
-        if (uiLabelMap != null) {
-            localizedIconTitle = uiLabelMap.get("CommonViewCalendar");
-        }
-        String formName = "";
-        String defaultDateTimeString = "";
-        StringBuilder imgSrc = new StringBuilder();
-        // add calendar pop-up button and seed data IF this is not a "time" type date-find
-        if (!"time".equals(dateFindField.getType())) {
-            ModelForm modelForm = modelFormField.getModelForm();
-            formName = FormRenderer.getCurrentFormName(modelForm, context);
-            defaultDateTimeString = UtilHttp.encodeBlanks(modelFormField.getEntry(context, dateFindField.getDefaultDateTimeString(context)));
-            this.appendContentUrl(imgSrc, "/images/cal.gif");
-        }
-        String defaultOptionFrom = dateFindField.getDefaultOptionFrom();
-        String defaultOptionThru = dateFindField.getDefaultOptionThru();
-        String value2 = modelFormField.getEntry(context);
-        if (value2 == null) {
-            value2 = "";
-        }
-        String titleStyle = "";
-        if (UtilValidate.isNotEmpty(modelFormField.getTitleStyle())) {
-            titleStyle = modelFormField.getTitleStyle();
-        }
-        StringWriter sr = new StringWriter();
-        sr.append("<@renderDateFindField ");
-        sr.append(" className=\"");
-        sr.append(className);
-        sr.append("\" alert=\"");
-        sr.append(alert);
-        sr.append("\" name=\"");
-        sr.append(name);
-        sr.append("\" localizedInputTitle=\"");
-        sr.append(localizedInputTitle);
-        sr.append("\" value=\"");
-        sr.append(value);
-        sr.append("\" size=\"");
-        sr.append(Integer.toString(size));
-        sr.append("\" maxlength=\"");
-        sr.append(Integer.toString(maxlength));
-        sr.append("\" dateType=\"");
-        sr.append(dateType);
-        sr.append("\" formName=\"");
-        sr.append(formName);
-        sr.append("\" defaultDateTimeString=\"");
-        sr.append(defaultDateTimeString);
-        sr.append("\" imgSrc=\"");
-        sr.append(imgSrc.toString());
-        sr.append("\" localizedIconTitle=\"");
-        sr.append(localizedIconTitle);
-        sr.append("\" titleStyle=\"");
-        sr.append(titleStyle);
-        sr.append("\" defaultOptionFrom=\"");
-        sr.append(defaultOptionFrom);
-        sr.append("\" defaultOptionThru=\"");
-        sr.append(defaultOptionThru);
-        sr.append("\" opEquals=\"");
-        sr.append(opEquals);
-        sr.append("\" opSameDay=\"");
-        sr.append(opSameDay);
-        sr.append("\" opGreaterThanFromDayStart=\"");
-        sr.append(opGreaterThanFromDayStart);
-        sr.append("\" opGreaterThan=\"");
-        sr.append(opGreaterThan);
-        sr.append("\" opGreaterThan=\"");
-        sr.append(opGreaterThan);
-        sr.append("\" opLessThan=\"");
-        sr.append(opLessThan);
-        sr.append("\" opUpToDay=\"");
-        sr.append(opUpToDay);
-        sr.append("\" opUpThruDay=\"");
-        sr.append(opUpThruDay);
-        sr.append("\" opIsEmpty=\"");
-        sr.append(opIsEmpty);
-        sr.append("\" />");
-        executeMacro(writer, sr.toString());
-        this.appendTooltip(writer, context, modelFormField);
-    }
-
-    public void renderLookupField(Appendable writer, Map<String, Object> context, LookupField lookupField) throws IOException {
-        ModelFormField modelFormField = lookupField.getModelFormField();
-        String lookupFieldFormName = lookupField.getFormName(context);
-        String className = "";
-        String alert = "false";
-        if (UtilValidate.isNotEmpty(modelFormField.getWidgetStyle())) {
-            className = modelFormField.getWidgetStyle();
-            if (modelFormField.shouldBeRed(context)) {
-                alert = "true";
-            }
-        }
-        //check for required field style on single forms
-        if ("single".equals(modelFormField.getModelForm().getType()) && modelFormField.getRequiredField()) {
-            String requiredStyle = modelFormField.getRequiredFieldStyle();
-            if (UtilValidate.isEmpty(requiredStyle))
-                requiredStyle = "required";
-            if (UtilValidate.isEmpty(className))
-                className = requiredStyle;
-            else
-                className = requiredStyle + " " + className;
-        }
-        String name = modelFormField.getParameterName(context);
-        String value = modelFormField.getEntry(context, lookupField.getDefaultValue(context));
-        if (value == null) {
-            value = "";
-        }
-        String size = Integer.toString(lookupField.getSize());
-        Integer maxlength = lookupField.getMaxlength();
-        String id = modelFormField.getCurrentContainerId(context);
-        List<ModelForm.UpdateArea> updateAreas = modelFormField.getOnChangeUpdateAreas();
-        //add default ajax auto completer to all lookup fields
-        if (UtilValidate.isEmpty(updateAreas) && UtilValidate.isNotEmpty(lookupFieldFormName)) {
-            String autoCompleterTarget = null;
-            if (lookupFieldFormName.indexOf('?') == -1) {
-                autoCompleterTarget = lookupFieldFormName + "?";
-            } else {
-                autoCompleterTarget = lookupFieldFormName + "&amp;amp;";
-            }
-            autoCompleterTarget = autoCompleterTarget + "ajaxLookup=Y";
-            updateAreas = new LinkedList<ModelForm.UpdateArea>();
-            updateAreas.add(new ModelForm.UpdateArea("change", id, autoCompleterTarget));
-        }
-        boolean ajaxEnabled = UtilValidate.isNotEmpty(updateAreas) && this.javaScriptEnabled;
-        String autocomplete = "";
-        if (!lookupField.getClientAutocompleteField() || !ajaxEnabled) {
-            autocomplete = "off";
-        }
-        String event = modelFormField.getEvent();
-        String action = modelFormField.getAction(context);
-        boolean readonly = lookupField.getReadonly();
-        // add lookup pop-up button
-        String descriptionFieldName = lookupField.getDescriptionFieldName();
-        ModelForm modelForm = modelFormField.getModelForm();
-        String formName = FormRenderer.getCurrentFormName(modelForm, context);
-        StringBuilder targetParameterIter = new StringBuilder();
-        StringBuilder imgSrc = new StringBuilder();
-        // FIXME: refactor using the StringUtils methods
-        List<String> targetParameterList = lookupField.getTargetParameterList();
-        targetParameterIter.append("[");
-        for (String targetParameter : targetParameterList) {
-            if (targetParameterIter.length() > 1) {
-                targetParameterIter.append(",");
-            }
-            targetParameterIter.append("'");
-            targetParameterIter.append(targetParameter);
-            targetParameterIter.append("'");
-        }
-        targetParameterIter.append("]");
-        this.appendContentUrl(imgSrc, "/images/fieldlookup.gif");
-        String ajaxUrl = "";
-        if (ajaxEnabled) {
-            ajaxUrl = createAjaxParamsFromUpdateAreas(updateAreas, "", context);
-        }
-        String lookupPresentation = lookupField.getLookupPresentation();
-        if (UtilValidate.isEmpty(lookupPresentation)) {
-            lookupPresentation = "";
-        }
-        String lookupHeight = lookupField.getLookupHeight();
-        if (UtilValidate.isEmpty(lookupHeight)) {
-            lookupHeight = "";
-        }
-        String lookupWidth = lookupField.getLookupWidth();
-        if (UtilValidate.isEmpty(lookupWidth)) {
-            lookupWidth = "";
-        }
-        String lookupPosition = lookupField.getLookupPosition();
-        if (UtilValidate.isEmpty(lookupPosition)) {
-            lookupPosition = "";
-        }
-        String fadeBackground = lookupField.getFadeBackground();
-        if (UtilValidate.isEmpty(fadeBackground)) {
-            fadeBackground = "false";
-        }
-        Boolean isInitiallyCollapsed = lookupField.getInitiallyCollapsed();
-        String clearText = "";
-        Map<String, Object> uiLabelMap = UtilGenerics.checkMap(context.get("uiLabelMap"));
-        if (uiLabelMap != null) {
-            clearText = (String) uiLabelMap.get("CommonClear");
-        } else {
-            Debug.logWarning("Could not find uiLabelMap in context", module);
-        }
-        Boolean showDescription = lookupField.getShowDescription();
-        if (showDescription == null) {
-            showDescription = "Y".equals(UtilProperties.getPropertyValue("widget", "widget.lookup.showDescription", "Y"));
-        }
-        // lastViewName, used by lookup to remember the real last view name
-        String lastViewName = request.getParameter("_LAST_VIEW_NAME_"); // Try to get it from parameters firstly
-        if (UtilValidate.isEmpty(lastViewName)) { // get from session
-            lastViewName = (String) request.getSession().getAttribute("_LAST_VIEW_NAME_");
-        }
-        if (UtilValidate.isEmpty(lastViewName)) {
-            lastViewName = "";
-        }
-        StringWriter sr = new StringWriter();
-        sr.append("<@renderLookupField ");
-        sr.append(" className=\"");
-        sr.append(className);
-        sr.append("\" alert=\"");
-        sr.append(alert);
-        sr.append("\" name=\"");
-        sr.append(name);
-        sr.append("\" value=\"");
-        sr.append(value);
-        sr.append("\" size=\"");
-        sr.append(size);
-        sr.append("\" maxlength=\"");
-        sr.append((maxlength != null ? Integer.toString(maxlength) : ""));
-        sr.append("\" id=\"");
-        sr.append(id);
-        sr.append("\" event=\"");
-        if (event != null) {
-            sr.append(event);
-        }
-        sr.append("\" action=\"");
-        if (action != null) {
-            sr.append(action);
-        }
-        sr.append("\" readonly=");
-        sr.append(Boolean.toString(readonly));
-        sr.append(" autocomplete=\"");
-        sr.append(autocomplete);
-        sr.append("\" descriptionFieldName=\"");
-        sr.append(descriptionFieldName);
-        sr.append("\" formName=\"");
-        sr.append(formName);
-        sr.append("\" fieldFormName=\"");
-        sr.append(lookupFieldFormName);
-        sr.append("\" targetParameterIter=");
-        sr.append(targetParameterIter.toString());
-        sr.append(" imgSrc=\"");
-        sr.append(imgSrc.toString());
-        sr.append("\" ajaxUrl=\"");
-        sr.append(ajaxUrl);
-        sr.append("\" ajaxEnabled=");
-        sr.append(Boolean.toString(ajaxEnabled));
-        sr.append(" presentation=\"");
-        sr.append(lookupPresentation);
-        sr.append("\" height=\"");
-        sr.append(lookupHeight);
-        sr.append("\" width=\"");
-        sr.append(lookupWidth);
-        sr.append("\" position=\"");
-        sr.append(lookupPosition);
-        sr.append("\" fadeBackground=\"");
-        sr.append(fadeBackground);
-        sr.append("\" clearText=\"");
-        sr.append(clearText);
-        sr.append("\" showDescription=\"");
-        sr.append(Boolean.toString(showDescription));
-        sr.append("\" initiallyCollapsed=\"");
-        sr.append(Boolean.toString(isInitiallyCollapsed));
-        sr.append("\" lastViewName=\"");
-        sr.append(lastViewName);
-        sr.append("\" />");
-        executeMacro(writer, sr.toString());
-        this.addAsterisks(writer, context, modelFormField);
-        this.makeHyperlinkString(writer, lookupField.getSubHyperlink(), context);
-        this.appendTooltip(writer, context, modelFormField);
-    }
-
-    protected String appendExternalLoginKey(String target) {
-        String result = target;
-        String sessionId = ";jsessionid=" + request.getSession().getId();
-        int questionIndex = target.indexOf("?");
-        if (questionIndex == -1) {
-            result += sessionId;
-        } else {
-            result = result.replace("?", sessionId + "?");
-        }
-        return result;
-    }
-
-    public void renderNextPrev(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {
-        boolean ajaxEnabled = false;
-        List<ModelForm.UpdateArea> updateAreas = modelForm.getOnPaginateUpdateAreas();
-        String targetService = modelForm.getPaginateTarget(context);
-        if (this.javaScriptEnabled) {
-            if (UtilValidate.isNotEmpty(updateAreas)) {
-                ajaxEnabled = true;
-            }
-        }
-        if (targetService == null) {
-            targetService = "${targetService}";
-        }
-        if (UtilValidate.isEmpty(targetService) && updateAreas == null) {
-            Debug.logWarning("Cannot paginate because TargetService is empty for the form: " + modelForm.getName(), module);
-            return;
-        }
-        // get the parameterized pagination index and size fields
-        int paginatorNumber = WidgetWorker.getPaginatorNumber(context);
-        String viewIndexParam = modelForm.getMultiPaginateIndexField(context);
-        String viewSizeParam = modelForm.getMultiPaginateSizeField(context);
-        int viewIndex = Paginator.getViewIndex(modelForm, context);
-        int viewSize = Paginator.getViewSize(modelForm, context);
-        int listSize = Paginator.getListSize(context);
-        int lowIndex = Paginator.getLowIndex(context);
-        int highIndex = Paginator.getHighIndex(context);
-        int actualPageSize = Paginator.getActualPageSize(context);
-        // needed for the "Page" and "rows" labels
-        Map<String, String> uiLabelMap = UtilGenerics.checkMap(context.get("uiLabelMap"));
-        String pageLabel = "";
-        String commonDisplaying = "";
-        if (uiLabelMap == null) {
-            Debug.logWarning("Could not find uiLabelMap in context", module);
-        } else {
-            pageLabel = uiLabelMap.get("CommonPage");
-            Map<String, Integer> messageMap = UtilMisc.toMap("lowCount", Integer.valueOf(lowIndex + 1), "highCount", Integer.valueOf(lowIndex + actualPageSize), "total", Integer.valueOf(listSize));
-            commonDisplaying = UtilProperties.getMessage("CommonUiLabels", "CommonDisplaying", messageMap, (Locale) context.get("locale"));
-        }
-        // for legacy support, the viewSizeParam is VIEW_SIZE and viewIndexParam is VIEW_INDEX when the fields are "viewSize" and "viewIndex"
-        if (viewIndexParam.equals("viewIndex" + "_" + paginatorNumber))
-            viewIndexParam = "VIEW_INDEX" + "_" + paginatorNumber;
-        if (viewSizeParam.equals("viewSize" + "_" + paginatorNumber))
-            viewSizeParam = "VIEW_SIZE" + "_" + paginatorNumber;
-        String str = (String) context.get("_QBESTRING_");
-        // strip legacy viewIndex/viewSize params from the query string
-        String queryString = UtilHttp.stripViewParamsFromQueryString(str, "" + paginatorNumber);
-        // strip parameterized index/size params from the query string
-        HashSet<String> paramNames = new HashSet<String>();
-        paramNames.add(viewIndexParam);
-        paramNames.add(viewSizeParam);
-        queryString = UtilHttp.stripNamedParamsFromQueryString(queryString, paramNames);
-        String anchor = "";
-        String paginateAnchor = modelForm.getPaginateTargetAnchor();
-        if (UtilValidate.isNotEmpty(paginateAnchor))
-            anchor = "#" + paginateAnchor;
-        // Create separate url path String and request parameters String,
-        // add viewIndex/viewSize parameters to request parameter String
-        String urlPath = UtilHttp.removeQueryStringFromTarget(targetService);
-        String prepLinkText = UtilHttp.getQueryStringFromTarget(targetService);
-        String prepLinkSizeText;
-        if (UtilValidate.isNotEmpty(queryString)) {
-            queryString = UtilHttp.encodeAmpersands(queryString);
-        }
-        if (prepLinkText == null) {
-            prepLinkText = "";
-        }
-        if (prepLinkText.indexOf("?") < 0) {
-            prepLinkText += "?";
-        } else if (!prepLinkText.endsWith("?")) {
-            prepLinkText += "&amp;";
-        }
-        if (!UtilValidate.isEmpty(queryString) && !queryString.equals("null")) {
-            prepLinkText += queryString + "&amp;";
-        }
-        prepLinkSizeText = prepLinkText + viewSizeParam + "='+this.value+'" + "&amp;" + viewIndexParam + "=0";
-        prepLinkText += viewSizeParam + "=" + viewSize + "&amp;" + viewIndexParam + "=";
-        if (ajaxEnabled) {
-            // Prepare params for prototype.js
-            prepLinkText = prepLinkText.replace("?", "");
-            prepLinkText = prepLinkText.replace("&amp;", "&");
-        }
-        String linkText;
-        String paginateStyle = modelForm.getPaginateStyle();
-        String paginateFirstStyle = modelForm.getPaginateFirstStyle();
-        String paginateFirstLabel = modelForm.getPaginateFirstLabel(context);
-        String firstUrl = "";
-        String ajaxFirstUrl = "";
-        String paginatePreviousStyle = modelForm.getPaginatePreviousStyle();
-        String paginatePreviousLabel = modelForm.getPaginatePreviousLabel(context);
-        String previousUrl = "";
-        String ajaxPreviousUrl = "";
-        String selectUrl = "";
-        String ajaxSelectUrl = "";
-        String paginateViewSizeLabel = modelForm.getPaginateViewSizeLabel(context);
-        String selectSizeUrl = "";
-        String ajaxSelectSizeUrl = "";
-        String paginateNextStyle = modelForm.getPaginateNextStyle();
-        String paginateNextLabel = modelForm.getPaginateNextLabel(context);
-        String nextUrl = "";
-        String ajaxNextUrl = "";
-        String paginateLastStyle = modelForm.getPaginateLastStyle();
-        String paginateLastLabel = modelForm.getPaginateLastLabel(context);
-        String lastUrl = "";
-        String ajaxLastUrl = "";
-        if (viewIndex > 0) {
-            if (ajaxEnabled) {
-                ajaxFirstUrl = createAjaxParamsFromUpdateAreas(updateAreas, prepLinkText + 0 + anchor, context);
-            } else {
-                linkText = prepLinkText + 0 + anchor;
-                firstUrl = rh.makeLink(this.request, this.response, urlPath + linkText);
-            }
-        }
-        if (viewIndex > 0) {
-            if (ajaxEnabled) {
-                ajaxPreviousUrl = createAjaxParamsFromUpdateAreas(updateAreas, prepLinkText + (viewIndex - 1) + anchor, context);
-            } else {
-                linkText = prepLinkText + (viewIndex - 1) + anchor;
-                previousUrl = rh.makeLink(this.request, this.response, urlPath + linkText);
-            }
-        }
-        // Page select dropdown
-        if (listSize > 0 && this.javaScriptEnabled) {
-            if (ajaxEnabled) {
-                ajaxSelectUrl = createAjaxParamsFromUpdateAreas(updateAreas, prepLinkText + "' + this.value + '", context);
-            } else {
-                linkText = prepLinkText;
-                if (linkText.startsWith("/")) {
-                    linkText = linkText.substring(1);
-                }
-                selectUrl = rh.makeLink(this.request, this.response, urlPath + linkText);
-            }
-        }
-        // Next button
-        if (highIndex < listSize) {
-            if (ajaxEnabled) {
-                ajaxNextUrl = createAjaxParamsFromUpdateAreas(updateAreas, prepLinkText + (viewIndex + 1) + anchor, context);
-            } else {
-                linkText = prepLinkText + (viewIndex + 1) + anchor;
-                nextUrl = rh.makeLink(this.request, this.response, urlPath + linkText);
-            }
-        }
-        // Last button
-        if (highIndex < listSize) {
-            int lastIndex = UtilMisc.getViewLastIndex(listSize, viewSize);
-            if (ajaxEnabled) {
-                ajaxLastUrl = createAjaxParamsFromUpdateAreas(updateAreas, prepLinkText + lastIndex + anchor, context);
-            } else {
-                linkText = prepLinkText + lastIndex + anchor;
-                lastUrl = rh.makeLink(this.request, this.response, urlPath + linkText);
-            }
-        }
-        // Page size select dropdown
-        if (listSize > 0 && this.javaScriptEnabled) {
-            if (ajaxEnabled) {
-                ajaxSelectSizeUrl = createAjaxParamsFromUpdateAreas(updateAreas, prepLinkSizeText + anchor, context);
-            } else {
-                linkText = prepLinkSizeText;
-                if (linkText.startsWith("/")) {
-                    linkText = linkText.substring(1);
-                }
-                selectSizeUrl = rh.makeLink(this.request, this.response, urlPath + linkText);
-            }
-        }
-        StringWriter sr = new StringWriter();
-        sr.append("<@renderNextPrev ");
-        sr.append(" paginateStyle=\"");
-        sr.append(paginateStyle);
-        sr.append("\" paginateFirstStyle=\"");
-        sr.append(paginateFirstStyle);
-        sr.append("\" viewIndex=");
-        sr.append(Integer.toString(viewIndex));
-        sr.append(" highIndex=");
-        sr.append(Integer.toString(highIndex));
-        sr.append(" listSize=");
-        sr.append(Integer.toString(listSize));
-        sr.append(" viewSize=");
-        sr.append(Integer.toString(viewSize));
-        sr.append(" ajaxEnabled=");
-        sr.append(Boolean.toString(ajaxEnabled));
-        sr.append(" javaScriptEnabled=");
-        sr.append(Boolean.toString(javaScriptEnabled));
-        sr.append(" ajaxFirstUrl=\"");
-        sr.append(ajaxFirstUrl);
-        sr.append("\" ajaxFirstUrl=\"");
-        sr.append(ajaxFirstUrl);
-        sr.append("\" ajaxFirstUrl=\"");
-        sr.append(ajaxFirstUrl);
-        sr.append("\" firstUrl=\"");
-        sr.append(firstUrl);
-        sr.append("\" paginateFirstLabel=\"");
-        sr.append(paginateFirstLabel);
-        sr.append("\" paginatePreviousStyle=\"");
-        sr.append(paginatePreviousStyle);
-        sr.append("\" ajaxPreviousUrl=\"");
-        sr.append(ajaxPreviousUrl);
-        sr.append("\" previousUrl=\"");
-        sr.append(previousUrl);
-        sr.append("\" paginatePreviousLabel=\"");
-        sr.append(paginatePreviousLabel);
-        sr.append("\" pageLabel=\"");
-        sr.append(pageLabel);
-        sr.append("\" ajaxSelectUrl=\"");
-        sr.append(ajaxSelectUrl);
-        sr.append("\" selectUrl=\"");
-        sr.append(selectUrl);
-        sr.append("\" ajaxSelectSizeUrl=\"");
-        sr.append(ajaxSelectSizeUrl);
-        sr.append("\" selectSizeUrl=\"");
-        sr.append(selectSizeUrl);
-        sr.append("\" commonDisplaying=\"");
-        sr.append(commonDisplaying);
-        sr.append("\" paginateNextStyle=\"");
-        sr.append(paginateNextStyle);
-        sr.append("\" ajaxNextUrl=\"");
-        sr.append(ajaxNextUrl);
-        sr.append("\" nextUrl=\"");
-        sr.append(nextUrl);
-        sr.append("\" paginateNextLabel=\"");
-        sr.append(paginateNextLabel);
-        sr.append("\" paginateLastStyle=\"");
-        sr.append(paginateLastStyle);
-        sr.append("\" ajaxLastUrl=\"");
-        sr.append(ajaxLastUrl);
-        sr.append("\" lastUrl=\"");
-        sr.append(lastUrl);
-        sr.append("\" paginateLastLabel=\"");
-        sr.append(paginateLastLabel);
-        sr.append("\" paginateViewSizeLabel=\"");
-        sr.append(paginateViewSizeLabel);
-        sr.append("\" />");
-        executeMacro(writer, sr.toString());
-    }
-
-    public void renderFileField(Appendable writer, Map<String, Object> context, FileField textField) throws IOException {
-        ModelFormField modelFormField = textField.getModelFormField();
-        String className = "";
-        String alert = "false";
-        String name = modelFormField.getParameterName(context);
-        String value = modelFormField.getEntry(context, textField.getDefaultValue(context));
-        String size = Integer.toString(textField.getSize());
-        String maxlength = "";
-        String autocomplete = "";
-        if (UtilValidate.isNotEmpty(modelFormField.getWidgetStyle())) {
-            className = modelFormField.getWidgetStyle();
-            if (modelFormField.shouldBeRed(context)) {
-                alert = "true";
-            }
-        }
-        if (UtilValidate.isEmpty(value)) {
-            value = "";
-        }
-        if (textField.getMaxlength() != null) {
-            maxlength = textField.getMaxlength().toString();
-        }
-        if (!textField.getClientAutocompleteField()) {
-            autocomplete = "off";
-        }
-        StringWriter sr = new StringWriter();
-        sr.append("<@renderFileField ");
-        sr.append(" className=\"");
-        sr.append(className);
-        sr.append("\" alert=\"");
-        sr.append(alert);
-        sr.append("\" name=\"");
-        sr.append(name);
-        sr.append("\" value=\"");
-        sr.append(value);
-        sr.append("\" size=\"");
-        sr.append(size);
-        sr.append("\" maxlength=\"");
-        sr.append(maxlength);
-        sr.append("\" autocomplete=\"");
-        sr.append(autocomplete);
-        sr.append("\" />");
-        executeMacro(writer, sr.toString());
-        this.makeHyperlinkString(writer, textField.getSubHyperlink(), context);
-        this.appendTooltip(writer, context, modelFormField);
-    }
-
-    public void renderPasswordField(Appendable writer, Map<String, Object> context, PasswordField passwordField) throws IOException {
-        ModelFormField modelFormField = passwordField.getModelFormField();
-        String className = "";
-        String alert = "false";
-        String name = modelFormField.getParameterName(context);
-        String size = Integer.toString(passwordField.getSize());
-        String maxlength = "";
-        String id = modelFormField.getCurrentContainerId(context);
-        String autocomplete = "";
-        if (UtilValidate.isNotEmpty(modelFormField.getWidgetStyle())) {
-            className = modelFormField.getWidgetStyle();
-            if (modelFormField.shouldBeRed(context)) {
-                alert = "true";
-            }
-        }
-        String value = modelFormField.getEntry(context, passwordField.getDefaultValue(context));
-        if (value == null) {
-            value = "";
-        }
-        if (passwordField.getMaxlength() != null) {
-            maxlength = passwordField.getMaxlength().toString();
-        }
-        if (id == null) {
-            id = "";
-        }
-        if (!passwordField.getClientAutocompleteField()) {
-            autocomplete = "off";
-        }
-        StringWriter sr = new StringWriter();
-        sr.append("<@renderPasswordField ");
-        sr.append(" className=\"");
-        sr.append(className);
-        sr.append("\" alert=\"");
-        sr.append(alert);
-        sr.append("\" name=\"");
-        sr.append(name);
-        sr.append("\" value=\"");
-        sr.append(value);
-        sr.append("\" size=\"");
-        sr.append(size);
-        sr.append("\" maxlength=\"");
-        sr.append(maxlength);
-        sr.append("\" id=\"");
-        sr.append(id);
-        sr.append("\" autocomplete=\"");
-        sr.append(autocomplete);
-        sr.append("\" />");
-        executeMacro(writer, sr.toString());
-        this.addAsterisks(writer, context, modelFormField);
-        this.makeHyperlinkString(writer, passwordField.getSubHyperlink(), context);
-        this.appendTooltip(writer, context, modelFormField);
-    }
-
-    public void renderImageField(Appendable writer, Map<String, Object> context, ImageField imageField) throws IOException {
-        ModelFormField modelFormField = imageField.getModelFormField();
-        String value = modelFormField.getEntry(context, imageField.getValue(context));
-        String description = imageField.getDescription(context);
-        String alternate = imageField.getAlternate(context);
-        String style = imageField.getStyle(context);
-        if (UtilValidate.isEmpty(description)) {
-            description = imageField.getModelFormField().getTitle(context);
-        }
-        if (UtilValidate.isEmpty(alternate)) {
-            alternate = description;
-        }
-        if (UtilValidate.isNotEmpty(value)) {
-            if (!value.startsWith("http")) {
-                StringBuilder buffer = new StringBuilder();
-                ContentUrlTag.appendContentPrefix(request, buffer);
-                buffer.append(value);
-                value = buffer.toString();
-            }
-        } else if (value == null) {
-            value = "";
-        }
-        String event = modelFormField.getEvent();
-        String action = modelFormField.getAction(context);
-        StringWriter sr = new StringWriter();
-        sr.append("<@renderImageField ");
-        sr.append(" value=\"");
-        sr.append(value);
-        sr.append("\" description=\"");
-        sr.append(encode(description, modelFormField, context));
-        sr.append("\" alternate=\"");
-        sr.append(encode(alternate, modelFormField, context));
-        sr.append("\" style=\"");
-        sr.append(style);
-        sr.append("\" event=\"");
-        sr.append(event == null ? "" : event);
-        sr.append("\" action=\"");
-        sr.append(action == null ? "" : action);
-        sr.append("\" />");
-        executeMacro(writer, sr.toString());
-        this.makeHyperlinkString(writer, imageField.getSubHyperlink(), context);
-        this.appendTooltip(writer, context, modelFormField);
-    }
-
-    public void renderFieldGroupOpen(Appendable writer, Map<String, Object> context, ModelForm.FieldGroup fieldGroup) throws IOException {
-        String style = fieldGroup.getStyle();
-        String id = fieldGroup.getId();
-        FlexibleStringExpander titleNotExpanded = FlexibleStringExpander.getInstance(fieldGroup.getTitle());
-        String title = titleNotExpanded.expandString(context);
-        Boolean collapsed = fieldGroup.initiallyCollapsed();
-        String collapsibleAreaId = fieldGroup.getId() + "_body";
-        Boolean collapsible = fieldGroup.collapsible();
-        String expandToolTip = "";
-        String collapseToolTip = "";
-        if (UtilValidate.isNotEmpty(style) || UtilValidate.isNotEmpty(id) || UtilValidate.isNotEmpty(title)) {
-            if (fieldGroup.collapsible()) {
-                Map<String, Object> uiLabelMap = UtilGenerics.checkMap(context.get("uiLabelMap"));
-                //Map<String, Object> paramMap = UtilGenerics.checkMap(context.get("requestParameters"));
-                if (uiLabelMap != null) {
-                    expandToolTip = (String) uiLabelMap.get("CommonExpand");
-                    collapseToolTip = (String) uiLabelMap.get("CommonCollapse");
-                }
-            }
-        }
-        StringWriter sr = new StringWriter();
-        sr.append("<@renderFieldGroupOpen ");
-        sr.append(" style=\"");
-        if (style != null) {
-            sr.append(style);
-        }
-        sr.append("\" id=\"");
-        sr.append(id);
-        sr.append("\" title=\"");
-        sr.append(title);
-        sr.append("\" collapsed=");
-        sr.append(Boolean.toString(collapsed));
-        sr.append(" collapsibleAreaId=\"");
-        sr.append(collapsibleAreaId);
-        sr.append("\" collapsible=");
-        sr.append(Boolean.toString(collapsible));
-        sr.append(" expandToolTip=\"");
-        sr.append(expandToolTip);
-        sr.append("\" collapseToolTip=\"");
-        sr.append(collapseToolTip);
-        sr.append("\" />");
-        executeMacro(writer, sr.toString());
-    }
-
-    public void renderFieldGroupClose(Appendable writer, Map<String, Object> context, ModelForm.FieldGroup fieldGroup) throws IOException {
-        String style = fieldGroup.getStyle();
-        String id = fieldGroup.getId();
-        FlexibleStringExpander titleNotExpanded = FlexibleStringExpander.getInstance(fieldGroup.getTitle());
-        String title = titleNotExpanded.expandString(context);
-        StringWriter sr = new StringWriter();
-        sr.append("<@renderFieldGroupClose ");
-        sr.append(" style=\"");
-        if (style != null) {
-            sr.append(style);
-        }
-        sr.append("\" id=\"");
-        if (id != null) {
-            sr.append(id);
-        }
-        sr.append("\" title=\"");
-        if (title != null) {
-            sr.append(title);
-        }
-        sr.append("\" />");
-        executeMacro(writer, sr.toString());
-    }
-
-    public void renderBanner(Appendable writer, Map<String, Object> context, ModelForm.Banner banner) throws IOException {
-        String style = banner.getStyle(context);
-        String leftStyle = banner.getLeftTextStyle(context);
-        if (UtilValidate.isEmpty(leftStyle))
-            leftStyle = style;
-        String rightStyle = banner.getRightTextStyle(context);
-        if (UtilValidate.isEmpty(rightStyle))
-            rightStyle = style;
-        String leftText = banner.getLeftText(context);
-        if (leftText == null) {
-            leftText = "";
-        }
-        String text = banner.getText(context);
-        if (text == null) {
-            text = "";
-        }
-        String rightText = banner.getRightText(context);
-        if (rightText == null) {
-            rightText = "";
-        }
-        StringWriter sr = new StringWriter();
-        sr.append("<@renderBanner ");
-        sr.append(" style=\"");
-        sr.append(style);
-        sr.append("\" leftStyle=\"");
-        sr.append(leftStyle);
-        sr.append("\" rightStyle=\"");
-        sr.append(rightStyle);
-        sr.append("\" leftText=\"");
-        sr.append(leftText);
-        sr.append("\" text=\"");
-        sr.append(text);
-        sr.append("\" rightText=\"");
-        sr.append(rightText);
-        sr.append("\" />");
-        executeMacro(writer, sr.toString());
-    }
-
-    /**
-     * Renders the beginning boundary comment string.
-     * @param writer The writer to write to
-     * @param widgetType The widget type: "Screen Widget", "Form Widget", etc.
-     * @param modelWidget The widget
-     */
-    public void renderBeginningBoundaryComment(Appendable writer, String widgetType, ModelWidget modelWidget) throws IOException {
-        if (this.widgetCommentsEnabled) {
-            StringWriter sr = new StringWriter();
-            sr.append("<@formatBoundaryComment ");
-            sr.append(" boundaryType=\"");
-            sr.append("Begin");
-            sr.append("\" widgetType=\"");
-            sr.append(widgetType);
-            sr.append("\" widgetName=\"");
-            sr.append(modelWidget.getBoundaryCommentName());
-            sr.append("\" />");
-            executeMacro(writer, sr.toString());
-        }
-    }
-
-    /**
-     * Renders the ending boundary comment string.
-     * @param writer The writer to write to
-     * @param widgetType The widget type: "Screen Widget", "Form Widget", etc.
-     * @param modelWidget The widget
-     */
-    public void renderEndingBoundaryComment(Appendable writer, String widgetType, ModelWidget modelWidget) throws IOException {
-        if (this.widgetCommentsEnabled) {
-            StringWriter sr = new StringWriter();
-            sr.append("<@formatBoundaryComment ");
-            sr.append(" boundaryType=\"");
-            sr.append("End");
-            sr.append("\" widgetType=\"");
-            sr.append(widgetType);
-            sr.append("\" widgetName=\"");
-            sr.append(modelWidget.getBoundaryCommentName());
-            sr.append("\" />");
-            executeMacro(writer, sr.toString());
-        }
-    }
-
-    public void renderSortField(Appendable writer, Map<String, Object> context, ModelFormField modelFormField, String titleText) throws IOException {
-        boolean ajaxEnabled = false;
-        ModelForm modelForm = modelFormField.getModelForm();
-        List<ModelForm.UpdateArea> updateAreas = modelForm.getOnSortColumnUpdateAreas();
-        if (updateAreas == null) {
-            // For backward compatibility.
-            updateAreas = modelForm.getOnPaginateUpdateAreas();
-        }
-        if (this.javaScriptEnabled) {
-            if (UtilValidate.isNotEmpty(updateAreas)) {
-                ajaxEnabled = true;
-            }
-        }
-        String paginateTarget = modelForm.getPaginateTarget(context);
-        if (paginateTarget.isEmpty() && updateAreas == null) {
-            Debug.logWarning("Cannot sort because the paginate target URL is empty for the form: " + modelForm.getName(), module);
-            return;
-        }
-        String oldSortField = modelForm.getSortField(context);
-        String sortFieldStyle = modelFormField.getSortFieldStyle();
-        // if the entry-name is defined use this instead of field name
-        String columnField = modelFormField.getEntryName();
-        if (UtilValidate.isEmpty(columnField)) {
-            columnField = modelFormField.getFieldName();
-        }
-        // switch between asc/desc order
-        String newSortField = columnField;
-        if (UtilValidate.isNotEmpty(oldSortField)) {
-            if (oldSortField.equals(columnField)) {
-                newSortField = "-" + columnField;
-                sortFieldStyle = modelFormField.getSortFieldStyleDesc();
-            } else if (oldSortField.equals("-" + columnField)) {
-                newSortField = columnField;
-                sortFieldStyle = modelFormField.getSortFieldStyleAsc();
-            }
-        }
-        String queryString = UtilHttp.getQueryStringFromTarget(paginateTarget).replace("?", "");
-        Map<String, Object> paramMap = UtilHttp.getQueryStringOnlyParameterMap(queryString);
-        String qbeString = (String) context.get("_QBESTRING_");
-        if (qbeString != null) {
-            qbeString = qbeString.replaceAll("&amp;", "&");
-            paramMap.putAll(UtilHttp.getQueryStringOnlyParameterMap(qbeString));
-        }
-        paramMap.put(modelForm.getSortFieldParameterName(), newSortField);
-        UtilHttp.canonicalizeParameterMap(paramMap);
-        String linkUrl = null;
-        if (ajaxEnabled) {
-            linkUrl = createAjaxParamsFromUpdateAreas(updateAreas, paramMap, null, context);
-        } else {
-            StringBuilder sb = new StringBuilder("?");
-            Iterator<Map.Entry<String, Object>> iter = paramMap.entrySet().iterator();
-            while (iter.hasNext()) {
-                Map.Entry<String, Object> entry = iter.next();
-                sb.append(entry.getKey()).append("=").append(entry.getValue());
-                if (iter.hasNext()) {
-                    sb.append("&amp;");
-                }
-            }
-            String newQueryString = sb.toString();
-            String urlPath = UtilHttp.removeQueryStringFromTarget(paginateTarget);
-            linkUrl = rh.makeLink(this.request, this.response, urlPath.concat(newQueryString));
-        }
-        StringWriter sr = new StringWriter();
-        sr.append("<@renderSortField ");
-        sr.append(" style=\"");
-        sr.append(sortFieldStyle);
-        sr.append("\" title=\"");
-        sr.append(titleText);
-        sr.append("\" linkUrl=\"");
-        sr.append(linkUrl);
-        sr.append("\" ajaxEnabled=");
-        sr.append(Boolean.toString(ajaxEnabled));
-        String tooltip = modelFormField.getSortFieldHelpText(context);
-        if (!tooltip.isEmpty()) {
-            sr.append(" tooltip=\"").append(tooltip).append("\"");
-        }
-        sr.append(" />");
-        executeMacro(writer, sr.toString());
-    }
-
-    /** Create an ajaxXxxx JavaScript CSV string from a list of UpdateArea objects. See
-     * <code>selectall.js</code>.
-     * @param updateAreas
-     * @param extraParams Renderer-supplied additional target parameters
-     * @param context
-     * @return Parameter string or empty string if no UpdateArea objects were found
-     */
-    private String createAjaxParamsFromUpdateAreas(List<ModelForm.UpdateArea> updateAreas, Map<String, Object> extraParams, String anchor, Map<String, ? extends Object> context) {
-        StringBuilder sb = new StringBuilder();
-        Iterator<ModelForm.UpdateArea> updateAreaIter = updateAreas.iterator();
-        while (updateAreaIter.hasNext()) {
-            ModelForm.UpdateArea updateArea = updateAreaIter.next();
-            sb.append(updateArea.getAreaId()).append(",");
-            String ajaxTarget = updateArea.getAreaTarget(context);
-            String urlPath = UtilHttp.removeQueryStringFromTarget(ajaxTarget);
-            sb.append(this.rh.makeLink(this.request, this.response,urlPath)).append(",");
-            String queryString = UtilHttp.getQueryStringFromTarget(ajaxTarget).replace("?", "");
-            Map<String, Object> parameters = UtilHttp.getQueryStringOnlyParameterMap(queryString);
-            Map<String, Object> ctx = UtilGenerics.checkMap(context);
-            Map<String, Object> updateParams = UtilGenerics.checkMap(updateArea.getParameterMap(ctx));
-            parameters.putAll(updateParams);
-            UtilHttp.canonicalizeParameterMap(parameters);
-            parameters.putAll(extraParams);
-            Iterator<Map.Entry<String, Object>> paramIter = parameters.entrySet().iterator();
-            while (paramIter.hasNext()) {
-                Map.Entry<String, Object> entry = paramIter.next();
-                sb.append(entry.getKey()).append("=").append(entry.getValue());
-                if (paramIter.hasNext()) {
-                    sb.append("&");
-                }
-            }
-            if (anchor != null) {
-                sb.append("#").append(anchor);
-            }
-            if (updateAreaIter.hasNext()) {
-                sb.append(",");
-            }
-        }
-        Locale locale = UtilMisc.ensureLocale(context.get("locale"));
-        return FlexibleStringExpander.expandString(sb.toString(), context, locale);
-    }
-
-    /** Create an ajaxXxxx JavaScript CSV string from a list of UpdateArea objects. See
-     * <code>selectall.js</code>.
-     * @param updateAreas
-     * @param extraParams Renderer-supplied additional target parameters
-     * @param context
-     * @return Parameter string or empty string if no UpdateArea objects were found
-     */
-    public String createAjaxParamsFromUpdateAreas(List<ModelForm.UpdateArea> updateAreas, String extraParams, Map<String, ? extends Object> context) {
-        //FIXME copy from HtmlFormRenderer.java
-        if (updateAreas == null) {
-            return "";
-        }
-        String ajaxUrl = "";
-        boolean firstLoop = true;
-        for (ModelForm.UpdateArea updateArea : updateAreas) {
-            if (firstLoop) {
-                firstLoop = false;
-            } else {
-                ajaxUrl += ",";
-            }
-            Map<String, Object> ctx = UtilGenerics.checkMap(context);
-            Map<String, String> parameters = updateArea.getParameterMap(ctx);
-            String targetUrl = updateArea.getAreaTarget(context);
-            String ajaxParams = getAjaxParamsFromTarget(targetUrl);
-            //add first parameters from updateArea parameters
-            if (UtilValidate.isNotEmpty(parameters)) {
-                if (UtilValidate.isEmpty(ajaxParams)) {
-                    ajaxParams = "";
-                }
-                for (Map.Entry<String, String> entry : parameters.entrySet()) {
-                    String key = entry.getKey();
-                    String value = entry.getValue();
-                    //test if ajax parameters are not already into extraParams, if so do not add it
-                    if (UtilValidate.isNotEmpty(extraParams) && extraParams.contains(value)) {
-                        continue;
-                    }
-                    if (ajaxParams.length() > 0 && ajaxParams.indexOf(key) < 0) {
-                        ajaxParams += "&";
-                    }
-                    if (ajaxParams.indexOf(key) < 0) {
-                        ajaxParams += key + "=" + value;
-                    }
-                }
-            }
-            //then add parameters from request. Those parameters could end with an anchor so we must set ajax parameters first
-            if (UtilValidate.isNotEmpty(extraParams)) {
-                if (ajaxParams.length() > 0 && !extraParams.startsWith("&")) {
-                    ajaxParams += "&";
-                }
-                ajaxParams += extraParams;
-            }
-            ajaxUrl += updateArea.getAreaId() + ",";
-            ajaxUrl += this.rh.makeLink(this.request, this.response, UtilHttp.removeQueryStringFromTarget(targetUrl));
-            ajaxUrl += "," + ajaxParams;
-        }
-        Locale locale = UtilMisc.ensureLocale(context.get("locale"));
-        return FlexibleStringExpander.expandString(ajaxUrl, context, locale);
-    }
-
-    /** Extracts parameters from a target URL string, prepares them for an Ajax
-     * JavaScript call. This method is currently set to return a parameter string
-     * suitable for the Prototype.js library.
-     * @param target Target URL string
-     * @return Parameter string
-     */
-    public static String getAjaxParamsFromTarget(String target) {
-        String targetParams = UtilHttp.getQueryStringFromTarget(target);
-        targetParams = targetParams.replace("?", "");
-        targetParams = targetParams.replace("&amp;", "&");
-        return targetParams;
-    }
-
-    public void appendTooltip(Appendable writer, Map<String, Object> context, ModelFormField modelFormField) throws IOException {
-        // render the tooltip, in other methods too
-        String tooltip = modelFormField.getTooltip(context);
-        StringWriter sr = new StringWriter();
-        sr.append("<@renderTooltip ");
-        sr.append("tooltip=\"");
-        sr.append(FreeMarkerWorker.encodeDoubleQuotes(tooltip));
-        sr.append("\" tooltipStyle=\"");
-        sr.append(modelFormField.getTooltipStyle());
-        sr.append("\" />");
-        executeMacro(writer, sr.toString());
-    }
-
-    public void makeHyperlinkString(Appendable writer, ModelFormField.SubHyperlink subHyperlink, Map<String, Object> context) throws IOException {
-        if (subHyperlink == null) {
-            return;
-        }
-        if (subHyperlink.shouldUse(context)) {
-            writer.append(' ');
-            makeHyperlinkByType(writer, subHyperlink.getLinkType(), subHyperlink.getStyle(context), subHyperlink.getUrlMode(),
-                    subHyperlink.getTarget(context), subHyperlink.getParameterMap(context), subHyperlink.getDescription(context),
-                    subHyperlink.getTargetWindow(context), null, subHyperlink.getModelFormField(), this.request, this.response,
-                    context);
-        }
-    }
-
-    public void addAsterisks(Appendable writer, Map<String, Object> context, ModelFormField modelFormField) throws IOException {
-        String requiredField = "false";
-        String requiredStyle = "";
-        if (modelFormField.getRequiredField()) {
-            requiredField = "true";
-            requiredStyle = modelFormField.getRequiredFieldStyle();
-        }
-        StringWriter sr = new StringWriter();
-        sr.append("<@renderAsterisks ");
-        sr.append("requiredField=\"");
-        sr.append(requiredField);
-        sr.append("\" requiredStyle=\"");
-        sr.append(requiredStyle);
-        sr.append("\" />");
-        executeMacro(writer, sr.toString());
-    }
-
-    public void appendContentUrl(Appendable writer, String location) throws IOException {
-        StringBuilder buffer = new StringBuilder();
-        ContentUrlTag.appendContentPrefix(this.request, buffer);
-        writer.append(buffer.toString());
-        writer.append(location);
-    }
-
-    public void makeHyperlinkByType(Appendable writer, String linkType, String linkStyle, String targetType, String target, Map<String, String> parameterMap, String description, String targetWindow, String confirmation, ModelFormField modelFormField, HttpServletRequest request,
-            HttpServletResponse response, Map<String, Object> context) throws IOException {
-        String realLinkType = WidgetWorker.determineAutoLinkType(linkType, target, targetType, request);
-        String encodedDescription = encode(description, modelFormField, context);
-        // get the parameterized pagination index and size fields
-        int paginatorNumber = WidgetWorker.getPaginatorNumber(context);
-        ModelForm modelForm = modelFormField.getModelForm();
-        String viewIndexField = modelForm.getMultiPaginateIndexField(context);
-        String viewSizeField = modelForm.getMultiPaginateSizeField(context);
-        int viewIndex = Paginator.getViewIndex(modelForm, context);
-        int viewSize = Paginator.getViewSize(modelForm, context);
-        if (viewIndexField.equals("viewIndex" + "_" + paginatorNumber)) {
-            viewIndexField = "VIEW_INDEX" + "_" + paginatorNumber;
-        }
-        if (viewSizeField.equals("viewSize" + "_" + paginatorNumber)) {
-            viewSizeField = "VIEW_SIZE" + "_" + paginatorNumber;
-        }
-        if ("hidden-form".equals(realLinkType)) {
-            parameterMap.put(viewIndexField, Integer.toString(viewIndex));
-            parameterMap.put(viewSizeField, Integer.toString(viewSize));
-            if (modelFormField != null && "multi".equals(modelForm.getType())) {
-                WidgetWorker.makeHiddenFormLinkAnchor(writer, linkStyle, encodedDescription, confirmation, modelFormField, request, response, context);
-                // this is a bit trickier, since we can't do a nested form we'll have to put the link to submit the form in place, but put the actual form def elsewhere, ie after the big form is closed
-                Map<String, Object> wholeFormContext = UtilGenerics.checkMap(context.get("wholeFormContext"));
-                Appendable postMultiFormWriter = wholeFormContext != null ? (Appendable) wholeFormContext.get("postMultiFormWriter") : null;
-                if (postMultiFormWriter == null) {
-                    postMultiFormWriter = new StringWriter();
-                    wholeFormContext.put("postMultiFormWriter", postMultiFormWriter);
-                }
-                WidgetWorker.makeHiddenFormLinkForm(postMultiFormWriter, target, targetType, targetWindow, parameterMap, modelFormField, request, response, context);
-            } else {
-                WidgetWorker.makeHiddenFormLinkForm(writer, target, targetType, targetWindow, parameterMap, modelFormField, request, response, context);
-                WidgetWorker.makeHiddenFormLinkAnchor(writer, linkStyle, encodedDescription, confirmation, modelFormField, request, response, context);
-            }
-        } else {
-            makeHyperlinkString(writer, linkStyle, targetType, target, parameterMap, encodedDescription, confirmation, modelFormField, request, response, context, targetWindow);
-        }
-
-    }
-
-    public void makeHyperlinkString(Appendable writer, String linkStyle, String targetType, String target, Map<String, String> parameterMap, String description, String confirmation, ModelFormField modelFormField, HttpServletRequest request, HttpServletResponse response, Map<String, Object> context,
-            String targetWindow) throws IOException {
-        if (UtilValidate.isNotEmpty(description) || UtilValidate.isNotEmpty(request.getAttribute("image"))) {
-            StringBuilder linkUrl = new StringBuilder();
-            WidgetWorker.buildHyperlinkUrl(linkUrl, target, targetType, parameterMap, null, false, false, true, request, response, context);
-            String event = "";
-            String action = "";
-            String imgSrc = "";
-            String alt = "";
-            String imgTitle = "";
-            String hiddenFormName = WidgetWorker.makeLinkHiddenFormName(context, modelFormField);
-            if (UtilValidate.isNotEmpty(modelFormField.getEvent()) && UtilValidate.isNotEmpty(modelFormField.getAction(context))) {
-                event = modelFormField.getEvent();
-                action = modelFormField.getAction(context);
-            }
-            if (UtilValidate.isNotEmpty(request.getAttribute("image"))) {
-                imgSrc = request.getAttribute("image").toString();
-            }
-            if (UtilValidate.isNotEmpty(request.getAttribute("alternate"))) {
-                alt = request.getAttribute("alternate").toString();
-            }
-            if (UtilValidate.isNotEmpty(request.getAttribute("imageTitle"))) {
-                imgTitle = request.getAttribute("imageTitle").toString();
-            }
-            Integer size = Integer.valueOf("0");
-            if (UtilValidate.isNotEmpty(request.getAttribute("descriptionSize"))) {
-                size = Integer.valueOf(request.getAttribute("descriptionSize").toString());
-            }
-            if (UtilValidate.isNotEmpty(description) && size > 0 && description.length() > size) {
-                imgTitle = description;
-                description = description.substring(0, size - 8) + "..." + description.substring(description.length() - 5);
-            }
-            if (UtilValidate.isEmpty(imgTitle)) {
-                imgTitle = modelFormField.getTitle(context);
-            }
-            StringWriter sr = new StringWriter();
-            sr.append("<@makeHyperlinkString ");
-            sr.append("linkStyle=\"");
-            sr.append(linkStyle == null ? "" : linkStyle);
-            sr.append("\" hiddenFormName=\"");
-            sr.append(hiddenFormName == null ? "" : hiddenFormName);
-            sr.append("\" event=\"");
-            sr.append(event);
-            sr.append("\" action=\"");
-            sr.append(action);
-            sr.append("\" imgSrc=\"");
-            sr.append(imgSrc);
-            sr.append("\" title=\"");
-            sr.append(imgTitle);
-            sr.append("\" alternate=\"");
-            sr.append(alt);
-            sr.append("\" linkUrl=\"");
-            sr.append(linkUrl.toString());
-            sr.append("\" targetWindow=\"");
-            sr.append(targetWindow);
-            sr.append("\" description=\"");
-            sr.append(description);
-            sr.append("\" confirmation =\"");
-            sr.append(confirmation);
-            sr.append("\" />");
-            executeMacro(writer, sr.toString());
-        }
-    }
-
-    public void makeHiddenFormLinkAnchor(Appendable writer, String linkStyle, String description, String confirmation, ModelFormField modelFormField, HttpServletRequest request, HttpServletResponse response, Map<String, Object> context) throws IOException {
-        if (UtilValidate.isNotEmpty(description) || UtilValidate.isNotEmpty(request.getAttribute("image"))) {
-            String hiddenFormName = WidgetWorker.makeLinkHiddenFormName(context, modelFormField);
-            String event = "";
-            String action = "";
-            String imgSrc = "";
-            if (UtilValidate.isNotEmpty(modelFormField.getEvent()) && UtilValidate.isNotEmpty(modelFormField.getAction(context))) {
-                event = modelFormField.getEvent();
-                action = modelFormField.getAction(context);
-            }
-            if (UtilValidate.isNotEmpty(request.getAttribute("image"))) {
-                imgSrc = request.getAttribute("image").toString();
-            }
-            StringWriter sr = new StringWriter();
-            sr.append("<@makeHiddenFormLinkAnchor ");
-            sr.append("linkStyle=\"");
-            sr.append(linkStyle == null ? "" : linkStyle);
-            sr.append("\" hiddenFormName=\"");
-            sr.append(hiddenFormName == null ? "" : hiddenFormName);
-            sr.append("\" event=\"");
-            sr.append(event);
-            sr.append("\" action=\"");
-            sr.append(action);
-            sr.append("\" imgSrc=\"");
-            sr.append(imgSrc);
-            sr.append("\" description=\"");
-            sr.append(description);
-            sr.append("\" confirmation =\"");
-            sr.append(confirmation);
-            sr.append("\" />");
-            executeMacro(writer, sr.toString());
-        }
-    }
-
-    public void makeHiddenFormLinkForm(Appendable writer, String target, String targetType, String targetWindow, List<CommonWidgetModels.Parameter> parameterList, ModelFormField modelFormField, HttpServletRequest request, HttpServletResponse response, Map<String, Object> context) throws IOException {
-        StringBuilder actionUrl = new StringBuilder();
-        WidgetWorker.buildHyperlinkUrl(actionUrl, target, targetType, null, null, false, false, true, request, response, context);
-        String name = WidgetWorker.makeLinkHiddenFormName(context, modelFormField);
-        StringBuilder parameters = new StringBuilder();
-        parameters.append("[");
-        for (CommonWidgetModels.Parameter parameter : parameterList) {
-            if (parameters.length() > 1) {
-                parameters.append(",");
-            }
-            parameters.append("{'name':'");
-            parameters.append(parameter.getName());
-            parameters.append("'");
-            parameters.append(",'value':'");
-            parameters.append(UtilCodec.getEncoder("html").encode(parameter.getValue(context)));
-            parameters.append("'}");
-        }
-        parameters.append("]");
-        StringWriter sr = new StringWriter();
-        sr.append("<@makeHiddenFormLinkForm ");
-        sr.append("actionUrl=\"");
-        sr.append(actionUrl.toString());
-        sr.append("\" name=\"");
-        sr.append(name);
-        sr.append("\" parameters=");
-        sr.append(parameters.toString());
-        sr.append(" targetWindow=\"");
-        sr.append(targetWindow);
-        sr.append("\" />");
-        executeMacro(writer, sr.toString());
-    }
-
-    public void renderContainerFindField(Appendable writer, Map<String, Object> context, ContainerField containerField) throws IOException {
-        String id = containerField.getModelFormField().getIdName();
-        String className = UtilFormatOut.checkNull(containerField.getModelFormField().getWidgetStyle());
-        StringWriter sr = new StringWriter();
-        sr.append("<@renderContainerField ");
-        sr.append("id=\"");
-        sr.append(id);
-        sr.append("\" className=\"");
-        sr.append(className);
-        sr.append("\" />");
-        executeMacro(writer, sr.toString());
-    }
-}
+/*******************************************************************************

+ * 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.renderer.macro;

+

+import java.io.IOException;

+import java.io.Reader;

+import java.io.StringReader;

+import java.io.StringWriter;

+import java.rmi.server.UID;

+import java.sql.Timestamp;

+import java.util.HashSet;

+import java.util.Iterator;

+import java.util.LinkedList;

+import java.util.List;

+import java.util.Locale;

+import java.util.Map;

+import java.util.Map.Entry;

+import java.util.Set;

+import java.util.WeakHashMap;

+

+import javax.servlet.ServletContext;

+import javax.servlet.http.HttpServletRequest;

+import javax.servlet.http.HttpServletResponse;

+

+import org.ofbiz.base.util.Debug;

+import org.ofbiz.base.util.StringUtil;

+import org.ofbiz.base.util.UtilCodec;

+import org.ofbiz.base.util.UtilFormatOut;

+import org.ofbiz.base.util.UtilGenerics;

+import org.ofbiz.base.util.UtilHttp;

+import org.ofbiz.base.util.UtilMisc;

+import org.ofbiz.base.util.UtilProperties;

+import org.ofbiz.base.util.UtilValidate;

+import org.ofbiz.base.util.string.FlexibleStringExpander;

+import org.ofbiz.base.util.template.FreeMarkerWorker;

+import org.ofbiz.entity.Delegator;

+import org.ofbiz.webapp.control.RequestHandler;

+import org.ofbiz.webapp.taglib.ContentUrlTag;

+import org.ofbiz.widget.WidgetWorker;

+import org.ofbiz.widget.model.CommonWidgetModels;

+import org.ofbiz.widget.model.FieldInfo;

+import org.ofbiz.widget.model.ModelForm;

+import org.ofbiz.widget.model.ModelFormField;

+import org.ofbiz.widget.model.ModelFormField.CheckField;

+import org.ofbiz.widget.model.ModelFormField.ContainerField;

+import org.ofbiz.widget.model.ModelFormField.DateFindField;

+import org.ofbiz.widget.model.ModelFormField.DateTimeField;

+import org.ofbiz.widget.model.ModelFormField.DisplayEntityField;

+import org.ofbiz.widget.model.ModelFormField.DisplayField;

+import org.ofbiz.widget.model.ModelFormField.DropDownField;

+import org.ofbiz.widget.model.ModelFormField.FieldInfoWithOptions;

+import org.ofbiz.widget.model.ModelFormField.FileField;

+import org.ofbiz.widget.model.ModelFormField.HiddenField;

+import org.ofbiz.widget.model.ModelFormField.HyperlinkField;

+import org.ofbiz.widget.model.ModelFormField.IgnoredField;

+import org.ofbiz.widget.model.ModelFormField.ImageField;

+import org.ofbiz.widget.model.ModelFormField.LookupField;

+import org.ofbiz.widget.model.ModelFormField.PasswordField;

+import org.ofbiz.widget.model.ModelFormField.RadioField;

+import org.ofbiz.widget.model.ModelFormField.RangeFindField;

+import org.ofbiz.widget.model.ModelFormField.ResetField;

+import org.ofbiz.widget.model.ModelFormField.SubmitField;

+import org.ofbiz.widget.model.ModelFormField.TextField;

+import org.ofbiz.widget.model.ModelFormField.TextFindField;

+import org.ofbiz.widget.model.ModelFormField.TextareaField;

+import org.ofbiz.widget.model.ModelFormFieldBuilder;

+import org.ofbiz.widget.model.ModelScreenWidget;

+import org.ofbiz.widget.model.ModelWidget;

+import org.ofbiz.widget.renderer.FormRenderer;

+import org.ofbiz.widget.renderer.FormStringRenderer;

+import org.ofbiz.widget.renderer.Paginator;

+import org.ofbiz.widget.renderer.UtilHelpText;

+

+import com.ibm.icu.util.Calendar;

+

+import freemarker.core.Environment;

+import freemarker.template.Template;

+import freemarker.template.TemplateException;

+

+/**

+ * Widget Library - Form Renderer implementation based on Freemarker macros

+ *

+ */

+public final class MacroFormRenderer implements FormStringRenderer {

+

+    public static final String module = MacroFormRenderer.class.getName();

+    private final Template macroLibrary;

+    private final WeakHashMap<Appendable, Environment> environments = new WeakHashMap<Appendable, Environment>();

+    private final UtilCodec.SimpleEncoder internalEncoder;

+    private final RequestHandler rh;

+    private final HttpServletRequest request;

+    private final HttpServletResponse response;

+    private final boolean javaScriptEnabled;

+    private boolean renderPagination = true;

+    private boolean widgetCommentsEnabled = false;

+

+    public MacroFormRenderer(String macroLibraryPath, HttpServletRequest request, HttpServletResponse response) throws TemplateException, IOException {

+        macroLibrary = FreeMarkerWorker.getTemplate(macroLibraryPath);

+        this.request = request;

+        this.response = response;

+        ServletContext ctx = (ServletContext) request.getAttribute("servletContext");

+        this.rh = (RequestHandler) ctx.getAttribute("_REQUEST_HANDLER_");

+        this.javaScriptEnabled = UtilHttp.isJavaScriptEnabled(request);

+        internalEncoder = UtilCodec.getEncoder("string");

+    }

+

+    @Deprecated

+    public MacroFormRenderer(String macroLibraryPath, Appendable writer, HttpServletRequest request, HttpServletResponse response) throws TemplateException, IOException {

+        this(macroLibraryPath, request, response);

+    }

+

+    public boolean getRenderPagination() {

+        return this.renderPagination;

+    }

+

+    public void setRenderPagination(boolean renderPagination) {

+        this.renderPagination = renderPagination;

+    }

+

+    private void executeMacro(Appendable writer, String macro) throws IOException {

+        try {

+            Environment environment = getEnvironment(writer);

+            Reader templateReader = new StringReader(macro);

+            Template template = new Template(new UID().toString(), templateReader, FreeMarkerWorker.getDefaultOfbizConfig());

+            templateReader.close();

+            environment.include(template);

+        } catch (TemplateException e) {

+            Debug.logError(e, "Error rendering screen thru ftl macro: " + macro, module);

+        } catch (IOException e) {

+            Debug.logError(e, "Error rendering screen thru ftl, macro: " + macro, module);

+        }

+    }

+

+    private Environment getEnvironment(Appendable writer) throws TemplateException, IOException {

+        Environment environment = environments.get(writer);

+        if (environment == null) {

+            Map<String, Object> input = UtilMisc.toMap("key", null);

+            environment = FreeMarkerWorker.renderTemplate(macroLibrary, input, writer);

+            environments.put(writer, environment);

+        }

+        return environment;

+    }

+

+    private void appendWhitespace(Appendable writer) throws IOException {

+        // appending line ends for now, but this could be replaced with a simple space or something

+        writer.append("\r\n");

+        //writer.append(' ');

+    }

+

+    private String encode(String value, ModelFormField modelFormField, Map<String, Object> context) {

+        if (UtilValidate.isEmpty(value)) {

+            return value;

+        }

+        UtilCodec.SimpleEncoder encoder = (UtilCodec.SimpleEncoder) context.get("simpleEncoder");

+        if (modelFormField.getEncodeOutput() && encoder != null) {

+            value = encoder.encode(value);

+        } else {

+            value = internalEncoder.encode(value);

+        }

+        return value;

+    }

+

+    public void renderLabel(Appendable writer, Map<String, Object> context, ModelScreenWidget.Label label) throws IOException {

+        String labelText = label.getText(context);

+        if (UtilValidate.isEmpty(labelText)) {

+            // nothing to render

+            return;

+        }

+        StringWriter sr = new StringWriter();

+        sr.append("<@renderLabel ");

+        sr.append("text=\"");

+        sr.append(labelText);

+        sr.append("\"");

+        sr.append(" />");

+        executeMacro(writer, sr.toString());

+    }

+

+    public void renderDisplayField(Appendable writer, Map<String, Object> context, DisplayField displayField) throws IOException {

+        ModelFormField modelFormField = displayField.getModelFormField();

+        String idName = modelFormField.getCurrentContainerId(context);

+        String description = displayField.getDescription(context);

+        String type = displayField.getType();

+        String imageLocation = displayField.getImageLocation(context);

+        Integer size = Integer.valueOf("0");

+        String title = "";

+        if (UtilValidate.isNotEmpty(displayField.getSize())) {

+            try {

+                size = Integer.parseInt(displayField.getSize());

+            } catch (NumberFormatException nfe) {

+                Debug.logError(nfe, "Error reading size of a field fieldName=" + displayField.getModelFormField().getFieldName() + " FormName= " + displayField.getModelFormField().getModelForm().getName(), module);

+            }

+        }

+        ModelFormField.InPlaceEditor inPlaceEditor = displayField.getInPlaceEditor();

+        boolean ajaxEnabled = inPlaceEditor != null && this.javaScriptEnabled;

+        if (UtilValidate.isNotEmpty(description) && size > 0 && description.length() > size) {

+            title = description;

+            description = description.substring(0, size - 8) + "..." + description.substring(description.length() - 5);

+        }

+        StringWriter sr = new StringWriter();

+        sr.append("<@renderDisplayField ");

+        sr.append("type=\"");

+        sr.append(type);

+        sr.append("\" imageLocation=\"");

+        sr.append(imageLocation);

+        sr.append("\" idName=\"");

+        sr.append(idName);

+        sr.append("\" description=\"");

+        sr.append(FreeMarkerWorker.encodeDoubleQuotes(description));

+        sr.append("\" title=\"");

+        sr.append(title);

+        sr.append("\" class=\"");

+        sr.append(modelFormField.getWidgetStyle());

+        sr.append("\" alert=\"");

+        sr.append(modelFormField.shouldBeRed(context) ? "true" : "false");

+        if (ajaxEnabled) {

+            String url = inPlaceEditor.getUrl(context);

+            String extraParameter = "{";

+            Map<String, Object> fieldMap = inPlaceEditor.getFieldMap(context);

+            if (fieldMap != null) {

+                Set<Entry<String, Object>> fieldSet = fieldMap.entrySet();

+                Iterator<Entry<String, Object>> fieldIterator = fieldSet.iterator();

+                int count = 0;

+                while (fieldIterator.hasNext()) {

+                    count++;

+                    Entry<String, Object> field = fieldIterator.next();

+                    extraParameter += field.getKey() + ":'" + (String) field.getValue() + "'";

+                    if (count < fieldSet.size()) {

+                        extraParameter += ',';

+                    }

+                }

+

+            }

+            extraParameter += "}";

+            sr.append("\" inPlaceEditorUrl=\"");

+            sr.append(url);

+            sr.append("\" inPlaceEditorParams=\"");

+            StringWriter inPlaceEditorParams = new StringWriter();

+            inPlaceEditorParams.append("{name: '");

+            if (UtilValidate.isNotEmpty(inPlaceEditor.getParamName())) {

+                inPlaceEditorParams.append(inPlaceEditor.getParamName());

+            } else {

+                inPlaceEditorParams.append(modelFormField.getFieldName());

+            }

+            inPlaceEditorParams.append("'");

+            inPlaceEditorParams.append(", method: 'POST'");

+            inPlaceEditorParams.append(", submitdata: " + extraParameter);

+            inPlaceEditorParams.append(", type: 'textarea'");

+            inPlaceEditorParams.append(", select: 'true'");

+            inPlaceEditorParams.append(", onreset: function(){jQuery('#cc_" + idName + "').css('background-color', 'transparent');}");

+            if (UtilValidate.isNotEmpty(inPlaceEditor.getCancelText())) {

+                inPlaceEditorParams.append(", cancel: '" + inPlaceEditor.getCancelText() + "'");

+            } else {

+                inPlaceEditorParams.append(", cancel: 'Cancel'");

+            }

+            if (UtilValidate.isNotEmpty(inPlaceEditor.getClickToEditText())) {

+                inPlaceEditorParams.append(", tooltip: '" + inPlaceEditor.getClickToEditText() + "'");

+            }

+            if (UtilValidate.isNotEmpty(inPlaceEditor.getFormClassName())) {

+                inPlaceEditorParams.append(", cssclass: '" + inPlaceEditor.getFormClassName() + "'");

+            } else {

+                inPlaceEditorParams.append(", cssclass: 'inplaceeditor-form'");

+            }

+            if (UtilValidate.isNotEmpty(inPlaceEditor.getLoadingText())) {

+                inPlaceEditorParams.append(", indicator: '" + inPlaceEditor.getLoadingText() + "'");

+            }

+            if (UtilValidate.isNotEmpty(inPlaceEditor.getOkControl())) {

+                inPlaceEditorParams.append(", submit: ");

+                if (!"false".equals(inPlaceEditor.getOkControl())) {

+                    inPlaceEditorParams.append("'");

+                }

+                inPlaceEditorParams.append(inPlaceEditor.getOkControl());

+                if (!"false".equals(inPlaceEditor.getOkControl())) {

+                    inPlaceEditorParams.append("'");

+                }

+            } else {

+                inPlaceEditorParams.append(", submit: 'OK'");

+            }

+            if (UtilValidate.isNotEmpty(inPlaceEditor.getRows())) {

+                inPlaceEditorParams.append(", rows: '" + inPlaceEditor.getRows() + "'");

+            }

+            if (UtilValidate.isNotEmpty(inPlaceEditor.getCols())) {

+                inPlaceEditorParams.append(", cols: '" + inPlaceEditor.getCols() + "'");

+            }

+            inPlaceEditorParams.append("}");

+            sr.append(inPlaceEditorParams.toString());

+        }

+        sr.append("\" />");

+        executeMacro(writer, sr.toString());

+        if (displayField instanceof DisplayEntityField) {

+            makeHyperlinkString(writer, ((DisplayEntityField) displayField).getSubHyperlink(), context);

+        }

+        this.appendTooltip(writer, context, modelFormField);

+    }

+

+    public void renderHyperlinkField(Appendable writer, Map<String, Object> context, HyperlinkField hyperlinkField) throws IOException {

+        this.request.setAttribute("image", hyperlinkField.getImageLocation(context));

+        ModelFormField modelFormField = hyperlinkField.getModelFormField();

+        String encodedAlternate = encode(hyperlinkField.getAlternate(context), modelFormField, context);

+        String encodedImageTitle = encode(hyperlinkField.getImageTitle(context), modelFormField, context);

+        this.request.setAttribute("alternate", encodedAlternate);

+        this.request.setAttribute("imageTitle", encodedImageTitle);

+        this.request.setAttribute("descriptionSize", hyperlinkField.getSize());

+        makeHyperlinkByType(writer, hyperlinkField.getLinkType(), modelFormField.getWidgetStyle(), hyperlinkField.getUrlMode(), hyperlinkField.getTarget(context), hyperlinkField.getParameterMap(context), hyperlinkField.getDescription(context), hyperlinkField.getTargetWindow(context),

+                hyperlinkField.getConfirmation(context), modelFormField, this.request, this.response, context);

+        this.appendTooltip(writer, context, modelFormField);

+        this.request.removeAttribute("image");

+        this.request.removeAttribute("descriptionSize");

+    }

+

+    public void renderTextField(Appendable writer, Map<String, Object> context, TextField textField) throws IOException {

+        ModelFormField modelFormField = textField.getModelFormField();

+        String name = modelFormField.getParameterName(context);

+        String className = "";

+        String alert = "false";

+        String mask = "";

+        String placeholder = textField.getPlaceholder(context);

+        if (UtilValidate.isNotEmpty(modelFormField.getWidgetStyle())) {

+            className = modelFormField.getWidgetStyle();

+            if (modelFormField.shouldBeRed(context)) {

+                alert = "true";

+            }

+        }

+        String value = modelFormField.getEntry(context, textField.getDefaultValue(context));

+        String textSize = Integer.toString(textField.getSize());

+        String maxlength = "";

+        if (textField.getMaxlength() != null) {

+            maxlength = Integer.toString(textField.getMaxlength());

+        }

+        String event = modelFormField.getEvent();

+        String action = modelFormField.getAction(context);

+        String id = modelFormField.getCurrentContainerId(context);

+        String clientAutocomplete = "false";

+        //check for required field style on single forms

+        if ("single".equals(modelFormField.getModelForm().getType()) && modelFormField.getRequiredField()) {

+            String requiredStyle = modelFormField.getRequiredFieldStyle();

+            if (UtilValidate.isEmpty(requiredStyle))

+                requiredStyle = "required";

+            if (UtilValidate.isEmpty(className))

+                className = requiredStyle;

+            else

+                className = requiredStyle + " " + className;

+        }

+        List<ModelForm.UpdateArea> updateAreas = modelFormField.getOnChangeUpdateAreas();

+        boolean ajaxEnabled = updateAreas != null && this.javaScriptEnabled;

+        if (textField.getClientAutocompleteField() || ajaxEnabled) {

+            clientAutocomplete = "true";

+        }

+        if (UtilValidate.isNotEmpty(textField.getMask())) {

+            mask = textField.getMask();

+        }

+        String ajaxUrl = createAjaxParamsFromUpdateAreas(updateAreas, "", context);

+        boolean disabled = textField.getDisabled();

+        StringWriter sr = new StringWriter();

+        sr.append("<@renderTextField ");

+        sr.append("name=\"");

+        sr.append(name);

+        sr.append("\" className=\"");

+        sr.append(className);

+        sr.append("\" alert=\"");

+        sr.append(alert);

+        sr.append("\" value=\"");

+        sr.append(value);

+        sr.append("\" textSize=\"");

+        sr.append(textSize);

+        sr.append("\" maxlength=\"");

+        sr.append(maxlength);

+        sr.append("\" id=\"");

+        sr.append(id);

+        sr.append("\" event=\"");

+        if (event != null) {

+            sr.append(event);

+        }

+        sr.append("\" action=\"");

+        if (action != null) {

+            sr.append(action);

+        }

+        sr.append("\" disabled=");

+        sr.append(Boolean.toString(disabled));

+        sr.append(" clientAutocomplete=\"");

+        sr.append(clientAutocomplete);

+        sr.append("\" ajaxUrl=\"");

+        sr.append(ajaxUrl);

+        sr.append("\" ajaxEnabled=");

+        sr.append(Boolean.toString(ajaxEnabled));

+        sr.append(" mask=\"");

+        sr.append(mask);

+        sr.append("\" placeholder=\"");

+        sr.append(placeholder);

+        sr.append("\" />");

+        executeMacro(writer, sr.toString());

+        ModelFormField.SubHyperlink subHyperlink = textField.getSubHyperlink();

+        if (subHyperlink != null && subHyperlink.shouldUse(context)) {

+            makeHyperlinkString(writer, subHyperlink, context);

+        }

+        this.addAsterisks(writer, context, modelFormField);

+        this.appendTooltip(writer, context, modelFormField);

+    }

+

+    public void renderTextareaField(Appendable writer, Map<String, Object> context, TextareaField textareaField) throws IOException {

+        ModelFormField modelFormField = textareaField.getModelFormField();

+        String name = modelFormField.getParameterName(context);

+        String cols = Integer.toString(textareaField.getCols());

+        String rows = Integer.toString(textareaField.getRows());

+        String id = modelFormField.getCurrentContainerId(context);

+        String className = "";

+        String alert = "false";

+        if (UtilValidate.isNotEmpty(modelFormField.getWidgetStyle())) {

+            className = modelFormField.getWidgetStyle();

+            if (modelFormField.shouldBeRed(context)) {

+                alert = "true";

+            }

+        }

+        //check for required field style on single forms

+        if ("single".equals(modelFormField.getModelForm().getType()) && modelFormField.getRequiredField()) {

+            String requiredStyle = modelFormField.getRequiredFieldStyle();

+            if (UtilValidate.isEmpty(requiredStyle))

+                requiredStyle = "required";

+            if (UtilValidate.isEmpty(className))

+                className = requiredStyle;

+            else

+                className = requiredStyle + " " + className;

+        }

+        String visualEditorEnable = "";

+        String buttons = "";

+        if (textareaField.getVisualEditorEnable()) {

+            visualEditorEnable = "true";

+            buttons = textareaField.getVisualEditorButtons(context);

+            if (UtilValidate.isEmpty(buttons)) {

+                buttons = "maxi";

+            }

+        }

+        String readonly = "";

+        if (textareaField.isReadOnly()) {

+            readonly = "readonly";

+        }

+        Map<String, Object> userLogin = UtilGenerics.checkMap(context.get("userLogin"));

+        String language = "en";

+        if (userLogin != null) {

+            language = UtilValidate.isEmpty((String) userLogin.get("lastLocale")) ? "en" : (String) userLogin.get("lastLocale");

+        }

+        String value = modelFormField.getEntry(context, textareaField.getDefaultValue(context));

+        StringWriter sr = new StringWriter();

+        sr.append("<@renderTextareaField ");

+        sr.append("name=\"");

+        sr.append(name);

+        sr.append("\" className=\"");

+        sr.append(className);

+        sr.append("\" alert=\"");

+        sr.append(alert);

+        sr.append("\" value=\"");

+        sr.append(value);

+        sr.append("\" cols=\"");

+        sr.append(cols);

+        sr.append("\" rows=\"");

+        sr.append(rows);

+        sr.append("\" id=\"");

+        sr.append(id);

+        sr.append("\" readonly=\"");

+        sr.append(readonly);

+        sr.append("\" visualEditorEnable=\"");

+        sr.append(visualEditorEnable);

+        sr.append("\" language=\"");

+        sr.append(language);

+        sr.append("\" buttons=\"");

+        sr.append(buttons);

+        sr.append("\" />");

+        executeMacro(writer, sr.toString());

+        this.addAsterisks(writer, context, modelFormField);

+        this.appendTooltip(writer, context, modelFormField);

+    }

+

+    public void renderDateTimeField(Appendable writer, Map<String, Object> context, DateTimeField dateTimeField) throws IOException {

+        ModelFormField modelFormField = dateTimeField.getModelFormField();

+        String paramName = modelFormField.getParameterName(context);

+        String defaultDateTimeString = dateTimeField.getDefaultDateTimeString(context);

+        String className = "";

+        String alert = "false";

+        String name = "";

+        String formattedMask = "";

+        String event = modelFormField.getEvent();

+        String action = modelFormField.getAction(context);

+        if (UtilValidate.isNotEmpty(modelFormField.getWidgetStyle())) {

+            className = modelFormField.getWidgetStyle();

+            if (modelFormField.shouldBeRed(context)) {

+                alert = "true";

+            }

+        }

+        boolean useTimeDropDown = "time-dropdown".equals(dateTimeField.getInputMethod());

+        String stepString = dateTimeField.getStep();

+        int step = 1;

+        StringBuilder timeValues = new StringBuilder();

+        if (useTimeDropDown && UtilValidate.isNotEmpty(step)) {

+            try {

+                step = Integer.valueOf(stepString).intValue();

+            } catch (IllegalArgumentException e) {

+                Debug.logWarning("Inavalid value for step property for field[" + paramName + "] with input-method=\"time-dropdown\" " + " Found Value [" + stepString + "]  " + e.getMessage(), module);

+            }

+            timeValues.append("[");

+            for (int i = 0; i <= 59;) {

+                if (i != 0) {

+                    timeValues.append(", ");

+                }

+                timeValues.append(i);

+                i += step;

+            }

+            timeValues.append("]");

+        }

+        Map<String, String> uiLabelMap = UtilGenerics.checkMap(context.get("uiLabelMap"));

+        if (uiLabelMap == null) {

+            Debug.logWarning("Could not find uiLabelMap in context", module);

+        }

+        String localizedInputTitle = "", localizedIconTitle = "";

+        // whether the date field is short form, yyyy-mm-dd

+        boolean shortDateInput = ("date".equals(dateTimeField.getType()) || useTimeDropDown ? true : false);

+        if (useTimeDropDown) {

+            name = UtilHttp.makeCompositeParam(paramName, "date");

+        } else {

+            name = paramName;

+        }

+        // the default values for a timestamp

+        int size = 25;

+        int maxlength = 30;

+        if (shortDateInput) {

+            size = maxlength = 10;

+            if (uiLabelMap != null) {

+                localizedInputTitle = uiLabelMap.get("CommonFormatDate");

+            }

+        } else if ("time".equals(dateTimeField.getType())) {

+            size = maxlength = 8;

+            if (uiLabelMap != null) {

+                localizedInputTitle = uiLabelMap.get("CommonFormatTime");

+            }

+        } else {

+            if (uiLabelMap != null) {

+                localizedInputTitle = uiLabelMap.get("CommonFormatDateTime");

+            }

+        }

+        /*

+         * FIXME: Using a builder here is a hack. Replace the builder with appropriate code.

+         */

+        ModelFormFieldBuilder builder = new ModelFormFieldBuilder(modelFormField);

+        boolean memEncodeOutput = modelFormField.getEncodeOutput();

+        if (useTimeDropDown)

+            // If time-dropdown deactivate encodingOutput for found hour and minutes

+            // FIXME: Encoding should be controlled by the renderer, not by the model.

+            builder.setEncodeOutput(false);

+        // FIXME: modelFormField.getEntry ignores shortDateInput when converting Date objects to Strings.

+        if (useTimeDropDown) {

+            builder.setEncodeOutput(memEncodeOutput);

+        }

+        modelFormField = builder.build();

+        String contextValue = modelFormField.getEntry(context, dateTimeField.getDefaultValue(context));

+        String value = contextValue;

+        if (UtilValidate.isNotEmpty(value)) {

+            if (value.length() > maxlength) {

+                value = value.substring(0, maxlength);

+            }

+        }

+        String id = modelFormField.getCurrentContainerId(context);

+        ModelForm modelForm = modelFormField.getModelForm();

+        String formName = FormRenderer.getCurrentFormName(modelForm, context);

+        String timeDropdown = dateTimeField.getInputMethod();

+        String timeDropdownParamName = "";

+        String classString = "";

+        boolean isTwelveHour = false;

+        String timeHourName = "";

+        int hour2 = 0, hour1 = 0, minutes = 0;

+        String timeMinutesName = "";

+        String amSelected = "", pmSelected = "", ampmName = "";

+        String compositeType = "";

+        // search for a localized label for the icon

+        if (uiLabelMap != null) {

+            localizedIconTitle = uiLabelMap.get("CommonViewCalendar");

+        }

+        if (!"time".equals(dateTimeField.getType())) {

+            String tempParamName;

+            if (useTimeDropDown) {

+                tempParamName = UtilHttp.makeCompositeParam(paramName, "date");

+            } else {

+                tempParamName = paramName;

+            }

+            timeDropdownParamName = tempParamName;

+            defaultDateTimeString = UtilHttp.encodeBlanks(modelFormField.getEntry(context, defaultDateTimeString));

+        }

+        // if we have an input method of time-dropdown, then render two

+        // dropdowns

+        if (useTimeDropDown) {

+            className = modelFormField.getWidgetStyle();

+            classString = (className != null ? className : "");

+            isTwelveHour = "12".equals(dateTimeField.getClock());

+            // set the Calendar to the default time of the form or now()

+            Calendar cal = null;

+            try {

+                Timestamp defaultTimestamp = Timestamp.valueOf(contextValue);

+                cal = Calendar.getInstance();

+                cal.setTime(defaultTimestamp);

+            } catch (IllegalArgumentException e) {

+                Debug.logWarning("Form widget field [" + paramName + "] with input-method=\"time-dropdown\" was not able to understand the default time [" + defaultDateTimeString + "]. The parsing error was: " + e.getMessage(), module);

+            }

+            timeHourName = UtilHttp.makeCompositeParam(paramName, "hour");

+            if (cal != null) {

+                int hour = cal.get(Calendar.HOUR_OF_DAY);

+                hour2 = hour;

+                if (hour == 0) {

+                    hour = 12;

+                }

+                if (hour > 12) {

+                    hour -= 12;

+                }

+                hour1 = hour;

+                minutes = cal.get(Calendar.MINUTE);

+            }

+            timeMinutesName = UtilHttp.makeCompositeParam(paramName, "minutes");

+            compositeType = UtilHttp.makeCompositeParam(paramName, "compositeType");

+            // if 12 hour clock, write the AM/PM selector

+            if (isTwelveHour) {

+                amSelected = ((cal != null && cal.get(Calendar.AM_PM) == Calendar.AM) ? "selected" : "");

+                pmSelected = ((cal != null && cal.get(Calendar.AM_PM) == Calendar.PM) ? "selected" : "");

+                ampmName = UtilHttp.makeCompositeParam(paramName, "ampm");

+            }

+        }

+        //check for required field style on single forms

+        if ("single".equals(modelFormField.getModelForm().getType()) && modelFormField.getRequiredField()) {

+            String requiredStyle = modelFormField.getRequiredFieldStyle();

+            if (UtilValidate.isEmpty(requiredStyle))

+                requiredStyle = "required";

+            if (UtilValidate.isEmpty(className))

+                className = requiredStyle;

+            else

+                className = requiredStyle + " " + className;

+        }

+        String mask = dateTimeField.getMask();

+        if ("Y".equals(mask)) {

+            if ("date".equals(dateTimeField.getType())) {

+                formattedMask = "9999-99-99";

+            } else if ("time".equals(dateTimeField.getType())) {

+                formattedMask = "99:99:99";

+            } else if ("timestamp".equals(dateTimeField.getType())) {

+                formattedMask = "9999-99-99 99:99:99";

+            }

+        }

+        StringWriter sr = new StringWriter();

+        sr.append("<@renderDateTimeField ");

+        sr.append("name=\"");

+        sr.append(name);

+        sr.append("\" className=\"");

+        sr.append(className);

+        sr.append("\" alert=\"");

+        sr.append(alert);

+        sr.append("\" value=\"");

+        sr.append(value);

+        sr.append("\" title=\"");

+        sr.append(localizedInputTitle);

+        sr.append("\" size=\"");

+        sr.append(Integer.toString(size));

+        sr.append("\" maxlength=\"");

+        sr.append(Integer.toString(maxlength));

+        sr.append("\" step=\"");

+        sr.append(Integer.toString(step));

+        sr.append("\" timeValues=\"");

+        sr.append(timeValues.toString());

+        sr.append("\" id=\"");

+        sr.append(id);

+        sr.append("\" event=\"");

+        sr.append(event);

+        sr.append("\" action=\"");

+        sr.append(action);

+        sr.append("\" dateType=\"");

+        sr.append(dateTimeField.getType());

+        sr.append("\" shortDateInput=");

+        sr.append(Boolean.toString(shortDateInput));

+        sr.append(" timeDropdownParamName=\"");

+        sr.append(timeDropdownParamName);

+        sr.append("\" defaultDateTimeString=\"");

+        sr.append(defaultDateTimeString);

+        sr.append("\" localizedIconTitle=\"");

+        sr.append(localizedIconTitle);

+        sr.append("\" timeDropdown=\"");

+        sr.append(timeDropdown);

+        sr.append("\" timeHourName=\"");

+        sr.append(timeHourName);

+        sr.append("\" classString=\"");

+        sr.append(classString);

+        sr.append("\" hour1=");

+        sr.append(Integer.toString(hour1));

+        sr.append(" hour2=");

+        sr.append(Integer.toString(hour2));

+        sr.append(" timeMinutesName=\"");

+        sr.append(timeMinutesName);

+        sr.append("\" minutes=");

+        sr.append(Integer.toString(minutes));

+        sr.append(" isTwelveHour=");

+        sr.append(Boolean.toString(isTwelveHour));

+        sr.append(" ampmName=\"");

+        sr.append(ampmName);

+        sr.append("\" amSelected=\"");

+        sr.append(amSelected);

+        sr.append("\" pmSelected=\"");

+        sr.append(pmSelected);

+        sr.append("\" compositeType=\"");

+        sr.append(compositeType);

+        sr.append("\" formName=\"");

+        sr.append(formName);

+        sr.append("\" mask=\"");

+        sr.append(formattedMask);

+        sr.append("\" />");

+        executeMacro(writer, sr.toString());

+        this.addAsterisks(writer, context, modelFormField);

+        this.appendTooltip(writer, context, modelFormField);

+    }

+

+    public void renderDropDownField(Appendable writer, Map<String, Object> context, DropDownField dropDownField) throws IOException {

+        ModelFormField modelFormField = dropDownField.getModelFormField();

+        ModelForm modelForm = modelFormField.getModelForm();

+        String currentValue = modelFormField.getEntry(context);

+        List<ModelFormField.OptionValue> allOptionValues = dropDownField.getAllOptionValues(context, WidgetWorker.getDelegator(context));

+        ModelFormField.AutoComplete autoComplete = dropDownField.getAutoComplete();

+        String event = modelFormField.getEvent();

+        String action = modelFormField.getAction(context);

+        Integer textSize = Integer.valueOf(0);

+        if (UtilValidate.isNotEmpty(dropDownField.getTextSize())) {

+            try {

+                textSize = Integer.parseInt(dropDownField.getTextSize());

+            } catch (NumberFormatException nfe) {

+                Debug.logError(nfe, "Error reading size of a field fieldName=" + dropDownField.getModelFormField().getFieldName() + " FormName= " + dropDownField.getModelFormField().getModelForm().getName(), module);

+            }

+            if (textSize > 0 && UtilValidate.isNotEmpty(currentValue) && currentValue.length() > textSize) {

+                currentValue = currentValue.substring(0, textSize - 8) + "..." + currentValue.substring(currentValue.length() - 5);

+            }

+        }

+        boolean ajaxEnabled = autoComplete != null && this.javaScriptEnabled;

+        String className = "";

+        String alert = "false";

+        String name = modelFormField.getParameterName(context);

+        String id = modelFormField.getCurrentContainerId(context);

+        String multiple = dropDownField.getAllowMultiple() ? "multiple" : "";

+        String otherFieldName = "";

+        String formName = modelForm.getName();

+        String size = dropDownField.getSize();

+        String dDFCurrent = dropDownField.getCurrent();

+        String firstInList = "";

+        String explicitDescription = "";

+        String allowEmpty = "";

+        StringBuilder options = new StringBuilder();

+        StringBuilder ajaxOptions = new StringBuilder();

+        if (UtilValidate.isNotEmpty(modelFormField.getWidgetStyle())) {

+            className = modelFormField.getWidgetStyle();

+            if (modelFormField.shouldBeRed(context)) {

+                alert = "true";

+            }

+        }

+        //check for required field style on single forms

+        if ("single".equals(modelFormField.getModelForm().getType()) && modelFormField.getRequiredField()) {

+            String requiredStyle = modelFormField.getRequiredFieldStyle();

+            if (UtilValidate.isEmpty(requiredStyle))

+                requiredStyle = "required";

+            if (UtilValidate.isEmpty(className))

+                className = requiredStyle;

+            else

+                className = requiredStyle + " " + className;

+        }

+        String currentDescription = null;

+        if (UtilValidate.isNotEmpty(currentValue)) {

+            for (ModelFormField.OptionValue optionValue : allOptionValues) {

+                if (optionValue.getKey().equals(currentValue)) {

+                    currentDescription = optionValue.getDescription();

+                    break;

+                }

+            }

+        }

+        int otherFieldSize = dropDownField.getOtherFieldSize();

+        if (otherFieldSize > 0) {

+            otherFieldName = dropDownField.getParameterNameOther(context);

+        }

+        // if the current value should go first, stick it in

+        if (UtilValidate.isNotEmpty(currentValue) && "first-in-list".equals(dropDownField.getCurrent())) {

+            firstInList = "first-in-list";

+        }

+        explicitDescription = (currentDescription != null ? currentDescription : dropDownField.getCurrentDescription(context));

+        if (UtilValidate.isEmpty(explicitDescription)) {

+            explicitDescription = (FieldInfoWithOptions.getDescriptionForOptionKey(currentValue, allOptionValues));

+        }

+        if (textSize > 0 && UtilValidate.isNotEmpty(explicitDescription) && explicitDescription.length() > textSize) {

+            explicitDescription = explicitDescription.substring(0, textSize - 8) + "..." + explicitDescription.substring(explicitDescription.length() - 5);

+        }

+        explicitDescription = encode(explicitDescription, modelFormField, context);

+        // if allow empty is true, add an empty option

+        if (dropDownField.getAllowEmpty()) {

+            allowEmpty = "Y";

+        }

+        List<String> currentValueList = null;

+        if (UtilValidate.isNotEmpty(currentValue) && dropDownField.getAllowMultiple()) {

+            // If currentValue is Array, it will start with [

+            if (currentValue.startsWith("[")) {

+                currentValueList = StringUtil.toList(currentValue);

+            } else {

+                currentValueList = UtilMisc.toList(currentValue);

+            }

+        }

+        options.append("[");

+        Iterator<ModelFormField.OptionValue> optionValueIter = allOptionValues.iterator();

+        int count = 0;

+        while (optionValueIter.hasNext()) {

+            ModelFormField.OptionValue optionValue = optionValueIter.next();

+            if (options.length() > 1) {

+                options.append(",");

+            }

+            options.append("{'key':'");

+            String key = encode(optionValue.getKey(), modelFormField, context);

+            options.append(key);

+            options.append("'");

+            options.append(",'description':'");

+            String description = optionValue.getDescription();

+            if (textSize > 0 && description.length() > textSize) {

+                description = description.substring(0, textSize - 8) + "..." + description.substring(description.length() - 5);

+            }

+            options.append(encode(description, modelFormField, context));

+

+            if (UtilValidate.isNotEmpty(currentValueList)) {

+                options.append("'");

+                options.append(",'selected':'");

+                if (currentValueList.contains(optionValue.getKey())) {

+                    options.append("selected");

+                } else {

+                    options.append("");

+                }

+            }

+

+            options.append("'}");

+            if (ajaxEnabled) {

+                count++;

+                ajaxOptions.append(optionValue.getKey()).append(": ");

+                ajaxOptions.append(" '").append(optionValue.getDescription()).append("'");

+                if (count != allOptionValues.size()) {

+                    ajaxOptions.append(", ");

+                }

+            }

+        }

+        options.append("]");

+        String noCurrentSelectedKey = dropDownField.getNoCurrentSelectedKey(context);

+        String otherValue = "", fieldName = "";

+        // Adapted from work by Yucca Korpela

+        // http://www.cs.tut.fi/~jkorpela/forms/combo.html

+        if (otherFieldSize > 0) {

+            fieldName = modelFormField.getParameterName(context);

+            Map<String, ? extends Object> dataMap = modelFormField.getMap(context);

+            if (dataMap == null) {

+                dataMap = context;

+            }

+            Object otherValueObj = dataMap.get(otherFieldName);

+            otherValue = (otherValueObj == null) ? "" : otherValueObj.toString();

+        }

+        String frequency = "";

+        String minChars = "";

+        String choices = "";

+        String autoSelect = "";

+        String partialSearch = "";

+        String partialChars = "";

+        String ignoreCase = "";

+        String fullSearch = "";

+        if (ajaxEnabled) {

+            frequency = autoComplete.getFrequency();

+            minChars = autoComplete.getMinChars();

+            choices = autoComplete.getChoices();

+            autoSelect = autoComplete.getAutoSelect();

+            partialSearch = autoComplete.getPartialSearch();

+            partialChars = autoComplete.getPartialChars();

+            ignoreCase = autoComplete.getIgnoreCase();

+            fullSearch = autoComplete.getFullSearch();

+        }

+        StringWriter sr = new StringWriter();

+        sr.append("<@renderDropDownField ");

+        sr.append("name=\"");

+        sr.append(name);

+        sr.append("\" className=\"");

+        sr.append(className);

+        sr.append("\" alert=\"");

+        sr.append(alert);

+        sr.append("\" id=\"");

+        sr.append(id);

+        sr.append("\" multiple=\"");

+        sr.append(multiple);

+        sr.append("\" formName=\"");

+        sr.append(formName);

+        sr.append("\" otherFieldName=\"");

+        sr.append(otherFieldName);

+        sr.append("\" event=\"");

+        if (event != null) {

+            sr.append(event);

+        }

+        sr.append("\" action=\"");

+        if (action != null) {

+            sr.append(action);

+        }

+        sr.append("\" size=\"");

+        sr.append(size);

+        sr.append("\" firstInList=\"");

+        sr.append(firstInList);

+        sr.append("\" currentValue=\"");

+        sr.append(currentValue);

+        sr.append("\" explicitDescription=\"");

+        sr.append(explicitDescription);

+        sr.append("\" allowEmpty=\"");

+        sr.append(allowEmpty);

+        sr.append("\" options=");

+        sr.append(options.toString());

+        sr.append(" fieldName=\"");

+        sr.append(fieldName);

+        sr.append("\" otherFieldName=\"");

+        sr.append(otherFieldName);

+        sr.append("\" otherValue=\"");

+        sr.append(otherValue);

+        sr.append("\" otherFieldSize=");

+        sr.append(Integer.toString(otherFieldSize));

+        sr.append(" dDFCurrent=\"");

+        sr.append(dDFCurrent);

+        sr.append("\" ajaxEnabled=");

+        sr.append(Boolean.toString(ajaxEnabled));

+        sr.append(" noCurrentSelectedKey=\"");

+        sr.append(noCurrentSelectedKey);

+        sr.append("\" ajaxOptions=\"");

+        sr.append(ajaxOptions.toString());

+        sr.append("\" frequency=\"");

+        sr.append(frequency);

+        sr.append("\" minChars=\"");

+        sr.append(minChars);

+        sr.append("\" choices=\"");

+        sr.append(choices);

+        sr.append("\" autoSelect=\"");

+        sr.append(autoSelect);

+        sr.append("\" partialSearch=\"");

+        sr.append(partialSearch);

+        sr.append("\" partialChars=\"");

+        sr.append(partialChars);

+        sr.append("\" ignoreCase=\"");

+        sr.append(ignoreCase);

+        sr.append("\" fullSearch=\"");

+        sr.append(fullSearch);

+        sr.append("\" />");

+        executeMacro(writer, sr.toString());

+        ModelFormField.SubHyperlink subHyperlink = dropDownField.getSubHyperlink();

+        if (subHyperlink != null && subHyperlink.shouldUse(context)) {

+            makeHyperlinkString(writer, subHyperlink, context);

+        }

+        this.appendTooltip(writer, context, modelFormField);

+    }

+

+    public void renderCheckField(Appendable writer, Map<String, Object> context, CheckField checkField) throws IOException {

+        ModelFormField modelFormField = checkField.getModelFormField();

+        modelFormField.getModelForm();

+        String currentValue = modelFormField.getEntry(context);

+        Boolean allChecked = checkField.isAllChecked(context);

+        String id = modelFormField.getCurrentContainerId(context);

+        String className = "";

+        String alert = "false";

+        String name = modelFormField.getParameterName(context);

+        String event = modelFormField.getEvent();

+        String action = modelFormField.getAction(context);

+        StringBuilder items = new StringBuilder();

+        if (UtilValidate.isNotEmpty(modelFormField.getWidgetStyle())) {

+            className = modelFormField.getWidgetStyle();

+            if (modelFormField.shouldBeRed(context)) {

+                alert = "true";

+            }

+        }

+        List<ModelFormField.OptionValue> allOptionValues = checkField.getAllOptionValues(context, WidgetWorker.getDelegator(context));

+        items.append("[");

+        for (ModelFormField.OptionValue optionValue : allOptionValues) {

+            if (items.length() > 1) {

+                items.append(",");

+            }

+            items.append("{'value':'");

+            items.append(optionValue.getKey());

+            items.append("', 'description':'" + encode(optionValue.getDescription(), modelFormField, context));

+            items.append("'}");

+        }

+        items.append("]");

+        StringWriter sr = new StringWriter();

+        sr.append("<@renderCheckField ");

+        sr.append("items=");

+        sr.append(items.toString());

+        sr.append(" className=\"");

+        sr.append(className);

+        sr.append("\" alert=\"");

+        sr.append(alert);

+        sr.append("\" id=\"");

+        sr.append(id);

+        sr.append("\" allChecked=");

+        sr.append((allChecked != null ? Boolean.toString(allChecked) : "\"\""));

+        sr.append(" currentValue=\"");

+        sr.append(currentValue);

+        sr.append("\" name=\"");

+        sr.append(name);

+        sr.append("\" event=\"");

+        if (event != null) {

+            sr.append(event);

+        }

+        sr.append("\" action=\"");

+        if (action != null) {

+            sr.append(action);

+        }

+        sr.append("\" />");

+        executeMacro(writer, sr.toString());

+        this.appendTooltip(writer, context, modelFormField);

+    }

+

+    public void renderRadioField(Appendable writer, Map<String, Object> context, RadioField radioField) throws IOException {

+        ModelFormField modelFormField = radioField.getModelFormField();

+        modelFormField.getModelForm();

+        List<ModelFormField.OptionValue> allOptionValues = radioField.getAllOptionValues(context, WidgetWorker.getDelegator(context));

+        String currentValue = modelFormField.getEntry(context);

+        String className = "";

+        String alert = "false";

+        String name = modelFormField.getParameterName(context);

+        String event = modelFormField.getEvent();

+        String action = modelFormField.getAction(context);

+        StringBuilder items = new StringBuilder();

+        if (UtilValidate.isNotEmpty(modelFormField.getWidgetStyle())) {

+            className = modelFormField.getWidgetStyle();

+            if (modelFormField.shouldBeRed(context)) {

+                alert = "true";

+            }

+        }

+        String noCurrentSelectedKey = radioField.getNoCurrentSelectedKey(context);

+        items.append("[");

+        for (ModelFormField.OptionValue optionValue : allOptionValues) {

+            if (items.length() > 1) {

+                items.append(",");

+            }

+            items.append("{'key':'");

+            items.append(optionValue.getKey());

+            items.append("', 'description':'" + encode(optionValue.getDescription(), modelFormField, context));

+            items.append("'}");

+        }

+        items.append("]");

+        StringWriter sr = new StringWriter();

+        sr.append("<@renderRadioField ");

+        sr.append("items=");

+        sr.append(items.toString());

+        sr.append(" className=\"");

+        sr.append(className);

+        sr.append("\" alert=\"");

+        sr.append(alert);

+        sr.append("\" currentValue=\"");

+        sr.append(currentValue);

+        sr.append("\" noCurrentSelectedKey=\"");

+        sr.append(noCurrentSelectedKey);

+        sr.append("\" name=\"");

+        sr.append(name);

+        sr.append("\" event=\"");

+        if (event != null) {

+            sr.append(event);

+        }

+        sr.append("\" action=\"");

+        if (action != null) {

+            sr.append(action);

+        }

+        sr.append("\" />");

+        executeMacro(writer, sr.toString());

+        this.appendTooltip(writer, context, modelFormField);

+    }

+

+    public void renderSubmitField(Appendable writer, Map<String, Object> context, SubmitField submitField) throws IOException {

+        ModelFormField modelFormField = submitField.getModelFormField();

+        ModelForm modelForm = modelFormField.getModelForm();

+        String event = modelFormField.getEvent();

+        String action = modelFormField.getAction(context);

+        String title = modelFormField.getTitle(context);

+        String name = modelFormField.getParameterName(context);

+        String buttonType = submitField.getButtonType();

+        String formName = FormRenderer.getCurrentFormName(modelForm, context);

+        String imgSrc = submitField.getImageLocation(context);

+        String confirmation = submitField.getConfirmation(context);

+        String className = "";

+        String alert = "false";

+        if (UtilValidate.isNotEmpty(modelFormField.getWidgetStyle())) {

+            className = modelFormField.getWidgetStyle();

+            if (modelFormField.shouldBeRed(context)) {

+                alert = "true";

+            }

+        }

+        String formId = FormRenderer.getCurrentContainerId(modelForm, context);

+        List<ModelForm.UpdateArea> updateAreas = modelForm.getOnSubmitUpdateAreas();

+        // This is here for backwards compatibility. Use on-event-update-area

+        // elements instead.

+        String backgroundSubmitRefreshTarget = submitField.getBackgroundSubmitRefreshTarget(context);

+        if (UtilValidate.isNotEmpty(backgroundSubmitRefreshTarget)) {

+            if (updateAreas == null) {

+                updateAreas = new LinkedList<ModelForm.UpdateArea>();

+            }

+            updateAreas.add(new ModelForm.UpdateArea("submit", formId, backgroundSubmitRefreshTarget));

+        }

+        boolean ajaxEnabled = (UtilValidate.isNotEmpty(updateAreas) || UtilValidate.isNotEmpty(backgroundSubmitRefreshTarget)) && this.javaScriptEnabled;

+        String ajaxUrl = "";

+        if (ajaxEnabled) {

+            ajaxUrl = createAjaxParamsFromUpdateAreas(updateAreas, "", context);

+        }

+        StringWriter sr = new StringWriter();

+        sr.append("<@renderSubmitField ");

+        sr.append("buttonType=\"");

+        sr.append(buttonType);

+        sr.append("\" className=\"");

+        sr.append(className);

+        sr.append("\" alert=\"");

+        sr.append(alert);

+        sr.append("\" formName=\"");

+        sr.append(formName);

+        sr.append("\" title=\"");

+        sr.append(encode(title, modelFormField, context));

+        sr.append("\" name=\"");

+        sr.append(name);

+        sr.append("\" event=\"");

+        if (event != null) {

+            sr.append(event);

+        }

+        sr.append("\" action=\"");

+        if (action != null) {

+            sr.append(action);

+        }

+        sr.append("\" imgSrc=\"");

+        sr.append(imgSrc);

+        sr.append("\" containerId=\"");

+        if (ajaxEnabled) {

+            sr.append(formId);

+        }

+        sr.append("\" confirmation =\"");

+        sr.append(confirmation);

+        sr.append("\" ajaxUrl=\"");

+        if (ajaxEnabled) {

+            sr.append(ajaxUrl);

+        }

+        sr.append("\" />");

+        executeMacro(writer, sr.toString());

+        this.appendTooltip(writer, context, modelFormField);

+    }

+

+    public void renderResetField(Appendable writer, Map<String, Object> context, ResetField resetField) throws IOException {

+        ModelFormField modelFormField = resetField.getModelFormField();

+        String name = modelFormField.getParameterName(context);

+        String className = "";

+        String alert = "false";

+        if (UtilValidate.isNotEmpty(modelFormField.getWidgetStyle())) {

+            className = modelFormField.getWidgetStyle();

+            if (modelFormField.shouldBeRed(context)) {

+                alert = "true";

+            }

+        }

+        String title = modelFormField.getTitle(context);

+        StringWriter sr = new StringWriter();

+        sr.append("<@renderResetField ");

+        sr.append(" className=\"");

+        sr.append(className);

+        sr.append("\" alert=\"");

+        sr.append(alert);

+        sr.append("\" name=\"");

+        sr.append(name);

+        sr.append("\" title=\"");

+        sr.append(title);

+        sr.append("\" />");

+        executeMacro(writer, sr.toString());

+        this.appendTooltip(writer, context, modelFormField);

+    }

+

+    public void renderHiddenField(Appendable writer, Map<String, Object> context, HiddenField hiddenField) throws IOException {

+        ModelFormField modelFormField = hiddenField.getModelFormField();

+        String value = hiddenField.getValue(context);

+        this.renderHiddenField(writer, context, modelFormField, value);

+    }

+

+    public void renderHiddenField(Appendable writer, Map<String, Object> context, ModelFormField modelFormField, String value) throws IOException {

+        String name = modelFormField.getParameterName(context);

+        String action = modelFormField.getAction(context);

+        String event = modelFormField.getEvent();

+        String id = modelFormField.getCurrentContainerId(context);

+        StringWriter sr = new StringWriter();

+        sr.append("<@renderHiddenField ");

+        sr.append(" name=\"");

+        sr.append(name);

+        sr.append("\" value=\"");

+        sr.append(value);

+        sr.append("\" id=\"");

+        sr.append(id);

+        sr.append("\" event=\"");

+        if (event != null) {

+            sr.append(event);

+        }

+        sr.append("\" action=\"");

+        if (action != null) {

+            sr.append(action);

+        }

+        sr.append("\" />");

+        executeMacro(writer, sr.toString());

+    }

+

+    public void renderIgnoredField(Appendable writer, Map<String, Object> context, IgnoredField ignoredField) {

+        // do nothing, it's an ignored field; could add a comment or something if we wanted to

+    }

+

+    public void renderFieldTitle(Appendable writer, Map<String, Object> context, ModelFormField modelFormField) throws IOException {

+        String titleText = modelFormField.getTitle(context);

+        String style = modelFormField.getTitleStyle();

+        String id = modelFormField.getCurrentContainerId(context);

+        StringBuilder sb = new StringBuilder();

+        if (UtilValidate.isNotEmpty(titleText)) {

+            if (" ".equals(titleText)) {

+                executeMacro(writer, "<@renderFormatEmptySpace />");

+            } else {

+                titleText = UtilHttp.encodeAmpersands(titleText);

+                titleText = encode(titleText, modelFormField, context);

+                if (UtilValidate.isNotEmpty(modelFormField.getHeaderLink())) {

+                    StringBuilder targetBuffer = new StringBuilder();

+                    FlexibleStringExpander target = FlexibleStringExpander.getInstance(modelFormField.getHeaderLink());

+                    String fullTarget = target.expandString(context);

+                    targetBuffer.append(fullTarget);

+                    String targetType = CommonWidgetModels.Link.DEFAULT_URL_MODE;

+                    if (UtilValidate.isNotEmpty(targetBuffer.toString()) && targetBuffer.toString().toLowerCase().startsWith("javascript:")) {

+                        targetType = "plain";

+                    }

+                    StringWriter sr = new StringWriter();

+                    makeHyperlinkString(sr, modelFormField.getHeaderLinkStyle(), targetType, targetBuffer.toString(), null, titleText, "", modelFormField, this.request, this.response, context, "");

+                    String title = sr.toString().replace("\"", "\'");

+                    sr = new StringWriter();

+                    sr.append("<@renderHyperlinkTitle ");

+                    sr.append(" name=\"");

+                    sr.append(modelFormField.getModelForm().getName());

+                    sr.append("\" title=\"");

+                    sr.append(FreeMarkerWorker.encodeDoubleQuotes(title));

+                    sr.append("\" />");

+                    executeMacro(writer, sr.toString());

+                } else if (modelFormField.isSortField()) {

+                    renderSortField(writer, context, modelFormField, titleText);

+                } else if (modelFormField.isRowSubmit()) {

+                    StringWriter sr = new StringWriter();

+                    sr.append("<@renderHyperlinkTitle ");

+                    sr.append(" name=\"");

+                    sr.append(modelFormField.getModelForm().getName());

+                    sr.append("\" title=\"");

+                    sr.append(titleText);

+                    sr.append("\" showSelectAll=\"Y\"/>");

+                    executeMacro(writer, sr.toString());

+                } else {

+                    sb.append(titleText);

+                }

+            }

+        }

+        if (!sb.toString().isEmpty()) {

+            //check for required field style on single forms

+            if ("single".equals(modelFormField.getModelForm().getType()) && modelFormField.getRequiredField()) {

+                String requiredStyle = modelFormField.getRequiredFieldStyle();

+                if (UtilValidate.isNotEmpty(requiredStyle)) {

+                    style = requiredStyle;

+                }

+            }

+            StringWriter sr = new StringWriter();

+            sr.append("<@renderFieldTitle ");

+            sr.append(" style=\"");

+            sr.append(style);

+            String displayHelpText = UtilProperties.getPropertyValue("widget.properties", "widget.form.displayhelpText");

+            if ("Y".equals(displayHelpText)) {

+                Delegator delegator = WidgetWorker.getDelegator(context);

+                Locale locale = (Locale) context.get("locale");

+                String entityName = modelFormField.getEntityName();

+                String fieldName = modelFormField.getFieldName();

+                String helpText = UtilHelpText.getEntityFieldDescription(entityName, fieldName, delegator, locale);

+

+                sr.append("\" fieldHelpText=\"");

+                sr.append(FreeMarkerWorker.encodeDoubleQuotes(helpText));

+            }

+            sr.append("\" title=\"");

+            sr.append(sb.toString());

+            if (UtilValidate.isNotEmpty(id)) {

+                sr.append("\" id=\"");

+                sr.append(id);

+                sr.append("_title");

+                // Render "for"

+                sr.append("\" for=\"");

+                sr.append(id);

+            }

+            sr.append("\" />");

+            executeMacro(writer, sr.toString());

+        }

+    }

+

+    public void renderSingleFormFieldTitle(Appendable writer, Map<String, Object> context, ModelFormField modelFormField) throws IOException {

+        renderFieldTitle(writer, context, modelFormField);

+    }

+

+    public void renderFormOpen(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {

+        this.widgetCommentsEnabled = ModelWidget.widgetBoundaryCommentsEnabled(context);

+        renderBeginningBoundaryComment(writer, "Form Widget - Form Element", modelForm);

+        String targetType = modelForm.getTargetType();

+        String targ = modelForm.getTarget(context, targetType);

+        StringBuilder linkUrl = new StringBuilder();

+        if (UtilValidate.isNotEmpty(targ)) {

+            //this.appendOfbizUrl(writer, "/" + targ);

+            WidgetWorker.buildHyperlinkUrl(linkUrl, targ, targetType, null, null, false, false, true, request, response, context);

+        }

+        String formType = modelForm.getType();

+        String targetWindow = modelForm.getTargetWindow(context);

+        String containerId = FormRenderer.getCurrentContainerId(modelForm, context);

+        String containerStyle = modelForm.getContainerStyle();

+        String autocomplete = "";

+        String name = FormRenderer.getCurrentFormName(modelForm, context);

+        String viewIndexField = modelForm.getMultiPaginateIndexField(context);

+        String viewSizeField = modelForm.getMultiPaginateSizeField(context);

+        int viewIndex = Paginator.getViewIndex(modelForm, context);

+        int viewSize = Paginator.getViewSize(modelForm, context);

+        boolean useRowSubmit = modelForm.getUseRowSubmit();

+        if (!modelForm.getClientAutocompleteFields()) {

+            autocomplete = "off";

+        }

+        StringWriter sr = new StringWriter();

+        sr.append("<@renderFormOpen ");

+        sr.append(" linkUrl=\"");

+        sr.append(linkUrl);

+        sr.append("\" formType=\"");

+        sr.append(formType);

+        sr.append("\" targetWindow=\"");

+        sr.append(targetWindow);

+        sr.append("\" containerId=\"");

+        sr.append(containerId);

+        sr.append("\" containerStyle=\"");

+        sr.append(containerStyle);

+        sr.append("\" autocomplete=\"");

+        sr.append(autocomplete);

+        sr.append("\" name=\"");

+        sr.append(name);

+        sr.append("\" viewIndexField=\"");

+        sr.append(viewIndexField);

+        sr.append("\" viewSizeField=\"");

+        sr.append(viewSizeField);

+        sr.append("\" viewIndex=\"");

+        sr.append(Integer.toString(viewIndex));

+        sr.append("\" viewSize=\"");

+        sr.append(Integer.toString(viewSize));

+        sr.append("\" useRowSubmit=");

+        sr.append(Boolean.toString(useRowSubmit));

+        sr.append(" />");

+        executeMacro(writer, sr.toString());

+    }

+

+    public void renderFormClose(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {

+        String focusFieldName = FormRenderer.getFocusFieldName(modelForm, context);

+        String formName = FormRenderer.getCurrentFormName(modelForm, context);

+        String containerId = FormRenderer.getCurrentContainerId(modelForm, context);

+        String hasRequiredField = "";

+        for (ModelFormField formField : modelForm.getFieldList()) {

+            if (formField.getRequiredField()) {

+                hasRequiredField = "Y";

+                break;

+            }

+        }

+        StringWriter sr = new StringWriter();

+        sr.append("<@renderFormClose ");

+        sr.append(" focusFieldName=\"");

+        sr.append(focusFieldName);

+        sr.append("\" formName=\"");

+        sr.append(formName);

+        sr.append("\" containerId=\"");

+        sr.append(containerId);

+        sr.append("\" hasRequiredField=\"");

+        sr.append(hasRequiredField);

+        sr.append("\" />");

+        executeMacro(writer, sr.toString());

+        renderEndingBoundaryComment(writer, "Form Widget - Form Element", modelForm);

+    }

+

+    public void renderMultiFormClose(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {

+        //FIXME copy from HtmlFormRenderer.java (except for the closing form tag itself, that is now converted)

+        Iterator<ModelFormField> submitFields = modelForm.getMultiSubmitFields().iterator();

+        while (submitFields.hasNext()) {

+            ModelFormField submitField = submitFields.next();

+            if (submitField != null && submitField.shouldUse(context)) {

+                // Threw this in that as a hack to keep the submit button from expanding the first field

+                // Needs a more rugged solution

+                // WARNING: this method (renderMultiFormClose) must be called after the

+                // table that contains the list has been closed (to avoid validation errors) so

+                // we cannot call here the methods renderFormatItemRowCell*: for this reason

+                // they are now commented.

+                // this.renderFormatItemRowCellOpen(writer, context, modelForm, submitField);

+                // this.renderFormatItemRowCellClose(writer, context, modelForm, submitField);

+                // this.renderFormatItemRowCellOpen(writer, context, modelForm, submitField);

+                submitField.renderFieldString(writer, context, this);

+                // this.renderFormatItemRowCellClose(writer, context, modelForm, submitField);

+            }

+        }

+        StringWriter sr = new StringWriter();

+        sr.append("<@renderMultiFormClose />");

+        executeMacro(writer, sr.toString());

+        // see if there is anything that needs to be added outside of the multi-form

+        Map<String, Object> wholeFormContext = UtilGenerics.checkMap(context.get("wholeFormContext"));

+        Appendable postMultiFormWriter = wholeFormContext != null ? (Appendable) wholeFormContext.get("postMultiFormWriter") : null;

+        if (postMultiFormWriter != null) {

+            writer.append(postMultiFormWriter.toString());

+            appendWhitespace(writer);

+        }

+        renderEndingBoundaryComment(writer, "Form Widget - Form Element (Multi)", modelForm);

+    }

+

+    public void renderFormatListWrapperOpen(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {

+        Map<String, Object> inputFields = UtilGenerics.checkMap(context.get("requestParameters"));

+        Map<String, Object> queryStringMap = UtilGenerics.toMap(context.get("queryStringMap"));

+        if (UtilValidate.isNotEmpty(queryStringMap)) {

+            inputFields.putAll(queryStringMap);

+        }

+        if (modelForm.getType().equals("multi")) {

+            inputFields = UtilHttp.removeMultiFormParameters(inputFields);

+        }

+        String queryString = UtilHttp.urlEncodeArgs(inputFields);

+        context.put("_QBESTRING_", queryString);

+        renderBeginningBoundaryComment(writer, "Form Widget", modelForm);

+        if (this.renderPagination) {

+            this.renderNextPrev(writer, context, modelForm);

+        }

+        List<ModelFormField> childFieldList = modelForm.getFieldList();

+        List<String> columnStyleList = new LinkedList<String>();

+        List<String> fieldNameList = new LinkedList<String>();

+        for (ModelFormField childField : childFieldList) {

+            int childFieldType = childField.getFieldInfo().getFieldType();

+            if (childFieldType == FieldInfo.HIDDEN || childFieldType == FieldInfo.IGNORED) {

+                continue;

+            }

+            String areaStyle = childField.getTitleAreaStyle();

+            if (UtilValidate.isEmpty(areaStyle)) {

+                areaStyle = "";

+            }

+            if (fieldNameList.contains(childField.getName())) {

+                if (UtilValidate.isNotEmpty(areaStyle)) {

+                    columnStyleList.set(fieldNameList.indexOf(childField.getName()), areaStyle);

+                }

+            } else {

+                columnStyleList.add(areaStyle);

+                fieldNameList.add(childField.getName());

+            }

+        }

+        columnStyleList = StringUtil.quoteStrList(columnStyleList);

+        String columnStyleListString = StringUtil.join(columnStyleList, ", ");

+        StringWriter sr = new StringWriter();

+        sr.append("<@renderFormatListWrapperOpen ");

+        sr.append(" formName=\"");

+        sr.append(modelForm.getName());

+        sr.append("\" style=\"");

+        sr.append(FlexibleStringExpander.expandString(modelForm.getDefaultTableStyle(), context));

+        sr.append("\" columnStyles=[");

+        if (UtilValidate.isNotEmpty(columnStyleListString)) {

+            // this is a fix for forms with no fields

+            sr.append(columnStyleListString);

+        }

+        sr.append("] />");

+        executeMacro(writer, sr.toString());

+

+    }

+

+    public void renderFormatListWrapperClose(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {

+        StringWriter sr = new StringWriter();

+        sr.append("<@renderFormatListWrapperClose");

+        sr.append(" formName=\"");

+        sr.append(modelForm.getName());

+        sr.append("\" />");

+        executeMacro(writer, sr.toString());

+        if (this.renderPagination) {

+            this.renderNextPrev(writer, context, modelForm);

+        }

+        renderEndingBoundaryComment(writer, "Form Widget - Formal List Wrapper", modelForm);

+    }

+

+    public void renderFormatHeaderRowOpen(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {

+        String headerStyle = FlexibleStringExpander.expandString(modelForm.getHeaderRowStyle(), context);

+        StringWriter sr = new StringWriter();

+        sr.append("<@renderFormatHeaderRowOpen ");

+        sr.append(" style=\"");

+        sr.append(headerStyle);

+        sr.append("\" />");

+        executeMacro(writer, sr.toString());

+    }

+

+    public void renderFormatHeaderRowClose(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {

+        StringWriter sr = new StringWriter();

+        sr.append("<@renderFormatHeaderRowClose />");

+        executeMacro(writer, sr.toString());

+    }

+

+    public void renderFormatHeaderRowCellOpen(Appendable writer, Map<String, Object> context, ModelForm modelForm, ModelFormField modelFormField, int positionSpan) throws IOException {

+        String areaStyle = modelFormField.getTitleAreaStyle();

+        StringWriter sr = new StringWriter();

+        sr.append("<@renderFormatHeaderRowCellOpen ");

+        sr.append(" style=\"");

+        sr.append(areaStyle);

+        sr.append("\" positionSpan=");

+        sr.append(Integer.toString(positionSpan));

+        sr.append(" />");

+        executeMacro(writer, sr.toString());

+    }

+

+    public void renderFormatHeaderRowCellClose(Appendable writer, Map<String, Object> context, ModelForm modelForm, ModelFormField modelFormField) throws IOException {

+        StringWriter sr = new StringWriter();

+        sr.append("<@renderFormatHeaderRowCellClose />");

+        executeMacro(writer, sr.toString());

+    }

+

+    public void renderFormatHeaderRowFormCellOpen(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {

+        String areaStyle = modelForm.getFormTitleAreaStyle();

+        StringWriter sr = new StringWriter();

+        sr.append("<@renderFormatHeaderRowFormCellOpen ");

+        sr.append(" style=\"");

+        sr.append(areaStyle);

+        sr.append("\" />");

+        executeMacro(writer, sr.toString());

+    }

+

+    public void renderFormatHeaderRowFormCellClose(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {

+        StringWriter sr = new StringWriter();

+        sr.append("<@renderFormatHeaderRowFormCellClose />");

+        executeMacro(writer, sr.toString());

+    }

+

+    public void renderFormatHeaderRowFormCellTitleSeparator(Appendable writer, Map<String, Object> context, ModelForm modelForm, ModelFormField modelFormField, boolean isLast) throws IOException {

+        String titleStyle = modelFormField.getTitleStyle();

+        StringWriter sr = new StringWriter();

+        sr.append("<@renderFormatHeaderRowFormCellTitleSeparator ");

+        sr.append(" style=\"");

+        sr.append(titleStyle);

+        sr.append("\" isLast=");

+        sr.append(Boolean.toString(isLast));

+        sr.append(" />");

+        executeMacro(writer, sr.toString());

+    }

+

+    public void renderFormatItemRowOpen(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {

+        Integer itemIndex = (Integer) context.get("itemIndex");

+        String altRowStyles = "";

+        String evenRowStyle = "";

+        String oddRowStyle = "";

+        if (itemIndex != null) {

+            altRowStyles = modelForm.getStyleAltRowStyle(context);

+            if (itemIndex.intValue() % 2 == 0) {

+                evenRowStyle = modelForm.getEvenRowStyle();

+            } else {

+                oddRowStyle = FlexibleStringExpander.expandString(modelForm.getOddRowStyle(), context);

+            }

+        }

+        StringWriter sr = new StringWriter();

+        sr.append("<@renderFormatItemRowOpen ");

+        sr.append(" formName=\"");

+        sr.append(modelForm.getName());

+        sr.append("\" itemIndex=");

+        sr.append(Integer.toString(itemIndex));

+        sr.append(" altRowStyles=\"");

+        sr.append(altRowStyles);

+        sr.append("\" evenRowStyle=\"");

+        sr.append(evenRowStyle);

+        sr.append("\" oddRowStyle=\"");

+        sr.append(oddRowStyle);

+        sr.append("\" />");

+        executeMacro(writer, sr.toString());

+    }

+

+    public void renderFormatItemRowClose(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {

+        StringWriter sr = new StringWriter();

+        sr.append("<@renderFormatItemRowClose ");

+        sr.append(" formName=\"");

+        sr.append(modelForm.getName());

+        sr.append("\"/>");

+        executeMacro(writer, sr.toString());

+    }

+

+    public void renderFormatItemRowCellOpen(Appendable writer, Map<String, Object> context, ModelForm modelForm, ModelFormField modelFormField, int positionSpan) throws IOException {

+        String areaStyle = modelFormField.getWidgetAreaStyle();

+        StringWriter sr = new StringWriter();

+        sr.append("<@renderFormatItemRowCellOpen ");

+        sr.append(" fieldName=\"");

+        sr.append(modelFormField.getName());

+        sr.append("\" style=\"");

+        sr.append(areaStyle);

+        sr.append("\" positionSpan=");

+        sr.append(Integer.toString(positionSpan));

+        sr.append(" />");

+        executeMacro(writer, sr.toString());

+    }

+

+    public void renderFormatItemRowCellClose(Appendable writer, Map<String, Object> context, ModelForm modelForm, ModelFormField modelFormField) throws IOException {

+        StringWriter sr = new StringWriter();

+        sr.append("<@renderFormatItemRowCellClose");

+        sr.append(" fieldName=\"");

+        sr.append(modelFormField.getName());

+        sr.append("\"/>");

+        executeMacro(writer, sr.toString());

+    }

+

+    public void renderFormatItemRowFormCellOpen(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {

+        String areaStyle = modelForm.getFormTitleAreaStyle();

+        StringWriter sr = new StringWriter();

+        sr.append("<@renderFormatItemRowFormCellOpen ");

+        sr.append(" style=\"");

+        sr.append(areaStyle);

+        sr.append("\" />");

+        executeMacro(writer, sr.toString());

+    }

+

+    public void renderFormatItemRowFormCellClose(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {

+        StringWriter sr = new StringWriter();

+        sr.append("<@renderFormatItemRowFormCellClose />");

+        executeMacro(writer, sr.toString());

+    }

+

+    public void renderFormatSingleWrapperOpen(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {

+        String style = FlexibleStringExpander.expandString(modelForm.getDefaultTableStyle(), context);

+        StringWriter sr = new StringWriter();

+        sr.append("<@renderFormatSingleWrapperOpen ");

+        sr.append(" formName=\"");

+        sr.append(modelForm.getName());

+        sr.append("\" style=\"");

+        sr.append(style);

+        sr.append("\" />");

+        executeMacro(writer, sr.toString());

+    }

+

+    public void renderFormatSingleWrapperClose(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {

+        StringWriter sr = new StringWriter();

+        sr.append("<@renderFormatSingleWrapperClose");

+        sr.append(" formName=\"");

+        sr.append(modelForm.getName());

+        sr.append("\"/>");

+        executeMacro(writer, sr.toString());

+    }

+

+    public void renderFormatFieldRowOpen(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {

+        StringWriter sr = new StringWriter();

+        sr.append("<@renderFormatFieldRowOpen />");

+        executeMacro(writer, sr.toString());

+    }

+

+    public void renderFormatFieldRowClose(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {

+        StringWriter sr = new StringWriter();

+        sr.append("<@renderFormatFieldRowClose />");

+        executeMacro(writer, sr.toString());

+    }

+

+    public void renderFormatFieldRowTitleCellOpen(Appendable writer, Map<String, Object> context, ModelFormField modelFormField) throws IOException {

+        String style = modelFormField.getTitleAreaStyle();

+        StringWriter sr = new StringWriter();

+        sr.append("<@renderFormatFieldRowTitleCellOpen ");

+        sr.append(" style=\"");

+        sr.append(style);

+        sr.append("\" />");

+        executeMacro(writer, sr.toString());

+    }

+

+    public void renderFormatFieldRowTitleCellClose(Appendable writer, Map<String, Object> context, ModelFormField modelFormField) throws IOException {

+        StringWriter sr = new StringWriter();

+        sr.append("<@renderFormatFieldRowTitleCellClose />");

+        executeMacro(writer, sr.toString());

+    }

+

+    public void renderFormatFieldRowSpacerCell(Appendable writer, Map<String, Object> context, ModelFormField modelFormField) throws IOException {

+    }

+

+    public void renderFormatFieldRowWidgetCellOpen(Appendable writer, Map<String, Object> context, ModelFormField modelFormField, int positions, int positionSpan, Integer nextPositionInRow) throws IOException {

+        String areaStyle = modelFormField.getWidgetAreaStyle();

+        StringWriter sr = new StringWriter();

+        sr.append("<@renderFormatFieldRowWidgetCellOpen ");

+        sr.append(" positionSpan=");

+        sr.append(Integer.toString(positionSpan));

+        sr.append(" style=\"");

+        sr.append(areaStyle);

+        sr.append("\" />");

+        executeMacro(writer, sr.toString());

+    }

+

+    public void renderFormatFieldRowWidgetCellClose(Appendable writer, Map<String, Object> context, ModelFormField modelFormField, int positions, int positionSpan, Integer nextPositionInRow) throws IOException {

+        StringWriter sr = new StringWriter();

+        sr.append("<@renderFormatFieldRowWidgetCellClose />");

+        executeMacro(writer, sr.toString());

+    }

+

+    public void renderFormatEmptySpace(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {

+        StringWriter sr = new StringWriter();

+        sr.append("<@renderFormatEmptySpace />");

+        executeMacro(writer, sr.toString());

+    }

+

+    public void renderTextFindField(Appendable writer, Map<String, Object> context, TextFindField textFindField) throws IOException {

+        ModelFormField modelFormField = textFindField.getModelFormField();

+        String defaultOption = textFindField.getDefaultOption();

+        String className = "";

+        String alert = "false";

+        String opEquals = "";

+        String opBeginsWith = "";

+        String opContains = "";

+        String opIsEmpty = "";

+        String opNotEqual = "";

+        String name = modelFormField.getParameterName(context);

+        String size = Integer.toString(textFindField.getSize());

+        String maxlength = "";

+        String autocomplete = "";

+        if (UtilValidate.isNotEmpty(modelFormField.getWidgetStyle())) {

+            className = modelFormField.getWidgetStyle();

+            if (modelFormField.shouldBeRed(context)) {

+                alert = "true";

+            }

+        }

+        Locale locale = (Locale) context.get("locale");

+        if (!textFindField.getHideOptions()) {

+            opEquals = UtilProperties.getMessage("conditional", "equals", locale);

+            opBeginsWith = UtilProperties.getMessage("conditional", "begins_with", locale);

+            opContains = UtilProperties.getMessage("conditional", "contains", locale);

+            opIsEmpty = UtilProperties.getMessage("conditional", "is_empty", locale);

+            opNotEqual = UtilProperties.getMessage("conditional", "not_equal", locale);

+        }

+        String value = modelFormField.getEntry(context, textFindField.getDefaultValue(context));

+        if (value == null) {

+            value = "";

+        }

+        if (textFindField.getMaxlength() != null) {

+            maxlength = textFindField.getMaxlength().toString();

+        }

+        if (!textFindField.getClientAutocompleteField()) {

+            autocomplete = "off";

+        }

+        String titleStyle = "";

+        if (UtilValidate.isNotEmpty(modelFormField.getTitleStyle())) {

+            titleStyle = modelFormField.getTitleStyle();

+        }

+        String ignoreCase = UtilProperties.getMessage("conditional", "ignore_case", locale);

+        boolean ignCase = textFindField.getIgnoreCase();

+        boolean hideIgnoreCase = textFindField.getHideIgnoreCase();

+        StringWriter sr = new StringWriter();

+        sr.append("<@renderTextFindField ");

+        sr.append(" name=\"");

+        sr.append(name);

+        sr.append("\" value=\"");

+        sr.append(value);

+        sr.append("\" defaultOption=\"");

+        sr.append(defaultOption);

+        sr.append("\" opEquals=\"");

+        sr.append(opEquals);

+        sr.append("\" opBeginsWith=\"");

+        sr.append(opBeginsWith);

+        sr.append("\" opContains=\"");

+        sr.append(opContains);

+        sr.append("\" opIsEmpty=\"");

+        sr.append(opIsEmpty);

+        sr.append("\" opNotEqual=\"");

+        sr.append(opNotEqual);

+        sr.append("\" className=\"");

+        sr.append(className);

+        sr.append("\" alert=\"");

+        sr.append(alert);

+        sr.append("\" size=\"");

+        sr.append(size);

+        sr.append("\" maxlength=\"");

+        sr.append(maxlength);

+        sr.append("\" autocomplete=\"");

+        sr.append(autocomplete);

+        sr.append("\" titleStyle=\"");

+        sr.append(titleStyle);

+        sr.append("\" hideIgnoreCase=");

+        sr.append(Boolean.toString(hideIgnoreCase));

+        sr.append(" ignCase=");

+        sr.append(Boolean.toString(ignCase));

+        sr.append(" ignoreCase=\"");

+        sr.append(ignoreCase);

+        sr.append("\" />");

+        executeMacro(writer, sr.toString());

+        this.appendTooltip(writer, context, modelFormField);

+    }

+

+    public void renderRangeFindField(Appendable writer, Map<String, Object> context, RangeFindField rangeFindField) throws IOException {

+        ModelFormField modelFormField = rangeFindField.getModelFormField();

+        Locale locale = (Locale) context.get("locale");

+        String opEquals = UtilProperties.getMessage("conditional", "equals", locale);

+        String opGreaterThan = UtilProperties.getMessage("conditional", "greater_than", locale);

+        String opGreaterThanEquals = UtilProperties.getMessage("conditional", "greater_than_equals", locale);

+        String opLessThan = UtilProperties.getMessage("conditional", "less_than", locale);

+        String opLessThanEquals = UtilProperties.getMessage("conditional", "less_than_equals", locale);

+        //String opIsEmpty = UtilProperties.getMessage("conditional", "is_empty", locale);

+        String className = "";

+        String alert = "false";

+        if (UtilValidate.isNotEmpty(modelFormField.getWidgetStyle())) {

+            className = modelFormField.getWidgetStyle();

+            if (modelFormField.shouldBeRed(context)) {

+                alert = "true";

+            }

+        }

+        String name = modelFormField.getParameterName(context);

+        String size = Integer.toString(rangeFindField.getSize());

+        String value = modelFormField.getEntry(context, rangeFindField.getDefaultValue(context));

+        if (value == null) {

+            value = "";

+        }

+        Integer maxlength = rangeFindField.getMaxlength();

+        String autocomplete = "";

+

+        if (!rangeFindField.getClientAutocompleteField()) {

+            autocomplete = "off";

+        }

+        String titleStyle = modelFormField.getTitleStyle();

+

+        if (titleStyle == null) {

+            titleStyle = "";

+        }

+        String defaultOptionFrom = rangeFindField.getDefaultOptionFrom();

+        String value2 = modelFormField.getEntry(context);

+        if (value2 == null) {

+            value2 = "";

+        }

+        String defaultOptionThru = rangeFindField.getDefaultOptionThru();

+        StringWriter sr = new StringWriter();

+        sr.append("<@renderRangeFindField ");

+        sr.append(" className=\"");

+        sr.append(className);

+        sr.append("\" alert=\"");

+        sr.append(alert);

+        sr.append("\" name=\"");

+        sr.append(name);

+        sr.append("\" value=\"");

+        sr.append(value);

+        sr.append("\" size=\"");

+        sr.append(size);

+        sr.append("\" maxlength=\"");

+        if (maxlength != null) {

+            sr.append(Integer.toString(maxlength));

+        }

+        sr.append("\" autocomplete=\"");

+        sr.append(autocomplete);

+        sr.append("\" titleStyle=\"");

+        sr.append(titleStyle);

+        sr.append("\" defaultOptionFrom=\"");

+        sr.append(defaultOptionFrom);

+        sr.append("\" opEquals=\"");

+        sr.append(opEquals);

+        sr.append("\" opGreaterThan=\"");

+        sr.append(opGreaterThan);

+        sr.append("\" opGreaterThanEquals=\"");

+        sr.append(opGreaterThanEquals);

+        sr.append("\" opLessThan=\"");

+        sr.append(opLessThan);

+        sr.append("\" opLessThanEquals=\"");

+        sr.append(opLessThanEquals);

+        sr.append("\" value2=\"");

+        sr.append(value2);

+        sr.append("\" defaultOptionThru=\"");

+        sr.append(defaultOptionThru);

+        sr.append("\" />");

+        executeMacro(writer, sr.toString());

+        this.appendTooltip(writer, context, modelFormField);

+    }

+

+    public void renderDateFindField(Appendable writer, Map<String, Object> context, DateFindField dateFindField) throws IOException {

+        ModelFormField modelFormField = dateFindField.getModelFormField();

+        Locale locale = (Locale) context.get("locale");

+        String opEquals = UtilProperties.getMessage("conditional", "equals", locale);

+        String opGreaterThan = UtilProperties.getMessage("conditional", "greater_than", locale);

+        String opSameDay = UtilProperties.getMessage("conditional", "same_day", locale);

+        String opGreaterThanFromDayStart = UtilProperties.getMessage("conditional", "greater_than_from_day_start", locale);

+        String opLessThan = UtilProperties.getMessage("conditional", "less_than", locale);

+        String opUpToDay = UtilProperties.getMessage("conditional", "up_to_day", locale);

+        String opUpThruDay = UtilProperties.getMessage("conditional", "up_thru_day", locale);

+        String opIsEmpty = UtilProperties.getMessage("conditional", "is_empty", locale);

+        Map<String, String> uiLabelMap = UtilGenerics.checkMap(context.get("uiLabelMap"));

+        if (uiLabelMap == null) {

+            Debug.logWarning("Could not find uiLabelMap in context", module);

+        }

+        String localizedInputTitle = "", localizedIconTitle = "";

+        String className = "";

+        String alert = "false";

+        if (UtilValidate.isNotEmpty(modelFormField.getWidgetStyle())) {

+            className = modelFormField.getWidgetStyle();

+            if (modelFormField.shouldBeRed(context)) {

+                alert = "true";

+            }

+        }

+        String name = modelFormField.getParameterName(context);

+        // the default values for a timestamp

+        int size = 25;

+        int maxlength = 30;

+        String dateType = dateFindField.getType();

+        if ("date".equals(dateType)) {

+            size = maxlength = 10;

+            if (uiLabelMap != null) {

+                localizedInputTitle = uiLabelMap.get("CommonFormatDate");

+            }

+        } else if ("time".equals(dateFindField.getType())) {

+            size = maxlength = 8;

+            if (uiLabelMap != null) {

+                localizedInputTitle = uiLabelMap.get("CommonFormatTime");

+            }

+        } else {

+            if (uiLabelMap != null) {

+                localizedInputTitle = uiLabelMap.get("CommonFormatDateTime");

+            }

+        }

+        String value = modelFormField.getEntry(context, dateFindField.getDefaultValue(context));

+        if (value == null) {

+            value = "";

+        }

+        // search for a localized label for the icon

+        if (uiLabelMap != null) {

+            localizedIconTitle = uiLabelMap.get("CommonViewCalendar");

+        }

+        String formName = "";

+        String defaultDateTimeString = "";

+        StringBuilder imgSrc = new StringBuilder();

+        // add calendar pop-up button and seed data IF this is not a "time" type date-find

+        if (!"time".equals(dateFindField.getType())) {

+            ModelForm modelForm = modelFormField.getModelForm();

+            formName = FormRenderer.getCurrentFormName(modelForm, context);

+            defaultDateTimeString = UtilHttp.encodeBlanks(modelFormField.getEntry(context, dateFindField.getDefaultDateTimeString(context)));

+            this.appendContentUrl(imgSrc, "/images/cal.gif");

+        }

+        String defaultOptionFrom = dateFindField.getDefaultOptionFrom();

+        String defaultOptionThru = dateFindField.getDefaultOptionThru();

+        String value2 = modelFormField.getEntry(context);

+        if (value2 == null) {

+            value2 = "";

+        }

+        String titleStyle = "";

+        if (UtilValidate.isNotEmpty(modelFormField.getTitleStyle())) {

+            titleStyle = modelFormField.getTitleStyle();

+        }

+        StringWriter sr = new StringWriter();

+        sr.append("<@renderDateFindField ");

+        sr.append(" className=\"");

+        sr.append(className);

+        sr.append("\" alert=\"");

+        sr.append(alert);

+        sr.append("\" name=\"");

+        sr.append(name);

+        sr.append("\" localizedInputTitle=\"");

+        sr.append(localizedInputTitle);

+        sr.append("\" value=\"");

+        sr.append(value);

+        sr.append("\" size=\"");

+        sr.append(Integer.toString(size));

+        sr.append("\" maxlength=\"");

+        sr.append(Integer.toString(maxlength));

+        sr.append("\" dateType=\"");

+        sr.append(dateType);

+        sr.append("\" formName=\"");

+        sr.append(formName);

+        sr.append("\" defaultDateTimeString=\"");

+        sr.append(defaultDateTimeString);

+        sr.append("\" imgSrc=\"");

+        sr.append(imgSrc.toString());

+        sr.append("\" localizedIconTitle=\"");

+        sr.append(localizedIconTitle);

+        sr.append("\" titleStyle=\"");

+        sr.append(titleStyle);

+        sr.append("\" defaultOptionFrom=\"");

+        sr.append(defaultOptionFrom);

+        sr.append("\" defaultOptionThru=\"");

+        sr.append(defaultOptionThru);

+        sr.append("\" opEquals=\"");

+        sr.append(opEquals);

+        sr.append("\" opSameDay=\"");

+        sr.append(opSameDay);

+        sr.append("\" opGreaterThanFromDayStart=\"");

+        sr.append(opGreaterThanFromDayStart);

+        sr.append("\" opGreaterThan=\"");

+        sr.append(opGreaterThan);

+        sr.append("\" opGreaterThan=\"");

+        sr.append(opGreaterThan);

+        sr.append("\" opLessThan=\"");

+        sr.append(opLessThan);

+        sr.append("\" opUpToDay=\"");

+        sr.append(opUpToDay);

+        sr.append("\" opUpThruDay=\"");

+        sr.append(opUpThruDay);

+        sr.append("\" opIsEmpty=\"");

+        sr.append(opIsEmpty);

+        sr.append("\" />");

+        executeMacro(writer, sr.toString());

+        this.appendTooltip(writer, context, modelFormField);

+    }

+

+    public void renderLookupField(Appendable writer, Map<String, Object> context, LookupField lookupField) throws IOException {

+        ModelFormField modelFormField = lookupField.getModelFormField();

+        String lookupFieldFormName = lookupField.getFormName(context);

+        String className = "";

+        String alert = "false";

+        if (UtilValidate.isNotEmpty(modelFormField.getWidgetStyle())) {

+            className = modelFormField.getWidgetStyle();

+            if (modelFormField.shouldBeRed(context)) {

+                alert = "true";

+            }

+        }

+        //check for required field style on single forms

+        if ("single".equals(modelFormField.getModelForm().getType()) && modelFormField.getRequiredField()) {

+            String requiredStyle = modelFormField.getRequiredFieldStyle();

+            if (UtilValidate.isEmpty(requiredStyle))

+                requiredStyle = "required";

+            if (UtilValidate.isEmpty(className))

+                className = requiredStyle;

+            else

+                className = requiredStyle + " " + className;

+        }

+        String name = modelFormField.getParameterName(context);

+        String value = modelFormField.getEntry(context, lookupField.getDefaultValue(context));

+        if (value == null) {

+            value = "";

+        }

+        String size = Integer.toString(lookupField.getSize());

+        Integer maxlength = lookupField.getMaxlength();

+        String id = modelFormField.getCurrentContainerId(context);

+        List<ModelForm.UpdateArea> updateAreas = modelFormField.getOnChangeUpdateAreas();

+        //add default ajax auto completer to all lookup fields

+        if (UtilValidate.isEmpty(updateAreas) && UtilValidate.isNotEmpty(lookupFieldFormName)) {

+            String autoCompleterTarget = null;

+            if (lookupFieldFormName.indexOf('?') == -1) {

+                autoCompleterTarget = lookupFieldFormName + "?";

+            } else {

+                autoCompleterTarget = lookupFieldFormName + "&amp;amp;";

+            }

+            autoCompleterTarget = autoCompleterTarget + "ajaxLookup=Y";

+            updateAreas = new LinkedList<ModelForm.UpdateArea>();

+            updateAreas.add(new ModelForm.UpdateArea("change", id, autoCompleterTarget));

+        }

+        boolean ajaxEnabled = UtilValidate.isNotEmpty(updateAreas) && this.javaScriptEnabled;

+        String autocomplete = "";

+        if (!lookupField.getClientAutocompleteField() || !ajaxEnabled) {

+            autocomplete = "off";

+        }

+        String event = modelFormField.getEvent();

+        String action = modelFormField.getAction(context);

+        boolean readonly = lookupField.getReadonly();

+        // add lookup pop-up button

+        String descriptionFieldName = lookupField.getDescriptionFieldName();

+        ModelForm modelForm = modelFormField.getModelForm();

+        String formName = FormRenderer.getCurrentFormName(modelForm, context);

+        StringBuilder targetParameterIter = new StringBuilder();

+        StringBuilder imgSrc = new StringBuilder();

+        // FIXME: refactor using the StringUtils methods

+        List<String> targetParameterList = lookupField.getTargetParameterList();

+        targetParameterIter.append("[");

+        for (String targetParameter : targetParameterList) {

+            if (targetParameterIter.length() > 1) {

+                targetParameterIter.append(",");

+            }

+            targetParameterIter.append("'");

+            targetParameterIter.append(targetParameter);

+            targetParameterIter.append("'");

+        }

+        targetParameterIter.append("]");

+        this.appendContentUrl(imgSrc, "/images/fieldlookup.gif");

+        String ajaxUrl = "";

+        if (ajaxEnabled) {

+            ajaxUrl = createAjaxParamsFromUpdateAreas(updateAreas, "", context);

+        }

+        String lookupPresentation = lookupField.getLookupPresentation();

+        if (UtilValidate.isEmpty(lookupPresentation)) {

+            lookupPresentation = "";

+        }

+        String lookupHeight = lookupField.getLookupHeight();

+        if (UtilValidate.isEmpty(lookupHeight)) {

+            lookupHeight = "";

+        }

+        String lookupWidth = lookupField.getLookupWidth();

+        if (UtilValidate.isEmpty(lookupWidth)) {

+            lookupWidth = "";

+        }

+        String lookupPosition = lookupField.getLookupPosition();

+        if (UtilValidate.isEmpty(lookupPosition)) {

+            lookupPosition = "";

+        }

+        String fadeBackground = lookupField.getFadeBackground();

+        if (UtilValidate.isEmpty(fadeBackground)) {

+            fadeBackground = "false";

+        }

+        Boolean isInitiallyCollapsed = lookupField.getInitiallyCollapsed();

+        String clearText = "";

+        Map<String, Object> uiLabelMap = UtilGenerics.checkMap(context.get("uiLabelMap"));

+        if (uiLabelMap != null) {

+            clearText = (String) uiLabelMap.get("CommonClear");

+        } else {

+            Debug.logWarning("Could not find uiLabelMap in context", module);

+        }

+        Boolean showDescription = lookupField.getShowDescription();

+        if (showDescription == null) {

+            showDescription = "Y".equals(UtilProperties.getPropertyValue("widget", "widget.lookup.showDescription", "Y"));

+        }

+        // lastViewName, used by lookup to remember the real last view name

+        String lastViewName = request.getParameter("_LAST_VIEW_NAME_"); // Try to get it from parameters firstly

+        if (UtilValidate.isEmpty(lastViewName)) { // get from session

+            lastViewName = (String) request.getSession().getAttribute("_LAST_VIEW_NAME_");

+        }

+        if (UtilValidate.isEmpty(lastViewName)) {

+            lastViewName = "";

+        }

+        StringWriter sr = new StringWriter();

+        sr.append("<@renderLookupField ");

+        sr.append(" className=\"");

+        sr.append(className);

+        sr.append("\" alert=\"");

+        sr.append(alert);

+        sr.append("\" name=\"");

+        sr.append(name);

+        sr.append("\" value=\"");

+        sr.append(value);

+        sr.append("\" size=\"");

+        sr.append(size);

+        sr.append("\" maxlength=\"");

+        sr.append((maxlength != null ? Integer.toString(maxlength) : ""));

+        sr.append("\" id=\"");

+        sr.append(id);

+        sr.append("\" event=\"");

+        if (event != null) {

+            sr.append(event);

+        }

+        sr.append("\" action=\"");

+        if (action != null) {

+            sr.append(action);

+        }

+        sr.append("\" readonly=");

+        sr.append(Boolean.toString(readonly));

+        sr.append(" autocomplete=\"");

+        sr.append(autocomplete);

+        sr.append("\" descriptionFieldName=\"");

+        sr.append(descriptionFieldName);

+        sr.append("\" formName=\"");

+        sr.append(formName);

+        sr.append("\" fieldFormName=\"");

+        sr.append(lookupFieldFormName);

+        sr.append("\" targetParameterIter=");

+        sr.append(targetParameterIter.toString());

+        sr.append(" imgSrc=\"");

+        sr.append(imgSrc.toString());

+        sr.append("\" ajaxUrl=\"");

+        sr.append(ajaxUrl);

+        sr.append("\" ajaxEnabled=");

+        sr.append(Boolean.toString(ajaxEnabled));

+        sr.append(" presentation=\"");

+        sr.append(lookupPresentation);

+        sr.append("\" height=\"");

+        sr.append(lookupHeight);

+        sr.append("\" width=\"");

+        sr.append(lookupWidth);

+        sr.append("\" position=\"");

+        sr.append(lookupPosition);

+        sr.append("\" fadeBackground=\"");

+        sr.append(fadeBackground);

+        sr.append("\" clearText=\"");

+        sr.append(clearText);

+        sr.append("\" showDescription=\"");

+        sr.append(Boolean.toString(showDescription));

+        sr.append("\" initiallyCollapsed=\"");

+        sr.append(Boolean.toString(isInitiallyCollapsed));

+        sr.append("\" lastViewName=\"");

+        sr.append(lastViewName);

+        sr.append("\" />");

+        executeMacro(writer, sr.toString());

+        this.addAsterisks(writer, context, modelFormField);

+        this.makeHyperlinkString(writer, lookupField.getSubHyperlink(), context);

+        this.appendTooltip(writer, context, modelFormField);

+    }

+

+    protected String appendExternalLoginKey(String target) {

+        String result = target;

+        String sessionId = ";jsessionid=" + request.getSession().getId();

+        int questionIndex = target.indexOf("?");

+        if (questionIndex == -1) {

+            result += sessionId;

+        } else {

+            result = result.replace("?", sessionId + "?");

+        }

+        return result;

+    }

+

+    public void renderNextPrev(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {

+        boolean ajaxEnabled = false;

+        List<ModelForm.UpdateArea> updateAreas = modelForm.getOnPaginateUpdateAreas();

+        String targetService = modelForm.getPaginateTarget(context);

+        if (this.javaScriptEnabled) {

+            if (UtilValidate.isNotEmpty(updateAreas)) {

+                ajaxEnabled = true;

+            }

+        }

+        if (targetService == null) {

+            targetService = "${targetService}";

+        }

+        if (UtilValidate.isEmpty(targetService) && updateAreas == null) {

+            Debug.logWarning("Cannot paginate because TargetService is empty for the form: " + modelForm.getName(), module);

+            return;

+        }

+        // get the parameterized pagination index and size fields

+        int paginatorNumber = WidgetWorker.getPaginatorNumber(context);

+        String viewIndexParam = modelForm.getMultiPaginateIndexField(context);

+        String viewSizeParam = modelForm.getMultiPaginateSizeField(context);

+        int viewIndex = Paginator.getViewIndex(modelForm, context);

+        int viewSize = Paginator.getViewSize(modelForm, context);

+        int listSize = Paginator.getListSize(context);

+        int lowIndex = Paginator.getLowIndex(context);

+        int highIndex = Paginator.getHighIndex(context);

+        int actualPageSize = Paginator.getActualPageSize(context);

+        // needed for the "Page" and "rows" labels

+        Map<String, String> uiLabelMap = UtilGenerics.checkMap(context.get("uiLabelMap"));

+        String pageLabel = "";

+        String commonDisplaying = "";

+        if (uiLabelMap == null) {

+            Debug.logWarning("Could not find uiLabelMap in context", module);

+        } else {

+            pageLabel = uiLabelMap.get("CommonPage");

+            Map<String, Integer> messageMap = UtilMisc.toMap("lowCount", Integer.valueOf(lowIndex + 1), "highCount", Integer.valueOf(lowIndex + actualPageSize), "total", Integer.valueOf(listSize));

+            commonDisplaying = UtilProperties.getMessage("CommonUiLabels", "CommonDisplaying", messageMap, (Locale) context.get("locale"));

+        }

+        // for legacy support, the viewSizeParam is VIEW_SIZE and viewIndexParam is VIEW_INDEX when the fields are "viewSize" and "viewIndex"

+        if (viewIndexParam.equals("viewIndex" + "_" + paginatorNumber))

+            viewIndexParam = "VIEW_INDEX" + "_" + paginatorNumber;

+        if (viewSizeParam.equals("viewSize" + "_" + paginatorNumber))

+            viewSizeParam = "VIEW_SIZE" + "_" + paginatorNumber;

+        String str = (String) context.get("_QBESTRING_");

+        // strip legacy viewIndex/viewSize params from the query string

+        String queryString = UtilHttp.stripViewParamsFromQueryString(str, "" + paginatorNumber);

+        // strip parameterized index/size params from the query string

+        HashSet<String> paramNames = new HashSet<String>();

+        paramNames.add(viewIndexParam);

+        paramNames.add(viewSizeParam);

+        queryString = UtilHttp.stripNamedParamsFromQueryString(queryString, paramNames);

+        String anchor = "";

+        String paginateAnchor = modelForm.getPaginateTargetAnchor();

+        if (UtilValidate.isNotEmpty(paginateAnchor))

+            anchor = "#" + paginateAnchor;

+        // Create separate url path String and request parameters String,

+        // add viewIndex/viewSize parameters to request parameter String

+        String urlPath = UtilHttp.removeQueryStringFromTarget(targetService);

+        String prepLinkText = UtilHttp.getQueryStringFromTarget(targetService);

+        String prepLinkSizeText;

+        if (UtilValidate.isNotEmpty(queryString)) {

+            queryString = UtilHttp.encodeAmpersands(queryString);

+        }

+        if (prepLinkText == null) {

+            prepLinkText = "";

+        }

+        if (prepLinkText.indexOf("?") < 0) {

+            prepLinkText += "?";

+        } else if (!prepLinkText.endsWith("?")) {

+            prepLinkText += "&amp;";

+        }

+        if (!UtilValidate.isEmpty(queryString) && !queryString.equals("null")) {

+            prepLinkText += queryString + "&amp;";

+        }

+        prepLinkSizeText = prepLinkText + viewSizeParam + "='+this.value+'" + "&amp;" + viewIndexParam + "=0";

+        prepLinkText += viewSizeParam + "=" + viewSize + "&amp;" + viewIndexParam + "=";

+        if (ajaxEnabled) {

+            // Prepare params for prototype.js

+            prepLinkText = prepLinkText.replace("?", "");

+            prepLinkText = prepLinkText.replace("&amp;", "&");

+        }

+        String linkText;

+        String paginateStyle = modelForm.getPaginateStyle();

+        String paginateFirstStyle = modelForm.getPaginateFirstStyle();

+        String paginateFirstLabel = modelForm.getPaginateFirstLabel(context);

+        String firstUrl = "";

+        String ajaxFirstUrl = "";

+        String paginatePreviousStyle = modelForm.getPaginatePreviousStyle();

+        String paginatePreviousLabel = modelForm.getPaginatePreviousLabel(context);

+        String previousUrl = "";

+        String ajaxPreviousUrl = "";

+        String selectUrl = "";

+        String ajaxSelectUrl = "";

+        String paginateViewSizeLabel = modelForm.getPaginateViewSizeLabel(context);

+        String selectSizeUrl = "";

+        String ajaxSelectSizeUrl = "";

+        String paginateNextStyle = modelForm.getPaginateNextStyle();

+        String paginateNextLabel = modelForm.getPaginateNextLabel(context);

+        String nextUrl = "";

+        String ajaxNextUrl = "";

+        String paginateLastStyle = modelForm.getPaginateLastStyle();

+        String paginateLastLabel = modelForm.getPaginateLastLabel(context);

+        String lastUrl = "";

+        String ajaxLastUrl = "";

+        if (viewIndex > 0) {

+            if (ajaxEnabled) {

+                ajaxFirstUrl = createAjaxParamsFromUpdateAreas(updateAreas, prepLinkText + 0 + anchor, context);

+            } else {

+                linkText = prepLinkText + 0 + anchor;

+                firstUrl = rh.makeLink(this.request, this.response, urlPath + linkText);

+            }

+        }

+        if (viewIndex > 0) {

+            if (ajaxEnabled) {

+                ajaxPreviousUrl = createAjaxParamsFromUpdateAreas(updateAreas, prepLinkText + (viewIndex - 1) + anchor, context);

+            } else {

+                linkText = prepLinkText + (viewIndex - 1) + anchor;

+                previousUrl = rh.makeLink(this.request, this.response, urlPath + linkText);

+            }

+        }

+        // Page select dropdown

+        if (listSize > 0 && this.javaScriptEnabled) {

+            if (ajaxEnabled) {

+                ajaxSelectUrl = createAjaxParamsFromUpdateAreas(updateAreas, prepLinkText + "' + this.value + '", context);

+            } else {

+                linkText = prepLinkText;

+                if (linkText.startsWith("/")) {

+                    linkText = linkText.substring(1);

+                }

+                selectUrl = rh.makeLink(this.request, this.response, urlPath + linkText);

+            }

+        }

+        // Next button

+        if (highIndex < listSize) {

+            if (ajaxEnabled) {

+                ajaxNextUrl = createAjaxParamsFromUpdateAreas(updateAreas, prepLinkText + (viewIndex + 1) + anchor, context);

+            } else {

+                linkText = prepLinkText + (viewIndex + 1) + anchor;

+                nextUrl = rh.makeLink(this.request, this.response, urlPath + linkText);

+            }

+        }

+        // Last button

+        if (highIndex < listSize) {

+            int lastIndex = UtilMisc.getViewLastIndex(listSize, viewSize);

+            if (ajaxEnabled) {

+                ajaxLastUrl = createAjaxParamsFromUpdateAreas(updateAreas, prepLinkText + lastIndex + anchor, context);

+            } else {

+                linkText = prepLinkText + lastIndex + anchor;

+                lastUrl = rh.makeLink(this.request, this.response, urlPath + linkText);

+            }

+        }

+        // Page size select dropdown

+        if (listSize > 0 && this.javaScriptEnabled) {

+            if (ajaxEnabled) {

+                ajaxSelectSizeUrl = createAjaxParamsFromUpdateAreas(updateAreas, prepLinkSizeText + anchor, context);

+            } else {

+                linkText = prepLinkSizeText;

+                if (linkText.startsWith("/")) {

+                    linkText = linkText.substring(1);

+                }

+                selectSizeUrl = rh.makeLink(this.request, this.response, urlPath + linkText);

+            }

+        }

+        StringWriter sr = new StringWriter();

+        sr.append("<@renderNextPrev ");

+        sr.append(" paginateStyle=\"");

+        sr.append(paginateStyle);

+        sr.append("\" paginateFirstStyle=\"");

+        sr.append(paginateFirstStyle);

+        sr.append("\" viewIndex=");

+        sr.append(Integer.toString(viewIndex));

+        sr.append(" highIndex=");

+        sr.append(Integer.toString(highIndex));

+        sr.append(" listSize=");

+        sr.append(Integer.toString(listSize));

+        sr.append(" viewSize=");

+        sr.append(Integer.toString(viewSize));

+        sr.append(" ajaxEnabled=");

+        sr.append(Boolean.toString(ajaxEnabled));

+        sr.append(" javaScriptEnabled=");

+        sr.append(Boolean.toString(javaScriptEnabled));

+        sr.append(" ajaxFirstUrl=\"");

+        sr.append(ajaxFirstUrl);

+        sr.append("\" ajaxFirstUrl=\"");

+        sr.append(ajaxFirstUrl);

+        sr.append("\" ajaxFirstUrl=\"");

+        sr.append(ajaxFirstUrl);

+        sr.append("\" firstUrl=\"");

+        sr.append(firstUrl);

+        sr.append("\" paginateFirstLabel=\"");

+        sr.append(paginateFirstLabel);

+        sr.append("\" paginatePreviousStyle=\"");

+        sr.append(paginatePreviousStyle);

+        sr.append("\" ajaxPreviousUrl=\"");

+        sr.append(ajaxPreviousUrl);

+        sr.append("\" previousUrl=\"");

+        sr.append(previousUrl);

+        sr.append("\" paginatePreviousLabel=\"");

+        sr.append(paginatePreviousLabel);

+        sr.append("\" pageLabel=\"");

+        sr.append(pageLabel);

+        sr.append("\" ajaxSelectUrl=\"");

+        sr.append(ajaxSelectUrl);

+        sr.append("\" selectUrl=\"");

+        sr.append(selectUrl);

+        sr.append("\" ajaxSelectSizeUrl=\"");

+        sr.append(ajaxSelectSizeUrl);

+        sr.append("\" selectSizeUrl=\"");

+        sr.append(selectSizeUrl);

+        sr.append("\" commonDisplaying=\"");

+        sr.append(commonDisplaying);

+        sr.append("\" paginateNextStyle=\"");

+        sr.append(paginateNextStyle);

+        sr.append("\" ajaxNextUrl=\"");

+        sr.append(ajaxNextUrl);

+        sr.append("\" nextUrl=\"");

+        sr.append(nextUrl);

+        sr.append("\" paginateNextLabel=\"");

+        sr.append(paginateNextLabel);

+        sr.append("\" paginateLastStyle=\"");

+        sr.append(paginateLastStyle);

+        sr.append("\" ajaxLastUrl=\"");

+        sr.append(ajaxLastUrl);

+        sr.append("\" lastUrl=\"");

+        sr.append(lastUrl);

+        sr.append("\" paginateLastLabel=\"");

+        sr.append(paginateLastLabel);

+        sr.append("\" paginateViewSizeLabel=\"");

+        sr.append(paginateViewSizeLabel);

+        sr.append("\" />");

+        executeMacro(writer, sr.toString());

+    }

+

+    public void renderFileField(Appendable writer, Map<String, Object> context, FileField textField) throws IOException {

+        ModelFormField modelFormField = textField.getModelFormField();

+        String className = "";

+        String alert = "false";

+        String name = modelFormField.getParameterName(context);

+        String value = modelFormField.getEntry(context, textField.getDefaultValue(context));

+        String size = Integer.toString(textField.getSize());

+        String maxlength = "";

+        String autocomplete = "";

+        if (UtilValidate.isNotEmpty(modelFormField.getWidgetStyle())) {

+            className = modelFormField.getWidgetStyle();

+            if (modelFormField.shouldBeRed(context)) {

+                alert = "true";

+            }

+        }

+        if (UtilValidate.isEmpty(value)) {

+            value = "";

+        }

+        if (textField.getMaxlength() != null) {

+            maxlength = textField.getMaxlength().toString();

+        }

+        if (!textField.getClientAutocompleteField()) {

+            autocomplete = "off";

+        }

+        StringWriter sr = new StringWriter();

+        sr.append("<@renderFileField ");

+        sr.append(" className=\"");

+        sr.append(className);

+        sr.append("\" alert=\"");

+        sr.append(alert);

+        sr.append("\" name=\"");

+        sr.append(name);

+        sr.append("\" value=\"");

+        sr.append(value);

+        sr.append("\" size=\"");

+        sr.append(size);

+        sr.append("\" maxlength=\"");

+        sr.append(maxlength);

+        sr.append("\" autocomplete=\"");

+        sr.append(autocomplete);

+        sr.append("\" />");

+        executeMacro(writer, sr.toString());

+        this.makeHyperlinkString(writer, textField.getSubHyperlink(), context);

+        this.appendTooltip(writer, context, modelFormField);

+    }

+

+    public void renderPasswordField(Appendable writer, Map<String, Object> context, PasswordField passwordField) throws IOException {

+        ModelFormField modelFormField = passwordField.getModelFormField();

+        String className = "";

+        String alert = "false";

+        String name = modelFormField.getParameterName(context);

+        String size = Integer.toString(passwordField.getSize());

+        String maxlength = "";

+        String id = modelFormField.getCurrentContainerId(context);

+        String autocomplete = "";

+        if (UtilValidate.isNotEmpty(modelFormField.getWidgetStyle())) {

+            className = modelFormField.getWidgetStyle();

+            if (modelFormField.shouldBeRed(context)) {

+                alert = "true";

+            }

+        }

+        String value = modelFormField.getEntry(context, passwordField.getDefaultValue(context));

+        if (value == null) {

+            value = "";

+        }

+        if (passwordField.getMaxlength() != null) {

+            maxlength = passwordField.getMaxlength().toString();

+        }

+        if (id == null) {

+            id = "";

+        }

+        if (!passwordField.getClientAutocompleteField()) {

+            autocomplete = "off";

+        }

+        StringWriter sr = new StringWriter();

+        sr.append("<@renderPasswordField ");

+        sr.append(" className=\"");

+        sr.append(className);

+        sr.append("\" alert=\"");

+        sr.append(alert);

+        sr.append("\" name=\"");

+        sr.append(name);

+        sr.append("\" value=\"");

+        sr.append(value);

+        sr.append("\" size=\"");

+        sr.append(size);

+        sr.append("\" maxlength=\"");

+        sr.append(maxlength);

+        sr.append("\" id=\"");

+        sr.append(id);

+        sr.append("\" autocomplete=\"");

+        sr.append(autocomplete);

+        sr.append("\" />");

+        executeMacro(writer, sr.toString());

+        this.addAsterisks(writer, context, modelFormField);

+        this.makeHyperlinkString(writer, passwordField.getSubHyperlink(), context);

+        this.appendTooltip(writer, context, modelFormField);

+    }

+

+    public void renderImageField(Appendable writer, Map<String, Object> context, ImageField imageField) throws IOException {

+        ModelFormField modelFormField = imageField.getModelFormField();

+        String value = modelFormField.getEntry(context, imageField.getValue(context));

+        String description = imageField.getDescription(context);

+        String alternate = imageField.getAlternate(context);

+        String style = imageField.getStyle(context);

+        if (UtilValidate.isEmpty(description)) {

+            description = imageField.getModelFormField().getTitle(context);

+        }

+        if (UtilValidate.isEmpty(alternate)) {

+            alternate = description;

+        }

+        if (UtilValidate.isNotEmpty(value)) {

+            if (!value.startsWith("http")) {

+                StringBuilder buffer = new StringBuilder();

+                ContentUrlTag.appendContentPrefix(request, buffer);

+                buffer.append(value);

+                value = buffer.toString();

+            }

+        } else if (value == null) {

+            value = "";

+        }

+        String event = modelFormField.getEvent();

+        String action = modelFormField.getAction(context);

+        StringWriter sr = new StringWriter();

+        sr.append("<@renderImageField ");

+        sr.append(" value=\"");

+        sr.append(value);

+        sr.append("\" description=\"");

+        sr.append(encode(description, modelFormField, context));

+        sr.append("\" alternate=\"");

+        sr.append(encode(alternate, modelFormField, context));

+        sr.append("\" style=\"");

+        sr.append(style);

+        sr.append("\" event=\"");

+        sr.append(event == null ? "" : event);

+        sr.append("\" action=\"");

+        sr.append(action == null ? "" : action);

+        sr.append("\" />");

+        executeMacro(writer, sr.toString());

+        this.makeHyperlinkString(writer, imageField.getSubHyperlink(), context);

+        this.appendTooltip(writer, context, modelFormField);

+    }

+

+    public void renderFieldGroupOpen(Appendable writer, Map<String, Object> context, ModelForm.FieldGroup fieldGroup) throws IOException {

+        String style = fieldGroup.getStyle();

+        String id = fieldGroup.getId();

+        FlexibleStringExpander titleNotExpanded = FlexibleStringExpander.getInstance(fieldGroup.getTitle());

+        String title = titleNotExpanded.expandString(context);

+        Boolean collapsed = fieldGroup.initiallyCollapsed();

+        String collapsibleAreaId = fieldGroup.getId() + "_body";

+        Boolean collapsible = fieldGroup.collapsible();

+        String expandToolTip = "";

+        String collapseToolTip = "";

+        if (UtilValidate.isNotEmpty(style) || UtilValidate.isNotEmpty(id) || UtilValidate.isNotEmpty(title)) {

+            if (fieldGroup.collapsible()) {

+                Map<String, Object> uiLabelMap = UtilGenerics.checkMap(context.get("uiLabelMap"));

+                //Map<String, Object> paramMap = UtilGenerics.checkMap(context.get("requestParameters"));

+                if (uiLabelMap != null) {

+                    expandToolTip = (String) uiLabelMap.get("CommonExpand");

+                    collapseToolTip = (String) uiLabelMap.get("CommonCollapse");

+                }

+            }

+        }

+        StringWriter sr = new StringWriter();

+        sr.append("<@renderFieldGroupOpen ");

+        sr.append(" style=\"");

+        if (style != null) {

+            sr.append(style);

+        }

+        sr.append("\" id=\"");

+        sr.append(id);

+        sr.append("\" title=\"");

+        sr.append(title);

+        sr.append("\" collapsed=");

+        sr.append(Boolean.toString(collapsed));

+        sr.append(" collapsibleAreaId=\"");

+        sr.append(collapsibleAreaId);

+        sr.append("\" collapsible=");

+        sr.append(Boolean.toString(collapsible));

+        sr.append(" expandToolTip=\"");

+        sr.append(expandToolTip);

+        sr.append("\" collapseToolTip=\"");

+        sr.append(collapseToolTip);

+        sr.append("\" />");

+        executeMacro(writer, sr.toString());

+    }

+

+    public void renderFieldGroupClose(Appendable writer, Map<String, Object> context, ModelForm.FieldGroup fieldGroup) throws IOException {

+        String style = fieldGroup.getStyle();

+        String id = fieldGroup.getId();

+        FlexibleStringExpander titleNotExpanded = FlexibleStringExpander.getInstance(fieldGroup.getTitle());

+        String title = titleNotExpanded.expandString(context);

+        StringWriter sr = new StringWriter();

+        sr.append("<@renderFieldGroupClose ");

+        sr.append(" style=\"");

+        if (style != null) {

+            sr.append(style);

+        }

+        sr.append("\" id=\"");

+        if (id != null) {

+            sr.append(id);

+        }

+        sr.append("\" title=\"");

+        if (title != null) {

+            sr.append(title);

+        }

+        sr.append("\" />");

+        executeMacro(writer, sr.toString());

+    }

+

+    public void renderBanner(Appendable writer, Map<String, Object> context, ModelForm.Banner banner) throws IOException {

+        String style = banner.getStyle(context);

+        String leftStyle = banner.getLeftTextStyle(context);

+        if (UtilValidate.isEmpty(leftStyle))

+            leftStyle = style;

+        String rightStyle = banner.getRightTextStyle(context);

+        if (UtilValidate.isEmpty(rightStyle))

+            rightStyle = style;

+        String leftText = banner.getLeftText(context);

+        if (leftText == null) {

+            leftText = "";

+        }

+        String text = banner.getText(context);

+        if (text == null) {

+            text = "";

+        }

+        String rightText = banner.getRightText(context);

+        if (rightText == null) {

+            rightText = "";

+        }

+        StringWriter sr = new StringWriter();

+        sr.append("<@renderBanner ");

+        sr.append(" style=\"");

+        sr.append(style);

+        sr.append("\" leftStyle=\"");

+        sr.append(leftStyle);

+        sr.append("\" rightStyle=\"");

+        sr.append(rightStyle);

+        sr.append("\" leftText=\"");

+        sr.append(leftText);

+        sr.append("\" text=\"");

+        sr.append(text);

+        sr.append("\" rightText=\"");

+        sr.append(rightText);

+        sr.append("\" />");

+        executeMacro(writer, sr.toString());

+    }

+

+    /**

+     * Renders the beginning boundary comment string.

+     * @param writer The writer to write to

+     * @param widgetType The widget type: "Screen Widget", "Form Widget", etc.

+     * @param modelWidget The widget

+     */

+    public void renderBeginningBoundaryComment(Appendable writer, String widgetType, ModelWidget modelWidget) throws IOException {

+        if (this.widgetCommentsEnabled) {

+            StringWriter sr = new StringWriter();

+            sr.append("<@formatBoundaryComment ");

+            sr.append(" boundaryType=\"");

+            sr.append("Begin");

+            sr.append("\" widgetType=\"");

+            sr.append(widgetType);

+            sr.append("\" widgetName=\"");

+            sr.append(modelWidget.getBoundaryCommentName());

+            sr.append("\" />");

+            executeMacro(writer, sr.toString());

+        }

+    }

+

+    /**

+     * Renders the ending boundary comment string.

+     * @param writer The writer to write to

+     * @param widgetType The widget type: "Screen Widget", "Form Widget", etc.

+     * @param modelWidget The widget

+     */

+    public void renderEndingBoundaryComment(Appendable writer, String widgetType, ModelWidget modelWidget) throws IOException {

+        if (this.widgetCommentsEnabled) {

+            StringWriter sr = new StringWriter();

+            sr.append("<@formatBoundaryComment ");

+            sr.append(" boundaryType=\"");

+            sr.append("End");

+            sr.append("\" widgetType=\"");

+            sr.append(widgetType);

+            sr.append("\" widgetName=\"");

+            sr.append(modelWidget.getBoundaryCommentName());

+            sr.append("\" />");

+            executeMacro(writer, sr.toString());

+        }

+    }

+

+    public void renderSortField(Appendable writer, Map<String, Object> context, ModelFormField modelFormField, String titleText) throws IOException {

+        boolean ajaxEnabled = false;

+        ModelForm modelForm = modelFormField.getModelForm();

+        List<ModelForm.UpdateArea> updateAreas = modelForm.getOnSortColumnUpdateAreas();

+        if (updateAreas == null) {

+            // For backward compatibility.

+            updateAreas = modelForm.getOnPaginateUpdateAreas();

+        }

+        if (this.javaScriptEnabled) {

+            if (UtilValidate.isNotEmpty(updateAreas)) {

+                ajaxEnabled = true;

+            }

+        }

+        String paginateTarget = modelForm.getPaginateTarget(context);

+        if (paginateTarget.isEmpty() && updateAreas == null) {

+            Debug.logWarning("Cannot sort because the paginate target URL is empty for the form: " + modelForm.getName(), module);

+            return;

+        }

+        String oldSortField = modelForm.getSortField(context);

+        String sortFieldStyle = modelFormField.getSortFieldStyle();

+        // if the entry-name is defined use this instead of field name

+        String columnField = modelFormField.getEntryName();

+        if (UtilValidate.isEmpty(columnField)) {

+            columnField = modelFormField.getFieldName();

+        }

+        // switch between asc/desc order

+        String newSortField = columnField;

+        if (UtilValidate.isNotEmpty(oldSortField)) {

+            if (oldSortField.equals(columnField)) {

+                newSortField = "-" + columnField;

+                sortFieldStyle = modelFormField.getSortFieldStyleDesc();

+            } else if (oldSortField.equals("-" + columnField)) {

+                newSortField = columnField;

+                sortFieldStyle = modelFormField.getSortFieldStyleAsc();

+            }

+        }

+        String queryString = UtilHttp.getQueryStringFromTarget(paginateTarget).replace("?", "");

+        Map<String, Object> paramMap = UtilHttp.getQueryStringOnlyParameterMap(queryString);

+        String qbeString = (String) context.get("_QBESTRING_");

+        if (qbeString != null) {

+            qbeString = qbeString.replaceAll("&amp;", "&");

+            paramMap.putAll(UtilHttp.getQueryStringOnlyParameterMap(qbeString));

+        }

+        paramMap.put(modelForm.getSortFieldParameterName(), newSortField);

+        UtilHttp.canonicalizeParameterMap(paramMap);

+        String linkUrl = null;

+        if (ajaxEnabled) {

+            linkUrl = createAjaxParamsFromUpdateAreas(updateAreas, paramMap, null, context);

+        } else {

+            StringBuilder sb = new StringBuilder("?");

+            Iterator<Map.Entry<String, Object>> iter = paramMap.entrySet().iterator();

+            while (iter.hasNext()) {

+                Map.Entry<String, Object> entry = iter.next();

+                sb.append(entry.getKey()).append("=").append(entry.getValue());

+                if (iter.hasNext()) {

+                    sb.append("&amp;");

+                }

+            }

+            String newQueryString = sb.toString();

+            String urlPath = UtilHttp.removeQueryStringFromTarget(paginateTarget);

+            linkUrl = rh.makeLink(this.request, this.response, urlPath.concat(newQueryString));

+        }

+        StringWriter sr = new StringWriter();

+        sr.append("<@renderSortField ");

+        sr.append(" style=\"");

+        sr.append(sortFieldStyle);

+        sr.append("\" title=\"");

+        sr.append(titleText);

+        sr.append("\" linkUrl=\"");

+        sr.append(linkUrl);

+        sr.append("\" ajaxEnabled=");

+        sr.append(Boolean.toString(ajaxEnabled));

+        String tooltip = modelFormField.getSortFieldHelpText(context);

+        if (!tooltip.isEmpty()) {

+            sr.append(" tooltip=\"").append(tooltip).append("\"");

+        }

+        sr.append(" />");

+        executeMacro(writer, sr.toString());

+    }

+

+    /** Create an ajaxXxxx JavaScript CSV string from a list of UpdateArea objects. See

+     * <code>selectall.js</code>.

+     * @param updateAreas

+     * @param extraParams Renderer-supplied additional target parameters

+     * @param context

+     * @return Parameter string or empty string if no UpdateArea objects were found

+     */

+    private String createAjaxParamsFromUpdateAreas(List<ModelForm.UpdateArea> updateAreas, Map<String, Object> extraParams, String anchor, Map<String, ? extends Object> context) {

+        StringBuilder sb = new StringBuilder();

+        Iterator<ModelForm.UpdateArea> updateAreaIter = updateAreas.iterator();

+        while (updateAreaIter.hasNext()) {

+            ModelForm.UpdateArea updateArea = updateAreaIter.next();

+            sb.append(updateArea.getAreaId()).append(",");

+            String ajaxTarget = updateArea.getAreaTarget(context);

+            String urlPath = UtilHttp.removeQueryStringFromTarget(ajaxTarget);

+            sb.append(this.rh.makeLink(this.request, this.response,urlPath)).append(",");

+            String queryString = UtilHttp.getQueryStringFromTarget(ajaxTarget).replace("?", "");

+            Map<String, Object> parameters = UtilHttp.getQueryStringOnlyParameterMap(queryString);

+            Map<String, Object> ctx = UtilGenerics.checkMap(context);

+            Map<String, Object> updateParams = UtilGenerics.checkMap(updateArea.getParameterMap(ctx));

+            parameters.putAll(updateParams);

+            UtilHttp.canonicalizeParameterMap(parameters);

+            parameters.putAll(extraParams);

+            Iterator<Map.Entry<String, Object>> paramIter = parameters.entrySet().iterator();

+            while (paramIter.hasNext()) {

+                Map.Entry<String, Object> entry = paramIter.next();

+                sb.append(entry.getKey()).append("=").append(entry.getValue());

+                if (paramIter.hasNext()) {

+                    sb.append("&");

+                }

+            }

+            if (anchor != null) {

+                sb.append("#").append(anchor);

+            }

+            if (updateAreaIter.hasNext()) {

+                sb.append(",");

+            }

+        }

+        Locale locale = UtilMisc.ensureLocale(context.get("locale"));

+        return FlexibleStringExpander.expandString(sb.toString(), context, locale);

+    }

+

+    /** Create an ajaxXxxx JavaScript CSV string from a list of UpdateArea objects. See

+     * <code>selectall.js</code>.

+     * @param updateAreas

+     * @param extraParams Renderer-supplied additional target parameters

+     * @param context

+     * @return Parameter string or empty string if no UpdateArea objects were found

+     */

+    public String createAjaxParamsFromUpdateAreas(List<ModelForm.UpdateArea> updateAreas, String extraParams, Map<String, ? extends Object> context) {

+        //FIXME copy from HtmlFormRenderer.java

+        if (updateAreas == null) {

+            return "";

+        }

+        String ajaxUrl = "";

+        boolean firstLoop = true;

+        for (ModelForm.UpdateArea updateArea : updateAreas) {

+            if (firstLoop) {

+                firstLoop = false;

+            } else {

+                ajaxUrl += ",";

+            }

+            Map<String, Object> ctx = UtilGenerics.checkMap(context);

+            Map<String, String> parameters = updateArea.getParameterMap(ctx);

+            String targetUrl = updateArea.getAreaTarget(context);

+            String ajaxParams = getAjaxParamsFromTarget(targetUrl);

+            //add first parameters from updateArea parameters

+            if (UtilValidate.isNotEmpty(parameters)) {

+                if (UtilValidate.isEmpty(ajaxParams)) {

+                    ajaxParams = "";

+                }

+                for (Map.Entry<String, String> entry : parameters.entrySet()) {

+                    String key = entry.getKey();

+                    String value = entry.getValue();

+                    //test if ajax parameters are not already into extraParams, if so do not add it

+                    if (UtilValidate.isNotEmpty(extraParams) && extraParams.contains(value)) {

+                        continue;

+                    }

+                    if (ajaxParams.length() > 0 && ajaxParams.indexOf(key) < 0) {

+                        ajaxParams += "&";

+                    }

+                    if (ajaxParams.indexOf(key) < 0) {

+                        ajaxParams += key + "=" + value;

+                    }

+                }

+            }

+            //then add parameters from request. Those parameters could end with an anchor so we must set ajax parameters first

+            if (UtilValidate.isNotEmpty(extraParams)) {

+                if (ajaxParams.length() > 0 && !extraParams.startsWith("&")) {

+                    ajaxParams += "&";

+                }

+                ajaxParams += extraParams;

+            }

+            ajaxUrl += updateArea.getAreaId() + ",";

+            ajaxUrl += this.rh.makeLink(this.request, this.response, UtilHttp.removeQueryStringFromTarget(targetUrl));

+            ajaxUrl += "," + ajaxParams;

+        }

+        Locale locale = UtilMisc.ensureLocale(context.get("locale"));

+        return FlexibleStringExpander.expandString(ajaxUrl, context, locale);

+    }

+

+    /** Extracts parameters from a target URL string, prepares them for an Ajax

+     * JavaScript call. This method is currently set to return a parameter string

+     * suitable for the Prototype.js library.

+     * @param target Target URL string

+     * @return Parameter string

+     */

+    public static String getAjaxParamsFromTarget(String target) {

+        String targetParams = UtilHttp.getQueryStringFromTarget(target);

+        targetParams = targetParams.replace("?", "");

+        targetParams = targetParams.replace("&amp;", "&");

+        return targetParams;

+    }

+

+    public void appendTooltip(Appendable writer, Map<String, Object> context, ModelFormField modelFormField) throws IOException {

+        // render the tooltip, in other methods too

+        String tooltip = modelFormField.getTooltip(context);

+        StringWriter sr = new StringWriter();

+        sr.append("<@renderTooltip ");

+        sr.append("tooltip=\"");

+        sr.append(FreeMarkerWorker.encodeDoubleQuotes(tooltip));

+        sr.append("\" tooltipStyle=\"");

+        sr.append(modelFormField.getTooltipStyle());

+        sr.append("\" />");

+        executeMacro(writer, sr.toString());

+    }

+

+    public void makeHyperlinkString(Appendable writer, ModelFormField.SubHyperlink subHyperlink, Map<String, Object> context) throws IOException {

+        if (subHyperlink == null) {

+            return;

+        }

+        if (subHyperlink.shouldUse(context)) {

+            writer.append(' ');

+            makeHyperlinkByType(writer, subHyperlink.getLinkType(), subHyperlink.getStyle(context), subHyperlink.getUrlMode(),

+                    subHyperlink.getTarget(context), subHyperlink.getParameterMap(context), subHyperlink.getDescription(context),

+                    subHyperlink.getTargetWindow(context), null, subHyperlink.getModelFormField(), this.request, this.response,

+                    context);

+        }

+    }

+

+    public void addAsterisks(Appendable writer, Map<String, Object> context, ModelFormField modelFormField) throws IOException {

+        String requiredField = "false";

+        String requiredStyle = "";

+        if (modelFormField.getRequiredField()) {

+            requiredField = "true";

+            requiredStyle = modelFormField.getRequiredFieldStyle();

+        }

+        StringWriter sr = new StringWriter();

+        sr.append("<@renderAsterisks ");

+        sr.append("requiredField=\"");

+        sr.append(requiredField);

+        sr.append("\" requiredStyle=\"");

+        sr.append(requiredStyle);

+        sr.append("\" />");

+        executeMacro(writer, sr.toString());

+    }

+

+    public void appendContentUrl(Appendable writer, String location) throws IOException {

+        StringBuilder buffer = new StringBuilder();

+        ContentUrlTag.appendContentPrefix(this.request, buffer);

+        writer.append(buffer.toString());

+        writer.append(location);

+    }

+

+    public void makeHyperlinkByType(Appendable writer, String linkType, String linkStyle, String targetType, String target, Map<String, String> parameterMap, String description, String targetWindow, String confirmation, ModelFormField modelFormField, HttpServletRequest request,

+            HttpServletResponse response, Map<String, Object> context) throws IOException {

+        String realLinkType = WidgetWorker.determineAutoLinkType(linkType, target, targetType, request);

+        String encodedDescription = encode(description, modelFormField, context);

+        // get the parameterized pagination index and size fields

+        int paginatorNumber = WidgetWorker.getPaginatorNumber(context);

+        ModelForm modelForm = modelFormField.getModelForm();

+        String viewIndexField = modelForm.getMultiPaginateIndexField(context);

+        String viewSizeField = modelForm.getMultiPaginateSizeField(context);

+        int viewIndex = Paginator.getViewIndex(modelForm, context);

+        int viewSize = Paginator.getViewSize(modelForm, context);

+        if (viewIndexField.equals("viewIndex" + "_" + paginatorNumber)) {

+            viewIndexField = "VIEW_INDEX" + "_" + paginatorNumber;

+        }

+        if (viewSizeField.equals("viewSize" + "_" + paginatorNumber)) {

+            viewSizeField = "VIEW_SIZE" + "_" + paginatorNumber;

+        }

+        if ("hidden-form".equals(realLinkType)) {

+            parameterMap.put(viewIndexField, Integer.toString(viewIndex));

+            parameterMap.put(viewSizeField, Integer.toString(viewSize));

+            if (modelFormField != null && "multi".equals(modelForm.getType())) {

+                WidgetWorker.makeHiddenFormLinkAnchor(writer, linkStyle, encodedDescription, confirmation, modelFormField, request, response, context);

+                // this is a bit trickier, since we can't do a nested form we'll have to put the link to submit the form in place, but put the actual form def elsewhere, ie after the big form is closed

+                Map<String, Object> wholeFormContext = UtilGenerics.checkMap(context.get("wholeFormContext"));

+                Appendable postMultiFormWriter = wholeFormContext != null ? (Appendable) wholeFormContext.get("postMultiFormWriter") : null;

+                if (postMultiFormWriter == null) {

+                    postMultiFormWriter = new StringWriter();

+                    wholeFormContext.put("postMultiFormWriter", postMultiFormWriter);

+                }

+                WidgetWorker.makeHiddenFormLinkForm(postMultiFormWriter, target, targetType, targetWindow, parameterMap, modelFormField, request, response, context);

+            } else {

+                WidgetWorker.makeHiddenFormLinkForm(writer, target, targetType, targetWindow, parameterMap, modelFormField, request, response, context);

+                WidgetWorker.makeHiddenFormLinkAnchor(writer, linkStyle, encodedDescription, confirmation, modelFormField, request, response, context);

+            }

+        } else {

+            makeHyperlinkString(writer, linkStyle, targetType, target, parameterMap, encodedDescription, confirmation, modelFormField, request, response, context, targetWindow);

+        }

+

+    }

+

+    public void makeHyperlinkString(Appendable writer, String linkStyle, String targetType, String target, Map<String, String> parameterMap, String description, String confirmation, ModelFormField modelFormField, HttpServletRequest request, HttpServletResponse response, Map<String, Object> context,

+            String targetWindow) throws IOException {

+        if (UtilValidate.isNotEmpty(description) || UtilValidate.isNotEmpty(request.getAttribute("image"))) {

+            StringBuilder linkUrl = new StringBuilder();

+            WidgetWorker.buildHyperlinkUrl(linkUrl, target, targetType, parameterMap, null, false, false, true, request, response, context);

+            String event = "";

+            String action = "";

+            String imgSrc = "";

+            String alt = "";

+            String imgTitle = "";

+            String hiddenFormName = WidgetWorker.makeLinkHiddenFormName(context, modelFormField);

+            if (UtilValidate.isNotEmpty(modelFormField.getEvent()) && UtilValidate.isNotEmpty(modelFormField.getAction(context))) {

+                event = modelFormField.getEvent();

+                action = modelFormField.getAction(context);

+            }

+            if (UtilValidate.isNotEmpty(request.getAttribute("image"))) {

+                imgSrc = request.getAttribute("image").toString();

+            }

+            if (UtilValidate.isNotEmpty(request.getAttribute("alternate"))) {

+                alt = request.getAttribute("alternate").toString();

+            }

+            if (UtilValidate.isNotEmpty(request.getAttribute("imageTitle"))) {

+                imgTitle = request.getAttribute("imageTitle").toString();

+            }

+            Integer size = Integer.valueOf("0");

+            if (UtilValidate.isNotEmpty(request.getAttribute("descriptionSize"))) {

+                size = Integer.valueOf(request.getAttribute("descriptionSize").toString());

+            }

+            if (UtilValidate.isNotEmpty(description) && size > 0 && description.length() > size) {

+                imgTitle = description;

+                description = description.substring(0, size - 8) + "..." + description.substring(description.length() - 5);

+            }

+            if (UtilValidate.isEmpty(imgTitle)) {

+                imgTitle = modelFormField.getTitle(context);

+            }

+            StringWriter sr = new StringWriter();

+            sr.append("<@makeHyperlinkString ");

+            sr.append("linkStyle=\"");

+            sr.append(linkStyle == null ? "" : linkStyle);

+            sr.append("\" hiddenFormName=\"");

+            sr.append(hiddenFormName == null ? "" : hiddenFormName);

+            sr.append("\" event=\"");

+            sr.append(event);

+            sr.append("\" action=\"");

+            sr.append(action);

+            sr.append("\" imgSrc=\"");

+            sr.append(imgSrc);

+            sr.append("\" title=\"");

+            sr.append(imgTitle);

+            sr.append("\" alternate=\"");

+            sr.append(alt);

+            sr.append("\" linkUrl=\"");

+            sr.append(linkUrl.toString());

+            sr.append("\" targetWindow=\"");

+            sr.append(targetWindow);

+            sr.append("\" description=\"");

+            sr.append(description);

+            sr.append("\" confirmation =\"");

+            sr.append(confirmation);

+            sr.append("\" />");

+            executeMacro(writer, sr.toString());

+        }

+    }

+

+    public void makeHiddenFormLinkAnchor(Appendable writer, String linkStyle, String description, String confirmation, ModelFormField modelFormField, HttpServletRequest request, HttpServletResponse response, Map<String, Object> context) throws IOException {

+        if (UtilValidate.isNotEmpty(description) || UtilValidate.isNotEmpty(request.getAttribute("image"))) {

+            String hiddenFormName = WidgetWorker.makeLinkHiddenFormName(context, modelFormField);

+            String event = "";

+            String action = "";

+            String imgSrc = "";

+            if (UtilValidate.isNotEmpty(modelFormField.getEvent()) && UtilValidate.isNotEmpty(modelFormField.getAction(context))) {

+                event = modelFormField.getEvent();

+                action = modelFormField.getAction(context);

+            }

+            if (UtilValidate.isNotEmpty(request.getAttribute("image"))) {

+                imgSrc = request.getAttribute("image").toString();

+            }

+            StringWriter sr = new StringWriter();

+            sr.append("<@makeHiddenFormLinkAnchor ");

+            sr.append("linkStyle=\"");

+            sr.append(linkStyle == null ? "" : linkStyle);

+            sr.append("\" hiddenFormName=\"");

+            sr.append(hiddenFormName == null ? "" : hiddenFormName);

+            sr.append("\" event=\"");

+            sr.append(event);

+            sr.append("\" action=\"");

+            sr.append(action);

+            sr.append("\" imgSrc=\"");

+            sr.append(imgSrc);

+            sr.append("\" description=\"");

+            sr.append(description);

+            sr.append("\" confirmation =\"");

+            sr.append(confirmation);

+            sr.append("\" />");

+            executeMacro(writer, sr.toString());

+        }

+    }

+

+    public void makeHiddenFormLinkForm(Appendable writer, String target, String targetType, String targetWindow, List<CommonWidgetModels.Parameter> parameterList, ModelFormField modelFormField, HttpServletRequest request, HttpServletResponse response, Map<String, Object> context) throws IOException {

+        StringBuilder actionUrl = new StringBuilder();

+        WidgetWorker.buildHyperlinkUrl(actionUrl, target, targetType, null, null, false, false, true, request, response, context);

+        String name = WidgetWorker.makeLinkHiddenFormName(context, modelFormField);

+        StringBuilder parameters = new StringBuilder();

+        parameters.append("[");

+        for (CommonWidgetModels.Parameter parameter : parameterList) {

+            if (parameters.length() > 1) {

+                parameters.append(",");

+            }

+            parameters.append("{'name':'");

+            parameters.append(parameter.getName());

+            parameters.append("'");

+            parameters.append(",'value':'");

+            parameters.append(UtilCodec.getEncoder("html").encode(parameter.getValue(context)));

+            parameters.append("'}");

+        }

+        parameters.append("]");

+        StringWriter sr = new StringWriter();

+        sr.append("<@makeHiddenFormLinkForm ");

+        sr.append("actionUrl=\"");

+        sr.append(actionUrl.toString());

+        sr.append("\" name=\"");

+        sr.append(name);

+        sr.append("\" parameters=");

+        sr.append(parameters.toString());

+        sr.append(" targetWindow=\"");

+        sr.append(targetWindow);

+        sr.append("\" />");

+        executeMacro(writer, sr.toString());

+    }

+

+    public void renderContainerFindField(Appendable writer, Map<String, Object> context, ContainerField containerField) throws IOException {

+        String id = containerField.getModelFormField().getIdName();

+        String className = UtilFormatOut.checkNull(containerField.getModelFormField().getWidgetStyle());

+        StringWriter sr = new StringWriter();

+        sr.append("<@renderContainerField ");

+        sr.append("id=\"");

+        sr.append(id);

+        sr.append("\" className=\"");

+        sr.append(className);

+        sr.append("\" />");

+        executeMacro(writer, sr.toString());

+    }

+}

diff --git a/framework/widget/src/org/ofbiz/widget/menu/MacroMenuRenderer.java b/framework/widget/src/org/ofbiz/widget/renderer/macro/MacroMenuRenderer.java
similarity index 97%
rename from framework/widget/src/org/ofbiz/widget/menu/MacroMenuRenderer.java
rename to framework/widget/src/org/ofbiz/widget/renderer/macro/MacroMenuRenderer.java
index fc99336..bcac580 100644
--- a/framework/widget/src/org/ofbiz/widget/menu/MacroMenuRenderer.java
+++ b/framework/widget/src/org/ofbiz/widget/renderer/macro/MacroMenuRenderer.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations

  * under the License.

  *******************************************************************************/

-package org.ofbiz.widget.menu;

+package org.ofbiz.widget.renderer.macro;

 

 import java.io.IOException;

 import java.io.Reader;

@@ -39,10 +39,13 @@
 import org.ofbiz.base.util.template.FreeMarkerWorker;

 import org.ofbiz.webapp.control.RequestHandler;

 import org.ofbiz.webapp.taglib.ContentUrlTag;

-import org.ofbiz.widget.CommonWidgetModels.Image;

-import org.ofbiz.widget.ModelWidget;

 import org.ofbiz.widget.WidgetWorker;

-import org.ofbiz.widget.menu.ModelMenuItem.MenuLink;

+import org.ofbiz.widget.model.CommonWidgetModels.Image;

+import org.ofbiz.widget.model.ModelMenu;

+import org.ofbiz.widget.model.ModelMenuItem;

+import org.ofbiz.widget.model.ModelMenuItem.MenuLink;

+import org.ofbiz.widget.model.ModelWidget;

+import org.ofbiz.widget.renderer.MenuStringRenderer;

 

 import freemarker.core.Environment;

 import freemarker.template.Template;

diff --git a/framework/widget/src/org/ofbiz/widget/screen/MacroScreenRenderer.java b/framework/widget/src/org/ofbiz/widget/renderer/macro/MacroScreenRenderer.java
similarity index 98%
rename from framework/widget/src/org/ofbiz/widget/screen/MacroScreenRenderer.java
rename to framework/widget/src/org/ofbiz/widget/renderer/macro/MacroScreenRenderer.java
index 3bb08d0..66c7f23 100644
--- a/framework/widget/src/org/ofbiz/widget/screen/MacroScreenRenderer.java
+++ b/framework/widget/src/org/ofbiz/widget/renderer/macro/MacroScreenRenderer.java
@@ -1,1045 +1,1048 @@
-/*******************************************************************************
- * 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.screen;
-
-import java.io.IOException;
-import java.io.Reader;
-import java.io.StringReader;
-import java.io.StringWriter;
-import java.math.BigDecimal;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Locale;
-import java.util.Map;
-import java.util.WeakHashMap;
-
-import javax.servlet.ServletContext;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import javax.xml.parsers.ParserConfigurationException;
-
-import org.ofbiz.base.util.Debug;
-import org.ofbiz.base.util.GeneralException;
-import org.ofbiz.base.util.UtilFormatOut;
-import org.ofbiz.base.util.UtilGenerics;
-import org.ofbiz.base.util.UtilHttp;
-import org.ofbiz.base.util.UtilMisc;
-import org.ofbiz.base.util.UtilProperties;
-import org.ofbiz.base.util.UtilValidate;
-import org.ofbiz.base.util.template.FreeMarkerWorker;
-import org.ofbiz.entity.Delegator;
-import org.ofbiz.entity.GenericValue;
-import org.ofbiz.service.LocalDispatcher;
-import org.ofbiz.webapp.control.RequestHandler;
-import org.ofbiz.webapp.taglib.ContentUrlTag;
-import org.ofbiz.widget.ModelWidget;
-import org.ofbiz.widget.WidgetContentWorker;
-import org.ofbiz.widget.WidgetDataResourceWorker;
-import org.ofbiz.widget.WidgetWorker;
-import org.ofbiz.widget.form.FormStringRenderer;
-import org.ofbiz.widget.form.MacroFormRenderer;
-import org.ofbiz.widget.form.ModelForm;
-import org.ofbiz.widget.form.Paginator;
-import org.ofbiz.widget.html.HtmlScreenRenderer.ScreenletMenuRenderer;
-import org.ofbiz.widget.menu.MenuStringRenderer;
-import org.ofbiz.widget.screen.ModelScreenWidget.Column;
-import org.ofbiz.widget.screen.ModelScreenWidget.ColumnContainer;
-import org.xml.sax.SAXException;
-
-import freemarker.core.Environment;
-import freemarker.template.Template;
-import freemarker.template.TemplateException;
-
-public class MacroScreenRenderer implements ScreenStringRenderer {
-
-    public static final String module = MacroScreenRenderer.class.getName();
-    private Template macroLibrary;
-    private WeakHashMap<Appendable, Environment> environments = new WeakHashMap<Appendable, Environment>();
-    private String rendererName;
-    private int elementId = 999;
-    protected boolean widgetCommentsEnabled = false;
-    private static final String formrenderer = UtilProperties.getPropertyValue("widget", "screen.formrenderer");
-    private int screenLetsIdCounter = 1;
-
-    public MacroScreenRenderer(String name, String macroLibraryPath) throws TemplateException, IOException {
-        macroLibrary = FreeMarkerWorker.getTemplate(macroLibraryPath);
-        rendererName = name;
-    }
-
-    @Deprecated
-    public MacroScreenRenderer(String name, String macroLibraryPath, Appendable writer) throws TemplateException, IOException {
-        this(name, macroLibraryPath);
-    }
-
-    private String getNextElementId() {
-        elementId++;
-        return "hsr" + elementId;
-    }
-
-    private void executeMacro(Appendable writer, String macro) throws IOException {
-        try {
-            Environment environment = getEnvironment(writer);
-            Reader templateReader = new StringReader(macro);
-            // FIXME: I am using a Date as an hack to provide a unique name for the template...
-            Template template = new Template((new java.util.Date()).toString(), templateReader, FreeMarkerWorker.getDefaultOfbizConfig());
-            templateReader.close();
-            environment.include(template);
-        } catch (TemplateException e) {
-            Debug.logError(e, "Error rendering screen macro [" + macro + "] thru ftl", module);
-        } catch (IOException e) {
-            Debug.logError(e, "Error rendering screen macro [" + macro + "] thru ftl", module);
-        }
-    }
-
-    private void executeMacro(Appendable writer, String macroName, Map<String, Object> parameters) throws IOException {
-        StringBuilder sb = new StringBuilder("<@");
-        sb.append(macroName);
-        if (parameters != null) {
-            for (Map.Entry<String, Object> parameter : parameters.entrySet()) {
-                sb.append(' ');
-                sb.append(parameter.getKey());
-                sb.append("=");
-                Object value = parameter.getValue();
-                if (value instanceof String) {
-                    sb.append('"');
-                    sb.append(((String) value).replaceAll("\"", "\\\\\""));
-                    sb.append('"');
-                } else {
-                    sb.append(value);
-                }
-            }
-        }
-        sb.append(" />");
-        executeMacro(writer, sb.toString());
-    }
-
-    private Environment getEnvironment(Appendable writer) throws TemplateException, IOException {
-        Environment environment = environments.get(writer);
-        if (environment == null) {
-            Map<String, Object> input = UtilMisc.toMap("key", null);
-            environment = FreeMarkerWorker.renderTemplate(macroLibrary, input, writer);
-            environments.put(writer, environment);
-        }
-        return environment;
-    }
-
-    public String getRendererName() {
-        return rendererName;
-    }
-
-    public void renderScreenBegin(Appendable writer, Map<String, Object> context) throws IOException {
-        executeMacro(writer, "renderScreenBegin", null);
-    }
-
-    public void renderScreenEnd(Appendable writer, Map<String, Object> context) throws IOException {
-        executeMacro(writer, "renderScreenEnd", null);
-    }
-
-    public void renderSectionBegin(Appendable writer, Map<String, Object> context, ModelScreenWidget.Section section) throws IOException {
-        if (section.isMainSection()) {
-            this.widgetCommentsEnabled = ModelWidget.widgetBoundaryCommentsEnabled(context);
-        }
-        if (this.widgetCommentsEnabled) {
-            Map<String, Object> parameters = new HashMap<String, Object>();
-            StringBuilder sb = new StringBuilder("Begin ");
-            sb.append(section.isMainSection() ? "Screen " : "Section Widget ");
-            sb.append(section.getBoundaryCommentName());
-            parameters.put("boundaryComment", sb.toString());
-            executeMacro(writer, "renderSectionBegin", parameters);
-        }
-    }
-    public void renderSectionEnd(Appendable writer, Map<String, Object> context, ModelScreenWidget.Section section) throws IOException {
-        if (this.widgetCommentsEnabled) {
-            Map<String, Object> parameters = new HashMap<String, Object>();
-            StringBuilder sb = new StringBuilder();
-            sb.append("End ");
-            sb.append(section.isMainSection() ? "Screen " : "Section Widget ");
-            sb.append(section.getBoundaryCommentName());
-            parameters.put("boundaryComment", sb.toString());
-            executeMacro(writer, "renderSectionEnd", parameters);
-        }
-    }
-
-    public void renderContainerBegin(Appendable writer, Map<String, Object> context, ModelScreenWidget.Container container) throws IOException {
-        String containerId = container.getId(context);
-        String autoUpdateTarget = container.getAutoUpdateTargetExdr(context);
-        HttpServletRequest request = (HttpServletRequest) context.get("request");
-        String autoUpdateLink = "";
-        if (UtilValidate.isNotEmpty(autoUpdateTarget) && UtilHttp.isJavaScriptEnabled(request)) {
-            if (UtilValidate.isEmpty(containerId)) {
-                containerId = getNextElementId();
-            }
-            HttpServletResponse response = (HttpServletResponse) context.get("response");
-            ServletContext ctx = (ServletContext) request.getAttribute("servletContext");
-            RequestHandler rh = (RequestHandler) ctx.getAttribute("_REQUEST_HANDLER_");
-            autoUpdateLink = rh.makeLink(request, response, autoUpdateTarget);
-        }
-        Map<String, Object> parameters = new HashMap<String, Object>();
-        parameters.put("id", containerId);
-        parameters.put("style", container.getStyle(context));
-        parameters.put("autoUpdateLink", autoUpdateLink);
-        parameters.put("autoUpdateInterval", container.getAutoUpdateInterval(context));
-        executeMacro(writer, "renderContainerBegin", parameters);
-    }
-
-    public void renderContainerEnd(Appendable writer, Map<String, Object> context, ModelScreenWidget.Container container) throws IOException {
-        executeMacro(writer, "renderContainerEnd", null);
-    }
-
-    public void renderLabel(Appendable writer, Map<String, Object> context, ModelScreenWidget.Label label) throws IOException {
-        Map<String, Object> parameters = new HashMap<String, Object>();
-        parameters.put("text", label.getText(context));
-        parameters.put("id", label.getId(context));
-        parameters.put("style", label.getStyle(context));
-        executeMacro(writer, "renderLabel", parameters);
-    }
-
-    public void renderHorizontalSeparator(Appendable writer, Map<String, Object> context, ModelScreenWidget.HorizontalSeparator separator) throws IOException {
-        Map<String, Object> parameters = new HashMap<String, Object>();
-        parameters.put("id", separator.getId(context));
-        parameters.put("style", separator.getStyle(context));
-        executeMacro(writer, "renderHorizontalSeparator", parameters);
-    }
-
-    public void renderLink(Appendable writer, Map<String, Object> context, ModelScreenWidget.ScreenLink link) throws IOException {
-        HttpServletResponse response = (HttpServletResponse) context.get("response");
-        HttpServletRequest request = (HttpServletRequest) context.get("request");
-
-        String targetWindow = link.getTargetWindow(context);
-        String target = link.getTarget(context);
-
-        String uniqueItemName = link.getModelScreen().getName() + "_LF_" + UtilMisc.<String>addToBigDecimalInMap(context, "screenUniqueItemIndex", BigDecimal.ONE);
-
-        String linkType = WidgetWorker.determineAutoLinkType(link.getLinkType(), target, link.getUrlMode(), request);
-        String linkUrl = "";
-        String actionUrl = "";
-        StringBuilder parameters=new StringBuilder();
-        String width = link.getWidth();
-        if (UtilValidate.isEmpty(width)) {
-            width = "300";
-        }
-        String height = link.getHeight();
-        if (UtilValidate.isEmpty(height)) {
-            height = "200";
-        }
-        if ("hidden-form".equals(linkType) || "ajax-window".equals(linkType)) {
-            StringBuilder sb = new StringBuilder();
-            WidgetWorker.buildHyperlinkUrl(sb, target, link.getUrlMode(), null, link.getPrefix(context),
-                    link.getFullPath(), link.getSecure(), link.getEncode(), request, response, context);
-            actionUrl = sb.toString();
-            parameters.append("[");
-            for (Map.Entry<String, String> parameter: link.getParameterMap(context).entrySet()) {
-                if (parameters.length() >1) {
-                    parameters.append(",");
-                }
-                parameters.append("{'name':'");
-                parameters.append(parameter.getKey());
-                parameters.append("'");
-                parameters.append(",'value':'");
-                parameters.append(parameter.getValue());
-                parameters.append("'}");
-            }
-            parameters.append("]");
-
-        }
-        String id = link.getId(context);
-        String style = link.getStyle(context);
-        String name = link.getName(context);
-        String text = link.getText(context);
-        if (UtilValidate.isNotEmpty(target)) {
-            if (!"hidden-form".equals(linkType)) {
-                StringBuilder sb = new StringBuilder();
-                WidgetWorker.buildHyperlinkUrl(sb, target, link.getUrlMode(), link.getParameterMap(context), link.getPrefix(context),
-                        link.getFullPath(), link.getSecure(), link.getEncode(), request, response, context);
-                linkUrl = sb.toString();
-            }
-        }
-        String imgStr = "";
-        ModelScreenWidget.ScreenImage img = link.getImage();
-        if (img != null) {
-            StringWriter sw = new StringWriter();
-            renderImage(sw, context, img);
-            imgStr = sw.toString();
-        }
-        StringWriter sr = new StringWriter();
-        sr.append("<@renderLink ");
-        sr.append("parameterList=");
-        sr.append(parameters.length()==0?"\"\"":parameters.toString());
-        sr.append(" targetWindow=\"");
-        sr.append(targetWindow);
-        sr.append("\" target=\"");
-        sr.append(target);
-        sr.append("\" uniqueItemName=\"");
-        sr.append(uniqueItemName);
-        sr.append("\" linkType=\"");
-        sr.append(linkType);
-        sr.append("\" actionUrl=\"");
-        sr.append(actionUrl);
-        sr.append("\" id=\"");
-        sr.append(id);
-        sr.append("\" style=\"");
-        sr.append(style);
-        sr.append("\" name=\"");
-        sr.append(name);
-        sr.append("\" width=\"");
-        sr.append(width);
-        sr.append("\" height=\"");
-        sr.append(height);
-        sr.append("\" linkUrl=\"");
-        sr.append(linkUrl);
-        sr.append("\" text=\"");
-        sr.append(text);
-        sr.append("\" imgStr=\"");
-        sr.append(imgStr.replaceAll("\"", "\\\\\""));
-        sr.append("\" />");
-        executeMacro(writer, sr.toString());
-    }
-
-    public void renderImage(Appendable writer, Map<String, Object> context, ModelScreenWidget.ScreenImage image) throws IOException {
-        if (image == null)
-            return ;
-        String src = image.getSrc(context);
-
-        String urlMode = image.getUrlMode();
-        boolean fullPath = false;
-        boolean secure = false;
-        boolean encode = false;
-        HttpServletResponse response = (HttpServletResponse) context.get("response");
-        HttpServletRequest request = (HttpServletRequest) context.get("request");
-        String urlString = "";
-        if (urlMode != null && urlMode.equalsIgnoreCase("intra-app")) {
-            if (request != null && response != null) {
-                ServletContext ctx = (ServletContext) request.getAttribute("servletContext");
-                RequestHandler rh = (RequestHandler) ctx.getAttribute("_REQUEST_HANDLER_");
-                urlString = rh.makeLink(request, response, src, fullPath, secure, encode);
-            } else {
-                urlString = src;
-            }
-        } else  if (urlMode != null && urlMode.equalsIgnoreCase("content")) {
-            if (request != null && response != null) {
-                StringBuilder newURL = new StringBuilder();
-                ContentUrlTag.appendContentPrefix(request, newURL);
-                newURL.append(src);
-                urlString = newURL.toString();
-            }
-        } else {
-            urlString = src;
-        }
-        Map<String, Object> parameters = new HashMap<String, Object>();
-        parameters.put("src", src);
-        parameters.put("id", image.getId(context));
-        parameters.put("style", image.getStyle(context));
-        parameters.put("wid", image.getWidth(context));
-        parameters.put("hgt", image.getHeight(context));
-        parameters.put("border", image.getBorder(context));
-        parameters.put("alt", image.getAlt(context));
-        parameters.put("urlString", urlString);
-        executeMacro(writer, "renderImage", parameters);
-    }
-
-    public void renderContentBegin(Appendable writer, Map<String, Object> context, ModelScreenWidget.Content content) throws IOException {
-         String editRequest = content.getEditRequest(context);
-         String enableEditName = content.getEnableEditName(context);
-         String enableEditValue = (String)context.get(enableEditName);
-
-         if (Debug.verboseOn()) Debug.logVerbose("directEditRequest:" + editRequest, module);
-
-         Map<String, Object> parameters = new HashMap<String, Object>();
-         parameters.put("editRequest", editRequest);
-         parameters.put("enableEditValue", enableEditValue == null ? "" : enableEditValue);
-         parameters.put("editContainerStyle", content.getEditContainerStyle(context));
-         executeMacro(writer, "renderContentBegin", parameters);
-    }
-
-    public void renderContentBody(Appendable writer, Map<String, Object> context, ModelScreenWidget.Content content) throws IOException {
-        Locale locale = UtilMisc.ensureLocale(context.get("locale"));
-        //Boolean nullThruDatesOnly = Boolean.valueOf(false);
-        String mimeTypeId = "text/html";
-        String expandedContentId = content.getContentId(context);
-        String expandedDataResourceId = content.getDataResourceId(context);
-        String renderedContent = null;
-        LocalDispatcher dispatcher = (LocalDispatcher) context.get("dispatcher");
-        Delegator delegator = (Delegator) context.get("delegator");
-
-        // make a new map for content rendering; so our current map does not get clobbered
-        Map<String, Object> contentContext = new HashMap<String, Object>();
-        contentContext.putAll(context);
-        String dataResourceId = (String)contentContext.get("dataResourceId");
-        if (Debug.verboseOn()) Debug.logVerbose("expandedContentId:" + expandedContentId, module);
-
-        try {
-            if (UtilValidate.isNotEmpty(dataResourceId)) {
-                if (WidgetDataResourceWorker.dataresourceWorker != null) {
-                    renderedContent = WidgetDataResourceWorker.dataresourceWorker.renderDataResourceAsTextExt(delegator, dataResourceId, contentContext, locale, mimeTypeId, false);
-                } else {
-                    Debug.logError("Not rendering content, WidgetDataResourceWorker.dataresourceWorker not found.", module);
-                }
-            } else if (UtilValidate.isNotEmpty(expandedContentId)) {
-                if (WidgetContentWorker.contentWorker != null) {
-                    renderedContent = WidgetContentWorker.contentWorker.renderContentAsTextExt(dispatcher, delegator, expandedContentId, contentContext, locale, mimeTypeId, true);
-                } else {
-                    Debug.logError("Not rendering content, WidgetContentWorker.contentWorker not found.", module);
-                }
-            } else if (UtilValidate.isNotEmpty(expandedDataResourceId)) {
-                if (WidgetDataResourceWorker.dataresourceWorker != null) {
-                    renderedContent = WidgetDataResourceWorker.dataresourceWorker.renderDataResourceAsTextExt(delegator, expandedDataResourceId, contentContext, locale, mimeTypeId, false);
-                } else {
-                    Debug.logError("Not rendering content, WidgetDataResourceWorker.dataresourceWorker not found.", module);
-                }
-            }
-            if (UtilValidate.isEmpty(renderedContent)) {
-                String editRequest = content.getEditRequest(context);
-                if (UtilValidate.isNotEmpty(editRequest)) {
-                    if (WidgetContentWorker.contentWorker != null) {
-                        WidgetContentWorker.contentWorker.renderContentAsTextExt(dispatcher, delegator, "NOCONTENTFOUND", writer, contentContext, locale, mimeTypeId, true);
-                    } else {
-                        Debug.logError("Not rendering content, WidgetContentWorker.contentWorker not found.", module);
-                    }
-                }
-            } else {
-                if (content.xmlEscape()) {
-                    renderedContent = UtilFormatOut.encodeXmlValue(renderedContent);
-                }
-
-                writer.append(renderedContent);
-            }
-
-        } catch (GeneralException e) {
-            String errMsg = "Error rendering included content with id [" + expandedContentId + "] : " + e.toString();
-            Debug.logError(e, errMsg, module);
-            //throw new RuntimeException(errMsg);
-        } catch (IOException e2) {
-            String errMsg = "Error rendering included content with id [" + expandedContentId + "] : " + e2.toString();
-            Debug.logError(e2, errMsg, module);
-            //throw new RuntimeException(errMsg);
-        }
-    }
-
-    public void renderContentEnd(Appendable writer, Map<String, Object> context, ModelScreenWidget.Content content) throws IOException {
-        String expandedContentId = content.getContentId(context);
-        String editMode = "Edit";
-        String editRequest = content.getEditRequest(context);
-        String enableEditName = content.getEnableEditName(context);
-        String enableEditValue = (String)context.get(enableEditName);
-        String urlString = "";
-        if (editRequest != null && editRequest.toUpperCase().indexOf("IMAGE") > 0) {
-            editMode += " Image";
-        }
-
-        if (UtilValidate.isNotEmpty(editRequest) && "true".equals(enableEditValue)) {
-            HttpServletResponse response = (HttpServletResponse) context.get("response");
-            HttpServletRequest request = (HttpServletRequest) context.get("request");
-            if (request != null && response != null) {
-                if (editRequest.indexOf("?") < 0)  editRequest += "?";
-                else editRequest += "&amp;";
-                editRequest += "contentId=" + expandedContentId;
-                ServletContext ctx = (ServletContext) request.getAttribute("servletContext");
-                RequestHandler rh = (RequestHandler) ctx.getAttribute("_REQUEST_HANDLER_");
-                urlString = rh.makeLink(request, response, editRequest, false, false, false);
-            }
-
-            Map<String, Object> parameters = new HashMap<String, Object>();
-            parameters.put("urlString", urlString);
-            parameters.put("editMode", editMode);
-            parameters.put("editContainerStyle", content.getEditContainerStyle(context));
-            parameters.put("editRequest", editRequest);
-            parameters.put("enableEditValue", enableEditValue);
-            executeMacro(writer, "renderContentEnd", parameters);
-        }
-    }
-
-    public void renderContentFrame(Appendable writer, Map<String, Object> context, ModelScreenWidget.Content content) throws IOException {
-        String dataResourceId = content.getDataResourceId(context);
-        String urlString = "/ViewSimpleContent?dataResourceId=" + dataResourceId;
-        String fullUrlString = "";
-        HttpServletRequest request = (HttpServletRequest) context.get("request");
-        HttpServletResponse response = (HttpServletResponse) context.get("response");
-        if (request != null && response != null) {
-            ServletContext ctx = (ServletContext) request.getAttribute("servletContext");
-            RequestHandler rh = (RequestHandler) ctx.getAttribute("_REQUEST_HANDLER_");
-            fullUrlString = rh.makeLink(request, response, urlString, true, false, false);
-        }
-
-        Map<String, Object> parameters = new HashMap<String, Object>();
-        parameters.put("fullUrl", fullUrlString);
-        parameters.put("width", content.getWidth());
-        parameters.put("height", content.getHeight());
-        parameters.put("border", content.getBorder());
-        executeMacro(writer, "renderContentFrame", parameters);
-    }
-
-    public void renderSubContentBegin(Appendable writer, Map<String, Object> context, ModelScreenWidget.SubContent content) throws IOException {
-         String enableEditName = content.getEnableEditName(context);
-         String enableEditValue = (String)context.get(enableEditName);
-
-         Map<String, Object> parameters = new HashMap<String, Object>();
-         parameters.put("editContainerStyle", content.getEditContainerStyle(context));
-         parameters.put("editRequest", content.getEditRequest(context));
-         parameters.put("enableEditValue", enableEditValue == null ? "" : enableEditValue);
-         executeMacro(writer, "renderSubContentBegin", parameters);
-    }
-
-    public void renderSubContentBody(Appendable writer, Map<String, Object> context, ModelScreenWidget.SubContent content) throws IOException {
-         Locale locale = UtilMisc.ensureLocale(context.get("locale"));
-         String mimeTypeId = "text/html";
-         String expandedContentId = content.getContentId(context);
-         String expandedMapKey = content.getMapKey(context);
-         String renderedContent = "";
-         LocalDispatcher dispatcher = (LocalDispatcher) context.get("dispatcher");
-         Delegator delegator = (Delegator) context.get("delegator");
-
-         // create a new map for the content rendering; so our current context does not get overwritten!
-         Map<String, Object> contentContext = new HashMap<String, Object>();
-         contentContext.putAll(context);
-
-         try {
-             if (WidgetContentWorker.contentWorker != null) {
-                 renderedContent = WidgetContentWorker.contentWorker.renderSubContentAsTextExt(dispatcher, delegator, expandedContentId, expandedMapKey, contentContext, locale, mimeTypeId, true);
-                 //Debug.logInfo("renderedContent=" + renderedContent, module);
-             } else {
-                 Debug.logError("Not rendering content, WidgetContentWorker.contentWorker not found.", module);
-             }
-             if (UtilValidate.isEmpty(renderedContent)) {
-                 String editRequest = content.getEditRequest(context);
-                 if (UtilValidate.isNotEmpty(editRequest)) {
-                     if (WidgetContentWorker.contentWorker != null) {
-                         WidgetContentWorker.contentWorker.renderContentAsTextExt(dispatcher, delegator, "NOCONTENTFOUND", writer, contentContext, locale, mimeTypeId, true);
-                     } else {
-                         Debug.logError("Not rendering content, WidgetContentWorker.contentWorker not found.", module);
-                     }
-                 }
-             } else {
-                 if (content.xmlEscape()) {
-                     renderedContent = UtilFormatOut.encodeXmlValue(renderedContent);
-                 }
-
-                 writer.append(renderedContent);
-             }
-
-         } catch (GeneralException e) {
-             String errMsg = "Error rendering included content with id [" + expandedContentId + "] : " + e.toString();
-             Debug.logError(e, errMsg, module);
-             //throw new RuntimeException(errMsg);
-         } catch (IOException e2) {
-             String errMsg = "Error rendering included content with id [" + expandedContentId + "] : " + e2.toString();
-             Debug.logError(e2, errMsg, module);
-             //throw new RuntimeException(errMsg);
-         }
-    }
-
-    public void renderSubContentEnd(Appendable writer, Map<String, Object> context, ModelScreenWidget.SubContent content) throws IOException {
-         String editMode = "Edit";
-         String editRequest = content.getEditRequest(context);
-         String enableEditName = content.getEnableEditName(context);
-         String enableEditValue = (String)context.get(enableEditName);
-         String expandedContentId = content.getContentId(context);
-         String expandedMapKey = content.getMapKey(context);
-         String urlString = "";
-         if (editRequest != null && editRequest.toUpperCase().indexOf("IMAGE") > 0) {
-             editMode += " Image";
-         }
-         if (UtilValidate.isNotEmpty(editRequest) && "true".equals(enableEditValue)) {
-             HttpServletResponse response = (HttpServletResponse) context.get("response");
-             HttpServletRequest request = (HttpServletRequest) context.get("request");
-             if (request != null && response != null) {
-                 if (editRequest.indexOf("?") < 0)  editRequest += "?";
-                 else editRequest += "&amp;";
-                 editRequest += "contentId=" + expandedContentId;
-                 if (UtilValidate.isNotEmpty(expandedMapKey)) {
-                     editRequest += "&amp;mapKey=" + expandedMapKey;
-                 }
-                 ServletContext ctx = (ServletContext) request.getAttribute("servletContext");
-                 RequestHandler rh = (RequestHandler) ctx.getAttribute("_REQUEST_HANDLER_");
-                 urlString = rh.makeLink(request, response, editRequest, false, false, false);
-             }
-         }
-
-         Map<String, Object> parameters = new HashMap<String, Object>();
-         parameters.put("urlString", urlString);
-         parameters.put("editMode", editMode);
-         parameters.put("editContainerStyle", content.getEditContainerStyle(context));
-         parameters.put("editRequest", editRequest);
-         parameters.put("enableEditValue", enableEditValue == null ? "" : enableEditValue);
-         executeMacro(writer, "renderSubContentEnd", parameters);
-    }
-
-
-    public void renderScreenletBegin(Appendable writer, Map<String, Object> context, boolean collapsed, ModelScreenWidget.Screenlet screenlet) throws IOException {
-        HttpServletRequest request = (HttpServletRequest) context.get("request");
-        HttpServletResponse response = (HttpServletResponse) context.get("response");
-        boolean javaScriptEnabled = UtilHttp.isJavaScriptEnabled(request);
-        ModelScreenWidget.Menu tabMenu = screenlet.getTabMenu();
-        if (tabMenu != null) {
-            tabMenu.renderWidgetString(writer, context, this);
-        }
-
-        String title = screenlet.getTitle(context);
-        boolean collapsible = screenlet.collapsible();
-        ModelScreenWidget.Menu navMenu = screenlet.getNavigationMenu();
-        ModelScreenWidget.Form navForm = screenlet.getNavigationForm();
-        String expandToolTip = "";
-        String collapseToolTip = "";
-        String fullUrlString = "";
-        String menuString = "";
-        boolean showMore = false;
-        if (UtilValidate.isNotEmpty(title) || navMenu != null || navForm != null || collapsible) {
-            showMore = true;
-            if (collapsible) {
-                this.getNextElementId();
-                Map<String, Object> uiLabelMap = UtilGenerics.checkMap(context.get("uiLabelMap"));
-                Map<String, Object> paramMap = UtilGenerics.checkMap(context.get("requestParameters"));
-                Map<String, Object> requestParameters = new HashMap<String, Object>(paramMap);
-                if (uiLabelMap != null) {
-                    expandToolTip = (String) uiLabelMap.get("CommonExpand");
-                    collapseToolTip = (String) uiLabelMap.get("CommonCollapse");
-                }
-                if (!javaScriptEnabled) {
-                    requestParameters.put(screenlet.getPreferenceKey(context) + "_collapsed", collapsed ? "false" : "true");
-                    String queryString = UtilHttp.urlEncodeArgs(requestParameters);
-                    fullUrlString = request.getRequestURI() + "?" + queryString;
-                }
-            }
-            StringWriter sb = new StringWriter();
-            if (navMenu != null) {
-                MenuStringRenderer savedRenderer = (MenuStringRenderer) context.get("menuStringRenderer");
-                MenuStringRenderer renderer = new ScreenletMenuRenderer(request, response);
-                context.put("menuStringRenderer", renderer);
-                navMenu.renderWidgetString(sb, context, this);
-                context.put("menuStringRenderer", savedRenderer);
-            } else if (navForm != null) {
-                renderScreenletPaginateMenu(sb, context, navForm);
-            }
-            menuString = sb.toString();
-        }
-
-        Map<String, Object> parameters = new HashMap<String, Object>();
-        parameters.put("title", title);
-        parameters.put("collapsible", collapsible);
-        parameters.put("saveCollapsed", screenlet.saveCollapsed());
-        if (UtilValidate.isNotEmpty (screenlet.getId(context))) {
-            parameters.put("id", screenlet.getId(context));
-            parameters.put("collapsibleAreaId", screenlet.getId(context) + "_col");
-        } else {
-            parameters.put("id", "screenlet_" + screenLetsIdCounter);
-            parameters.put("collapsibleAreaId","screenlet_" + screenLetsIdCounter + "_col");
-            screenLetsIdCounter++;
-        }
-        parameters.put("expandToolTip", expandToolTip);
-        parameters.put("collapseToolTip", collapseToolTip);
-        parameters.put("fullUrlString", fullUrlString);
-        parameters.put("padded", screenlet.padded());
-        parameters.put("menuString", menuString);
-        parameters.put("showMore", showMore);
-        parameters.put("collapsed", collapsed);
-        parameters.put("javaScriptEnabled", javaScriptEnabled);
-        executeMacro(writer, "renderScreenletBegin", parameters);
-    }
-
-    public void renderScreenletSubWidget(Appendable writer, Map<String, Object> context, ModelScreenWidget subWidget, ModelScreenWidget.Screenlet screenlet) throws GeneralException, IOException  {
-        if (subWidget.equals(screenlet.getNavigationForm())) {
-            HttpServletRequest request = (HttpServletRequest) context.get("request");
-            HttpServletResponse response = (HttpServletResponse) context.get("response");
-            if (request != null && response != null) {
-                Map<String, Object> globalCtx = UtilGenerics.checkMap(context.get("globalContext"));
-                globalCtx.put("NO_PAGINATOR", true);
-                FormStringRenderer savedRenderer = (FormStringRenderer) context.get("formStringRenderer");
-                MacroFormRenderer renderer = null;
-                try {
-                    renderer = new MacroFormRenderer(formrenderer, request, response);
-                } catch (TemplateException e) {
-                    Debug.logError("Not rendering content, error on MacroFormRenderer creation.", module);
-                }
-                renderer.setRenderPagination(false);
-                context.put("formStringRenderer", renderer);
-                subWidget.renderWidgetString(writer, context, this);
-                context.put("formStringRenderer", savedRenderer);
-            }
-        } else {
-            subWidget.renderWidgetString(writer, context, this);
-        }
-    }
-    public void renderScreenletEnd(Appendable writer, Map<String, Object> context, ModelScreenWidget.Screenlet screenlet) throws IOException {
-        executeMacro(writer, "renderScreenletEnd", null);
-    }
-
-    protected void renderScreenletPaginateMenu(Appendable writer, Map<String, Object> context, ModelScreenWidget.Form form) throws IOException {
-        HttpServletResponse response = (HttpServletResponse) context.get("response");
-        HttpServletRequest request = (HttpServletRequest) context.get("request");
-        ModelForm modelForm = form.getModelForm(context);
-        modelForm.runFormActions(context);
-        Paginator.preparePager(modelForm, context);
-        String targetService = modelForm.getPaginateTarget(context);
-        if (targetService == null) {
-            targetService = "${targetService}";
-        }
-
-        // get the parametrized pagination index and size fields
-        int paginatorNumber = WidgetWorker.getPaginatorNumber(context);
-        String viewIndexParam = modelForm.getMultiPaginateIndexField(context);
-        String viewSizeParam = modelForm.getMultiPaginateSizeField(context);
-
-        int viewIndex = Paginator.getViewIndex(modelForm, context);
-        int viewSize = Paginator.getViewSize(modelForm, context);
-        int listSize = Paginator.getListSize(context);
-
-        int highIndex = Paginator.getHighIndex(context);
-        int actualPageSize = Paginator.getActualPageSize(context);
-
-        // if this is all there seems to be (if listSize < 0, then size is unknown)
-        if (actualPageSize >= listSize && listSize >= 0) return;
-
-        // needed for the "Page" and "rows" labels
-        Map<String, String> uiLabelMap = UtilGenerics.cast(context.get("uiLabelMap"));
-        String ofLabel = "";
-        if (uiLabelMap == null) {
-            Debug.logWarning("Could not find uiLabelMap in context", module);
-        } else {
-            ofLabel = uiLabelMap.get("CommonOf");
-            ofLabel = ofLabel.toLowerCase();
-        }
-
-        // for legacy support, the viewSizeParam is VIEW_SIZE and viewIndexParam is VIEW_INDEX when the fields are "viewSize" and "viewIndex"
-        if (viewIndexParam.equals("viewIndex" + "_" + paginatorNumber)) viewIndexParam = "VIEW_INDEX" + "_" + paginatorNumber;
-        if (viewSizeParam.equals("viewSize" + "_" + paginatorNumber)) viewSizeParam = "VIEW_SIZE" + "_" + paginatorNumber;
-
-        ServletContext ctx = (ServletContext) request.getAttribute("servletContext");
-        RequestHandler rh = (RequestHandler) ctx.getAttribute("_REQUEST_HANDLER_");
-
-        Map<String, Object> inputFields = UtilGenerics.toMap(context.get("requestParameters"));
-        // strip out any multi form fields if the form is of type multi
-        if (modelForm.getType().equals("multi")) {
-            inputFields = UtilHttp.removeMultiFormParameters(inputFields);
-        }
-        String queryString = UtilHttp.urlEncodeArgs(inputFields);
-        // strip legacy viewIndex/viewSize params from the query string
-        queryString = UtilHttp.stripViewParamsFromQueryString(queryString, "" + paginatorNumber);
-        // strip parametrized index/size params from the query string
-        HashSet<String> paramNames = new HashSet<String>();
-        paramNames.add(viewIndexParam);
-        paramNames.add(viewSizeParam);
-        queryString = UtilHttp.stripNamedParamsFromQueryString(queryString, paramNames);
-
-        String anchor = "";
-        String paginateAnchor = modelForm.getPaginateTargetAnchor();
-        if (paginateAnchor != null) anchor = "#" + paginateAnchor;
-
-        // preparing the link text, so that later in the code we can reuse this and just add the viewIndex
-        String prepLinkText = "";
-        prepLinkText = targetService;
-        if (prepLinkText.indexOf("?") < 0) {
-            prepLinkText += "?";
-        } else if (!prepLinkText.endsWith("?")) {
-            prepLinkText += "&amp;";
-        }
-        if (!UtilValidate.isEmpty(queryString) && !queryString.equals("null")) {
-            prepLinkText += queryString + "&amp;";
-        }
-        prepLinkText += viewSizeParam + "=" + viewSize + "&amp;" + viewIndexParam + "=";
-
-        String linkText;
-
-
-        // The current screenlet title bar navigation syling requires rendering
-        // these links in reverse order
-        // Last button
-        String lastLinkUrl = "";
-        if (highIndex < listSize) {
-            int lastIndex = UtilMisc.getViewLastIndex(listSize, viewSize);
-            linkText = prepLinkText + lastIndex + anchor;
-            lastLinkUrl = rh.makeLink(request, response, linkText);
-        }
-        String nextLinkUrl = "";
-        if (highIndex < listSize) {
-            linkText = prepLinkText + (viewIndex + 1) + anchor;
-            // - make the link
-            nextLinkUrl = rh.makeLink(request, response, linkText);
-        }
-        String previousLinkUrl = "";
-        if (viewIndex > 0) {
-            linkText = prepLinkText + (viewIndex - 1) + anchor;
-            previousLinkUrl = rh.makeLink(request, response, linkText);
-        }
-        String firstLinkUrl = "";
-        if (viewIndex > 0) {
-            linkText = prepLinkText + 0 + anchor;
-            firstLinkUrl = rh.makeLink(request, response, linkText);
-        }
-
-        Map<String, Object> parameters = new HashMap<String, Object>();
-        parameters.put("lowIndex", Paginator.getLowIndex(context));
-        parameters.put("actualPageSize", actualPageSize);
-        parameters.put("ofLabel", ofLabel);
-        parameters.put("listSize", listSize);
-        parameters.put("paginateLastStyle", modelForm.getPaginateLastStyle());
-        parameters.put("lastLinkUrl", lastLinkUrl);
-        parameters.put("paginateLastLabel", modelForm.getPaginateLastLabel(context));
-        parameters.put("paginateNextStyle", modelForm.getPaginateNextStyle());
-        parameters.put("nextLinkUrl", nextLinkUrl);
-        parameters.put("paginateNextLabel", modelForm.getPaginateNextLabel(context));
-        parameters.put("paginatePreviousStyle", modelForm.getPaginatePreviousStyle());
-        parameters.put("paginatePreviousLabel", modelForm.getPaginatePreviousLabel(context));
-        parameters.put("previousLinkUrl", previousLinkUrl);
-        parameters.put("paginateFirstStyle", modelForm.getPaginateFirstStyle());
-        parameters.put("paginateFirstLabel", modelForm.getPaginateFirstLabel(context));
-        parameters.put("firstLinkUrl", firstLinkUrl);
-        executeMacro(writer, "renderScreenletPaginateMenu", parameters);
-    }
-
-    public void renderPortalPageBegin(Appendable writer, Map<String, Object> context, ModelScreenWidget.PortalPage portalPage) throws GeneralException, IOException {
-        String portalPageId = portalPage.getActualPortalPageId(context);
-        String originalPortalPageId = portalPage.getOriginalPortalPageId(context);
-        String confMode = portalPage.getConfMode(context);
-
-        Map<String, String> uiLabelMap = UtilGenerics.cast(context.get("uiLabelMap"));
-        String addColumnLabel = "";
-        String addColumnHint = "";
-        if (uiLabelMap == null) {
-            Debug.logWarning("Could not find uiLabelMap in context", module);
-        } else {
-            addColumnLabel = uiLabelMap.get("CommonAddColumn");
-            addColumnHint = uiLabelMap.get("CommonAddAColumnToThisPortalPage");
-        }
-
-        StringWriter sr = new StringWriter();
-        sr.append("<@renderPortalPageBegin ");
-        sr.append("originalPortalPageId=\"");
-        sr.append(originalPortalPageId);
-        sr.append("\" portalPageId=\"");
-        sr.append(portalPageId);
-        sr.append("\" confMode=\"");
-        sr.append(confMode);
-        sr.append("\" addColumnLabel=\"");
-        sr.append(addColumnLabel);
-        sr.append("\" addColumnHint=\"");
-        sr.append(addColumnHint);
-        sr.append("\" />");
-        executeMacro(writer, sr.toString());
-    }
-
-    public void renderPortalPageEnd(Appendable writer, Map<String, Object> context, ModelScreenWidget.PortalPage portalPage) throws GeneralException, IOException {
-        StringWriter sr = new StringWriter();
-        sr.append("<@renderPortalPageEnd/>");
-        executeMacro(writer, sr.toString());
-    }
-
-    public void renderPortalPageColumnBegin(Appendable writer, Map<String, Object> context, ModelScreenWidget.PortalPage portalPage, GenericValue portalPageColumn) throws GeneralException, IOException {
-        String portalPageId = portalPage.getActualPortalPageId(context);
-        String originalPortalPageId = portalPage.getOriginalPortalPageId(context);
-        String columnSeqId = portalPageColumn.getString("columnSeqId");
-        String columnWidthPercentage = portalPageColumn.getString("columnWidthPercentage");
-        String columnWidthPixels = portalPageColumn.getString("columnWidthPixels");
-        String confMode = portalPage.getConfMode(context);
-
-        Map<String, String> uiLabelMap = UtilGenerics.cast(context.get("uiLabelMap"));
-        String delColumnLabel = "";
-        String delColumnHint = "";
-        String addPortletLabel = "";
-        String addPortletHint = "";
-        String colWidthLabel = "";
-        String setColumnSizeHint = "";
-        
-        if (uiLabelMap == null) {
-            Debug.logWarning("Could not find uiLabelMap in context", module);
-        } else {
-            delColumnLabel = uiLabelMap.get("CommonDeleteColumn");
-            delColumnHint = uiLabelMap.get("CommonDeleteThisColumn");
-
-            addPortletLabel = uiLabelMap.get("CommonAddAPortlet");
-            addPortletHint = uiLabelMap.get("CommonAddPortletToPage");
-            colWidthLabel = uiLabelMap.get("CommonWidth");
-            setColumnSizeHint = uiLabelMap.get("CommonSetColumnWidth");
-        }
-
-        StringWriter sr = new StringWriter();
-        sr.append("<@renderPortalPageColumnBegin ");
-        sr.append("originalPortalPageId=\"");
-        sr.append(originalPortalPageId);
-        sr.append("\" portalPageId=\"");
-        sr.append(portalPageId);
-        sr.append("\" columnSeqId=\"");
-        sr.append(columnSeqId);
-        sr.append("\" ");
-        if (UtilValidate.isNotEmpty(columnWidthPixels)) {
-            sr.append("width=\"");
-            sr.append(columnWidthPixels);
-            sr.append("px\"");
-        } else if (UtilValidate.isNotEmpty(columnWidthPercentage)) {
-            sr.append("width=\"");
-            sr.append(columnWidthPercentage);
-            sr.append("%\"");
-        }
-        sr.append(" confMode=\"");
-        sr.append(confMode);
-        sr.append("\" delColumnLabel=\"");
-        sr.append(delColumnLabel);
-        sr.append("\" delColumnHint=\"");
-        sr.append(delColumnHint);
-        sr.append("\" addPortletLabel=\"");
-        sr.append(addPortletLabel);
-        sr.append("\" addPortletHint=\"");
-        sr.append(addPortletHint);
-        sr.append("\" colWidthLabel=\"");
-        sr.append(colWidthLabel);
-        sr.append("\" setColumnSizeHint=\"");
-        sr.append(setColumnSizeHint);
-        sr.append("\" />");
-        executeMacro(writer, sr.toString());
-    }   
-
-    public void renderPortalPageColumnEnd(Appendable writer, Map<String, Object> context, ModelScreenWidget.PortalPage portalPage, GenericValue portalPageColumn) throws GeneralException, IOException {
-        StringWriter sr = new StringWriter();
-        sr.append("<@renderPortalPageColumnEnd/>");
-        executeMacro(writer, sr.toString());
-    }
-
-    public void renderPortalPagePortletBegin(Appendable writer, Map<String, Object> context, ModelScreenWidget.PortalPage portalPage, GenericValue portalPortlet) throws GeneralException, IOException {
-        String portalPageId = portalPage.getActualPortalPageId(context);
-        String originalPortalPageId = portalPage.getOriginalPortalPageId(context);
-        String portalPortletId = portalPortlet.getString("portalPortletId");
-        String portletSeqId = portalPortlet.getString("portletSeqId");
-        String columnSeqId = portalPortlet.getString("columnSeqId");
-        String confMode = portalPage.getConfMode(context);
-        String editFormName = portalPortlet.getString("editFormName");
-        String editFormLocation = portalPortlet.getString("editFormLocation");
-
-        String prevPortletId = (String) context.get("prevPortletId");
-        String prevPortletSeqId = (String) context.get("prevPortletSeqId");
-        String nextPortletId = (String) context.get("nextPortletId");
-        String nextPortletSeqId = (String) context.get("nextPortletSeqId");
-        String prevColumnSeqId = (String) context.get("prevColumnSeqId");
-        String nextColumnSeqId = (String) context.get("nextColumnSeqId");
-
-        Map<String, String> uiLabelMap = UtilGenerics.cast(context.get("uiLabelMap"));
-        String delPortletHint = "";
-        String editAttributeHint = "";
-        if (uiLabelMap == null) {
-            Debug.logWarning("Could not find uiLabelMap in context", module);
-        } else {
-            delPortletHint = uiLabelMap.get("CommonDeleteThisPortlet");
-            editAttributeHint = uiLabelMap.get("CommonEditPortletAttributes");
-        }
-
-        StringWriter sr = new StringWriter();
-        sr.append("<@renderPortalPagePortletBegin ");
-        sr.append("originalPortalPageId=\"");
-        sr.append(originalPortalPageId);
-        sr.append("\" portalPageId=\"");
-        sr.append(portalPageId);
-        sr.append("\" portalPortletId=\"");
-        sr.append(portalPortletId);
-        sr.append("\" portletSeqId=\"");
-        sr.append(portletSeqId);
-        sr.append("\" prevPortletId=\"");
-        sr.append(prevPortletId);
-        sr.append("\" prevPortletSeqId=\"");
-        sr.append(prevPortletSeqId);
-        sr.append("\" nextPortletId=\"");
-        sr.append(nextPortletId);
-        sr.append("\" nextPortletSeqId=\"");
-        sr.append(nextPortletSeqId);
-        sr.append("\" columnSeqId=\"");
-        sr.append(columnSeqId);
-        sr.append("\" prevColumnSeqId=\"");
-        sr.append(prevColumnSeqId);
-        sr.append("\" nextColumnSeqId=\"");
-        sr.append(nextColumnSeqId);
-        sr.append("\" delPortletHint=\"");
-        sr.append(delPortletHint);
-        sr.append("\" editAttributeHint=\"");
-        sr.append(editAttributeHint);
-        sr.append("\" confMode=\"");
-        sr.append(confMode);
-        sr.append("\"");
-        if (UtilValidate.isNotEmpty(editFormName) && UtilValidate.isNotEmpty(editFormLocation)) {
-            sr.append(" editAttribute=\"true\"");
-        }
-        sr.append("/>");
-        executeMacro(writer, sr.toString());
-    }
-
-    public void renderPortalPagePortletEnd(Appendable writer, Map<String, Object> context, ModelScreenWidget.PortalPage portalPage, GenericValue portalPortlet) throws GeneralException, IOException {
-        String confMode = portalPage.getConfMode(context);
-
-        StringWriter sr = new StringWriter();
-        sr.append("<@renderPortalPagePortletEnd ");
-        sr.append(" confMode=\"");
-        sr.append(confMode);
-        sr.append("\" />");
-        executeMacro(writer, sr.toString());
-    }
-
-    public void renderPortalPagePortletBody(Appendable writer, Map<String, Object> context, ModelScreenWidget.PortalPage portalPage, GenericValue portalPortlet) throws GeneralException, IOException {
-        String portalPortletId = portalPortlet.getString("portalPortletId");
-        String screenName = portalPortlet.getString("screenName");
-        String screenLocation = portalPortlet.getString("screenLocation");
-
-        ModelScreen modelScreen = null;
-        if (UtilValidate.isNotEmpty(screenName) && UtilValidate.isNotEmpty(screenLocation)) {
-            try {
-                modelScreen = ScreenFactory.getScreenFromLocation(screenLocation, screenName);
-            } catch (IOException e) {
-                String errMsg = "Error rendering portlet ID [" + portalPortletId + "]: " + e.toString();
-                Debug.logError(e, errMsg, module);
-                throw new RuntimeException(errMsg);
-            } catch (SAXException e) {
-                String errMsg = "Error rendering portlet ID [" + portalPortletId + "]: " + e.toString();
-                Debug.logError(e, errMsg, module);
-                throw new RuntimeException(errMsg);
-            } catch (ParserConfigurationException e) {
-                String errMsg = "Error rendering portlet ID [" + portalPortletId + "]: " + e.toString();
-                Debug.logError(e, errMsg, module);
-                throw new RuntimeException(errMsg);
-            }
-        }
-        modelScreen.renderScreenString(writer, context, this);
-    }
-
-    @Override
-    public void renderColumnContainer(Appendable writer, Map<String, Object> context, ColumnContainer columnContainer) throws IOException {
-        String id = columnContainer.getId(context);
-        String style = columnContainer.getStyle(context);
-        StringBuilder sb = new StringBuilder("<@renderColumnContainerBegin");
-        sb.append(" id=\"");
-        sb.append(id);
-        sb.append("\" style=\"");
-        sb.append(style);
-        sb.append("\" />");
-        executeMacro(writer, sb.toString());
-        for (Column column : columnContainer.getColumns()) {
-            id = column.getId(context);
-            style = column.getStyle(context);
-            sb = new StringBuilder("<@renderColumnBegin");
-            sb.append(" id=\"");
-            sb.append(id);
-            sb.append("\" style=\"");
-            sb.append(style);
-            sb.append("\" />");
-            executeMacro(writer, sb.toString());
-            for (ModelScreenWidget subWidget : column.getSubWidgets()) {
-                try {
-                    subWidget.renderWidgetString(writer, context, this);
-                } catch (GeneralException e) {
-                    throw new IOException(e);
-                }
-            }
-            executeMacro(writer, "<@renderColumnEnd />");
-        }
-        executeMacro(writer, "<@renderColumnContainerEnd />");
-    }
-}
+/*******************************************************************************

+ * 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.renderer.macro;

+

+import java.io.IOException;

+import java.io.Reader;

+import java.io.StringReader;

+import java.io.StringWriter;

+import java.math.BigDecimal;

+import java.util.HashMap;

+import java.util.HashSet;

+import java.util.Locale;

+import java.util.Map;

+import java.util.WeakHashMap;

+

+import javax.servlet.ServletContext;

+import javax.servlet.http.HttpServletRequest;

+import javax.servlet.http.HttpServletResponse;

+import javax.xml.parsers.ParserConfigurationException;

+

+import org.ofbiz.base.util.Debug;

+import org.ofbiz.base.util.GeneralException;

+import org.ofbiz.base.util.UtilFormatOut;

+import org.ofbiz.base.util.UtilGenerics;

+import org.ofbiz.base.util.UtilHttp;

+import org.ofbiz.base.util.UtilMisc;

+import org.ofbiz.base.util.UtilProperties;

+import org.ofbiz.base.util.UtilValidate;

+import org.ofbiz.base.util.template.FreeMarkerWorker;

+import org.ofbiz.entity.Delegator;

+import org.ofbiz.entity.GenericValue;

+import org.ofbiz.service.LocalDispatcher;

+import org.ofbiz.webapp.control.RequestHandler;

+import org.ofbiz.webapp.taglib.ContentUrlTag;

+import org.ofbiz.widget.WidgetWorker;

+import org.ofbiz.widget.content.WidgetContentWorker;

+import org.ofbiz.widget.content.WidgetDataResourceWorker;

+import org.ofbiz.widget.model.ModelForm;

+import org.ofbiz.widget.model.ModelScreen;

+import org.ofbiz.widget.model.ModelScreenWidget;

+import org.ofbiz.widget.model.ModelScreenWidget.Column;

+import org.ofbiz.widget.model.ModelScreenWidget.ColumnContainer;

+import org.ofbiz.widget.model.ModelWidget;

+import org.ofbiz.widget.model.ScreenFactory;

+import org.ofbiz.widget.renderer.FormStringRenderer;

+import org.ofbiz.widget.renderer.MenuStringRenderer;

+import org.ofbiz.widget.renderer.Paginator;

+import org.ofbiz.widget.renderer.ScreenStringRenderer;

+import org.ofbiz.widget.renderer.html.HtmlScreenRenderer.ScreenletMenuRenderer;

+import org.xml.sax.SAXException;

+

+import freemarker.core.Environment;

+import freemarker.template.Template;

+import freemarker.template.TemplateException;

+

+public class MacroScreenRenderer implements ScreenStringRenderer {

+

+    public static final String module = MacroScreenRenderer.class.getName();

+    private Template macroLibrary;

+    private WeakHashMap<Appendable, Environment> environments = new WeakHashMap<Appendable, Environment>();

+    private String rendererName;

+    private int elementId = 999;

+    protected boolean widgetCommentsEnabled = false;

+    private static final String formrenderer = UtilProperties.getPropertyValue("widget", "screen.formrenderer");

+    private int screenLetsIdCounter = 1;

+

+    public MacroScreenRenderer(String name, String macroLibraryPath) throws TemplateException, IOException {

+        macroLibrary = FreeMarkerWorker.getTemplate(macroLibraryPath);

+        rendererName = name;

+    }

+

+    @Deprecated

+    public MacroScreenRenderer(String name, String macroLibraryPath, Appendable writer) throws TemplateException, IOException {

+        this(name, macroLibraryPath);

+    }

+

+    private String getNextElementId() {

+        elementId++;

+        return "hsr" + elementId;

+    }

+

+    private void executeMacro(Appendable writer, String macro) throws IOException {

+        try {

+            Environment environment = getEnvironment(writer);

+            Reader templateReader = new StringReader(macro);

+            // FIXME: I am using a Date as an hack to provide a unique name for the template...

+            Template template = new Template((new java.util.Date()).toString(), templateReader, FreeMarkerWorker.getDefaultOfbizConfig());

+            templateReader.close();

+            environment.include(template);

+        } catch (TemplateException e) {

+            Debug.logError(e, "Error rendering screen macro [" + macro + "] thru ftl", module);

+        } catch (IOException e) {

+            Debug.logError(e, "Error rendering screen macro [" + macro + "] thru ftl", module);

+        }

+    }

+

+    private void executeMacro(Appendable writer, String macroName, Map<String, Object> parameters) throws IOException {

+        StringBuilder sb = new StringBuilder("<@");

+        sb.append(macroName);

+        if (parameters != null) {

+            for (Map.Entry<String, Object> parameter : parameters.entrySet()) {

+                sb.append(' ');

+                sb.append(parameter.getKey());

+                sb.append("=");

+                Object value = parameter.getValue();

+                if (value instanceof String) {

+                    sb.append('"');

+                    sb.append(((String) value).replaceAll("\"", "\\\\\""));

+                    sb.append('"');

+                } else {

+                    sb.append(value);

+                }

+            }

+        }

+        sb.append(" />");

+        executeMacro(writer, sb.toString());

+    }

+

+    private Environment getEnvironment(Appendable writer) throws TemplateException, IOException {

+        Environment environment = environments.get(writer);

+        if (environment == null) {

+            Map<String, Object> input = UtilMisc.toMap("key", null);

+            environment = FreeMarkerWorker.renderTemplate(macroLibrary, input, writer);

+            environments.put(writer, environment);

+        }

+        return environment;

+    }

+

+    public String getRendererName() {

+        return rendererName;

+    }

+

+    public void renderScreenBegin(Appendable writer, Map<String, Object> context) throws IOException {

+        executeMacro(writer, "renderScreenBegin", null);

+    }

+

+    public void renderScreenEnd(Appendable writer, Map<String, Object> context) throws IOException {

+        executeMacro(writer, "renderScreenEnd", null);

+    }

+

+    public void renderSectionBegin(Appendable writer, Map<String, Object> context, ModelScreenWidget.Section section) throws IOException {

+        if (section.isMainSection()) {

+            this.widgetCommentsEnabled = ModelWidget.widgetBoundaryCommentsEnabled(context);

+        }

+        if (this.widgetCommentsEnabled) {

+            Map<String, Object> parameters = new HashMap<String, Object>();

+            StringBuilder sb = new StringBuilder("Begin ");

+            sb.append(section.isMainSection() ? "Screen " : "Section Widget ");

+            sb.append(section.getBoundaryCommentName());

+            parameters.put("boundaryComment", sb.toString());

+            executeMacro(writer, "renderSectionBegin", parameters);

+        }

+    }

+    public void renderSectionEnd(Appendable writer, Map<String, Object> context, ModelScreenWidget.Section section) throws IOException {

+        if (this.widgetCommentsEnabled) {

+            Map<String, Object> parameters = new HashMap<String, Object>();

+            StringBuilder sb = new StringBuilder();

+            sb.append("End ");

+            sb.append(section.isMainSection() ? "Screen " : "Section Widget ");

+            sb.append(section.getBoundaryCommentName());

+            parameters.put("boundaryComment", sb.toString());

+            executeMacro(writer, "renderSectionEnd", parameters);

+        }

+    }

+

+    public void renderContainerBegin(Appendable writer, Map<String, Object> context, ModelScreenWidget.Container container) throws IOException {

+        String containerId = container.getId(context);

+        String autoUpdateTarget = container.getAutoUpdateTargetExdr(context);

+        HttpServletRequest request = (HttpServletRequest) context.get("request");

+        String autoUpdateLink = "";

+        if (UtilValidate.isNotEmpty(autoUpdateTarget) && UtilHttp.isJavaScriptEnabled(request)) {

+            if (UtilValidate.isEmpty(containerId)) {

+                containerId = getNextElementId();

+            }

+            HttpServletResponse response = (HttpServletResponse) context.get("response");

+            ServletContext ctx = (ServletContext) request.getAttribute("servletContext");

+            RequestHandler rh = (RequestHandler) ctx.getAttribute("_REQUEST_HANDLER_");

+            autoUpdateLink = rh.makeLink(request, response, autoUpdateTarget);

+        }

+        Map<String, Object> parameters = new HashMap<String, Object>();

+        parameters.put("id", containerId);

+        parameters.put("style", container.getStyle(context));

+        parameters.put("autoUpdateLink", autoUpdateLink);

+        parameters.put("autoUpdateInterval", container.getAutoUpdateInterval(context));

+        executeMacro(writer, "renderContainerBegin", parameters);

+    }

+

+    public void renderContainerEnd(Appendable writer, Map<String, Object> context, ModelScreenWidget.Container container) throws IOException {

+        executeMacro(writer, "renderContainerEnd", null);

+    }

+

+    public void renderLabel(Appendable writer, Map<String, Object> context, ModelScreenWidget.Label label) throws IOException {

+        Map<String, Object> parameters = new HashMap<String, Object>();

+        parameters.put("text", label.getText(context));

+        parameters.put("id", label.getId(context));

+        parameters.put("style", label.getStyle(context));

+        executeMacro(writer, "renderLabel", parameters);

+    }

+

+    public void renderHorizontalSeparator(Appendable writer, Map<String, Object> context, ModelScreenWidget.HorizontalSeparator separator) throws IOException {

+        Map<String, Object> parameters = new HashMap<String, Object>();

+        parameters.put("id", separator.getId(context));

+        parameters.put("style", separator.getStyle(context));

+        executeMacro(writer, "renderHorizontalSeparator", parameters);

+    }

+

+    public void renderLink(Appendable writer, Map<String, Object> context, ModelScreenWidget.ScreenLink link) throws IOException {

+        HttpServletResponse response = (HttpServletResponse) context.get("response");

+        HttpServletRequest request = (HttpServletRequest) context.get("request");

+

+        String targetWindow = link.getTargetWindow(context);

+        String target = link.getTarget(context);

+

+        String uniqueItemName = link.getModelScreen().getName() + "_LF_" + UtilMisc.<String>addToBigDecimalInMap(context, "screenUniqueItemIndex", BigDecimal.ONE);

+

+        String linkType = WidgetWorker.determineAutoLinkType(link.getLinkType(), target, link.getUrlMode(), request);

+        String linkUrl = "";

+        String actionUrl = "";

+        StringBuilder parameters=new StringBuilder();

+        String width = link.getWidth();

+        if (UtilValidate.isEmpty(width)) {

+            width = "300";

+        }

+        String height = link.getHeight();

+        if (UtilValidate.isEmpty(height)) {

+            height = "200";

+        }

+        if ("hidden-form".equals(linkType) || "ajax-window".equals(linkType)) {

+            StringBuilder sb = new StringBuilder();

+            WidgetWorker.buildHyperlinkUrl(sb, target, link.getUrlMode(), null, link.getPrefix(context),

+                    link.getFullPath(), link.getSecure(), link.getEncode(), request, response, context);

+            actionUrl = sb.toString();

+            parameters.append("[");

+            for (Map.Entry<String, String> parameter: link.getParameterMap(context).entrySet()) {

+                if (parameters.length() >1) {

+                    parameters.append(",");

+                }

+                parameters.append("{'name':'");

+                parameters.append(parameter.getKey());

+                parameters.append("'");

+                parameters.append(",'value':'");

+                parameters.append(parameter.getValue());

+                parameters.append("'}");

+            }

+            parameters.append("]");

+

+        }

+        String id = link.getId(context);

+        String style = link.getStyle(context);

+        String name = link.getName(context);

+        String text = link.getText(context);

+        if (UtilValidate.isNotEmpty(target)) {

+            if (!"hidden-form".equals(linkType)) {

+                StringBuilder sb = new StringBuilder();

+                WidgetWorker.buildHyperlinkUrl(sb, target, link.getUrlMode(), link.getParameterMap(context), link.getPrefix(context),

+                        link.getFullPath(), link.getSecure(), link.getEncode(), request, response, context);

+                linkUrl = sb.toString();

+            }

+        }

+        String imgStr = "";

+        ModelScreenWidget.ScreenImage img = link.getImage();

+        if (img != null) {

+            StringWriter sw = new StringWriter();

+            renderImage(sw, context, img);

+            imgStr = sw.toString();

+        }

+        StringWriter sr = new StringWriter();

+        sr.append("<@renderLink ");

+        sr.append("parameterList=");

+        sr.append(parameters.length()==0?"\"\"":parameters.toString());

+        sr.append(" targetWindow=\"");

+        sr.append(targetWindow);

+        sr.append("\" target=\"");

+        sr.append(target);

+        sr.append("\" uniqueItemName=\"");

+        sr.append(uniqueItemName);

+        sr.append("\" linkType=\"");

+        sr.append(linkType);

+        sr.append("\" actionUrl=\"");

+        sr.append(actionUrl);

+        sr.append("\" id=\"");

+        sr.append(id);

+        sr.append("\" style=\"");

+        sr.append(style);

+        sr.append("\" name=\"");

+        sr.append(name);

+        sr.append("\" width=\"");

+        sr.append(width);

+        sr.append("\" height=\"");

+        sr.append(height);

+        sr.append("\" linkUrl=\"");

+        sr.append(linkUrl);

+        sr.append("\" text=\"");

+        sr.append(text);

+        sr.append("\" imgStr=\"");

+        sr.append(imgStr.replaceAll("\"", "\\\\\""));

+        sr.append("\" />");

+        executeMacro(writer, sr.toString());

+    }

+

+    public void renderImage(Appendable writer, Map<String, Object> context, ModelScreenWidget.ScreenImage image) throws IOException {

+        if (image == null)

+            return ;

+        String src = image.getSrc(context);

+

+        String urlMode = image.getUrlMode();

+        boolean fullPath = false;

+        boolean secure = false;

+        boolean encode = false;

+        HttpServletResponse response = (HttpServletResponse) context.get("response");

+        HttpServletRequest request = (HttpServletRequest) context.get("request");

+        String urlString = "";

+        if (urlMode != null && urlMode.equalsIgnoreCase("intra-app")) {

+            if (request != null && response != null) {

+                ServletContext ctx = (ServletContext) request.getAttribute("servletContext");

+                RequestHandler rh = (RequestHandler) ctx.getAttribute("_REQUEST_HANDLER_");

+                urlString = rh.makeLink(request, response, src, fullPath, secure, encode);

+            } else {

+                urlString = src;

+            }

+        } else  if (urlMode != null && urlMode.equalsIgnoreCase("content")) {

+            if (request != null && response != null) {

+                StringBuilder newURL = new StringBuilder();

+                ContentUrlTag.appendContentPrefix(request, newURL);

+                newURL.append(src);

+                urlString = newURL.toString();

+            }

+        } else {

+            urlString = src;

+        }

+        Map<String, Object> parameters = new HashMap<String, Object>();

+        parameters.put("src", src);

+        parameters.put("id", image.getId(context));

+        parameters.put("style", image.getStyle(context));

+        parameters.put("wid", image.getWidth(context));

+        parameters.put("hgt", image.getHeight(context));

+        parameters.put("border", image.getBorder(context));

+        parameters.put("alt", image.getAlt(context));

+        parameters.put("urlString", urlString);

+        executeMacro(writer, "renderImage", parameters);

+    }

+

+    public void renderContentBegin(Appendable writer, Map<String, Object> context, ModelScreenWidget.Content content) throws IOException {

+         String editRequest = content.getEditRequest(context);

+         String enableEditName = content.getEnableEditName(context);

+         String enableEditValue = (String)context.get(enableEditName);

+

+         if (Debug.verboseOn()) Debug.logVerbose("directEditRequest:" + editRequest, module);

+

+         Map<String, Object> parameters = new HashMap<String, Object>();

+         parameters.put("editRequest", editRequest);

+         parameters.put("enableEditValue", enableEditValue == null ? "" : enableEditValue);

+         parameters.put("editContainerStyle", content.getEditContainerStyle(context));

+         executeMacro(writer, "renderContentBegin", parameters);

+    }

+

+    public void renderContentBody(Appendable writer, Map<String, Object> context, ModelScreenWidget.Content content) throws IOException {

+        Locale locale = UtilMisc.ensureLocale(context.get("locale"));

+        //Boolean nullThruDatesOnly = Boolean.valueOf(false);

+        String mimeTypeId = "text/html";

+        String expandedContentId = content.getContentId(context);

+        String expandedDataResourceId = content.getDataResourceId(context);

+        String renderedContent = null;

+        LocalDispatcher dispatcher = (LocalDispatcher) context.get("dispatcher");

+        Delegator delegator = (Delegator) context.get("delegator");

+

+        // make a new map for content rendering; so our current map does not get clobbered

+        Map<String, Object> contentContext = new HashMap<String, Object>();

+        contentContext.putAll(context);

+        String dataResourceId = (String)contentContext.get("dataResourceId");

+        if (Debug.verboseOn()) Debug.logVerbose("expandedContentId:" + expandedContentId, module);

+

+        try {

+            if (UtilValidate.isNotEmpty(dataResourceId)) {

+                if (WidgetDataResourceWorker.dataresourceWorker != null) {

+                    renderedContent = WidgetDataResourceWorker.dataresourceWorker.renderDataResourceAsTextExt(delegator, dataResourceId, contentContext, locale, mimeTypeId, false);

+                } else {

+                    Debug.logError("Not rendering content, WidgetDataResourceWorker.dataresourceWorker not found.", module);

+                }

+            } else if (UtilValidate.isNotEmpty(expandedContentId)) {

+                if (WidgetContentWorker.contentWorker != null) {

+                    renderedContent = WidgetContentWorker.contentWorker.renderContentAsTextExt(dispatcher, delegator, expandedContentId, contentContext, locale, mimeTypeId, true);

+                } else {

+                    Debug.logError("Not rendering content, WidgetContentWorker.contentWorker not found.", module);

+                }

+            } else if (UtilValidate.isNotEmpty(expandedDataResourceId)) {

+                if (WidgetDataResourceWorker.dataresourceWorker != null) {

+                    renderedContent = WidgetDataResourceWorker.dataresourceWorker.renderDataResourceAsTextExt(delegator, expandedDataResourceId, contentContext, locale, mimeTypeId, false);

+                } else {

+                    Debug.logError("Not rendering content, WidgetDataResourceWorker.dataresourceWorker not found.", module);

+                }

+            }

+            if (UtilValidate.isEmpty(renderedContent)) {

+                String editRequest = content.getEditRequest(context);

+                if (UtilValidate.isNotEmpty(editRequest)) {

+                    if (WidgetContentWorker.contentWorker != null) {

+                        WidgetContentWorker.contentWorker.renderContentAsTextExt(dispatcher, delegator, "NOCONTENTFOUND", writer, contentContext, locale, mimeTypeId, true);

+                    } else {

+                        Debug.logError("Not rendering content, WidgetContentWorker.contentWorker not found.", module);

+                    }

+                }

+            } else {

+                if (content.xmlEscape()) {

+                    renderedContent = UtilFormatOut.encodeXmlValue(renderedContent);

+                }

+

+                writer.append(renderedContent);

+            }

+

+        } catch (GeneralException e) {

+            String errMsg = "Error rendering included content with id [" + expandedContentId + "] : " + e.toString();

+            Debug.logError(e, errMsg, module);

+            //throw new RuntimeException(errMsg);

+        } catch (IOException e2) {

+            String errMsg = "Error rendering included content with id [" + expandedContentId + "] : " + e2.toString();

+            Debug.logError(e2, errMsg, module);

+            //throw new RuntimeException(errMsg);

+        }

+    }

+

+    public void renderContentEnd(Appendable writer, Map<String, Object> context, ModelScreenWidget.Content content) throws IOException {

+        String expandedContentId = content.getContentId(context);

+        String editMode = "Edit";

+        String editRequest = content.getEditRequest(context);

+        String enableEditName = content.getEnableEditName(context);

+        String enableEditValue = (String)context.get(enableEditName);

+        String urlString = "";

+        if (editRequest != null && editRequest.toUpperCase().indexOf("IMAGE") > 0) {

+            editMode += " Image";

+        }

+

+        if (UtilValidate.isNotEmpty(editRequest) && "true".equals(enableEditValue)) {

+            HttpServletResponse response = (HttpServletResponse) context.get("response");

+            HttpServletRequest request = (HttpServletRequest) context.get("request");

+            if (request != null && response != null) {

+                if (editRequest.indexOf("?") < 0)  editRequest += "?";

+                else editRequest += "&amp;";

+                editRequest += "contentId=" + expandedContentId;

+                ServletContext ctx = (ServletContext) request.getAttribute("servletContext");

+                RequestHandler rh = (RequestHandler) ctx.getAttribute("_REQUEST_HANDLER_");

+                urlString = rh.makeLink(request, response, editRequest, false, false, false);

+            }

+

+            Map<String, Object> parameters = new HashMap<String, Object>();

+            parameters.put("urlString", urlString);

+            parameters.put("editMode", editMode);

+            parameters.put("editContainerStyle", content.getEditContainerStyle(context));

+            parameters.put("editRequest", editRequest);

+            parameters.put("enableEditValue", enableEditValue);

+            executeMacro(writer, "renderContentEnd", parameters);

+        }

+    }

+

+    public void renderContentFrame(Appendable writer, Map<String, Object> context, ModelScreenWidget.Content content) throws IOException {

+        String dataResourceId = content.getDataResourceId(context);

+        String urlString = "/ViewSimpleContent?dataResourceId=" + dataResourceId;

+        String fullUrlString = "";

+        HttpServletRequest request = (HttpServletRequest) context.get("request");

+        HttpServletResponse response = (HttpServletResponse) context.get("response");

+        if (request != null && response != null) {

+            ServletContext ctx = (ServletContext) request.getAttribute("servletContext");

+            RequestHandler rh = (RequestHandler) ctx.getAttribute("_REQUEST_HANDLER_");

+            fullUrlString = rh.makeLink(request, response, urlString, true, false, false);

+        }

+

+        Map<String, Object> parameters = new HashMap<String, Object>();

+        parameters.put("fullUrl", fullUrlString);

+        parameters.put("width", content.getWidth());

+        parameters.put("height", content.getHeight());

+        parameters.put("border", content.getBorder());

+        executeMacro(writer, "renderContentFrame", parameters);

+    }

+

+    public void renderSubContentBegin(Appendable writer, Map<String, Object> context, ModelScreenWidget.SubContent content) throws IOException {

+         String enableEditName = content.getEnableEditName(context);

+         String enableEditValue = (String)context.get(enableEditName);

+

+         Map<String, Object> parameters = new HashMap<String, Object>();

+         parameters.put("editContainerStyle", content.getEditContainerStyle(context));

+         parameters.put("editRequest", content.getEditRequest(context));

+         parameters.put("enableEditValue", enableEditValue == null ? "" : enableEditValue);

+         executeMacro(writer, "renderSubContentBegin", parameters);

+    }

+

+    public void renderSubContentBody(Appendable writer, Map<String, Object> context, ModelScreenWidget.SubContent content) throws IOException {

+         Locale locale = UtilMisc.ensureLocale(context.get("locale"));

+         String mimeTypeId = "text/html";

+         String expandedContentId = content.getContentId(context);

+         String expandedMapKey = content.getMapKey(context);

+         String renderedContent = "";

+         LocalDispatcher dispatcher = (LocalDispatcher) context.get("dispatcher");

+         Delegator delegator = (Delegator) context.get("delegator");

+

+         // create a new map for the content rendering; so our current context does not get overwritten!

+         Map<String, Object> contentContext = new HashMap<String, Object>();

+         contentContext.putAll(context);

+

+         try {

+             if (WidgetContentWorker.contentWorker != null) {

+                 renderedContent = WidgetContentWorker.contentWorker.renderSubContentAsTextExt(dispatcher, delegator, expandedContentId, expandedMapKey, contentContext, locale, mimeTypeId, true);

+                 //Debug.logInfo("renderedContent=" + renderedContent, module);

+             } else {

+                 Debug.logError("Not rendering content, WidgetContentWorker.contentWorker not found.", module);

+             }

+             if (UtilValidate.isEmpty(renderedContent)) {

+                 String editRequest = content.getEditRequest(context);

+                 if (UtilValidate.isNotEmpty(editRequest)) {

+                     if (WidgetContentWorker.contentWorker != null) {

+                         WidgetContentWorker.contentWorker.renderContentAsTextExt(dispatcher, delegator, "NOCONTENTFOUND", writer, contentContext, locale, mimeTypeId, true);

+                     } else {

+                         Debug.logError("Not rendering content, WidgetContentWorker.contentWorker not found.", module);

+                     }

+                 }

+             } else {

+                 if (content.xmlEscape()) {

+                     renderedContent = UtilFormatOut.encodeXmlValue(renderedContent);

+                 }

+

+                 writer.append(renderedContent);

+             }

+

+         } catch (GeneralException e) {

+             String errMsg = "Error rendering included content with id [" + expandedContentId + "] : " + e.toString();

+             Debug.logError(e, errMsg, module);

+             //throw new RuntimeException(errMsg);

+         } catch (IOException e2) {

+             String errMsg = "Error rendering included content with id [" + expandedContentId + "] : " + e2.toString();

+             Debug.logError(e2, errMsg, module);

+             //throw new RuntimeException(errMsg);

+         }

+    }

+

+    public void renderSubContentEnd(Appendable writer, Map<String, Object> context, ModelScreenWidget.SubContent content) throws IOException {

+         String editMode = "Edit";

+         String editRequest = content.getEditRequest(context);

+         String enableEditName = content.getEnableEditName(context);

+         String enableEditValue = (String)context.get(enableEditName);

+         String expandedContentId = content.getContentId(context);

+         String expandedMapKey = content.getMapKey(context);

+         String urlString = "";

+         if (editRequest != null && editRequest.toUpperCase().indexOf("IMAGE") > 0) {

+             editMode += " Image";

+         }

+         if (UtilValidate.isNotEmpty(editRequest) && "true".equals(enableEditValue)) {

+             HttpServletResponse response = (HttpServletResponse) context.get("response");

+             HttpServletRequest request = (HttpServletRequest) context.get("request");

+             if (request != null && response != null) {

+                 if (editRequest.indexOf("?") < 0)  editRequest += "?";

+                 else editRequest += "&amp;";

+                 editRequest += "contentId=" + expandedContentId;

+                 if (UtilValidate.isNotEmpty(expandedMapKey)) {

+                     editRequest += "&amp;mapKey=" + expandedMapKey;

+                 }

+                 ServletContext ctx = (ServletContext) request.getAttribute("servletContext");

+                 RequestHandler rh = (RequestHandler) ctx.getAttribute("_REQUEST_HANDLER_");

+                 urlString = rh.makeLink(request, response, editRequest, false, false, false);

+             }

+         }

+

+         Map<String, Object> parameters = new HashMap<String, Object>();

+         parameters.put("urlString", urlString);

+         parameters.put("editMode", editMode);

+         parameters.put("editContainerStyle", content.getEditContainerStyle(context));

+         parameters.put("editRequest", editRequest);

+         parameters.put("enableEditValue", enableEditValue == null ? "" : enableEditValue);

+         executeMacro(writer, "renderSubContentEnd", parameters);

+    }

+

+

+    public void renderScreenletBegin(Appendable writer, Map<String, Object> context, boolean collapsed, ModelScreenWidget.Screenlet screenlet) throws IOException {

+        HttpServletRequest request = (HttpServletRequest) context.get("request");

+        HttpServletResponse response = (HttpServletResponse) context.get("response");

+        boolean javaScriptEnabled = UtilHttp.isJavaScriptEnabled(request);

+        ModelScreenWidget.Menu tabMenu = screenlet.getTabMenu();

+        if (tabMenu != null) {

+            tabMenu.renderWidgetString(writer, context, this);

+        }

+

+        String title = screenlet.getTitle(context);

+        boolean collapsible = screenlet.collapsible();

+        ModelScreenWidget.Menu navMenu = screenlet.getNavigationMenu();

+        ModelScreenWidget.Form navForm = screenlet.getNavigationForm();

+        String expandToolTip = "";

+        String collapseToolTip = "";

+        String fullUrlString = "";

+        String menuString = "";

+        boolean showMore = false;

+        if (UtilValidate.isNotEmpty(title) || navMenu != null || navForm != null || collapsible) {

+            showMore = true;

+            if (collapsible) {

+                this.getNextElementId();

+                Map<String, Object> uiLabelMap = UtilGenerics.checkMap(context.get("uiLabelMap"));

+                Map<String, Object> paramMap = UtilGenerics.checkMap(context.get("requestParameters"));

+                Map<String, Object> requestParameters = new HashMap<String, Object>(paramMap);

+                if (uiLabelMap != null) {

+                    expandToolTip = (String) uiLabelMap.get("CommonExpand");

+                    collapseToolTip = (String) uiLabelMap.get("CommonCollapse");

+                }

+                if (!javaScriptEnabled) {

+                    requestParameters.put(screenlet.getPreferenceKey(context) + "_collapsed", collapsed ? "false" : "true");

+                    String queryString = UtilHttp.urlEncodeArgs(requestParameters);

+                    fullUrlString = request.getRequestURI() + "?" + queryString;

+                }

+            }

+            StringWriter sb = new StringWriter();

+            if (navMenu != null) {

+                MenuStringRenderer savedRenderer = (MenuStringRenderer) context.get("menuStringRenderer");

+                MenuStringRenderer renderer = new ScreenletMenuRenderer(request, response);

+                context.put("menuStringRenderer", renderer);

+                navMenu.renderWidgetString(sb, context, this);

+                context.put("menuStringRenderer", savedRenderer);

+            } else if (navForm != null) {

+                renderScreenletPaginateMenu(sb, context, navForm);

+            }

+            menuString = sb.toString();

+        }

+

+        Map<String, Object> parameters = new HashMap<String, Object>();

+        parameters.put("title", title);

+        parameters.put("collapsible", collapsible);

+        parameters.put("saveCollapsed", screenlet.saveCollapsed());

+        if (UtilValidate.isNotEmpty (screenlet.getId(context))) {

+            parameters.put("id", screenlet.getId(context));

+            parameters.put("collapsibleAreaId", screenlet.getId(context) + "_col");

+        } else {

+            parameters.put("id", "screenlet_" + screenLetsIdCounter);

+            parameters.put("collapsibleAreaId","screenlet_" + screenLetsIdCounter + "_col");

+            screenLetsIdCounter++;

+        }

+        parameters.put("expandToolTip", expandToolTip);

+        parameters.put("collapseToolTip", collapseToolTip);

+        parameters.put("fullUrlString", fullUrlString);

+        parameters.put("padded", screenlet.padded());

+        parameters.put("menuString", menuString);

+        parameters.put("showMore", showMore);

+        parameters.put("collapsed", collapsed);

+        parameters.put("javaScriptEnabled", javaScriptEnabled);

+        executeMacro(writer, "renderScreenletBegin", parameters);

+    }

+

+    public void renderScreenletSubWidget(Appendable writer, Map<String, Object> context, ModelScreenWidget subWidget, ModelScreenWidget.Screenlet screenlet) throws GeneralException, IOException  {

+        if (subWidget.equals(screenlet.getNavigationForm())) {

+            HttpServletRequest request = (HttpServletRequest) context.get("request");

+            HttpServletResponse response = (HttpServletResponse) context.get("response");

+            if (request != null && response != null) {

+                Map<String, Object> globalCtx = UtilGenerics.checkMap(context.get("globalContext"));

+                globalCtx.put("NO_PAGINATOR", true);

+                FormStringRenderer savedRenderer = (FormStringRenderer) context.get("formStringRenderer");

+                MacroFormRenderer renderer = null;

+                try {

+                    renderer = new MacroFormRenderer(formrenderer, request, response);

+                } catch (TemplateException e) {

+                    Debug.logError("Not rendering content, error on MacroFormRenderer creation.", module);

+                }

+                renderer.setRenderPagination(false);

+                context.put("formStringRenderer", renderer);

+                subWidget.renderWidgetString(writer, context, this);

+                context.put("formStringRenderer", savedRenderer);

+            }

+        } else {

+            subWidget.renderWidgetString(writer, context, this);

+        }

+    }

+    public void renderScreenletEnd(Appendable writer, Map<String, Object> context, ModelScreenWidget.Screenlet screenlet) throws IOException {

+        executeMacro(writer, "renderScreenletEnd", null);

+    }

+

+    protected void renderScreenletPaginateMenu(Appendable writer, Map<String, Object> context, ModelScreenWidget.Form form) throws IOException {

+        HttpServletResponse response = (HttpServletResponse) context.get("response");

+        HttpServletRequest request = (HttpServletRequest) context.get("request");

+        ModelForm modelForm = form.getModelForm(context);

+        modelForm.runFormActions(context);

+        Paginator.preparePager(modelForm, context);

+        String targetService = modelForm.getPaginateTarget(context);

+        if (targetService == null) {

+            targetService = "${targetService}";

+        }

+

+        // get the parametrized pagination index and size fields

+        int paginatorNumber = WidgetWorker.getPaginatorNumber(context);

+        String viewIndexParam = modelForm.getMultiPaginateIndexField(context);

+        String viewSizeParam = modelForm.getMultiPaginateSizeField(context);

+

+        int viewIndex = Paginator.getViewIndex(modelForm, context);

+        int viewSize = Paginator.getViewSize(modelForm, context);

+        int listSize = Paginator.getListSize(context);

+

+        int highIndex = Paginator.getHighIndex(context);

+        int actualPageSize = Paginator.getActualPageSize(context);

+

+        // if this is all there seems to be (if listSize < 0, then size is unknown)

+        if (actualPageSize >= listSize && listSize >= 0) return;

+

+        // needed for the "Page" and "rows" labels

+        Map<String, String> uiLabelMap = UtilGenerics.cast(context.get("uiLabelMap"));

+        String ofLabel = "";

+        if (uiLabelMap == null) {

+            Debug.logWarning("Could not find uiLabelMap in context", module);

+        } else {

+            ofLabel = uiLabelMap.get("CommonOf");

+            ofLabel = ofLabel.toLowerCase();

+        }

+

+        // for legacy support, the viewSizeParam is VIEW_SIZE and viewIndexParam is VIEW_INDEX when the fields are "viewSize" and "viewIndex"

+        if (viewIndexParam.equals("viewIndex" + "_" + paginatorNumber)) viewIndexParam = "VIEW_INDEX" + "_" + paginatorNumber;

+        if (viewSizeParam.equals("viewSize" + "_" + paginatorNumber)) viewSizeParam = "VIEW_SIZE" + "_" + paginatorNumber;

+

+        ServletContext ctx = (ServletContext) request.getAttribute("servletContext");

+        RequestHandler rh = (RequestHandler) ctx.getAttribute("_REQUEST_HANDLER_");

+

+        Map<String, Object> inputFields = UtilGenerics.toMap(context.get("requestParameters"));

+        // strip out any multi form fields if the form is of type multi

+        if (modelForm.getType().equals("multi")) {

+            inputFields = UtilHttp.removeMultiFormParameters(inputFields);

+        }

+        String queryString = UtilHttp.urlEncodeArgs(inputFields);

+        // strip legacy viewIndex/viewSize params from the query string

+        queryString = UtilHttp.stripViewParamsFromQueryString(queryString, "" + paginatorNumber);

+        // strip parametrized index/size params from the query string

+        HashSet<String> paramNames = new HashSet<String>();

+        paramNames.add(viewIndexParam);

+        paramNames.add(viewSizeParam);

+        queryString = UtilHttp.stripNamedParamsFromQueryString(queryString, paramNames);

+

+        String anchor = "";

+        String paginateAnchor = modelForm.getPaginateTargetAnchor();

+        if (paginateAnchor != null) anchor = "#" + paginateAnchor;

+

+        // preparing the link text, so that later in the code we can reuse this and just add the viewIndex

+        String prepLinkText = "";

+        prepLinkText = targetService;

+        if (prepLinkText.indexOf("?") < 0) {

+            prepLinkText += "?";

+        } else if (!prepLinkText.endsWith("?")) {

+            prepLinkText += "&amp;";

+        }

+        if (!UtilValidate.isEmpty(queryString) && !queryString.equals("null")) {

+            prepLinkText += queryString + "&amp;";

+        }

+        prepLinkText += viewSizeParam + "=" + viewSize + "&amp;" + viewIndexParam + "=";

+

+        String linkText;

+

+

+        // The current screenlet title bar navigation syling requires rendering

+        // these links in reverse order

+        // Last button

+        String lastLinkUrl = "";

+        if (highIndex < listSize) {

+            int lastIndex = UtilMisc.getViewLastIndex(listSize, viewSize);

+            linkText = prepLinkText + lastIndex + anchor;

+            lastLinkUrl = rh.makeLink(request, response, linkText);

+        }

+        String nextLinkUrl = "";

+        if (highIndex < listSize) {

+            linkText = prepLinkText + (viewIndex + 1) + anchor;

+            // - make the link

+            nextLinkUrl = rh.makeLink(request, response, linkText);

+        }

+        String previousLinkUrl = "";

+        if (viewIndex > 0) {

+            linkText = prepLinkText + (viewIndex - 1) + anchor;

+            previousLinkUrl = rh.makeLink(request, response, linkText);

+        }

+        String firstLinkUrl = "";

+        if (viewIndex > 0) {

+            linkText = prepLinkText + 0 + anchor;

+            firstLinkUrl = rh.makeLink(request, response, linkText);

+        }

+

+        Map<String, Object> parameters = new HashMap<String, Object>();

+        parameters.put("lowIndex", Paginator.getLowIndex(context));

+        parameters.put("actualPageSize", actualPageSize);

+        parameters.put("ofLabel", ofLabel);

+        parameters.put("listSize", listSize);

+        parameters.put("paginateLastStyle", modelForm.getPaginateLastStyle());

+        parameters.put("lastLinkUrl", lastLinkUrl);

+        parameters.put("paginateLastLabel", modelForm.getPaginateLastLabel(context));

+        parameters.put("paginateNextStyle", modelForm.getPaginateNextStyle());

+        parameters.put("nextLinkUrl", nextLinkUrl);

+        parameters.put("paginateNextLabel", modelForm.getPaginateNextLabel(context));

+        parameters.put("paginatePreviousStyle", modelForm.getPaginatePreviousStyle());

+        parameters.put("paginatePreviousLabel", modelForm.getPaginatePreviousLabel(context));

+        parameters.put("previousLinkUrl", previousLinkUrl);

+        parameters.put("paginateFirstStyle", modelForm.getPaginateFirstStyle());

+        parameters.put("paginateFirstLabel", modelForm.getPaginateFirstLabel(context));

+        parameters.put("firstLinkUrl", firstLinkUrl);

+        executeMacro(writer, "renderScreenletPaginateMenu", parameters);

+    }

+

+    public void renderPortalPageBegin(Appendable writer, Map<String, Object> context, ModelScreenWidget.PortalPage portalPage) throws GeneralException, IOException {

+        String portalPageId = portalPage.getActualPortalPageId(context);

+        String originalPortalPageId = portalPage.getOriginalPortalPageId(context);

+        String confMode = portalPage.getConfMode(context);

+

+        Map<String, String> uiLabelMap = UtilGenerics.cast(context.get("uiLabelMap"));

+        String addColumnLabel = "";

+        String addColumnHint = "";

+        if (uiLabelMap == null) {

+            Debug.logWarning("Could not find uiLabelMap in context", module);

+        } else {

+            addColumnLabel = uiLabelMap.get("CommonAddColumn");

+            addColumnHint = uiLabelMap.get("CommonAddAColumnToThisPortalPage");

+        }

+

+        StringWriter sr = new StringWriter();

+        sr.append("<@renderPortalPageBegin ");

+        sr.append("originalPortalPageId=\"");

+        sr.append(originalPortalPageId);

+        sr.append("\" portalPageId=\"");

+        sr.append(portalPageId);

+        sr.append("\" confMode=\"");

+        sr.append(confMode);

+        sr.append("\" addColumnLabel=\"");

+        sr.append(addColumnLabel);

+        sr.append("\" addColumnHint=\"");

+        sr.append(addColumnHint);

+        sr.append("\" />");

+        executeMacro(writer, sr.toString());

+    }

+

+    public void renderPortalPageEnd(Appendable writer, Map<String, Object> context, ModelScreenWidget.PortalPage portalPage) throws GeneralException, IOException {

+        StringWriter sr = new StringWriter();

+        sr.append("<@renderPortalPageEnd/>");

+        executeMacro(writer, sr.toString());

+    }

+

+    public void renderPortalPageColumnBegin(Appendable writer, Map<String, Object> context, ModelScreenWidget.PortalPage portalPage, GenericValue portalPageColumn) throws GeneralException, IOException {

+        String portalPageId = portalPage.getActualPortalPageId(context);

+        String originalPortalPageId = portalPage.getOriginalPortalPageId(context);

+        String columnSeqId = portalPageColumn.getString("columnSeqId");

+        String columnWidthPercentage = portalPageColumn.getString("columnWidthPercentage");

+        String columnWidthPixels = portalPageColumn.getString("columnWidthPixels");

+        String confMode = portalPage.getConfMode(context);

+

+        Map<String, String> uiLabelMap = UtilGenerics.cast(context.get("uiLabelMap"));

+        String delColumnLabel = "";

+        String delColumnHint = "";

+        String addPortletLabel = "";

+        String addPortletHint = "";

+        String colWidthLabel = "";

+        String setColumnSizeHint = "";

+        

+        if (uiLabelMap == null) {

+            Debug.logWarning("Could not find uiLabelMap in context", module);

+        } else {

+            delColumnLabel = uiLabelMap.get("CommonDeleteColumn");

+            delColumnHint = uiLabelMap.get("CommonDeleteThisColumn");

+

+            addPortletLabel = uiLabelMap.get("CommonAddAPortlet");

+            addPortletHint = uiLabelMap.get("CommonAddPortletToPage");

+            colWidthLabel = uiLabelMap.get("CommonWidth");

+            setColumnSizeHint = uiLabelMap.get("CommonSetColumnWidth");

+        }

+

+        StringWriter sr = new StringWriter();

+        sr.append("<@renderPortalPageColumnBegin ");

+        sr.append("originalPortalPageId=\"");

+        sr.append(originalPortalPageId);

+        sr.append("\" portalPageId=\"");

+        sr.append(portalPageId);

+        sr.append("\" columnSeqId=\"");

+        sr.append(columnSeqId);

+        sr.append("\" ");

+        if (UtilValidate.isNotEmpty(columnWidthPixels)) {

+            sr.append("width=\"");

+            sr.append(columnWidthPixels);

+            sr.append("px\"");

+        } else if (UtilValidate.isNotEmpty(columnWidthPercentage)) {

+            sr.append("width=\"");

+            sr.append(columnWidthPercentage);

+            sr.append("%\"");

+        }

+        sr.append(" confMode=\"");

+        sr.append(confMode);

+        sr.append("\" delColumnLabel=\"");

+        sr.append(delColumnLabel);

+        sr.append("\" delColumnHint=\"");

+        sr.append(delColumnHint);

+        sr.append("\" addPortletLabel=\"");

+        sr.append(addPortletLabel);

+        sr.append("\" addPortletHint=\"");

+        sr.append(addPortletHint);

+        sr.append("\" colWidthLabel=\"");

+        sr.append(colWidthLabel);

+        sr.append("\" setColumnSizeHint=\"");

+        sr.append(setColumnSizeHint);

+        sr.append("\" />");

+        executeMacro(writer, sr.toString());

+    }   

+

+    public void renderPortalPageColumnEnd(Appendable writer, Map<String, Object> context, ModelScreenWidget.PortalPage portalPage, GenericValue portalPageColumn) throws GeneralException, IOException {

+        StringWriter sr = new StringWriter();

+        sr.append("<@renderPortalPageColumnEnd/>");

+        executeMacro(writer, sr.toString());

+    }

+

+    public void renderPortalPagePortletBegin(Appendable writer, Map<String, Object> context, ModelScreenWidget.PortalPage portalPage, GenericValue portalPortlet) throws GeneralException, IOException {

+        String portalPageId = portalPage.getActualPortalPageId(context);

+        String originalPortalPageId = portalPage.getOriginalPortalPageId(context);

+        String portalPortletId = portalPortlet.getString("portalPortletId");

+        String portletSeqId = portalPortlet.getString("portletSeqId");

+        String columnSeqId = portalPortlet.getString("columnSeqId");

+        String confMode = portalPage.getConfMode(context);

+        String editFormName = portalPortlet.getString("editFormName");

+        String editFormLocation = portalPortlet.getString("editFormLocation");

+

+        String prevPortletId = (String) context.get("prevPortletId");

+        String prevPortletSeqId = (String) context.get("prevPortletSeqId");

+        String nextPortletId = (String) context.get("nextPortletId");

+        String nextPortletSeqId = (String) context.get("nextPortletSeqId");

+        String prevColumnSeqId = (String) context.get("prevColumnSeqId");

+        String nextColumnSeqId = (String) context.get("nextColumnSeqId");

+

+        Map<String, String> uiLabelMap = UtilGenerics.cast(context.get("uiLabelMap"));

+        String delPortletHint = "";

+        String editAttributeHint = "";

+        if (uiLabelMap == null) {

+            Debug.logWarning("Could not find uiLabelMap in context", module);

+        } else {

+            delPortletHint = uiLabelMap.get("CommonDeleteThisPortlet");

+            editAttributeHint = uiLabelMap.get("CommonEditPortletAttributes");

+        }

+

+        StringWriter sr = new StringWriter();

+        sr.append("<@renderPortalPagePortletBegin ");

+        sr.append("originalPortalPageId=\"");

+        sr.append(originalPortalPageId);

+        sr.append("\" portalPageId=\"");

+        sr.append(portalPageId);

+        sr.append("\" portalPortletId=\"");

+        sr.append(portalPortletId);

+        sr.append("\" portletSeqId=\"");

+        sr.append(portletSeqId);

+        sr.append("\" prevPortletId=\"");

+        sr.append(prevPortletId);

+        sr.append("\" prevPortletSeqId=\"");

+        sr.append(prevPortletSeqId);

+        sr.append("\" nextPortletId=\"");

+        sr.append(nextPortletId);

+        sr.append("\" nextPortletSeqId=\"");

+        sr.append(nextPortletSeqId);

+        sr.append("\" columnSeqId=\"");

+        sr.append(columnSeqId);

+        sr.append("\" prevColumnSeqId=\"");

+        sr.append(prevColumnSeqId);

+        sr.append("\" nextColumnSeqId=\"");

+        sr.append(nextColumnSeqId);

+        sr.append("\" delPortletHint=\"");

+        sr.append(delPortletHint);

+        sr.append("\" editAttributeHint=\"");

+        sr.append(editAttributeHint);

+        sr.append("\" confMode=\"");

+        sr.append(confMode);

+        sr.append("\"");

+        if (UtilValidate.isNotEmpty(editFormName) && UtilValidate.isNotEmpty(editFormLocation)) {

+            sr.append(" editAttribute=\"true\"");

+        }

+        sr.append("/>");

+        executeMacro(writer, sr.toString());

+    }

+

+    public void renderPortalPagePortletEnd(Appendable writer, Map<String, Object> context, ModelScreenWidget.PortalPage portalPage, GenericValue portalPortlet) throws GeneralException, IOException {

+        String confMode = portalPage.getConfMode(context);

+

+        StringWriter sr = new StringWriter();

+        sr.append("<@renderPortalPagePortletEnd ");

+        sr.append(" confMode=\"");

+        sr.append(confMode);

+        sr.append("\" />");

+        executeMacro(writer, sr.toString());

+    }

+

+    public void renderPortalPagePortletBody(Appendable writer, Map<String, Object> context, ModelScreenWidget.PortalPage portalPage, GenericValue portalPortlet) throws GeneralException, IOException {

+        String portalPortletId = portalPortlet.getString("portalPortletId");

+        String screenName = portalPortlet.getString("screenName");

+        String screenLocation = portalPortlet.getString("screenLocation");

+

+        ModelScreen modelScreen = null;

+        if (UtilValidate.isNotEmpty(screenName) && UtilValidate.isNotEmpty(screenLocation)) {

+            try {

+                modelScreen = ScreenFactory.getScreenFromLocation(screenLocation, screenName);

+            } catch (IOException e) {

+                String errMsg = "Error rendering portlet ID [" + portalPortletId + "]: " + e.toString();

+                Debug.logError(e, errMsg, module);

+                throw new RuntimeException(errMsg);

+            } catch (SAXException e) {

+                String errMsg = "Error rendering portlet ID [" + portalPortletId + "]: " + e.toString();

+                Debug.logError(e, errMsg, module);

+                throw new RuntimeException(errMsg);

+            } catch (ParserConfigurationException e) {

+                String errMsg = "Error rendering portlet ID [" + portalPortletId + "]: " + e.toString();

+                Debug.logError(e, errMsg, module);

+                throw new RuntimeException(errMsg);

+            }

+        }

+        modelScreen.renderScreenString(writer, context, this);

+    }

+

+    @Override

+    public void renderColumnContainer(Appendable writer, Map<String, Object> context, ColumnContainer columnContainer) throws IOException {

+        String id = columnContainer.getId(context);

+        String style = columnContainer.getStyle(context);

+        StringBuilder sb = new StringBuilder("<@renderColumnContainerBegin");

+        sb.append(" id=\"");

+        sb.append(id);

+        sb.append("\" style=\"");

+        sb.append(style);

+        sb.append("\" />");

+        executeMacro(writer, sb.toString());

+        for (Column column : columnContainer.getColumns()) {

+            id = column.getId(context);

+            style = column.getStyle(context);

+            sb = new StringBuilder("<@renderColumnBegin");

+            sb.append(" id=\"");

+            sb.append(id);

+            sb.append("\" style=\"");

+            sb.append(style);

+            sb.append("\" />");

+            executeMacro(writer, sb.toString());

+            for (ModelScreenWidget subWidget : column.getSubWidgets()) {

+                try {

+                    subWidget.renderWidgetString(writer, context, this);

+                } catch (GeneralException e) {

+                    throw new IOException(e);

+                }

+            }

+            executeMacro(writer, "<@renderColumnEnd />");

+        }

+        executeMacro(writer, "<@renderColumnContainerEnd />");

+    }

+}

diff --git a/framework/widget/src/org/ofbiz/widget/screen/MacroScreenViewHandler.java b/framework/widget/src/org/ofbiz/widget/renderer/macro/MacroScreenViewHandler.java
similarity index 96%
rename from framework/widget/src/org/ofbiz/widget/screen/MacroScreenViewHandler.java
rename to framework/widget/src/org/ofbiz/widget/renderer/macro/MacroScreenViewHandler.java
index d6f1290..b431fd7 100644
--- a/framework/widget/src/org/ofbiz/widget/screen/MacroScreenViewHandler.java
+++ b/framework/widget/src/org/ofbiz/widget/renderer/macro/MacroScreenViewHandler.java
@@ -1,168 +1,167 @@
-/*******************************************************************************
- * 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.screen;
-
-import java.io.IOException;
-import java.io.Writer;
-import java.util.List;
-import java.util.Map;
-
-import javax.servlet.ServletContext;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import javax.xml.parsers.ParserConfigurationException;
-
-import org.ofbiz.base.util.Debug;
-import org.ofbiz.base.util.GeneralException;
-import org.ofbiz.base.util.UtilCodec;
-import org.ofbiz.base.util.UtilGenerics;
-import org.ofbiz.base.util.UtilProperties;
-import org.ofbiz.base.util.UtilValidate;
-import org.ofbiz.base.util.collections.MapStack;
-import org.ofbiz.entity.Delegator;
-import org.ofbiz.entity.util.EntityUtilProperties;
-import org.ofbiz.service.LocalDispatcher;
-import org.ofbiz.service.ModelService;
-import org.ofbiz.service.ServiceUtil;
-import org.ofbiz.webapp.view.AbstractViewHandler;
-import org.ofbiz.webapp.view.ViewHandlerException;
-import org.ofbiz.widget.form.FormStringRenderer;
-import org.ofbiz.widget.form.MacroFormRenderer;
-import org.ofbiz.widget.menu.MacroMenuRenderer;
-import org.ofbiz.widget.menu.MenuStringRenderer;
-import org.ofbiz.widget.tree.MacroTreeRenderer;
-import org.ofbiz.widget.tree.TreeStringRenderer;
-import org.xml.sax.SAXException;
-
-import freemarker.template.TemplateException;
-import freemarker.template.utility.StandardCompress;
-
-public class MacroScreenViewHandler extends AbstractViewHandler {
-
-    public static final String module = MacroScreenViewHandler.class.getName();
-
-    protected ServletContext servletContext = null;
-
-    public void init(ServletContext context) throws ViewHandlerException {
-        this.servletContext = context;
-    }
-
-    private ScreenStringRenderer loadRenderers(HttpServletRequest request, HttpServletResponse response,
-            Map<String, Object> context, Writer writer) throws GeneralException, TemplateException, IOException {
-        String screenMacroLibraryPath = UtilProperties.getPropertyValue("widget", getName() + ".screenrenderer");
-        String formMacroLibraryPath = UtilProperties.getPropertyValue("widget", getName() + ".formrenderer");
-        String treeMacroLibraryPath = UtilProperties.getPropertyValue("widget", getName() + ".treerenderer");
-        String menuMacroLibraryPath = UtilProperties.getPropertyValue("widget", getName() + ".menurenderer");
-        Map<String, Object> userPreferences = UtilGenerics.cast(context.get("userPreferences"));
-        if (userPreferences != null) {
-            String visualThemeId = (String) userPreferences.get("VISUAL_THEME");
-            if (visualThemeId != null) {
-                LocalDispatcher dispatcher = (LocalDispatcher) context.get("dispatcher");
-                Map<String, Object> serviceCtx = dispatcher.getDispatchContext().makeValidContext("getVisualThemeResources",
-                        ModelService.IN_PARAM, context);
-                serviceCtx.put("visualThemeId", visualThemeId);
-                Map<String, Object> serviceResult = dispatcher.runSync("getVisualThemeResources", serviceCtx);
-                if (ServiceUtil.isSuccess(serviceResult)) {
-                    Map<String, List<String>> themeResources = UtilGenerics.cast(serviceResult.get("themeResources"));
-                    List<String> resourceList = UtilGenerics.cast(themeResources.get("VT_SCRN_MACRO_LIB"));
-                    if (resourceList != null && !resourceList.isEmpty()) {
-                        String macroLibraryPath = resourceList.get(0);
-                        if (macroLibraryPath != null) {
-                            screenMacroLibraryPath = macroLibraryPath;
-                        }
-                    }
-                    resourceList = UtilGenerics.cast(themeResources.get("VT_FORM_MACRO_LIB"));
-                    if (resourceList != null && !resourceList.isEmpty()) {
-                        String macroLibraryPath = resourceList.get(0);
-                        if (macroLibraryPath != null) {
-                            formMacroLibraryPath = macroLibraryPath;
-                        }
-                    }
-                    resourceList = UtilGenerics.cast(themeResources.get("VT_TREE_MACRO_LIB"));
-                    if (resourceList != null && !resourceList.isEmpty()) {
-                        String macroLibraryPath = resourceList.get(0);
-                        if (macroLibraryPath != null) {
-                            treeMacroLibraryPath = macroLibraryPath;
-                        }
-                    }
-                    resourceList = UtilGenerics.cast(themeResources.get("VT_MENU_MACRO_LIB"));
-                    if (resourceList != null && !resourceList.isEmpty()) {
-                        String macroLibraryPath = resourceList.get(0);
-                        if (macroLibraryPath != null) {
-                            menuMacroLibraryPath = macroLibraryPath;
-                        }
-                    }
-                }
-            }
-        }
-        ScreenStringRenderer screenStringRenderer = new MacroScreenRenderer(UtilProperties.getPropertyValue("widget", getName()
-                + ".name"), screenMacroLibraryPath);
-        FormStringRenderer formStringRenderer = new MacroFormRenderer(formMacroLibraryPath, request, response);
-        context.put("formStringRenderer", formStringRenderer);
-        TreeStringRenderer treeStringRenderer = new MacroTreeRenderer(treeMacroLibraryPath, writer);
-        context.put("treeStringRenderer", treeStringRenderer);
-        MenuStringRenderer menuStringRenderer = new MacroMenuRenderer(menuMacroLibraryPath, request, response);
-        context.put("menuStringRenderer", menuStringRenderer);
-        return screenStringRenderer;
-    }
-
-    public void render(String name, String page, String info, String contentType, String encoding, HttpServletRequest request, HttpServletResponse response) throws ViewHandlerException {
-        try {
-            Writer writer = response.getWriter();
-            Delegator delegator = (Delegator) request.getAttribute("delegator");
-            // compress output if configured to do so
-            if (UtilValidate.isEmpty(encoding)) {
-                encoding = EntityUtilProperties.getPropertyValue("widget", getName() + ".default.encoding", "none", delegator);
-            }
-            boolean compressOutput = "compressed".equals(encoding);
-            if (!compressOutput) {
-                compressOutput = "true".equals(EntityUtilProperties.getPropertyValue("widget", getName() + ".compress", delegator));
-            }
-            if (!compressOutput && this.servletContext != null) {
-                compressOutput = "true".equals(this.servletContext.getAttribute("compressHTML"));
-            }
-            if (compressOutput) {
-                // StandardCompress defaults to a 2k buffer. That could be increased
-                // to speed up output.
-                writer = new StandardCompress().getWriter(writer, null);
-            }
-            MapStack<String> context = MapStack.create();
-            ScreenRenderer.populateContextForRequest(context, null, request, response, servletContext);
-            ScreenStringRenderer screenStringRenderer = loadRenderers(request, response, context, writer);
-            ScreenRenderer screens = new ScreenRenderer(writer, context, screenStringRenderer);
-            context.put("screens", screens);
-            context.put("simpleEncoder", UtilCodec.getEncoder(UtilProperties.getPropertyValue("widget", getName() + ".encoder")));
-            screenStringRenderer.renderScreenBegin(writer, context);
-            screens.render(page);
-            screenStringRenderer.renderScreenEnd(writer, context);
-            writer.flush();
-        } catch (TemplateException e) {
-            Debug.logError(e, "Error initializing screen renderer", module);
-            throw new ViewHandlerException(e.getMessage());
-        } catch (IOException e) {
-            throw new ViewHandlerException("Error in the response writer/output stream: " + e.toString(), e);
-        } catch (SAXException e) {
-            throw new ViewHandlerException("XML Error rendering page: " + e.toString(), e);
-        } catch (ParserConfigurationException e) {
-            throw new ViewHandlerException("XML Error rendering page: " + e.toString(), e);
-        } catch (GeneralException e) {
-            throw new ViewHandlerException("Lower level error rendering page: " + e.toString(), e);
-        }
-    }
-}
+/*******************************************************************************

+ * 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.renderer.macro;

+

+import java.io.IOException;

+import java.io.Writer;

+import java.util.List;

+import java.util.Map;

+

+import javax.servlet.ServletContext;

+import javax.servlet.http.HttpServletRequest;

+import javax.servlet.http.HttpServletResponse;

+import javax.xml.parsers.ParserConfigurationException;

+

+import org.ofbiz.base.util.Debug;

+import org.ofbiz.base.util.GeneralException;

+import org.ofbiz.base.util.UtilCodec;

+import org.ofbiz.base.util.UtilGenerics;

+import org.ofbiz.base.util.UtilProperties;

+import org.ofbiz.base.util.UtilValidate;

+import org.ofbiz.base.util.collections.MapStack;

+import org.ofbiz.entity.Delegator;

+import org.ofbiz.entity.util.EntityUtilProperties;

+import org.ofbiz.service.LocalDispatcher;

+import org.ofbiz.service.ModelService;

+import org.ofbiz.service.ServiceUtil;

+import org.ofbiz.webapp.view.AbstractViewHandler;

+import org.ofbiz.webapp.view.ViewHandlerException;

+import org.ofbiz.widget.renderer.FormStringRenderer;

+import org.ofbiz.widget.renderer.MenuStringRenderer;

+import org.ofbiz.widget.renderer.ScreenRenderer;

+import org.ofbiz.widget.renderer.ScreenStringRenderer;

+import org.ofbiz.widget.renderer.TreeStringRenderer;

+import org.xml.sax.SAXException;

+

+import freemarker.template.TemplateException;

+import freemarker.template.utility.StandardCompress;

+

+public class MacroScreenViewHandler extends AbstractViewHandler {

+

+    public static final String module = MacroScreenViewHandler.class.getName();

+

+    protected ServletContext servletContext = null;

+

+    public void init(ServletContext context) throws ViewHandlerException {

+        this.servletContext = context;

+    }

+

+    private ScreenStringRenderer loadRenderers(HttpServletRequest request, HttpServletResponse response,

+            Map<String, Object> context, Writer writer) throws GeneralException, TemplateException, IOException {

+        String screenMacroLibraryPath = UtilProperties.getPropertyValue("widget", getName() + ".screenrenderer");

+        String formMacroLibraryPath = UtilProperties.getPropertyValue("widget", getName() + ".formrenderer");

+        String treeMacroLibraryPath = UtilProperties.getPropertyValue("widget", getName() + ".treerenderer");

+        String menuMacroLibraryPath = UtilProperties.getPropertyValue("widget", getName() + ".menurenderer");

+        Map<String, Object> userPreferences = UtilGenerics.cast(context.get("userPreferences"));

+        if (userPreferences != null) {

+            String visualThemeId = (String) userPreferences.get("VISUAL_THEME");

+            if (visualThemeId != null) {

+                LocalDispatcher dispatcher = (LocalDispatcher) context.get("dispatcher");

+                Map<String, Object> serviceCtx = dispatcher.getDispatchContext().makeValidContext("getVisualThemeResources",

+                        ModelService.IN_PARAM, context);

+                serviceCtx.put("visualThemeId", visualThemeId);

+                Map<String, Object> serviceResult = dispatcher.runSync("getVisualThemeResources", serviceCtx);

+                if (ServiceUtil.isSuccess(serviceResult)) {

+                    Map<String, List<String>> themeResources = UtilGenerics.cast(serviceResult.get("themeResources"));

+                    List<String> resourceList = UtilGenerics.cast(themeResources.get("VT_SCRN_MACRO_LIB"));

+                    if (resourceList != null && !resourceList.isEmpty()) {

+                        String macroLibraryPath = resourceList.get(0);

+                        if (macroLibraryPath != null) {

+                            screenMacroLibraryPath = macroLibraryPath;

+                        }

+                    }

+                    resourceList = UtilGenerics.cast(themeResources.get("VT_FORM_MACRO_LIB"));

+                    if (resourceList != null && !resourceList.isEmpty()) {

+                        String macroLibraryPath = resourceList.get(0);

+                        if (macroLibraryPath != null) {

+                            formMacroLibraryPath = macroLibraryPath;

+                        }

+                    }

+                    resourceList = UtilGenerics.cast(themeResources.get("VT_TREE_MACRO_LIB"));

+                    if (resourceList != null && !resourceList.isEmpty()) {

+                        String macroLibraryPath = resourceList.get(0);

+                        if (macroLibraryPath != null) {

+                            treeMacroLibraryPath = macroLibraryPath;

+                        }

+                    }

+                    resourceList = UtilGenerics.cast(themeResources.get("VT_MENU_MACRO_LIB"));

+                    if (resourceList != null && !resourceList.isEmpty()) {

+                        String macroLibraryPath = resourceList.get(0);

+                        if (macroLibraryPath != null) {

+                            menuMacroLibraryPath = macroLibraryPath;

+                        }

+                    }

+                }

+            }

+        }

+        ScreenStringRenderer screenStringRenderer = new MacroScreenRenderer(UtilProperties.getPropertyValue("widget", getName()

+                + ".name"), screenMacroLibraryPath);

+        FormStringRenderer formStringRenderer = new MacroFormRenderer(formMacroLibraryPath, request, response);

+        context.put("formStringRenderer", formStringRenderer);

+        TreeStringRenderer treeStringRenderer = new MacroTreeRenderer(treeMacroLibraryPath, writer);

+        context.put("treeStringRenderer", treeStringRenderer);

+        MenuStringRenderer menuStringRenderer = new MacroMenuRenderer(menuMacroLibraryPath, request, response);

+        context.put("menuStringRenderer", menuStringRenderer);

+        return screenStringRenderer;

+    }

+

+    public void render(String name, String page, String info, String contentType, String encoding, HttpServletRequest request, HttpServletResponse response) throws ViewHandlerException {

+        try {

+            Writer writer = response.getWriter();

+            Delegator delegator = (Delegator) request.getAttribute("delegator");

+            // compress output if configured to do so

+            if (UtilValidate.isEmpty(encoding)) {

+                encoding = EntityUtilProperties.getPropertyValue("widget", getName() + ".default.encoding", "none", delegator);

+            }

+            boolean compressOutput = "compressed".equals(encoding);

+            if (!compressOutput) {

+                compressOutput = "true".equals(EntityUtilProperties.getPropertyValue("widget", getName() + ".compress", delegator));

+            }

+            if (!compressOutput && this.servletContext != null) {

+                compressOutput = "true".equals(this.servletContext.getAttribute("compressHTML"));

+            }

+            if (compressOutput) {

+                // StandardCompress defaults to a 2k buffer. That could be increased

+                // to speed up output.

+                writer = new StandardCompress().getWriter(writer, null);

+            }

+            MapStack<String> context = MapStack.create();

+            ScreenRenderer.populateContextForRequest(context, null, request, response, servletContext);

+            ScreenStringRenderer screenStringRenderer = loadRenderers(request, response, context, writer);

+            ScreenRenderer screens = new ScreenRenderer(writer, context, screenStringRenderer);

+            context.put("screens", screens);

+            context.put("simpleEncoder", UtilCodec.getEncoder(UtilProperties.getPropertyValue("widget", getName() + ".encoder")));

+            screenStringRenderer.renderScreenBegin(writer, context);

+            screens.render(page);

+            screenStringRenderer.renderScreenEnd(writer, context);

+            writer.flush();

+        } catch (TemplateException e) {

+            Debug.logError(e, "Error initializing screen renderer", module);

+            throw new ViewHandlerException(e.getMessage());

+        } catch (IOException e) {

+            throw new ViewHandlerException("Error in the response writer/output stream: " + e.toString(), e);

+        } catch (SAXException e) {

+            throw new ViewHandlerException("XML Error rendering page: " + e.toString(), e);

+        } catch (ParserConfigurationException e) {

+            throw new ViewHandlerException("XML Error rendering page: " + e.toString(), e);

+        } catch (GeneralException e) {

+            throw new ViewHandlerException("Lower level error rendering page: " + e.toString(), e);

+        }

+    }

+}

diff --git a/framework/widget/src/org/ofbiz/widget/tree/MacroTreeRenderer.java b/framework/widget/src/org/ofbiz/widget/renderer/macro/MacroTreeRenderer.java
similarity index 97%
rename from framework/widget/src/org/ofbiz/widget/tree/MacroTreeRenderer.java
rename to framework/widget/src/org/ofbiz/widget/renderer/macro/MacroTreeRenderer.java
index 24d3f5c..07ed850 100644
--- a/framework/widget/src/org/ofbiz/widget/tree/MacroTreeRenderer.java
+++ b/framework/widget/src/org/ofbiz/widget/renderer/macro/MacroTreeRenderer.java
@@ -1,370 +1,370 @@
-/*******************************************************************************
- * 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.tree;
-
-import java.io.IOException;
-import java.io.Reader;
-import java.io.StringReader;
-import java.io.StringWriter;
-import java.util.List;
-import java.util.Map;
-
-import javax.servlet.ServletContext;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-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.UtilValidate;
-import org.ofbiz.base.util.template.FreeMarkerWorker;
-import org.ofbiz.webapp.control.RequestHandler;
-import org.ofbiz.webapp.taglib.ContentUrlTag;
-import org.ofbiz.widget.ModelWidget;
-import org.ofbiz.widget.WidgetWorker;
-import org.ofbiz.widget.screen.ScreenRenderer;
-import org.ofbiz.widget.screen.ScreenStringRenderer;
-import org.ofbiz.widget.tree.ModelTree;
-import org.ofbiz.widget.tree.TreeStringRenderer;
-
-import freemarker.core.Environment;
-import freemarker.template.Template;
-import freemarker.template.TemplateException;
-
-/**
- * Widget Library - Tree Renderer implementation based on Freemarker macros
- * 
- */
-public class MacroTreeRenderer implements TreeStringRenderer {
-
-    public static final String module = MacroTreeRenderer.class.getName();
-    private Template macroLibrary;
-    private Environment environment;
-
-
-    public MacroTreeRenderer(String macroLibraryPath, Appendable writer) throws TemplateException, IOException {
-        this.macroLibrary = FreeMarkerWorker.getTemplate(macroLibraryPath);
-        Map<String, Object> input = UtilMisc.toMap("key", null);
-        this.environment = FreeMarkerWorker.renderTemplate(this.macroLibrary, input, writer);
-    }
-
-    private void executeMacro(String macro) throws IOException {
-        try {
-            Reader templateReader = new StringReader(macro);
-            // FIXME: I am using a Date as an hack to provide a unique name for the template...
-            Template template = new Template((new java.util.Date()).toString(), templateReader,
-                    FreeMarkerWorker.getDefaultOfbizConfig());
-            templateReader.close();
-            this.environment.include(template);
-        } catch (TemplateException e) {
-            Debug.logError(e, "Error rendering tree thru ftl", module);
-        } catch (IOException e) {
-            Debug.logError(e, "Error rendering tree thru ftl", module);
-        }
-    }
- 
-    /**
-     * Renders the beginning boundary comment string.
-     * @param writer The writer to write to
-     * @param widgetType The widget type: "Screen Widget", "Tree Widget", etc.
-     * @param modelWidget The widget
-     */
-    public void renderBeginningBoundaryComment(Appendable writer, String widgetType, ModelWidget modelWidget) throws IOException {
-        StringWriter sr = new StringWriter();
-        sr.append("<@formatBoundaryComment ");
-        sr.append(" boundaryType=\"");
-        sr.append("Begin");
-        sr.append("\" widgetType=\"");
-        sr.append(widgetType);
-        sr.append("\" widgetName=\"");
-        sr.append(modelWidget.getBoundaryCommentName());
-        sr.append("\" />");
-        executeMacro(sr.toString());
-    }
-    
-    /**
-     * Renders the ending boundary comment string.
-     * @param writer The writer to write to
-     * @param widgetType The widget type: "Screen Widget", "Tree Widget", etc.
-     * @param modelWidget The widget
-     */
-    public void renderEndingBoundaryComment(Appendable writer, String widgetType, ModelWidget modelWidget) throws IOException {
-        StringWriter sr = new StringWriter();
-        sr.append("<@formatBoundaryComment ");
-        sr.append(" boundaryType=\"");
-        sr.append("End");
-        sr.append("\" widgetType=\"");
-        sr.append(widgetType);
-        sr.append("\" widgetName=\"");
-        sr.append(modelWidget.getBoundaryCommentName());
-        sr.append("\" />");
-        executeMacro(sr.toString());
-    }
-    
-    public void renderNodeBegin(Appendable writer, Map<String, Object> context, ModelTree.ModelNode node, int depth) throws IOException {
-        String currentNodeTrailPiped = null;
-        List<String> currentNodeTrail = UtilGenerics.toList(context.get("currentNodeTrail"));
-        
-        String style = "";
-        if (node.isRootNode()) {
-            if (ModelWidget.widgetBoundaryCommentsEnabled(context)) {
-                renderBeginningBoundaryComment(writer, "Tree Widget", node.getModelTree());
-            }
-            style = "basic-tree";
-        }
- 
-        StringWriter sr = new StringWriter();
-        sr.append("<@renderNodeBegin ");
-        sr.append(" style=\"");
-        sr.append(style);
-        sr.append("\" />");
-        executeMacro(sr.toString());
-
-        String pkName = node.getPkName(context);
-        String entityId = null;
-        String entryName = node.getEntryName();
-        if (UtilValidate.isNotEmpty(entryName)) {
-            Map<String, String> map = UtilGenerics.checkMap(context.get(entryName));
-            entityId = map.get(pkName);
-        } else {
-            entityId = (String) context.get(pkName);
-        }
-        boolean hasChildren = node.hasChildren(context);
-
-        // check to see if this node needs to be expanded.
-        if (hasChildren && node.isExpandCollapse()) {
-            // FIXME: Using a widget model in this way is an ugly hack.
-            ModelTree.ModelNode.Link expandCollapseLink = null;
-            String targetEntityId = null;
-            List<String> targetNodeTrail = UtilGenerics.toList(context.get("targetNodeTrail"));
-            if (depth < targetNodeTrail.size()) {
-                targetEntityId = targetNodeTrail.get(depth);
-            }
-
-            int openDepth = node.getModelTree().getOpenDepth();
-            if (depth >= openDepth && (targetEntityId == null || !targetEntityId.equals(entityId))) {
-                // Not on the trail
-                if (node.showPeers(depth, context)) {
-                    context.put("processChildren", Boolean.FALSE);
-                    //expandCollapseLink.setText("&nbsp;+&nbsp;");
-                    currentNodeTrailPiped = StringUtil.join(currentNodeTrail, "|");
-                    StringBuilder target = new StringBuilder(node.getModelTree().getExpandCollapseRequest(context));
-                    String trailName = node.getModelTree().getTrailName(context);
-                    if (target.indexOf("?") < 0) {
-                        target.append("?");
-                    } else {
-                        target.append("&");
-                    }
-                    target.append(trailName).append("=").append(currentNodeTrailPiped);
-                    expandCollapseLink = new ModelTree.ModelNode.Link("collapsed", target.toString(), " ");
-                }
-            } else {
-                context.put("processChildren", Boolean.TRUE);
-                //expandCollapseLink.setText("&nbsp;-&nbsp;");
-                String lastContentId = currentNodeTrail.remove(currentNodeTrail.size() - 1);
-                currentNodeTrailPiped = StringUtil.join(currentNodeTrail, "|");
-                if (currentNodeTrailPiped == null) {
-                    currentNodeTrailPiped = "";
-                }
-                StringBuilder target = new StringBuilder(node.getModelTree().getExpandCollapseRequest(context));
-                String trailName = node.getModelTree().getTrailName(context);
-                if (target.indexOf("?") < 0) {
-                    target.append("?");
-                } else {
-                    target.append("&");
-                }
-                target.append(trailName).append("=").append(currentNodeTrailPiped);
-                expandCollapseLink = new ModelTree.ModelNode.Link("expanded", target.toString(), " ");
-                // add it so it can be remove in renderNodeEnd
-                currentNodeTrail.add(lastContentId);
-            }
-            if (expandCollapseLink != null) {
-                renderLink(writer, context, expandCollapseLink);
-            }
-        } else if (!hasChildren) {
-            context.put("processChildren", Boolean.FALSE);
-            ModelTree.ModelNode.Link expandCollapseLink = new ModelTree.ModelNode.Link("leafnode", "", " ");
-            renderLink(writer, context, expandCollapseLink);
-        }
-    }
-
-    public void renderNodeEnd(Appendable writer, Map<String, Object> context, ModelTree.ModelNode node) throws IOException {
-        Boolean processChildren = (Boolean) context.get("processChildren");
-        StringWriter sr = new StringWriter();
-        sr.append("<@renderNodeEnd ");
-        sr.append(" processChildren=");
-        sr.append(Boolean.toString(processChildren.booleanValue()));
-        sr.append(" isRootNode=");
-        sr.append(Boolean.toString(node.isRootNode()));
-        sr.append(" />");
-        executeMacro(sr.toString());
-        if (node.isRootNode()) {
-            if (ModelWidget.widgetBoundaryCommentsEnabled(context)) {
-                renderEndingBoundaryComment(writer, "Tree Widget", node.getModelTree());
-            }
-        }
-    }
-
-    public void renderLastElement(Appendable writer, Map<String, Object> context, ModelTree.ModelNode node) throws IOException {
-        Boolean processChildren = (Boolean) context.get("processChildren");
-        if (processChildren.booleanValue()) {            
-            StringWriter sr = new StringWriter();
-            sr.append("<@renderLastElement ");
-            sr.append("style=\"");
-            sr.append("basic-tree");
-            sr.append("\" />");
-            executeMacro(sr.toString());
-        }
-    }
-
-    public void renderLabel(Appendable writer, Map<String, Object> context, ModelTree.ModelNode.Label label) throws IOException {
-        String id = label.getId(context); 
-        String style = label.getStyle(context);
-        String labelText = label.getText(context);
-
-        StringWriter sr = new StringWriter();
-        sr.append("<@renderLabel ");
-        sr.append("id=\"");
-        sr.append(id);
-        sr.append("\" style=\"");
-        sr.append(style);
-        sr.append("\" labelText=\"");
-        sr.append(labelText);        
-        sr.append("\" />");
-        executeMacro(sr.toString());        
-    }
-
-    public void renderLink(Appendable writer, Map<String, Object> context, ModelTree.ModelNode.Link link) throws IOException {
-        String target = link.getTarget(context);
-        StringBuilder linkUrl = new StringBuilder();
-        HttpServletResponse response = (HttpServletResponse) context.get("response");
-        HttpServletRequest request = (HttpServletRequest) context.get("request");
-        
-        if (UtilValidate.isNotEmpty(target)) {
-            WidgetWorker.buildHyperlinkUrl(linkUrl, target, link.getUrlMode(), link.getParameterMap(context), link.getPrefix(context),
-                    link.getFullPath(), link.getSecure(), link.getEncode(), request, response, context);            
-        }        
-        
-        String id = link.getId(context);
-        String style = link.getStyle(context);
-        String name = link.getName(context);
-        String title = link.getTitle(context);
-        String targetWindow = link.getTargetWindow(context);
-        String linkText = link.getText(context);
-        
-        String imgStr = "";
-        ModelTree.ModelNode.Image img = link.getImage();
-        if (img != null) {
-            StringWriter sw = new StringWriter();
-            renderImage(sw, context, img);
-            imgStr = sw.toString();
-        }
-        
-        StringWriter sr = new StringWriter();
-        sr.append("<@renderLink ");
-        sr.append("id=\"");
-        sr.append(id);
-        sr.append("\" style=\"");
-        sr.append(style);
-        sr.append("\" name=\"");
-        sr.append(name);
-        sr.append("\" title=\"");
-        sr.append(title);
-        sr.append("\" targetWindow=\"");
-        sr.append(targetWindow);  
-        sr.append("\" linkUrl=\"");
-        sr.append(linkUrl);     
-        sr.append("\" linkText=\"");
-        sr.append(linkText);           
-        sr.append("\" imgStr=\"");
-        sr.append(imgStr.replaceAll("\"", "\\\\\""));
-        sr.append("\" />");
-        executeMacro(sr.toString());
-    }
-  
-    public void renderImage(Appendable writer, Map<String, Object> context, ModelTree.ModelNode.Image image) throws IOException {
-        if (image == null) {
-            return ;            
-        }
-        HttpServletResponse response = (HttpServletResponse) context.get("response");
-        HttpServletRequest request = (HttpServletRequest) context.get("request");
-        
-        String urlMode = image.getUrlMode();
-        String src = image.getSrc(context);
-        String id = image.getId(context);
-        String style = image.getStyle(context);
-        String wid = image.getWidth(context);
-        String hgt = image.getHeight(context);
-        String border = image.getBorder(context);
-        String alt = ""; //TODO add alt to tree images image.getAlt(context);
- 
-        boolean fullPath = false;
-        boolean secure = false;
-        boolean encode = false;
-        String urlString = "";
-        
-        if (urlMode != null && urlMode.equalsIgnoreCase("intra-app")) {
-            if (request != null && response != null) {
-                ServletContext ctx = (ServletContext) request.getAttribute("servletContext");
-                RequestHandler rh = (RequestHandler) ctx.getAttribute("_REQUEST_HANDLER_");
-                urlString = rh.makeLink(request, response, src, fullPath, secure, encode);
-            } else {
-                urlString = src;
-            }
-        } else  if (urlMode != null && urlMode.equalsIgnoreCase("content")) {
-            if (request != null && response != null) {
-                StringBuilder newURL = new StringBuilder();
-                ContentUrlTag.appendContentPrefix(request, newURL);
-                newURL.append(src);
-                urlString = newURL.toString();
-            }
-        } else {
-            urlString = src;
-        }
-        StringWriter sr = new StringWriter();
-        sr.append("<@renderImage ");
-        sr.append("src=\"");
-        sr.append(src);
-        sr.append("\" id=\"");
-        sr.append(id);
-        sr.append("\" style=\"");
-        sr.append(style);
-        sr.append("\" wid=\"");
-        sr.append(wid);
-        sr.append("\" hgt=\"");
-        sr.append(hgt);
-        sr.append("\" border=\"");
-        sr.append(border);
-        sr.append("\" alt=\"");
-        sr.append(alt);
-        sr.append("\" urlString=\"");
-        sr.append(urlString);
-        sr.append("\" />");
-        executeMacro(sr.toString());        
-    }
-
-    public ScreenStringRenderer getScreenStringRenderer(Map<String, Object> context) {
-        ScreenRenderer screenRenderer = (ScreenRenderer)context.get("screens");
-        if (screenRenderer != null) {
-            return screenRenderer.getScreenStringRenderer();
-        } 
-        return null;
-    }
-}
+/*******************************************************************************

+ * 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.renderer.macro;

+

+import java.io.IOException;

+import java.io.Reader;

+import java.io.StringReader;

+import java.io.StringWriter;

+import java.util.List;

+import java.util.Map;

+

+import javax.servlet.ServletContext;

+import javax.servlet.http.HttpServletRequest;

+import javax.servlet.http.HttpServletResponse;

+

+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.UtilValidate;

+import org.ofbiz.base.util.template.FreeMarkerWorker;

+import org.ofbiz.webapp.control.RequestHandler;

+import org.ofbiz.webapp.taglib.ContentUrlTag;

+import org.ofbiz.widget.WidgetWorker;

+import org.ofbiz.widget.model.ModelTree;

+import org.ofbiz.widget.model.ModelWidget;

+import org.ofbiz.widget.renderer.ScreenRenderer;

+import org.ofbiz.widget.renderer.ScreenStringRenderer;

+import org.ofbiz.widget.renderer.TreeStringRenderer;

+

+import freemarker.core.Environment;

+import freemarker.template.Template;

+import freemarker.template.TemplateException;

+

+/**

+ * Widget Library - Tree Renderer implementation based on Freemarker macros

+ * 

+ */

+public class MacroTreeRenderer implements TreeStringRenderer {

+

+    public static final String module = MacroTreeRenderer.class.getName();

+    private Template macroLibrary;

+    private Environment environment;

+

+

+    public MacroTreeRenderer(String macroLibraryPath, Appendable writer) throws TemplateException, IOException {

+        this.macroLibrary = FreeMarkerWorker.getTemplate(macroLibraryPath);

+        Map<String, Object> input = UtilMisc.toMap("key", null);

+        this.environment = FreeMarkerWorker.renderTemplate(this.macroLibrary, input, writer);

+    }

+

+    private void executeMacro(String macro) throws IOException {

+        try {

+            Reader templateReader = new StringReader(macro);

+            // FIXME: I am using a Date as an hack to provide a unique name for the template...

+            Template template = new Template((new java.util.Date()).toString(), templateReader,

+                    FreeMarkerWorker.getDefaultOfbizConfig());

+            templateReader.close();

+            this.environment.include(template);

+        } catch (TemplateException e) {

+            Debug.logError(e, "Error rendering tree thru ftl", module);

+        } catch (IOException e) {

+            Debug.logError(e, "Error rendering tree thru ftl", module);

+        }

+    }

+ 

+    /**

+     * Renders the beginning boundary comment string.

+     * @param writer The writer to write to

+     * @param widgetType The widget type: "Screen Widget", "Tree Widget", etc.

+     * @param modelWidget The widget

+     */

+    public void renderBeginningBoundaryComment(Appendable writer, String widgetType, ModelWidget modelWidget) throws IOException {

+        StringWriter sr = new StringWriter();

+        sr.append("<@formatBoundaryComment ");

+        sr.append(" boundaryType=\"");

+        sr.append("Begin");

+        sr.append("\" widgetType=\"");

+        sr.append(widgetType);

+        sr.append("\" widgetName=\"");

+        sr.append(modelWidget.getBoundaryCommentName());

+        sr.append("\" />");

+        executeMacro(sr.toString());

+    }

+    

+    /**

+     * Renders the ending boundary comment string.

+     * @param writer The writer to write to

+     * @param widgetType The widget type: "Screen Widget", "Tree Widget", etc.

+     * @param modelWidget The widget

+     */

+    public void renderEndingBoundaryComment(Appendable writer, String widgetType, ModelWidget modelWidget) throws IOException {

+        StringWriter sr = new StringWriter();

+        sr.append("<@formatBoundaryComment ");

+        sr.append(" boundaryType=\"");

+        sr.append("End");

+        sr.append("\" widgetType=\"");

+        sr.append(widgetType);

+        sr.append("\" widgetName=\"");

+        sr.append(modelWidget.getBoundaryCommentName());

+        sr.append("\" />");

+        executeMacro(sr.toString());

+    }

+    

+    public void renderNodeBegin(Appendable writer, Map<String, Object> context, ModelTree.ModelNode node, int depth) throws IOException {

+        String currentNodeTrailPiped = null;

+        List<String> currentNodeTrail = UtilGenerics.toList(context.get("currentNodeTrail"));

+        

+        String style = "";

+        if (node.isRootNode()) {

+            if (ModelWidget.widgetBoundaryCommentsEnabled(context)) {

+                renderBeginningBoundaryComment(writer, "Tree Widget", node.getModelTree());

+            }

+            style = "basic-tree";

+        }

+ 

+        StringWriter sr = new StringWriter();

+        sr.append("<@renderNodeBegin ");

+        sr.append(" style=\"");

+        sr.append(style);

+        sr.append("\" />");

+        executeMacro(sr.toString());

+

+        String pkName = node.getPkName(context);

+        String entityId = null;

+        String entryName = node.getEntryName();

+        if (UtilValidate.isNotEmpty(entryName)) {

+            Map<String, String> map = UtilGenerics.checkMap(context.get(entryName));

+            entityId = map.get(pkName);

+        } else {

+            entityId = (String) context.get(pkName);

+        }

+        boolean hasChildren = node.hasChildren(context);

+

+        // check to see if this node needs to be expanded.

+        if (hasChildren && node.isExpandCollapse()) {

+            // FIXME: Using a widget model in this way is an ugly hack.

+            ModelTree.ModelNode.Link expandCollapseLink = null;

+            String targetEntityId = null;

+            List<String> targetNodeTrail = UtilGenerics.toList(context.get("targetNodeTrail"));

+            if (depth < targetNodeTrail.size()) {

+                targetEntityId = targetNodeTrail.get(depth);

+            }

+

+            int openDepth = node.getModelTree().getOpenDepth();

+            if (depth >= openDepth && (targetEntityId == null || !targetEntityId.equals(entityId))) {

+                // Not on the trail

+                if (node.showPeers(depth, context)) {

+                    context.put("processChildren", Boolean.FALSE);

+                    //expandCollapseLink.setText("&nbsp;+&nbsp;");

+                    currentNodeTrailPiped = StringUtil.join(currentNodeTrail, "|");

+                    StringBuilder target = new StringBuilder(node.getModelTree().getExpandCollapseRequest(context));

+                    String trailName = node.getModelTree().getTrailName(context);

+                    if (target.indexOf("?") < 0) {

+                        target.append("?");

+                    } else {

+                        target.append("&");

+                    }

+                    target.append(trailName).append("=").append(currentNodeTrailPiped);

+                    expandCollapseLink = new ModelTree.ModelNode.Link("collapsed", target.toString(), " ");

+                }

+            } else {

+                context.put("processChildren", Boolean.TRUE);

+                //expandCollapseLink.setText("&nbsp;-&nbsp;");

+                String lastContentId = currentNodeTrail.remove(currentNodeTrail.size() - 1);

+                currentNodeTrailPiped = StringUtil.join(currentNodeTrail, "|");

+                if (currentNodeTrailPiped == null) {

+                    currentNodeTrailPiped = "";

+                }

+                StringBuilder target = new StringBuilder(node.getModelTree().getExpandCollapseRequest(context));

+                String trailName = node.getModelTree().getTrailName(context);

+                if (target.indexOf("?") < 0) {

+                    target.append("?");

+                } else {

+                    target.append("&");

+                }

+                target.append(trailName).append("=").append(currentNodeTrailPiped);

+                expandCollapseLink = new ModelTree.ModelNode.Link("expanded", target.toString(), " ");

+                // add it so it can be remove in renderNodeEnd

+                currentNodeTrail.add(lastContentId);

+            }

+            if (expandCollapseLink != null) {

+                renderLink(writer, context, expandCollapseLink);

+            }

+        } else if (!hasChildren) {

+            context.put("processChildren", Boolean.FALSE);

+            ModelTree.ModelNode.Link expandCollapseLink = new ModelTree.ModelNode.Link("leafnode", "", " ");

+            renderLink(writer, context, expandCollapseLink);

+        }

+    }

+

+    public void renderNodeEnd(Appendable writer, Map<String, Object> context, ModelTree.ModelNode node) throws IOException {

+        Boolean processChildren = (Boolean) context.get("processChildren");

+        StringWriter sr = new StringWriter();

+        sr.append("<@renderNodeEnd ");

+        sr.append(" processChildren=");

+        sr.append(Boolean.toString(processChildren.booleanValue()));

+        sr.append(" isRootNode=");

+        sr.append(Boolean.toString(node.isRootNode()));

+        sr.append(" />");

+        executeMacro(sr.toString());

+        if (node.isRootNode()) {

+            if (ModelWidget.widgetBoundaryCommentsEnabled(context)) {

+                renderEndingBoundaryComment(writer, "Tree Widget", node.getModelTree());

+            }

+        }

+    }

+

+    public void renderLastElement(Appendable writer, Map<String, Object> context, ModelTree.ModelNode node) throws IOException {

+        Boolean processChildren = (Boolean) context.get("processChildren");

+        if (processChildren.booleanValue()) {            

+            StringWriter sr = new StringWriter();

+            sr.append("<@renderLastElement ");

+            sr.append("style=\"");

+            sr.append("basic-tree");

+            sr.append("\" />");

+            executeMacro(sr.toString());

+        }

+    }

+

+    public void renderLabel(Appendable writer, Map<String, Object> context, ModelTree.ModelNode.Label label) throws IOException {

+        String id = label.getId(context); 

+        String style = label.getStyle(context);

+        String labelText = label.getText(context);

+

+        StringWriter sr = new StringWriter();

+        sr.append("<@renderLabel ");

+        sr.append("id=\"");

+        sr.append(id);

+        sr.append("\" style=\"");

+        sr.append(style);

+        sr.append("\" labelText=\"");

+        sr.append(labelText);        

+        sr.append("\" />");

+        executeMacro(sr.toString());        

+    }

+

+    public void renderLink(Appendable writer, Map<String, Object> context, ModelTree.ModelNode.Link link) throws IOException {

+        String target = link.getTarget(context);

+        StringBuilder linkUrl = new StringBuilder();

+        HttpServletResponse response = (HttpServletResponse) context.get("response");

+        HttpServletRequest request = (HttpServletRequest) context.get("request");

+        

+        if (UtilValidate.isNotEmpty(target)) {

+            WidgetWorker.buildHyperlinkUrl(linkUrl, target, link.getUrlMode(), link.getParameterMap(context), link.getPrefix(context),

+                    link.getFullPath(), link.getSecure(), link.getEncode(), request, response, context);            

+        }        

+        

+        String id = link.getId(context);

+        String style = link.getStyle(context);

+        String name = link.getName(context);

+        String title = link.getTitle(context);

+        String targetWindow = link.getTargetWindow(context);

+        String linkText = link.getText(context);

+        

+        String imgStr = "";

+        ModelTree.ModelNode.Image img = link.getImage();

+        if (img != null) {

+            StringWriter sw = new StringWriter();

+            renderImage(sw, context, img);

+            imgStr = sw.toString();

+        }

+        

+        StringWriter sr = new StringWriter();

+        sr.append("<@renderLink ");

+        sr.append("id=\"");

+        sr.append(id);

+        sr.append("\" style=\"");

+        sr.append(style);

+        sr.append("\" name=\"");

+        sr.append(name);

+        sr.append("\" title=\"");

+        sr.append(title);

+        sr.append("\" targetWindow=\"");

+        sr.append(targetWindow);  

+        sr.append("\" linkUrl=\"");

+        sr.append(linkUrl);     

+        sr.append("\" linkText=\"");

+        sr.append(linkText);           

+        sr.append("\" imgStr=\"");

+        sr.append(imgStr.replaceAll("\"", "\\\\\""));

+        sr.append("\" />");

+        executeMacro(sr.toString());

+    }

+  

+    public void renderImage(Appendable writer, Map<String, Object> context, ModelTree.ModelNode.Image image) throws IOException {

+        if (image == null) {

+            return ;            

+        }

+        HttpServletResponse response = (HttpServletResponse) context.get("response");

+        HttpServletRequest request = (HttpServletRequest) context.get("request");

+        

+        String urlMode = image.getUrlMode();

+        String src = image.getSrc(context);

+        String id = image.getId(context);

+        String style = image.getStyle(context);

+        String wid = image.getWidth(context);

+        String hgt = image.getHeight(context);

+        String border = image.getBorder(context);

+        String alt = ""; //TODO add alt to tree images image.getAlt(context);

+ 

+        boolean fullPath = false;

+        boolean secure = false;

+        boolean encode = false;

+        String urlString = "";

+        

+        if (urlMode != null && urlMode.equalsIgnoreCase("intra-app")) {

+            if (request != null && response != null) {

+                ServletContext ctx = (ServletContext) request.getAttribute("servletContext");

+                RequestHandler rh = (RequestHandler) ctx.getAttribute("_REQUEST_HANDLER_");

+                urlString = rh.makeLink(request, response, src, fullPath, secure, encode);

+            } else {

+                urlString = src;

+            }

+        } else  if (urlMode != null && urlMode.equalsIgnoreCase("content")) {

+            if (request != null && response != null) {

+                StringBuilder newURL = new StringBuilder();

+                ContentUrlTag.appendContentPrefix(request, newURL);

+                newURL.append(src);

+                urlString = newURL.toString();

+            }

+        } else {

+            urlString = src;

+        }

+        StringWriter sr = new StringWriter();

+        sr.append("<@renderImage ");

+        sr.append("src=\"");

+        sr.append(src);

+        sr.append("\" id=\"");

+        sr.append(id);

+        sr.append("\" style=\"");

+        sr.append(style);

+        sr.append("\" wid=\"");

+        sr.append(wid);

+        sr.append("\" hgt=\"");

+        sr.append(hgt);

+        sr.append("\" border=\"");

+        sr.append(border);

+        sr.append("\" alt=\"");

+        sr.append(alt);

+        sr.append("\" urlString=\"");

+        sr.append(urlString);

+        sr.append("\" />");

+        executeMacro(sr.toString());        

+    }

+

+    public ScreenStringRenderer getScreenStringRenderer(Map<String, Object> context) {

+        ScreenRenderer screenRenderer = (ScreenRenderer)context.get("screens");

+        if (screenRenderer != null) {

+            return screenRenderer.getScreenStringRenderer();

+        } 

+        return null;

+    }

+}

diff --git a/framework/widget/src/org/ofbiz/widget/text/TextFormRenderer.java b/framework/widget/src/org/ofbiz/widget/renderer/text/TextFormRenderer.java
similarity index 90%
rename from framework/widget/src/org/ofbiz/widget/text/TextFormRenderer.java
rename to framework/widget/src/org/ofbiz/widget/renderer/text/TextFormRenderer.java
index 2189128..dbbbec9 100644
--- a/framework/widget/src/org/ofbiz/widget/text/TextFormRenderer.java
+++ b/framework/widget/src/org/ofbiz/widget/renderer/text/TextFormRenderer.java
@@ -1,302 +1,302 @@
-/*******************************************************************************
- * 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.text;
-
-import java.io.IOException;
-import java.util.List;
-import java.util.Map;
-
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.ofbiz.base.util.UtilValidate;
-import org.ofbiz.widget.WidgetWorker;
-import org.ofbiz.widget.form.FormStringRenderer;
-import org.ofbiz.widget.form.ModelForm;
-import org.ofbiz.widget.form.ModelFormField;
-import org.ofbiz.widget.form.ModelFormField.CheckField;
-import org.ofbiz.widget.form.ModelFormField.ContainerField;
-import org.ofbiz.widget.form.ModelFormField.DateFindField;
-import org.ofbiz.widget.form.ModelFormField.DateTimeField;
-import org.ofbiz.widget.form.ModelFormField.DisplayField;
-import org.ofbiz.widget.form.ModelFormField.DropDownField;
-import org.ofbiz.widget.form.ModelFormField.FieldInfoWithOptions;
-import org.ofbiz.widget.form.ModelFormField.FileField;
-import org.ofbiz.widget.form.ModelFormField.HiddenField;
-import org.ofbiz.widget.form.ModelFormField.HyperlinkField;
-import org.ofbiz.widget.form.ModelFormField.IgnoredField;
-import org.ofbiz.widget.form.ModelFormField.ImageField;
-import org.ofbiz.widget.form.ModelFormField.LookupField;
-import org.ofbiz.widget.form.ModelFormField.PasswordField;
-import org.ofbiz.widget.form.ModelFormField.RadioField;
-import org.ofbiz.widget.form.ModelFormField.RangeFindField;
-import org.ofbiz.widget.form.ModelFormField.ResetField;
-import org.ofbiz.widget.form.ModelFormField.SubmitField;
-import org.ofbiz.widget.form.ModelFormField.TextField;
-import org.ofbiz.widget.form.ModelFormField.TextFindField;
-import org.ofbiz.widget.form.ModelFormField.TextareaField;
-
-
-/**
- * Widget Library - Csv Form Renderer implementation
- *
- */
-public class TextFormRenderer implements FormStringRenderer {
-
-    public static final String module = TextFormRenderer.class.getName();
-
-    HttpServletRequest request;
-    HttpServletResponse response;
-
-    protected TextFormRenderer() {}
-
-    public TextFormRenderer(HttpServletRequest request, HttpServletResponse response) {
-        this.request = request;
-        this.response = response;
-    }
-
-    public void appendWhitespace(Appendable writer) throws IOException {
-        // appending line ends for now, but this could be replaced with a simple space or something
-        writer.append("\r\n");
-        //writer.append(' ');
-    }
-
-    private void makeTextString(Appendable writer, String widgetStyle, String text) throws IOException {
-        // TODO: escape characters here
-        writer.append(text);
-    }
-
-    public void renderDisplayField(Appendable writer, Map<String, Object> context, DisplayField displayField) throws IOException {
-        ModelFormField modelFormField = displayField.getModelFormField();
-        this.makeTextString(writer, modelFormField.getWidgetStyle(), displayField.getDescription(context));
-    }
-
-    public void renderHyperlinkField(Appendable writer, Map<String, Object> context, HyperlinkField hyperlinkField) throws IOException {
-        ModelFormField modelFormField = hyperlinkField.getModelFormField();
-        this.makeTextString(writer, modelFormField.getWidgetStyle(), hyperlinkField.getDescription(context));
-    }
-
-    public void renderTextField(Appendable writer, Map<String, Object> context, TextField textField) throws IOException {
-        ModelFormField modelFormField = textField.getModelFormField();
-        this.makeTextString(writer, modelFormField.getWidgetStyle(), modelFormField.getEntry(context, textField.getDefaultValue(context)));
-    }
-
-    public void renderTextareaField(Appendable writer, Map<String, Object> context, TextareaField textareaField) throws IOException {
-        ModelFormField modelFormField = textareaField.getModelFormField();
-        this.makeTextString(writer, modelFormField.getWidgetStyle(), modelFormField.getEntry(context, textareaField.getDefaultValue(context)));
-    }
-
-    public void renderDateTimeField(Appendable writer, Map<String, Object> context, DateTimeField dateTimeField) throws IOException {
-        ModelFormField modelFormField = dateTimeField.getModelFormField();
-        this.makeTextString(writer, modelFormField.getWidgetStyle(), modelFormField.getEntry(context, dateTimeField.getDefaultValue(context)));
-    }
-
-    public void renderDropDownField(Appendable writer, Map<String, Object> context, DropDownField dropDownField) throws IOException {
-        ModelFormField modelFormField = dropDownField.getModelFormField();
-        String currentValue = modelFormField.getEntry(context);
-        List<ModelFormField.OptionValue> allOptionValues = dropDownField.getAllOptionValues(context, WidgetWorker.getDelegator(context));
-        // if the current value should go first, display it
-        if (UtilValidate.isNotEmpty(currentValue) && "first-in-list".equals(dropDownField.getCurrent())) {
-            String explicitDescription = dropDownField.getCurrentDescription(context);
-            if (UtilValidate.isNotEmpty(explicitDescription)) {
-                this.makeTextString(writer, modelFormField.getWidgetStyle(), explicitDescription);
-            } else {
-                this.makeTextString(writer, modelFormField.getWidgetStyle(), FieldInfoWithOptions.getDescriptionForOptionKey(currentValue, allOptionValues));
-            }
-        } else {
-            for (ModelFormField.OptionValue optionValue: allOptionValues) {
-                String noCurrentSelectedKey = dropDownField.getNoCurrentSelectedKey(context);
-                if ((UtilValidate.isNotEmpty(currentValue) && currentValue.equals(optionValue.getKey()) && "selected".equals(dropDownField.getCurrent())) ||
-                        (UtilValidate.isEmpty(currentValue) && noCurrentSelectedKey != null && noCurrentSelectedKey.equals(optionValue.getKey()))) {
-                    this.makeTextString(writer, modelFormField.getWidgetStyle(), optionValue.getDescription());
-                    break;
-                }
-            }
-        }
-    }
-
-    public void renderCheckField(Appendable writer, Map<String, Object> context, CheckField checkField) {
-    }
-
-    public void renderRadioField(Appendable writer, Map<String, Object> context, RadioField radioField) {
-    }
-
-    public void renderSubmitField(Appendable writer, Map<String, Object> context, SubmitField submitField) {
-    }
-
-    public void renderResetField(Appendable writer, Map<String, Object> context, ResetField resetField) {
-    }
-
-    public void renderHiddenField(Appendable writer, Map<String, Object> context, HiddenField hiddenField) {
-    }
-
-    public void renderHiddenField(Appendable writer, Map<String, Object> context, ModelFormField modelFormField, String value) {
-    }
-
-    public void renderIgnoredField(Appendable writer, Map<String, Object> context, IgnoredField ignoredField) {
-    }
-
-    public void renderFieldTitle(Appendable writer, Map<String, Object> context, ModelFormField modelFormField) throws IOException {
-        this.makeTextString(writer, modelFormField.getWidgetStyle(), modelFormField.getTitle(context));
-    }
-
-    public void renderSingleFormFieldTitle(Appendable writer, Map<String, Object> context, ModelFormField modelFormField) throws IOException {
-        renderFieldTitle(writer, context, modelFormField);
-    }
-
-    public void renderFormOpen(Appendable writer, Map<String, Object> context, ModelForm modelForm) {
-    }
-
-    public void renderFormClose(Appendable writer, Map<String, Object> context, ModelForm modelForm) {
-    }
-
-    public void renderMultiFormClose(Appendable writer, Map<String, Object> context, ModelForm modelForm) {
-    }
-
-    public void renderFormatListWrapperOpen(Appendable writer, Map<String, Object> context, ModelForm modelForm) {
-    }
-
-    public void renderFormatListWrapperClose(Appendable writer, Map<String, Object> context, ModelForm modelForm) {
-    }
-
-    public void renderFormatHeaderRowOpen(Appendable writer, Map<String, Object> context, ModelForm modelForm) {
-    }
-
-    public void renderFormatHeaderRowClose(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {
-        this.appendWhitespace(writer);
-    }
-
-    public void renderFormatHeaderRowCellOpen(Appendable writer, Map<String, Object> context, ModelForm modelForm, ModelFormField modelFormField, int positionSpan) {
-    }
-
-    public void renderFormatHeaderRowCellClose(Appendable writer, Map<String, Object> context, ModelForm modelForm, ModelFormField modelFormField) {
-    }
-
-    public void renderFormatHeaderRowFormCellOpen(Appendable writer, Map<String, Object> context, ModelForm modelForm) {
-    }
-
-    public void renderFormatHeaderRowFormCellClose(Appendable writer, Map<String, Object> context, ModelForm modelForm) {
-    }
-
-    public void renderFormatHeaderRowFormCellTitleSeparator(Appendable writer, Map<String, Object> context, ModelForm modelForm, ModelFormField modelFormField, boolean isLast) {
-    }
-
-    public void renderFormatItemRowOpen(Appendable writer, Map<String, Object> context, ModelForm modelForm) {
-    }
-
-    public void renderFormatItemRowClose(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {
-        this.appendWhitespace(writer);
-    }
-
-    public void renderFormatItemRowCellOpen(Appendable writer, Map<String, Object> context, ModelForm modelForm, ModelFormField modelFormField, int positionSpan) {
-    }
-
-    public void renderFormatItemRowCellClose(Appendable writer, Map<String, Object> context, ModelForm modelForm, ModelFormField modelFormField) {
-    }
-
-    public void renderFormatItemRowFormCellOpen(Appendable writer, Map<String, Object> context, ModelForm modelForm) {
-    }
-
-    public void renderFormatItemRowFormCellClose(Appendable writer, Map<String, Object> context, ModelForm modelForm) {
-    }
-
-    public void renderFormatSingleWrapperOpen(Appendable writer, Map<String, Object> context, ModelForm modelForm) {
-    }
-
-    public void renderFormatSingleWrapperClose(Appendable writer, Map<String, Object> context, ModelForm modelForm) {
-    }
-
-    public void renderFormatFieldRowOpen(Appendable writer, Map<String, Object> context, ModelForm modelForm) {
-    }
-
-    public void renderFormatFieldRowClose(Appendable writer, Map<String, Object> context, ModelForm modelForm) {
-    }
-
-    public void renderFormatFieldRowTitleCellOpen(Appendable writer, Map<String, Object> context, ModelFormField modelFormField) {
-    }
-
-    public void renderFormatFieldRowTitleCellClose(Appendable writer, Map<String, Object> context, ModelFormField modelFormField) {
-    }
-
-    public void renderFormatFieldRowSpacerCell(Appendable writer, Map<String, Object> context, ModelFormField modelFormField) {
-    }
-
-    public void renderFormatFieldRowWidgetCellOpen(Appendable writer, Map<String, Object> context, ModelFormField modelFormField, int positions, int positionSpan, Integer nextPositionInRow) {
-    }
-
-    public void renderFormatFieldRowWidgetCellClose(Appendable writer, Map<String, Object> context, ModelFormField modelFormField, int positions, int positionSpan, Integer nextPositionInRow) {
-    }
-
-    public void renderFormatEmptySpace(Appendable writer, Map<String, Object> context, ModelForm modelForm) {
-        // TODO
-    }
-
-    public void renderTextFindField(Appendable writer, Map<String, Object> context, TextFindField textFindField) throws IOException {
-        ModelFormField modelFormField = textFindField.getModelFormField();
-        this.makeTextString(writer, modelFormField.getWidgetStyle(), modelFormField.getEntry(context, textFindField.getDefaultValue(context)));
-    }
-
-    public void renderRangeFindField(Appendable writer, Map<String, Object> context, RangeFindField rangeFindField) throws IOException {
-        ModelFormField modelFormField = rangeFindField.getModelFormField();
-        this.makeTextString(writer, modelFormField.getWidgetStyle(), modelFormField.getEntry(context, rangeFindField.getDefaultValue(context)));
-    }
-
-    public void renderDateFindField(Appendable writer, Map<String, Object> context, DateFindField dateFindField) throws IOException {
-        ModelFormField modelFormField = dateFindField.getModelFormField();
-        this.makeTextString(writer, modelFormField.getWidgetStyle(), modelFormField.getEntry(context, dateFindField.getDefaultValue(context)));
-    }
-
-    public void renderLookupField(Appendable writer, Map<String, Object> context, LookupField lookupField) throws IOException {
-        ModelFormField modelFormField = lookupField.getModelFormField();
-        this.makeTextString(writer, modelFormField.getWidgetStyle(), modelFormField.getEntry(context, lookupField.getDefaultValue(context)));
-    }
-
-    public void renderNextPrev(Appendable writer, Map<String, Object> context, ModelForm modelForm) {
-    }
-
-    public void renderFileField(Appendable writer, Map<String, Object> context, FileField textField) throws IOException {
-        ModelFormField modelFormField = textField.getModelFormField();
-        this.makeTextString(writer, modelFormField.getWidgetStyle(), modelFormField.getEntry(context, textField.getDefaultValue(context)));
-    }
-
-    public void renderPasswordField(Appendable writer, Map<String, Object> context, PasswordField passwordField) {
-    }
-
-    public void renderImageField(Appendable writer, Map<String, Object> context, ImageField imageField) {
-        // TODO
-    }
-
-    public void renderFieldGroupOpen(Appendable writer, Map<String, Object> context, ModelForm.FieldGroup fieldGroup) {
-        // TODO
-    }
-
-    public void renderFieldGroupClose(Appendable writer, Map<String, Object> context, ModelForm.FieldGroup fieldGroup) {
-        // TODO
-    }
-
-    public void renderBanner(Appendable writer, Map<String, Object> context, ModelForm.Banner banner) {
-        // TODO
-    }
-
-    public void renderHyperlinkTitle(Appendable writer, Map<String, Object> context, ModelFormField modelFormField, String titleText) {
-    }
-
-    public void renderContainerFindField(Appendable writer, Map<String, Object> context, ContainerField containerField) throws IOException {
-    }
-}
+/*******************************************************************************

+ * 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.renderer.text;

+

+import java.io.IOException;

+import java.util.List;

+import java.util.Map;

+

+import javax.servlet.http.HttpServletRequest;

+import javax.servlet.http.HttpServletResponse;

+

+import org.ofbiz.base.util.UtilValidate;

+import org.ofbiz.widget.WidgetWorker;

+import org.ofbiz.widget.model.ModelForm;

+import org.ofbiz.widget.model.ModelFormField;

+import org.ofbiz.widget.model.ModelFormField.CheckField;

+import org.ofbiz.widget.model.ModelFormField.ContainerField;

+import org.ofbiz.widget.model.ModelFormField.DateFindField;

+import org.ofbiz.widget.model.ModelFormField.DateTimeField;

+import org.ofbiz.widget.model.ModelFormField.DisplayField;

+import org.ofbiz.widget.model.ModelFormField.DropDownField;

+import org.ofbiz.widget.model.ModelFormField.FieldInfoWithOptions;

+import org.ofbiz.widget.model.ModelFormField.FileField;

+import org.ofbiz.widget.model.ModelFormField.HiddenField;

+import org.ofbiz.widget.model.ModelFormField.HyperlinkField;

+import org.ofbiz.widget.model.ModelFormField.IgnoredField;

+import org.ofbiz.widget.model.ModelFormField.ImageField;

+import org.ofbiz.widget.model.ModelFormField.LookupField;

+import org.ofbiz.widget.model.ModelFormField.PasswordField;

+import org.ofbiz.widget.model.ModelFormField.RadioField;

+import org.ofbiz.widget.model.ModelFormField.RangeFindField;

+import org.ofbiz.widget.model.ModelFormField.ResetField;

+import org.ofbiz.widget.model.ModelFormField.SubmitField;

+import org.ofbiz.widget.model.ModelFormField.TextField;

+import org.ofbiz.widget.model.ModelFormField.TextFindField;

+import org.ofbiz.widget.model.ModelFormField.TextareaField;

+import org.ofbiz.widget.renderer.FormStringRenderer;

+

+

+/**

+ * Widget Library - Csv Form Renderer implementation

+ *

+ */

+public class TextFormRenderer implements FormStringRenderer {

+

+    public static final String module = TextFormRenderer.class.getName();

+

+    HttpServletRequest request;

+    HttpServletResponse response;

+

+    protected TextFormRenderer() {}

+

+    public TextFormRenderer(HttpServletRequest request, HttpServletResponse response) {

+        this.request = request;

+        this.response = response;

+    }

+

+    public void appendWhitespace(Appendable writer) throws IOException {

+        // appending line ends for now, but this could be replaced with a simple space or something

+        writer.append("\r\n");

+        //writer.append(' ');

+    }

+

+    private void makeTextString(Appendable writer, String widgetStyle, String text) throws IOException {

+        // TODO: escape characters here

+        writer.append(text);

+    }

+

+    public void renderDisplayField(Appendable writer, Map<String, Object> context, DisplayField displayField) throws IOException {

+        ModelFormField modelFormField = displayField.getModelFormField();

+        this.makeTextString(writer, modelFormField.getWidgetStyle(), displayField.getDescription(context));

+    }

+

+    public void renderHyperlinkField(Appendable writer, Map<String, Object> context, HyperlinkField hyperlinkField) throws IOException {

+        ModelFormField modelFormField = hyperlinkField.getModelFormField();

+        this.makeTextString(writer, modelFormField.getWidgetStyle(), hyperlinkField.getDescription(context));

+    }

+

+    public void renderTextField(Appendable writer, Map<String, Object> context, TextField textField) throws IOException {

+        ModelFormField modelFormField = textField.getModelFormField();

+        this.makeTextString(writer, modelFormField.getWidgetStyle(), modelFormField.getEntry(context, textField.getDefaultValue(context)));

+    }

+

+    public void renderTextareaField(Appendable writer, Map<String, Object> context, TextareaField textareaField) throws IOException {

+        ModelFormField modelFormField = textareaField.getModelFormField();

+        this.makeTextString(writer, modelFormField.getWidgetStyle(), modelFormField.getEntry(context, textareaField.getDefaultValue(context)));

+    }

+

+    public void renderDateTimeField(Appendable writer, Map<String, Object> context, DateTimeField dateTimeField) throws IOException {

+        ModelFormField modelFormField = dateTimeField.getModelFormField();

+        this.makeTextString(writer, modelFormField.getWidgetStyle(), modelFormField.getEntry(context, dateTimeField.getDefaultValue(context)));

+    }

+

+    public void renderDropDownField(Appendable writer, Map<String, Object> context, DropDownField dropDownField) throws IOException {

+        ModelFormField modelFormField = dropDownField.getModelFormField();

+        String currentValue = modelFormField.getEntry(context);

+        List<ModelFormField.OptionValue> allOptionValues = dropDownField.getAllOptionValues(context, WidgetWorker.getDelegator(context));

+        // if the current value should go first, display it

+        if (UtilValidate.isNotEmpty(currentValue) && "first-in-list".equals(dropDownField.getCurrent())) {

+            String explicitDescription = dropDownField.getCurrentDescription(context);

+            if (UtilValidate.isNotEmpty(explicitDescription)) {

+                this.makeTextString(writer, modelFormField.getWidgetStyle(), explicitDescription);

+            } else {

+                this.makeTextString(writer, modelFormField.getWidgetStyle(), FieldInfoWithOptions.getDescriptionForOptionKey(currentValue, allOptionValues));

+            }

+        } else {

+            for (ModelFormField.OptionValue optionValue: allOptionValues) {

+                String noCurrentSelectedKey = dropDownField.getNoCurrentSelectedKey(context);

+                if ((UtilValidate.isNotEmpty(currentValue) && currentValue.equals(optionValue.getKey()) && "selected".equals(dropDownField.getCurrent())) ||

+                        (UtilValidate.isEmpty(currentValue) && noCurrentSelectedKey != null && noCurrentSelectedKey.equals(optionValue.getKey()))) {

+                    this.makeTextString(writer, modelFormField.getWidgetStyle(), optionValue.getDescription());

+                    break;

+                }

+            }

+        }

+    }

+

+    public void renderCheckField(Appendable writer, Map<String, Object> context, CheckField checkField) {

+    }

+

+    public void renderRadioField(Appendable writer, Map<String, Object> context, RadioField radioField) {

+    }

+

+    public void renderSubmitField(Appendable writer, Map<String, Object> context, SubmitField submitField) {

+    }

+

+    public void renderResetField(Appendable writer, Map<String, Object> context, ResetField resetField) {

+    }

+

+    public void renderHiddenField(Appendable writer, Map<String, Object> context, HiddenField hiddenField) {

+    }

+

+    public void renderHiddenField(Appendable writer, Map<String, Object> context, ModelFormField modelFormField, String value) {

+    }

+

+    public void renderIgnoredField(Appendable writer, Map<String, Object> context, IgnoredField ignoredField) {

+    }

+

+    public void renderFieldTitle(Appendable writer, Map<String, Object> context, ModelFormField modelFormField) throws IOException {

+        this.makeTextString(writer, modelFormField.getWidgetStyle(), modelFormField.getTitle(context));

+    }

+

+    public void renderSingleFormFieldTitle(Appendable writer, Map<String, Object> context, ModelFormField modelFormField) throws IOException {

+        renderFieldTitle(writer, context, modelFormField);

+    }

+

+    public void renderFormOpen(Appendable writer, Map<String, Object> context, ModelForm modelForm) {

+    }

+

+    public void renderFormClose(Appendable writer, Map<String, Object> context, ModelForm modelForm) {

+    }

+

+    public void renderMultiFormClose(Appendable writer, Map<String, Object> context, ModelForm modelForm) {

+    }

+

+    public void renderFormatListWrapperOpen(Appendable writer, Map<String, Object> context, ModelForm modelForm) {

+    }

+

+    public void renderFormatListWrapperClose(Appendable writer, Map<String, Object> context, ModelForm modelForm) {

+    }

+

+    public void renderFormatHeaderRowOpen(Appendable writer, Map<String, Object> context, ModelForm modelForm) {

+    }

+

+    public void renderFormatHeaderRowClose(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {

+        this.appendWhitespace(writer);

+    }

+

+    public void renderFormatHeaderRowCellOpen(Appendable writer, Map<String, Object> context, ModelForm modelForm, ModelFormField modelFormField, int positionSpan) {

+    }

+

+    public void renderFormatHeaderRowCellClose(Appendable writer, Map<String, Object> context, ModelForm modelForm, ModelFormField modelFormField) {

+    }

+

+    public void renderFormatHeaderRowFormCellOpen(Appendable writer, Map<String, Object> context, ModelForm modelForm) {

+    }

+

+    public void renderFormatHeaderRowFormCellClose(Appendable writer, Map<String, Object> context, ModelForm modelForm) {

+    }

+

+    public void renderFormatHeaderRowFormCellTitleSeparator(Appendable writer, Map<String, Object> context, ModelForm modelForm, ModelFormField modelFormField, boolean isLast) {

+    }

+

+    public void renderFormatItemRowOpen(Appendable writer, Map<String, Object> context, ModelForm modelForm) {

+    }

+

+    public void renderFormatItemRowClose(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {

+        this.appendWhitespace(writer);

+    }

+

+    public void renderFormatItemRowCellOpen(Appendable writer, Map<String, Object> context, ModelForm modelForm, ModelFormField modelFormField, int positionSpan) {

+    }

+

+    public void renderFormatItemRowCellClose(Appendable writer, Map<String, Object> context, ModelForm modelForm, ModelFormField modelFormField) {

+    }

+

+    public void renderFormatItemRowFormCellOpen(Appendable writer, Map<String, Object> context, ModelForm modelForm) {

+    }

+

+    public void renderFormatItemRowFormCellClose(Appendable writer, Map<String, Object> context, ModelForm modelForm) {

+    }

+

+    public void renderFormatSingleWrapperOpen(Appendable writer, Map<String, Object> context, ModelForm modelForm) {

+    }

+

+    public void renderFormatSingleWrapperClose(Appendable writer, Map<String, Object> context, ModelForm modelForm) {

+    }

+

+    public void renderFormatFieldRowOpen(Appendable writer, Map<String, Object> context, ModelForm modelForm) {

+    }

+

+    public void renderFormatFieldRowClose(Appendable writer, Map<String, Object> context, ModelForm modelForm) {

+    }

+

+    public void renderFormatFieldRowTitleCellOpen(Appendable writer, Map<String, Object> context, ModelFormField modelFormField) {

+    }

+

+    public void renderFormatFieldRowTitleCellClose(Appendable writer, Map<String, Object> context, ModelFormField modelFormField) {

+    }

+

+    public void renderFormatFieldRowSpacerCell(Appendable writer, Map<String, Object> context, ModelFormField modelFormField) {

+    }

+

+    public void renderFormatFieldRowWidgetCellOpen(Appendable writer, Map<String, Object> context, ModelFormField modelFormField, int positions, int positionSpan, Integer nextPositionInRow) {

+    }

+

+    public void renderFormatFieldRowWidgetCellClose(Appendable writer, Map<String, Object> context, ModelFormField modelFormField, int positions, int positionSpan, Integer nextPositionInRow) {

+    }

+

+    public void renderFormatEmptySpace(Appendable writer, Map<String, Object> context, ModelForm modelForm) {

+        // TODO

+    }

+

+    public void renderTextFindField(Appendable writer, Map<String, Object> context, TextFindField textFindField) throws IOException {

+        ModelFormField modelFormField = textFindField.getModelFormField();

+        this.makeTextString(writer, modelFormField.getWidgetStyle(), modelFormField.getEntry(context, textFindField.getDefaultValue(context)));

+    }

+

+    public void renderRangeFindField(Appendable writer, Map<String, Object> context, RangeFindField rangeFindField) throws IOException {

+        ModelFormField modelFormField = rangeFindField.getModelFormField();

+        this.makeTextString(writer, modelFormField.getWidgetStyle(), modelFormField.getEntry(context, rangeFindField.getDefaultValue(context)));

+    }

+

+    public void renderDateFindField(Appendable writer, Map<String, Object> context, DateFindField dateFindField) throws IOException {

+        ModelFormField modelFormField = dateFindField.getModelFormField();

+        this.makeTextString(writer, modelFormField.getWidgetStyle(), modelFormField.getEntry(context, dateFindField.getDefaultValue(context)));

+    }

+

+    public void renderLookupField(Appendable writer, Map<String, Object> context, LookupField lookupField) throws IOException {

+        ModelFormField modelFormField = lookupField.getModelFormField();

+        this.makeTextString(writer, modelFormField.getWidgetStyle(), modelFormField.getEntry(context, lookupField.getDefaultValue(context)));

+    }

+

+    public void renderNextPrev(Appendable writer, Map<String, Object> context, ModelForm modelForm) {

+    }

+

+    public void renderFileField(Appendable writer, Map<String, Object> context, FileField textField) throws IOException {

+        ModelFormField modelFormField = textField.getModelFormField();

+        this.makeTextString(writer, modelFormField.getWidgetStyle(), modelFormField.getEntry(context, textField.getDefaultValue(context)));

+    }

+

+    public void renderPasswordField(Appendable writer, Map<String, Object> context, PasswordField passwordField) {

+    }

+

+    public void renderImageField(Appendable writer, Map<String, Object> context, ImageField imageField) {

+        // TODO

+    }

+

+    public void renderFieldGroupOpen(Appendable writer, Map<String, Object> context, ModelForm.FieldGroup fieldGroup) {

+        // TODO

+    }

+

+    public void renderFieldGroupClose(Appendable writer, Map<String, Object> context, ModelForm.FieldGroup fieldGroup) {

+        // TODO

+    }

+

+    public void renderBanner(Appendable writer, Map<String, Object> context, ModelForm.Banner banner) {

+        // TODO

+    }

+

+    public void renderHyperlinkTitle(Appendable writer, Map<String, Object> context, ModelFormField modelFormField, String titleText) {

+    }

+

+    public void renderContainerFindField(Appendable writer, Map<String, Object> context, ContainerField containerField) throws IOException {

+    }

+}

diff --git a/framework/widget/src/org/ofbiz/widget/text/TextScreenRenderer.java b/framework/widget/src/org/ofbiz/widget/renderer/text/TextScreenRenderer.java
similarity index 96%
rename from framework/widget/src/org/ofbiz/widget/text/TextScreenRenderer.java
rename to framework/widget/src/org/ofbiz/widget/renderer/text/TextScreenRenderer.java
index 74c3a2f..9843f1c 100644
--- a/framework/widget/src/org/ofbiz/widget/text/TextScreenRenderer.java
+++ b/framework/widget/src/org/ofbiz/widget/renderer/text/TextScreenRenderer.java
@@ -1,153 +1,153 @@
-/*******************************************************************************
- * 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.text;
-
-import java.io.IOException;
-import java.util.Map;
-
-import org.ofbiz.base.util.GeneralException;
-import org.ofbiz.base.util.UtilValidate;
-import org.ofbiz.widget.screen.ModelScreenWidget;
-import org.ofbiz.widget.screen.ScreenStringRenderer;
-import org.ofbiz.widget.screen.ModelScreenWidget.ColumnContainer;
-import org.ofbiz.entity.GenericValue;
-
-/**
- * Widget Library - Text Screen Renderer implementation
- * @deprecated Use MacroScreenRenderer.
- */
-public class TextScreenRenderer implements ScreenStringRenderer {
-
-    public static final String module = TextScreenRenderer.class.getName();
-
-    public TextScreenRenderer() {}
-
-    public String getRendererName() {
-        return "text";
-    }
-
-    public void renderScreenBegin(Appendable writer, Map<String, Object> context) throws IOException {
-    }
-
-    public void renderScreenEnd(Appendable writer, Map<String, Object> context) throws IOException {
-    }
-
-    public void renderSectionBegin(Appendable writer, Map<String, Object> context, ModelScreenWidget.Section section) throws IOException {
-        // do nothing, this is just a place holder container for HTML
-    }
-    public void renderSectionEnd(Appendable writer, Map<String, Object> context, ModelScreenWidget.Section section) throws IOException {
-        // do nothing, this is just a place holder container for HTML
-    }
-
-    public void renderContainerBegin(Appendable writer, Map<String, Object> context, ModelScreenWidget.Container container) throws IOException {
-    }
-    public void renderContainerEnd(Appendable writer, Map<String, Object> context, ModelScreenWidget.Container container) throws IOException {
-        appendWhitespace(writer);
-    }
-
-    public void renderLabel(Appendable writer, Map<String, Object> context, ModelScreenWidget.Label label) throws IOException {
-        String labelText = label.getText(context);
-        if (UtilValidate.isEmpty(labelText)) {
-            // nothing to render
-            return;
-        }
-        writer.append(labelText);
-        appendWhitespace(writer);
-    }
-
-    public void renderHorizontalSeparator(Appendable writer, Map<String, Object> context, ModelScreenWidget.HorizontalSeparator separator) throws IOException {
-        // TODO: not implemented
-    }
-
-    public void renderLink(Appendable writer, Map<String, Object> context, ModelScreenWidget.ScreenLink link) throws IOException {
-        // TODO: not implemented
-    }
-
-    public void renderImage(Appendable writer, Map<String, Object> context, ModelScreenWidget.ScreenImage image) throws IOException {
-        // TODO: not implemented
-    }
-
-    public void renderContentBegin(Appendable writer, Map<String, Object> context, ModelScreenWidget.Content content) throws IOException {
-        // TODO: not implemented
-    }
-
-    public void renderContentBody(Appendable writer, Map<String, Object> context, ModelScreenWidget.Content content) throws IOException {
-        // TODO: not implemented
-    }
-
-    public void renderContentEnd(Appendable writer, Map<String, Object> context, ModelScreenWidget.Content content) throws IOException {
-        // TODO: not implemented
-    }
-
-    public void renderContentFrame(Appendable writer, Map<String, Object> context, ModelScreenWidget.Content content) throws IOException {
-        // TODO: not implemented
-    }
-
-    public void renderSubContentBegin(Appendable writer, Map<String, Object> context, ModelScreenWidget.SubContent content) throws IOException {
-        // TODO: not implemented
-    }
-
-    public void renderSubContentBody(Appendable writer, Map<String, Object> context, ModelScreenWidget.SubContent content) throws IOException {
-        // TODO: not implemented
-    }
-
-    public void renderSubContentEnd(Appendable writer, Map<String, Object> context, ModelScreenWidget.SubContent content) throws IOException {
-        // TODO: not implemented
-    }
-
-    public void appendWhitespace(Appendable writer) throws IOException {
-        // appending line ends for now, but this could be replaced with a simple space or something
-        writer.append("\r\n");
-    }
-    public void renderScreenletBegin(Appendable writer, Map<String, Object> context, boolean collapsed, ModelScreenWidget.Screenlet screenlet) throws IOException {
-        // TODO: not implemented
-    }
-    public void renderScreenletSubWidget(Appendable writer, Map<String, Object> context, ModelScreenWidget subWidget, ModelScreenWidget.Screenlet screenlet) throws GeneralException {
-        // TODO: not implemented
-    }
-    public void renderScreenletEnd(Appendable writer, Map<String, Object> context, ModelScreenWidget.Screenlet screenlet) throws IOException {
-        // TODO: not implemented
-    }
-    public void renderPortalPageBegin(Appendable writer, Map<String, Object> context, ModelScreenWidget.PortalPage portalPage) throws GeneralException, IOException {
-        // TODO: not implemented
-    }
-    public void renderPortalPageEnd(Appendable writer, Map<String, Object> context, ModelScreenWidget.PortalPage portalPage) throws GeneralException, IOException {
-        // TODO: not implemented
-    }
-    public void renderPortalPageColumnBegin(Appendable writer, Map<String, Object> context, ModelScreenWidget.PortalPage portalPage, GenericValue portalPageColumn) throws GeneralException, IOException {
-        // TODO: not implemented
-    }
-    public void renderPortalPageColumnEnd(Appendable writer, Map<String, Object> context, ModelScreenWidget.PortalPage portalPage, GenericValue portalPageColumn) throws GeneralException, IOException {
-        // TODO: not implemented
-    }
-    public void renderPortalPagePortletBegin(Appendable writer, Map<String, Object> context, ModelScreenWidget.PortalPage portalPage, GenericValue portalPortlet) throws GeneralException, IOException {
-        // TODO: not implemented
-    }
-    public void renderPortalPagePortletEnd(Appendable writer, Map<String, Object> context, ModelScreenWidget.PortalPage portalPage, GenericValue portalPortlet) throws GeneralException, IOException {
-        // TODO: not implemented
-    }
-    public void renderPortalPagePortletBody(Appendable writer, Map<String, Object> context, ModelScreenWidget.PortalPage portalPage, GenericValue portalPortlet) throws GeneralException, IOException {
-        // TODO: not implemented
-    }
-
-    @Override
-    public void renderColumnContainer(Appendable writer, Map<String, Object> context, ColumnContainer columnContainer) throws IOException {
-        // TODO: not implemented
-    }
-}
+/*******************************************************************************

+ * 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.renderer.text;

+

+import java.io.IOException;

+import java.util.Map;

+

+import org.ofbiz.base.util.GeneralException;

+import org.ofbiz.base.util.UtilValidate;

+import org.ofbiz.entity.GenericValue;

+import org.ofbiz.widget.model.ModelScreenWidget;

+import org.ofbiz.widget.model.ModelScreenWidget.ColumnContainer;

+import org.ofbiz.widget.renderer.ScreenStringRenderer;

+

+/**

+ * Widget Library - Text Screen Renderer implementation

+ * @deprecated Use MacroScreenRenderer.

+ */

+public class TextScreenRenderer implements ScreenStringRenderer {

+

+    public static final String module = TextScreenRenderer.class.getName();

+

+    public TextScreenRenderer() {}

+

+    public String getRendererName() {

+        return "text";

+    }

+

+    public void renderScreenBegin(Appendable writer, Map<String, Object> context) throws IOException {

+    }

+

+    public void renderScreenEnd(Appendable writer, Map<String, Object> context) throws IOException {

+    }

+

+    public void renderSectionBegin(Appendable writer, Map<String, Object> context, ModelScreenWidget.Section section) throws IOException {

+        // do nothing, this is just a place holder container for HTML

+    }

+    public void renderSectionEnd(Appendable writer, Map<String, Object> context, ModelScreenWidget.Section section) throws IOException {

+        // do nothing, this is just a place holder container for HTML

+    }

+

+    public void renderContainerBegin(Appendable writer, Map<String, Object> context, ModelScreenWidget.Container container) throws IOException {

+    }

+    public void renderContainerEnd(Appendable writer, Map<String, Object> context, ModelScreenWidget.Container container) throws IOException {

+        appendWhitespace(writer);

+    }

+

+    public void renderLabel(Appendable writer, Map<String, Object> context, ModelScreenWidget.Label label) throws IOException {

+        String labelText = label.getText(context);

+        if (UtilValidate.isEmpty(labelText)) {

+            // nothing to render

+            return;

+        }

+        writer.append(labelText);

+        appendWhitespace(writer);

+    }

+

+    public void renderHorizontalSeparator(Appendable writer, Map<String, Object> context, ModelScreenWidget.HorizontalSeparator separator) throws IOException {

+        // TODO: not implemented

+    }

+

+    public void renderLink(Appendable writer, Map<String, Object> context, ModelScreenWidget.ScreenLink link) throws IOException {

+        // TODO: not implemented

+    }

+

+    public void renderImage(Appendable writer, Map<String, Object> context, ModelScreenWidget.ScreenImage image) throws IOException {

+        // TODO: not implemented

+    }

+

+    public void renderContentBegin(Appendable writer, Map<String, Object> context, ModelScreenWidget.Content content) throws IOException {

+        // TODO: not implemented

+    }

+

+    public void renderContentBody(Appendable writer, Map<String, Object> context, ModelScreenWidget.Content content) throws IOException {

+        // TODO: not implemented

+    }

+

+    public void renderContentEnd(Appendable writer, Map<String, Object> context, ModelScreenWidget.Content content) throws IOException {

+        // TODO: not implemented

+    }

+

+    public void renderContentFrame(Appendable writer, Map<String, Object> context, ModelScreenWidget.Content content) throws IOException {

+        // TODO: not implemented

+    }

+

+    public void renderSubContentBegin(Appendable writer, Map<String, Object> context, ModelScreenWidget.SubContent content) throws IOException {

+        // TODO: not implemented

+    }

+

+    public void renderSubContentBody(Appendable writer, Map<String, Object> context, ModelScreenWidget.SubContent content) throws IOException {

+        // TODO: not implemented

+    }

+

+    public void renderSubContentEnd(Appendable writer, Map<String, Object> context, ModelScreenWidget.SubContent content) throws IOException {

+        // TODO: not implemented

+    }

+

+    public void appendWhitespace(Appendable writer) throws IOException {

+        // appending line ends for now, but this could be replaced with a simple space or something

+        writer.append("\r\n");

+    }

+    public void renderScreenletBegin(Appendable writer, Map<String, Object> context, boolean collapsed, ModelScreenWidget.Screenlet screenlet) throws IOException {

+        // TODO: not implemented

+    }

+    public void renderScreenletSubWidget(Appendable writer, Map<String, Object> context, ModelScreenWidget subWidget, ModelScreenWidget.Screenlet screenlet) throws GeneralException {

+        // TODO: not implemented

+    }

+    public void renderScreenletEnd(Appendable writer, Map<String, Object> context, ModelScreenWidget.Screenlet screenlet) throws IOException {

+        // TODO: not implemented

+    }

+    public void renderPortalPageBegin(Appendable writer, Map<String, Object> context, ModelScreenWidget.PortalPage portalPage) throws GeneralException, IOException {

+        // TODO: not implemented

+    }

+    public void renderPortalPageEnd(Appendable writer, Map<String, Object> context, ModelScreenWidget.PortalPage portalPage) throws GeneralException, IOException {

+        // TODO: not implemented

+    }

+    public void renderPortalPageColumnBegin(Appendable writer, Map<String, Object> context, ModelScreenWidget.PortalPage portalPage, GenericValue portalPageColumn) throws GeneralException, IOException {

+        // TODO: not implemented

+    }

+    public void renderPortalPageColumnEnd(Appendable writer, Map<String, Object> context, ModelScreenWidget.PortalPage portalPage, GenericValue portalPageColumn) throws GeneralException, IOException {

+        // TODO: not implemented

+    }

+    public void renderPortalPagePortletBegin(Appendable writer, Map<String, Object> context, ModelScreenWidget.PortalPage portalPage, GenericValue portalPortlet) throws GeneralException, IOException {

+        // TODO: not implemented

+    }

+    public void renderPortalPagePortletEnd(Appendable writer, Map<String, Object> context, ModelScreenWidget.PortalPage portalPage, GenericValue portalPortlet) throws GeneralException, IOException {

+        // TODO: not implemented

+    }

+    public void renderPortalPagePortletBody(Appendable writer, Map<String, Object> context, ModelScreenWidget.PortalPage portalPage, GenericValue portalPortlet) throws GeneralException, IOException {

+        // TODO: not implemented

+    }

+

+    @Override

+    public void renderColumnContainer(Appendable writer, Map<String, Object> context, ColumnContainer columnContainer) throws IOException {

+        // TODO: not implemented

+    }

+}

diff --git a/framework/widget/src/org/ofbiz/widget/xml/XmlFormRenderer.java b/framework/widget/src/org/ofbiz/widget/renderer/xml/XmlFormRenderer.java
similarity index 91%
rename from framework/widget/src/org/ofbiz/widget/xml/XmlFormRenderer.java
rename to framework/widget/src/org/ofbiz/widget/renderer/xml/XmlFormRenderer.java
index 3f037b5..a1c49ef 100644
--- a/framework/widget/src/org/ofbiz/widget/xml/XmlFormRenderer.java
+++ b/framework/widget/src/org/ofbiz/widget/renderer/xml/XmlFormRenderer.java
@@ -1,343 +1,343 @@
-/*******************************************************************************
- * 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.xml;
-
-import java.io.IOException;
-import java.util.List;
-import java.util.Map;
-
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.ofbiz.base.util.UtilValidate;
-import org.ofbiz.widget.WidgetWorker;
-import org.ofbiz.widget.form.FormStringRenderer;
-import org.ofbiz.widget.form.ModelForm;
-import org.ofbiz.widget.form.ModelFormField;
-import org.ofbiz.widget.form.ModelFormField.CheckField;
-import org.ofbiz.widget.form.ModelFormField.ContainerField;
-import org.ofbiz.widget.form.ModelFormField.DateFindField;
-import org.ofbiz.widget.form.ModelFormField.DateTimeField;
-import org.ofbiz.widget.form.ModelFormField.DisplayField;
-import org.ofbiz.widget.form.ModelFormField.DropDownField;
-import org.ofbiz.widget.form.ModelFormField.FieldInfoWithOptions;
-import org.ofbiz.widget.form.ModelFormField.FileField;
-import org.ofbiz.widget.form.ModelFormField.HiddenField;
-import org.ofbiz.widget.form.ModelFormField.HyperlinkField;
-import org.ofbiz.widget.form.ModelFormField.IgnoredField;
-import org.ofbiz.widget.form.ModelFormField.ImageField;
-import org.ofbiz.widget.form.ModelFormField.LookupField;
-import org.ofbiz.widget.form.ModelFormField.PasswordField;
-import org.ofbiz.widget.form.ModelFormField.RadioField;
-import org.ofbiz.widget.form.ModelFormField.RangeFindField;
-import org.ofbiz.widget.form.ModelFormField.ResetField;
-import org.ofbiz.widget.form.ModelFormField.SubmitField;
-import org.ofbiz.widget.form.ModelFormField.TextField;
-import org.ofbiz.widget.form.ModelFormField.TextFindField;
-import org.ofbiz.widget.form.ModelFormField.TextareaField;
-
-
-/**
- * Widget Library - Xml Form Renderer implementation
- *
- */
-public class XmlFormRenderer implements FormStringRenderer {
-
-    public static final String module = XmlFormRenderer.class.getName();
-
-    HttpServletRequest request;
-    HttpServletResponse response;
-
-    protected XmlFormRenderer() throws IOException {}
-
-    public XmlFormRenderer(HttpServletRequest request, HttpServletResponse response) throws IOException {
-        this.request = request;
-        this.response = response;
-    }
-
-    public void appendWhitespace(Appendable writer) throws IOException {
-        // appending line ends for now, but this could be replaced with a simple space or something
-        writer.append("\r\n");
-        //writer.append(' ');
-    }
-
-    private void makeTextString(Appendable writer, String widgetStyle, String text) throws IOException {
-        // TODO: escape characters here
-        writer.append(text);
-    }
-
-    public void renderDisplayField(Appendable writer, Map<String, Object> context, DisplayField displayField) throws IOException {
-        ModelFormField modelFormField = displayField.getModelFormField();
-        this.makeTextString(writer, modelFormField.getWidgetStyle(), displayField.getDescription(context));
-        this.appendWhitespace(writer);
-    }
-
-    public void renderHyperlinkField(Appendable writer, Map<String, Object> context, HyperlinkField hyperlinkField) throws IOException {
-        ModelFormField modelFormField = hyperlinkField.getModelFormField();
-        this.makeTextString(writer, modelFormField.getWidgetStyle(), hyperlinkField.getDescription(context));
-        this.appendWhitespace(writer);
-    }
-
-    public void renderTextField(Appendable writer, Map<String, Object> context, TextField textField) throws IOException {
-        ModelFormField modelFormField = textField.getModelFormField();
-        this.makeTextString(writer, modelFormField.getWidgetStyle(), modelFormField.getEntry(context, textField.getDefaultValue(context)));
-        this.appendWhitespace(writer);
-    }
-
-    public void renderTextareaField(Appendable writer, Map<String, Object> context, TextareaField textareaField) throws IOException {
-        ModelFormField modelFormField = textareaField.getModelFormField();
-        this.makeTextString(writer, modelFormField.getWidgetStyle(), modelFormField.getEntry(context, textareaField.getDefaultValue(context)));
-        this.appendWhitespace(writer);
-    }
-
-    public void renderDateTimeField(Appendable writer, Map<String, Object> context, DateTimeField dateTimeField) throws IOException {
-        ModelFormField modelFormField = dateTimeField.getModelFormField();
-        this.makeTextString(writer, modelFormField.getWidgetStyle(), modelFormField.getEntry(context, dateTimeField.getDefaultValue(context)));
-        this.appendWhitespace(writer);
-    }
-
-    public void renderDropDownField(Appendable writer, Map<String, Object> context, DropDownField dropDownField) throws IOException {
-        ModelFormField modelFormField = dropDownField.getModelFormField();
-        String currentValue = modelFormField.getEntry(context);
-        List<ModelFormField.OptionValue> allOptionValues = dropDownField.getAllOptionValues(context, WidgetWorker.getDelegator(context));
-        // if the current value should go first, display it
-        if (UtilValidate.isNotEmpty(currentValue) && "first-in-list".equals(dropDownField.getCurrent())) {
-            String explicitDescription = dropDownField.getCurrentDescription(context);
-            if (UtilValidate.isNotEmpty(explicitDescription)) {
-                this.makeTextString(writer, modelFormField.getWidgetStyle(), explicitDescription);
-            } else {
-                this.makeTextString(writer, modelFormField.getWidgetStyle(), FieldInfoWithOptions.getDescriptionForOptionKey(currentValue, allOptionValues));
-            }
-        } else {
-            for (ModelFormField.OptionValue optionValue : allOptionValues) {
-                String noCurrentSelectedKey = dropDownField.getNoCurrentSelectedKey(context);
-                if ((UtilValidate.isNotEmpty(currentValue) && currentValue.equals(optionValue.getKey()) && "selected".equals(dropDownField.getCurrent())) ||
-                        (UtilValidate.isEmpty(currentValue) && noCurrentSelectedKey != null && noCurrentSelectedKey.equals(optionValue.getKey()))) {
-                    this.makeTextString(writer, modelFormField.getWidgetStyle(), optionValue.getDescription());
-                    break;
-                }
-            }
-        }
-        this.appendWhitespace(writer);
-    }
-
-    public void renderCheckField(Appendable writer, Map<String, Object> context, CheckField checkField) throws IOException {
-    }
-
-    public void renderRadioField(Appendable writer, Map<String, Object> context, RadioField radioField) throws IOException {
-    }
-
-    public void renderSubmitField(Appendable writer, Map<String, Object> context, SubmitField submitField) throws IOException {
-    }
-
-    public void renderResetField(Appendable writer, Map<String, Object> context, ResetField resetField) throws IOException {
-    }
-
-    public void renderHiddenField(Appendable writer, Map<String, Object> context, HiddenField hiddenField) throws IOException {
-    }
-
-    public void renderHiddenField(Appendable writer, Map<String, Object> context, ModelFormField modelFormField, String value) throws IOException {
-    }
-
-    public void renderIgnoredField(Appendable writer, Map<String, Object> context, IgnoredField ignoredField) throws IOException {
-    }
-
-    public void renderFieldTitle(Appendable writer, Map<String, Object> context, ModelFormField modelFormField) throws IOException {
-    }
-
-    public void renderSingleFormFieldTitle(Appendable writer, Map<String, Object> context, ModelFormField modelFormField) throws IOException {
-        renderFieldTitle(writer, context, modelFormField);
-    }
-
-    public void renderFormOpen(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {
-    }
-
-    public void renderFormClose(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {
-    }
-
-    public void renderMultiFormClose(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {
-    }
-
-    public void renderFormatListWrapperOpen(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {
-        writer.append("<");
-        writer.append(modelForm.getName());
-        writer.append("Export>");
-        this.appendWhitespace(writer);
-    }
-
-    public void renderFormatListWrapperClose(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {
-        writer.append("</");
-        writer.append(modelForm.getName());
-        writer.append("Export>");
-        this.appendWhitespace(writer);
-    }
-
-    public void renderFormatHeaderRowOpen(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {
-    }
-
-    public void renderFormatHeaderRowClose(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {
-    }
-
-    public void renderFormatHeaderRowCellOpen(Appendable writer, Map<String, Object> context, ModelForm modelForm, ModelFormField modelFormField, int positionSpan) throws IOException {
-    }
-
-    public void renderFormatHeaderRowCellClose(Appendable writer, Map<String, Object> context, ModelForm modelForm, ModelFormField modelFormField) throws IOException {
-    }
-
-    public void renderFormatHeaderRowFormCellOpen(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {
-    }
-
-    public void renderFormatHeaderRowFormCellClose(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {
-    }
-
-    public void renderFormatHeaderRowFormCellTitleSeparator(Appendable writer, Map<String, Object> context, ModelForm modelForm, ModelFormField modelFormField, boolean isLast) throws IOException {
-    }
-
-    public void renderFormatItemRowOpen(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {
-        writer.append("<");
-        writer.append(modelForm.getName());
-        writer.append(">");
-        this.appendWhitespace(writer);
-    }
-
-    public void renderFormatItemRowClose(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {
-        writer.append("</");
-        writer.append(modelForm.getName());
-        writer.append(">");
-        this.appendWhitespace(writer);
-    }
-
-    public void renderFormatItemRowCellOpen(Appendable writer, Map<String, Object> context, ModelForm modelForm, ModelFormField modelFormField, int positionSpan) throws IOException {
-        writer.append("<");
-        writer.append(modelFormField.getName());
-        writer.append(">");
-        this.appendWhitespace(writer);
-    }
-
-    public void renderFormatItemRowCellClose(Appendable writer, Map<String, Object> context, ModelForm modelForm, ModelFormField modelFormField) throws IOException {
-        writer.append("</");
-        writer.append(modelFormField.getName());
-        writer.append(">");
-        this.appendWhitespace(writer);
-    }
-
-    public void renderFormatItemRowFormCellOpen(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {
-    }
-
-    public void renderFormatItemRowFormCellClose(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {
-    }
-
-    public void renderFormatSingleWrapperOpen(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {
-        writer.append("<");
-        writer.append(modelForm.getName());
-        writer.append("Export>");
-        this.appendWhitespace(writer);
-    }
-
-    public void renderFormatSingleWrapperClose(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {
-        writer.append("</");
-        writer.append(modelForm.getName());
-        writer.append("Export>");
-        this.appendWhitespace(writer);
-    }
-
-    public void renderFormatFieldRowOpen(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {
-    }
-
-    public void renderFormatFieldRowClose(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {
-    }
-
-
-    public void renderFormatFieldRowTitleCellOpen(Appendable writer, Map<String, Object> context, ModelFormField modelFormField) throws IOException {
-    }
-
-    public void renderFormatFieldRowTitleCellClose(Appendable writer, Map<String, Object> context, ModelFormField modelFormField) throws IOException {
-    }
-
-    public void renderFormatFieldRowSpacerCell(Appendable writer, Map<String, Object> context, ModelFormField modelFormField) throws IOException {
-    }
-
-    public void renderFormatFieldRowWidgetCellOpen(Appendable writer, Map<String, Object> context, ModelFormField modelFormField, int positions, int positionSpan, Integer nextPositionInRow) throws IOException {
-    }
-
-    public void renderFormatFieldRowWidgetCellClose(Appendable writer, Map<String, Object> context, ModelFormField modelFormField, int positions, int positionSpan, Integer nextPositionInRow) throws IOException {
-    }
-
-    public void renderFormatEmptySpace(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {
-        // TODO
-    }
-
-    public void renderTextFindField(Appendable writer, Map<String, Object> context, TextFindField textFindField) throws IOException {
-        ModelFormField modelFormField = textFindField.getModelFormField();
-        this.makeTextString(writer, modelFormField.getWidgetStyle(), modelFormField.getEntry(context, textFindField.getDefaultValue(context)));
-        this.appendWhitespace(writer);
-    }
-
-    public void renderRangeFindField(Appendable writer, Map<String, Object> context, RangeFindField rangeFindField) throws IOException {
-        ModelFormField modelFormField = rangeFindField.getModelFormField();
-        this.makeTextString(writer, modelFormField.getWidgetStyle(), modelFormField.getEntry(context, rangeFindField.getDefaultValue(context)));
-        this.appendWhitespace(writer);
-    }
-
-    public void renderDateFindField(Appendable writer, Map<String, Object> context, DateFindField dateFindField) throws IOException {
-        ModelFormField modelFormField = dateFindField.getModelFormField();
-        this.makeTextString(writer, modelFormField.getWidgetStyle(), modelFormField.getEntry(context, dateFindField.getDefaultValue(context)));
-        this.appendWhitespace(writer);
-    }
-
-    public void renderLookupField(Appendable writer, Map<String, Object> context, LookupField lookupField) throws IOException {
-        ModelFormField modelFormField = lookupField.getModelFormField();
-        this.makeTextString(writer, modelFormField.getWidgetStyle(), modelFormField.getEntry(context, lookupField.getDefaultValue(context)));
-        this.appendWhitespace(writer);
-    }
-
-    public void renderNextPrev(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {
-    }
-
-    public void renderFileField(Appendable writer, Map<String, Object> context, FileField textField) throws IOException {
-        ModelFormField modelFormField = textField.getModelFormField();
-        this.makeTextString(writer, modelFormField.getWidgetStyle(), modelFormField.getEntry(context, textField.getDefaultValue(context)));
-        this.appendWhitespace(writer);
-    }
-
-    public void renderPasswordField(Appendable writer, Map<String, Object> context, PasswordField passwordField) throws IOException {
-    }
-
-    public void renderImageField(Appendable writer, Map<String, Object> context, ImageField imageField) throws IOException {
-        // TODO
-    }
-
-    public void renderFieldGroupOpen(Appendable writer, Map<String, Object> context, ModelForm.FieldGroup fieldGroup) throws IOException {
-        // TODO
-    }
-
-    public void renderFieldGroupClose(Appendable writer, Map<String, Object> context, ModelForm.FieldGroup fieldGroup) throws IOException {
-        // TODO
-    }
-
-    public void renderBanner(Appendable writer, Map<String, Object> context, ModelForm.Banner banner) throws IOException {
-        // TODO
-    }
-
-    public void renderHyperlinkTitle(Appendable writer, Map<String, Object> context, ModelFormField modelFormField, String titleText) throws IOException {
-    }
-
-    public void renderContainerFindField(Appendable writer, Map<String, Object> context, ContainerField containerField) throws IOException {
-    }
-}
+/*******************************************************************************

+ * 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.renderer.xml;

+

+import java.io.IOException;

+import java.util.List;

+import java.util.Map;

+

+import javax.servlet.http.HttpServletRequest;

+import javax.servlet.http.HttpServletResponse;

+

+import org.ofbiz.base.util.UtilValidate;

+import org.ofbiz.widget.WidgetWorker;

+import org.ofbiz.widget.model.ModelForm;

+import org.ofbiz.widget.model.ModelFormField;

+import org.ofbiz.widget.model.ModelFormField.CheckField;

+import org.ofbiz.widget.model.ModelFormField.ContainerField;

+import org.ofbiz.widget.model.ModelFormField.DateFindField;

+import org.ofbiz.widget.model.ModelFormField.DateTimeField;

+import org.ofbiz.widget.model.ModelFormField.DisplayField;

+import org.ofbiz.widget.model.ModelFormField.DropDownField;

+import org.ofbiz.widget.model.ModelFormField.FieldInfoWithOptions;

+import org.ofbiz.widget.model.ModelFormField.FileField;

+import org.ofbiz.widget.model.ModelFormField.HiddenField;

+import org.ofbiz.widget.model.ModelFormField.HyperlinkField;

+import org.ofbiz.widget.model.ModelFormField.IgnoredField;

+import org.ofbiz.widget.model.ModelFormField.ImageField;

+import org.ofbiz.widget.model.ModelFormField.LookupField;

+import org.ofbiz.widget.model.ModelFormField.PasswordField;

+import org.ofbiz.widget.model.ModelFormField.RadioField;

+import org.ofbiz.widget.model.ModelFormField.RangeFindField;

+import org.ofbiz.widget.model.ModelFormField.ResetField;

+import org.ofbiz.widget.model.ModelFormField.SubmitField;

+import org.ofbiz.widget.model.ModelFormField.TextField;

+import org.ofbiz.widget.model.ModelFormField.TextFindField;

+import org.ofbiz.widget.model.ModelFormField.TextareaField;

+import org.ofbiz.widget.renderer.FormStringRenderer;

+

+

+/**

+ * Widget Library - Xml Form Renderer implementation

+ *

+ */

+public class XmlFormRenderer implements FormStringRenderer {

+

+    public static final String module = XmlFormRenderer.class.getName();

+

+    HttpServletRequest request;

+    HttpServletResponse response;

+

+    protected XmlFormRenderer() throws IOException {}

+

+    public XmlFormRenderer(HttpServletRequest request, HttpServletResponse response) throws IOException {

+        this.request = request;

+        this.response = response;

+    }

+

+    public void appendWhitespace(Appendable writer) throws IOException {

+        // appending line ends for now, but this could be replaced with a simple space or something

+        writer.append("\r\n");

+        //writer.append(' ');

+    }

+

+    private void makeTextString(Appendable writer, String widgetStyle, String text) throws IOException {

+        // TODO: escape characters here

+        writer.append(text);

+    }

+

+    public void renderDisplayField(Appendable writer, Map<String, Object> context, DisplayField displayField) throws IOException {

+        ModelFormField modelFormField = displayField.getModelFormField();

+        this.makeTextString(writer, modelFormField.getWidgetStyle(), displayField.getDescription(context));

+        this.appendWhitespace(writer);

+    }

+

+    public void renderHyperlinkField(Appendable writer, Map<String, Object> context, HyperlinkField hyperlinkField) throws IOException {

+        ModelFormField modelFormField = hyperlinkField.getModelFormField();

+        this.makeTextString(writer, modelFormField.getWidgetStyle(), hyperlinkField.getDescription(context));

+        this.appendWhitespace(writer);

+    }

+

+    public void renderTextField(Appendable writer, Map<String, Object> context, TextField textField) throws IOException {

+        ModelFormField modelFormField = textField.getModelFormField();

+        this.makeTextString(writer, modelFormField.getWidgetStyle(), modelFormField.getEntry(context, textField.getDefaultValue(context)));

+        this.appendWhitespace(writer);

+    }

+

+    public void renderTextareaField(Appendable writer, Map<String, Object> context, TextareaField textareaField) throws IOException {

+        ModelFormField modelFormField = textareaField.getModelFormField();

+        this.makeTextString(writer, modelFormField.getWidgetStyle(), modelFormField.getEntry(context, textareaField.getDefaultValue(context)));

+        this.appendWhitespace(writer);

+    }

+

+    public void renderDateTimeField(Appendable writer, Map<String, Object> context, DateTimeField dateTimeField) throws IOException {

+        ModelFormField modelFormField = dateTimeField.getModelFormField();

+        this.makeTextString(writer, modelFormField.getWidgetStyle(), modelFormField.getEntry(context, dateTimeField.getDefaultValue(context)));

+        this.appendWhitespace(writer);

+    }

+

+    public void renderDropDownField(Appendable writer, Map<String, Object> context, DropDownField dropDownField) throws IOException {

+        ModelFormField modelFormField = dropDownField.getModelFormField();

+        String currentValue = modelFormField.getEntry(context);

+        List<ModelFormField.OptionValue> allOptionValues = dropDownField.getAllOptionValues(context, WidgetWorker.getDelegator(context));

+        // if the current value should go first, display it

+        if (UtilValidate.isNotEmpty(currentValue) && "first-in-list".equals(dropDownField.getCurrent())) {

+            String explicitDescription = dropDownField.getCurrentDescription(context);

+            if (UtilValidate.isNotEmpty(explicitDescription)) {

+                this.makeTextString(writer, modelFormField.getWidgetStyle(), explicitDescription);

+            } else {

+                this.makeTextString(writer, modelFormField.getWidgetStyle(), FieldInfoWithOptions.getDescriptionForOptionKey(currentValue, allOptionValues));

+            }

+        } else {

+            for (ModelFormField.OptionValue optionValue : allOptionValues) {

+                String noCurrentSelectedKey = dropDownField.getNoCurrentSelectedKey(context);

+                if ((UtilValidate.isNotEmpty(currentValue) && currentValue.equals(optionValue.getKey()) && "selected".equals(dropDownField.getCurrent())) ||

+                        (UtilValidate.isEmpty(currentValue) && noCurrentSelectedKey != null && noCurrentSelectedKey.equals(optionValue.getKey()))) {

+                    this.makeTextString(writer, modelFormField.getWidgetStyle(), optionValue.getDescription());

+                    break;

+                }

+            }

+        }

+        this.appendWhitespace(writer);

+    }

+

+    public void renderCheckField(Appendable writer, Map<String, Object> context, CheckField checkField) throws IOException {

+    }

+

+    public void renderRadioField(Appendable writer, Map<String, Object> context, RadioField radioField) throws IOException {

+    }

+

+    public void renderSubmitField(Appendable writer, Map<String, Object> context, SubmitField submitField) throws IOException {

+    }

+

+    public void renderResetField(Appendable writer, Map<String, Object> context, ResetField resetField) throws IOException {

+    }

+

+    public void renderHiddenField(Appendable writer, Map<String, Object> context, HiddenField hiddenField) throws IOException {

+    }

+

+    public void renderHiddenField(Appendable writer, Map<String, Object> context, ModelFormField modelFormField, String value) throws IOException {

+    }

+

+    public void renderIgnoredField(Appendable writer, Map<String, Object> context, IgnoredField ignoredField) throws IOException {

+    }

+

+    public void renderFieldTitle(Appendable writer, Map<String, Object> context, ModelFormField modelFormField) throws IOException {

+    }

+

+    public void renderSingleFormFieldTitle(Appendable writer, Map<String, Object> context, ModelFormField modelFormField) throws IOException {

+        renderFieldTitle(writer, context, modelFormField);

+    }

+

+    public void renderFormOpen(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {

+    }

+

+    public void renderFormClose(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {

+    }

+

+    public void renderMultiFormClose(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {

+    }

+

+    public void renderFormatListWrapperOpen(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {

+        writer.append("<");

+        writer.append(modelForm.getName());

+        writer.append("Export>");

+        this.appendWhitespace(writer);

+    }

+

+    public void renderFormatListWrapperClose(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {

+        writer.append("</");

+        writer.append(modelForm.getName());

+        writer.append("Export>");

+        this.appendWhitespace(writer);

+    }

+

+    public void renderFormatHeaderRowOpen(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {

+    }

+

+    public void renderFormatHeaderRowClose(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {

+    }

+

+    public void renderFormatHeaderRowCellOpen(Appendable writer, Map<String, Object> context, ModelForm modelForm, ModelFormField modelFormField, int positionSpan) throws IOException {

+    }

+

+    public void renderFormatHeaderRowCellClose(Appendable writer, Map<String, Object> context, ModelForm modelForm, ModelFormField modelFormField) throws IOException {

+    }

+

+    public void renderFormatHeaderRowFormCellOpen(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {

+    }

+

+    public void renderFormatHeaderRowFormCellClose(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {

+    }

+

+    public void renderFormatHeaderRowFormCellTitleSeparator(Appendable writer, Map<String, Object> context, ModelForm modelForm, ModelFormField modelFormField, boolean isLast) throws IOException {

+    }

+

+    public void renderFormatItemRowOpen(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {

+        writer.append("<");

+        writer.append(modelForm.getName());

+        writer.append(">");

+        this.appendWhitespace(writer);

+    }

+

+    public void renderFormatItemRowClose(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {

+        writer.append("</");

+        writer.append(modelForm.getName());

+        writer.append(">");

+        this.appendWhitespace(writer);

+    }

+

+    public void renderFormatItemRowCellOpen(Appendable writer, Map<String, Object> context, ModelForm modelForm, ModelFormField modelFormField, int positionSpan) throws IOException {

+        writer.append("<");

+        writer.append(modelFormField.getName());

+        writer.append(">");

+        this.appendWhitespace(writer);

+    }

+

+    public void renderFormatItemRowCellClose(Appendable writer, Map<String, Object> context, ModelForm modelForm, ModelFormField modelFormField) throws IOException {

+        writer.append("</");

+        writer.append(modelFormField.getName());

+        writer.append(">");

+        this.appendWhitespace(writer);

+    }

+

+    public void renderFormatItemRowFormCellOpen(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {

+    }

+

+    public void renderFormatItemRowFormCellClose(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {

+    }

+

+    public void renderFormatSingleWrapperOpen(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {

+        writer.append("<");

+        writer.append(modelForm.getName());

+        writer.append("Export>");

+        this.appendWhitespace(writer);

+    }

+

+    public void renderFormatSingleWrapperClose(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {

+        writer.append("</");

+        writer.append(modelForm.getName());

+        writer.append("Export>");

+        this.appendWhitespace(writer);

+    }

+

+    public void renderFormatFieldRowOpen(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {

+    }

+

+    public void renderFormatFieldRowClose(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {

+    }

+

+

+    public void renderFormatFieldRowTitleCellOpen(Appendable writer, Map<String, Object> context, ModelFormField modelFormField) throws IOException {

+    }

+

+    public void renderFormatFieldRowTitleCellClose(Appendable writer, Map<String, Object> context, ModelFormField modelFormField) throws IOException {

+    }

+

+    public void renderFormatFieldRowSpacerCell(Appendable writer, Map<String, Object> context, ModelFormField modelFormField) throws IOException {

+    }

+

+    public void renderFormatFieldRowWidgetCellOpen(Appendable writer, Map<String, Object> context, ModelFormField modelFormField, int positions, int positionSpan, Integer nextPositionInRow) throws IOException {

+    }

+

+    public void renderFormatFieldRowWidgetCellClose(Appendable writer, Map<String, Object> context, ModelFormField modelFormField, int positions, int positionSpan, Integer nextPositionInRow) throws IOException {

+    }

+

+    public void renderFormatEmptySpace(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {

+        // TODO

+    }

+

+    public void renderTextFindField(Appendable writer, Map<String, Object> context, TextFindField textFindField) throws IOException {

+        ModelFormField modelFormField = textFindField.getModelFormField();

+        this.makeTextString(writer, modelFormField.getWidgetStyle(), modelFormField.getEntry(context, textFindField.getDefaultValue(context)));

+        this.appendWhitespace(writer);

+    }

+

+    public void renderRangeFindField(Appendable writer, Map<String, Object> context, RangeFindField rangeFindField) throws IOException {

+        ModelFormField modelFormField = rangeFindField.getModelFormField();

+        this.makeTextString(writer, modelFormField.getWidgetStyle(), modelFormField.getEntry(context, rangeFindField.getDefaultValue(context)));

+        this.appendWhitespace(writer);

+    }

+

+    public void renderDateFindField(Appendable writer, Map<String, Object> context, DateFindField dateFindField) throws IOException {

+        ModelFormField modelFormField = dateFindField.getModelFormField();

+        this.makeTextString(writer, modelFormField.getWidgetStyle(), modelFormField.getEntry(context, dateFindField.getDefaultValue(context)));

+        this.appendWhitespace(writer);

+    }

+

+    public void renderLookupField(Appendable writer, Map<String, Object> context, LookupField lookupField) throws IOException {

+        ModelFormField modelFormField = lookupField.getModelFormField();

+        this.makeTextString(writer, modelFormField.getWidgetStyle(), modelFormField.getEntry(context, lookupField.getDefaultValue(context)));

+        this.appendWhitespace(writer);

+    }

+

+    public void renderNextPrev(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {

+    }

+

+    public void renderFileField(Appendable writer, Map<String, Object> context, FileField textField) throws IOException {

+        ModelFormField modelFormField = textField.getModelFormField();

+        this.makeTextString(writer, modelFormField.getWidgetStyle(), modelFormField.getEntry(context, textField.getDefaultValue(context)));

+        this.appendWhitespace(writer);

+    }

+

+    public void renderPasswordField(Appendable writer, Map<String, Object> context, PasswordField passwordField) throws IOException {

+    }

+

+    public void renderImageField(Appendable writer, Map<String, Object> context, ImageField imageField) throws IOException {

+        // TODO

+    }

+

+    public void renderFieldGroupOpen(Appendable writer, Map<String, Object> context, ModelForm.FieldGroup fieldGroup) throws IOException {

+        // TODO

+    }

+

+    public void renderFieldGroupClose(Appendable writer, Map<String, Object> context, ModelForm.FieldGroup fieldGroup) throws IOException {

+        // TODO

+    }

+

+    public void renderBanner(Appendable writer, Map<String, Object> context, ModelForm.Banner banner) throws IOException {

+        // TODO

+    }

+

+    public void renderHyperlinkTitle(Appendable writer, Map<String, Object> context, ModelFormField modelFormField, String titleText) throws IOException {

+    }

+

+    public void renderContainerFindField(Appendable writer, Map<String, Object> context, ContainerField containerField) throws IOException {

+    }

+}

diff --git a/framework/widget/templates/htmlFormMacroLibrary.ftl b/framework/widget/templates/htmlFormMacroLibrary.ftl
index 1b14fc7..a91dc8c 100644
--- a/framework/widget/templates/htmlFormMacroLibrary.ftl
+++ b/framework/widget/templates/htmlFormMacroLibrary.ftl
@@ -617,7 +617,7 @@
 Parameter: lastViewName, String, optional - If the ajaxEnabled parameter is true, the contents of lastViewName will be appended to the Ajax URL.
 -->
 <#macro renderLookupField name formName fieldFormName className="" alert="false" value="" size="" maxlength="" id="" event="" action="" readonly=false autocomplete="" descriptionFieldName="" targetParameterIter="" imgSrc="" ajaxUrl="" ajaxEnabled=javaScriptEnabled presentation="layer" width="" height="" position="" fadeBackground="true" clearText="" showDescription="" initiallyCollapsed="" lastViewName="main" >
-  <#if Static["org.ofbiz.widget.ModelWidget"].widgetBoundaryCommentsEnabled(context)>
+  <#if Static["org.ofbiz.widget.model.ModelWidget"].widgetBoundaryCommentsEnabled(context)>
   <!-- @renderLookupField -->
   </#if>
   <#if (!ajaxUrl?has_content) && ajaxEnabled?has_content && ajaxEnabled>
diff --git a/specialpurpose/birt/src/org/ofbiz/birt/BirtFactory.java b/specialpurpose/birt/src/org/ofbiz/birt/BirtFactory.java
index 5112344..36e4cc0 100644
--- a/specialpurpose/birt/src/org/ofbiz/birt/BirtFactory.java
+++ b/specialpurpose/birt/src/org/ofbiz/birt/BirtFactory.java
@@ -27,7 +27,7 @@
 import org.eclipse.birt.report.engine.api.IReportEngine;
 import org.ofbiz.base.location.FlexibleLocation;
 import org.ofbiz.base.util.Debug;
-import org.ofbiz.widget.screen.ScreenFactory;
+import org.ofbiz.widget.model.ScreenFactory;
 import org.xml.sax.SAXException;
 
 /**
diff --git a/specialpurpose/birt/src/org/ofbiz/birt/email/BirtEmailServices.java b/specialpurpose/birt/src/org/ofbiz/birt/email/BirtEmailServices.java
index 98f0a4d..ee9082d 100644
--- a/specialpurpose/birt/src/org/ofbiz/birt/email/BirtEmailServices.java
+++ b/specialpurpose/birt/src/org/ofbiz/birt/email/BirtEmailServices.java
@@ -52,8 +52,8 @@
 import org.ofbiz.service.DispatchContext;
 import org.ofbiz.service.LocalDispatcher;
 import org.ofbiz.service.ServiceUtil;
-import org.ofbiz.widget.html.HtmlScreenRenderer;
-import org.ofbiz.widget.screen.ScreenRenderer;
+import org.ofbiz.widget.renderer.ScreenRenderer;
+import org.ofbiz.widget.renderer.html.HtmlScreenRenderer;
 import org.xml.sax.SAXException;
 
 public class BirtEmailServices {
diff --git a/specialpurpose/birt/webapp/birt/WEB-INF/web.xml b/specialpurpose/birt/webapp/birt/WEB-INF/web.xml
index 25a19b7..d758c82 100644
--- a/specialpurpose/birt/webapp/birt/WEB-INF/web.xml
+++ b/specialpurpose/birt/webapp/birt/WEB-INF/web.xml
@@ -39,7 +39,7 @@
     <context-param>

         <param-name>widgetVerbose</param-name>

         <param-value>false</param-value>

-        <description>Enable widget boundary comments. See org.ofbiz.widget.ModelWidget.widgetBoundaryCommentsEnabled().</description>

+        <description>Enable widget boundary comments. See org.ofbiz.widget.model.ModelWidget.widgetBoundaryCommentsEnabled().</description>

     </context-param>

     <context-param>

         <param-name>compressHTML</param-name>

diff --git a/specialpurpose/ecommerce/webapp/ecommerce/WEB-INF/actions/content/Mrv.groovy b/specialpurpose/ecommerce/webapp/ecommerce/WEB-INF/actions/content/Mrv.groovy
index b2d3958..26d40d1 100644
--- a/specialpurpose/ecommerce/webapp/ecommerce/WEB-INF/actions/content/Mrv.groovy
+++ b/specialpurpose/ecommerce/webapp/ecommerce/WEB-INF/actions/content/Mrv.groovy
@@ -32,8 +32,7 @@
 import org.ofbiz.security.*;
 import org.ofbiz.service.*;
 import org.ofbiz.entity.model.*;
-import org.ofbiz.widget.html.*;
-import org.ofbiz.widget.form.*;
+import org.ofbiz.widget.renderer.html.HtmlFormWrapper;
 import org.ofbiz.base.util.collections.LifoSet;
 
 import javax.servlet.*;
diff --git a/specialpurpose/ecommerce/webapp/ecommerce/WEB-INF/actions/content/Search.groovy b/specialpurpose/ecommerce/webapp/ecommerce/WEB-INF/actions/content/Search.groovy
index 969fa80..9f97520 100644
--- a/specialpurpose/ecommerce/webapp/ecommerce/WEB-INF/actions/content/Search.groovy
+++ b/specialpurpose/ecommerce/webapp/ecommerce/WEB-INF/actions/content/Search.groovy
@@ -27,7 +27,7 @@
 import org.ofbiz.base.util.UtilHttp
 import org.ofbiz.content.search.SearchWorker
 import org.ofbiz.product.feature.ParametricSearch
-import org.ofbiz.widget.html.HtmlFormWrapper
+import org.ofbiz.widget.renderer.html.HtmlFormWrapper
 import org.apache.lucene.search.*
 import org.apache.lucene.index.DirectoryReader
 import org.apache.lucene.store.Directory
diff --git a/specialpurpose/ecommerce/webapp/ecommerce/WEB-INF/actions/forum/ContentAddPrep.groovy b/specialpurpose/ecommerce/webapp/ecommerce/WEB-INF/actions/forum/ContentAddPrep.groovy
index e6626a9..872d335 100644
--- a/specialpurpose/ecommerce/webapp/ecommerce/WEB-INF/actions/forum/ContentAddPrep.groovy
+++ b/specialpurpose/ecommerce/webapp/ecommerce/WEB-INF/actions/forum/ContentAddPrep.groovy
@@ -31,8 +31,7 @@
 import org.ofbiz.security.*;
 import org.ofbiz.service.*;
 import org.ofbiz.entity.model.*;
-import org.ofbiz.widget.html.*;
-import org.ofbiz.widget.form.*;
+import org.ofbiz.widget.renderer.html.HtmlFormWrapper;
 import org.ofbiz.securityext.login.*;
 import org.ofbiz.common.*;
 import org.ofbiz.entity.model.*;
diff --git a/specialpurpose/ecommerce/webapp/ecommerce/WEB-INF/actions/forum/ContentPrep.groovy b/specialpurpose/ecommerce/webapp/ecommerce/WEB-INF/actions/forum/ContentPrep.groovy
index 3690b25..87dcbcc 100644
--- a/specialpurpose/ecommerce/webapp/ecommerce/WEB-INF/actions/forum/ContentPrep.groovy
+++ b/specialpurpose/ecommerce/webapp/ecommerce/WEB-INF/actions/forum/ContentPrep.groovy
@@ -23,8 +23,7 @@
 import org.ofbiz.security.*;
 import org.ofbiz.service.*;
 import org.ofbiz.entity.model.*;
-import org.ofbiz.widget.html.*;
-import org.ofbiz.widget.form.*;
+import org.ofbiz.widget.renderer.html.HtmlFormWrapper;
 import org.ofbiz.content.data.DataResourceWorker;
 import org.ofbiz.webapp.ftl.FreeMarkerViewHandler;
 import org.ofbiz.content.content.ContentWorker;
diff --git a/specialpurpose/ecommerce/webapp/ecommerce/WEB-INF/actions/forum/CurrentValPrep.groovy b/specialpurpose/ecommerce/webapp/ecommerce/WEB-INF/actions/forum/CurrentValPrep.groovy
index 58e925e..c3b6598 100644
--- a/specialpurpose/ecommerce/webapp/ecommerce/WEB-INF/actions/forum/CurrentValPrep.groovy
+++ b/specialpurpose/ecommerce/webapp/ecommerce/WEB-INF/actions/forum/CurrentValPrep.groovy
@@ -31,8 +31,7 @@
 import org.ofbiz.security.*;
 import org.ofbiz.service.*;
 import org.ofbiz.entity.model.*;
-import org.ofbiz.widget.html.*;
-import org.ofbiz.widget.form.*;
+import org.ofbiz.widget.renderer.html.HtmlFormWrapper;
 import org.ofbiz.content.ContentManagementWorker;
 
 import javax.servlet.*;
diff --git a/specialpurpose/ecommerce/webapp/ecommerce/WEB-INF/actions/forum/EditAddPrep.groovy b/specialpurpose/ecommerce/webapp/ecommerce/WEB-INF/actions/forum/EditAddPrep.groovy
index 39c6301..6c742fa 100644
--- a/specialpurpose/ecommerce/webapp/ecommerce/WEB-INF/actions/forum/EditAddPrep.groovy
+++ b/specialpurpose/ecommerce/webapp/ecommerce/WEB-INF/actions/forum/EditAddPrep.groovy
@@ -31,8 +31,7 @@
 import org.ofbiz.security.*;
 import org.ofbiz.service.*;
 import org.ofbiz.entity.model.*;
-import org.ofbiz.widget.html.*;
-import org.ofbiz.widget.form.*;
+import org.ofbiz.widget.renderer.html.HtmlFormWrapper;
 import org.ofbiz.securityext.login.*;
 import org.ofbiz.common.*;
 import org.ofbiz.entity.model.*;
diff --git a/specialpurpose/ecommerce/webapp/ecommerce/WEB-INF/actions/forum/FormPrep.groovy b/specialpurpose/ecommerce/webapp/ecommerce/WEB-INF/actions/forum/FormPrep.groovy
index dc3a55e..a4199db 100644
--- a/specialpurpose/ecommerce/webapp/ecommerce/WEB-INF/actions/forum/FormPrep.groovy
+++ b/specialpurpose/ecommerce/webapp/ecommerce/WEB-INF/actions/forum/FormPrep.groovy
@@ -33,8 +33,8 @@
 import org.ofbiz.security.*;
 import org.ofbiz.service.*;
 import org.ofbiz.entity.model.*;
-import org.ofbiz.widget.html.*;
-import org.ofbiz.widget.form.*;
+import org.ofbiz.widget.renderer.html.HtmlFormWrapper;
+import org.ofbiz.widget.model.*;
 import org.ofbiz.content.data.DataResourceWorker;
 
 
diff --git a/specialpurpose/ecommerce/webapp/ecommerce/WEB-INF/actions/forum/HtmlAreaPrep.groovy b/specialpurpose/ecommerce/webapp/ecommerce/WEB-INF/actions/forum/HtmlAreaPrep.groovy
index 7d333a1..08b9d76 100644
--- a/specialpurpose/ecommerce/webapp/ecommerce/WEB-INF/actions/forum/HtmlAreaPrep.groovy
+++ b/specialpurpose/ecommerce/webapp/ecommerce/WEB-INF/actions/forum/HtmlAreaPrep.groovy
@@ -22,8 +22,7 @@
 import org.ofbiz.security.*;
 import org.ofbiz.service.*;
 import org.ofbiz.entity.model.*;
-import org.ofbiz.widget.html.*;
-import org.ofbiz.widget.form.*;
+import org.ofbiz.widget.renderer.html.HtmlFormWrapper;
 import org.ofbiz.content.data.DataResourceWorker;
 import org.ofbiz.webapp.ftl.FreeMarkerViewHandler;
 
diff --git a/specialpurpose/ecommerce/webapp/ecommerce/WEB-INF/actions/forum/NodeTrailPrep.groovy b/specialpurpose/ecommerce/webapp/ecommerce/WEB-INF/actions/forum/NodeTrailPrep.groovy
index e63eb48..0083497 100644
--- a/specialpurpose/ecommerce/webapp/ecommerce/WEB-INF/actions/forum/NodeTrailPrep.groovy
+++ b/specialpurpose/ecommerce/webapp/ecommerce/WEB-INF/actions/forum/NodeTrailPrep.groovy
@@ -32,8 +32,7 @@
 import org.ofbiz.security.*;
 import org.ofbiz.service.*;
 import org.ofbiz.entity.model.*;
-import org.ofbiz.widget.html.*;
-import org.ofbiz.widget.form.*;
+import org.ofbiz.widget.renderer.html.HtmlFormWrapper;
 import org.ofbiz.securityext.login.*;
 import org.ofbiz.common.*;
 import org.ofbiz.entity.model.*;
diff --git a/specialpurpose/ecommerce/webapp/ecommerce/WEB-INF/actions/forum/OwnerContentPrep.groovy b/specialpurpose/ecommerce/webapp/ecommerce/WEB-INF/actions/forum/OwnerContentPrep.groovy
index cf2a018..03cdb9e 100644
--- a/specialpurpose/ecommerce/webapp/ecommerce/WEB-INF/actions/forum/OwnerContentPrep.groovy
+++ b/specialpurpose/ecommerce/webapp/ecommerce/WEB-INF/actions/forum/OwnerContentPrep.groovy
@@ -22,8 +22,7 @@
 import org.ofbiz.security.*;
 import org.ofbiz.service.*;
 import org.ofbiz.entity.model.*;
-import org.ofbiz.widget.html.*;
-import org.ofbiz.widget.form.*;
+import org.ofbiz.widget.renderer.html.HtmlFormWrapper;
 import org.ofbiz.content.data.DataResourceWorker;
 import org.ofbiz.webapp.ftl.FreeMarkerViewHandler;
 import org.ofbiz.content.content.ContentWorker;
diff --git a/specialpurpose/ecommerce/webapp/ecommerce/WEB-INF/actions/forum/PermPrep.groovy b/specialpurpose/ecommerce/webapp/ecommerce/WEB-INF/actions/forum/PermPrep.groovy
index 54defd4..1b239a2 100644
--- a/specialpurpose/ecommerce/webapp/ecommerce/WEB-INF/actions/forum/PermPrep.groovy
+++ b/specialpurpose/ecommerce/webapp/ecommerce/WEB-INF/actions/forum/PermPrep.groovy
@@ -32,8 +32,7 @@
 import org.ofbiz.security.*;
 import org.ofbiz.service.*;
 import org.ofbiz.entity.model.*;
-import org.ofbiz.widget.html.*;
-import org.ofbiz.widget.form.*;
+import org.ofbiz.widget.renderer.html.HtmlFormWrapper;
 import org.ofbiz.content.content.PermissionRecorder;
 import org.ofbiz.content.ContentManagementWorker;
 
diff --git a/specialpurpose/ecommerce/webapp/ecommerce/WEB-INF/actions/forum/PubInit.groovy b/specialpurpose/ecommerce/webapp/ecommerce/WEB-INF/actions/forum/PubInit.groovy
index e94b4fb..a2fc188 100644
--- a/specialpurpose/ecommerce/webapp/ecommerce/WEB-INF/actions/forum/PubInit.groovy
+++ b/specialpurpose/ecommerce/webapp/ecommerce/WEB-INF/actions/forum/PubInit.groovy
@@ -32,8 +32,7 @@
 import org.ofbiz.service.*;
 import org.ofbiz.entity.model.*;
 import org.ofbiz.webapp.website.WebSiteWorker;
-import org.ofbiz.widget.html.*;
-import org.ofbiz.widget.form.*;
+import org.ofbiz.widget.renderer.html.HtmlFormWrapper;
 import org.ofbiz.securityext.login.*;
 import org.ofbiz.common.*;
 import org.ofbiz.entity.model.*;
diff --git a/specialpurpose/ecommerce/webapp/ecommerce/WEB-INF/actions/forum/RespondPermAndPrep.groovy b/specialpurpose/ecommerce/webapp/ecommerce/WEB-INF/actions/forum/RespondPermAndPrep.groovy
index 22d5a48..c1c8225 100644
--- a/specialpurpose/ecommerce/webapp/ecommerce/WEB-INF/actions/forum/RespondPermAndPrep.groovy
+++ b/specialpurpose/ecommerce/webapp/ecommerce/WEB-INF/actions/forum/RespondPermAndPrep.groovy
@@ -32,8 +32,7 @@
 import org.ofbiz.security.*;
 import org.ofbiz.service.*;
 import org.ofbiz.entity.model.*;
-import org.ofbiz.widget.html.*;
-import org.ofbiz.widget.form.*;
+import org.ofbiz.widget.renderer.html.HtmlFormWrapper;
 import org.ofbiz.content.content.PermissionRecorder;
 
 import javax.servlet.*;
diff --git a/specialpurpose/ecommerce/webapp/ecommerce/WEB-INF/actions/forum/ResponsePrep.groovy b/specialpurpose/ecommerce/webapp/ecommerce/WEB-INF/actions/forum/ResponsePrep.groovy
index dc767ba..b43bf1e 100644
--- a/specialpurpose/ecommerce/webapp/ecommerce/WEB-INF/actions/forum/ResponsePrep.groovy
+++ b/specialpurpose/ecommerce/webapp/ecommerce/WEB-INF/actions/forum/ResponsePrep.groovy
@@ -32,8 +32,7 @@
 import org.ofbiz.security.*;
 import org.ofbiz.service.*;
 import org.ofbiz.entity.model.*;
-import org.ofbiz.widget.html.*;
-import org.ofbiz.widget.form.*;
+import org.ofbiz.widget.renderer.html.HtmlFormWrapper;
 import org.ofbiz.securityext.login.*;
 import org.ofbiz.common.*;
 import org.ofbiz.content.content.ContentWorker;
diff --git a/specialpurpose/ecommerce/webapp/ecommerce/WEB-INF/actions/forum/ViewPrep.groovy b/specialpurpose/ecommerce/webapp/ecommerce/WEB-INF/actions/forum/ViewPrep.groovy
index a66a665..49214ce 100644
--- a/specialpurpose/ecommerce/webapp/ecommerce/WEB-INF/actions/forum/ViewPrep.groovy
+++ b/specialpurpose/ecommerce/webapp/ecommerce/WEB-INF/actions/forum/ViewPrep.groovy
@@ -32,8 +32,7 @@
 import org.ofbiz.security.*;
 import org.ofbiz.service.*;
 import org.ofbiz.entity.model.*;
-import org.ofbiz.widget.html.*;
-import org.ofbiz.widget.form.*;
+import org.ofbiz.widget.renderer.html.HtmlFormWrapper;
 import org.ofbiz.securityext.login.*;
 import org.ofbiz.common.*;
 import org.ofbiz.content.content.ContentWorker;
diff --git a/specialpurpose/ecommerce/webapp/ecommerce/WEB-INF/actions/includes/MruAdd.groovy b/specialpurpose/ecommerce/webapp/ecommerce/WEB-INF/actions/includes/MruAdd.groovy
index a497978..bf30075 100644
--- a/specialpurpose/ecommerce/webapp/ecommerce/WEB-INF/actions/includes/MruAdd.groovy
+++ b/specialpurpose/ecommerce/webapp/ecommerce/WEB-INF/actions/includes/MruAdd.groovy
@@ -32,8 +32,7 @@
 import org.ofbiz.security.*;
 import org.ofbiz.service.*;
 import org.ofbiz.entity.model.*;
-import org.ofbiz.widget.html.*;
-import org.ofbiz.widget.form.*;
+import org.ofbiz.widget.renderer.html.HtmlFormWrapper;
 import org.ofbiz.content.ContentManagementWorker;
 import org.ofbiz.content.content.ContentWorker;
 import org.ofbiz.base.util.collections.LifoSet;
diff --git a/specialpurpose/ecommerce/webapp/ecommerce/WEB-INF/controller.xml b/specialpurpose/ecommerce/webapp/ecommerce/WEB-INF/controller.xml
index 7819d50..3cf26e9 100644
--- a/specialpurpose/ecommerce/webapp/ecommerce/WEB-INF/controller.xml
+++ b/specialpurpose/ecommerce/webapp/ecommerce/WEB-INF/controller.xml
@@ -33,9 +33,9 @@
 
     <handler name="jsp" type="view" class="org.ofbiz.webapp.view.JspViewHandler"/>
     <handler name="http" type="view" class="org.ofbiz.webapp.view.HttpViewHandler"/>
-    <handler name="screen" type="view" class="org.ofbiz.widget.screen.MacroScreenViewHandler"/>
+    <handler name="screen" type="view" class="org.ofbiz.widget.renderer.macro.MacroScreenViewHandler"/>
     <handler name="simplecontent" type="view" class="org.ofbiz.content.view.SimpleContentViewHandler"/>
-    <handler name="screenfop" type="view" class="org.ofbiz.widget.screen.ScreenFopViewHandler"/>
+    <handler name="screenfop" type="view" class="org.ofbiz.widget.renderer.fo.ScreenFopViewHandler"/>
 
     <!-- Events run from here for the first hit in a visit -->
     <firstvisit>
diff --git a/specialpurpose/example/src/org/ofbiz/example/ExamplePrintServices.java b/specialpurpose/example/src/org/ofbiz/example/ExamplePrintServices.java
index 28239f1..50b4973 100644
--- a/specialpurpose/example/src/org/ofbiz/example/ExamplePrintServices.java
+++ b/specialpurpose/example/src/org/ofbiz/example/ExamplePrintServices.java
@@ -49,8 +49,8 @@
 import org.ofbiz.service.DispatchContext;
 import org.ofbiz.service.ServiceUtil;
 import org.ofbiz.webapp.view.ApacheFopWorker;
-import org.ofbiz.widget.html.HtmlScreenRenderer;
-import org.ofbiz.widget.screen.ScreenRenderer;
+import org.ofbiz.widget.renderer.ScreenRenderer;
+import org.ofbiz.widget.renderer.html.HtmlScreenRenderer;
 import org.xml.sax.SAXException;
 
 public class ExamplePrintServices {
diff --git a/specialpurpose/googlecheckout/script/org/ofbiz/googleCheckout/PrepareXMLTemplate.xml b/specialpurpose/googlecheckout/script/org/ofbiz/googleCheckout/PrepareXMLTemplate.xml
index bc13918..b51e4de 100644
--- a/specialpurpose/googlecheckout/script/org/ofbiz/googleCheckout/PrepareXMLTemplate.xml
+++ b/specialpurpose/googlecheckout/script/org/ofbiz/googleCheckout/PrepareXMLTemplate.xml
@@ -102,18 +102,18 @@
         <set field="xscreenContext.sendInitialAuthDetails" from-field="sendInitialAuthDetails"/>
         <set field="xscreenContext.shoppingCart" from-field="parameters.shoppingCart"/>
         <!-- create string renderer -->
-        <create-object class-name="org.ofbiz.widget.html.HtmlScreenRenderer" field="xhtmlStringRenderer"></create-object>
+        <create-object class-name="org.ofbiz.widget.renderer.html.HtmlScreenRenderer" field="xhtmlStringRenderer"></create-object>
         <!-- create screen renderer -->
-        <create-object class-name="org.ofbiz.widget.screen.ScreenRenderer" field="screens">
+        <create-object class-name="org.ofbiz.widget.renderer.ScreenRenderer" field="screens">
             <field field="XMLWriter" type="java.lang.Appendable"/>
             <field field="xscreenContext" type="org.ofbiz.base.util.collections.MapStack"/>
-            <field field="xhtmlStringRenderer" type="org.ofbiz.widget.screen.ScreenStringRenderer"/>
+            <field field="xhtmlStringRenderer" type="org.ofbiz.widget.renderer.ScreenStringRenderer"/>
         </create-object>
         <set field="xscreenContext.screens" from-field="screens"/>
-        <create-object class-name="org.ofbiz.widget.screen.ScreenRenderer" field="xscreens">
+        <create-object class-name="org.ofbiz.widget.renderer.ScreenRenderer" field="xscreens">
             <field field="XMLWriter" type="java.lang.Appendable"/>
             <field field="xscreenContext" type="org.ofbiz.base.util.collections.MapStack"/>
-            <field field="xhtmlStringRenderer" type="org.ofbiz.widget.screen.ScreenStringRenderer"/>
+            <field field="xhtmlStringRenderer" type="org.ofbiz.widget.renderer.ScreenStringRenderer"/>
         </create-object>
         <!-- get uri -->
         <property-to-field resource="googleCheckout" property="xmlTemplateUri" field="screenUri"/>
diff --git a/specialpurpose/googlecheckout/webapp/googlecheckout/WEB-INF/web.xml b/specialpurpose/googlecheckout/webapp/googlecheckout/WEB-INF/web.xml
index 22091dc..809b3ac 100644
--- a/specialpurpose/googlecheckout/webapp/googlecheckout/WEB-INF/web.xml
+++ b/specialpurpose/googlecheckout/webapp/googlecheckout/WEB-INF/web.xml
@@ -46,7 +46,7 @@
     <context-param>
         <param-name>widgetVerbose</param-name>
         <param-value>false</param-value>
-        <description>Enable widget boundary comments. See org.ofbiz.widget.ModelWidget.widgetBoundaryCommentsEnabled().</description>
+        <description>Enable widget boundary comments. See org.ofbiz.widget.model.ModelWidget.widgetBoundaryCommentsEnabled().</description>
     </context-param>
     <context-param>
         <param-name>compressHTML</param-name>
diff --git a/specialpurpose/oagis/src/org/ofbiz/oagis/OagisServices.java b/specialpurpose/oagis/src/org/ofbiz/oagis/OagisServices.java
index eb308d3..8bef31b 100644
--- a/specialpurpose/oagis/src/org/ofbiz/oagis/OagisServices.java
+++ b/specialpurpose/oagis/src/org/ofbiz/oagis/OagisServices.java
@@ -63,9 +63,9 @@
 import org.ofbiz.service.GenericServiceException;
 import org.ofbiz.service.LocalDispatcher;
 import org.ofbiz.service.ServiceUtil;
-import org.ofbiz.widget.fo.FoFormRenderer;
-import org.ofbiz.widget.html.HtmlScreenRenderer;
-import org.ofbiz.widget.screen.ScreenRenderer;
+import org.ofbiz.widget.renderer.ScreenRenderer;
+import org.ofbiz.widget.renderer.fo.FoFormRenderer;
+import org.ofbiz.widget.renderer.html.HtmlScreenRenderer;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 import org.xml.sax.SAXException;
diff --git a/specialpurpose/oagis/src/org/ofbiz/oagis/OagisShipmentServices.java b/specialpurpose/oagis/src/org/ofbiz/oagis/OagisShipmentServices.java
index 7c00c37..158dc4a 100644
--- a/specialpurpose/oagis/src/org/ofbiz/oagis/OagisShipmentServices.java
+++ b/specialpurpose/oagis/src/org/ofbiz/oagis/OagisShipmentServices.java
@@ -61,9 +61,9 @@
 import org.ofbiz.service.GenericServiceException;
 import org.ofbiz.service.LocalDispatcher;
 import org.ofbiz.service.ServiceUtil;
-import org.ofbiz.widget.fo.FoFormRenderer;
-import org.ofbiz.widget.html.HtmlScreenRenderer;
-import org.ofbiz.widget.screen.ScreenRenderer;
+import org.ofbiz.widget.renderer.ScreenRenderer;
+import org.ofbiz.widget.renderer.fo.FoFormRenderer;
+import org.ofbiz.widget.renderer.html.HtmlScreenRenderer;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 
diff --git a/specialpurpose/scrum/webapp/demotest/WEB-INF/web.xml b/specialpurpose/scrum/webapp/demotest/WEB-INF/web.xml
index efe5fcc..a516711 100644
--- a/specialpurpose/scrum/webapp/demotest/WEB-INF/web.xml
+++ b/specialpurpose/scrum/webapp/demotest/WEB-INF/web.xml
@@ -46,7 +46,7 @@
         <param-name>widgetVerbose</param-name>
         <param-value>false</param-value>
         <description>Enable widget boundary comments. See
-            org.ofbiz.widget.ModelWidget.widgetBoundaryCommentsEnabled().
+            org.ofbiz.widget.model.ModelWidget.widgetBoundaryCommentsEnabled().
         </description>
     </context-param>
     <context-param>
diff --git a/specialpurpose/scrum/webapp/scrum/WEB-INF/web.xml b/specialpurpose/scrum/webapp/scrum/WEB-INF/web.xml
index 2394a62..b40ecd5 100644
--- a/specialpurpose/scrum/webapp/scrum/WEB-INF/web.xml
+++ b/specialpurpose/scrum/webapp/scrum/WEB-INF/web.xml
@@ -38,7 +38,7 @@
     <context-param>
         <param-name>widgetVerbose</param-name>
         <param-value>false</param-value>
-        <description>Enable widget boundary comments. See org.ofbiz.widget.ModelWidget.widgetBoundaryCommentsEnabled().</description>
+        <description>Enable widget boundary comments. See org.ofbiz.widget.model.ModelWidget.widgetBoundaryCommentsEnabled().</description>
     </context-param>
     <context-param>
         <param-name>compressHTML</param-name>
diff --git a/specialpurpose/webpos/webapp/webpos/WEB-INF/controller.xml b/specialpurpose/webpos/webapp/webpos/WEB-INF/controller.xml
index cfc6e54..87b3c7f 100644
--- a/specialpurpose/webpos/webapp/webpos/WEB-INF/controller.xml
+++ b/specialpurpose/webpos/webapp/webpos/WEB-INF/controller.xml
@@ -28,7 +28,7 @@
     <handler name="simple" type="request" class="org.ofbiz.webapp.event.SimpleEventHandler"/>
     <handler name="groovy" type="request" class="org.ofbiz.webapp.event.GroovyEventHandler"/>    
     <handler name="jsp" type="view" class="org.ofbiz.webapp.view.JspViewHandler"/>
-    <handler name="screen" type="view" class="org.ofbiz.widget.screen.MacroScreenViewHandler"/>
+    <handler name="screen" type="view" class="org.ofbiz.widget.renderer.macro.MacroScreenViewHandler"/>
     
     <!-- Events run from here for the first hit in a visit -->
     <firstvisit>
diff --git a/themes/bluelight/includes/appbarOpen.ftl b/themes/bluelight/includes/appbarOpen.ftl
index f32cd29..48716f9 100644
--- a/themes/bluelight/includes/appbarOpen.ftl
+++ b/themes/bluelight/includes/appbarOpen.ftl
@@ -23,7 +23,7 @@
 <#assign displayApps = Static["org.ofbiz.webapp.control.LoginWorker"].getAppBarWebInfos(security, userLogin, ofbizServerName, "main")>
 <#assign displaySecondaryApps = Static["org.ofbiz.webapp.control.LoginWorker"].getAppBarWebInfos(security, userLogin, ofbizServerName, "secondary")>
 
-<#assign appModelMenu = Static["org.ofbiz.widget.menu.MenuFactory"].getMenuFromLocation(applicationMenuLocation,applicationMenuName)>
+<#assign appModelMenu = Static["org.ofbiz.widget.model.MenuFactory"].getMenuFromLocation(applicationMenuLocation,applicationMenuName)>
 <#if appModelMenu.getModelMenuItemByName(headerItem)??>
   <#if headerItem!="main">
     <#assign show_last_menu = true>
diff --git a/themes/droppingcrumbs/includes/appbarClose.ftl b/themes/droppingcrumbs/includes/appbarClose.ftl
index d26504b..02ee335 100644
--- a/themes/droppingcrumbs/includes/appbarClose.ftl
+++ b/themes/droppingcrumbs/includes/appbarClose.ftl
@@ -16,7 +16,7 @@
 specific language governing permissions and limitations
 under the License.
 -->
-<#assign appModelMenu = Static["org.ofbiz.widget.menu.MenuFactory"].getMenuFromLocation(applicationMenuLocation,applicationMenuName)>
+<#assign appModelMenu = Static["org.ofbiz.widget.model.MenuFactory"].getMenuFromLocation(applicationMenuLocation,applicationMenuName)>
 <#if appModelMenu.getModelMenuItemByName(headerItem)??>
   <#if headerItem!="main">
     <div class="breadcrumbs-sep">
diff --git a/themes/droppingcrumbs/includes/appbarOpen.ftl b/themes/droppingcrumbs/includes/appbarOpen.ftl
index 54e62e8..08372b7 100644
--- a/themes/droppingcrumbs/includes/appbarOpen.ftl
+++ b/themes/droppingcrumbs/includes/appbarOpen.ftl
@@ -24,7 +24,7 @@
 <#assign displayApps = Static["org.ofbiz.webapp.control.LoginWorker"].getAppBarWebInfos(security, userLogin, ofbizServerName, "main")>
 <#assign displaySecondaryApps = Static["org.ofbiz.webapp.control.LoginWorker"].getAppBarWebInfos(security, userLogin, ofbizServerName, "secondary")>
 
-<#assign appModelMenu = Static["org.ofbiz.widget.menu.MenuFactory"].getMenuFromLocation(applicationMenuLocation,applicationMenuName)>
+<#assign appModelMenu = Static["org.ofbiz.widget.model.MenuFactory"].getMenuFromLocation(applicationMenuLocation,applicationMenuName)>
 <#if appModelMenu.getModelMenuItemByName(headerItem)??>
   <#if headerItem!="main">
     <#assign show_last_menu = true>
diff --git a/themes/tomahawk/includes/appbarClose.ftl b/themes/tomahawk/includes/appbarClose.ftl
index fb14d29..6bae13e 100644
--- a/themes/tomahawk/includes/appbarClose.ftl
+++ b/themes/tomahawk/includes/appbarClose.ftl
@@ -16,7 +16,7 @@
 specific language governing permissions and limitations
 under the License.
 -->
-<#assign appModelMenu = Static["org.ofbiz.widget.menu.MenuFactory"].getMenuFromLocation(applicationMenuLocation,applicationMenuName)>
+<#assign appModelMenu = Static["org.ofbiz.widget.model.MenuFactory"].getMenuFromLocation(applicationMenuLocation,applicationMenuName)>
 <#if person?has_content>
   <#assign userName = (person.firstName!) + " " + (person.middleName!) + " " + person.lastName!>
 <#elseif partyGroup?has_content>
diff --git a/themes/tomahawk/includes/appbarOpen.ftl b/themes/tomahawk/includes/appbarOpen.ftl
index dbba5bd..01ae98c 100644
--- a/themes/tomahawk/includes/appbarOpen.ftl
+++ b/themes/tomahawk/includes/appbarOpen.ftl
@@ -24,7 +24,7 @@
 <#assign displayApps = Static["org.ofbiz.webapp.control.LoginWorker"].getAppBarWebInfos(security, userLogin, ofbizServerName, "main")>
 <#assign displaySecondaryApps = Static["org.ofbiz.webapp.control.LoginWorker"].getAppBarWebInfos(security, userLogin, ofbizServerName, "secondary")>
 
-<#assign appModelMenu = Static["org.ofbiz.widget.menu.MenuFactory"].getMenuFromLocation(applicationMenuLocation,applicationMenuName)>
+<#assign appModelMenu = Static["org.ofbiz.widget.model.MenuFactory"].getMenuFromLocation(applicationMenuLocation,applicationMenuName)>
 <#if appModelMenu.getModelMenuItemByName(headerItem)??>
   <#if headerItem!="main">
     <#assign show_last_menu = true>