package br.com.caelum.stella.faces.validation; import java.util.List; import java.util.ResourceBundle; import javax.el.ValueExpression; import javax.faces.application.FacesMessage; import javax.faces.component.StateHolder; import javax.faces.component.UIComponent; import javax.faces.component.ValueHolder; import javax.faces.context.FacesContext; import javax.faces.validator.FacesValidator; import javax.faces.validator.Validator; import javax.faces.validator.ValidatorException; import br.com.caelum.stella.ResourceBundleMessageProducer; import br.com.caelum.stella.ValidationMessage; import br.com.caelum.stella.type.Estado; import br.com.caelum.stella.validation.InvalidStateException; import br.com.caelum.stella.validation.RejectAllValidator; import br.com.caelum.stella.validation.error.IEError; /** * Caso ocorra algum erro de validação, todas as mensagens serão enfileiradas no * FacesContext e associadas ao elemento inválido. * * @author Leonardo Bessa */ @FacesValidator(StellaIEValidator.VALIDATOR_ID) public class StellaIEValidator implements Validator, StateHolder { /** * Identificador do Validador JSF. */ public static final String VALIDATOR_ID = "StellaIEValidator"; private final ResourceBundleFinder resourceBundleFinder = new ResourceBundleFinder(); private boolean formatted = false; private String estadoComponentId; private String estado; private boolean transientValue = false; private ValueExpression binding; public void validate(final FacesContext facesContext, final UIComponent uiComponent, final Object value) throws ValidatorException { ResourceBundle bundle = resourceBundleFinder.getForCurrentLocale(facesContext); ResourceBundleMessageProducer producer = new ResourceBundleMessageProducer(bundle); try { br.com.caelum.stella.validation.Validator<String> validator; try { String estadoValue; if (estado == null) { ValueHolder estadoValueHolder = (ValueHolder) facesContext.getViewRoot().findComponent( estadoComponentId); estadoValue = estadoValueHolder.getValue().toString(); } else { estadoValue = estado; } validator = Estado.valueOf(estadoValue).getIEValidator(producer, formatted); } catch (Exception ex) { validator = new RejectAllValidator<String>(producer, IEError.UNDEFINED_STATE); } validator.assertValid(value.toString()); } catch (InvalidStateException e) { List<ValidationMessage> messages = e.getInvalidMessages(); String firstErrorMessage = messages.get(0).getMessage(); registerAllMessages(facesContext, uiComponent, messages.subList(1, messages.size())); throw new ValidatorException(new FacesMessage(firstErrorMessage)); } } private void registerAllMessages(final FacesContext facesContext, final UIComponent uiComponent, final List<ValidationMessage> messages) { for (ValidationMessage message : messages) { String componentId = uiComponent.getClientId(facesContext); facesContext.addMessage(componentId, new FacesMessage(message.getMessage())); } } /** * Atribui se a regra de validação deve considerar, ou não, a cadeia no * formato do documento. * * @param formatted * caso seja <code>true</code> o validador considera que a cadeia * está formatada; caso contrário, considera que a cadeia contém * apenas dígitos numéricos. */ public void setFormatted(final boolean formatted) { this.formatted = formatted; } public void setEstadoComponentId(final String estadoComponentId) { this.estadoComponentId = estadoComponentId; } public String getEstado() { return estado; } public void setEstado(final String estado) { this.estado = estado; } public Object saveState(final FacesContext context) { Object values[] = new Object[4]; values[0] = estadoComponentId; values[1] = formatted; values[2] = estado; values[3] = binding; return values; } public void restoreState(final FacesContext context, final Object state) { Object values[] = (Object[]) state; estadoComponentId = (String) values[0]; formatted = (Boolean) values[1]; estado = (String) values[2]; binding = (ValueExpression) values[3]; if (binding != null) { binding.setValue(context.getELContext(), this); } } public boolean isTransient() { return transientValue; } public void setTransient(final boolean transientValue) { this.transientValue = transientValue; } public void setBinding(final ValueExpression binding) { this.binding = binding; } }