svn commit: r1652852 [15/22] - in /ofbiz/trunk: applications/content/src/org/ofbiz/content/cms/ applications/content/src/org/ofbiz/content/content/ applications/content/src/org/ofbiz/content/data/ applications/content/src/org/ofbiz/content/output/ appl...

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

svn commit: r1652852 [15/22] - in /ofbiz/trunk: applications/content/src/org/ofbiz/content/cms/ applications/content/src/org/ofbiz/content/content/ applications/content/src/org/ofbiz/content/data/ applications/content/src/org/ofbiz/content/output/ appl...

adrianc
Added: ofbiz/trunk/framework/widget/src/org/ofbiz/widget/renderer/Paginator.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/widget/src/org/ofbiz/widget/renderer/Paginator.java?rev=1652852&view=auto
==============================================================================
--- ofbiz/trunk/framework/widget/src/org/ofbiz/widget/renderer/Paginator.java (added)
+++ ofbiz/trunk/framework/widget/src/org/ofbiz/widget/renderer/Paginator.java Sun Jan 18 21:03:40 2015
@@ -0,0 +1,237 @@
+/*******************************************************************************
+ * 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.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.NoSuchElementException;
+
+import org.ofbiz.base.util.Debug;
+import org.ofbiz.base.util.UtilGenerics;
+import org.ofbiz.base.util.UtilValidate;
+import org.ofbiz.entity.GenericEntityException;
+import org.ofbiz.entity.util.EntityListIterator;
+import org.ofbiz.widget.WidgetWorker;
+import org.ofbiz.widget.model.ModelForm;
+
+/**
+ * Utility methods for handling list pagination.
+ *
+ */
+public final class Paginator {
+
+    public static final String module = Paginator.class.getName();
+
+    public static int getActualPageSize(Map<String, Object> context) {
+        Integer value = (Integer) context.get("actualPageSize");
+        return value != null ? value.intValue() : (getHighIndex(context) - getLowIndex(context));
+    }
+
+    public static int getHighIndex(Map<String, Object> context) {
+        Integer value = (Integer) context.get("highIndex");
+        return value != null ? value.intValue() : 0;
+    }
+
+    public static void getListLimits(ModelForm modelForm, Map<String, Object> context, Object entryList) {
+        int viewIndex = 0;
+        int viewSize = 0;
+        int lowIndex = 0;
+        int highIndex = 0;
+        int listSize = modelForm.getOverrideListSize(context);
+        if (listSize > 0) {
+            //setOverridenListSize(true);
+        } else if (entryList instanceof EntityListIterator) {
+            EntityListIterator iter = (EntityListIterator) entryList;
+            try {
+                listSize = iter.getResultsSizeAfterPartialList();
+            } catch (GenericEntityException e) {
+                Debug.logError(e, "Error getting list size", module);
+                listSize = 0;
+            }
+        } else if (entryList instanceof List<?>) {
+            List<?> items = (List<?>) entryList;
+            listSize = items.size();
+        }
+        if (modelForm.getPaginate(context)) {
+            viewIndex = getViewIndex(modelForm, context);
+            viewSize = getViewSize(modelForm, context);
+            lowIndex = viewIndex * viewSize;
+            highIndex = (viewIndex + 1) * viewSize;
+        } else {
+            viewIndex = 0;
+            viewSize = ModelForm.MAX_PAGE_SIZE;
+            lowIndex = 0;
+            highIndex = ModelForm.MAX_PAGE_SIZE;
+        }
+        context.put("listSize", Integer.valueOf(listSize));
+        context.put("viewIndex", Integer.valueOf(viewIndex));
+        context.put("viewSize", Integer.valueOf(viewSize));
+        context.put("lowIndex", Integer.valueOf(lowIndex));
+        context.put("highIndex", Integer.valueOf(highIndex));
+    }
+
+    public static int getListSize(Map<String, Object> context) {
+        Integer value = (Integer) context.get("listSize");
+        return value != null ? value.intValue() : 0;
+    }
+
+    public static int getLowIndex(Map<String, Object> context) {
+        Integer value = (Integer) context.get("lowIndex");
+        return value != null ? value.intValue() : 0;
+    }
+
+    public static int getViewIndex(ModelForm modelForm, Map<String, Object> context) {
+        String field = modelForm.getMultiPaginateIndexField(context);
+        int viewIndex = 0;
+        try {
+            Object value = context.get(field);
+            if (value == null) {
+                // try parameters.VIEW_INDEX as that is an old OFBiz convention
+                Map<String, Object> parameters = UtilGenerics.cast(context.get("parameters"));
+                if (parameters != null) {
+                    value = parameters.get("VIEW_INDEX" + "_" + WidgetWorker.getPaginatorNumber(context));
+
+                    if (value == null) {
+                        value = parameters.get(field);
+                    }
+                }
+            }
+            // try paginate index field without paginator number
+            if (value == null) {
+                field = modelForm.getPaginateIndexField(context);
+                value = context.get(field);
+            }
+            if (value instanceof Integer) {
+                viewIndex = ((Integer) value).intValue();
+            } else if (value instanceof String) {
+                viewIndex = Integer.parseInt((String) value);
+            }
+        } catch (Exception e) {
+            Debug.logWarning(e, "Error getting paginate view index: " + e.toString(), module);
+        }
+        return viewIndex;
+    }
+
+    public static int getViewSize(ModelForm modelForm, Map<String, Object> context) {
+        String field = modelForm.getMultiPaginateSizeField(context);
+        int viewSize = modelForm.getDefaultViewSize();
+        try {
+            Object value = context.get(field);
+            if (value == null) {
+                // try parameters.VIEW_SIZE as that is an old OFBiz convention
+                Map<String, Object> parameters = UtilGenerics.cast(context.get("parameters"));
+                if (parameters != null) {
+                    value = parameters.get("VIEW_SIZE" + "_" + WidgetWorker.getPaginatorNumber(context));
+
+                    if (value == null) {
+                        value = parameters.get(field);
+                    }
+                }
+            }
+            // try the page size field without paginator number
+            if (value == null) {
+                field = modelForm.getPaginateSizeField(context);
+                value = context.get(field);
+            }
+            if (value instanceof Integer) {
+                viewSize = ((Integer) value).intValue();
+            } else if (value instanceof String && UtilValidate.isNotEmpty(value)) {
+                viewSize = Integer.parseInt((String) value);
+            }
+        } catch (Exception e) {
+            Debug.logWarning(e, "Error getting paginate view size: " + e.toString(), module);
+        }
+        return viewSize;
+    }
+
+    public static void preparePager(ModelForm modelForm, Map<String, Object> context) {
+
+        String lookupName = modelForm.getListName();
+        if (UtilValidate.isEmpty(lookupName)) {
+            Debug.logError("No value for list or iterator name found.", module);
+            return;
+        }
+        Object obj = context.get(lookupName);
+        if (obj == null) {
+            if (Debug.verboseOn())
+                Debug.logVerbose("No object for list or iterator name [" + lookupName + "] found, so not running pagination.",
+                        module);
+            return;
+        }
+        // if list is empty, do not render rows
+        Iterator<?> iter = null;
+        if (obj instanceof Iterator<?>) {
+            iter = (Iterator<?>) obj;
+        } else if (obj instanceof List<?>) {
+            iter = ((List<?>) obj).listIterator();
+        }
+
+        // set low and high index
+        getListLimits(modelForm, context, obj);
+
+        int listSize = ((Integer) context.get("listSize")).intValue();
+        int lowIndex = ((Integer) context.get("lowIndex")).intValue();
+        int highIndex = ((Integer) context.get("highIndex")).intValue();
+        // Debug.logInfo("preparePager: low - high = " + lowIndex + " - " + highIndex, module);
+
+        // we're passed a subset of the list, so use (0, viewSize) range
+        if (modelForm.isOverridenListSize()) {
+            lowIndex = 0;
+            highIndex = ((Integer) context.get("viewSize")).intValue();
+        }
+
+        if (iter == null)
+            return;
+
+        // count item rows
+        int itemIndex = -1;
+        Object item = safeNext(iter);
+        while (item != null && itemIndex < highIndex) {
+            itemIndex++;
+            item = safeNext(iter);
+        }
+
+        // Debug.logInfo("preparePager: Found rows = " + itemIndex, module);
+
+        // reduce the highIndex if number of items falls short
+        if ((itemIndex + 1) < highIndex) {
+            highIndex = itemIndex + 1;
+            // if list size is overridden, use full listSize
+            context.put("highIndex", Integer.valueOf(modelForm.isOverridenListSize() ? listSize : highIndex));
+        }
+        context.put("actualPageSize", Integer.valueOf(highIndex - lowIndex));
+
+        if (iter instanceof EntityListIterator) {
+            try {
+                ((EntityListIterator) iter).beforeFirst();
+            } catch (GenericEntityException e) {
+                Debug.logError(e, "Error rewinding list form render EntityListIterator: " + e.toString(), module);
+            }
+        }
+    }
+
+    private static <X> X safeNext(Iterator<X> iterator) {
+        try {
+            return iterator.next();
+        } catch (NoSuchElementException e) {
+            return null;
+        }
+    }
+}

Added: ofbiz/trunk/framework/widget/src/org/ofbiz/widget/renderer/ScreenRenderException.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/widget/src/org/ofbiz/widget/renderer/ScreenRenderException.java?rev=1652852&view=auto
==============================================================================
--- ofbiz/trunk/framework/widget/src/org/ofbiz/widget/renderer/ScreenRenderException.java (added)
+++ ofbiz/trunk/framework/widget/src/org/ofbiz/widget/renderer/ScreenRenderException.java Sun Jan 18 21:03:40 2015
@@ -0,0 +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.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);
+    }
+}

Added: ofbiz/trunk/framework/widget/src/org/ofbiz/widget/renderer/ScreenRenderer.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/widget/src/org/ofbiz/widget/renderer/ScreenRenderer.java?rev=1652852&view=auto
==============================================================================
--- ofbiz/trunk/framework/widget/src/org/ofbiz/widget/renderer/ScreenRenderer.java (added)
+++ ofbiz/trunk/framework/widget/src/org/ofbiz/widget/renderer/ScreenRenderer.java Sun Jan 18 21:03:40 2015
@@ -0,0 +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.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"));
+    }
+}

Added: ofbiz/trunk/framework/widget/src/org/ofbiz/widget/renderer/ScreenStringRenderer.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/widget/src/org/ofbiz/widget/renderer/ScreenStringRenderer.java?rev=1652852&view=auto
==============================================================================
--- ofbiz/trunk/framework/widget/src/org/ofbiz/widget/renderer/ScreenStringRenderer.java (added)
+++ ofbiz/trunk/framework/widget/src/org/ofbiz/widget/renderer/ScreenStringRenderer.java Sun Jan 18 21:03:40 2015
@@ -0,0 +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.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;
+}
+
+
+

Added: ofbiz/trunk/framework/widget/src/org/ofbiz/widget/renderer/TreeStringRenderer.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/widget/src/org/ofbiz/widget/renderer/TreeStringRenderer.java?rev=1652852&view=auto
==============================================================================
--- ofbiz/trunk/framework/widget/src/org/ofbiz/widget/renderer/TreeStringRenderer.java (added)
+++ ofbiz/trunk/framework/widget/src/org/ofbiz/widget/renderer/TreeStringRenderer.java Sun Jan 18 21:03:40 2015
@@ -0,0 +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.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);
+}

Added: ofbiz/trunk/framework/widget/src/org/ofbiz/widget/renderer/UtilHelpText.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/widget/src/org/ofbiz/widget/renderer/UtilHelpText.java?rev=1652852&view=auto
==============================================================================
--- ofbiz/trunk/framework/widget/src/org/ofbiz/widget/renderer/UtilHelpText.java (added)
+++ ofbiz/trunk/framework/widget/src/org/ofbiz/widget/renderer/UtilHelpText.java Sun Jan 18 21:03:40 2015
@@ -0,0 +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.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;
+    }
+}

Added: ofbiz/trunk/framework/widget/src/org/ofbiz/widget/renderer/fo/FoFormRenderer.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/widget/src/org/ofbiz/widget/renderer/fo/FoFormRenderer.java?rev=1652852&view=auto
==============================================================================
--- ofbiz/trunk/framework/widget/src/org/ofbiz/widget/renderer/fo/FoFormRenderer.java (added)
+++ ofbiz/trunk/framework/widget/src/org/ofbiz/widget/renderer/fo/FoFormRenderer.java Sun Jan 18 21:03:40 2015
@@ -0,0 +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.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 {
+    }
+}

Added: ofbiz/trunk/framework/widget/src/org/ofbiz/widget/renderer/fo/FoScreenRenderer.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/widget/src/org/ofbiz/widget/renderer/fo/FoScreenRenderer.java?rev=1652852&view=auto
==============================================================================
--- ofbiz/trunk/framework/widget/src/org/ofbiz/widget/renderer/fo/FoScreenRenderer.java (added)
+++ ofbiz/trunk/framework/widget/src/org/ofbiz/widget/renderer/fo/FoScreenRenderer.java Sun Jan 18 21:03:40 2015
@@ -0,0 +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.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
+    }
+}

Added: ofbiz/trunk/framework/widget/src/org/ofbiz/widget/renderer/fo/ScreenFopViewHandler.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/widget/src/org/ofbiz/widget/renderer/fo/ScreenFopViewHandler.java?rev=1652852&view=auto
==============================================================================
--- ofbiz/trunk/framework/widget/src/org/ofbiz/widget/renderer/fo/ScreenFopViewHandler.java (added)
+++ ofbiz/trunk/framework/widget/src/org/ofbiz/widget/renderer/fo/ScreenFopViewHandler.java Sun Jan 18 21:03:40 2015
@@ -0,0 +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.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);
+        }
+    }
+}