/*******************************************************************************
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 *******************************************************************************/
package org.ofbiz.widget.screen;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.Set;

import javax.xml.parsers.ParserConfigurationException;

import org.ofbiz.base.util.Debug;
import org.ofbiz.base.util.GeneralException;
import org.ofbiz.base.util.StringUtil;
import org.ofbiz.base.util.UtilGenerics;
import org.ofbiz.base.util.UtilMisc;
import org.ofbiz.base.util.UtilXml;
import org.ofbiz.base.util.collections.MapStack;
import org.ofbiz.base.util.string.FlexibleStringExpander;
import org.ofbiz.entity.Delegator;
import org.ofbiz.entity.GenericEntityException;
import org.ofbiz.entity.GenericValue;
import org.ofbiz.entity.condition.EntityCondition;
import org.ofbiz.entity.util.EntityQuery;
import org.ofbiz.widget.ModelWidget;
import org.ofbiz.widget.ModelWidgetAction;
import org.ofbiz.widget.ModelWidgetVisitor;
import org.ofbiz.widget.PortalPageWorker;
import org.ofbiz.widget.WidgetFactory;
import org.ofbiz.widget.WidgetWorker;
import org.ofbiz.widget.form.FormFactory;
import org.ofbiz.widget.form.FormRenderer;
import org.ofbiz.widget.form.FormStringRenderer;
import org.ofbiz.widget.form.ModelForm;
import org.ofbiz.widget.menu.MenuFactory;
import org.ofbiz.widget.menu.MenuStringRenderer;
import org.ofbiz.widget.menu.ModelMenu;
import org.ofbiz.widget.tree.ModelTree;
import org.ofbiz.widget.tree.TreeFactory;
import org.ofbiz.widget.tree.TreeStringRenderer;
import org.w3c.dom.Element;
import org.xml.sax.SAXException;


/**
 * Widget Library - Screen model class
 */
@SuppressWarnings("serial")
public abstract class ModelScreenWidget extends ModelWidget {
    public static final String module = ModelScreenWidget.class.getName();

    private final ModelScreen modelScreen;

    public ModelScreenWidget(ModelScreen modelScreen, Element widgetElement) {
        super(widgetElement);
        this.modelScreen = modelScreen;
        if (Debug.verboseOn()) Debug.logVerbose("Reading Screen sub-widget with name: " + widgetElement.getNodeName(), module);
    }

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

    protected static List<ModelScreenWidget> readSubWidgets(ModelScreen modelScreen, List<? extends Element> subElementList) {
        if (subElementList.isEmpty()) {
            return Collections.emptyList();
        }
        List<ModelScreenWidget> subWidgets = new ArrayList<ModelScreenWidget>(subElementList.size());
        for (Element subElement: subElementList) {
            subWidgets.add(WidgetFactory.getModelScreenWidget(modelScreen, subElement));
        }
        return Collections.unmodifiableList(subWidgets);
    }

    protected static void renderSubWidgetsString(List<ModelScreenWidget> subWidgets, Appendable writer, Map<String, Object> context, ScreenStringRenderer screenStringRenderer) throws GeneralException, IOException {
        if (subWidgets == null) {
            return;
        }
        for (ModelScreenWidget subWidget: subWidgets) {
            if (Debug.verboseOn()) Debug.logVerbose("Rendering screen " + subWidget.getModelScreen().getName() + "; widget class is " + subWidget.getClass().getName(), module);

            // render the sub-widget itself
            subWidget.renderWidgetString(writer, context, screenStringRenderer);
        }
    }

    public ModelScreen getModelScreen() {
        return this.modelScreen;
    }

    public static final class SectionsRenderer implements Map<String, ModelScreenWidget> {
        private final Map<String, ModelScreenWidget> sectionMap;
        private final ScreenStringRenderer screenStringRenderer;
        private final Map<String, Object> context;
        private final Appendable writer;

        public SectionsRenderer(Map<String, ModelScreenWidget> sectionMap, Map<String, Object> context, Appendable writer,
                ScreenStringRenderer screenStringRenderer) {
            Map<String, ModelScreenWidget> localMap = new HashMap<String, ModelScreenWidget>();
            localMap.putAll(sectionMap);
            this.sectionMap = Collections.unmodifiableMap(localMap);
            this.context = context;
            this.writer = writer;
            this.screenStringRenderer = screenStringRenderer;
        }

        /** This is a lot like the ScreenRenderer class and returns an empty String so it can be used more easily with FreeMarker */
        public String render(String sectionName) throws GeneralException, IOException {
            ModelScreenWidget section = sectionMap.get(sectionName);
            // if no section by that name, write nothing
            if (section != null) {
                section.renderWidgetString(this.writer, this.context, this.screenStringRenderer);
            }
            return "";
        }

        @Override
        public int size() {
            return sectionMap.size();
        }

        @Override
        public boolean isEmpty() {
            return sectionMap.isEmpty();
        }

        @Override
        public boolean containsKey(Object key) {
            return sectionMap.containsKey(key);
        }

        @Override
        public boolean containsValue(Object value) {
            return sectionMap.containsValue(value);
        }

        @Override
        public ModelScreenWidget get(Object key) {
            return sectionMap.get(key);
        }

        @Override
        public ModelScreenWidget put(String key, ModelScreenWidget value) {
            return sectionMap.put(key, value);
        }

        @Override
        public ModelScreenWidget remove(Object key) {
            return sectionMap.remove(key);
        }

        @Override
        public void clear() {
            sectionMap.clear();
        }

        @Override
        public Set<String> keySet() {
            return sectionMap.keySet();
        }

        @Override
        public Collection<ModelScreenWidget> values() {
            return sectionMap.values();
        }

        @Override
        public Set<java.util.Map.Entry<String, ModelScreenWidget>> entrySet() {
            return sectionMap.entrySet();
        }

        @Override
        public boolean equals(Object o) {
            return sectionMap.equals(o);
        }

        @Override
        public int hashCode() {
            return sectionMap.hashCode();
        }

        @Override
        public void putAll(Map<? extends String, ? extends ModelScreenWidget> m) {
            sectionMap.putAll(m);
        }
    }

    public static final class Section extends ModelScreenWidget {
        public static final String TAG_NAME = "section";
        private final ModelScreenCondition condition;
        private final List<ModelWidgetAction> 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) {
                this.condition = new ModelScreenCondition(modelScreen, conditionElement);
            } else {
                this.condition = null;
            }

            // read all actions under the "actions" element
            Element actionsElement = UtilXml.firstChildElement(sectionElement, "actions");
            if (actionsElement != null) {
                this.actions = ModelWidgetAction.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
                ModelWidgetAction.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<ModelWidgetAction> getActions() {
            return actions;
        }

        public List<ModelScreenWidget> getSubWidgets() {
            return subWidgets;
        }

        public List<ModelScreenWidget> getFailWidgets() {
            return failWidgets;
        }

        public boolean isMainSection() {
            return isMainSection;
        }
    }

    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 static final class Column {
        private final FlexibleStringExpander idExdr;
        private final FlexibleStringExpander styleExdr;
        private final List<ModelScreenWidget> subWidgets;

        public Column(ModelScreen modelScreen, Element 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);
        }
    }

    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 static final class Screenlet extends ModelScreenWidget {
        public static final String TAG_NAME = "screenlet";
        private final FlexibleStringExpander idExdr;
        private final FlexibleStringExpander titleExdr;
        private final Menu navigationMenu;
        private final Menu tabMenu;
        private final Form navigationForm;
        private final boolean collapsible;
        private final FlexibleStringExpander initiallyCollapsed;
        private final boolean saveCollapsed;
        private final boolean padded;
        private final List<ModelScreenWidget> subWidgets;

        public Screenlet(ModelScreen modelScreen, Element screenletElement) {
            super(modelScreen, screenletElement);
            this.idExdr = FlexibleStringExpander.getInstance(screenletElement.getAttribute("id"));
            boolean collapsible = "true".equals(screenletElement.getAttribute("collapsible"));
            this.initiallyCollapsed = FlexibleStringExpander.getInstance(screenletElement.getAttribute("initially-collapsed"));
            if ("true".equals(this.initiallyCollapsed.getOriginal())) {
                collapsible = true;
            }
            this.collapsible = collapsible;
            // By default, for a collapsible screenlet, the collapsed/expanded status must be saved
            this.saveCollapsed = !("false".equals(screenletElement.getAttribute("save-collapsed")));

            boolean padded = !"false".equals(screenletElement.getAttribute("padded"));
            if (this.collapsible && getName().isEmpty() && idExdr.isEmpty()) {
                throw new IllegalArgumentException("Collapsible screenlets must have a name or id [" + getModelScreen().getName() + "]");
            }
            this.titleExdr = FlexibleStringExpander.getInstance(screenletElement.getAttribute("title"));
            List<? extends Element> subElementList = UtilXml.childElementList(screenletElement);
            // Make a copy of the unmodifiable List so we can modify it.
            ArrayList<ModelScreenWidget> subWidgets = new ArrayList<ModelScreenWidget>(ModelScreenWidget.readSubWidgets(getModelScreen(), subElementList));
            Menu navigationMenu = null;
            String navMenuName = screenletElement.getAttribute("navigation-menu-name");
            if (!navMenuName.isEmpty()) {
                for (ModelWidget subWidget : subWidgets) {
                    if (navMenuName.equals(subWidget.getName()) && subWidget instanceof Menu) {
                        navigationMenu = (Menu) subWidget;
                        subWidgets.remove(subWidget);
                        break;
                    }
                }
            }
            this.navigationMenu = navigationMenu;
            Menu tabMenu = null;
            String tabMenuName = screenletElement.getAttribute("tab-menu-name");
            if (!tabMenuName.isEmpty()) {
                for (ModelWidget subWidget : subWidgets) {
                    if (tabMenuName.equals(subWidget.getName()) && subWidget instanceof Menu) {
                        tabMenu = (Menu) subWidget;
                        subWidgets.remove(subWidget);
                        break;
                    }
                }
            }
            this.tabMenu = tabMenu;
            Form navigationForm = null;
            String formName = screenletElement.getAttribute("navigation-form-name");
            if (!formName.isEmpty() && this.navigationMenu == null) {
                for (ModelWidget subWidget : subWidgets) {
                    if (formName.equals(subWidget.getName()) && subWidget instanceof Form) {
                        navigationForm = (Form) subWidget;
                        padded = false;
                        break;
                    }
                }
            }
            this.subWidgets = Collections.unmodifiableList(subWidgets);
            this.navigationForm = navigationForm;
            this.padded = padded;
        }

        @Override
        public void renderWidgetString(Appendable writer, Map<String, Object> context, ScreenStringRenderer screenStringRenderer) throws GeneralException, IOException {
            boolean collapsed = getInitiallyCollapsed(context);
            if (this.collapsible) {
                String preferenceKey = getPreferenceKey(context) + "_collapsed";
                Map<String, Object> requestParameters = UtilGenerics.checkMap(context.get("requestParameters"));
                if (requestParameters != null) {
                    String collapsedParam = (String) requestParameters.get(preferenceKey);
                    collapsed = "true".equals(collapsedParam);
                }
            }
            try {
                screenStringRenderer.renderScreenletBegin(writer, context, collapsed, this);
                for (ModelScreenWidget subWidget : this.subWidgets) {
                    screenStringRenderer.renderScreenletSubWidget(writer, context, subWidget, this);
                }
                screenStringRenderer.renderScreenletEnd(writer, context, this);
            } catch (IOException e) {
                String errMsg = "Error rendering screenlet in screen named [" + getModelScreen().getName() + "]: ";
                Debug.logError(e, errMsg, module);
                throw new RuntimeException(errMsg + e);
            }
        }

        public boolean collapsible() {
            return this.collapsible;
        }

        //initially-collapsed status, which may be overriden by user preference
        public boolean getInitiallyCollapsed(Map<String, Object> context) {
            String screenletId = this.getId(context) + "_collapsed";
            Map<String, ? extends Object> userPreferences = UtilGenerics.checkMap(context.get("userPreferences"));
            if (userPreferences != null && userPreferences.containsKey(screenletId)) {
                return Boolean.valueOf((String)userPreferences.get(screenletId)).booleanValue() ;
            }

            return "true".equals(this.initiallyCollapsed.expand(context));
        }

        public boolean saveCollapsed() {
            return this.saveCollapsed;
        }
        public boolean padded() {
            return this.padded;
        }

        public String getPreferenceKey(Map<String, Object> context) {
            String name = this.idExdr.expandString(context);
            if (name.isEmpty()) {
                name = "screenlet" + "_" + Integer.toHexString(hashCode());
            }
            return name;
        }

        public String getId(Map<String, Object> context) {
            return this.idExdr.expandString(context);
        }

        public List<ModelScreenWidget> getSubWidgets() {
            return subWidgets;
        }

        public String getTitle(Map<String, Object> context) {
            String title = this.titleExdr.expandString(context);
            StringUtil.SimpleEncoder simpleEncoder = (StringUtil.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 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 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 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 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);
            StringUtil.SimpleEncoder simpleEncoder = (StringUtil.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 static final class Form extends ModelScreenWidget {
        public static final String TAG_NAME = "include-form";
        private final FlexibleStringExpander nameExdr;
        private final FlexibleStringExpander locationExdr;
        private final FlexibleStringExpander shareScopeExdr;

        public Form(ModelScreen modelScreen, Element formElement) {
            super(modelScreen, formElement);
            this.nameExdr = FlexibleStringExpander.getInstance(formElement.getAttribute("name"));
            this.locationExdr = FlexibleStringExpander.getInstance(formElement.getAttribute("location"));
            this.shareScopeExdr = FlexibleStringExpander.getInstance(formElement.getAttribute("share-scope"));
        }

        @Override
        public void renderWidgetString(Appendable writer, Map<String, Object> context, ScreenStringRenderer screenStringRenderer) {
            // Output format might not support forms, so make form rendering optional.
            FormStringRenderer formStringRenderer = (FormStringRenderer) context.get("formStringRenderer");
            if (formStringRenderer == null) {
                Debug.logVerbose("FormStringRenderer instance not found in rendering context, form not rendered.", module);
                return;
            }
            boolean protectScope = !shareScope(context);
            if (protectScope) {
                if (!(context instanceof MapStack<?>)) {
                    context = MapStack.create(context);
                }
                UtilGenerics.<MapStack<String>>cast(context).push();
            }
            ModelForm modelForm = getModelForm(context);
            FormRenderer renderer = new FormRenderer(modelForm, formStringRenderer);
            try {
                renderer.render(writer, context);
            } catch (Exception e) {
                String errMsg = "Error rendering included form named [" + getName() + "] at location [" + this.getLocation(context) + "]: " + e.toString();
                Debug.logError(e, errMsg, module);
                throw new RuntimeException(errMsg + e);
            }

            if (protectScope) {
                UtilGenerics.<MapStack<String>>cast(context).pop();
            }
        }

        public ModelForm getModelForm(Map<String, Object> context) {
            ModelForm modelForm = null;
            String name = this.getName(context);
            String location = this.getLocation(context);
            try {
                modelForm = FormFactory.getFormFromLocation(location, name, getModelScreen().getDelegator(context).getModelReader(), getModelScreen().getDispatcher(context).getDispatchContext());
            } catch (Exception e) {
                String errMsg = "Error rendering included form named [" + name + "] at location [" + location + "]: ";
                Debug.logError(e, errMsg, module);
                throw new RuntimeException(errMsg + e);
            }
            return modelForm;
        }

        public String getName(Map<String, Object> context) {
            return this.nameExdr.expandString(context);
        }

        public String getLocation() {
            return locationExdr.getOriginal();
        }

        public String getLocation(Map<String, Object> context) {
            return this.locationExdr.expandString(context);
        }

        public boolean shareScope(Map<String, Object> context) {
            String shareScopeString = this.shareScopeExdr.expandString(context);
            // defaults to false, so anything but true is false
            return "true".equals(shareScopeString);
        }

        @Override
        public void accept(ModelWidgetVisitor visitor) throws Exception {
            visitor.visit(this);
        }
    }

    public 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);
            }
            StringBuffer renderBuffer = new StringBuffer();
            modelTree.renderTreeString(renderBuffer, context, treeStringRenderer);
            try {
                writer.append(renderBuffer.toString());
            } 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);
            }

            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 static final class PlatformSpecific extends ModelScreenWidget {
        public static final String TAG_NAME = "platform-specific";
        private final Map<String, ModelScreenWidget> subWidgets;

        public PlatformSpecific(ModelScreen modelScreen, Element platformSpecificElement) {
            super(modelScreen, platformSpecificElement);
            Map<String, ModelScreenWidget> subWidgets = new HashMap<String, ModelScreenWidget>();
            List<? extends Element> childElements = UtilXml.childElementList(platformSpecificElement);
            if (childElements != null) {
                for (Element childElement: childElements) {
                    if ("html".equals(childElement.getNodeName())) {
                        subWidgets.put("html", new HtmlWidget(modelScreen, childElement));
                    } else if ("xsl-fo".equals(childElement.getNodeName())) {
                        subWidgets.put("xsl-fo", new HtmlWidget(modelScreen, childElement));
                    } else if ("xml".equals(childElement.getNodeName())) {
                        subWidgets.put("xml", new HtmlWidget(modelScreen, childElement));
                    } else {
                        throw new IllegalArgumentException("Tag not supported under the platform-specific tag with name: " + childElement.getNodeName());
                    }
                }
            }
            this.subWidgets = Collections.unmodifiableMap(subWidgets);
        }

        @Override
        public void renderWidgetString(Appendable writer, Map<String, Object> context, ScreenStringRenderer screenStringRenderer) throws GeneralException, IOException {
            ModelScreenWidget subWidget = null;
            subWidget = subWidgets.get(screenStringRenderer.getRendererName());
            if (subWidget == null) {
                // This is here for backward compatibility
                Debug.logWarning("In platform-dependent could not find template for " + screenStringRenderer.getRendererName() + ", using the one for html.", module);
                subWidget = subWidgets.get("html");
            }
            if (subWidget != null) {
                subWidget.renderWidgetString(writer, context, screenStringRenderer);
            }
        }

        @Override
        public void accept(ModelWidgetVisitor visitor) throws Exception {
            visitor.visit(this);
        }

        public Map<String, ModelScreenWidget> getSubWidgets() {
            return subWidgets;
        }
    }

    public static final class Content extends ModelScreenWidget {
        public static final String TAG_NAME = "content";

        private final FlexibleStringExpander contentId;
        private final FlexibleStringExpander editRequest;
        private final FlexibleStringExpander editContainerStyle;
        private final FlexibleStringExpander enableEditName;
        private final boolean xmlEscape;
        private final FlexibleStringExpander dataResourceId;
        private final String width;
        private final String height;
        private final String border;

        public Content(ModelScreen modelScreen, Element subContentElement) {
            super(modelScreen, subContentElement);
            this.contentId = FlexibleStringExpander.getInstance(subContentElement.getAttribute("content-id"));
            this.dataResourceId = FlexibleStringExpander.getInstance(subContentElement.getAttribute("dataresource-id"));
            this.editRequest = FlexibleStringExpander.getInstance(subContentElement.getAttribute("edit-request"));
            this.editContainerStyle = FlexibleStringExpander.getInstance(subContentElement.getAttribute("edit-container-style"));
            this.enableEditName = FlexibleStringExpander.getInstance(subContentElement.getAttribute("enable-edit-name"));
            this.xmlEscape = "true".equals(subContentElement.getAttribute("xml-escape"));
            String width = subContentElement.getAttribute("width");
            if (width.isEmpty())
                width = "60%";
            this.height = subContentElement.getAttribute("height");
            if (this.height.isEmpty())
                width = "400px";
            this.width = width;
            this.border = subContentElement.getAttribute("border");
        }

        @Override
        public void renderWidgetString(Appendable writer, Map<String, Object> context, ScreenStringRenderer screenStringRenderer) {
            try {
                // pushing the contentId on the context as "contentId" is done
                // because many times there will be embedded "subcontent" elements
                // that use the syntax: <subcontent content-id="${contentId}"...
                // and this is a step to make sure that it is there.
                Delegator delegator = (Delegator) context.get("delegator");
                GenericValue content = null;
                String expandedDataResourceId = getDataResourceId(context);
                String expandedContentId = getContentId(context);
                if (!(context instanceof MapStack<?>)) {
                    context = MapStack.create(context);
                }

                // This is an important step to make sure that the current contentId is in the context
                // as templates that contain "subcontent" elements will expect to find the master
                // contentId in the context as "contentId".
                UtilGenerics.<MapStack<String>>cast(context).push();
                context.put("contentId", expandedContentId);

                if (expandedDataResourceId.isEmpty()) {
                    if (!expandedContentId.isEmpty()) {
                        content = EntityQuery.use(delegator).from("Content").where("contentId", expandedContentId).cache().queryOne();
                    } else {
                        String errMsg = "contentId is empty.";
                        Debug.logError(errMsg, module);
                        return;
                    }
                    if (content != null) {
                        expandedDataResourceId = content.getString("dataResourceId");
                    } else {
                        String errMsg = "Could not find content with contentId [" + expandedContentId + "] ";
                        Debug.logError(errMsg, module);
                        throw new RuntimeException(errMsg);
                    }
                }

                GenericValue dataResource = null;
                if (!expandedDataResourceId.isEmpty()) {
                    dataResource = EntityQuery.use(delegator).from("DataResource").where("dataResourceId", expandedDataResourceId).cache().queryOne();
                }

                String mimeTypeId = null;
                if (dataResource != null) {
                    mimeTypeId = dataResource.getString("mimeTypeId");
                }
                if (content != null) {
                    mimeTypeId = content.getString("mimeTypeId");
                }

                if (!(mimeTypeId != null
                        && ((mimeTypeId.indexOf("application") >= 0) || (mimeTypeId.indexOf("image")) >= 0))) {
                    screenStringRenderer.renderContentBegin(writer, context, this);
                    screenStringRenderer.renderContentBody(writer, context, this);
                    screenStringRenderer.renderContentEnd(writer, context, this);
                }
                UtilGenerics.<MapStack<String>>cast(context).pop();
            } catch (IOException e) {
                String errMsg = "Error rendering content with contentId [" + getContentId(context) + "]: " + e.toString();
                Debug.logError(e, errMsg, module);
                throw new RuntimeException(errMsg);
            } catch (GenericEntityException e) {
                String errMsg = "Error obtaining content with contentId [" + getContentId(context) + "]: " + e.toString();
                Debug.logError(e, errMsg, module);
                throw new RuntimeException(errMsg);
            }

        }

        public String getContentId(Map<String, Object> context) {
            return this.contentId.expandString(context);
        }

        public String getDataResourceId() {
            return this.dataResourceId.getOriginal();
        }

        public String getDataResourceId(Map<String, Object> context) {
            return this.dataResourceId.expandString(context);
        }

        public String getEditRequest(Map<String, Object> context) {
            return this.editRequest.expandString(context);
        }

        public String getEditContainerStyle(Map<String, Object> context) {
            return this.editContainerStyle.expandString(context);
        }

        public String getEnableEditName(Map<String, Object> context) {
            return this.enableEditName.expandString(context);
        }

        public boolean xmlEscape() {
            return this.xmlEscape;
        }

        public String getWidth() {
            return this.width;
        }

        public String getHeight() {
            return this.height;
        }

        public String getBorder() {
            return this.border;
        }

        @Override
        public void accept(ModelWidgetVisitor visitor) throws Exception {
            visitor.visit(this);
        }
    }

    public 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 static final class Link extends ModelScreenWidget {
        public static final String TAG_NAME = "link";
        private final FlexibleStringExpander textExdr;
        private final FlexibleStringExpander idExdr;
        private final FlexibleStringExpander styleExdr;
        private final FlexibleStringExpander targetExdr;
        private final FlexibleStringExpander targetWindowExdr;
        private final FlexibleStringExpander prefixExdr;
        private final FlexibleStringExpander nameExdr;
        private final Image image;
        private final String urlMode;
        private final boolean fullPath;
        private final boolean secure;
        private final boolean encode;
        private final String linkType;
        private final String width;
        private final String height;
        private final List<WidgetWorker.Parameter> parameterList;
        private final WidgetWorker.AutoServiceParameters autoServiceParameters;
        private final WidgetWorker.AutoEntityParameters autoEntityParameters;

        public Link(ModelScreen modelScreen, Element linkElement) {
            super(modelScreen, linkElement);
            this.textExdr = FlexibleStringExpander.getInstance(linkElement.getAttribute("text"));
            this.idExdr = FlexibleStringExpander.getInstance(linkElement.getAttribute("id"));
            this.styleExdr = FlexibleStringExpander.getInstance(linkElement.getAttribute("style"));
            this.nameExdr = FlexibleStringExpander.getInstance(linkElement.getAttribute("name"));
            this.targetExdr = FlexibleStringExpander.getInstance(linkElement.getAttribute("target"));
            this.targetWindowExdr = FlexibleStringExpander.getInstance(linkElement.getAttribute("target-window"));
            this.prefixExdr = FlexibleStringExpander.getInstance(linkElement.getAttribute("prefix"));
            this.urlMode = linkElement.getAttribute("url-mode");
            this.fullPath = "true".equals(linkElement.getAttribute("full-path"));
            this.secure = "true".equals(linkElement.getAttribute("secure"));
            this.encode = "true".equals(linkElement.getAttribute("encode"));
            Element imageElement = UtilXml.firstChildElement(linkElement, "image");
            if (imageElement != null) {
                this.image = new Image(modelScreen, imageElement);
            } else {
                this.image = null;
            }
            this.linkType = linkElement.getAttribute("link-type");
            List<? extends Element> parameterElementList = UtilXml.childElementList(linkElement, "parameter");
            if (parameterElementList.isEmpty()) {
                this.parameterList = Collections.emptyList();
            } else {
                List<WidgetWorker.Parameter> parameterList = new ArrayList<WidgetWorker.Parameter>(parameterElementList.size());
                for (Element parameterElement : parameterElementList) {
                    parameterList.add(new WidgetWorker.Parameter(parameterElement));
                }
                this.parameterList = Collections.unmodifiableList(parameterList);
            }
            Element autoServiceParamsElement = UtilXml.firstChildElement(linkElement, "auto-parameters-service");
            if (autoServiceParamsElement != null) {
                this.autoServiceParameters = new WidgetWorker.AutoServiceParameters(autoServiceParamsElement);
            } else {
                this.autoServiceParameters = null;
            }
            Element autoEntityParamsElement = UtilXml.firstChildElement(linkElement, "auto-parameters-entity");
            if (autoEntityParamsElement != null) {
                this.autoEntityParameters = new WidgetWorker.AutoEntityParameters(autoEntityParamsElement);
            } else {
                this.autoEntityParameters = null;
            }
            this.width = linkElement.getAttribute("width");
            this.height = linkElement.getAttribute("height");
        }

        @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 [" + getId(context) + "]: " + e.toString();
                Debug.logError(e, errMsg, module);
                throw new RuntimeException(errMsg);
            }
        }

        public String getText(Map<String, Object> context) {
            String text = this.textExdr.expandString(context);
            StringUtil.SimpleEncoder simpleEncoder = (StringUtil.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);
        }

        public String getTarget(Map<String, Object> context) {
            Map<String, Object> expanderContext = context;
            StringUtil.SimpleEncoder simpleEncoder = context == null ? null : (StringUtil.SimpleEncoder) context.get("simpleEncoder");
            if (simpleEncoder != null) {
                expanderContext = StringUtil.HtmlEncodingMapWrapper.getHtmlEncodingMapWrapper(context, simpleEncoder);
            }
            return this.targetExdr.expandString(expanderContext);
        }

        public String getName(Map<String, Object> context) {
            return this.nameExdr.expandString(context);
        }

        public String getTargetWindow(Map<String, Object> context) {
            return this.targetWindowExdr.expandString(context);
        }

        public String getUrlMode() {
            return this.urlMode;
        }

        public String getPrefix(Map<String, Object> context) {
            return this.prefixExdr.expandString(context);
        }

        public boolean getFullPath() {
            return this.fullPath;
        }

        public boolean getSecure() {
            return this.secure;
        }

        public boolean getEncode() {
            return this.encode;
        }

        public Image getImage() {
            return this.image;
        }

        public String getLinkType() {
            return this.linkType;
        }

        public String getWidth() {
            return this.width;
        }

        public String getHeight() {
            return this.height;
        }

        public Map<String, String> getParameterMap(Map<String, Object> context) {
            Map<String, String> fullParameterMap = new HashMap<String, String>();

            /* leaving this here... may want to add it at some point like the hyperlink element:
            Map<String, String> addlParamMap = this.parametersMapAcsr.get(context);
            if (addlParamMap != null) {
                fullParameterMap.putAll(addlParamMap);
            }
            */
            
            for (WidgetWorker.Parameter parameter: this.parameterList) {
                fullParameterMap.put(parameter.getName(), parameter.getValue(context));
            }

            if (autoServiceParameters != null) {
                fullParameterMap.putAll(autoServiceParameters.getParametersMap(context, null));
            }
            if (autoEntityParameters != null) {
                fullParameterMap.putAll(autoEntityParameters.getParametersMap(context, null));
            }

            return fullParameterMap;
        }

        @Override
        public void accept(ModelWidgetVisitor visitor) throws Exception {
            visitor.visit(this);
        }
    }

    public static final class Image extends ModelScreenWidget {
        public static final String TAG_NAME = "image";
        private final FlexibleStringExpander srcExdr;
        private final FlexibleStringExpander idExdr;
        private final FlexibleStringExpander styleExdr;
        private final FlexibleStringExpander widthExdr;
        private final FlexibleStringExpander heightExdr;
        private final FlexibleStringExpander borderExdr;
        private final FlexibleStringExpander alt;
        private final String urlMode;

        public Image(ModelScreen modelScreen, Element imageElement) {
            super(modelScreen, imageElement);
            this.srcExdr = FlexibleStringExpander.getInstance(imageElement.getAttribute("src"));
            this.idExdr = FlexibleStringExpander.getInstance(imageElement.getAttribute("id"));
            this.styleExdr = FlexibleStringExpander.getInstance(imageElement.getAttribute("style"));
            this.widthExdr = FlexibleStringExpander.getInstance(imageElement.getAttribute("width"));
            this.heightExdr = FlexibleStringExpander.getInstance(imageElement.getAttribute("height"));
            this.borderExdr = FlexibleStringExpander.getInstance(imageElement.getAttribute("border"));
            this.alt = FlexibleStringExpander.getInstance(imageElement.getAttribute("alt"));
            String urlMode = imageElement.getAttribute("url-mode");
            if (urlMode.isEmpty()) {
                urlMode = "content";
            }
            this.urlMode = urlMode;
        }

        @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 [" + getId(context) + "]: " + e.toString();
                Debug.logError(e, errMsg, module);
                throw new RuntimeException(errMsg);
            }
        }

        public String getSrc(Map<String, Object> context) {
            return this.srcExdr.expandString(context);
        }

        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 getWidth(Map<String, Object> context) {
            return this.widthExdr.expandString(context);
        }

        public String getHeight(Map<String, Object> context) {
            return this.heightExdr.expandString(context);
        }

        public String getBorder(Map<String, Object> context) {
            return this.borderExdr.expandString(context);
        }

        public String getAlt(Map<String, Object> context) {
            String alt = this.alt.expandString(context);
            StringUtil.SimpleEncoder simpleEncoder = (StringUtil.SimpleEncoder) context.get("simpleEncoder");
            if (simpleEncoder != null) {
                alt = simpleEncoder.encode(alt);
            }
            return alt;
        }

        public String getUrlMode() {
            return this.urlMode;
        }

        @Override
        public void accept(ModelWidgetVisitor visitor) throws Exception {
            visitor.visit(this);
        }
    }

    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 = delegator.findByAnd("PortalPageColumn", UtilMisc.toMap("portalPageId", actualPortalPageId),
                        UtilMisc.toList("columnSeqId"), true);

                // 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 = delegator.findByAnd("PortalPagePortletView", UtilMisc.toMap("portalPageId", portalPage.getString("portalPageId"), "columnSeqId", columnSeqId), UtilMisc.toList("sequenceNum"), false);
                    
                    // 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 = delegator.findList("PortletAttribute",
                            EntityCondition.makeCondition(UtilMisc.toMap("portalPageId", portletValue.get("portalPageId"), "portalPortletId", portletValue.get("portalPortletId"), "portletSeqId", portletValue.get("portletSeqId"))),
                            null, null, null, false);
                        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);
        }
    }

}
