org.andromda.timetracker.web.timecardsearch.SearchController.java Source code

Java tutorial

Introduction

Here is the source code for org.andromda.timetracker.web.timecardsearch.SearchController.java

Source

// license-header java merge-point
// Generated by andromda-jsf cartridge (controllers\Controller.java.vsl) DO NOT EDIT!
package org.andromda.timetracker.web.timecardsearch;

import java.io.Serializable;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import javax.faces.application.FacesMessage;
import javax.faces.component.UIComponent;
import javax.faces.component.UIForm;
import javax.faces.component.UIInput;
import javax.faces.component.ValueHolder;
import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;
import javax.faces.event.FacesEvent;
import javax.faces.event.ValueChangeEvent;
import javax.faces.validator.ValidatorException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.andromda.presentation.gui.AdfFacesContextWrapper;
import org.andromda.presentation.gui.FormPopulator;
import org.andromda.presentation.gui.JsfUtils;
import org.andromda.presentation.gui.Messages;
import org.andromda.presentation.gui.PatternMatchingExceptionHandler;
import org.andromda.timetracker.ServiceLocator;
import org.andromda.timetracker.service.TimeTrackingService;
import org.andromda.timetracker.service.UserService;
import org.andromda.timetracker.web.timecarddetails.TimecardController;
import org.apache.commons.beanutils.PropertyUtils;
import org.apache.commons.lang.exception.ExceptionUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.myfaces.trinidad.component.UIXIterator;
import org.apache.myfaces.trinidad.context.RequestContext;
import org.apache.myfaces.trinidad.util.ComponentUtils;

/**
 * TODO: Model Documentation for org.andromda.timetracker.web.timecardsearch.SearchController
 */
public abstract class SearchController implements Serializable {
    private static final long serialVersionUID = 1L;

    private static final Log logger = LogFactory.getLog(SearchController.class);

    /**
     * TODO: Model Documentation for
     * org.andromda.timetracker.web.timecardsearch.SearchController.populateSearchScreen
     * @param form
     * @throws Throwable
     */
    public abstract void populateSearchScreen(PopulateSearchScreenForm form) throws Throwable;

    /**
     * TODO: Model Documentation for
     * org.andromda.timetracker.web.timecardsearch.SearchController.initializeTimecardId
     * @param form
     * @throws Throwable
     */
    public abstract void initializeTimecardId(InitializeTimecardIdForm form) throws Throwable;

    /**
     * Resets all the "isSet" flags on the forms to false.
     */
    protected void resetFormSetFlags() {
        // Resets all the "isSet" flags on the forms to false.
        this.getSearchTimecardsSearchForm().resetIsSetFlags();
        this.getSearchTimecardsDetailsForm().resetIsSetFlags();
        this.getSearchTimecardsForm().resetIsSetFlags();
    }

    /**
     * Retrieves the {@link SearchTimecardsSearchFormImpl} form instance (normally you wont't
     * need to call this method explicitly, however this is here for times when you need to access the
     * <em>searchTimecardsSearchTimecardsSearchForm</em> instance outside of its assigned controller operation).
     * @return SearchTimecardsSearchFormImpl
     */
    protected SearchTimecardsSearchFormImpl getSearchTimecardsSearchForm() {
        // - we do this in the case a button that submitted the form was set to immediate (this should be removed
        //   when we found a better way to handle this).
        final UIForm uiForm = this.findForm(this.getContext().getViewRoot(),
                "searchTimecardsSearchTimecardsSearchForm");
        this.populateComponentInputs(uiForm);
        return (SearchTimecardsSearchFormImpl) this.resolveVariable("searchTimecardsSearchTimecardsSearchForm");
    }

    /**
     * TODO: Model Documentation for org.andromda.timetracker.web.timecardsearch.search
     * This method is called when 'search' is triggered in the view 'Search Timecards'.
     * It can be safely overridden in descendant classes.
    SearchTimecardsSearchFormImpl)
     * @param form
     */
    protected void _searchTimecards_search(SearchTimecardsSearchFormImpl form) {
        //this method can be overridden
    }

    /**
     * @return searchTimecardsSearch
     */
    public String searchTimecardsSearch() {
        return searchTimecardsSearch((FacesEvent) null);
    }

    /**
     * @param event
     */
    public void searchTimecardsSearch(final ActionEvent event) {
        this.searchTimecardsSearch((FacesEvent) event);
    }

    /**
     * @param event
     */
    public void searchTimecardsSearch(final ValueChangeEvent event) {
        this.searchTimecardsSearch((FacesEvent) event);
    }

    /**
     * @param event
     * @return searchTimecardsSearch
     */
    @SuppressWarnings({ "unchecked", "rawtypes" })
    public String searchTimecardsSearch(final FacesEvent event) {
        String forward = null;
        final Object currentForm = this.resolveVariable("form");
        try {
            final SearchTimecardsSearchFormImpl form = this.getSearchTimecardsSearchForm();
            form.setEvent(event);
            this.setForm("form", form, true);
            // - pass any properties from the previous form along
            FormPopulator.populateForm(currentForm, form, false);
            // - populate the form with any event attributes that may match
            // IMPORTANT: it isn't possible to automatically populate any property named "id" since that
            // is a reserved name in JSF (the id of a component), therefore we have to unfortunately ignore any available "id" attribute
            FormPopulator.populateFormFromPropertyMap(form, form.getDateTimeFormatters(),
                    (Map) this.getRequestAttribute(ACTION_EVENT_ATTRIBUTES), new String[] { "id" });
            if (event != null) {
                final Map eventProperties = new HashMap();
                eventProperties.put(event.getComponent().getId(), event.getSource());
                FormPopulator.populateFormFromPropertyMapAssignableTypesOnly(form, null, eventProperties);
                FormPopulator.populateFormFromPropertyMap(form, form.getDateTimeFormatters(),
                        event.getComponent().getAttributes(), new String[] { "id" });
            }
            // - populate the form with any request attributes that may match
            FormPopulator.populateFormFromRequestAttributes(form, form.getDateTimeFormatters(), false, true);
            // - populate the form with any request parameters that may match
            FormPopulator.populateFormFromPropertyMap(form, form.getDateTimeFormatters(),
                    this.getContext().getExternalContext().getRequestParameterMap());
            //trigger method execution
            _searchTimecards_search(form);

            forward = _populateSearchScreen(form);
            if ("search-timecards-search-timecards".equals(forward)) {
                forward = null; //the destination form is the same, stay on the current view
            }
            final FacesMessage.Severity messageSeverity = this.getMaximumMessageSeverity();
            if (messageSeverity != null
                    && FacesMessage.SEVERITY_ERROR.getOrdinal() <= messageSeverity.getOrdinal()) {
                // - copy any messages to the 'currentForm'
                PropertyUtils.setProperty(currentForm, "jsfMessages",
                        PropertyUtils.getProperty(form, "jsfMessages"));
                this.setForm("form", currentForm, false);
            }
            if (event != null) {
                SearchTimecardsViewPopulator.populateFormAndViewVariables(this.getContext(), form);
            }
        } catch (final Throwable throwable) {
            this.setForm("form", currentForm, false);
            // - set the forward to null so that we stay on the current view
            forward = null;
            try {
                // - the exception is re-thrown by the exception handler and handled by the catch below if it can't get a messageKey
                //   (no reason to check for presence of messageKey)
                this.addErrorMessage(
                        Messages.get(PatternMatchingExceptionHandler.instance().handleException(throwable),
                                PatternMatchingExceptionHandler.instance().getMessageArguments(throwable)));
            } catch (Throwable exception) {
                logger.error(exception.getMessage(), exception);
                this.addExceptionMessage(exception);
            }
        }
        return forward;
    }

    /**
     * TODO: Model Documentation for org.andromda.timetracker.web.timecardsearch.Populate Search
     * Screen
     * @param form
     * @return forward
     * @throws Throwable
     */
    protected String _populateSearchScreen(final SearchTimecardsSearchFormImpl form) throws Throwable {
        String forward = null;
        populateSearchScreen(form);
        forward = "search-timecards-search-timecards";

        //update the viewRoot
        final UIComponent viewRoot = FacesContext.getCurrentInstance().getViewRoot();
        final RequestContext requestContext = RequestContext.getCurrentInstance();
        updateTableValue(requestContext, viewRoot, "timecardSummaries", form.getTimecardSummaries());

        return forward;
    }

    /**
     * Retrieves the {@link SearchTimecardsDetailsFormImpl} form instance (normally you wont't
     * need to call this method explicitly, however this is here for times when you need to access the
     * <em>searchTimecardsSearchTimecardsDetailsForm</em> instance outside of its assigned controller operation).
     * @return SearchTimecardsDetailsFormImpl
     */
    protected SearchTimecardsDetailsFormImpl getSearchTimecardsDetailsForm() {
        // - we do this in the case a button that submitted the form was set to immediate (this should be removed
        //   when we found a better way to handle this).
        final UIForm uiForm = this.findForm(this.getContext().getViewRoot(),
                "searchTimecardsSearchTimecardsDetailsForm");
        this.populateComponentInputs(uiForm);
        return (SearchTimecardsDetailsFormImpl) this.resolveVariable("searchTimecardsSearchTimecardsDetailsForm");
    }

    /**
     * TODO: Model Documentation for org.andromda.timetracker.web.timecardsearch.details
     * This method is called when 'details' is triggered in the view 'Search Timecards'.
     * It can be safely overridden in descendant classes.
    SearchTimecardsDetailsFormImpl)
     * @param form
     */
    protected void _searchTimecards_details(SearchTimecardsDetailsFormImpl form) {
        //this method can be overridden
    }

    /**
     * @return searchTimecardsDetails
     */
    public String searchTimecardsDetails() {
        return searchTimecardsDetails((FacesEvent) null);
    }

    /**
     * @param event
     */
    public void searchTimecardsDetails(final ActionEvent event) {
        this.searchTimecardsDetails((FacesEvent) event);
    }

    /**
     * @param event
     */
    public void searchTimecardsDetails(final ValueChangeEvent event) {
        this.searchTimecardsDetails((FacesEvent) event);
    }

    /**
     * @param event
     * @return searchTimecardsDetails
     */
    @SuppressWarnings({ "unchecked", "rawtypes" })
    public String searchTimecardsDetails(final FacesEvent event) {
        String forward = null;
        final Object currentForm = this.resolveVariable("form");
        try {
            final SearchTimecardsDetailsFormImpl form = this.getSearchTimecardsDetailsForm();
            form.setEvent(event);
            this.setForm("form", form, true);
            // - pass any properties from the previous form along
            FormPopulator.populateForm(currentForm, form, false);
            // - populate the form with any event attributes that may match
            // IMPORTANT: it isn't possible to automatically populate any property named "id" since that
            // is a reserved name in JSF (the id of a component), therefore we have to unfortunately ignore any available "id" attribute
            FormPopulator.populateFormFromPropertyMap(form, form.getDateTimeFormatters(),
                    (Map) this.getRequestAttribute(ACTION_EVENT_ATTRIBUTES), new String[] { "id" });
            if (event != null) {
                final Map eventProperties = new HashMap();
                eventProperties.put(event.getComponent().getId(), event.getSource());
                FormPopulator.populateFormFromPropertyMapAssignableTypesOnly(form, null, eventProperties);
                FormPopulator.populateFormFromPropertyMap(form, form.getDateTimeFormatters(),
                        event.getComponent().getAttributes(), new String[] { "id" });
            }
            // - populate the form with any request attributes that may match
            FormPopulator.populateFormFromRequestAttributes(form, form.getDateTimeFormatters(), false, true);
            // - populate the form with any request parameters that may match
            FormPopulator.populateFormFromPropertyMap(form, form.getDateTimeFormatters(),
                    this.getContext().getExternalContext().getRequestParameterMap());
            //trigger method execution
            _searchTimecards_details(form);

            forward = _initializeTimecardId(form);
            if ("search-timecards-search-timecards".equals(forward)) {
                forward = null; //the destination form is the same, stay on the current view
            }
            final FacesMessage.Severity messageSeverity = this.getMaximumMessageSeverity();
            if (messageSeverity != null
                    && FacesMessage.SEVERITY_ERROR.getOrdinal() <= messageSeverity.getOrdinal()) {
                // - copy any messages to the 'currentForm'
                PropertyUtils.setProperty(currentForm, "jsfMessages",
                        PropertyUtils.getProperty(form, "jsfMessages"));
                this.setForm("form", currentForm, false);
            }
            if (event != null) {
                SearchTimecardsViewPopulator.populateFormAndViewVariables(this.getContext(), form);
            }
        } catch (final Throwable throwable) {
            this.setForm("form", currentForm, false);
            // - set the forward to null so that we stay on the current view
            forward = null;
            try {
                // - the exception is re-thrown by the exception handler and handled by the catch below if it can't get a messageKey
                //   (no reason to check for presence of messageKey)
                this.addErrorMessage(
                        Messages.get(PatternMatchingExceptionHandler.instance().handleException(throwable),
                                PatternMatchingExceptionHandler.instance().getMessageArguments(throwable)));
            } catch (Throwable exception) {
                logger.error(exception.getMessage(), exception);
                this.addExceptionMessage(exception);
            }
        }
        return forward;
    }

    /**
     * TODO: Model Documentation for org.andromda.timetracker.web.timecardsearch.Initialize Timecard
     * Id
     * @param form
     * @return forward
     * @throws Throwable
     */
    protected String _initializeTimecardId(final SearchTimecardsDetailsFormImpl form) throws Throwable {
        String forward = null;
        initializeTimecardId(form);
        forward = ((TimecardController) this.resolveVariable("timecardController")).timecardDetails();
        return forward;
    }

    /**
     * Retrieves the {@link SearchTimecardsFormImpl} form instance (normally you wont't
     * need to call this method explicitly, however this is here for times when you need to access the
     * <em>searchTimecardsSearchTimecardsForm</em> instance outside of its assigned controller operation).
     * @return SearchTimecardsFormImpl
     */
    protected SearchTimecardsFormImpl getSearchTimecardsForm() {
        // - we do this in the case a button that submitted the form was set to immediate (this should be removed
        //   when we found a better way to handle this).
        final UIForm uiForm = this.findForm(this.getContext().getViewRoot(), "searchTimecardsSearchTimecardsForm");
        this.populateComponentInputs(uiForm);
        return (SearchTimecardsFormImpl) this.resolveVariable("searchTimecardsSearchTimecardsForm");
    }

    /**
     * This method is called when the use case 'Search Timecards' starts.
     * It can be safely overridden in descendant classes.
    SearchTimecardsFormImpl)
     * @param form
     */
    protected void _searchTimecards_started(SearchTimecardsFormImpl form) {
        //this method can be overridden
    }

    /**
     * @return searchTimecards
     */
    public String searchTimecards() {
        return searchTimecards((FacesEvent) null);
    }

    /**
     * @param event
     */
    public void searchTimecards(final ActionEvent event) {
        this.searchTimecards((FacesEvent) event);
    }

    /**
     * @param event
     */
    public void searchTimecards(final ValueChangeEvent event) {
        this.searchTimecards((FacesEvent) event);
    }

    /**
     * @param event
     * @return searchTimecards
     */
    @SuppressWarnings({ "unchecked", "rawtypes" })
    public String searchTimecards(final FacesEvent event) {
        String forward = null;
        final Object currentForm = this.resolveVariable("form");
        try {
            final SearchTimecardsFormImpl form = this.getSearchTimecardsForm();
            form.setEvent(event);
            this.setForm("form", form, true);
            // - pass any properties from the previous form along
            FormPopulator.populateForm(currentForm, form, false);
            // - populate the form with any event attributes that may match
            // IMPORTANT: it isn't possible to automatically populate any property named "id" since that
            // is a reserved name in JSF (the id of a component), therefore we have to unfortunately ignore any available "id" attribute
            FormPopulator.populateFormFromPropertyMap(form, form.getDateTimeFormatters(),
                    (Map) this.getRequestAttribute(ACTION_EVENT_ATTRIBUTES), new String[] { "id" });
            if (event != null) {
                final Map eventProperties = new HashMap();
                eventProperties.put(event.getComponent().getId(), event.getSource());
                FormPopulator.populateFormFromPropertyMapAssignableTypesOnly(form, null, eventProperties);
                FormPopulator.populateFormFromPropertyMap(form, form.getDateTimeFormatters(),
                        event.getComponent().getAttributes(), new String[] { "id" });
            }
            // - populate the form with any request attributes that may match
            FormPopulator.populateFormFromRequestAttributes(form, form.getDateTimeFormatters(), false, true);
            // - populate the form with any request parameters that may match
            FormPopulator.populateFormFromPropertyMap(form, form.getDateTimeFormatters(),
                    this.getContext().getExternalContext().getRequestParameterMap());
            //trigger method execution
            _searchTimecards_started(form);

            forward = _populateSearchScreen(form);
            final FacesMessage.Severity messageSeverity = this.getMaximumMessageSeverity();
            if (messageSeverity != null
                    && FacesMessage.SEVERITY_ERROR.getOrdinal() <= messageSeverity.getOrdinal()) {
                // - copy any messages to the 'currentForm'
                PropertyUtils.setProperty(currentForm, "jsfMessages",
                        PropertyUtils.getProperty(form, "jsfMessages"));
                this.setForm("form", currentForm, false);
            }
            if (event != null) {
                SearchTimecardsViewPopulator.populateFormAndViewVariables(this.getContext(), form);
            }
        } catch (final Throwable throwable) {
            this.setForm("form", currentForm, false);
            // - set the forward to null so that we stay on the current view
            forward = null;
            try {
                // - the exception is re-thrown by the exception handler and handled by the catch below if it can't get a messageKey
                //   (no reason to check for presence of messageKey)
                this.addErrorMessage(
                        Messages.get(PatternMatchingExceptionHandler.instance().handleException(throwable),
                                PatternMatchingExceptionHandler.instance().getMessageArguments(throwable)));
            } catch (Throwable exception) {
                logger.error(exception.getMessage(), exception);
                this.addExceptionMessage(exception);
            }
        }
        return forward;
    }

    /**
     * TODO: Model Documentation for org.andromda.timetracker.web.timecardsearch.Populate Search
     * Screen
     * @param form
     * @return forward
     * @throws Throwable
     */
    protected String _populateSearchScreen(final SearchTimecardsFormImpl form) throws Throwable {
        String forward = null;
        populateSearchScreen(form);
        forward = "search-timecards-search-timecards";

        //update the viewRoot
        final UIComponent viewRoot = FacesContext.getCurrentInstance().getViewRoot();
        final RequestContext requestContext = RequestContext.getCurrentInstance();
        updateTableValue(requestContext, viewRoot, "timecardSummaries", form.getTimecardSummaries());

        return forward;
    }

    /**
     * Returns a reference to the userService back-end service.
     * @return ServiceLocator.instance().getUserService()
     */
    protected final UserService getUserService() {
        try {
            return ServiceLocator.instance().getUserService();
        } catch (final Throwable throwable) {
            throw new RuntimeException(throwable);
        }
    }

    /**
     * Returns a reference to the timeTrackingService back-end service.
     * @return ServiceLocator.instance().getTimeTrackingService()
     */
    protected final TimeTrackingService getTimeTrackingService() {
        try {
            return ServiceLocator.instance().getTimeTrackingService();
        } catch (final Throwable throwable) {
            throw new RuntimeException(throwable);
        }
    }

    /**
     * Gets the current faces context.  This object is the point
     * from which to retrieve any request, session, etc information.
     *
     * @return the JSF faces context instance.
     */
    public FacesContext getContext() {
        return FacesContext.getCurrentInstance();
    }

    /**
     * A helper method that gets the current request from the faces
     * context.
     *
     * @return the current request instance.
     */
    protected HttpServletRequest getRequest() {
        return (HttpServletRequest) this.getContext().getExternalContext().getRequest();
    }

    /**
     * A helper method that gets the current reponse from the faces
     * context.
     *
     * @return the current response instance.
     */
    protected HttpServletResponse getResponse() {
        return (HttpServletResponse) this.getContext().getExternalContext().getResponse();
    }

    /**
     * A helper method that gets the current session from the faces
     * context.
     *
     * @param create If the create parameter is true, create (if necessary) and return a
     *        session instance associated with the current request. If the create
     *        parameter is false return any existing session instance associated with the
     *        current request, or return null if there is no such session.
     * @return the current session instance.
     */
    protected HttpSession getSession(final boolean create) {
        return (HttpSession) this.getContext().getExternalContext().getSession(create);
    }

    /**
     * Attempts to resolve the variable, given, the <code>name</code> of
     * the variable using the faces context variable resolver instance.
     * @param name
     * @return the resolved variable or null if not found.
     */
    @SuppressWarnings("deprecation")
    protected Object resolveVariable(final String name) {
        RequestContext adfContext = RequestContext.getCurrentInstance();
        Object variable = adfContext.getPageFlowScope().get(name);
        // - if we couldn't get the variable from the regular ADF context, see if
        //   the session contains an ADF context with the variable
        if (variable == null) {
            final HttpSession session = this.getSession(false);
            if (session != null) {
                final AdfFacesContextWrapper contextWrapper = (AdfFacesContextWrapper) session
                        .getAttribute("AndroMDAADFContext");
                adfContext = contextWrapper != null ? contextWrapper.getCurrentInstance() : null;
            }
            variable = adfContext != null ? adfContext.getPageFlowScope().get(name) : null;
        }
        // - finally try resolving it in the standard JSF manner
        if (variable == null) {
            final FacesContext context = this.getContext();
            variable = context != null
                    ? context.getApplication().getVariableResolver().resolveVariable(context, name)
                    : null;
        }
        return variable;
    }

    private void setForm(final String formKey, final Object form, boolean includeInSession) {
        final AdfFacesContextWrapper contextWrapper = new AdfFacesContextWrapper();
        contextWrapper.getCurrentInstance().getPageFlowScope().put(formKey, form);
        if (includeInSession) {
            this.setSessionAttribute(formKey, form);
            // - add this temporary ADF context to the session so that we can retrieve from a view populator if required
            this.getSession(false).setAttribute("AndroMDAADFContext", contextWrapper);
        }
    }

    /**
     * Finds the root cause of the given <code>throwable</code> and
     * adds the message taken from that cause to the faces context messages.
     *
     * @param throwable the exception information to add.
     */
    protected final void addExceptionMessage(Throwable throwable) {
        String message = null;
        final Throwable rootCause = ExceptionUtils.getRootCause(throwable);
        if (rootCause != null) {
            message = rootCause.toString();
        }
        if (message == null || message.trim().length() == 0) {
            message = throwable.toString();
        }
        this.addErrorMessage(message);
    }

    /**
     * Adds the given error <code>message</code> to the current faces context.
     *
     * @param message the message to add.
     */
    protected void addErrorMessage(final String message) {
        this.addMessage(FacesMessage.SEVERITY_ERROR, message);
    }

    /**
     * Adds the given warning <code>message</code> to the current faces context.
     *
     * @param message the message to add.
     */
    protected void addWarningMessage(final String message) {
        this.addMessage(FacesMessage.SEVERITY_WARN, message);
    }

    /**
     * Adds the given info <code>message</code> to the current faces context.
     *
     * @param message the message to add.
     */
    protected void addInfoMessage(final String message) {
        this.addMessage(FacesMessage.SEVERITY_INFO, message);
    }

    /**
     * Adds the given fatal <code>message</code> to the current faces context.
     *
     * @param message the message to add.
     */
    protected void addFatalMessage(final String message) {
        this.addMessage(FacesMessage.SEVERITY_FATAL, message);
    }

    /**
     * Adds a message to the faces context (which will show up on your view when using the
     * lt;h:messages/gt; tag).
     *
     * @param severity the severity of the message
     * @param message the message to add.
     */
    protected void addMessage(final FacesMessage.Severity severity, final String message) {
        final FacesMessage facesMessage = new FacesMessage(severity, message, message);
        final Object form = this.resolveVariable("form");
        if (form != null) {
            try {
                final Method method = form.getClass().getMethod("addJsfMessages",
                        new Class[] { FacesMessage.class });
                method.invoke(form, new Object[] { facesMessage });
            } catch (final Exception exception) {
                throw new RuntimeException(exception);
            }
        }
    }

    /**
     * Sets the messages title to use on the next view.
     *
     * @param messagesTitle the title to use.
     */
    protected void setMessagesTitle(final String messagesTitle) {
        final Object form = this.resolveVariable("form");
        if (form != null) {
            try {
                final Method method = form.getClass().getMethod("setJsfMessagesTitle",
                        new Class[] { String.class });
                method.invoke(form, new Object[] { messagesTitle });
            } catch (final Exception exception) {
                throw new RuntimeException(exception);
            }
        }
    }

    /**
     * Gets the maximum severity of the messages stored in the current form.
     *
     * @return the maximum message severity.
     */
    protected FacesMessage.Severity getMaximumMessageSeverity() {
        FacesMessage.Severity maximumSeverity = null;
        final Object form = this.resolveVariable("form");
        if (form != null) {
            try {
                final Method method = form.getClass().getMethod("getMaximumMessageSeverity", (Class[]) null);
                maximumSeverity = (FacesMessage.Severity) method.invoke(form, (Object[]) null);
            } catch (final Exception exception) {
                throw new RuntimeException(exception);
            }
        }
        return maximumSeverity;
    }

    /**
     * Copies all matching properties from the <code>fromForm</code> to the given
     * <code>toForm</code> overriding any previously set values.
     * @param fromForm
     * @param toForm
     */
    protected void copyForm(final Object fromForm, final Object toForm) {
        FormPopulator.populateForm(fromForm, toForm, true);
    }

    /**
     * Finds the form (if one is present) on the given <code>component</code> having the given
     * <code>id</code>.
     *
     * @param component the component to search.
     * @param id the id of the form.
     * @return the form or null if none was found.
     */
    private UIForm findForm(UIComponent component, String id) {
        UIForm foundForm = null;
        if (component != null) {
            for (final Iterator<UIComponent> iterator = component.getFacetsAndChildren(); iterator.hasNext();) {
                final UIComponent uiComponent = iterator.next();
                if (uiComponent instanceof UIForm) {
                    final UIForm form = (UIForm) uiComponent;
                    if (form.getId().equals(id)) {
                        foundForm = form;
                        break;
                    }
                }
                foundForm = this.findForm(uiComponent, id);
                if (foundForm != null) {
                    break;
                }
            }
        }
        return foundForm;
    }

    /**
     * If the given <code>component</code> has an child input elements, this method finds
     * them all and populates them.  This is to get around the fact that when immediate is set to true
     * on a button that submits the form that the form isn't populated.
     *
     * @param component the component to populate.
     */
    private void populateComponentInputs(UIComponent component) {
        if (component != null) {
            for (final Iterator<UIComponent> iterator = component.getFacetsAndChildren(); iterator.hasNext();) {
                final UIComponent uiComponent = iterator.next();
                if (uiComponent instanceof UIInput) {
                    try {
                        final UIInput input = (UIInput) uiComponent;
                        input.validate(this.getContext());
                        input.updateModel(this.getContext());
                    } catch (ValidatorException exception) {
                        // - ignore, no value is set (validate will be called by the regular
                        //   JSF lifecycle processing anyway, this is just called to populate the
                        //   local value
                    }
                } else {
                    this.populateComponentInputs(uiComponent);
                }
            }
        }
    }

    /**
     * Retrieves the current action form while making sure the form is of the given
     * <code>type</code>.  If the action form is found, but not of the given type, null will
     * be returned.
     *
     * @param type the type of form to retrieve.
     * @return the found form.
     */
    protected Object getCurrentActionForm(final Class<?> type) {
        Object form = this.getCurrentActionForm();
        if (!type.isInstance(form)) {
            form = null;
        }
        return form;
    }

    /**
     * Retrieves the current action form instance.
     *
     * @return the current action form instance.
     */
    protected Object getCurrentActionForm() {
        return this.resolveVariable("form");
    }

    /**
     * The name of the request attribute that stores the attributes from the current action event.
     */
    private static final String ACTION_EVENT_ATTRIBUTES = "actionEventAttributes";

    /**
     * This method just captures the event attributes and sets them into the request
     * so that we can retrieve in controller action operation and use to populate form.
     *
     * @param event the action event.
     */
    public void action(ActionEvent event) {
        this.setRequestAttribute(ACTION_EVENT_ATTRIBUTES, event.getComponent().getAttributes());
    }

    /**
     * @param name
     * @param object
     */
    protected void setRequestAttribute(final String name, final Object object) {
        JsfUtils.setAttribute(this.getContext().getExternalContext().getRequest(), name, object);
    }

    /**
     * @param name
     * @return RequestAttribute
     */
    protected Object getRequestAttribute(final String name) {
        return JsfUtils.getAttribute(this.getContext().getExternalContext().getRequest(), name);
    }

    /**
     * @param name
     * @param object
     */
    protected void setSessionAttribute(final String name, final Object object) {
        JsfUtils.setAttribute(this.getContext().getExternalContext().getSession(false), name, object);
    }

    /**
     * @param name
     * @return SessionAttribute
     */
    protected Object getSessionAttribute(final String name) {
        return JsfUtils.getAttribute(this.getContext().getExternalContext().getSession(false), name);
    }

    /**
     * Updates the component value in the view root.
     */
    @SuppressWarnings("unused")
    private void updateComponentValue(RequestContext requestContext, UIComponent viewRoot, String id,
            Object value) {
        UIComponent component = ComponentUtils.findRelativeComponent(viewRoot, id);
        if (component instanceof ValueHolder)//just in case the view was changed
        {
            ((ValueHolder) component).setValue(value);
        }
    }

    /**
     * Updates the table value in the view root.
     */
    @SuppressWarnings("unused")
    private void updateTableValue(RequestContext requestContext, UIComponent viewRoot, String id, Object value) {
        UIComponent component = ComponentUtils.findRelativeComponent(viewRoot, id);
        if (component instanceof UIXIterator)//just in case the view was changed
        {
            ((UIXIterator) component).setValue(value);
        }
    }
}