gpt4 book ai didi

java - jaxb 和 jsr303

转载 作者:搜寻专家 更新时间:2023-10-31 20:06:34 24 4
gpt4 key购买 nike

我正在使用 jaxb 从配置中构建对象。到目前为止,我编写了用于验证的自定义函数,但我想进入注释。

例如:

@XmlElement
public void setNumber(Integer i){
if (i<10 || i>20) throw new IllegalArgumentException(...);
this.number=i;
}

上述方法的异常是描述性的,并为我提供了错误在 xml 中的位置。

我想进入这个:

@XmlElement
@Min(10)
@Max(20)
public void setNumber(Integer i){
this.number=i;
}

我可以通过读取 afterMarshal 中的注释并根据属性注释运行验证函数来验证这一点,但随后我丢失了发生错误的实际位置(在 xml 中)。

你有没有什么,我应该使用不同的方法/框架来解决这个问题吗?

编辑:澄清一下,我必须使用注释方法,因为我需要我正在编写的配置编辑器的属性约束元数据

最佳答案

这是我自己用来解决这个问题的 XJC 插件(在我的例子中,我需要注释来独立于 XML 模式进行验证,因为我也有 JMS 端点):

它的作用:

-它为不在xs默认模式中的对象生成@valid注解(所以注解是级联的)

-它为具有 MinOccur 值 >= 1 的对象或需要使用的属性生成 @NotNull 注释

-它为具有 minOccurs > 1 的列表生成@Size

-如果有 maxLength 或 minLength 限制,它生成@Size

-@DecimalMax 用于 maxInclusive 限制

-@DecimalMin 用于 minInclusive 限制

-@Digits 如果有 totalDigits 或 fractionDigits 限制。

-@Pattern 如果有Pattern限制

请注意,minExclusive 和 maxExclusive 限制被排除在外。

要使用它,您必须将类文件与内容为“com.sun.tools.xjc.addon.jaxb.JaxbValidationsPlugins”的 META-INF/services/com.sun.tools.xjc.Plugin 文件一起打包(即类的完全限定名称)并使用 -XValidate 开关调用 XJC。

实现起来并不难,但我希望它对某些人有用。源代码作为 TXT 文件附加。享受吧!

package com.sun.tools.xjc.addon.jaxb;

import java.lang.reflect.Field;
import java.math.BigInteger;
import java.util.Collections;
import java.util.List;

import javax.validation.Valid;
import javax.validation.constraints.DecimalMax;
import javax.validation.constraints.DecimalMin;
import javax.validation.constraints.Digits;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;
import javax.validation.constraints.Size;

import org.xml.sax.ErrorHandler;

import com.sun.codemodel.JAnnotationUse;
import com.sun.codemodel.JFieldVar;
import com.sun.tools.xjc.Options;
import com.sun.tools.xjc.Plugin;
import com.sun.tools.xjc.model.CAttributePropertyInfo;
import com.sun.tools.xjc.model.CElementPropertyInfo;
import com.sun.tools.xjc.model.CPropertyInfo;
import com.sun.tools.xjc.outline.ClassOutline;
import com.sun.tools.xjc.outline.FieldOutline;
import com.sun.tools.xjc.outline.Outline;
import com.sun.xml.xsom.XSComponent;
import com.sun.xml.xsom.XSSimpleType;
import com.sun.xml.xsom.impl.AttributeUseImpl;
import com.sun.xml.xsom.impl.ElementDecl;
import com.sun.xml.xsom.impl.ParticleImpl;

public class JaxbValidationsPlugins extends Plugin {
public String getOptionName() {
return "Xvalidate";
}

public List<String> getCustomizationURIs() {
return Collections.singletonList(namespace);
}

private String namespace = "http://jaxb.dev.java.net/plugin/code-injector";

public boolean isCustomizationTagName(String nsUri, String localName) {
return nsUri.equals(namespace) && localName.equals("code");
}

public String getUsage() {
return " -Xvalidate : inject Bean validation annotations (JSR 303)";
}

public boolean run(Outline model, Options opt, ErrorHandler errorHandler) {

try {

for (ClassOutline co : model.getClasses()) {

for (CPropertyInfo property : co.target.getProperties()) {
if (property instanceof CElementPropertyInfo) {
recorrePropiedad((CElementPropertyInfo) property, co, model);
} else if (property instanceof CAttributePropertyInfo) {
recorrePropiedad((CAttributePropertyInfo) property, co, model);
}
}
}

return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}

static int i = 0;

/**
* XS:Element
*
* @param property
* @param clase
* @param model
*/
public void recorrePropiedad(CElementPropertyInfo property, ClassOutline clase, Outline model) {
FieldOutline field = model.getField(property);
XSComponent definicion = property.getSchemaComponent();
ParticleImpl particle = (ParticleImpl) definicion;
int maxOccurs = ((BigInteger) getField("maxOccurs", particle)).intValue();
int minOccurs = ((BigInteger) getField("minOccurs", particle)).intValue();
JFieldVar var = (JFieldVar) clase.implClass.fields().get(getField("privateName", property));
if (minOccurs < 0 || minOccurs >= 1) {
if (!hasAnnotation(var, NotNull.class)) {
System.out.println("@NotNull: " + property.getName() + " de la clase " + clase.implClass.name());
var.annotate(NotNull.class);
}
}
if(maxOccurs>1){
if (!hasAnnotation(var, Size.class)) {
System.out.println("@Size ("+minOccurs+","+maxOccurs+") " + property.getName() + " de la clase " + clase.implClass.name());
var.annotate(Size.class).param("min", minOccurs).param("max", maxOccurs);
}
}

ElementDecl declaracion = (ElementDecl) getField("term", particle);
if (declaracion.getType().getTargetNamespace().startsWith("http://hotelbeds.com")) {
if (!hasAnnotation(var, Valid.class)) {
System.out.println("@Valid: " + property.getName() + " de la clase " + clase.implClass.name());
var.annotate(Valid.class);
}
}
if (declaracion.getType() instanceof XSSimpleType) {
procesaType((XSSimpleType) declaracion.getType(), var, property.getName(), clase.implClass.name());
} else if (declaracion.getType().getBaseType() instanceof XSSimpleType) {
procesaType((XSSimpleType) declaracion.getType().getBaseType(), var, property.getName(), clase.implClass.name());
}

// if(declaracion.getType() instanceof
// if(declaracion.getType().ge)
// procesaType(declaracion.getType().getBaseType(),var);
}

/**
* XS:Attribute
*
* @param property
* @param clase
* @param model
*/
public void recorrePropiedad(CAttributePropertyInfo property, ClassOutline clase, Outline model) {
FieldOutline field = model.getField(property);
System.out.println("Tratando attributo " + property.getName() + " de la clase " + clase.implClass.name());
XSComponent definicion = property.getSchemaComponent();
AttributeUseImpl particle = (AttributeUseImpl) definicion;
JFieldVar var = (JFieldVar) clase.implClass.fields().get(getField("privateName", property));
if (particle.isRequired()) {
if (!hasAnnotation(var, NotNull.class)) {
System.out.println("@NotNull: " + property.getName() + " de la clase " + clase.implClass.name());
var.annotate(NotNull.class);
}
}
if (particle.getDecl().getType().getTargetNamespace().startsWith("http://hotelbeds.com")) {
if (!hasAnnotation(var, Valid.class)) {
System.out.println("@Valid: " + property.getName() + " de la clase " + clase.implClass.name());
var.annotate(Valid.class);
}
}
procesaType(particle.getDecl().getType(), var, property.getName(), clase.implClass.name());
}

public void procesaType(XSSimpleType tipo, JFieldVar field, String campo, String clase) {
if (tipo.getFacet("maxLength") != null || tipo.getFacet("minLength") != null) {
Integer maxLength = tipo.getFacet("maxLength") == null ? null : parseInt(tipo.getFacet("maxLength").getValue().value);
Integer minLength = tipo.getFacet("minLength") == null ? null : parseInt(tipo.getFacet("minLength").getValue().value);
if (!hasAnnotation(field, Size.class)) {
System.out.println("@Size(" + minLength + "," + maxLength + "): " + campo + " de la clase " + clase);
field.annotate(Size.class).param("min", minLength).param("max", maxLength);
}
}
/*
* <bindings multiple="true" node=
* "//xs:complexType/.//xs:element[contains(@type,'IntPercentRestriction')]"
* > <annox:annotate> <annox:annotate
* annox:class="javax.validation.constraints.Digits" integer="3"
* fraction="2" /> <annox:annotate
* annox:class="javax.validation.constraints.Min" value="-100" />
* value="100" /> </annox:annotate> </bindings>
*//*
* <xs:restriction base="xs:decimal"> <xs:fractionDigits value="2"/>
* <xs:maxInclusive value="100.00"/> <xs:minInclusive
* value="-100.00"/> <xs:totalDigits value="5"/> </xs:restriction>
*/
if (tipo.getFacet("maxInclusive") != null && tipo.getFacet("maxInclusive").getValue().value != null && !hasAnnotation(field,DecimalMax.class)){
System.out.println("@DecimalMax(" + tipo.getFacet("maxInclusive").getValue().value + "): " + campo + " de la clase " + clase);
field.annotate(DecimalMax.class).param("value", tipo.getFacet("maxInclusive").getValue().value);
}
if (tipo.getFacet("minInclusive") != null && tipo.getFacet("minInclusive").getValue().value != null && !hasAnnotation(field,DecimalMin.class)){
System.out.println("@DecimalMin(" + tipo.getFacet("minInclusive").getValue().value + "): " + campo + " de la clase " + clase);
field.annotate(DecimalMin.class).param("value", tipo.getFacet("minInclusive").getValue().value);
}
if (tipo.getFacet("totalDigits") != null) {
Integer totalDigits = tipo.getFacet("totalDigits") == null ? null : parseInt(tipo.getFacet("totalDigits").getValue().value);
int fractionDigits = tipo.getFacet("fractionDigits") == null ? 0 : parseInt(tipo.getFacet("fractionDigits").getValue().value);
if (!hasAnnotation(field, Digits.class)) {
System.out.println("@Digits(" + totalDigits + "," + fractionDigits + "): " + campo + " de la clase " + clase);
JAnnotationUse annox = field.annotate(Digits.class).param("integer", (totalDigits - fractionDigits));
if (tipo.getFacet("fractionDigits") != null) {
annox.param("fraction", fractionDigits);
}
}
}
/**
* <annox:annotate annox:class="javax.validation.constraints.Pattern"
message="Name can only contain capital letters, numbers and the simbols '-', '_', '/', ' '"
regexp="^[A-Z0-9_\s//-]*" />
*/
if(tipo.getFacet("pattern")!=null){
System.out.println("@Pattern(" +tipo.getFacet("pattern").getValue().value+ "): " + campo + " de la clase " + clase);
if (!hasAnnotation(field, Pattern.class)) {
field.annotate(Pattern.class).param("regexp", tipo.getFacet("pattern").getValue().value);
}

}

}

@SuppressWarnings({ "unchecked", "rawtypes" })
public boolean hasAnnotation(JFieldVar var, Class anotacion) {
List<JAnnotationUse> lista = (List<JAnnotationUse>) getField("annotations", var);
if (lista != null) {
for (JAnnotationUse uso : lista) {
if (((Class) getField("clazz._class", uso)).getCanonicalName().equals(anotacion.getCanonicalName())) {
return true;
}
}
}
return false;
}


private Integer parseInt(String valor) {
try {

Integer i = Integer.parseInt(valor);
if (i < 2147483647 && i > -2147483648) {
return i;
}
} catch (Exception e) {
try{
return (int)Math.round(Double.parseDouble(valor));

}catch(Exception ex){
;
}

}
return null;

}

/*
private Long parseLong(String valor) {
try {
Long i = Long.parseLong(valor);
if (i < 2147483647 && i > -2147483648) {
return i;
}
} catch (Exception e) {
return Math.round(Double.parseDouble(valor));
}
return null;

}
*/
private Object getField(String path, Object oo) {
try {
if (path.contains(".")) {
String field = path.substring(0, path.indexOf("."));
Field campo = oo.getClass().getDeclaredField(field);
campo.setAccessible(true);
Object result = campo.get(oo);
return getField(path.substring(path.indexOf(".") + 1), result);
} else {
Field campo = getSimpleField(path, oo.getClass());
campo.setAccessible(true);
return campo.get(oo);
}
} catch (Exception e) {
System.out.println("Field " + path + " not found on " + oo.getClass().getName());
}
return null;
}

private static Field getSimpleField(String fieldName, Class<?> clazz) {
Class<?> tmpClass = clazz;
try {
do {
for (Field field : tmpClass.getDeclaredFields()) {
String candidateName = field.getName();
if (!candidateName.equals(fieldName)) {
continue;
}
field.setAccessible(true);
return field;
}
tmpClass = tmpClass.getSuperclass();
} while (clazz != null);
} catch (Exception e) {
System.out.println("Field '" + fieldName + "' not found on class " + clazz);
}
return null;
}
}

关于java - jaxb 和 jsr303,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5063713/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com