/**
* License Agreement.
*
* JBoss RichFaces - Ajax4jsf Component Library
*
* 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.richfaces.component;
import java.util.Iterator;
import javax.el.ValueExpression;
import javax.faces.component.UIComponent;
import javax.faces.component.UIInput;
import javax.faces.context.FacesContext;
import javax.faces.el.ValueBinding;
import javax.faces.event.AbortProcessingException;
import javax.faces.event.ActionEvent;
import javax.faces.event.FacesEvent;
import javax.faces.event.PhaseId;
import javax.faces.event.ValueChangeEvent;
import org.ajax4jsf.renderkit.AjaxRendererUtils;
import org.richfaces.event.SwitchablePanelSwitchEvent;
/**
* @author Nick Belaevski - nbelaevski@exadel.com
* created 23.01.2007
*
*/
public abstract class UISwitchablePanel extends UIInput {
/**
* value for tab change method for - client-side tabs.
*/
public static final String CLIENT_METHOD = "client";
/**
* value for tab change method - server-side tabs
*/
public static final String SERVER_METHOD = "server";
/**
* value for tab change method - ajax tabs
*/
public static final String AJAX_METHOD = "ajax";
/**
* default tab change method - server.
*/
public static final String DEFAULT_METHOD = SERVER_METHOD;
private String switchType;
public String getSwitchType() {
if (this.switchType != null) {
return switchType;
}
ValueBinding switchTypeBinding = getValueBinding("switchType");
if (switchTypeBinding != null) {
return (String) switchTypeBinding.getValue(FacesContext.getCurrentInstance());
}
//TODO use DEFAULT_METHOD
return SERVER_METHOD;
}
public void setSwitchType(String switchType) {
this.switchType = switchType;
}
public Object convertSwitchValue(UIComponent component, Object object) {
return object;
}
public void queueEvent(FacesEvent event) {
if (event instanceof SwitchablePanelSwitchEvent && this.equals(event.getComponent())) {
if (isImmediate()) {
event.setPhaseId(PhaseId.APPLY_REQUEST_VALUES);
} else {
event.setPhaseId(PhaseId.UPDATE_MODEL_VALUES);
}
}
super.queueEvent(event);
}
public void broadcast(FacesEvent facesEvent) throws AbortProcessingException {
if(facesEvent instanceof ActionEvent){
//TODO invoke action listener or remove it
if(isImmediate()){
FacesContext facesContext = FacesContext.getCurrentInstance();
facesContext.renderResponse();
}
} //TODO else here
if (facesEvent instanceof SwitchablePanelSwitchEvent) {
if (isRendered()) {
FacesContext facesContext = FacesContext.getCurrentInstance();
SwitchablePanelSwitchEvent switchEvent = (SwitchablePanelSwitchEvent) facesEvent;
Object newValue = convertSwitchValue(switchEvent.getEventSource(),
switchEvent.getValue());
Object oldValue = getValue();
if ((oldValue == null && newValue != null) ||
(oldValue != null && !oldValue.equals(newValue))) {
queueEvent(new ValueChangeEvent(this, oldValue, newValue));
}
//TODO UIInput should update the model, not the switchable panel itself
ValueExpression valueBinding = getValueExpression("value");
if (valueBinding != null) {
valueBinding.setValue(facesContext.getELContext(), newValue);
setValue(null);
setLocalValueSet(false);
} else {
setValue(newValue);
}
if (AjaxRendererUtils.isAjaxRequest(facesContext) && this.getSwitchType().equals(AJAX_METHOD)) {
AjaxRendererUtils.addRegionByName(facesContext,
this,
this.getId());
}
}
} else /* component should throw IllegalArgumentException for unknown events - RF-30 */ {
super.broadcast(facesEvent);
}
}
public void updateModel(FacesContext context) {
//no processing here
}
protected Iterator getSwitchedFacetsAndChildren() {
return getFacetsAndChildren();
}
public void processDecodes(FacesContext context) {
if (context == null) {
throw new NullPointerException("FacesContext is null!");
}
if (!isRendered()) {
return ;
}
// Process all facets and children of this component
Iterator kids = getSwitchedFacetsAndChildren();
while (kids.hasNext()) {
UIComponent kid = (UIComponent) kids.next();
kid.processDecodes(context);
}
try {
decode(context);
if (isImmediate()) {
validate(context);
// if (!isValid()) {
// context.renderResponse();
// }
//UISwitchablePanel has a special behavior
//it stops processing after APPLY_REQUEST_VALUES phase
//when immediate
//
// set context.renderResponse() in broadcast method if component is immediate
// and ActionEvent is occured (RF-1032)
// context.renderResponse();
}
} catch (RuntimeException e) {
context.renderResponse();
throw e;
}
}
public void processUpdates(FacesContext context) {
if (context == null) {
throw new NullPointerException("FacesContext is null!");
}
if (!isRendered()) {
return ;
}
Iterator kids = getSwitchedFacetsAndChildren();
while (kids.hasNext()) {
UIComponent kid = (UIComponent) kids.next();
kid.processUpdates(context);
}
try {
updateModel(context);
if (!isValid()) {
context.renderResponse();
}
} catch (RuntimeException e) {
context.renderResponse();
throw e;
}
}
public void processValidators(FacesContext context) {
if (context == null) {
throw new NullPointerException("FacesContext is null!");
}
if (!isRendered()) {
return ;
}
Iterator kids = getSwitchedFacetsAndChildren();
while (kids.hasNext()) {
UIComponent kid = (UIComponent) kids.next();
kid.processValidators(context);
}
try {
if (!isImmediate()) {
validate(context);
if (!isValid()) {
context.renderResponse();
}
}
} catch (RuntimeException e) {
context.renderResponse();
throw e;
}
}
public Object saveState(FacesContext context) {
Object[] states = new Object[2];
states[0] = super.saveState(context);
states[1] = switchType;
return states;
}
public void restoreState(FacesContext context, Object state) {
Object[] states = (Object[]) state;
super.restoreState(context, states[0]);
this.switchType = (String) states[1];
}
}