Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Alternativa para o Validator no VRaptor, este incluir um mapa dos erros no request e não uma lista como é feito no DefaultValidator.
package br.com.fredericci.validation;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import br.com.caelum.vraptor.Result;
import br.com.caelum.vraptor.View;
import br.com.caelum.vraptor.core.Localization;
import br.com.caelum.vraptor.ioc.Component;
import br.com.caelum.vraptor.ioc.RequestScoped;
import br.com.caelum.vraptor.proxy.Proxifier;
import br.com.caelum.vraptor.util.test.MockResult;
import br.com.caelum.vraptor.validator.AbstractValidator;
import br.com.caelum.vraptor.validator.BeanValidator;
import br.com.caelum.vraptor.validator.DefaultValidator;
import br.com.caelum.vraptor.validator.I18nMessage;
import br.com.caelum.vraptor.validator.Message;
import br.com.caelum.vraptor.validator.Outjector;
import br.com.caelum.vraptor.validator.Validations;
import br.com.caelum.vraptor.view.ValidationViewsFactory;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimap;
/**
* Implementacao alternativa do validator para adicionar um mapa com os erros
* ocorridos no request
*
* @author dennys
*
*/
@Component
@RequestScoped
public class Validator extends AbstractValidator {
private static final Logger logger = LoggerFactory.getLogger(DefaultValidator.class);
private final Result result;
private final List<Message> errors = new ArrayList<Message>();
private final ValidationViewsFactory viewsFactory;
private final List<BeanValidator> beanValidators;
private final Outjector outjector;
private final Proxifier proxifier;
private final Localization localization;
public Validator(Result result, ValidationViewsFactory factory, Outjector outjector, Proxifier proxifier, List<BeanValidator> beanValidators, Localization localization) {
this.result = result;
this.viewsFactory = factory;
this.outjector = outjector;
this.proxifier = proxifier;
this.beanValidators = beanValidators;
this.localization = localization;
}
public void checking(Validations validations) {
addAll(validations.getErrors(localization.getBundle()));
}
public void validate(Object object) {
if (beanValidators == null || beanValidators.isEmpty()) {
logger.warn("has no validators registered");
} else {
for (BeanValidator validator : beanValidators) {
addAll(validator.validate(object));
}
}
}
public <T extends View> T onErrorUse(Class<T> view) {
if (!hasErrors()) {
return new MockResult(proxifier).use(view); // ignore anything, no
// errors occurred
}
result.include("errors", errors);
result.include("errorsMap", toMap(errors));
outjector.outjectRequestMap();
return viewsFactory.instanceFor(view, errors);
}
private Multimap<String, String> toMap(List<Message> errorsList) {
Multimap<String, String> errorsMap = HashMultimap.create();
for (Message message : errorsList) {
errorsMap.put(message.getCategory(), message.getMessage());
}
return errorsMap;
}
public void addAll(Collection<? extends Message> messages) {
for (Message message : messages) {
add(message);
}
}
public void add(Message message) {
if (message instanceof I18nMessage && !((I18nMessage) message).hasBundle()) {
((I18nMessage) message).setBundle(localization.getBundle());
}
this.errors.add(message);
}
public boolean hasErrors() {
return !errors.isEmpty();
}
public List<Message> getErrors() {
return Collections.unmodifiableList(this.errors);
}
}
@lucascs
Copy link

lucascs commented Jan 13, 2012

vc tinha esquecido o link no tweet ;)

então, tem dois problemas com isso

  • os códigos atuais parariam de funcionar
  • como as chaves são as categorias, eu não conseguiria mostrar dois erros pro mesmo campo

talvez fosse legal ter algo como errors e errorMap no request, um com a lista atual e outra como esse mapa.

@dennysfredericci
Copy link
Author

dennysfredericci commented Jan 13, 2012

Hehehe nem tinha percebido a falta do link! que cabeça! Só fiquei curioso... como encontrou o link? hahaha

1 - os códigos atuais parariam de funcionar: Ok, isso eu ja estava prevendo.

2 - como as chaves são as categorias, eu não conseguiria mostrar dois erros pro mesmo campo: Não cheguei a pensar nisso... :( ... Humm.. talvez uma solucao seria ter uma lista ou um array de strings como valor no mapa....

Troquei a implementação padrão por mapa porque achei simples usar: ${errors['categoria']}

@lucascs
Copy link

lucascs commented Jan 13, 2012

Digamos que (quase) tudo que o google indexa e tem a palavra VRaptor, eu recebo uma notificação ;)

dá uma olhada no Guava, a classe Multimap. Já é dependência do VRaptor e já faz o que vc quer.

@dennysfredericci
Copy link
Author

dennysfredericci commented Feb 2, 2012

Bacana a idéia do Multimap! Acho que para ficar bom só faltaria uma taglib ou algo do genero para deixar o jsp limpo...

algo do tipo:

<v:errors category="categoria" />

@dennysfredericci
Copy link
Author

dennysfredericci commented Feb 3, 2012

@lucascs
Copy link

lucascs commented Feb 3, 2012

Bem legal!

mas com essa taglib, dá pra fazer usando a List mesmo, certo?

@dennysfredericci
Copy link
Author

dennysfredericci commented Feb 3, 2012

Hum! Verdade nem tinha pensado nisso!

A implementação vai ficar mais simples também! Acabei de atualizar la....

@lucascs
Copy link

lucascs commented Feb 3, 2012

Agora sim =)

tweet?

manda lá pro vraptor-contrib, plz
https://github.com/caelum/vraptor-contrib

[]'s

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment