package inc.monsters.mias.workaround;

import org.apache.myfaces.extensions.validator.trinidad.ExtValTrinidadClientValidatorWrapper;

import javax.faces.event.PhaseListener;
import javax.faces.event.PhaseEvent;
import javax.faces.event.PhaseId;
import javax.faces.context.FacesContext;
import javax.faces.component.UIComponent;
import javax.faces.component.EditableValueHolder;
import javax.faces.validator.Validator;

/**
 * This class is a work around for an issue in the ExtValTrinidadClientValidatorWrapper,
 * which could cause a NullPointerException if a custom validator is used with ExtVal's
 * {@code @Validator} tag. (This appears to occur only on a Glassfish server.)
 * 
 * The class removes the ExtValTrinidadClientValidatorWrapper class right after the
 * render response phase. That's right after the work is done and just before the 
 * issue occurs.
 * 
 * @author Gerhard Petracek
 */
public class ResetPhaseListener implements PhaseListener
{
    private static final long serialVersionUID = 9005735495977534071L;

    public void afterPhase(PhaseEvent phaseEvent)
    {
        for(UIComponent uiComponent : FacesContext.getCurrentInstance().getViewRoot().getChildren())
        {
            removeTrinidadValidatorWrapper(uiComponent);
        }
    }

    private void removeTrinidadValidatorWrapper(UIComponent uiComponent)
    {
        if(uiComponent instanceof EditableValueHolder)
        {
            for(Validator validator : ((EditableValueHolder)uiComponent).getValidators())
            {
                if(validator instanceof ExtValTrinidadClientValidatorWrapper)
                {
                    ((EditableValueHolder)uiComponent).removeValidator(validator);
                }
            }
        }
        else
        {
            for(UIComponent child : uiComponent.getChildren())
            {
                removeTrinidadValidatorWrapper(child);
            }
        }
    }

    public void beforePhase(PhaseEvent phaseEvent)
    {
    }

    public PhaseId getPhaseId()
    {
        return PhaseId.RENDER_RESPONSE;
    }
}
