2011-06-09 19 views
15

Quiero validar una cadena con un conjunto de valores utilizando la anotación. Lo que quiero es básicamente estoValidación de cadenas de Java utilizando valores de enum y anotación

@ValidateString(enumClass=com.co.enum) 
String dataType; 

int maxValue; 
int minValue; 
int precision; 

o

@ValidateString(values={"String","Boolean", "Integer"}) 
String dataType; 

int maxValue; 
int minValue; 
int precision; 

También quiero hacer algo de validación de otras variables, dependiendo del valor establecido en tipoDatos,

si (tipo de datos = "String ") maxValue, minValue, precisión, todos deben ser nulos o cero.

No puedo pensar en una forma de lograr esto mediante anotaciones personalizadas .. . .

Alguien por favor me ayude a

+0

¿Cuál es el "negocio" real necesita? ¿Qué está tratando de resolver? (Estoy seguro de que en realidad no necesitas hacer esto exactamente; esta es solo una forma de hacer algo) – Bohemian

Respuesta

16

Esto es lo que hice.

anotación

public @interface ValidateString { 

    String[] acceptedValues(); 

    String message() default "{uk.dds.ideskos.validator.ValidateString.message}"; 

    Class<?>[] groups() default { }; 

    Class<? extends Payload>[] payload() default { }; 
} 

Validación Clase

public class StringValidator implements ConstraintValidator<ValidateString, String>{ 

    private List<String> valueList; 

    @Override 
    public void initialize(ValidateString constraintAnnotation) { 
     valueList = new ArrayList<String>(); 
     for(String val : constraintAnnotation.acceptedValues()) { 
      valueList.add(val.toUpperCase()); 
     } 
    } 

    @Override 
    public boolean isValid(String value, ConstraintValidatorContext context) { 
     if(!valueList.contains(value.toUpperCase())) { 
      return false; 
     } 
     return true; 
    } 

} 

Y lo utilicé como

@ValidateString(acceptedValues={"Integer", "String"}, message="Invalid dataType") 
String dataType; 

Long maxValue; 
Long minValue; 

Ahora tengo que encontrar la manera de poner en práctica comprobación condicional decir. si String, entonces maxValue y minValue deben ser nulos o cero ...

¿Alguna idea?

+0

La mayor desventaja es que si la enumeración cambia, esta anotación se olvida rápidamente. ¿No hay una forma de asignar esto a los valores de la enumeración? –

8

Zanja la representación de cadena, y hacer una enumeración real.

public enum DataType { 
    STRING, 
    BOOLEAN, 
    INTEGER; 
} 

De esta manera se evita la vez tener que hacer la comparación de cadenas de la String dataType variable anterior para determinar si está en la enumeración. Por otro lado, también hace que sea imposible asignar un valor no válido a la variable miembro dataType y dado que las enumeraciones están garantizadas como singleton dentro del cargador de clases, también ahorra espacio en la memoria.

Vale la pena el esfuerzo de cambiar el código para usar enumeraciones. Sin embargo, suponiendo que no puede, al menos puede cambiar la anotación para usar enumeraciones.

@ValidateString(DataType.STRING) String dataType; 

y de esa manera su ValidateString anotación al menos llega a beneficiarse de las enumeraciones, aunque el resto del código no lo hace.

Ahora, con la muy rara posibilidad de que no pueda usar una enumeración, puede establecer enteros públicos estáticos, que mapean cada valor aceptado.

public class DataType { 
    public static final int STRING = 1; 
    public static final int BOOLEAN = 2; 
    ... 
} 

Sin embargo, si se utiliza una cadena para el parámetro de anotación, no tenemos un sistema de comprobación de tipos que se extiende en el tipo de especificar que sólo los valores particulares están permitidos. En otras palabras, Java no tiene la capacidad de hacer algo como esto:

public int<values=[1,3,5,7..9]> oddInt; 

que un error si se ha intentado asignar

oddInt = 4; 

¿Por qué es esto importante? Porque si no se aplica a Java normal, entonces no se puede aplicar a la enumeración que se implementa en clases regulares de Java.

+0

"Elimina la representación de String, y haz una enumeración real". Este es realmente el peor consejo para la validación de entrada del usuario ... Con una solicitud HTTP, por ejemplo, el usuario siempre envía una cadena. Si el valor es incorrecto, el usuario espera obtener un mensaje correcto (por ejemplo, dataType no coincide con ningún valor conocido. Utilice uno de ...) y no 400 MALA PETICIÓN, lo que ocurriría con una enumeración real –

+0

Un método estático simple en el enum 'valueForString (...)' devolvería el valor de Enum, o null si no hubiera ninguno (debido a un error tipográfico, por ejemplo). Centraliza la validación de la entrada, y lo hace en el lugar donde se definen las entradas. Y no seamos demasiado dramáticos. Este no es el peor consejo, ya que ambos podemos soñar con consejos mucho peores. –

9

Así que aquí es el código de validación usando siendo la primavera y funciona muy bien para mí. El código completo se proporciona a continuación.

import java.lang.annotation.Documented; 
import java.lang.annotation.ElementType; 
import java.lang.annotation.Retention; 
import java.lang.annotation.RetentionPolicy; 
import java.lang.annotation.Target; 

import javax.validation.Constraint; 
import javax.validation.Payload; 
import javax.validation.ReportAsSingleViolation; 
import javax.validation.constraints.NotNull; 

@Documented 
@Constraint(validatedBy = EnumValidatorImpl.class) 
@Retention(RetentionPolicy.RUNTIME) 
@Target(ElementType.FIELD) 
@NotNull(message = "Value cannot be null") 
@ReportAsSingleViolation 
public @interface EnumValidator { 

    Class<? extends Enum<?>> enumClazz(); 

    String message() default "Value is not valid"; 

    Class<?>[] groups() default {}; 

    Class<? extends Payload>[] payload() default {}; 

} 

Implementación de la clase anterior:

import java.util.ArrayList; 
import java.util.List; 

import javax.validation.ConstraintValidator; 
import javax.validation.ConstraintValidatorContext; 

public class EnumValidatorImpl implements ConstraintValidator<EnumValidator, String> { 

    List<String> valueList = null; 

    @Override 
    public boolean isValid(String value, ConstraintValidatorContext context) { 
    if(!valueList.contains(value.toUpperCase())) { 
     return false; 
    } 
    return true; 
    } 

    @Override 
    public void initialize(EnumValidator constraintAnnotation) { 
    valueList = new ArrayList<String>(); 
    Class<? extends Enum<?>> enumClass = constraintAnnotation.enumClazz(); 

    @SuppressWarnings("rawtypes") 
    Enum[] enumValArr = enumClass.getEnumConstants(); 

    for(@SuppressWarnings("rawtypes") 
    Enum enumVal : enumValArr) { 
     valueList.add(enumVal.toString().toUpperCase()); 
    } 

    } 

} 

USO DE ARRIBA La anotación es muy simple

@JsonProperty("lead_id") 
    @EnumValidator(enumClazz=DefaultEnum.class,message="This error is coming from the enum class", groups = {Group1.class }) 
    private String leadId; 
+0

Gran solución .. –

+1

Hola, ¿dónde se inicializaron los grupos? – Sofiane

Cuestiones relacionadas