com.netspective.sparx.form.Dialog.java Source code

Java tutorial

Introduction

Here is the source code for com.netspective.sparx.form.Dialog.java

Source

/*
 * Copyright (c) 2000-2004 Netspective Communications LLC. All rights reserved.
 *
 * Netspective Communications LLC ("Netspective") permits redistribution, modification and use of this file in source
 * and binary form ("The Software") under the Netspective Source License ("NSL" or "The License"). The following
 * conditions are provided as a summary of the NSL but the NSL remains the canonical license and must be accepted
 * before using The Software. Any use of The Software indicates agreement with the NSL.
 *
 * 1. Each copy or derived work of The Software must preserve the copyright notice and this notice unmodified.
 *
 * 2. Redistribution of The Software is allowed in object code form only (as Java .class files or a .jar file
 *    containing the .class files) and only as part of an application that uses The Software as part of its primary
 *    functionality. No distribution of the package is allowed as part of a software development kit, other library,
 *    or development tool without written consent of Netspective. Any modified form of The Software is bound by these
 *    same restrictions.
 *
 * 3. Redistributions of The Software in any form must include an unmodified copy of The License, normally in a plain
 *    ASCII text file unless otherwise agreed to, in writing, by Netspective.
 *
 * 4. The names "Netspective", "Axiom", "Commons", "Junxion", and "Sparx" are trademarks of Netspective and may not be
 *    used to endorse or appear in products derived from The Software without written consent of Netspective.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT A WARRANTY OF ANY KIND. ALL EXPRESS OR IMPLIED REPRESENTATIONS AND
 * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT,
 * ARE HEREBY DISCLAIMED.
 *
 * NETSPECTIVE AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE OR ANY THIRD PARTY AS A
 * RESULT OF USING OR DISTRIBUTING THE SOFTWARE. IN NO EVENT WILL NETSPECTIVE OR ITS LICENSORS BE LIABLE FOR ANY LOST
 * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER
 * CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THE SOFTWARE, EVEN
 * IF IT HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
 */
package com.netspective.sparx.form;

import java.io.File;
import java.io.IOException;
import java.io.Writer;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.servlet.http.HttpSession;

import org.apache.commons.collections.LRUMap;
import org.apache.commons.lang.exception.NestableRuntimeException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.tools.ant.Main;

import com.netspective.commons.text.TextUtils;
import com.netspective.commons.value.ValueSource;
import com.netspective.commons.value.source.StaticValueSource;
import com.netspective.commons.xdm.XdmParseContext;
import com.netspective.commons.xdm.XmlDataModelSchema;
import com.netspective.commons.xdm.exception.DataModelException;
import com.netspective.commons.xml.template.Template;
import com.netspective.commons.xml.template.TemplateCatalog;
import com.netspective.commons.xml.template.TemplateConsumer;
import com.netspective.commons.xml.template.TemplateConsumerDefn;
import com.netspective.sparx.Project;
import com.netspective.sparx.form.field.DialogField;
import com.netspective.sparx.form.field.DialogFieldFlags;
import com.netspective.sparx.form.field.DialogFields;
import com.netspective.sparx.form.field.type.CompositeField;
import com.netspective.sparx.form.field.type.GridField;
import com.netspective.sparx.form.field.type.SectionField;
import com.netspective.sparx.form.field.type.SeparatorField;
import com.netspective.sparx.form.handler.DialogExecuteDefaultHandler;
import com.netspective.sparx.form.handler.DialogExecuteHandler;
import com.netspective.sparx.form.handler.DialogExecuteHandlerTemplateConsumer;
import com.netspective.sparx.form.handler.DialogExecuteHandlers;
import com.netspective.sparx.form.handler.DialogNextActionProvider;
import com.netspective.sparx.form.listener.DialogInitialPopulateForDisplayListener;
import com.netspective.sparx.form.listener.DialogInitialPopulateForSubmitListener;
import com.netspective.sparx.form.listener.DialogInitialPopulateListener;
import com.netspective.sparx.form.listener.DialogListener;
import com.netspective.sparx.form.listener.DialogListenerPlaceholder;
import com.netspective.sparx.form.listener.DialogPopulateForDisplayListener;
import com.netspective.sparx.form.listener.DialogPopulateForSubmitListener;
import com.netspective.sparx.form.listener.DialogPopulateListener;
import com.netspective.sparx.form.listener.DialogStateAfterValidationListener;
import com.netspective.sparx.form.listener.DialogStateBeforeValidationListener;
import com.netspective.sparx.form.listener.DialogStateListener;
import com.netspective.sparx.form.listener.DialogValidateListener;
import com.netspective.sparx.navigate.NavigationContext;
import com.netspective.sparx.panel.AbstractPanel;
import com.netspective.sparx.panel.HtmlInputPanel;
import com.netspective.sparx.panel.editor.PanelEditor;
import com.netspective.sparx.panel.editor.PanelEditorState;
import com.netspective.sparx.theme.Theme;
import com.netspective.sparx.value.source.ThemeResourceUrlValueSource;

/**
 * The <code>Dialog</code> object contains the dialog/form's structural information, field types, rules, and
 * execution logic. It is cached and reused whenever needed. It contains methods to create the HTML for display,
 * to perform client-side validations, and to perform server-side validations.
 */
public class Dialog extends AbstractPanel
        implements HtmlInputPanel, TemplateConsumer, XmlDataModelSchema.ConstructionFinalizeListener {
    public static final XmlDataModelSchema.Options XML_DATA_MODEL_SCHEMA_OPTIONS = new XmlDataModelSchema.Options()
            .setIgnorePcData(true);
    public static final String ATTRNAME_TYPE = "type";
    public static final String[] ATTRNAMES_SET_BEFORE_CONSUMING = new String[] { "name" };

    private static DialogTypeTemplateConsumerDefn dialogTypeConsumer = new DialogTypeTemplateConsumerDefn();
    private static int dialogNumber = 0;

    static {
        TemplateCatalog.registerConsumerDefnForClass(dialogTypeConsumer, Dialog.class, true, true);
        TemplateCatalog.registerConsumerDefnForClass(DialogExecuteHandlerTemplateConsumer.INSTANCE,
                DialogExecuteHandler.class, true, true);
    }

    protected static class DialogTypeTemplateConsumerDefn extends TemplateConsumerDefn {
        public DialogTypeTemplateConsumerDefn() {
            super(Dialog.class.getName(), ATTRNAME_TYPE, ATTRNAMES_SET_BEFORE_CONSUMING);
        }

        public String getNameSpaceId() {
            return Dialog.class.getName();
        }
    }

    /**
     * Request parameter which indicates whether or not the dialog should be automatically executed when it is being loaded
     */
    public static final String PARAMNAME_AUTOEXECUTE = "_d_exec";
    public static final String PARAMNAME_OVERRIDE_SKIN = "_d_skin";
    public static final String PARAMNAME_DIALOGPREFIX = "_d.";
    public static final String PARAMNAME_CONTROLPREFIX = "_dc.";

    public static final String ATTRNAME_DIALOG_STATES = Dialog.class.getName() + ".STATES";
    public static final String ATTRNAME_DIALOG_STATES_MAX_ENTRIES = Dialog.class.getName() + ".STATES.MAX_ENTRIES";
    public static final int DIALOG_STATES_LRU_MAP_DEFAULT_MAX_SIZE = 16; // keep the last 32 dialog states in the session at any time

    public static final String PARAMNAME_DIALOG_STATE_ID = ".dialog_state_id";
    public static final String PARAMNAME_POST_EXECUTE_REDIRECT = ".post_exec_redirect";
    public static final String PARAMNAME_SUBMIT_DATA = ".submit_data";
    public static final String PARAMNAME_PEND_DATA = ".pend_data";
    public static final String PARAMNAME_CANCEL_DATA = ".cancel_data";
    public static final String PARAMNAME_RESET_CONTEXT = ".reset_context";
    public static final String PARAMNAME_VALIDATE_TRIGGER_FIELD = ".validate_trigger_field";

    /**
     * Converts dialog name to uppercase for use as MapKey
     *
     * @param name dialog name
     *
     * @return formatted dialog name
     */
    public static final String translateNameForMapKey(String name) {
        return name != null ? name.toUpperCase() : null;
    }

    private Project project;
    private Log log = LogFactory.getLog(Dialog.class);
    private DialogFields fields;
    private DialogFlags dialogFlags;
    private DialogDebugFlags debugFlags;
    private DialogLoopStyle loop = new DialogLoopStyle(DialogLoopStyle.APPEND);
    private DialogDirector director = createDirector();
    private DialogsNameSpace nameSpace;
    private String name = "dialog_" + (++dialogNumber);
    private String htmlFormName;
    private int layoutColumnsCount = 1;
    private String[] retainRequestParams;
    private Class dialogContextClass = DialogContext.class;
    private List dialogTypes = new ArrayList();
    private List clientJavascripts = new ArrayList();
    private DialogExecuteHandlers executeHandlers = new DialogExecuteHandlers();
    private DialogNextActionProvider nextActionProvider;
    private boolean redirectAfterExecute = true;
    private ValueSource multipleExecErrorMessage = new StaticValueSource(
            "Multiple executions of this dialog are not allowed.");
    private String cookieName;

    private boolean haveInitialPopulateForDisplayListeners;
    private boolean haveInitialPopulateForSubmitListeners;
    private boolean haveInitialPopulateListeners;
    private boolean havePopulateForDisplayListeners;
    private boolean havePopulateForSubmitListeners;
    private boolean havePopulateListeners;
    private boolean haveStateAfterValidationListeners;
    private boolean haveStateBeforeValidationListeners;
    private boolean haveStateListeners;
    private boolean haveValidationListeners;
    private List initialPopulateForDisplayListeners = new ArrayList();
    private List initialPopulateForSubmitListeners = new ArrayList();
    private List initialPopulateListeners = new ArrayList();
    private List populateForDisplayListeners = new ArrayList();
    private List populateForSubmitListeners = new ArrayList();
    private List populateListeners = new ArrayList();
    private List stateAfterValidationListeners = new ArrayList();
    private List stateBeforeValidationListeners = new ArrayList();
    private List stateListeners = new ArrayList();
    private List validationListeners = new ArrayList();

    /**
     * Creates an empty dialog object.
     */
    public Dialog() {
        fields = constructFields();
        dialogFlags = createDialogFlags();
        debugFlags = createDebugFlags();
    }

    /**
     * Creates a dialog in the project.
     *
     * @param project the project in which the dialog is created
     */
    public Dialog(Project project) {
        this.project = project;
        fields = constructFields();
        dialogFlags = createDialogFlags();
        debugFlags = createDebugFlags();
    }

    /**
     * Creates a dialog in the project.
     *
     * @param project the project in which the dialog is created
     * @param pkg     the package in which the dialog is created
     */
    public Dialog(Project project, DialogsPackage pkg) {
        this(project);
        setNameSpace(pkg);
    }

    /**
     * Gets the project object for the dialog.
     *
     * @return the project object for the dialog
     */
    public Project getProject() {
        return project;
    }

    public TemplateConsumerDefn getTemplateConsumerDefn() {
        return dialogTypeConsumer;
    }

    public void registerTemplateConsumption(Template template) {
        dialogTypes.add(template.getTemplateName());
    }

    public DialogFields constructFields() {
        return new DialogFields(this);
    }

    public DialogFlags createDialogFlags() {
        return new DialogFlags();
    }

    public DialogDebugFlags createDebugFlags() {
        return new DialogDebugFlags();
    }

    public Log getLog() {
        return log;
    }

    /**
     * Gets the name of the dialog.
     *
     * @return dialog name
     */
    public String getName() {
        return name;
    }

    /**
     * Gets the complete qualified dialog name in the format appropriate to be used as Map Key.
     *
     * @return the formatted dialog name
     */
    public String getNameForMapKey() {
        return translateNameForMapKey(getQualifiedName());
    }

    /**
     * Gets the complete qualified name of the dialog.
     *
     * @return qualified name of the dialog
     */
    public String getQualifiedName() {
        return nameSpace != null ? nameSpace.getNameSpaceId() + "." + name : name;
    }

    /**
     * Sets the name of the dialog. The name may only contain upper or lowercase letters, numbers, and underscores.
     * There should no punctuation characters or spaces and the name should be a valid JavaScript name.
     *
     * @param name the name of the dialog
     */
    public void setName(String name) {
        this.name = name;
        setHtmlFormName(name);
        log = LogFactory.getLog(getClass() + "." + getQualifiedName());
    }

    /**
     * Gets the name of the dialog created for HTML form.
     *
     * @return the name of HTML form for the dialog
     */
    public String getHtmlFormName() {
        return htmlFormName;
    }

    /**
     * Sets the name of the dialog created for HTML form. The name may only contain
     * upper or lowercase letters, numbers, and underscores.  There should no
     * punctuation characters or spaces and the name should be a valid JavaScript
     * name.  This name may or may not be the same as that specified by the Sparx
     * <code>dialog</code> tag.
     *
     * @param newName dialog name
     */
    public void setHtmlFormName(String newName) {
        htmlFormName = TextUtils.getInstance().xmlTextToJavaIdentifier(newName, false);
    }

    public DialogDebugFlags getDebugFlags() {
        return debugFlags;
    }

    public void setDebugFlags(DialogDebugFlags debugFlags) {
        this.debugFlags = debugFlags;
    }

    public DialogFlags getDialogFlags() {
        return dialogFlags;
    }

    public void setDialogFlags(DialogFlags dialogFlags) {
        this.dialogFlags = dialogFlags;
    }

    /**
     * Gets the cookie name used to store client-persistent field values
     *
     * @return String cookie name
     */
    public String getCookieName() {
        return cookieName == null ? getQualifiedName() : cookieName;
    }

    /**
     * Sets the cookie name used to store client-persistent field values
     *
     * @param name cookie name for this dialog
     */
    public void setCookieName(String name) {
        cookieName = name;
    }

    /**
     * Gets the loop style for the dialog. By default, it is set to append.
     *
     * @return dialog loop style
     */
    public DialogLoopStyle getLoop() {
        return loop;
    }

    /**
     * Specifies whether or not to show the dialog even after the dialog executes.
     * Used to show forms after searches complete.
     *
     * @param loop loop style such as append or prepend
     */
    public void setLoop(DialogLoopStyle loop) {
        this.loop = loop;
    }

    /**
     * Gets the HTML to be inserted between the dialog and its execution content,
     * if the loop is set to append or prepend.
     *
     * @return the HTML to be inserted between the dialog and its execution content
     */
    public String getLoopSeparator() {
        return loop.getLoopSeparator();
    }

    /**
     * Specifies the HTML to be inserted between the dialog and its execution content,
     * if the loop is set to append or prepend.
     *
     * @param loopSeparator HTML to be inserted between the dialog and its execution content
     */

    public void setLoopSeparator(String loopSeparator) {
        loop.setLoopSeparator(loopSeparator);
    }

    /**
     * Checks whether the dialog should be redirected after executing
     * (performing the tasks it's been instructed to perform).
     *
     * @return <code>true</code> if the dialog needs to be redirected after execution;
     *         <code>false</code> otherwise
     */
    public boolean isRedirectAfterExecute() {
        return redirectAfterExecute;
    }

    /**
     * Sets whether or not the dialog should be redirected after executing
     * (performing the tasks it's been instructed to perform).
     *
     * @param redirectAfterExecute <code>true</code> if the dialog needs to be
     *                             redirected after execution; <code>false</code> otherwise
     */
    public void setRedirectAfterExecute(boolean redirectAfterExecute) {
        this.redirectAfterExecute = redirectAfterExecute;
    }

    /**
     * Checks whether or not the dialog heading is to be hidden.
     *
     * @param dc current dialog context for the dialog
     *
     * @return <code>true</code> if the heading should be hidden; <code>false</code> otherwise
     */
    public boolean hideHeading(DialogContext dc) {
        if (dialogFlags.flagIsSet(DialogFlags.HIDE_HEADING_IN_EXEC_MODE) && dc.getDialogState().isInExecuteMode())
            return true;
        else
            return false;
    }

    /**
     * Gets the custom context class associated with the dialog.
     *
     * @return dialog context class
     */
    public Class getDialogContextClass() {
        return dialogContextClass;
    }

    /**
     * Sets a custom class as the context class for the dialog, to be dynamically
     * loaded and instantiated.
     *
     * @param dialogContextClass custom class to be set as the dialog context class
     */
    public void setDialogContextClass(Class dialogContextClass) {
        this.dialogContextClass = dialogContextClass;
    }

    public int getLayoutColumnsCount() {
        return layoutColumnsCount;
    }

    public String getPostExecuteRedirectUrlParamName() {
        return PARAMNAME_DIALOGPREFIX + htmlFormName + PARAMNAME_POST_EXECUTE_REDIRECT;
    }

    /**
     * Gets the name of dialog's state identifier.
     *
     * @return name of dialog's state identifier
     */

    public String getDialogStateIdentifierParamName() {
        return PARAMNAME_DIALOGPREFIX + htmlFormName + PARAMNAME_DIALOG_STATE_ID;
    }

    /**
     * Gets the name of the hidden input field used to keep track of the name of the dialog field that triggered
     * the submission of the form so that the field can be validated immediately.
     */
    public String getDialogValidateTriggerFieldParamName() {
        return PARAMNAME_DIALOGPREFIX + htmlFormName + PARAMNAME_VALIDATE_TRIGGER_FIELD;
    }

    public String getResetContextParamName() {
        return PARAMNAME_DIALOGPREFIX + htmlFormName + PARAMNAME_RESET_CONTEXT;
    }

    /**
     * Gets the name of the Submit button.
     *
     * @return name of the Submit button
     */

    public String getSubmitDataParamName() {
        return PARAMNAME_DIALOGPREFIX + htmlFormName + PARAMNAME_SUBMIT_DATA;
    }

    /**
     * Gets the name of the Cancel button.
     *
     * @return name of the Cancel button
     */
    public String getCancelDataParamName() {
        return PARAMNAME_DIALOGPREFIX + htmlFormName + PARAMNAME_CANCEL_DATA;
    }

    public String getPendDataParamName() {
        return PARAMNAME_DIALOGPREFIX + htmlFormName + PARAMNAME_PEND_DATA;
    }

    public String getValuesRequestAttrName() {
        return "dialog-" + htmlFormName + "-field-values";
    }

    /**
     * Gets a list of dialog fields.
     *
     * @return list of all dialog fields
     */
    public DialogFields getFields() {
        return fields;
    }

    /**
     * Indicates whether or not to retain the HTTP request parameters as dialog fields.
     *
     * @return <code>true</code> if the request parameters are retained in the dialog;
     *         <code>false</code> otherwise
     */
    public boolean retainRequestParams() {
        return dialogFlags.flagIsSet(DialogFlags.RETAIN_ALL_REQUEST_PARAMS) || (retainRequestParams != null);
    }

    /**
     * Gets the retained request parameters as a string array.
     *
     * @return the request parameters that were retained
     */
    public String[] getRetainParams() {
        return retainRequestParams;
    }

    /**
     * Sets the request parameters to be retained for use in multiple invocation
     * of the dialog during more than one request/response cycle.
     *
     * @param value names of request parameters to be retained.  Pass asterist (*) as
     *              the value to retain all request parameters
     */
    public void setRetainParams(String value) {
        if (value.equals("*"))
            dialogFlags.setFlag(DialogFlags.RETAIN_ALL_REQUEST_PARAMS);
        else
            retainRequestParams = TextUtils.getInstance().split(value, ",", true);
    }

    /**
     * Gets the error message to be displayed when multiple executions of the
     * dialog are detected.
     *
     * @return the error message
     */
    public ValueSource getMultipleExecErrorMessage() {
        return multipleExecErrorMessage;
    }

    /**
     * Sets the error message for multiple executions of the dialog.
     */
    public void setMultipleExecErrorMessage(ValueSource multipleExecErrorMessage) {
        this.multipleExecErrorMessage = multipleExecErrorMessage;
    }

    /**
     * Gets the URL for the next action of the dialog after execution. It searches for a next action URL using the
     * following order (and uses the first one found)<p>
     * <ol>
     * <li>The dialog director next actions field. If the director returns "-" as the URL, it means keep checking.</li>
     * <li>The dialog's next action provider delegated class (using Dialog.getNextActionProvider())</li>
     * <li>Active page next action provider delegated class (using dc.NavigationContext().getNextActionProvider)</li>
     * <li>The default url passed in</li>
     * </ol>
     *
     * @param dc         The dialog context for the dialog that just executed
     * @param defaultUrl The URL to use if no specific next actions are provided
     *
     * @return URL string to use for the URL (to send in redirect)
     */
    public String getNextActionUrl(DialogContext dc, String defaultUrl) {
        if (director != null && director.hasNextAction()) {
            String url = director.getDialogNextActionUrl(dc, null);
            if (url != null)
                return url;

            // if the url is null, it means that the director returned the default (NULL) and wants to let the
            // the delegated callers handle it so we'll fall through to the rest of the providers below
        }
        // if this dialog is being executed within a panel editor context, then use the panel'editor's mode URL
        PanelEditorState state = (PanelEditorState) dc.getHttpRequest()
                .getAttribute(PanelEditor.PANEL_EDITOR_REQ_ATTRIBUTE_PREFIX);
        if (state != null) {
            return state.calculateNextModeUrl(dc);
        }

        // see if we are delegating our next action call to another class
        if (nextActionProvider != null)
            return nextActionProvider.getDialogNextActionUrl(dc, defaultUrl);

        // first see if there is page-specific or tree-wide next action provider
        DialogNextActionProvider navNextActionProvider = dc.getNavigationContext().getDialogNextActionProvider();
        if (navNextActionProvider != null)
            return navNextActionProvider.getDialogNextActionUrl(dc, defaultUrl);

        return defaultUrl;
    }

    /**
     * Gets the dialog director object.
     *
     * @return the dialog director object
     */
    public DialogDirector getDirector() {
        return director;
    }

    /**
     * Creates and returns the dialog director. Used mainly for XDM dialog creation.
     *
     * @return dialog director object
     */
    public DialogDirector createDirector() {
        return new DialogDirector();
    }

    /**
     * Sets the director for the dialog.
     *
     * @param value the director to be set for the dialog
     */
    public void addDirector(DialogDirector value) {
        director = value;
        value.setOwner(this);
    }

    /**
     * Gets all the javascript files to be included with this dialog.
     *
     * @return all the client javascript files
     */
    public List getClientJs() {
        return this.clientJavascripts;
    }

    /**
     * Adds a javascript file to be included.
     *
     * @param clientJsFile the javascript file to be included
     */
    public void addClientJs(DialogIncludeJavascriptFile clientJsFile) {
        clientJavascripts.add(clientJsFile);
    }

    /**
     * Gets the package namespace to which this dialog belongs.
     *
     * @return package namespace of the dialog
     */
    public DialogsNameSpace getNameSpace() {
        return nameSpace;
    }

    /**
     * Sets the package namespace for the dialog.
     *
     * @param nameSpace the namespace to be set for the dialog
     */
    public void setNameSpace(DialogsNameSpace nameSpace) {
        this.nameSpace = nameSpace;
    }

    /**
     * Creates a new DialogField object and returns it. Used mainly by XDM to create a dialog field.
     *
     * @return a new dialog field object
     */
    public DialogField createField() {
        return new DialogField();
    }

    /**
     * Adds a dialog field.
     *
     * @param field a dialog field
     */
    public void addField(DialogField field) {
        fields.add(field);
        field.setOwner(this);
    }

    /**
     * Creates a new composite field and returns it. This is used mainly by XDM
     * to instantiate a composite field.
     *
     * @return the newly created composite field
     */
    public CompositeField createComposite() {
        return new CompositeField();
    }

    public SectionField createSection() {
        return new SectionField();
    }

    public void addSection(SectionField field) {
        addField(field);
    }

    /**
     * Adds a composite field to the dialog.
     *
     * @param field the CompositeField object to be added to the dialog
     */
    public void addComposite(CompositeField field) {
        addField(field);
    }

    /**
     * Creates a new separator field. This is used mainly by XDM to instantiate
     * a separator field.
     *
     * @return the newly created separator field
     */
    public SeparatorField createSeparator() {
        return new SeparatorField();
    }

    /**
     * Adds a separator field to the dialog.
     *
     * @param field the separator field to be added to the dialog
     */
    public void addSeparator(SeparatorField field) {
        addField(field);
    }

    /**
     * Creates a new grid field. This is used mainly by XDM to instantiate
     * a grid field.
     *
     * @return the newly created grid field
     */
    public GridField createGrid() {
        return new GridField();
    }

    /**
     * Adds a grid field to the dialog.
     *
     * @param field the grid field to be added to the dialog
     */
    public void addGrid(GridField field) {
        addField(field);
    }

    /**
     * Calls the <code>finalizeContents</code> for each field belonging to the
     * dialog and also calculates the layout of the dialog fields.
     */
    public void finalizeContents() {
        boolean includedUnixCryptJS = false;

        fields.finalizeContents();
        for (int i = 0; i < fields.size(); i++) {
            DialogField field = fields.get(i);
            if (field.getFlags()
                    .flagIsSet(DialogFieldFlags.COLUMN_BREAK_BEFORE | DialogFieldFlags.COLUMN_BREAK_AFTER))
                layoutColumnsCount++;

            if (field.getClientEncryption() != null) {
                ClientDataEncryption encryption = field.getClientEncryption();
                if (encryption.getStyle().getValueIndex() == DataEncryptionStyle.UNIX_CRYPT) {
                    if (!includedUnixCryptJS) {
                        DialogIncludeJavascriptFile js = new DialogIncludeJavascriptFile();
                        js.setHref(new ThemeResourceUrlValueSource("/scripts/javacrypt.js"));
                        addClientJs(js);
                        includedUnixCryptJS = true;
                    }
                }
            }
        }
    }

    /**
     * Called at the end of  XDM processing to create the Dialog object. Currently
     * calls <code>finalizeContents</code>.
     *
     * @param pc          The XDM parsing context
     * @param element     The XML element for the dialog object
     * @param elementName The name of the element
     */
    public void finalizeConstruction(XdmParseContext pc, Object element, String elementName)
            throws DataModelException {
        finalizeContents();
    }

    /**
     * Populates the dialog with field values.  This should be called everytime
     * the dialog is loaded except when it is ready for execution (validated already)
     *
     * @param dc         dialog context
     * @param formatType format for the field
     */
    public void populateValues(DialogContext dc, int formatType) {
        DialogState dialogState = dc.getDialogState();

        for (int i = 0; i < fields.size(); i++) {
            DialogField field = fields.get(i);
            if (field.isAvailable(dc))
                field.populateValue(dc, formatType);
        }

        if (director != null) {
            DialogField field = director.getNextActionsField();
            if (field != null)
                field.populateValue(dc, formatType);
        }

        if (dialogState.isInitialEntry()) {
            if (formatType == DialogField.DISPLAY_FORMAT && haveInitialPopulateForDisplayListeners) {
                for (int i = 0; i < initialPopulateForDisplayListeners.size(); i++)
                    ((DialogInitialPopulateForDisplayListener) initialPopulateForDisplayListeners.get(i))
                            .populateInitialDialogValuesForDisplay(dc);
            }

            if (formatType == DialogField.SUBMIT_FORMAT && haveInitialPopulateForSubmitListeners) {
                for (int i = 0; i < initialPopulateForSubmitListeners.size(); i++)
                    ((DialogInitialPopulateForSubmitListener) initialPopulateForSubmitListeners.get(i))
                            .populateInitialDialogValuesForSubmit(dc);
            }

            if (haveInitialPopulateListeners) {
                for (int i = 0; i < initialPopulateListeners.size(); i++)
                    ((DialogInitialPopulateListener) initialPopulateListeners.get(i))
                            .populateInitialDialogValues(dc, formatType);
            }
        }

        if (formatType == DialogField.DISPLAY_FORMAT && havePopulateForDisplayListeners) {
            for (int i = 0; i < populateForDisplayListeners.size(); i++)
                ((DialogPopulateForDisplayListener) populateForDisplayListeners.get(i))
                        .populateDialogValuesForDisplay(dc);
        }

        if (formatType == DialogField.SUBMIT_FORMAT && havePopulateForSubmitListeners) {
            for (int i = 0; i < populateForSubmitListeners.size(); i++)
                ((DialogPopulateForSubmitListener) populateForSubmitListeners.get(i))
                        .populateDialogValuesForSubmit(dc);
        }

        if (havePopulateListeners) {
            for (int i = 0; i < populateListeners.size(); i++)
                ((DialogPopulateListener) populateListeners.get(i)).populateDialogValues(dc, formatType);
        }

        if (getDialogFlags().flagIsSet(DialogFlags.RETAIN_INITIAL_STATE) && dialogState.isInitialEntry())
            dialogState.saveInitialState(dc);
    }

    /**
     * Checks each field to see if its state needs to be changed or not, usually
     * based on Conditionals.
     * <p/>
     * <b>IMPORTANT</b>: If any changes are made in this class, make sure
     * that they are also reflected in QuerySelectDialog and QueryBuilderDialog classes
     * which extend this class but they overwrite this method and don't make a call
     * to this method.
     *
     * @param dc    dialog context
     * @param stage stage which the dialog is currently in, such as before validation
     *              and after validation)
     */
    public void makeStateChanges(DialogContext dc, int stage) {
        for (int i = 0; i < fields.size(); i++) {
            DialogField field = fields.get(i);
            field.makeStateChanges(dc, stage);
        }
        DialogDirector director = getDirector();
        if (director != null)
            director.makeStateChanges(dc, stage);

        if (stage == DialogContext.STATECALCSTAGE_BEFORE_VALIDATION && haveStateBeforeValidationListeners) {
            for (int i = 0; i < stateBeforeValidationListeners.size(); i++)
                ((DialogStateBeforeValidationListener) stateBeforeValidationListeners.get(i))
                        .makeDialogStateChangesBeforeValidation(dc);
        }

        if (stage == DialogContext.STATECALCSTAGE_AFTER_VALIDATION && haveStateAfterValidationListeners) {
            for (int i = 0; i < stateAfterValidationListeners.size(); i++)
                ((DialogStateAfterValidationListener) stateAfterValidationListeners.get(i))
                        .makeDialogStateChangesChangesAfterValidation(dc);
        }

        if (haveStateListeners) {
            for (int i = 0; i < stateListeners.size(); i++)
                ((DialogStateListener) stateListeners.get(i)).makeDialogStateChanges(dc, stage);
        }
    }

    /**
     * Creates a new <code>DialogExecuteDefaultHandler</code> object. This is
     * used mainly by XDM to instantiate a DialogExecuteHandler object.
     *
     * @return the newly created dialog execute handler object
     */
    public DialogExecuteHandler createOnExecute() {
        return new DialogExecuteDefaultHandler();
    }

    /**
     * Adds a new <code>DialogExecuteHandler</code> object to the list of execute
     * handlers for the dialog. These listeners that implement the
     * <code>DialogExecuteHandler</code> interface will be called at execution time
     * to process custome dialog execute actions.
     *
     * @param handler execution handler object to be added for the dialog
     */
    public void addOnExecute(DialogExecuteHandler handler) {
        executeHandlers.add(handler);
        addListener(handler); // see if there are any other interfaces implemented by this handler
    }

    /**
     * Gets all the dialog execute handlers associated with the dialog.
     *
     * @return all the execute handlers for the dialog
     */
    public DialogExecuteHandlers getExecuteHandlers() {
        return executeHandlers;
    }

    /**
     * Ascertains whether or not this dialog should just auto-execute (not show
     * any input) by default.
     *
     * @return <code>true</code> if auto executing by default
     */
    public boolean isAutoExecByDefault() {
        return false;
    }

    /**
     * If this dialog is not auto-exec by default, then does the current state of the dialog (using the context)
     * indicate that it should be auto-executed.
     *
     * @param dc                    The current dialog context
     * @param autoExecReqParamValue The value of the _d_exec request parameter
     *
     * @return <code>true</code> if the current state indicates auto-execution; <code>false</code> otherwise
     */
    public boolean isAutoExec(DialogContext dc, String autoExecReqParamValue) {
        return autoExecReqParamValue != null && !autoExecReqParamValue.equals("no");
    }

    /**
     * Executes the actions of the dialog.
     *
     * @param writer stream for dialog execution output
     * @param dc     dialog context
     */
    public void execute(Writer writer, DialogContext dc) throws IOException, DialogExecuteException {
        if (dc.executeStageHandled())
            return;

        try {
            if (executeHandlers.size() > 0)
                executeHandlers.handleDialogExecute(writer, dc);
            else
                dc.renderDebugPanels(writer);
            getDialogState(dc).setAlreadyExecuted();
            handlePostExecute(writer, dc);
        } catch (DialogExecuteException e) {
            handlePostExecuteException(writer, dc, null, e);
        }
    }

    /**
     * Gets the next action provider of the dialog. The next action represents
     * the action to be performed after dialog execution.
     *
     * @return the next action provider for the dialog
     */
    public DialogNextActionProvider getNextActionProvider() {
        return nextActionProvider;
    }

    /**
     * Sets the next action provider for the dialog.  The next action represents
     * the action to be performed after dialog execution.
     *
     * @param nextActionProvider the next action provider for the dialog
     */
    public void addNextActionProvider(DialogNextActionProvider nextActionProvider) {
        this.nextActionProvider = nextActionProvider;
    }

    /**
     * Handles any post execution actions. Currently, it sets a flag to indicate
     * that the execution has been handled and then performs a URL redirection.
     *
     * @param writer Writer object related to the response buffer
     * @param dc     current dialog context
     */
    public void handlePostExecute(Writer writer, DialogContext dc) throws IOException {
        if (!getDialogFlags().flagIsSet(DialogFlags.DISABLE_ACTIVITY_ANNOUNCEMENT))
            dc.getParentActivity().broadcastChildActivity(dc);

        dc.setExecuteStageHandled(true);
        if (getDialogFlags().flagIsSet(DialogFlags.CLOSE_PAGE_AFTER_EXECUTE)) {
            writer.write("<script>\n" + "<!--\n" + "    window.close();\n" + "-->\n" + "</script>");
            return;
        }

        dc.performDefaultRedirect(writer, null);
    }

    /**
     * Handles any post execution actions. Currently, it sets a flag to indicate
     * that the execution has been handled and then performs a URL redirection.
     *
     * @param writer   Writer object related to the response buffer
     * @param dc       current dialog context
     * @param redirect the URL to redirect to
     */
    public void handlePostExecute(Writer writer, DialogContext dc, String redirect) throws IOException {
        if (!getDialogFlags().flagIsSet(DialogFlags.DISABLE_ACTIVITY_ANNOUNCEMENT))
            dc.getParentActivity().broadcastChildActivity(dc);

        dc.setExecuteStageHandled(true);
        if (getDialogFlags().flagIsSet(DialogFlags.CLOSE_PAGE_AFTER_EXECUTE)) {
            writer.write("<script>\n" + "<!--\n" + "    window.close();\n" + "-->\n" + "</script>");
            return;
        }
        dc.performDefaultRedirect(writer, redirect);
    }

    /**
     * Logs the exeception and writes it to the Writer.
     *
     * @param writer  Writer object related to the response buffer
     * @param dc      current dialog context
     * @param message custom exception message
     * @param e       the exception object
     */
    public void handlePostExecuteException(Writer writer, DialogContext dc, String message, Exception e)
            throws DialogExecuteException, IOException {
        dc.setExecuteStageHandled(true);
        getLog().error(message, e);
        dc.setRedirectDisabled(true);
        if (e instanceof DialogExecuteException)
            throw (DialogExecuteException) e;
        else
            throw new DialogExecuteException(e);
    }

    /**
     * Gets the current state of the dialog.
     *
     * @param dc current dialog context
     *
     * @return the current state of the dialog
     */
    public DialogState getDialogState(DialogContext dc) {
        HttpSession session = dc.getHttpRequest().getSession();
        Map dialogStates = (Map) session.getAttribute(ATTRNAME_DIALOG_STATES);
        if (dialogStates == null) {
            Integer maxEntriesAttr = (Integer) session.getAttribute(ATTRNAME_DIALOG_STATES_MAX_ENTRIES);
            dialogStates = new LRUMap(
                    maxEntriesAttr != null ? maxEntriesAttr.intValue() : DIALOG_STATES_LRU_MAP_DEFAULT_MAX_SIZE);
            session.setAttribute(ATTRNAME_DIALOG_STATES, dialogStates);
        }

        DialogState result = null;
        String existingStateId = dc.getRequest().getParameter(getDialogStateIdentifierParamName());
        if (existingStateId != null)
            result = (DialogState) dialogStates.get(existingStateId);

        if (result == null) {
            result = constructDialogState();
            result.initialize(dc);
            dialogStates.put(result.getIdentifier(), result);
        }

        return result;
    }

    /**
     * Creates a new dialog state object.
     *
     * @return newly created dialog state object
     */
    public DialogState constructDialogState() {
        return new DialogState();
    }

    /**
     * Create dialog context for a dialog. If a custom dialog context class is
     * defined, the custom class will be instantiated, else a default
     * <code>DialogContext</code> object will be returned.
     *
     * @param nc   current navigation context for the dialog
     * @param skin dialog skin
     *
     * @return DialogContext newly create dialog context object
     */
    public DialogContext createContext(NavigationContext nc, DialogSkin skin) {
        DialogContext dc = null;
        try {
            dc = (DialogContext) dialogContextClass.newInstance();
        } catch (Exception e) {
            getLog().error(e);
            dc = new DialogContext();
        }
        dc.initialize(nc, this, skin);
        return dc;
    }

    /**
     * Initially populates the dialog with values in display format and then
     * calculates the state of the dialog.  If the dialog is in execute mode,
     * the values are then formatted for submittal.
     *
     * @param dc current dialog context
     */
    public void prepareContext(DialogContext dc) {
        populateValues(dc, DialogField.DISPLAY_FORMAT);
        dc.calcState();
        // validated and the dialog is ready for execution
        if (dc.getDialogState().isInExecuteMode()) {
            dc.persistValuesToBrowser();
            populateValues(dc, DialogField.SUBMIT_FORMAT);
        }
    }

    /**
     * Creates and writes the HTML for the dialog
     *
     * @param writer                 stream to write the dialog HTML to
     * @param dc                     dialog context
     * @param contextPreparedAlready flag to indicate whether or not the
     *                               context has been prepared
     */
    public void render(Writer writer, DialogContext dc, boolean contextPreparedAlready)
            throws IOException, DialogExecuteException {
        if (!contextPreparedAlready)
            prepareContext(dc);

        if (dc.getDialogState().isInExecuteMode()) {
            boolean debug = debugFlags.flagIsSet(DialogDebugFlags.SHOW_FIELD_DATA);
            if (debug)
                dc.setRedirectDisabled(true);

            switch (loop.getValueIndex()) {
            case DialogLoopStyle.NONE:
                if (debug)
                    dc.renderDebugPanels(writer);
                else
                    execute(writer, dc);
                break;

            case DialogLoopStyle.APPEND:
                if (debug)
                    dc.renderDebugPanels(writer);
                else
                    execute(writer, dc);
                writer.write(loop.getLoopSeparator());
                dc.getSkin().renderHtml(writer, dc);
                break;

            case DialogLoopStyle.PREPEND:
                dc.getSkin().renderHtml(writer, dc);
                writer.write(loop.getLoopSeparator());
                if (debug)
                    dc.renderDebugPanels(writer);
                else
                    execute(writer, dc);
                break;
            }
        } else {
            dc.getSkin().renderHtml(writer, dc);
        }

        renderViewSource(writer, dc.getNavigationContext());
    }

    /**
     * Creates and writes the HTML for the dialog using a dialog theme.
     *
     * @param writer stream to write the HTML
     * @param dc     current dialog context
     * @param theme  dialog theme
     */
    public void render(Writer writer, DialogContext dc, Theme theme, int flags) throws IOException {
        render(writer, dc.getNavigationContext(), theme, flags);
    }

    /**
     * Creates and writes the HTML for the dialog using a dialog theme.
     *
     * @param writer stream to write the HTML
     * @param nc     current navigation context for the dialog
     * @param theme  dialog theme
     *
     * @throws IOException when an error occurs while writing to HTML stream
     */
    public void render(Writer writer, NavigationContext nc, Theme theme, int flags) throws IOException {
        DialogContext dc = createContext(nc, theme.getDefaultDialogSkin());
        try {
            render(writer, dc, false);
        } catch (DialogExecuteException e) {
            log.error("Dialog execute error", e);
            throw new NestableRuntimeException(e);
        }
    }

    /**
     * Generates a custom java bean class file representing the context of the dialog.
     *
     * @param destDir   the destination directory to write the bean class
     * @param pkgPrefix the package to which the bean class belongs
     *
     * @return the bean class file
     *
     * @throws IOException when an error occurs during file or html stream I/O
     */
    public File generateDialogContextBean(File destDir, String pkgPrefix) throws IOException {
        StringBuffer importsCode = new StringBuffer();
        StringBuffer membersCode = new StringBuffer();

        Set modulesImported = new HashSet();

        DialogFields fields = getFields();
        for (int i = 0; i < fields.size(); i++) {
            DialogField field = fields.get(i);
            DialogContextBeanMemberInfo mi = field.getDialogContextBeanMemberInfo();
            if (mi != null) {
                String[] importModules = mi.getImportModules();
                if (importModules != null) {
                    for (int m = 0; m < importModules.length; m++) {
                        String module = importModules[m];
                        if (!modulesImported.contains(module)) {
                            modulesImported.add(module);
                            importsCode.append("import " + module + ";\n");
                        }
                    }
                }
                membersCode.append(mi.getCode());
                membersCode.append("\n");
            }
            if (field instanceof GridField || field instanceof CompositeField || field instanceof SectionField)
                continue;
            DialogFields childrenFields = field.getChildren();
            if (childrenFields != null && childrenFields.size() > 0) {
                for (int j = 0; j < childrenFields.size(); j++) {
                    DialogField child = childrenFields.get(j);
                    DialogContextBeanMemberInfo miChild = child.getDialogContextBeanMemberInfo();
                    if (mi != null) {
                        String[] importModules = miChild.getImportModules();
                        if (importModules != null) {
                            for (int m = 0; m < importModules.length; m++) {
                                String module = importModules[m];
                                if (!modulesImported.contains(module)) {
                                    modulesImported.add(module);
                                    importsCode.append("import " + module + ";\n");
                                }
                            }
                        }
                        membersCode.append(miChild.getCode());
                        membersCode.append("\n");
                    }
                }
            }
        }

        TextUtils textUtils = TextUtils.getInstance();
        String className = textUtils.xmlTextToJavaIdentifier(getName(), true);

        String packageName = pkgPrefix + "." + textUtils.xmlTextToJavaPackageName(getNameSpace().getNameSpaceId());

        StringBuffer code = new StringBuffer();
        code.append(
                "\n/* this file is generated by com.netspective.sparx.form.Dialog.getSubclassedDialogContextCode(), do not modify (you can extend it, though) */\n\n");
        code.append("package " + packageName + ";\n\n");
        if (importsCode.length() > 0)
            code.append(importsCode.toString());
        code.append("import com.netspective.sparx.form.*;\n");
        code.append("import com.netspective.sparx.form.field.*;\n");
        code.append("import com.netspective.sparx.form.field.type.*;\n\n");
        code.append("public class " + className + "Context\n");
        code.append("{\n");
        code.append("    public static final String DIALOG_ID = \"" + getQualifiedName() + "\";\n");
        code.append("    private DialogContext dialogContext;\n");
        code.append("    private DialogFieldStates fieldStates;\n\n");
        code.append("    public " + className + "Context(DialogContext dc)\n");
        code.append("    {\n");
        code.append("        this.dialogContext = dc;\n");
        code.append("        this.fieldStates = dc.getFieldStates();\n");
        code.append("    }\n\n");
        code.append("    public DialogContext getDialogContext() { return dialogContext; }\n\n");
        code.append(membersCode.toString());
        code.append("}\n");

        File javaFilePath = new File(destDir, packageName.replace('.', '/'));
        javaFilePath.mkdirs();

        File javaFile = new File(javaFilePath, className + "Context.java");

        Writer writer = new java.io.FileWriter(javaFile);
        writer.write(code.toString());
        writer.close();

        return javaFile;
    }

    /**
     * Indicates whether or not the dialog needs validation.
     *
     * @param dc dialog context
     *
     * @return <code>true</code> if the dialog needs validation; <code>false</code> otherwise
     */
    public boolean needsValidation(DialogContext dc) {
        int validateFieldsCount = 0;

        for (int i = 0; i < fields.size(); i++) {
            DialogField field = fields.get(i);
            if (field.isAvailable(dc) && field.needsValidation(dc))
                validateFieldsCount++;
        }

        return validateFieldsCount > 0 ? true : false;
    }

    /**
     * Checks to see if the dialog submission was triggered for validation of a single field.
     *
     * @param dc current dialog context
     *
     * @return NULL if the dialog doesn't allow the event or if the triggering field name is empty
     *
     * @see #getDialogValidateTriggerFieldParamName()
     */
    public String checkFieldValidationTrigger(DialogContext dc) {
        // check to see which field initiated the submission
        String validateFieldName = dc.getHttpRequest().getParameter(getDialogValidateTriggerFieldParamName());
        if (validateFieldName != null && validateFieldName.length() > 0)
            return validateFieldName;
        return null;
    }

    /**
     * Checks whether or not the dailog is valid for execution.
     *
     * @param dc dialog context
     *
     * @return <code>true</code> if the dialog is valid; <code>false</code> otherwise.
     */
    public boolean isValid(DialogContext dc) {
        DialogValidationContext dvc = dc.getValidationContext();
        int valStage = dvc.getValidationStage();
        if (valStage == DialogValidationContext.VALSTAGE_PERFORMED_SUCCEEDED
                || valStage == DialogValidationContext.VALSTAGE_IGNORE)
            return true;
        if (valStage == DialogValidationContext.VALSTAGE_PERFORMED_FAILED)
            return false;

        for (int i = 0; i < fields.size(); i++) {
            DialogField field = fields.get(i);
            if ((field.isAvailable(dc) && !field.isInputHidden(dc)))
                field.validate(dvc);
        }

        if (haveValidationListeners) {
            for (int i = 0; i < validationListeners.size(); i++)
                ((DialogValidateListener) validationListeners.get(i)).validateDialog(dvc);
        }

        boolean isValid = dvc.isValid();
        dvc.setValidationStage(isValid ? DialogValidationContext.VALSTAGE_PERFORMED_SUCCEEDED
                : DialogValidationContext.VALSTAGE_PERFORMED_FAILED);
        return isValid;
    }

    /**
     * Formats and displays the error message in HTML format.
     *
     * @param writer html stream
     * @param e      error message
     */
    protected void renderFormattedExceptionMessage(Writer writer, Exception e) throws IOException {
        writer.write("<div class='textbox'>" + Main.getAntVersion() + "<p><pre>");
        writer.write(TextUtils.getInstance().getStackTrace(e));
        writer.write("</pre>");
    }

    /**
     * Attaches a custom class to manage dialog events such as validation,
     * execution and so on.  Creates a placeholder for the dynamic listener class.
     *
     * @return a placeholder for the dialog listener
     */
    public DialogListener createListener() {
        return new DialogListenerPlaceholder();
    }

    /**
     * Registers a listener for the dialog.  Listeners are used to define custom actions
     * for different stages that the dialog goes through.
     *
     * @param listeners list of listeners to which the listener is being registered
     * @param listener  the listener to be registered
     */
    private void registerListener(List listeners, DialogListener listener) {
        if (!listeners.contains(listener))
            listeners.add(listener);
    }

    /**
     * Adds a listener for the dialog.  Listeners are used to define custom actions
     * for different stages that the dialog goes through.  There are several listener
     * interfaces available for a dialog:
     * <ul>
     * <li>DialogInitialPopulateForDisplayListener: processed during initial population of the dialog and the format type is set to display mode </li>
     * <li>DialogInitialPopulateForSubmitListener: processed during initial population of the dialog  and the format type is set to submit mode </li>
     * <li>DialogInitialPopulateListener</li>
     * <li>DialogPopulateForDisplayListener: processed during subsequent population of the dialog and the format type is set to display mode</li>
     * <li>DialogPopulateForSubmitListener: porcessed during subsequent population of the dialog and the format type is set to submit mode</li>
     * <li>DialogPopulateListener</li>
     * <li>DialogStateAfterValidationListener</li>
     * <li>DialogStateBeforeValidationListener</li>
     * <li>DialogStateListener</li>
     * <li>DialogValidateListener</li>
     * <li>DialogExecuteHandler: </li>
     * </ul>
     * Implementing listeners classes can be registered to the dialog using the
     * <code>&lt;listener&gt;</code> tag.
     *
     * @param listener the listener to be added for the dialog
     */
    public void addListener(DialogListener listener) {
        if (listener instanceof DialogInitialPopulateForDisplayListener) {
            haveInitialPopulateForDisplayListeners = true;
            registerListener(initialPopulateForDisplayListeners, listener);
        }

        if (listener instanceof DialogInitialPopulateForSubmitListener) {
            haveInitialPopulateForSubmitListeners = true;
            registerListener(initialPopulateForSubmitListeners, listener);
        }

        if (listener instanceof DialogInitialPopulateListener) {
            haveInitialPopulateListeners = true;
            registerListener(initialPopulateListeners, listener);
        }

        if (listener instanceof DialogPopulateForDisplayListener) {
            havePopulateForDisplayListeners = true;
            registerListener(populateForDisplayListeners, listener);
        }

        if (listener instanceof DialogPopulateForSubmitListener) {
            havePopulateForSubmitListeners = true;
            registerListener(populateForSubmitListeners, listener);
        }

        if (listener instanceof DialogPopulateListener) {
            havePopulateListeners = true;
            registerListener(populateListeners, listener);
        }

        if (listener instanceof DialogStateAfterValidationListener) {
            haveStateAfterValidationListeners = true;
            registerListener(stateAfterValidationListeners, listener);
        }

        if (listener instanceof DialogStateBeforeValidationListener) {
            haveStateBeforeValidationListeners = true;
            registerListener(stateBeforeValidationListeners, listener);
        }

        if (listener instanceof DialogStateListener) {
            haveStateListeners = true;
            registerListener(stateListeners, listener);
        }

        if (listener instanceof DialogValidateListener) {
            haveValidationListeners = true;
            registerListener(validationListeners, listener);
        }

        if (listener instanceof DialogExecuteHandler)
            executeHandlers.add((DialogExecuteHandler) listener);
    }

    /**
     * Gets a list of all the initial dialog population listeners for display mode.
     *
     * @return all the initial dialog population listeners, for display mode
     */
    public List getInitialPopulateForDisplayListeners() {
        return initialPopulateForDisplayListeners;
    }

    /**
     * Gets a list of all the initial dialog population for submit mode.
     *
     * @return all the initial dialog population, for submit mode
     */
    public List getInitialPopulateForSubmitListeners() {
        return initialPopulateForSubmitListeners;
    }

    /**
     * Gets all the initial population listeners for the dialog.
     *
     * @return all the initial population listeners
     */
    public List getInitialPopulateListeners() {
        return initialPopulateListeners;
    }

    /**
     * Gets all the subsequent population listeners for display mode.
     *
     * @return all the population listeners, for display mode
     */
    public List getPopulateForDisplayListeners() {
        return populateForDisplayListeners;
    }

    /**
     * Gets all the subsequent population listeners for submit mode.
     *
     * @return all the population listeners, for submit mode
     */
    public List getPopulateForSubmitListeners() {
        return populateForSubmitListeners;
    }

    /**
     * Gets all the dialog population listeners.
     *
     * @return all the population listeners for the dialog
     */
    public List getPopulateListeners() {
        return populateListeners;
    }

    /**
     * Gets all the listeners for the dialog after validation stage.
     *
     * @return all the listeners for the dialog, after validation stage
     */
    public List getStateAfterValidationListeners() {
        return stateAfterValidationListeners;
    }

    /**
     * Gets all the listeners for the dialog before validation stage.
     *
     * @return all the listeners for the dialog, before validation stage
     */
    public List getStateBeforeValidationListeners() {
        return stateBeforeValidationListeners;
    }

    /**
     * Gets all the dialog state listeners.
     *
     * @return all the state listeners for the dialog
     */
    public List getStateListeners() {
        return stateListeners;
    }

    /**
     * Gets all the dialog validation listeners.
     *
     * @return all the validation listeners for the dialog
     */
    public List getValidationListeners() {
        return validationListeners;
    }
}