/*
* {START_JAVA_COPYRIGHT_NOTICE
* Copyright 2004 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
* END_COPYRIGHT_NOTICE}
*/
package documentmanagementprototype2;
import java.util.Iterator;
import java.util.Map;
import javax.faces.FactoryFinder;
import javax.faces.application.Application;
import javax.faces.application.FacesMessage;
import javax.faces.component.EditableValueHolder;
import javax.faces.component.UIComponent;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.faces.el.ValueBinding;
import javax.faces.event.PhaseEvent;
import javax.faces.event.PhaseId;
import javax.faces.event.PhaseListener;
import javax.faces.lifecycle.Lifecycle;
import javax.faces.lifecycle.LifecycleFactory;
/**
* <p><strong>FacesBean</strong> is the abstract base class for all page beans,
* session scope data beans, and application scope data beans that wish to
* participate in the request processing lifecycle. Concrete subclasses of
* this class will typically be registered as managed beans, so that they get
* created on demand (and added to the relevant scope's attributes).</p>
*/
public abstract class AbstractSessionBean implements PhaseListener {
// ------------------------------------------------------------- Constructor
/**
* <p>Register this bean as a <code>PhaseListener</code> so that it can
* participate in the request processing lifecycle of each request.</p>
*/
public AbstractSessionBean() {
getLifecycle().addPhaseListener(this);
}
// --------------------------------------------------- Convenience Accessors
/**
* <p>Return the <code>Application</code> instance for the current
* web application.</p>
*/
protected Application getApplication() {
return FacesContext.getCurrentInstance().getApplication();
}
/**
* <p>Return a <code>Map</code> of the application scope attributes
* for this web application.</p>
*/
protected Map getApplicationMap() {
return getExternalContext().getApplicationMap();
}
/**
* <p>Return the <code>FacesContext</code> instance for the current
* request.</p>
*/
protected FacesContext getContext() {
return FacesContext.getCurrentInstance();
}
/**
* <p>Return the <code>ExternalContext</code> instance for the
* current request.</p>
*/
protected ExternalContext getExternalContext() {
return FacesContext.getCurrentInstance().getExternalContext();
}
/**
* <p>Return the configured <code>Lifecycle</code> instance for the
* current web application.</p>
*/
protected Lifecycle getLifecycle() {
String lifecycleId =
getExternalContext().getInitParameter("javax.faces.LIFECYCLE_ID"); //NOI18N
if (lifecycleId == null || lifecycleId.length() == 0) {
lifecycleId = LifecycleFactory.DEFAULT_LIFECYCLE;
}
LifecycleFactory lifecycleFactory = (LifecycleFactory)
FactoryFinder.getFactory(FactoryFinder.LIFECYCLE_FACTORY);
return lifecycleFactory.getLifecycle(lifecycleId);
}
/**
* <p>Return a <code>Map</code> of the request scope attributes for
* the current request.</p>
*/
protected Map getRequestMap() {
return getExternalContext().getRequestMap();
}
/**
* <p>Return a <code>Map</code> of the session scope attributes for the
* current user's session. Note that calling this method will cause a
* session to be created if there is not already one associated with
* this request.</p>
*/
protected Map getSessionMap() {
return getExternalContext().getSessionMap();
}
// ------------------------------------------------------- Bean Manipulation
/**
* <p>Return any attribute stored in request scope, session scope, or
* application scope under the specified name. If no such
* attribute is found, and if this name is the registered name of a
* managed bean, cause a new instance of this managed bean to be created
* (and stored in an appropriate scope, if necessary) and returned.
* If no attribute exists, and no managed bean was created, return
* <code>null</code>.</p>
*
* @param name Name of the attribute to be retrieved
*/
protected Object getBean(String name) {
return getApplication().getVariableResolver().resolveVariable(getContext(), name);
}
/**
* <p>Replace the value of any attribute stored in request scope,
* session scope, or application scope under the specified name. If there
* is no such attribute, create a new request scope attribute under this
* name, and store the value there.</p>
*/
protected void setBean(String name, Object value) {
setValue("#{" + name + "}", value); //NOI18N
}
// ------------------------------------------------------ Value Manipulation
/**
* <p>Evaluate the specified value binding expression, and return
* the value that it points at.</p>
*
* @param expr Value binding expression (including delimiters)
*/
protected Object getValue(String expr) {
ValueBinding vb = getApplication().createValueBinding(expr);
return (vb.getValue(getContext()));
}
/**
* <p>Evaluate the specified value binding expression, and update
* the value that it points at.</p>
*
* @param expr Value binding expression (including delimiters) that
* must point at a writeable property
* @param value New value for the property pointed at by <code>expr</code>
*/
protected void setValue(String expr, Object value) {
ValueBinding vb = getApplication().createValueBinding(expr);
vb.setValue(getContext(), value);
}
// ----------------------------------------------------------- PhaseListener
/**
* <p>Call through to the "before" lifecycle callback method
* for the current phase.</p>
*
* @param phaseEvent <code>PhaseEvent</code> to be processed
*/
public void beforePhase(PhaseEvent phaseEvent) {
PhaseId phaseId = phaseEvent.getPhaseId();
if (PhaseId.RESTORE_VIEW.equals(phaseId)) {
beforeRestoreView();
} else if (PhaseId.APPLY_REQUEST_VALUES.equals(phaseId)) {
beforeApplyRequestValues();
} else if (PhaseId.PROCESS_VALIDATIONS.equals(phaseId)) {
beforeProcessValidations();
} else if (PhaseId.UPDATE_MODEL_VALUES.equals(phaseId)) {
beforeUpdateModelValues();
} else if (PhaseId.INVOKE_APPLICATION.equals(phaseId)) {
beforeInvokeApplication();
} else if (PhaseId.RENDER_RESPONSE.equals(phaseId)) {
beforeRenderResponse();
}
}
/**
* <p>Call through to the "after" lifecycle callback method
* for the current phase.</p>
*
* @param phaseEvent <code>PhaseEvent</code> to be processed
*/
public void afterPhase(PhaseEvent phaseEvent) {
PhaseId phaseId = phaseEvent.getPhaseId();
if (PhaseId.RESTORE_VIEW.equals(phaseId)) {
afterRestoreView();
} else if (PhaseId.APPLY_REQUEST_VALUES.equals(phaseId)) {
afterApplyRequestValues();
} else if (PhaseId.PROCESS_VALIDATIONS.equals(phaseId)) {
afterProcessValidations();
} else if (PhaseId.UPDATE_MODEL_VALUES.equals(phaseId)) {
afterUpdateModelValues();
} else if (PhaseId.INVOKE_APPLICATION.equals(phaseId)) {
afterInvokeApplication();
} else if (PhaseId.RENDER_RESPONSE.equals(phaseId)) {
afterRenderResponse();
if (getRequestMap().containsValue(this)) {
getLifecycle().removePhaseListener(this);
}
}
}
/**
* <p>Return <code>PhaseId.ANY_PHASE</code> to indicate that we are
* interested in all phases.</p>
*/
public PhaseId getPhaseId() {
return PhaseId.ANY_PHASE;
}
// ----------------------------------------------------- Lifecycle Callbacks
// These methods are called by beforePhase() and afterPhase() as appropriate
// and allow subclasses to perform additional tasks at the corresponding
// moment in the request processing lifecycle for each request. The default
// implementations do nothing.
protected void beforeRestoreView() {}
protected void afterRestoreView() {}
protected void beforeApplyRequestValues() {}
protected void afterApplyRequestValues() {}
protected void beforeProcessValidations() {}
protected void afterProcessValidations() {}
protected void beforeUpdateModelValues() {}
protected void afterUpdateModelValues() {}
protected void beforeInvokeApplication() {}
protected void afterInvokeApplication() {}
protected void beforeRenderResponse() {}
protected void afterRenderResponse() {}
// ------------------------------------------------------- Phase Processing
/**
* <p>Skip any remaining request processing lifecycle phases for the
* current request, and go immediately to <em>Render Response</em>
* phase. This method is typically invoked when you want to throw
* away input values provided by the user, instead of processing them.</p>
*/
protected void renderResponse() {
getContext().renderResponse();
}
// -------------------------------------------------- Component Manipulation
/**
* <p>Erase previously submitted values for all input components on this
* page. This method <strong>MUST</strong> be called if you have bound
* input components to database columns, and then arbitrarily navigate
* the underlying <code>RowSet</code> to a different row in an event
* handler method.</p>
*/
protected void erase() {
erase(getContext().getViewRoot());
}
/**
* <p>Private helper method for <code>erase()</code> that recursively
* descends the component tree and performs the required processing.</p>
*
* @param component The component to be erased
*/
private void erase(UIComponent component) {
// Erase the component itself (if needed)
if (component instanceof EditableValueHolder) {
((EditableValueHolder) component).setSubmittedValue(null);
}
// Process the facets and children of this component
Iterator kids = component.getFacetsAndChildren();
while (kids.hasNext()) {
erase((UIComponent) kids.next());
}
}
// ------------------------------------------------------------- Log Methods
/**
* <p>Log the specified message to the container's log file.</p>
*
* @param message Message to be logged
*/
protected void log(String message) {
getExternalContext().log(message);
}
/**
* <p>Log the specified message and exception to the container's
* log file.</p>
*
* @param message Message to be logged
* @param throwable Exception to be logged
*/
protected void log(String message, Throwable throwable) {
getExternalContext().log(message, throwable);
}
// --------------------------------------------------------- Message Methods
/**
* <p>Enqueue a global <code>FacesMessage</code> (not associated
* with any particular componen) containing the specified summary text
* and a message severity level of <code>FacesMessage.SEVERITY_INFO</code>.
* </p>
*
* @param summary Summary text for this message
*/
protected void info(String summary) {
getContext().addMessage(null,
new FacesMessage(FacesMessage.SEVERITY_INFO, summary, null));
}
/**
* <p>Enqueue a <code>FacesMessage</code> associated with the
* specified component, containing the specified summary text
* and a message severity level of <code>FacesMessage.SEVERITY_INFO</code>.
* </p>
*
* @param component Component with which this message is associated
* @param summary Summary text for this message
*/
protected void info(UIComponent component, String summary) {
getContext().addMessage(component.getClientId(getContext()),
new FacesMessage(FacesMessage.SEVERITY_INFO, summary, null));
}
/**
* <p>Enqueue a global <code>FacesMessage</code> (not associated
* with any particular componen) containing the specified summary text
* and a message severity level of <code>FacesMessage.SEVERITY_WARN</code>.
* </p>
*
* @param summary Summary text for this message
*/
protected void warn(String summary) {
getContext().addMessage(null,
new FacesMessage(FacesMessage.SEVERITY_WARN, summary, null));
}
/**
* <p>Enqueue a <code>FacesMessage</code> associated with the
* specified component, containing the specified summary text
* and a message severity level of <code>FacesMessage.SEVERITY_WARN</code>.
* </p>
*
* @param component Component with which this message is associated
* @param summary Summary text for this message
*/
protected void warn(UIComponent component, String summary) {
getContext().addMessage(component.getClientId(getContext()),
new FacesMessage(FacesMessage.SEVERITY_WARN, summary, null));
}
/**
* <p>Enqueue a global <code>FacesMessage</code> (not associated
* with any particular componen) containing the specified summary text
* and a message severity level of <code>FacesMessage.SEVERITY_ERROR</code>.
* </p>
*
* @param summary Summary text for this message
*/
protected void error(String summary) {
getContext().addMessage(null,
new FacesMessage(FacesMessage.SEVERITY_ERROR, summary, null));
}
/**
* <p>Enqueue a <code>FacesMessage</code> associated with the
* specified component, containing the specified summary text
* and a message severity level of <code>FacesMessage.SEVERITY_ERROR</code>.
* </p>
*
* @param component Component with which this message is associated
* @param summary Summary text for this message
*/
protected void error(UIComponent component, String summary) {
getContext().addMessage(component.getClientId(getContext()),
new FacesMessage(FacesMessage.SEVERITY_ERROR, summary, null));
}
/**
* <p>Enqueue a global <code>FacesMessage</code> (not associated
* with any particular componen) containing the specified summary text
* and a message severity level of <code>FacesMessage.SEVERITY_FATAL</code>.
* </p>
*
* @param summary Summary text for this message
*/
protected void fatal(String summary) {
getContext().addMessage(null,
new FacesMessage(FacesMessage.SEVERITY_FATAL, summary, null));
}
/**
* <p>Enqueue a <code>FacesMessage</code> associated with the
* specified component, containing the specified summary text
* and a message severity level of <code>FacesMessage.SEVERITY_FATAL</code>.
* </p>
*
* @param component Component with which this message is associated
* @param summary Summary text for this message
*/
protected void fatal(UIComponent component, String summary) {
getContext().addMessage(component.getClientId(getContext()),
new FacesMessage(FacesMessage.SEVERITY_FATAL, summary, null));
}
}