/*
* Copyright 2011-2012 Blazebit
*/
package com.blazebit.blazefaces.listener;
import java.util.Collection;
import java.util.Iterator;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.faces.component.EditableValueHolder;
import javax.faces.component.NamingContainer;
import javax.faces.component.UIComponent;
import javax.faces.component.UIForm;
import javax.faces.component.UINamingContainer;
import javax.faces.component.UIViewRoot;
import javax.faces.context.FacesContext;
import javax.faces.event.PhaseEvent;
import javax.faces.event.PhaseId;
import javax.faces.event.PhaseListener;
/**
*
* @author Christian Beikov
* @since 0.1.2
*/
public class ResetInputPhaseListener implements PhaseListener {
private static final long serialVersionUID = 1L;
private static final Logger log = Logger.getLogger(ResetInputPhaseListener.class.getName());
@Override
public void afterPhase(PhaseEvent pe) {
if (pe.getFacesContext().getPartialViewContext().isAjaxRequest()) {
Collection<String> renderIds = pe.getFacesContext().getPartialViewContext().getRenderIds();
UIViewRoot view = pe.getFacesContext().getViewRoot();
for (String renderId : renderIds) {
UIComponent comp = findComponent(view, renderId);
if (comp != null) {
recursiveReset(comp);
} else {
log.log(Level.WARNING, "Could not find component with id '" + renderId + "' in view '" + view.getViewId() + "'");
}
}
}
}
/**
* Originally taken from Mojarra implementation of UIComponentBase with the
* addition of special checking when the NamingContainer is of the type UIForm.
*/
private UIComponent findComponent(UIComponent comp, String expr) {
if (expr == null) {
throw new NullPointerException();
}
FacesContext ctx = FacesContext.getCurrentInstance();
final char sepChar = UINamingContainer.getSeparatorChar(ctx);
final String SEPARATOR_STRING = String.valueOf(sepChar);
if (expr.length() == 0) {
// if an empty value is provided, fail fast.
throw new IllegalArgumentException("\"\"");
}
// Identify the base component from which we will perform our search
UIComponent base = comp;
if (expr.charAt(0) == sepChar) {
// Absolute searches start at the root of the tree
while (base.getParent() != null) {
base = base.getParent();
}
// Treat remainder of the expression as relative
expr = expr.substring(1);
} else if (!(base instanceof NamingContainer)) {
// Relative expressions start at the closest NamingContainer or root
while (base.getParent() != null) {
if (base instanceof NamingContainer) {
break;
}
base = base.getParent();
}
}
// Evaluate the search expression (now guaranteed to be relative)
UIComponent result = null;
String[] segments = expr.split(SEPARATOR_STRING);
for (int i = 0, length = (segments.length - 1);
i < segments.length;
i++, length--) {
result = findComponent(base, segments[i], (i == 0));
// the first element of the expression may match base.id
// (vs. a child if of base)
if (i == 0 && result == null
&& segments[i].equals(base.getId())) {
result = base;
}
if (result != null && (!(result instanceof NamingContainer)) && length > 0) {
throw new IllegalArgumentException(segments[i]);
}
if (result == null) {
break;
}
base = result;
}
// Return the final result of our search
return (result);
}
private UIComponent findComponent(UIComponent base, String id, boolean checkId) {
if (checkId && id.equals(base.getId())) {
return base;
}
// Search through our facets and children
UIComponent result = null;
for (Iterator<UIComponent> i = base.getFacetsAndChildren(); i.hasNext();) {
UIComponent kid = i.next();
// Special handling for UIForm because of the attribute prependId
if (!(kid instanceof NamingContainer) || (kid instanceof UIForm && !((UIForm) kid).isPrependId() && !id.equals(kid.getId()))) {
if (checkId && id.equals(kid.getId())) {
result = kid;
break;
}
result = findComponent(kid, id, true);
if (result != null) {
break;
}
} else if (id.equals(kid.getId())) {
result = kid;
break;
}
}
return (result);
}
private void recursiveReset(UIComponent comp) {
if (comp instanceof EditableValueHolder) {
((EditableValueHolder) comp).resetValue();
}
for (Iterator<UIComponent> i = comp.getFacetsAndChildren(); i.hasNext();) {
recursiveReset(i.next());
}
}
@Override
public void beforePhase(PhaseEvent pe) {
}
@Override
public PhaseId getPhaseId() {
return PhaseId.RESTORE_VIEW;
}
}