/*******************************************************************************
 * 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.apache.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.apache.ofbiz.base.util.Debug;
import org.apache.ofbiz.base.util.GeneralException;
import org.apache.ofbiz.base.util.UtilCodec;
import org.apache.ofbiz.base.util.UtilGenerics;
import org.apache.ofbiz.base.util.UtilXml;
import org.apache.ofbiz.base.util.collections.MapStack;
import org.apache.ofbiz.base.util.string.FlexibleStringExpander;
import org.apache.ofbiz.entity.Delegator;
import org.apache.ofbiz.entity.GenericEntityException;
import org.apache.ofbiz.entity.GenericValue;
import org.apache.ofbiz.entity.util.EntityQuery;
import org.apache.ofbiz.widget.WidgetFactory;
import org.apache.ofbiz.widget.model.CommonWidgetModels.AutoEntityParameters;
import org.apache.ofbiz.widget.model.CommonWidgetModels.AutoServiceParameters;
import org.apache.ofbiz.widget.model.CommonWidgetModels.Image;
import org.apache.ofbiz.widget.model.CommonWidgetModels.Link;
import org.apache.ofbiz.widget.model.CommonWidgetModels.Parameter;
import org.apache.ofbiz.widget.portal.PortalPageWorker;
import org.apache.ofbiz.widget.renderer.FormRenderer;
import org.apache.ofbiz.widget.renderer.FormStringRenderer;
import org.apache.ofbiz.widget.renderer.MenuStringRenderer;
import org.apache.ofbiz.widget.renderer.ScreenRenderer;
import org.apache.ofbiz.widget.renderer.ScreenStringRenderer;
import org.apache.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.
            List<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);
                    if (collapsedParam != null)
                        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();
            }
            try {
                ModelForm modelForm = getModelForm(context);
                FormRenderer renderer = new FormRenderer(modelForm, formStringRenderer);
                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) throws IOException, SAXException, ParserConfigurationException {
            String name = this.getName(context);
            String location = this.getLocation(context);
            return FormFactory.getFormFromLocation(location, name, getModelScreen().getDelegator(context).getModelReader(),
                    getModelScreen().getDispatcher(context).getDispatchContext());
        }

        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 Grid extends ModelScreenWidget {
        public static final String TAG_NAME = "include-grid";
        private final FlexibleStringExpander nameExdr;
        private final FlexibleStringExpander locationExdr;
        private final FlexibleStringExpander shareScopeExdr;

        public Grid(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 grid 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 = GridFactory.getGridFromLocation(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 if ("text".equals(childElement.getNodeName())) {
                        subWidgets.put("text", new HtmlWidget(modelScreen, childElement));
                    } else if ("csv".equals(childElement.getNodeName())) {
                        subWidgets.put("csv", new HtmlWidget(modelScreen, childElement));
                    } else if ("xls".equals(childElement.getNodeName())) {
                        subWidgets.put("xls", 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) {
                        if (content.get("dataResourceId") != 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;
        }
    }

}
