Compare commits

..

11 Commits

11 changed files with 286 additions and 310 deletions

View File

@ -3,7 +3,7 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>kangaroo-and-rabbit</groupId> <groupId>kangaroo-and-rabbit</groupId>
<artifactId>archidata</artifactId> <artifactId>archidata</artifactId>
<version>0.22.0</version> <version>0.23.0</version>
<properties> <properties>
<java.version>21</java.version> <java.version>21</java.version>
<maven.compiler.version>3.1</maven.compiler.version> <maven.compiler.version>3.1</maven.compiler.version>

View File

@ -41,6 +41,24 @@ import jakarta.ws.rs.DefaultValue;
public class AnnotationTools { public class AnnotationTools {
static final Logger LOGGER = LoggerFactory.getLogger(AnnotationTools.class); static final Logger LOGGER = LoggerFactory.getLogger(AnnotationTools.class);
public static <TYPE extends Annotation> TYPE get(final Field element, final Class<TYPE> clazz) {
final TYPE[] annotations = element.getDeclaredAnnotationsByType(clazz);
if (annotations.length == 0) {
return null;
}
return annotations[0];
}
public static <TYPE extends Annotation> TYPE[] gets(final Field element, final Class<TYPE> clazz) {
final TYPE[] annotations = element.getDeclaredAnnotationsByType(clazz);
if (annotations.length == 0) {
return null;
}
return annotations;
}
// For SQL declaration table Name // For SQL declaration table Name
public static String getTableName(final Class<?> clazz, final QueryOptions options) throws DataAccessException { public static String getTableName(final Class<?> clazz, final QueryOptions options) throws DataAccessException {
if (options != null) { if (options != null) {
@ -92,27 +110,15 @@ public class AnnotationTools {
} }
public static CollectionItemNotNull getCollectionItemNotNull(final Field element) { public static CollectionItemNotNull getCollectionItemNotNull(final Field element) {
final Annotation[] annotation = element.getDeclaredAnnotationsByType(CollectionItemNotNull.class); return get(element, CollectionItemNotNull.class);
if (annotation.length == 0) {
return null;
}
return (CollectionItemNotNull) annotation[0];
} }
public static CollectionItemUnique getCollectionItemUnique(final Field element) { public static CollectionItemUnique getCollectionItemUnique(final Field element) {
final Annotation[] annotation = element.getDeclaredAnnotationsByType(CollectionItemUnique.class); return get(element, CollectionItemUnique.class);
if (annotation.length == 0) {
return null;
}
return (CollectionItemUnique) annotation[0];
} }
public static CollectionNotEmpty getCollectionNotEmpty(final Field element) { public static CollectionNotEmpty getCollectionNotEmpty(final Field element) {
final Annotation[] annotation = element.getDeclaredAnnotationsByType(CollectionNotEmpty.class); return get(element, CollectionNotEmpty.class);
if (annotation.length == 0) {
return null;
}
return (CollectionNotEmpty) annotation[0];
} }
public static boolean getSchemaReadOnly(final Field element) { public static boolean getSchemaReadOnly(final Field element) {
@ -164,75 +170,39 @@ public class AnnotationTools {
} }
public static ManyToOne getManyToOne(final Field element) { public static ManyToOne getManyToOne(final Field element) {
final Annotation[] annotation = element.getDeclaredAnnotationsByType(ManyToOne.class); return get(element, ManyToOne.class);
if (annotation.length == 0) {
return null;
}
return (ManyToOne) annotation[0];
} }
public static ManyToMany getManyToMany(final Field element) { public static ManyToMany getManyToMany(final Field element) {
final Annotation[] annotation = element.getDeclaredAnnotationsByType(ManyToMany.class); return get(element, ManyToMany.class);
if (annotation.length == 0) {
return null;
}
return (ManyToMany) annotation[0];
} }
public static OneToMany getOneToMany(final Field element) { public static OneToMany getOneToMany(final Field element) {
final Annotation[] annotation = element.getDeclaredAnnotationsByType(OneToMany.class); return get(element, OneToMany.class);
if (annotation.length == 0) {
return null;
}
return (OneToMany) annotation[0];
} }
public static DataJson getDataJson(final Field element) { public static DataJson getDataJson(final Field element) {
final Annotation[] annotation = element.getDeclaredAnnotationsByType(DataJson.class); return get(element, DataJson.class);
if (annotation.length == 0) {
return null;
}
return (DataJson) annotation[0];
} }
public static Checker[] getCheckers(final Field element) { public static Checker[] getConstraintsCheckers(final Field element) {
final Annotation[] annotation = element.getDeclaredAnnotationsByType(Checker.class); return gets(element, Checker.class);
if (annotation.length == 0) {
return null;
}
return (Checker[]) annotation;
} }
public static DecimalMin getConstraintsDecimalMin(final Field element) { public static DecimalMin getConstraintsDecimalMin(final Field element) {
final Annotation[] annotation = element.getDeclaredAnnotationsByType(DecimalMin.class); return get(element, DecimalMin.class);
if (annotation.length == 0) {
return null;
}
return ((DecimalMin) annotation[0]);
} }
public static DecimalMax getConstraintsDecimalMax(final Field element) { public static DecimalMax getConstraintsDecimalMax(final Field element) {
final Annotation[] annotation = element.getDeclaredAnnotationsByType(DecimalMax.class); return get(element, DecimalMax.class);
if (annotation.length == 0) {
return null;
}
return ((DecimalMax) annotation[0]);
} }
public static Long getConstraintsMax(final Field element) { public static Max getConstraintsMax(final Field element) {
final Annotation[] annotation = element.getDeclaredAnnotationsByType(Max.class); return get(element, Max.class);
if (annotation.length == 0) {
return null;
}
return ((Max) annotation[0]).value();
} }
public static Long getConstraintsMin(final Field element) { public static Min getConstraintsMin(final Field element) {
final Annotation[] annotation = element.getDeclaredAnnotationsByType(Min.class); return get(element, Min.class);
if (annotation.length == 0) {
return null;
}
return ((Min) annotation[0]).value();
} }
public static int getLimitSize(final Field element) { public static int getLimitSize(final Field element) {
@ -245,27 +215,15 @@ public class AnnotationTools {
} }
public static Size getConstraintsSize(final Field element) { public static Size getConstraintsSize(final Field element) {
final Annotation[] annotation = element.getDeclaredAnnotationsByType(Size.class); return get(element, Size.class);
if (annotation.length == 0) {
return null;
}
return (Size) annotation[0];
} }
public static String getConstraintsPattern(final Field element) { public static Pattern getConstraintsPattern(final Field element) {
final Annotation[] annotation = element.getDeclaredAnnotationsByType(Pattern.class); return get(element, Pattern.class);
if (annotation.length == 0) {
return null;
}
return ((Pattern) annotation[0]).regexp();
} }
public static boolean getConstraintsEmail(final Field element) { public static Email getConstraintsEmail(final Field element) {
final Annotation[] annotation = element.getDeclaredAnnotationsByType(Email.class); return get(element, Email.class);
if (annotation.length == 0) {
return false;
}
return true;
} }
public static boolean isAnnotationGroup(final Field field, final Class<?> annotationType) { public static boolean isAnnotationGroup(final Field field, final Class<?> annotationType) {

View File

@ -0,0 +1,12 @@
package org.kar.archidata.annotation.checker;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ ElementType.TYPE, ElementType.FIELD })
@Retention(RetentionPolicy.RUNTIME)
public @interface CheckForeignKey {
Class<?> target();
}

View File

@ -12,16 +12,15 @@ import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.UUID;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import org.kar.archidata.annotation.AnnotationTools; import org.kar.archidata.annotation.AnnotationTools;
import org.kar.archidata.annotation.checker.CheckForeignKey;
import org.kar.archidata.annotation.checker.Checker; import org.kar.archidata.annotation.checker.Checker;
import org.kar.archidata.annotation.checker.CollectionItemNotNull; import org.kar.archidata.annotation.checker.CollectionItemNotNull;
import org.kar.archidata.annotation.checker.CollectionItemUnique; import org.kar.archidata.annotation.checker.CollectionItemUnique;
import org.kar.archidata.annotation.checker.CollectionNotEmpty; import org.kar.archidata.annotation.checker.CollectionNotEmpty;
import org.kar.archidata.dataAccess.DBAccess; import org.kar.archidata.dataAccess.DBAccess;
import org.kar.archidata.dataAccess.DataAccess;
import org.kar.archidata.dataAccess.QueryCondition; import org.kar.archidata.dataAccess.QueryCondition;
import org.kar.archidata.dataAccess.QueryOptions; import org.kar.archidata.dataAccess.QueryOptions;
import org.kar.archidata.dataAccess.options.CheckFunctionInterface; import org.kar.archidata.dataAccess.options.CheckFunctionInterface;
@ -36,6 +35,8 @@ import org.slf4j.LoggerFactory;
import jakarta.persistence.ManyToOne; import jakarta.persistence.ManyToOne;
import jakarta.validation.constraints.DecimalMax; import jakarta.validation.constraints.DecimalMax;
import jakarta.validation.constraints.DecimalMin; import jakarta.validation.constraints.DecimalMin;
import jakarta.validation.constraints.Max;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.Size; import jakarta.validation.constraints.Size;
public class CheckJPA<T> implements CheckFunctionInterface { public class CheckJPA<T> implements CheckFunctionInterface {
@ -134,6 +135,8 @@ public class CheckJPA<T> implements CheckFunctionInterface {
if (maxValueDecimal != null) { if (maxValueDecimal != null) {
final long maxValue = Long.parseLong(maxValueDecimal.value()); final long maxValue = Long.parseLong(maxValueDecimal.value());
final boolean inclusive = maxValueDecimal.inclusive(); final boolean inclusive = maxValueDecimal.inclusive();
final String exceptionComment = "Value too height max=" + maxValue
+ (inclusive ? " (inclusive)" : " (exclusive)");
add(fieldName, add(fieldName,
( (
final DBAccess ioDb, final DBAccess ioDb,
@ -148,12 +151,10 @@ public class CheckJPA<T> implements CheckFunctionInterface {
final Long elemTyped = (Long) elem; final Long elemTyped = (Long) elem;
if (inclusive) { if (inclusive) {
if (elemTyped > maxValue) { if (elemTyped > maxValue) {
throw new InputException(baseName + fieldName, throw new InputException(baseName + fieldName, exceptionComment);
"Value too height max: " + maxValue);
} }
} else if (elemTyped >= maxValue) { } else if (elemTyped >= maxValue) {
throw new InputException(baseName + fieldName, throw new InputException(baseName + fieldName, exceptionComment);
"Value too height max: " + maxValue);
} }
}); });
} }
@ -161,6 +162,8 @@ public class CheckJPA<T> implements CheckFunctionInterface {
if (minValueDecimal != null) { if (minValueDecimal != null) {
final long minValue = Long.parseLong(minValueDecimal.value()); final long minValue = Long.parseLong(minValueDecimal.value());
final boolean inclusive = minValueDecimal.inclusive(); final boolean inclusive = minValueDecimal.inclusive();
final String exceptionComment = "Value too low min=" + minValue
+ (inclusive ? " (inclusive)" : " (exclusive)");
add(fieldName, add(fieldName,
( (
final DBAccess ioDb, final DBAccess ioDb,
@ -175,17 +178,17 @@ public class CheckJPA<T> implements CheckFunctionInterface {
final Long elemTyped = (Long) elem; final Long elemTyped = (Long) elem;
if (inclusive) { if (inclusive) {
if (elemTyped < minValue) { if (elemTyped < minValue) {
throw new InputException(baseName + fieldName, throw new InputException(baseName + fieldName, exceptionComment);
"Value too Low min: " + minValue);
} }
} else if (elemTyped <= minValue) { } else if (elemTyped <= minValue) {
throw new InputException(baseName + fieldName, throw new InputException(baseName + fieldName, exceptionComment);
"Value too Low min: " + minValue);
} }
}); });
} }
final Long maxValue = AnnotationTools.getConstraintsMax(field); final Max maxValue = AnnotationTools.getConstraintsMax(field);
if (maxValue != null) { if (maxValue != null) {
final Long maxValueTmp = maxValue.value();
final String exceptionComment = "Value too height max=" + maxValueTmp + " (inclusive)";
add(fieldName, add(fieldName,
( (
final DBAccess ioDb, final DBAccess ioDb,
@ -198,14 +201,15 @@ public class CheckJPA<T> implements CheckFunctionInterface {
return; return;
} }
final Long elemTyped = (Long) elem; final Long elemTyped = (Long) elem;
if (elemTyped > maxValue) { if (elemTyped > maxValueTmp) {
throw new InputException(baseName + fieldName, throw new InputException(baseName + fieldName, exceptionComment);
"Value too height max: " + maxValue);
} }
}); });
} }
final Long minValue = AnnotationTools.getConstraintsMin(field); final Min minValue = AnnotationTools.getConstraintsMin(field);
if (minValue != null) { if (minValue != null) {
final Long minValueTmp = minValue.value();
final String exceptionComment = "Value too low min=" + minValueTmp + " (inclusive)";
add(fieldName, add(fieldName,
( (
final DBAccess ioDb, final DBAccess ioDb,
@ -218,42 +222,18 @@ public class CheckJPA<T> implements CheckFunctionInterface {
return; return;
} }
final Long elemTyped = (Long) elem; final Long elemTyped = (Long) elem;
if (elemTyped < minValue) { if (elemTyped < minValueTmp) {
throw new InputException(baseName + fieldName, throw new InputException(baseName + fieldName, exceptionComment);
"Value too Low min: " + minValue);
} }
}); });
} }
final ManyToOne annotationManyToOne = AnnotationTools.getManyToOne(field);
if (annotationManyToOne != null && annotationManyToOne.targetEntity() != null) {
add(fieldName,
(
final DBAccess ioDb,
final String baseName,
final T data,
final List<String> modifiedValue,
final QueryOptions options) -> {
final Object elem = field.get(data);
if (elem == null) {
return;
}
final List<ConditionChecker> condCheckers = options.get(ConditionChecker.class);
final Condition conditionCheck = condCheckers.isEmpty() ? null
: condCheckers.get(0).toCondition();
final long count = DataAccess.count(annotationManyToOne.targetEntity(), elem,
conditionCheck);
if (count == 0) {
throw new InputException(baseName + fieldName,
"Foreign element does not exist in the DB:" + elem);
}
});
}
} else if (type == Integer.class || type == int.class) { } else if (type == Integer.class || type == int.class) {
final DecimalMax maxValueDecimal = AnnotationTools.getConstraintsDecimalMax(field); final DecimalMax maxValueDecimal = AnnotationTools.getConstraintsDecimalMax(field);
if (maxValueDecimal != null) { if (maxValueDecimal != null) {
final int maxValue = Integer.parseInt(maxValueDecimal.value()); final int maxValue = Integer.parseInt(maxValueDecimal.value());
final boolean inclusive = maxValueDecimal.inclusive(); final boolean inclusive = maxValueDecimal.inclusive();
final String exceptionComment = "Value too height max=" + maxValue
+ (inclusive ? " (inclusive)" : " (exclusive)");
add(fieldName, add(fieldName,
( (
final DBAccess ioDb, final DBAccess ioDb,
@ -268,13 +248,11 @@ public class CheckJPA<T> implements CheckFunctionInterface {
final Integer elemTyped = (Integer) elem; final Integer elemTyped = (Integer) elem;
if (inclusive) { if (inclusive) {
if (elemTyped > maxValue) { if (elemTyped > maxValue) {
throw new InputException(baseName + fieldName, throw new InputException(baseName + fieldName, exceptionComment);
"Value too height max: " + maxValue);
} }
} else if (elemTyped >= maxValue) { } else if (elemTyped >= maxValue) {
throw new InputException(baseName + fieldName, throw new InputException(baseName + fieldName, exceptionComment);
"Value too height max: " + maxValue);
} }
}); });
} }
@ -282,6 +260,8 @@ public class CheckJPA<T> implements CheckFunctionInterface {
if (minValueDecimal != null) { if (minValueDecimal != null) {
final int minValue = Integer.parseInt(minValueDecimal.value()); final int minValue = Integer.parseInt(minValueDecimal.value());
final boolean inclusive = minValueDecimal.inclusive(); final boolean inclusive = minValueDecimal.inclusive();
final String exceptionComment = "Value too low min=" + minValue
+ (inclusive ? " (inclusive)" : " (exclusive)");
add(fieldName, add(fieldName,
( (
final DBAccess ioDb, final DBAccess ioDb,
@ -296,18 +276,17 @@ public class CheckJPA<T> implements CheckFunctionInterface {
final Integer elemTyped = (Integer) elem; final Integer elemTyped = (Integer) elem;
if (inclusive) { if (inclusive) {
if (elemTyped < minValue) { if (elemTyped < minValue) {
throw new InputException(baseName + fieldName, throw new InputException(baseName + fieldName, exceptionComment);
"Value too Low min: " + minValue);
} }
} else if (elemTyped <= minValue) { } else if (elemTyped <= minValue) {
throw new InputException(baseName + fieldName, throw new InputException(baseName + fieldName, exceptionComment);
"Value too Low min: " + minValue);
} }
}); });
} }
final Long maxValueRoot = AnnotationTools.getConstraintsMax(field); final Max maxValueRoot = AnnotationTools.getConstraintsMax(field);
if (maxValueRoot != null) { if (maxValueRoot != null) {
final int maxValue = maxValueRoot.intValue(); final int maxValue = (int) maxValueRoot.value();
final String exceptionComment = "Value too height max=" + maxValue + " (inclusive)";
add(fieldName, add(fieldName,
( (
final DBAccess ioDb, final DBAccess ioDb,
@ -321,14 +300,14 @@ public class CheckJPA<T> implements CheckFunctionInterface {
} }
final Integer elemTyped = (Integer) elem; final Integer elemTyped = (Integer) elem;
if (elemTyped > maxValue) { if (elemTyped > maxValue) {
throw new InputException(baseName + fieldName, throw new InputException(baseName + fieldName, exceptionComment);
"Value too height max: " + maxValue);
} }
}); });
} }
final Long minValueRoot = AnnotationTools.getConstraintsMin(field); final Min minValueRoot = AnnotationTools.getConstraintsMin(field);
if (minValueRoot != null) { if (minValueRoot != null) {
final int minValue = minValueRoot.intValue(); final int minValue = (int) minValueRoot.value();
final String exceptionComment = "Value too low min=" + minValue + " (inclusive)";
add(fieldName, add(fieldName,
( (
final DBAccess ioDb, final DBAccess ioDb,
@ -342,49 +321,7 @@ public class CheckJPA<T> implements CheckFunctionInterface {
} }
final Integer elemTyped = (Integer) elem; final Integer elemTyped = (Integer) elem;
if (elemTyped < minValue) { if (elemTyped < minValue) {
throw new InputException(baseName + fieldName, throw new InputException(baseName + fieldName, exceptionComment);
"Value too Low min: " + minValue);
}
});
}
final ManyToOne annotationManyToOne = AnnotationTools.getManyToOne(field);
if (annotationManyToOne != null && annotationManyToOne.targetEntity() != null) {
add(fieldName,
(
final DBAccess ioDb,
final String baseName,
final T data,
final List<String> modifiedValue,
final QueryOptions options) -> {
final Object elem = field.get(data);
if (elem == null) {
return;
}
final long count = DataAccess.count(annotationManyToOne.targetEntity(), elem);
if (count == 0) {
throw new InputException(baseName + fieldName,
"Foreign element does not exist in the DB:" + elem);
}
});
}
} else if (type == UUID.class) {
final ManyToOne annotationManyToOne = AnnotationTools.getManyToOne(field);
if (annotationManyToOne != null && annotationManyToOne.targetEntity() != null) {
add(fieldName,
(
final DBAccess ioDb,
final String baseName,
final T data,
final List<String> modifiedValue,
final QueryOptions options) -> {
final Object elem = field.get(data);
if (elem == null) {
return;
}
final long count = DataAccess.count(annotationManyToOne.targetEntity(), elem);
if (count == 0) {
throw new InputException(baseName + fieldName,
"Foreign element does not exist in the DB:" + elem);
} }
}); });
} }
@ -395,6 +332,8 @@ public class CheckJPA<T> implements CheckFunctionInterface {
if (maxValueDecimal != null) { if (maxValueDecimal != null) {
final float maxValue = Float.parseFloat(maxValueDecimal.value()); final float maxValue = Float.parseFloat(maxValueDecimal.value());
final boolean inclusive = maxValueDecimal.inclusive(); final boolean inclusive = maxValueDecimal.inclusive();
final String exceptionComment = "Value too height max=" + maxValue
+ (inclusive ? " (inclusive)" : " (exclusive)");
add(fieldName, add(fieldName,
( (
final DBAccess ioDb, final DBAccess ioDb,
@ -409,12 +348,10 @@ public class CheckJPA<T> implements CheckFunctionInterface {
final Float elemTyped = (Float) elem; final Float elemTyped = (Float) elem;
if (inclusive) { if (inclusive) {
if (elemTyped > maxValue) { if (elemTyped > maxValue) {
throw new InputException(baseName + fieldName, throw new InputException(baseName + fieldName, exceptionComment);
"Value too height max: " + maxValue);
} }
} else if (elemTyped >= maxValue) { } else if (elemTyped >= maxValue) {
throw new InputException(baseName + fieldName, throw new InputException(baseName + fieldName, exceptionComment);
"Value too height max: " + maxValue);
} }
}); });
} }
@ -422,6 +359,8 @@ public class CheckJPA<T> implements CheckFunctionInterface {
if (minValueDecimal != null) { if (minValueDecimal != null) {
final float minValue = Float.parseFloat(minValueDecimal.value()); final float minValue = Float.parseFloat(minValueDecimal.value());
final boolean inclusive = minValueDecimal.inclusive(); final boolean inclusive = minValueDecimal.inclusive();
final String exceptionComment = "Value too low min=" + minValue
+ (inclusive ? " (inclusive)" : " (exclusive)");
add(fieldName, add(fieldName,
( (
final DBAccess ioDb, final DBAccess ioDb,
@ -436,18 +375,17 @@ public class CheckJPA<T> implements CheckFunctionInterface {
final Float elemTyped = (Float) elem; final Float elemTyped = (Float) elem;
if (inclusive) { if (inclusive) {
if (elemTyped < minValue) { if (elemTyped < minValue) {
throw new InputException(baseName + fieldName, throw new InputException(baseName + fieldName, exceptionComment);
"Value too Low min: " + minValue);
} }
} else if (elemTyped <= minValue) { } else if (elemTyped <= minValue) {
throw new InputException(baseName + fieldName, throw new InputException(baseName + fieldName, exceptionComment);
"Value too Low min: " + minValue);
} }
}); });
} }
final Long maxValueRoot = AnnotationTools.getConstraintsMax(field); final Max maxValueRoot = AnnotationTools.getConstraintsMax(field);
if (maxValueRoot != null) { if (maxValueRoot != null) {
final float maxValue = maxValueRoot.floatValue(); final float maxValue = maxValueRoot.value();
final String exceptionComment = "Value too height max=" + maxValue + " (inclusive)";
add(fieldName, add(fieldName,
( (
final DBAccess ioDb, final DBAccess ioDb,
@ -462,14 +400,14 @@ public class CheckJPA<T> implements CheckFunctionInterface {
final Float elemTyped = (Float) elem; final Float elemTyped = (Float) elem;
if (elemTyped > maxValue) { if (elemTyped > maxValue) {
throw new InputException(baseName + fieldName, throw new InputException(baseName + fieldName, exceptionComment);
"Value too height max: " + maxValue);
} }
}); });
} }
final Long minValueRoot = AnnotationTools.getConstraintsMin(field); final Min minValueRoot = AnnotationTools.getConstraintsMin(field);
if (minValueRoot != null) { if (minValueRoot != null) {
final float minValue = minValueRoot.floatValue(); final float minValue = minValueRoot.value();
final String exceptionComment = "Value too low min=" + minValue + " (inclusive)";
add(fieldName, add(fieldName,
( (
final DBAccess ioDb, final DBAccess ioDb,
@ -483,8 +421,7 @@ public class CheckJPA<T> implements CheckFunctionInterface {
} }
final Float elemTyped = (Float) elem; final Float elemTyped = (Float) elem;
if (elemTyped < minValue) { if (elemTyped < minValue) {
throw new InputException(baseName + fieldName, throw new InputException(baseName + fieldName, exceptionComment);
"Value too Low min: " + minValue);
} }
}); });
} }
@ -493,6 +430,8 @@ public class CheckJPA<T> implements CheckFunctionInterface {
if (maxValueDecimal != null) { if (maxValueDecimal != null) {
final double maxValue = Float.parseFloat(maxValueDecimal.value()); final double maxValue = Float.parseFloat(maxValueDecimal.value());
final boolean inclusive = maxValueDecimal.inclusive(); final boolean inclusive = maxValueDecimal.inclusive();
final String exceptionComment = "Value too height max=" + maxValue
+ (inclusive ? " (inclusive)" : " (exclusive)");
add(fieldName, add(fieldName,
( (
final DBAccess ioDb, final DBAccess ioDb,
@ -507,12 +446,10 @@ public class CheckJPA<T> implements CheckFunctionInterface {
final Double elemTyped = (Double) elem; final Double elemTyped = (Double) elem;
if (inclusive) { if (inclusive) {
if (elemTyped > maxValue) { if (elemTyped > maxValue) {
throw new InputException(baseName + fieldName, throw new InputException(baseName + fieldName, exceptionComment);
"Value too height max: " + maxValue);
} }
} else if (elemTyped >= maxValue) { } else if (elemTyped >= maxValue) {
throw new InputException(baseName + fieldName, throw new InputException(baseName + fieldName, exceptionComment);
"Value too height max: " + maxValue);
} }
}); });
} }
@ -520,6 +457,8 @@ public class CheckJPA<T> implements CheckFunctionInterface {
if (minValueDecimal != null) { if (minValueDecimal != null) {
final double minValue = Float.parseFloat(minValueDecimal.value()); final double minValue = Float.parseFloat(minValueDecimal.value());
final boolean inclusive = minValueDecimal.inclusive(); final boolean inclusive = minValueDecimal.inclusive();
final String exceptionComment = "Value too low min=" + minValue
+ (inclusive ? " (inclusive)" : " (exclusive)");
add(fieldName, add(fieldName,
( (
final DBAccess ioDb, final DBAccess ioDb,
@ -538,14 +477,14 @@ public class CheckJPA<T> implements CheckFunctionInterface {
"Value too Low min: " + minValue); "Value too Low min: " + minValue);
} }
} else if (elemTyped <= minValue) { } else if (elemTyped <= minValue) {
throw new InputException(baseName + fieldName, throw new InputException(baseName + fieldName, exceptionComment);
"Value too Low min: " + minValue);
} }
}); });
} }
final Long maxValueRoot = AnnotationTools.getConstraintsMax(field); final Max maxValueRoot = AnnotationTools.getConstraintsMax(field);
if (maxValueRoot != null) { if (maxValueRoot != null) {
final double maxValue = maxValueRoot.doubleValue(); final double maxValue = maxValueRoot.value();
final String exceptionComment = "Value too height max=" + maxValue + " (inclusive)";
add(fieldName, add(fieldName,
( (
final DBAccess ioDb, final DBAccess ioDb,
@ -559,14 +498,14 @@ public class CheckJPA<T> implements CheckFunctionInterface {
} }
final Double elemTyped = (Double) elem; final Double elemTyped = (Double) elem;
if (elemTyped > maxValue) { if (elemTyped > maxValue) {
throw new InputException(baseName + fieldName, throw new InputException(baseName + fieldName, exceptionComment);
"Value too height max: " + maxValue);
} }
}); });
} }
final Long minValueRoot = AnnotationTools.getConstraintsMin(field); final Min minValueRoot = AnnotationTools.getConstraintsMin(field);
if (minValueRoot != null) { if (minValueRoot != null) {
final double minValue = minValueRoot.doubleValue(); final double minValue = minValueRoot.value();
final String exceptionComment = "Value too low min=" + minValue + " (inclusive)";
add(fieldName, add(fieldName,
( (
final DBAccess ioDb, final DBAccess ioDb,
@ -580,8 +519,7 @@ public class CheckJPA<T> implements CheckFunctionInterface {
} }
final Double elemTyped = (Double) elem; final Double elemTyped = (Double) elem;
if (elemTyped < minValue) { if (elemTyped < minValue) {
throw new InputException(baseName + fieldName, throw new InputException(baseName + fieldName, exceptionComment);
"Value too Low min: " + minValue);
} }
}); });
} }
@ -592,26 +530,6 @@ public class CheckJPA<T> implements CheckFunctionInterface {
} else if (type == LocalTime.class) { } else if (type == LocalTime.class) {
} else if (type == String.class) { } else if (type == String.class) {
final int maxSizeString = AnnotationTools.getLimitSize(field);
if (maxSizeString > 0) {
add(fieldName,
(
final DBAccess ioDb,
final String baseName,
final T data,
final List<String> modifiedValue,
final QueryOptions options) -> {
final Object elem = field.get(data);
if (elem == null) {
return;
}
final String elemTyped = (String) elem;
if (elemTyped.length() > maxSizeString) {
throw new InputException(baseName + fieldName,
"Too long size must be <= " + maxSizeString);
}
});
}
final Size limitSize = AnnotationTools.getConstraintsSize(field); final Size limitSize = AnnotationTools.getConstraintsSize(field);
if (limitSize != null) { if (limitSize != null) {
add(fieldName, add(fieldName,
@ -636,9 +554,10 @@ public class CheckJPA<T> implements CheckFunctionInterface {
} }
}); });
} }
final String patternString = AnnotationTools.getConstraintsPattern(field); final jakarta.validation.constraints.Pattern patternString = AnnotationTools
if (patternString != null) { .getConstraintsPattern(field);
final Pattern pattern = Pattern.compile(patternString); if (patternString != null && patternString.regexp() != null) {
final Pattern pattern = Pattern.compile(patternString.regexp());
add(fieldName, add(fieldName,
( (
final DBAccess ioDb, final DBAccess ioDb,
@ -653,12 +572,12 @@ public class CheckJPA<T> implements CheckFunctionInterface {
final String elemTyped = (String) elem; final String elemTyped = (String) elem;
if (!pattern.matcher(elemTyped).find()) { if (!pattern.matcher(elemTyped).find()) {
throw new InputException(baseName + fieldName, throw new InputException(baseName + fieldName,
"does not match the required pattern (constraints) must be '" "does not match the required pattern (constraints) must be '" + pattern
+ patternString + "'"); + "'");
} }
}); });
} }
if (AnnotationTools.getConstraintsEmail(field)) { if (AnnotationTools.getConstraintsEmail(field) != null) {
final String emailPattern = "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$"; final String emailPattern = "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$";
final Pattern pattern = Pattern.compile(emailPattern); final Pattern pattern = Pattern.compile(emailPattern);
add(fieldName, add(fieldName,
@ -683,7 +602,7 @@ public class CheckJPA<T> implements CheckFunctionInterface {
} else if (type.isEnum()) { } else if (type.isEnum()) {
// nothing to do. // nothing to do.
} }
final Checker[] checkers = AnnotationTools.getCheckers(field); final Checker[] checkers = AnnotationTools.getConstraintsCheckers(field);
if (checkers != null) { if (checkers != null) {
for (final Checker checker : checkers) { for (final Checker checker : checkers) {
if (checker == null || checker.value() == CheckFunctionVoid.class) { if (checker == null || checker.value() == CheckFunctionVoid.class) {
@ -733,6 +652,87 @@ public class CheckJPA<T> implements CheckFunctionInterface {
} }
} }
} }
final CheckForeignKey foreighKey = AnnotationTools.get(field, CheckForeignKey.class);
if (foreighKey != null) {
if (Collection.class.isAssignableFrom(field.getType())) {
add(fieldName,
(
final DBAccess ioDb,
final String baseName,
final T data,
final List<String> modifiedValue,
final QueryOptions options) -> {
// get the field of the specific element
final Object tmpData = field.get(data);
// It is not the objective of this element to check if it is authorize to set NULL
if (tmpData == null) {
return;
}
final List<ConditionChecker> condCheckers = options.get(ConditionChecker.class);
final Condition conditionCheck = condCheckers.isEmpty() ? null
: condCheckers.get(0).toCondition();
final Collection<?> tmpCollection = (Collection<?>) tmpData;
final Object[] elements = tmpCollection.toArray();
for (int iii = 0; iii < elements.length; iii++) {
if (elements[iii] == null) {
continue;
}
final Long count = ioDb.count(foreighKey.target(), elements[iii],
conditionCheck);
if (count != 1) {
throw new InputException(baseName + fieldName + '[' + iii + ']',
"Foreign-key does not exist in the DB:" + elements[iii]);
}
}
});
} else {
add(fieldName,
(
final DBAccess ioDb,
final String baseName,
final T data,
final List<String> modifiedValue,
final QueryOptions options) -> {
final Object tmpData = field.get(data);
if (tmpData == null) {
return;
}
final List<ConditionChecker> condCheckers = options.get(ConditionChecker.class);
final Condition conditionCheck = condCheckers.isEmpty() ? null
: condCheckers.get(0).toCondition();
final Long count = ioDb.count(foreighKey.target(), tmpData, conditionCheck);
if (count != 1) {
throw new InputException(baseName + fieldName,
"Foreign-key does not exist in the DB:" + tmpData);
}
});
}
}
// check if we really want to keep it ...
final ManyToOne annotationManyToOne = AnnotationTools.getManyToOne(field);
if (annotationManyToOne != null && annotationManyToOne.targetEntity() != null) {
add(fieldName,
(
final DBAccess ioDb,
final String baseName,
final T data,
final List<String> modifiedValue,
final QueryOptions options) -> {
final Object elem = field.get(data);
if (elem == null) {
return;
}
final List<ConditionChecker> condCheckers = options.get(ConditionChecker.class);
final Condition conditionCheck = condCheckers.isEmpty() ? null
: condCheckers.get(0).toCondition();
final long count = ioDb.count(annotationManyToOne.targetEntity(), elem, conditionCheck);
if (count == 0) {
throw new InputException(baseName + fieldName,
"Foreign element does not exist in the DB:" + elem);
}
});
}
final CollectionItemUnique collectionUnique = AnnotationTools.getCollectionItemUnique(field); final CollectionItemUnique collectionUnique = AnnotationTools.getCollectionItemUnique(field);
if (collectionUnique != null) { if (collectionUnique != null) {
if (!Collection.class.isAssignableFrom(field.getType())) { if (!Collection.class.isAssignableFrom(field.getType())) {
@ -781,7 +781,7 @@ public class CheckJPA<T> implements CheckFunctionInterface {
for (int iii = 0; iii < elements.length; iii++) { for (int iii = 0; iii < elements.length; iii++) {
if (elements[iii] == null) { if (elements[iii] == null) {
throw new InputException(baseName + fieldName + '[' + iii + ']', throw new InputException(baseName + fieldName + '[' + iii + ']',
"This collection can not conatain NULL item"); "Collection can not contain NULL item");
} }
} }
}); });
@ -805,7 +805,7 @@ public class CheckJPA<T> implements CheckFunctionInterface {
} }
final Collection<?> tmpCollection = (Collection<?>) tmpData; final Collection<?> tmpCollection = (Collection<?>) tmpData;
if (tmpCollection.isEmpty()) { if (tmpCollection.isEmpty()) {
throw new InputException(baseName + fieldName, "Can not be empty"); throw new InputException(baseName + fieldName, "Collection can not be empty");
} }
}); });
} }
@ -822,15 +822,16 @@ public class CheckJPA<T> implements CheckFunctionInterface {
final List<ConditionChecker> condCheckers = options.get(ConditionChecker.class); final List<ConditionChecker> condCheckers = options.get(ConditionChecker.class);
Object other = null; Object other = null;
if (condCheckers.isEmpty()) { if (condCheckers.isEmpty()) {
other = DataAccess.getWhere(this.clazz, other = ioDb.getWhere(this.clazz,
new Condition(new QueryCondition(fieldName, "==", field.get(data)))); new Condition(new QueryCondition(fieldName, "==", field.get(data))));
} else { } else {
other = DataAccess.getWhere(this.clazz, other = ioDb.getWhere(this.clazz,
new Condition(new QueryCondition(fieldName, "==", field.get(data))), new Condition(new QueryCondition(fieldName, "==", field.get(data))),
condCheckers.get(0).toCondition()); condCheckers.get(0).toCondition());
} }
if (other != null) { if (other != null) {
throw new InputException(baseName + fieldName, "Name already exist in the DB"); throw new InputException(baseName + fieldName,
"The field is already exist in the DB");
} }
}); });
} }

View File

@ -151,38 +151,6 @@ public class DotClassElement {
return ".optional()"; return ".optional()";
} }
public String maxSizeZod(final FieldProperty field) {
final StringBuilder builder = new StringBuilder();
final Class<?> clazz = field.model().getOriginClasses();
if (clazz == String.class) {
if (field.sizeMin() > 0) {
builder.append(".min(");
builder.append(field.sizeMin());
builder.append(")");
}
if (field.sizeMax() > 0) {
builder.append(".max(");
builder.append(field.sizeMax());
builder.append(")");
}
}
if (clazz == short.class || clazz == Short.class || clazz == int.class || clazz == Integer.class
|| clazz == long.class || clazz == Long.class || clazz == float.class || clazz == Float.class
|| clazz == double.class || clazz == Double.class) {
if (field.min() != null && field.min() > 0) {
builder.append(".min(");
builder.append(field.min());
builder.append(")");
}
if (field.max() != null && field.max() > 0) {
builder.append(".max(");
builder.append(field.max());
builder.append(")");
}
}
return builder.toString();
}
public String readOnlyZod(final FieldProperty field) { public String readOnlyZod(final FieldProperty field) {
if (field.readOnly()) { if (field.readOnly()) {
return ".readonly()"; return ".readonly()";

View File

@ -18,6 +18,12 @@ import org.slf4j.LoggerFactory;
import jakarta.persistence.ManyToMany; import jakarta.persistence.ManyToMany;
import jakarta.persistence.ManyToOne; import jakarta.persistence.ManyToOne;
import jakarta.persistence.OneToMany; import jakarta.persistence.OneToMany;
import jakarta.validation.constraints.DecimalMax;
import jakarta.validation.constraints.DecimalMin;
import jakarta.validation.constraints.Email;
import jakarta.validation.constraints.Max;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.Pattern;
import jakarta.validation.constraints.Size; import jakarta.validation.constraints.Size;
public class ClassObjectModel extends ClassModel { public class ClassObjectModel extends ClassModel {
@ -61,24 +67,31 @@ public class ClassObjectModel extends ClassModel {
ClassModel model, ClassModel model,
ClassModel linkClass, // link class when use remote ID (ex: list<UUID>) ClassModel linkClass, // link class when use remote ID (ex: list<UUID>)
String comment, String comment,
int sizeMin, // String SizeMin Size stringSize, // String Size
int sizeMax, // String SizeMax Min min, // number min value
Long min, // number min value Max max, // number max value
Long max, // number max value DecimalMin decimalMin,
DecimalMax decimalMax,
Pattern pattern,
Email email,
Boolean readOnly, Boolean readOnly,
Boolean notNull, Boolean notNull,
Boolean columnNotNull, Boolean columnNotNull,
Boolean nullable) { Boolean nullable) {
public FieldProperty(final String name, final ClassModel model, final ClassModel linkClass, public FieldProperty(final String name, final ClassModel model, final ClassModel linkClass,
final String comment, final int sizeMin, final int sizeMax, final Long min, final Long max, final String comment, final Size stringSize, final Min min, final Max max, final DecimalMin decimalMin,
final Boolean readOnly, final Boolean notNull, final Boolean columnNotNull, final Boolean nullable) { final DecimalMax decimalMax, final Pattern pattern, final Email email, final Boolean readOnly,
final Boolean notNull, final Boolean columnNotNull, final Boolean nullable) {
this.name = name; this.name = name;
this.model = model; this.model = model;
this.linkClass = linkClass; this.linkClass = linkClass;
this.comment = comment; this.comment = comment;
this.sizeMin = sizeMin; this.stringSize = stringSize;
this.sizeMax = sizeMax; this.decimalMin = decimalMin;
this.decimalMax = decimalMax;
this.pattern = pattern;
this.email = email;
this.min = min; this.min = min;
this.max = max; this.max = max;
this.readOnly = readOnly; this.readOnly = readOnly;
@ -88,17 +101,6 @@ public class ClassObjectModel extends ClassModel {
} }
private static int getStringMinSize(final Field field) throws DataAccessException {
final Size size = AnnotationTools.getConstraintsSize(field);
return size != null ? size.min() : 0;
}
private static int getStringMaxSize(final Field field) throws DataAccessException {
final Size size = AnnotationTools.getConstraintsSize(field);
final int colomnLimitSize = AnnotationTools.getLimitSize(field);
return size == null ? colomnLimitSize : colomnLimitSize < size.max() ? colomnLimitSize : size.max();
}
private static Class<?> getSubModelIfExist2(final Field field) { private static Class<?> getSubModelIfExist2(final Field field) {
final ManyToOne manyToOne = AnnotationTools.getManyToOne(field); final ManyToOne manyToOne = AnnotationTools.getManyToOne(field);
if (manyToOne != null) { if (manyToOne != null) {
@ -137,10 +139,13 @@ public class ClassObjectModel extends ClassModel {
ClassModel.getModel(field.getGenericType(), previous), // ClassModel.getModel(field.getGenericType(), previous), //
getSubModelIfExist(field, previous), // getSubModelIfExist(field, previous), //
AnnotationTools.getSchemaDescription(field), // AnnotationTools.getSchemaDescription(field), //
getStringMinSize(field), // AnnotationTools.getConstraintsSize(field), //
getStringMaxSize(field), //
AnnotationTools.getConstraintsMin(field), // AnnotationTools.getConstraintsMin(field), //
AnnotationTools.getConstraintsMax(field), // AnnotationTools.getConstraintsMax(field), //
AnnotationTools.getConstraintsDecimalMin(field), //
AnnotationTools.getConstraintsDecimalMax(field), //
AnnotationTools.getConstraintsPattern(field), //
AnnotationTools.getConstraintsEmail(field), //
AnnotationTools.getSchemaReadOnly(field), // AnnotationTools.getSchemaReadOnly(field), //
AnnotationTools.getConstraintsNotNull(field), // AnnotationTools.getConstraintsNotNull(field), //
AnnotationTools.getColumnNotNull(field), // AnnotationTools.getColumnNotNull(field), //

View File

@ -259,30 +259,59 @@ public class TsClassElement {
final StringBuilder builder = new StringBuilder(); final StringBuilder builder = new StringBuilder();
final Class<?> clazz = field.model().getOriginClasses(); final Class<?> clazz = field.model().getOriginClasses();
if (clazz == String.class) { if (clazz == String.class) {
if (field.sizeMin() > 0) { if (field.stringSize() != null) {
builder.append(".min("); if (field.stringSize().min() > 0) {
builder.append(field.sizeMin()); // A string size can not be lower at 0
builder.append(")"); builder.append(".min(");
builder.append(field.stringSize().min());
builder.append(")");
}
if (field.stringSize().max() != Integer.MAX_VALUE) {
builder.append(".max(");
builder.append(field.stringSize().max());
builder.append(")");
}
} }
if (field.sizeMax() > 0) { /*Must be tested before
builder.append(".max("); if (field.pattern() != null) {
builder.append(field.sizeMax()); builder.append(".regex((");
builder.append(field.pattern().regexp());
builder.append(")"); builder.append(")");
} }*/
/*Must be tested before
if (field.email() != null) {
builder.append(".regex((");
builder.append(field.email().regexp());
builder.append(")");
}*/
} }
if (clazz == short.class || clazz == Short.class || clazz == int.class || clazz == Integer.class if (clazz == short.class || clazz == Short.class || clazz == int.class || clazz == Integer.class
|| clazz == long.class || clazz == Long.class || clazz == float.class || clazz == Float.class || clazz == long.class || clazz == Long.class || clazz == float.class || clazz == Float.class
|| clazz == double.class || clazz == Double.class) { || clazz == double.class || clazz == Double.class) {
if (field.min() != null && field.min() > 0) { if (field.min() != null) {
builder.append(".min("); builder.append(".min(");
builder.append(field.min()); builder.append(field.min().value());
builder.append(")"); builder.append(")");
} }
if (field.max() != null && field.max() > 0) { if (field.max() != null) {
builder.append(".max("); builder.append(".max(");
builder.append(field.max()); builder.append(field.max().value());
builder.append(")"); builder.append(")");
} }
if (field.decimalMax() != null) {
builder.append(".max(");
builder.append(field.decimalMax().value());
builder.append(", { inclusive: ");
builder.append(field.decimalMax().inclusive() ? "true" : "false");
builder.append("})");
}
if (field.decimalMin() != null) {
builder.append(".min(");
builder.append(field.decimalMin().value());
builder.append(", { inclusive: ");
builder.append(field.decimalMin().inclusive() ? "true" : "false");
builder.append("})");
}
} }
return builder.toString(); return builder.toString();
} }

View File

@ -68,7 +68,6 @@ public class MySecurityContext implements SecurityContext {
} }
// get associated Roles: // get associated Roles:
final PartRight rightPart = getRightOfRoleInGroup(group, role); final PartRight rightPart = getRightOfRoleInGroup(group, role);
LOGGER.info("detect : {}", rightPart);
if (PartRight.READ_WRITE.equals(rightPart)) { if (PartRight.READ_WRITE.equals(rightPart)) {
return true; return true;
} }

View File

@ -7,6 +7,7 @@ import com.fasterxml.jackson.annotation.JsonInclude;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.persistence.Column; import jakarta.persistence.Column;
import jakarta.persistence.Table; import jakarta.persistence.Table;
import jakarta.validation.constraints.Size;
@Table(name = "data") @Table(name = "data")
@DataIfNotExists @DataIfNotExists
@ -14,9 +15,11 @@ import jakarta.persistence.Table;
public class Data extends OIDGenericDataSoftDelete { public class Data extends OIDGenericDataSoftDelete {
@Column(length = 128, nullable = false) @Column(length = 128, nullable = false)
@Schema(description = "Sha512 of the data") @Schema(description = "Sha512 of the data")
@Size(max = 512)
public String sha512; public String sha512;
@Column(length = 128, nullable = false) @Column(length = 128, nullable = false)
@Schema(description = "Mime -type of the media") @Schema(description = "Mime -type of the media")
@Size(max = 512)
public String mimeType; public String mimeType;
@Column(nullable = false) @Column(nullable = false)
@Schema(description = "Size in Byte of the data") @Schema(description = "Size in Byte of the data")

View File

@ -51,6 +51,7 @@ public class User extends GenericDataSoftDelete {
@Nullable @Nullable
public Boolean blocked = false; public Boolean blocked = false;
@Column(length = 512) @Column(length = 512)
@Size(max = 512)
public String blockedReason; public String blockedReason;
@Schema(description = "List of Id of the specific covers") @Schema(description = "List of Id of the specific covers")

View File

@ -1 +1 @@
0.22.0 0.23.0