#2169 Refactor after #2170 tidy javax/jakarta validation annotation reading (#2171)

Introduces ReadValidationAnnotations with javax and jakarta implementations and moves the validation annotation reading there
This commit is contained in:
Rob Bygrave
2021-02-17 22:23:07 +13:00
committed by GitHub
parent 3bb4126e26
commit b4ae721998
12 changed files with 182 additions and 147 deletions
@@ -34,7 +34,6 @@ import javax.persistence.EmbeddedId;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.Version;
import javax.validation.constraints.Size;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Type;
@@ -1140,24 +1139,6 @@ public class DeployBeanProperty {
return result;
}
public List<Size> getMetaAnnotationJavaxSize() {
final List<Size> size = getMetaAnnotations(Size.class);
final List<Size.List> lists = getMetaAnnotations(Size.List.class);
for (Size.List list : lists) {
Collections.addAll(size, list.value());
}
return size;
}
public List<jakarta.validation.constraints.Size> getMetaAnnotationJakartaSize() {
final List<jakarta.validation.constraints.Size> size = getMetaAnnotations(jakarta.validation.constraints.Size.class);
final List<jakarta.validation.constraints.Size.List> lists = getMetaAnnotations(jakarta.validation.constraints.Size.List.class);
for (jakarta.validation.constraints.Size.List list : lists) {
Collections.addAll(size, list.value());
}
return size;
}
public Formula getMetaAnnotationFormula(Platform platform) {
Formula fallback = null;
for (Annotation ann : metaAnnotations) {
@@ -26,7 +26,6 @@ import javax.persistence.JoinTable;
import javax.persistence.ManyToOne;
import javax.persistence.OneToOne;
import javax.persistence.PrimaryKeyJoinColumn;
import javax.validation.constraints.NotNull;
/**
* Read the deployment annotations for Associated One beans.
@@ -115,21 +114,10 @@ public class AnnotationAssocOnes extends AnnotationAssoc {
if (nonNull != null) {
prop.setNullable(false);
}
if (javaxValidationAnnotations) {
NotNull notNull = get(prop, NotNull.class);
if (notNull != null && isEbeanValidationGroups(notNull.groups())) {
prop.setNullable(false);
// overrides optional attribute of ManyToOne etc
prop.getTableJoin().setType(SqlJoinType.INNER);
}
}
if (jakartaValidationAnnotations) {
jakarta.validation.constraints.NotNull notNull = get(prop, jakarta.validation.constraints.NotNull.class);
if (notNull != null && isEbeanValidationGroups(notNull.groups())) {
prop.setNullable(false);
// overrides optional attribute of ManyToOne etc
prop.getTableJoin().setType(SqlJoinType.INNER);
}
if (readConfig.isValidationNotNull(prop)) {
// overrides optional attribute of ManyToOne etc
prop.setNullable(false);
prop.getTableJoin().setType(SqlJoinType.INNER);
}
// check for manually defined joins
@@ -69,8 +69,6 @@ import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.persistence.Transient;
import javax.persistence.Version;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import java.sql.Types;
import java.util.Set;
import java.util.UUID;
@@ -258,48 +256,19 @@ public class AnnotationFields extends AnnotationParser {
}
private void initValidation(DeployBeanProperty prop) {
if (javaxValidationAnnotations) {
NotNull notNull = get(prop, NotNull.class);
if (notNull != null && isEbeanValidationGroups(notNull.groups())) {
// Not null on all validation groups so enable
// DDL generation of Not Null Constraint
prop.setNullable(false);
}
if (readConfig.isValidationNotNull(prop)) {
prop.setNullable(false);
}
if (jakartaValidationAnnotations) {
jakarta.validation.constraints.NotNull notNull = get(prop, jakarta.validation.constraints.NotNull.class);
if (notNull != null && isEbeanValidationGroups(notNull.groups())) {
// Not null on all validation groups so enable
// DDL generation of Not Null Constraint
prop.setNullable(false);
}
}
if (!prop.isLob()) {
// take the max size of all @Size annotations
int maxSize = -1;
if (javaxValidationAnnotations) {
for (Size size : prop.getMetaAnnotationJavaxSize()) {
if (size.max() < Integer.MAX_VALUE) {
maxSize = Math.max(maxSize, size.max());
}
}
}
if (jakartaValidationAnnotations) {
for (jakarta.validation.constraints.Size size : prop.getMetaAnnotationJakartaSize()) {
if (size.max() < Integer.MAX_VALUE) {
maxSize = Math.max(maxSize, size.max());
}
}
}
if (maxSize != -1) {
int maxSize = readConfig.maxValidationSize(prop);
if (maxSize > 0) {
prop.setDbLength(maxSize);
}
}
}
private void initTenantId(DeployBeanProperty prop) {
if (javaxValidationAnnotations || jakartaValidationAnnotations) {
if (readConfig.checkValidationAnnotations()) {
initValidation(prop);
}
if (has(prop, TenantId.class)) {
@@ -9,7 +9,6 @@ import io.ebeaninternal.server.deploy.meta.DeployBeanPropertyAssocOne;
import javax.persistence.AttributeOverride;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.validation.groups.Default;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
@@ -26,17 +25,11 @@ public abstract class AnnotationParser extends AnnotationBase {
final Class<?> beanType;
final boolean javaxValidationAnnotations;
final boolean jakartaValidationAnnotations;
final ReadAnnotationConfig readConfig;
AnnotationParser(DeployBeanInfo<?> info, ReadAnnotationConfig readConfig) {
super(info.getUtil());
this.readConfig = readConfig;
this.javaxValidationAnnotations = readConfig.isJavaxValidationAnnotations();
this.jakartaValidationAnnotations = readConfig.isJakartaValidationAnnotations();
this.info = info;
this.beanType = info.getDescriptor().getBeanType();
this.descriptor = info.getDescriptor();
@@ -130,17 +123,6 @@ public abstract class AnnotationParser extends AnnotationBase {
}
}
/**
* Return true if the validation groups are {@link Default} (respectively empty)
* can be applied to DDL generation.
*/
boolean isEbeanValidationGroups(Class<?>[] groups) {
if (!util.isUseValidationNotNull()) {
return false;
}
return groups.length == 0 || groups.length == 1 && Default.class.isAssignableFrom(groups[0]);
}
String[] convertColumnNames(String[] columnNames) {
for (int i = 0; i < columnNames.length; i++) {
columnNames[i] = databasePlatform.convertQuotedIdentifiers(columnNames[i]);
@@ -1,11 +0,0 @@
package io.ebeaninternal.server.deploy.parse;
import jakarta.validation.constraints.Size;
class InitMetaJakartaValidationAnnotation {
static void init(ReadAnnotationConfig readConfig) {
readConfig.addMetaAnnotation(Size.class);
readConfig.addMetaAnnotation(Size.List.class);
}
}
@@ -1,11 +0,0 @@
package io.ebeaninternal.server.deploy.parse;
import javax.validation.constraints.Size;
class InitMetaJavaxValidationAnnotation {
static void init(ReadAnnotationConfig readConfig) {
readConfig.addMetaAnnotation(Size.class);
readConfig.addMetaAnnotation(Size.List.class);
}
}
@@ -3,8 +3,10 @@ package io.ebeaninternal.server.deploy.parse;
import io.ebean.annotation.Aggregation;
import io.ebean.annotation.Formula;
import io.ebean.annotation.Where;
import io.ebean.config.ClassLoadConfig;
import io.ebean.config.DatabaseConfig;
import io.ebeaninternal.server.deploy.generatedproperty.GeneratedPropertyFactory;
import io.ebeaninternal.server.deploy.meta.DeployBeanProperty;
import javax.persistence.Column;
import java.util.HashSet;
@@ -24,7 +26,9 @@ class ReadAnnotationConfig {
private final boolean jakartaValidationAnnotations;
private final boolean jacksonAnnotations;
private final boolean idGeneratorAutomatic;
private final boolean useValidationNotNull;
private final ReadValidationAnnotations javaxValidation;
private final ReadValidationAnnotations jakartaValidation;
private final Set<Class<?>> metaAnnotations = new HashSet<>();
ReadAnnotationConfig(GeneratedPropertyFactory generatedPropFactory, String asOfViewSuffix, String versionsBetweenSuffix, DatabaseConfig config) {
@@ -34,21 +38,32 @@ class ReadAnnotationConfig {
this.disableL2Cache = config.isDisableL2Cache();
this.eagerFetchLobs = config.isEagerFetchLobs();
this.idGeneratorAutomatic = config.isIdGeneratorAutomatic();
this.javaxValidationAnnotations = generatedPropFactory.getClassLoadConfig().isJavaxValidationAnnotationsPresent();
this.jakartaValidationAnnotations = generatedPropFactory.getClassLoadConfig().isJakartaValidationAnnotationsPresent();
this.jacksonAnnotations = generatedPropFactory.getClassLoadConfig().isJacksonAnnotationsPresent();
this.useValidationNotNull = config.isUseValidationNotNull();
ClassLoadConfig classLoadConfig = generatedPropFactory.getClassLoadConfig();
this.javaxValidationAnnotations = classLoadConfig.isJavaxValidationAnnotationsPresent();
this.jakartaValidationAnnotations = classLoadConfig.isJakartaValidationAnnotationsPresent();
this.jacksonAnnotations = classLoadConfig.isJacksonAnnotationsPresent();
this.metaAnnotations.add(Column.class);
this.metaAnnotations.add(Formula.class);
this.metaAnnotations.add(Formula.List.class);
this.metaAnnotations.add(Where.class);
this.metaAnnotations.add(Where.List.class);
this.metaAnnotations.add(Aggregation.class);
this.javaxValidation = javaxValidationAnnotations ? new ReadValidationAnnotationsJavax(this) : null;
this.jakartaValidation = jakartaValidationAnnotations ? new ReadValidationAnnotationsJakarta(this) : null;
if (jacksonAnnotations) {
InitMetaJacksonAnnotation.init(this);
}
}
public void addMetaAnnotation(Class<?> annotation) {
void addMetaAnnotation(Class<?> annotation) {
metaAnnotations.add(annotation);
}
boolean checkValidationAnnotations() {
return javaxValidationAnnotations || jakartaValidationAnnotations;
}
GeneratedPropertyFactory getGeneratedPropFactory() {
return generatedPropFactory;
}
@@ -73,14 +88,6 @@ class ReadAnnotationConfig {
return idGeneratorAutomatic;
}
boolean isJavaxValidationAnnotations() {
return javaxValidationAnnotations;
}
boolean isJakartaValidationAnnotations() {
return jakartaValidationAnnotations;
}
boolean isJacksonAnnotations() {
return jacksonAnnotations;
}
@@ -88,4 +95,35 @@ class ReadAnnotationConfig {
public Set<Class<?>> getMetaAnnotations() {
return metaAnnotations;
}
/**
* Return true if a NotNull validation annotation is on the property.
*/
boolean isValidationNotNull(DeployBeanProperty property) {
if (!useValidationNotNull) {
return false;
}
if (javaxValidation != null && javaxValidation.isValidationNotNull(property)) {
return true;
}
if (jakartaValidation != null && jakartaValidation.isValidationNotNull(property)) {
return true;
}
return false;
}
/**
* Return the max size of all validation @Size annotations.
*/
int maxValidationSize(DeployBeanProperty prop) {
int maxSize = 0;
if (javaxValidation != null) {
maxSize = Math.max(maxSize, javaxValidation.maxSize(prop));
}
if (jakartaValidation != null) {
maxSize = Math.max(maxSize, jakartaValidation.maxSize(prop));
}
return maxSize;
}
}
@@ -14,15 +14,6 @@ public class ReadAnnotations {
public ReadAnnotations(GeneratedPropertyFactory generatedPropFactory, String asOfViewSuffix, String versionsBetweenSuffix, DatabaseConfig config) {
this.readConfig = new ReadAnnotationConfig(generatedPropFactory, asOfViewSuffix, versionsBetweenSuffix, config);
if (readConfig.isJavaxValidationAnnotations()) {
InitMetaJavaxValidationAnnotation.init(readConfig);
}
if (readConfig.isJakartaValidationAnnotations()) {
InitMetaJakartaValidationAnnotation.init(readConfig);
}
if (readConfig.isJacksonAnnotations()) {
InitMetaJacksonAnnotation.init(readConfig);
}
}
/**
@@ -0,0 +1,19 @@
package io.ebeaninternal.server.deploy.parse;
import io.ebeaninternal.server.deploy.meta.DeployBeanProperty;
/**
* Reads validation NotNull and Size annotations for mapping.
*/
interface ReadValidationAnnotations {
/**
* Return true if the property has a NotNull validation annotation.
*/
boolean isValidationNotNull(DeployBeanProperty property);
/**
* Return the max value of the Size validation annotations on the property.
*/
int maxSize(DeployBeanProperty property);
}
@@ -0,0 +1,51 @@
package io.ebeaninternal.server.deploy.parse;
import io.ebean.util.AnnotationUtil;
import io.ebeaninternal.server.deploy.meta.DeployBeanProperty;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import jakarta.validation.groups.Default;
import java.util.Collections;
import java.util.List;
/**
* Jakarta validation annotations reader.
*/
class ReadValidationAnnotationsJakarta implements ReadValidationAnnotations {
ReadValidationAnnotationsJakarta(ReadAnnotationConfig readConfig) {
readConfig.addMetaAnnotation(Size.class);
readConfig.addMetaAnnotation(Size.List.class);
}
@Override
public boolean isValidationNotNull(DeployBeanProperty property) {
NotNull notNull = AnnotationUtil.get(property.getField(), NotNull.class);
return (notNull != null && isEbeanValidationGroups(notNull.groups()));
}
private boolean isEbeanValidationGroups(Class<?>[] groups) {
return groups.length == 0 || groups.length == 1 && Default.class.isAssignableFrom(groups[0]);
}
@Override
public int maxSize(DeployBeanProperty property) {
int maxSize = 0;
for (Size size : getMetaAnnotationJavaxSize(property)) {
if (size.max() < Integer.MAX_VALUE) {
maxSize = Math.max(maxSize, size.max());
}
}
return maxSize;
}
private List<Size> getMetaAnnotationJavaxSize(DeployBeanProperty prop) {
final List<Size> size = prop.getMetaAnnotations(Size.class);
final List<Size.List> lists = prop.getMetaAnnotations(Size.List.class);
for (Size.List list : lists) {
Collections.addAll(size, list.value());
}
return size;
}
}
@@ -0,0 +1,52 @@
package io.ebeaninternal.server.deploy.parse;
import io.ebean.util.AnnotationUtil;
import io.ebeaninternal.server.deploy.meta.DeployBeanProperty;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import javax.validation.groups.Default;
import java.util.Collections;
import java.util.List;
/**
* Javax validation annotations reader.
*/
class ReadValidationAnnotationsJavax implements ReadValidationAnnotations {
ReadValidationAnnotationsJavax(ReadAnnotationConfig readConfig) {
readConfig.addMetaAnnotation(Size.class);
readConfig.addMetaAnnotation(Size.List.class);
}
@Override
public boolean isValidationNotNull(DeployBeanProperty property) {
NotNull notNull = AnnotationUtil.get(property.getField(), NotNull.class);
return (notNull != null && isEbeanValidationGroups(notNull.groups()));
}
private boolean isEbeanValidationGroups(Class<?>[] groups) {
return groups.length == 0 || groups.length == 1 && Default.class.isAssignableFrom(groups[0]);
}
@Override
public int maxSize(DeployBeanProperty prop) {
int maxSize = 0;
for (Size size : getMetaAnnotationJavaxSize(prop)) {
if (size.max() < Integer.MAX_VALUE) {
maxSize = Math.max(maxSize, size.max());
}
}
return maxSize;
}
private List<Size> getMetaAnnotationJavaxSize(DeployBeanProperty prop) {
final List<Size> size = prop.getMetaAnnotations(Size.class);
final List<Size.List> lists = prop.getMetaAnnotations(Size.List.class);
for (Size.List list : lists) {
Collections.addAll(size, list.value());
}
return size;
}
}