/**
* License Agreement.
*
* Rich Faces - Natural Ajax for Java Server Faces (JSF)
*
* Copyright (C) 2007 Exadel, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License version 2.1 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package org.ajax4jsf.component;
import javax.faces.application.Application;
import javax.faces.component.StateHolder;
import javax.faces.component.UIComponent;
import javax.faces.component.UIComponentBase;
import javax.faces.context.FacesContext;
import javax.faces.el.MethodBinding;
import javax.faces.el.ValueBinding;
import javax.faces.event.AbortProcessingException;
import javax.faces.event.FacesEvent;
import org.ajax4jsf.Messages;
import org.ajax4jsf.component.AjaxContainerBase;
import org.ajax4jsf.context.AjaxContext;
import org.ajax4jsf.event.AjaxEvent;
import org.ajax4jsf.event.AjaxListener;
import org.ajax4jsf.event.AjaxRenderEvent;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* @author shura
*
* Brige design pattern for any UIComponent append support ajax partial rendering. For AJAX request, apply
* ActionListeniers, construct list of components for render - by direct setting
* from Listenier or Components bean methods.
* For use in concrete component, in constructor must be instantiated to class field as :
* private AjaxRegionBrige brige;
* ....
* Constructor(){
* brige = new AjaxRegionBrige(this);
* }.
* And delegate all brige public methods.
* @See <code>AJAXConatiner</code> interface , or from configuration - by
* <ajax:forupdate>jsp tag's of this or nested components, or from all
* <code>UIForm</code> components instances with <code>isSubmitted</code>
* set to <code>true</code>
*
*/
public class AjaxRegionBrige implements AjaxContainerBase, StateHolder{
// Private Fields
private static final Log log = LogFactory.getLog(AjaxRegionBrige.class);
/**
* Listener for call on Ajax Requests
*/
private MethodBinding ajaxListener = null;
/**
* Flag for immediate call listeners
*/
private boolean immediate = false;
private boolean immediateSet = false;
private boolean selfRendered = false;
private boolean selfRenderedSet = false;
private boolean transientFlag = false;
private UIComponent component ;
private boolean submitted = false;
// Interface implementation
/**
* @param component
*/
public AjaxRegionBrige(UIComponent component) {
this.component = component;
}
/*
* (non-Javadoc)
*
* @see org.ajax4jsf.components.custom.ajax.AjaxContainer#getAjaxListener()
*/
public MethodBinding getAjaxListener() {
return this.ajaxListener;
}
/*
* (non-Javadoc)
*
* @see ogr.apache.myfaces.custom.ajax.AjaxContainer#setAjaxListener(javax.faces.el.MethodBinding)
*/
public void setAjaxListener(MethodBinding ajaxListener) {
//
if (log.isDebugEnabled())
{
log.debug(Messages.getMessage(Messages.SET_AJAX_LISTENER, ajaxListener.getExpressionString()));
}
this.ajaxListener = ajaxListener;
}
/*
* (non-Javadoc)
*
* @see ogr.apache.myfaces.custom.ajax.AjaxContainer#isImmediate()
*/
public boolean isImmediate() {
if (this.immediateSet) {
return (this.immediate);
}
ValueBinding vb = component.getValueBinding("immediate");
if (vb != null) {
return (Boolean.TRUE.equals(vb.getValue(FacesContext.getCurrentInstance())));
} else {
return (this.immediate);
}
}
/*
* (non-Javadoc)
*
* @see ogr.apache.myfaces.custom.ajax.AjaxContainer#setImmediate(boolean)
*/
public void setImmediate(boolean immediate) {
if (immediate != this.immediate) {
this.immediate = immediate;
}
this.immediateSet = true;
}
/* (non-Javadoc)
* @see org.ajax4jsf.framework.ajax.AjaxContainer#isSelfRendered()
*/
public boolean isSelfRendered() {
if (this.selfRenderedSet) {
return (this.selfRendered);
}
ValueBinding vb = component.getValueBinding("selfRendered");
if (vb != null) {
return (Boolean.TRUE.equals(vb.getValue(FacesContext.getCurrentInstance())));
} else {
return (this.selfRendered);
}
}
/* (non-Javadoc)
* @see org.ajax4jsf.framework.ajax.AjaxContainer#setSelfRendered(boolean)
*/
public void setSelfRendered(boolean selfRendered) {
this.selfRendered = selfRendered;
this.selfRenderedSet = true;
}
/**
* @return Returns the submitted.
*/
public boolean isSubmitted()
{
// TODO - more correct check for submitted state
return this.submitted;
}
/**
* @param submitted The submitted to set.
*/
public void setSubmitted(boolean submitted)
{
// Important - decoder must set submitted AFTER setAjaxRequest !!!
if (log.isDebugEnabled() && submitted && (!isSubmitted())) {
log.debug(Messages.getMessage(Messages.SUBMITTED_AJAX_REQUEST));
}
this.submitted = submitted;
}
/**
* <p>
* In addition to to the default {@link UIComponent#broadcast}processing,
* pass the {@link AjaxEvent}being broadcast to the method referenced by
* <code>AjaxListener</code> (if any), and to the default
* {@link AjaxListener}registered on the {@link Application}.
* </p>
*
* @param event
* {@link FacesEvent}to be broadcast
*
* @exception AbortProcessingException
* Signal the JavaServer Faces implementation that no further
* processing on the current event should be performed
* @exception IllegalArgumentException
* if the implementation class of this {@link FacesEvent}is
* not supported by this component
* @exception NullPointerException
* if <code>event</code> is <code>null</code>
*/
public void broadcast(FacesEvent event) throws AbortProcessingException {
// Perform standard superclass processing
// component.broadcast(event);
if (event instanceof AjaxEvent) {
if (log.isDebugEnabled())
{
log.debug(Messages.getMessage(Messages.SEND_EVENT_TO_AJAX_LISTENER, component.getId()));
}
// Notify the specified action listener method (if any)
MethodBinding mb = getAjaxListener();
if (mb != null) {
FacesContext context = FacesContext.getCurrentInstance();
mb.invoke(context, new Object[] { event });
}
// TODO - perform special rendering, withowt RENDER_VIEW phase.
if(isSelfRendered()) {
// queue new event to end of queue to perform child elements
// events.
if (log.isDebugEnabled())
{
log.debug("Queue AjaxRenderEvent for self-render of AjaxContainer with Id "
+ component.getId());
}
FacesEvent renderEvent = new AjaxRenderEvent(component);
renderEvent.setPhaseId(event.getPhaseId());
component.queueEvent(renderEvent);
}
}
if (event instanceof AjaxRenderEvent) {
FacesContext context = FacesContext.getCurrentInstance();
AjaxContext.getCurrentInstance(context).renderAjaxRegion(context, component, false);
}
}
/*
* (non-Javadoc)
*
* @see javax.faces.component.StateHolder#restoreState(javax.faces.context.FacesContext,
* java.lang.Object)
*/
public void restoreState(FacesContext context, Object state) {
if (log.isDebugEnabled()) {
log.debug(Messages.getMessage(Messages.RESTORE_AJAX_COMPONENT_STATE, component.getId()));
}
Object values[] = (Object[]) state;
// super.restoreState(context, values[0]);
this.immediate = ((Boolean) values[0]).booleanValue();
this.immediateSet = ((Boolean) values[1]).booleanValue();
this.ajaxListener = (MethodBinding) UIComponentBase.restoreAttachedState(context, values[2]);
this.selfRendered = ((Boolean) values[3]).booleanValue();
this.selfRenderedSet = ((Boolean) values[4]).booleanValue();
}
/*
* (non-Javadoc)
*
* @see javax.faces.component.StateHolder#saveState(javax.faces.context.FacesContext)
*/
public Object saveState(FacesContext context) {
//
if (log.isDebugEnabled()) {
log.debug(Messages.getMessage(Messages.SAVE_AJAX_COMPONENT_STATE, component.getId()));
}
Object[] values = new Object[5];
// values[0] = super.saveState(context);
values[0] = Boolean.valueOf(immediate);
values[1] = Boolean.valueOf(immediateSet);
values[2] = UIComponentBase.saveAttachedState(context, ajaxListener);
values[3] = Boolean.valueOf(selfRendered);
values[4] = Boolean.valueOf(selfRenderedSet);
return values;
}
/* public void processDecodes(javax.faces.context.FacesContext context)
{
if (context == null) throw new NullPointerException("context");
// due SUN ri design, clear current sattus.
if(! component.isRendered()) return;
if(log.isDebugEnabled()){
log.debug("Process decodes of AjaxContainer with Id "+component.getId());
}
component.decode(context);
// If it is AJAX request for different area - skip decoding childs.
if (isAjaxRequest()&& !isSubmitted()){
if(log.isDebugEnabled()){
log.debug("Skip Decoders for childrens of AjaxContainer with Id "+component.getId());
}
return;
}
for (Iterator it = component.getFacetsAndChildren(); it.hasNext(); )
{
UIComponent childOrFacet = (UIComponent)it.next();
childOrFacet.processDecodes(context);
}
}
public void processValidators(javax.faces.context.FacesContext context)
{
if (context == null) throw new NullPointerException("context");
if(! component.isRendered()) return;
if (isAjaxRequest()&& !isSubmitted()){
if(log.isDebugEnabled()){
log.debug("Skip Validators for childrens of AjaxContainer with Id "+component.getId());
}
return;
}
for (Iterator it = component.getFacetsAndChildren(); it.hasNext(); )
{
UIComponent childOrFacet = (UIComponent)it.next();
childOrFacet.processValidators(context);
}
}
public void processUpdates(javax.faces.context.FacesContext context)
{
if (context == null) throw new NullPointerException("context");
if(! component.isRendered()) return;
if (isAjaxRequest()&& !isSubmitted()){
if(log.isDebugEnabled()){
log.debug("Skip updates for childrens of AjaxContainer with Id "+component.getId());
}
return;
}
for (Iterator it = component.getFacetsAndChildren(); it.hasNext(); )
{
UIComponent childOrFacet = (UIComponent)it.next();
childOrFacet.processUpdates(context);
}
}
*/
public boolean isTransient() {
return transientFlag;
}
public void setTransient(boolean transientFlag) {
this.transientFlag = transientFlag;
}
}