package org.seasar.jsf.util;

import javax.faces.application.FacesMessage;
import javax.faces.component.UIComponent;
import javax.faces.component.UIInput;
import javax.faces.context.FacesContext;
import javax.faces.el.EvaluationException;
import javax.faces.el.MethodBinding;
import javax.faces.validator.Validator;
import javax.faces.validator.ValidatorException;

import org.seasar.jsf.JsfConstants;

/**
 * @author higa
 *  
 */
public final class UIComponentUtil {

    private UIComponentUtil() {
    }

    public static UIComponent findParent(UIComponent component,
            Class parentClass) {

        for (UIComponent parent = component.getParent(); parent != null; parent = parent
                .getParent()) {
            if (parentClass.isInstance(parent)) {
                return parent;
            }
        }
        throw new IllegalArgumentException(parentClass.getName());
    }

    public static String getLabel(UIComponent component) {
        String label = (String) component.getAttributes().get(
                JsfConstants.LABEL_ATTR);
        if (label != null) {
            return label;
        }
        return component.getId();
    }

    public static void callValidators(FacesContext context, UIInput input,
            Object convertedValue) {
        
        Validator[] validators = input.getValidators();
        for (int i = 0; i < validators.length; ++i) {
            Validator validator = validators[i];
            try {
                validator.validate(context, input, convertedValue);
            } catch (ValidatorException e) {
                input.setValid(false);
                FacesMessage facesMessage = e.getFacesMessage();
                if (facesMessage != null) {
                    context
                            .addMessage(input.getClientId(context),
                                    facesMessage);
                }
            }
        }
        MethodBinding validatorBinding = input.getValidator();
        if (validatorBinding != null) {
            try {
                validatorBinding.invoke(context, new Object[] { context, input,
                        convertedValue });
            } catch (EvaluationException e) {
                input.setValid(false);
                Throwable cause = e.getCause();
                if (cause instanceof ValidatorException) {
                    FacesMessage facesMessage = ((ValidatorException) cause)
                            .getFacesMessage();
                    if (facesMessage != null) {
                        context.addMessage(input.getClientId(context),
                                facesMessage);
                    }
                } else {
                    throw e;
                }
            }
        }
    }
}