/**
*
*/
package org.richfaces.component;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import javax.el.MethodExpression;
import javax.el.ValueExpression;
import javax.faces.FacesException;
import javax.faces.component.EditableValueHolder;
import javax.faces.component.UIComponent;
import javax.faces.component.UIComponentBase;
import javax.faces.component.UIInput;
import javax.faces.component.UIMessage;
import javax.faces.context.FacesContext;
import javax.faces.event.AbortProcessingException;
import javax.faces.event.FacesEvent;
import javax.faces.event.PhaseId;
import org.ajax4jsf.component.AjaxComponent;
import org.ajax4jsf.component.AjaxContainer;
import org.ajax4jsf.component.AjaxSupport;
import org.ajax4jsf.component.EventValueExpression;
import org.ajax4jsf.context.AjaxContext;
import org.ajax4jsf.event.AjaxEvent;
import org.ajax4jsf.event.AjaxListener;
import org.ajax4jsf.renderkit.AjaxRendererUtils;
import org.ajax4jsf.webapp.taglib.MethodExpressionAjaxListener;
import org.richfaces.event.ValidationEvent;
/**
* JSF component class
*
*/
public abstract class UIBeanValidator extends UIComponentBase implements AjaxComponent, AjaxSupport, AjaxContainer {
public static final String COMPONENT_TYPE = "org.richfaces.BeanValidator";
public static final String COMPONENT_FAMILY = "org.richfaces.BeanValidator";
public static final String BEAN_VALIDATOR_FACET = "org.richfaces.validator.";
@Override
public void setParent(UIComponent parent) {
super.setParent(parent);
if (null != parent && parent instanceof EditableValueHolder) {
setParentProperties(parent);
}
}
/**
* @param parent
* @throws FacesException
*/
public void setParentProperties(UIComponent parent) throws FacesException {
if (!(parent instanceof EditableValueHolder)) {
throw new FacesException("Parent component must be an EditableValueHolder");
}
if (null != getEvent()) {
ValueExpression binding = new EventValueExpression(this);
parent.setValueExpression(getEvent(), binding);
}
}
@Override
public void broadcast(FacesEvent event) throws AbortProcessingException {
super.broadcast(event);
if (event.getComponent() == this) {
FacesContext context = getFacesContext();
if (event instanceof ValidationEvent) {
// ByPass UpdateModelValue
context.renderResponse();
} else if (event instanceof AjaxEvent) {
// TODO - find all UIMessages components for a parent UIInput.
// for an ajaxSingle component, re-render only target message.
AjaxContext ajaxContext = AjaxContext.getCurrentInstance(context);
ajaxContext.setSubmittedRegionClientId(this.getClientId(context));
}
}
}
@Override
public void queueEvent(FacesEvent event) {
if (event instanceof ValidationEvent && event.getComponent() == this) {
UIComponent parent = getParent();
if (parent instanceof UIInput) {
UIInput input = (UIInput) parent;
if (input.isImmediate()) {
event.setPhaseId(PhaseId.APPLY_REQUEST_VALUES);
} else {
event.setPhaseId(PhaseId.PROCESS_VALIDATIONS);
}
}
}
super.queueEvent(event);
}
public String getEventString() {
StringBuffer buildOnEvent = new StringBuffer();
String onsubmit = getOnsubmit();
// Insert script to call before submit ajax request.
if (null != onsubmit) {
buildOnEvent.append(onsubmit).append(";");
}
buildOnEvent.append(AjaxRendererUtils.buildOnEvent(this, getFacesContext(), getEvent()));
String script = buildOnEvent.toString();
return script;
}
public UIComponent getSingleComponent() {
return getParent();
}
public void encodeAjax(FacesContext context) throws IOException {
AjaxContext ajaxContext = AjaxContext.getCurrentInstance(context);
Set<String> renderedAreas = ajaxContext.getAjaxRenderedAreas();
List<UIMessage> messages = getMessages(context);
for (UIMessage message : messages) {
if (message.isRendered()) {
message.encodeAll(context);
renderedAreas.add(message.getClientId(context));
}
}
// Write information about encoded areas after submission.
AjaxRendererUtils.encodeAreas(context, this);
}
public List<UIMessage> getMessages(FacesContext context) {
ArrayList<UIMessage> messages = new ArrayList<UIMessage>();
UIComponent form = AjaxRendererUtils.getNestingForm(this);
if (null == form) {
form = context.getViewRoot();
}
findMessages(form, messages);
return messages;
}
/**
* Recursive search messages for the parent component.
*
* @param component
* @param messages
*/
protected void findMessages(UIComponent component, ArrayList<UIMessage> messages) {
// TODO create more intellectual search, symmenric for an UIMessage
// algoritm.
Iterator<UIComponent> facetsAndChildren = component.getFacetsAndChildren();
while (facetsAndChildren.hasNext()) {
UIComponent child = (UIComponent) facetsAndChildren.next();
if (child instanceof UIMessage) {
UIMessage message = (UIMessage) child;
String messageFor = message.getFor();
if (null != messageFor && messageFor.equals(getParent().getId())) {
messages.add(message);
}
} else {
findMessages(child, messages);
}
}
}
/*
* (non-Javadoc)
*
* @see org.ajax4jsf.event.AjaxSource#addAjaxListener(org.ajax4jsf.event.AjaxListener)
*/
public void addAjaxListener(AjaxListener listener) {
addFacesListener(listener);
}
/*
* (non-Javadoc)
*
* @see org.ajax4jsf.event.AjaxSource#getAjaxListeners()
*/
public AjaxListener[] getAjaxListeners() {
return (AjaxListener[]) getFacesListeners(AjaxListener.class);
}
/* (non-Javadoc)
* @see org.ajax4jsf.event.AjaxSource#removeAjaxListener(org.ajax4jsf.event.AjaxListener)
*/
public void removeAjaxListener(AjaxListener listener) {
removeFacesListener(listener);
}
public void setAjaxListener(MethodExpression listener) {
AjaxListener[] ajaxListeners = getAjaxListeners();
for (int i = 0; i < ajaxListeners.length; i++) {
AjaxListener ajaxListener = ajaxListeners[i];
if (ajaxListener.getClass().equals(MethodExpressionAjaxListener.class)) {
MethodExpressionAjaxListener expressionListener = (MethodExpressionAjaxListener) ajaxListener;
if (expressionListener.getExpression() != listener) {
removeAjaxListener(ajaxListener);
if (listener == null) {
return;
} else {
break;
}
}
}
}
addAjaxListener(new MethodExpressionAjaxListener(listener));
}
public MethodExpression getAjaxListener() {
AjaxListener[] ajaxListeners = getAjaxListeners();
for (int i = 0; i < ajaxListeners.length; i++) {
AjaxListener ajaxListener = ajaxListeners[i];
if (ajaxListener.getClass().equals(MethodExpressionAjaxListener.class)) {
MethodExpressionAjaxListener expressionListener = (MethodExpressionAjaxListener) ajaxListener;
return expressionListener.getExpression();
}
}
return null;
}
}