Compare commits
	
		
			39 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 218fa3be2e | |||
| 015c38ff5b | |||
| 24590b2a1e | |||
| c04660c01a | |||
| 3e81673d38 | |||
| 69880df4aa | |||
| 510553550f | |||
| e071d3dbf7 | |||
| 249e6ad2c8 | |||
| e156e528c1 | |||
| 89ab0f3b6a | |||
| 3d5a024084 | |||
| ba6478182d | |||
| cc639243fc | |||
| 24c226e92c | |||
| b5fcc3e20c | |||
| d028eb2261 | |||
| ca18d3759d | |||
| a7c9bb5e1b | |||
| d011b3a587 | |||
| 6974adbfdf | |||
| 461aece7a0 | |||
| 3f15d560ed | |||
| 8f3c14e28d | |||
| 0d419f651e | |||
| 9dad14d200 | |||
| 990b7c08da | |||
| 7f393a9e44 | |||
| c91291dbce | |||
| d684b5eaa9 | |||
| 85b27c0b31 | |||
| 1abbac944d | |||
| cef06889ee | |||
| 1e05e8361a | |||
| 4adc097c6b | |||
| 69e076e991 | |||
| 5e478e3caa | |||
| 5a97f794f6 | |||
| ac59e17de8 | 
							
								
								
									
										2
									
								
								pom.xml
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								pom.xml
									
									
									
									
									
								
							| @@ -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.20.2</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> | ||||||
|   | |||||||
| @@ -5,6 +5,10 @@ import java.lang.reflect.Field; | |||||||
| import java.util.ArrayList; | import java.util.ArrayList; | ||||||
| import java.util.List; | import java.util.List; | ||||||
|  |  | ||||||
|  | import org.kar.archidata.annotation.checker.Checker; | ||||||
|  | import org.kar.archidata.annotation.checker.CollectionItemNotNull; | ||||||
|  | import org.kar.archidata.annotation.checker.CollectionItemUnique; | ||||||
|  | import org.kar.archidata.annotation.checker.CollectionNotEmpty; | ||||||
| import org.kar.archidata.dataAccess.QueryOptions; | import org.kar.archidata.dataAccess.QueryOptions; | ||||||
| import org.kar.archidata.dataAccess.options.OptionRenameColumn; | import org.kar.archidata.dataAccess.options.OptionRenameColumn; | ||||||
| import org.kar.archidata.dataAccess.options.OverrideTableName; | import org.kar.archidata.dataAccess.options.OverrideTableName; | ||||||
| @@ -24,6 +28,8 @@ import jakarta.persistence.ManyToMany; | |||||||
| import jakarta.persistence.ManyToOne; | import jakarta.persistence.ManyToOne; | ||||||
| import jakarta.persistence.OneToMany; | import jakarta.persistence.OneToMany; | ||||||
| import jakarta.persistence.Table; | import jakarta.persistence.Table; | ||||||
|  | import jakarta.validation.constraints.DecimalMax; | ||||||
|  | import jakarta.validation.constraints.DecimalMin; | ||||||
| import jakarta.validation.constraints.Email; | import jakarta.validation.constraints.Email; | ||||||
| import jakarta.validation.constraints.Max; | import jakarta.validation.constraints.Max; | ||||||
| import jakarta.validation.constraints.Min; | import jakarta.validation.constraints.Min; | ||||||
| @@ -35,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) { | ||||||
| @@ -85,6 +109,18 @@ public class AnnotationTools { | |||||||
| 		return tmp; | 		return tmp; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	public static CollectionItemNotNull getCollectionItemNotNull(final Field element) { | ||||||
|  | 		return get(element, CollectionItemNotNull.class); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static CollectionItemUnique getCollectionItemUnique(final Field element) { | ||||||
|  | 		return get(element, CollectionItemUnique.class); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static CollectionNotEmpty getCollectionNotEmpty(final Field element) { | ||||||
|  | 		return get(element, CollectionNotEmpty.class); | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	public static boolean getSchemaReadOnly(final Field element) { | 	public static boolean getSchemaReadOnly(final Field element) { | ||||||
| 		final Annotation[] annotation = element.getDeclaredAnnotationsByType(Schema.class); | 		final Annotation[] annotation = element.getDeclaredAnnotationsByType(Schema.class); | ||||||
| 		if (annotation.length == 0) { | 		if (annotation.length == 0) { | ||||||
| @@ -134,51 +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 Long getConstraintsMax(final Field element) { | 	public static Checker[] getConstraintsCheckers(final Field element) { | ||||||
| 		final Annotation[] annotation = element.getDeclaredAnnotationsByType(Max.class); | 		return gets(element, Checker.class); | ||||||
| 		if (annotation.length == 0) { |  | ||||||
| 			return null; |  | ||||||
| 		} |  | ||||||
| 		return ((Max) annotation[0]).value(); |  | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	public static Long getConstraintsMin(final Field element) { | 	public static DecimalMin getConstraintsDecimalMin(final Field element) { | ||||||
| 		final Annotation[] annotation = element.getDeclaredAnnotationsByType(Min.class); | 		return get(element, DecimalMin.class); | ||||||
| 		if (annotation.length == 0) { | 	} | ||||||
| 			return null; |  | ||||||
| 		} | 	public static DecimalMax getConstraintsDecimalMax(final Field element) { | ||||||
| 		return ((Min) annotation[0]).value(); | 		return get(element, DecimalMax.class); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static Max getConstraintsMax(final Field element) { | ||||||
|  | 		return get(element, Max.class); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static Min getConstraintsMin(final Field element) { | ||||||
|  | 		return get(element, Min.class); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	public static int getLimitSize(final Field element) { | 	public static int getLimitSize(final Field element) { | ||||||
| @@ -191,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) { | ||||||
|   | |||||||
| @@ -5,13 +5,8 @@ import java.lang.annotation.Retention; | |||||||
| import java.lang.annotation.RetentionPolicy; | import java.lang.annotation.RetentionPolicy; | ||||||
| import java.lang.annotation.Target; | import java.lang.annotation.Target; | ||||||
|  |  | ||||||
| import org.kar.archidata.dataAccess.options.CheckFunctionInterface; |  | ||||||
| import org.kar.archidata.dataAccess.options.CheckFunctionVoid; |  | ||||||
|  |  | ||||||
| @Target({ ElementType.TYPE, ElementType.FIELD }) | @Target({ ElementType.TYPE, ElementType.FIELD }) | ||||||
| @Retention(RetentionPolicy.RUNTIME) | @Retention(RetentionPolicy.RUNTIME) | ||||||
| public @interface DataJson { | public @interface DataJson { | ||||||
| 	Class<? extends CheckFunctionInterface> checker() default CheckFunctionVoid.class; |  | ||||||
|  |  | ||||||
| 	Class<?> targetEntity() default Void.class; | 	Class<?> targetEntity() default Void.class; | ||||||
| } | } | ||||||
|   | |||||||
| @@ -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(); | ||||||
|  | } | ||||||
							
								
								
									
										14
									
								
								src/org/kar/archidata/annotation/checker/Checker.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								src/org/kar/archidata/annotation/checker/Checker.java
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,14 @@ | |||||||
|  | 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; | ||||||
|  |  | ||||||
|  | import org.kar.archidata.dataAccess.options.CheckFunctionInterface; | ||||||
|  |  | ||||||
|  | @Target({ ElementType.TYPE, ElementType.FIELD }) | ||||||
|  | @Retention(RetentionPolicy.RUNTIME) | ||||||
|  | public @interface Checker { | ||||||
|  | 	Class<? extends CheckFunctionInterface> value(); | ||||||
|  | } | ||||||
| @@ -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.FIELD) | ||||||
|  | @Retention(RetentionPolicy.RUNTIME) | ||||||
|  | public @interface CollectionItemNotNull { | ||||||
|  |  | ||||||
|  | } | ||||||
| @@ -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.FIELD) | ||||||
|  | @Retention(RetentionPolicy.RUNTIME) | ||||||
|  | public @interface CollectionItemUnique { | ||||||
|  |  | ||||||
|  | } | ||||||
| @@ -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.FIELD) | ||||||
|  | @Retention(RetentionPolicy.RUNTIME) | ||||||
|  | public @interface CollectionNotEmpty { | ||||||
|  |  | ||||||
|  | } | ||||||
| @@ -1,4 +1,4 @@ | |||||||
| package org.kar.archidata.annotation; | package org.kar.archidata.annotation.method; | ||||||
| 
 | 
 | ||||||
| import java.lang.annotation.ElementType; | import java.lang.annotation.ElementType; | ||||||
| import java.lang.annotation.Retention; | import java.lang.annotation.Retention; | ||||||
| @@ -1,4 +1,4 @@ | |||||||
| package org.kar.archidata.annotation; | package org.kar.archidata.annotation.method; | ||||||
| 
 | 
 | ||||||
| import java.lang.annotation.ElementType; | import java.lang.annotation.ElementType; | ||||||
| import java.lang.annotation.Retention; | import java.lang.annotation.Retention; | ||||||
| @@ -89,13 +89,18 @@ public class DataResource { | |||||||
|  |  | ||||||
| 	public static String getFileDataOld(final UUID uuid) { | 	public static String getFileDataOld(final UUID uuid) { | ||||||
| 		final String stringUUID = uuid.toString(); | 		final String stringUUID = uuid.toString(); | ||||||
| 		final String filePath = ConfigBaseVariable.getMediaDataFolder() + File.separator + stringUUID + File.separator | 		final String part1 = stringUUID.substring(0, 2); | ||||||
| 				+ "data"; | 		final String part2 = stringUUID.substring(2, 4); | ||||||
|  | 		final String part3 = stringUUID.substring(4); | ||||||
|  | 		final String finalPath = part1 + File.separator + part2; | ||||||
|  | 		String filePath = ConfigBaseVariable.getMediaDataFolder() + "_uuid" + File.separator + finalPath | ||||||
|  | 				+ File.separator; | ||||||
| 		try { | 		try { | ||||||
| 			createFolder(ConfigBaseVariable.getMediaDataFolder() + File.separator + stringUUID + File.separator); | 			createFolder(filePath); | ||||||
| 		} catch (final IOException e) { | 		} catch (final IOException e) { | ||||||
| 			e.printStackTrace(); | 			e.printStackTrace(); | ||||||
| 		} | 		} | ||||||
|  | 		filePath += part3; | ||||||
| 		return filePath; | 		return filePath; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|   | |||||||
| @@ -14,7 +14,7 @@ public class ExceptionCatcher implements ExceptionMapper<Exception> { | |||||||
| 	public Response toResponse(final Exception exception) { | 	public Response toResponse(final Exception exception) { | ||||||
| 		LOGGER.warn("Catch exception (not managed...):"); | 		LOGGER.warn("Catch exception (not managed...):"); | ||||||
| 		final RestErrorResponse ret = build(exception); | 		final RestErrorResponse ret = build(exception); | ||||||
| 		LOGGER.error("Error UUID={}", ret.uuid); | 		LOGGER.error("Error OID={}", ret.oid); | ||||||
| 		exception.printStackTrace(); | 		exception.printStackTrace(); | ||||||
| 		return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(ret).type(MediaType.APPLICATION_JSON) | 		return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(ret).type(MediaType.APPLICATION_JSON) | ||||||
| 				.build(); | 				.build(); | ||||||
|   | |||||||
| @@ -15,7 +15,7 @@ public class FailExceptionCatcher implements ExceptionMapper<FailException> { | |||||||
| 	public Response toResponse(final FailException exception) { | 	public Response toResponse(final FailException exception) { | ||||||
| 		LOGGER.warn("Catch FailException: {}", exception.getLocalizedMessage()); | 		LOGGER.warn("Catch FailException: {}", exception.getLocalizedMessage()); | ||||||
| 		final RestErrorResponse ret = build(exception); | 		final RestErrorResponse ret = build(exception); | ||||||
| 		LOGGER.error("Error UUID={}", ret.uuid); | 		LOGGER.error("Error OID={}", ret.oid); | ||||||
| 		if (exception.exception != null) { | 		if (exception.exception != null) { | ||||||
| 			exception.exception.printStackTrace(); | 			exception.exception.printStackTrace(); | ||||||
| 		} | 		} | ||||||
|   | |||||||
| @@ -8,19 +8,35 @@ import jakarta.ws.rs.core.MediaType; | |||||||
| import jakarta.ws.rs.core.Response; | import jakarta.ws.rs.core.Response; | ||||||
| import jakarta.ws.rs.ext.ExceptionMapper; | import jakarta.ws.rs.ext.ExceptionMapper; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * This class catches InputException and maps it to a HTTP response. | ||||||
|  |  */ | ||||||
| public class InputExceptionCatcher implements ExceptionMapper<InputException> { | public class InputExceptionCatcher implements ExceptionMapper<InputException> { | ||||||
| 	private static final Logger LOGGER = LoggerFactory.getLogger(InputExceptionCatcher.class); | 	private static final Logger LOGGER = LoggerFactory.getLogger(InputExceptionCatcher.class); | ||||||
|  |  | ||||||
|  | 	/** | ||||||
|  | 	 * This method is called when an InputException is thrown. | ||||||
|  | 	 * It logs the exception and builds a response with the error details. | ||||||
|  | 	 * | ||||||
|  | 	 * @param exception the InputException that was thrown | ||||||
|  | 	 * @return a Response object containing the error details | ||||||
|  | 	 */ | ||||||
| 	@Override | 	@Override | ||||||
| 	public Response toResponse(final InputException exception) { | 	public Response toResponse(final InputException exception) { | ||||||
| 		LOGGER.warn("Catch InputException:"); | 		LOGGER.warn("Catch InputException:"); | ||||||
| 		final RestErrorResponse ret = build(exception); | 		final RestErrorResponse ret = build(exception); | ||||||
| 		LOGGER.error("Error UUID={} ==> '{}'=>'{}'", ret.uuid, exception.missingVariable, | 		LOGGER.error("Error OID={} ==> '{}'=>'{}'", ret.oid, exception.missingVariable, | ||||||
| 				exception.getLocalizedMessage()); | 				exception.getLocalizedMessage()); | ||||||
| 		// exception.printStackTrace(); | 		// exception.printStackTrace(); | ||||||
| 		return Response.status(exception.status).entity(ret).type(MediaType.APPLICATION_JSON).build(); | 		return Response.status(exception.status).entity(ret).type(MediaType.APPLICATION_JSON).build(); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	/** | ||||||
|  | 	 * This method builds a RestErrorResponse object from the InputException. | ||||||
|  | 	 * | ||||||
|  | 	 * @param exception the InputException that was thrown | ||||||
|  | 	 * @return a RestErrorResponse object containing the error details | ||||||
|  | 	 */ | ||||||
| 	private RestErrorResponse build(final InputException exception) { | 	private RestErrorResponse build(final InputException exception) { | ||||||
| 		return new RestErrorResponse(exception.status, "Error on input='" + exception.missingVariable + "'", | 		return new RestErrorResponse(exception.status, "Error on input='" + exception.missingVariable + "'", | ||||||
| 				exception.getMessage()); | 				exception.getMessage()); | ||||||
|   | |||||||
| @@ -12,16 +12,29 @@ import jakarta.ws.rs.ext.ExceptionMapper; | |||||||
| public class JacksonExceptionCatcher implements ExceptionMapper<JacksonException> { | public class JacksonExceptionCatcher implements ExceptionMapper<JacksonException> { | ||||||
| 	private static final Logger LOGGER = LoggerFactory.getLogger(JacksonExceptionCatcher.class); | 	private static final Logger LOGGER = LoggerFactory.getLogger(JacksonExceptionCatcher.class); | ||||||
|  |  | ||||||
|  | 	/** | ||||||
|  | 	 * This method is called when a JacksonException is thrown. | ||||||
|  | 	 * It logs the exception, builds a response with the error details, and returns it. | ||||||
|  | 	 * | ||||||
|  | 	 * @param exception the JacksonException that was thrown | ||||||
|  | 	 * @return a Response object containing the error details | ||||||
|  | 	 */ | ||||||
| 	@Override | 	@Override | ||||||
| 	public Response toResponse(final JacksonException exception) { | 	public Response toResponse(final JacksonException exception) { | ||||||
| 		LOGGER.warn("Catch exception Input data parsing:"); | 		LOGGER.warn("Catch exception Input data parsing:"); | ||||||
| 		final RestErrorResponse ret = build(exception); | 		final RestErrorResponse ret = build(exception); | ||||||
| 		LOGGER.error("Error UUID={}", ret.uuid); | 		LOGGER.error("Error OID={}", ret.oid); | ||||||
| 		exception.printStackTrace(); | 		exception.printStackTrace(); | ||||||
| 		return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(ret).type(MediaType.APPLICATION_JSON) | 		return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(ret).type(MediaType.APPLICATION_JSON) | ||||||
| 				.build(); | 				.build(); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	/** | ||||||
|  | 	 * Builds a RestErrorResponse object from the given exception. | ||||||
|  | 	 * | ||||||
|  | 	 * @param exception the Exception that was thrown | ||||||
|  | 	 * @return a RestErrorResponse object containing the error details | ||||||
|  | 	 */ | ||||||
| 	private RestErrorResponse build(final Exception exception) { | 	private RestErrorResponse build(final Exception exception) { | ||||||
| 		return new RestErrorResponse(Response.Status.INTERNAL_SERVER_ERROR, "Catch JSON Exception", | 		return new RestErrorResponse(Response.Status.INTERNAL_SERVER_ERROR, "Catch JSON Exception", | ||||||
| 				exception.getMessage()); | 				exception.getMessage()); | ||||||
|   | |||||||
| @@ -1,10 +1,9 @@ | |||||||
| package org.kar.archidata.catcher; | package org.kar.archidata.catcher; | ||||||
|  |  | ||||||
| import java.time.Instant; | import java.time.Instant; | ||||||
| import java.util.UUID; |  | ||||||
|  |  | ||||||
|  | import org.bson.types.ObjectId; | ||||||
| import org.kar.archidata.annotation.NoWriteSpecificMode; | import org.kar.archidata.annotation.NoWriteSpecificMode; | ||||||
| import org.kar.archidata.tools.UuidUtils; |  | ||||||
|  |  | ||||||
| import jakarta.persistence.Column; | import jakarta.persistence.Column; | ||||||
| import jakarta.validation.constraints.NotNull; | import jakarta.validation.constraints.NotNull; | ||||||
| @@ -12,7 +11,7 @@ import jakarta.ws.rs.core.Response; | |||||||
|  |  | ||||||
| @NoWriteSpecificMode | @NoWriteSpecificMode | ||||||
| public class RestErrorResponse { | public class RestErrorResponse { | ||||||
| 	public UUID uuid = UuidUtils.nextUUID(); | 	public ObjectId oid = new ObjectId(); | ||||||
| 	@NotNull | 	@NotNull | ||||||
| 	@Column(length = 0) | 	@Column(length = 0) | ||||||
| 	public String name; // Mandatory for TS generic error | 	public String name; // Mandatory for TS generic error | ||||||
|   | |||||||
| @@ -15,7 +15,7 @@ public class SystemExceptionCatcher implements ExceptionMapper<SystemException> | |||||||
| 	public Response toResponse(final SystemException exception) { | 	public Response toResponse(final SystemException exception) { | ||||||
| 		LOGGER.warn("Catch SystemException:"); | 		LOGGER.warn("Catch SystemException:"); | ||||||
| 		final RestErrorResponse ret = build(exception); | 		final RestErrorResponse ret = build(exception); | ||||||
| 		LOGGER.error("Error UUID={}", ret.uuid); | 		LOGGER.error("Error OID={}", ret.oid); | ||||||
| 		exception.printStackTrace(); | 		exception.printStackTrace(); | ||||||
| 		return Response.status(exception.status).entity(ret).type(MediaType.APPLICATION_JSON).build(); | 		return Response.status(exception.status).entity(ret).type(MediaType.APPLICATION_JSON).build(); | ||||||
| 	} | 	} | ||||||
|   | |||||||
| @@ -14,7 +14,7 @@ public class WebApplicationExceptionCatcher implements ExceptionMapper<WebApplic | |||||||
| 	@Override | 	@Override | ||||||
| 	public Response toResponse(final WebApplicationException exception) { | 	public Response toResponse(final WebApplicationException exception) { | ||||||
| 		final RestErrorResponse ret = build(exception); | 		final RestErrorResponse ret = build(exception); | ||||||
| 		LOGGER.error("Error UUID={}", ret.uuid); | 		LOGGER.error("Error OID={}", ret.oid); | ||||||
| 		return Response.status(exception.getResponse().getStatusInfo().toEnum()).entity(ret) | 		return Response.status(exception.getResponse().getStatusInfo().toEnum()).entity(ret) | ||||||
| 				.type(MediaType.APPLICATION_JSON).build(); | 				.type(MediaType.APPLICATION_JSON).build(); | ||||||
| 	} | 	} | ||||||
|   | |||||||
							
								
								
									
										898
									
								
								src/org/kar/archidata/checker/CheckJPA.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										898
									
								
								src/org/kar/archidata/checker/CheckJPA.java
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,898 @@ | |||||||
|  | package org.kar.archidata.checker; | ||||||
|  |  | ||||||
|  | import java.lang.reflect.Field; | ||||||
|  | import java.sql.Timestamp; | ||||||
|  | import java.time.LocalDate; | ||||||
|  | import java.time.LocalTime; | ||||||
|  | import java.util.ArrayList; | ||||||
|  | import java.util.Collection; | ||||||
|  | import java.util.Date; | ||||||
|  | import java.util.HashMap; | ||||||
|  | import java.util.HashSet; | ||||||
|  | import java.util.List; | ||||||
|  | import java.util.Map; | ||||||
|  | import java.util.Set; | ||||||
|  | import java.util.regex.Pattern; | ||||||
|  |  | ||||||
|  | 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.CollectionItemNotNull; | ||||||
|  | import org.kar.archidata.annotation.checker.CollectionItemUnique; | ||||||
|  | import org.kar.archidata.annotation.checker.CollectionNotEmpty; | ||||||
|  | import org.kar.archidata.dataAccess.DBAccess; | ||||||
|  | import org.kar.archidata.dataAccess.QueryCondition; | ||||||
|  | import org.kar.archidata.dataAccess.QueryOptions; | ||||||
|  | import org.kar.archidata.dataAccess.options.CheckFunctionInterface; | ||||||
|  | import org.kar.archidata.dataAccess.options.CheckFunctionVoid; | ||||||
|  | import org.kar.archidata.dataAccess.options.Condition; | ||||||
|  | import org.kar.archidata.dataAccess.options.ConditionChecker; | ||||||
|  | import org.kar.archidata.exception.DataAccessException; | ||||||
|  | import org.kar.archidata.exception.InputException; | ||||||
|  | import org.slf4j.Logger; | ||||||
|  | import org.slf4j.LoggerFactory; | ||||||
|  |  | ||||||
|  | import jakarta.persistence.ManyToOne; | ||||||
|  | import jakarta.validation.constraints.DecimalMax; | ||||||
|  | import jakarta.validation.constraints.DecimalMin; | ||||||
|  | import jakarta.validation.constraints.Max; | ||||||
|  | import jakarta.validation.constraints.Min; | ||||||
|  | import jakarta.validation.constraints.Size; | ||||||
|  |  | ||||||
|  | public class CheckJPA<T> implements CheckFunctionInterface { | ||||||
|  |  | ||||||
|  | 	private static final Logger LOGGER = LoggerFactory.getLogger(CheckJPA.class); | ||||||
|  | 	private final Class<?> clazz; | ||||||
|  |  | ||||||
|  | 	/** By default some element are not read like createAt and UpdatedAt. This option permit to read it. */ | ||||||
|  | 	public interface CheckInterface<K> { | ||||||
|  | 		/** This function implementation is design to check if the updated class is valid of not for insertion | ||||||
|  | 		 * @param ioDb Access on the Data-Base | ||||||
|  | 		 * @param baseName Base of the name input that is displayed in exception generated. | ||||||
|  | 		 * @param data The object that might be injected. | ||||||
|  | 		 * @param modifiedValue List of fields that modification is requested. | ||||||
|  | 		 * @param options Some query option that the checker can need to generate basic check. | ||||||
|  | 		 * @throws Exception Exception is generate if the data are incorrect. */ | ||||||
|  | 		void check( | ||||||
|  | 				final DBAccess ioDb, | ||||||
|  | 				final String baseName, | ||||||
|  | 				final K data, | ||||||
|  | 				List<String> modifiedValue, | ||||||
|  | 				final QueryOptions options) throws Exception; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	protected Map<String, List<CheckInterface<T>>> checking = null; | ||||||
|  |  | ||||||
|  | 	protected void add(final String field, final CheckInterface<T> checkFunction) throws DataAccessException { | ||||||
|  | 		if (!AnnotationTools.hasFieldsName(this.clazz, field)) { | ||||||
|  | 			LOGGER.error("Try to add a JPA Filter on an inexistant Field: '{}' not in {}", field, | ||||||
|  | 					AnnotationTools.getAllFieldsNames(this.clazz)); | ||||||
|  | 			throw new DataAccessException("Try to add a JPA Filter on an inexistant Field: '" + field + "' not in " | ||||||
|  | 					+ AnnotationTools.getAllFieldsNames(this.clazz)); | ||||||
|  | 		} | ||||||
|  | 		List<CheckInterface<T>> actions = this.checking.get(field); | ||||||
|  | 		if (actions == null) { | ||||||
|  | 			actions = new ArrayList<>(); | ||||||
|  | 			this.checking.put(field, actions); | ||||||
|  | 		} | ||||||
|  | 		actions.add(checkFunction); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public CheckJPA(final Class<T> clazz) { | ||||||
|  | 		this.clazz = clazz; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public void initialize() throws Exception { | ||||||
|  | 		if (this.checking != null) { | ||||||
|  | 			return; | ||||||
|  | 		} | ||||||
|  | 		try { | ||||||
|  | 			this.checking = new HashMap<>(); | ||||||
|  | 			// create Table: | ||||||
|  | 			final List<String> primaryKeys = new ArrayList<>(); | ||||||
|  | 			for (final Field field : this.clazz.getFields()) { | ||||||
|  | 				final String fieldName = field.getName(); // AnnotationTools.getFieldName(field); | ||||||
|  | 				if (AnnotationTools.isPrimaryKey(field)) { | ||||||
|  | 					add(fieldName, | ||||||
|  | 							( | ||||||
|  | 									final DBAccess ioDb, | ||||||
|  | 									final String baseName, | ||||||
|  | 									final T data, | ||||||
|  | 									final List<String> modifiedValue, | ||||||
|  | 									final QueryOptions options) -> { | ||||||
|  | 								throw new InputException(baseName + fieldName, | ||||||
|  | 										"This is a '@Id' (primaryKey) ==> can not be change"); | ||||||
|  | 							}); | ||||||
|  | 				} | ||||||
|  | 				if (AnnotationTools.getConstraintsNotNull(field)) { | ||||||
|  | 					add(fieldName, | ||||||
|  | 							( | ||||||
|  | 									final DBAccess ioDb, | ||||||
|  | 									final String baseName, | ||||||
|  | 									final T data, | ||||||
|  | 									final List<String> modifiedValue, | ||||||
|  | 									final QueryOptions options) -> { | ||||||
|  | 								if (field.get(data) == null) { | ||||||
|  | 									throw new InputException(baseName + fieldName, "Can not be null"); | ||||||
|  | 								} | ||||||
|  | 							}); | ||||||
|  | 				} | ||||||
|  | 				if (AnnotationTools.isCreatedAtField(field) || AnnotationTools.isUpdateAtField(field)) { | ||||||
|  | 					add(fieldName, | ||||||
|  | 							( | ||||||
|  | 									final DBAccess ioDb, | ||||||
|  | 									final String baseName, | ||||||
|  | 									final T data, | ||||||
|  | 									final List<String> modifiedValue, | ||||||
|  | 									final QueryOptions options) -> { | ||||||
|  | 								throw new InputException(baseName + fieldName, "It is forbidden to change this field"); | ||||||
|  | 							}); | ||||||
|  | 				} | ||||||
|  |  | ||||||
|  | 				final Class<?> type = field.getType(); | ||||||
|  | 				if (type == Long.class || type == long.class) { | ||||||
|  | 					final DecimalMax maxValueDecimal = AnnotationTools.getConstraintsDecimalMax(field); | ||||||
|  | 					if (maxValueDecimal != null) { | ||||||
|  | 						final long maxValue = Long.parseLong(maxValueDecimal.value()); | ||||||
|  | 						final boolean inclusive = maxValueDecimal.inclusive(); | ||||||
|  | 						final String exceptionComment = "Value too height max=" + maxValue | ||||||
|  | 								+ (inclusive ? " (inclusive)" : " (exclusive)"); | ||||||
|  | 						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 elemTyped = (Long) elem; | ||||||
|  | 									if (inclusive) { | ||||||
|  | 										if (elemTyped > maxValue) { | ||||||
|  | 											throw new InputException(baseName + fieldName, exceptionComment); | ||||||
|  | 										} | ||||||
|  | 									} else if (elemTyped >= maxValue) { | ||||||
|  | 										throw new InputException(baseName + fieldName, exceptionComment); | ||||||
|  | 									} | ||||||
|  | 								}); | ||||||
|  | 					} | ||||||
|  | 					final DecimalMin minValueDecimal = AnnotationTools.getConstraintsDecimalMin(field); | ||||||
|  | 					if (minValueDecimal != null) { | ||||||
|  | 						final long minValue = Long.parseLong(minValueDecimal.value()); | ||||||
|  | 						final boolean inclusive = minValueDecimal.inclusive(); | ||||||
|  | 						final String exceptionComment = "Value too low min=" + minValue | ||||||
|  | 								+ (inclusive ? " (inclusive)" : " (exclusive)"); | ||||||
|  | 						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 elemTyped = (Long) elem; | ||||||
|  | 									if (inclusive) { | ||||||
|  | 										if (elemTyped < minValue) { | ||||||
|  | 											throw new InputException(baseName + fieldName, exceptionComment); | ||||||
|  | 										} | ||||||
|  | 									} else if (elemTyped <= minValue) { | ||||||
|  | 										throw new InputException(baseName + fieldName, exceptionComment); | ||||||
|  | 									} | ||||||
|  | 								}); | ||||||
|  | 					} | ||||||
|  | 					final Max maxValue = AnnotationTools.getConstraintsMax(field); | ||||||
|  | 					if (maxValue != null) { | ||||||
|  | 						final Long maxValueTmp = maxValue.value(); | ||||||
|  | 						final String exceptionComment = "Value too height max=" + maxValueTmp + " (inclusive)"; | ||||||
|  | 						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 elemTyped = (Long) elem; | ||||||
|  | 									if (elemTyped > maxValueTmp) { | ||||||
|  | 										throw new InputException(baseName + fieldName, exceptionComment); | ||||||
|  | 									} | ||||||
|  | 								}); | ||||||
|  | 					} | ||||||
|  | 					final Min minValue = AnnotationTools.getConstraintsMin(field); | ||||||
|  | 					if (minValue != null) { | ||||||
|  | 						final Long minValueTmp = minValue.value(); | ||||||
|  | 						final String exceptionComment = "Value too low min=" + minValueTmp + " (inclusive)"; | ||||||
|  | 						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 elemTyped = (Long) elem; | ||||||
|  | 									if (elemTyped < minValueTmp) { | ||||||
|  | 										throw new InputException(baseName + fieldName, exceptionComment); | ||||||
|  | 									} | ||||||
|  | 								}); | ||||||
|  | 					} | ||||||
|  | 				} else if (type == Integer.class || type == int.class) { | ||||||
|  | 					final DecimalMax maxValueDecimal = AnnotationTools.getConstraintsDecimalMax(field); | ||||||
|  | 					if (maxValueDecimal != null) { | ||||||
|  | 						final int maxValue = Integer.parseInt(maxValueDecimal.value()); | ||||||
|  | 						final boolean inclusive = maxValueDecimal.inclusive(); | ||||||
|  | 						final String exceptionComment = "Value too height max=" + maxValue | ||||||
|  | 								+ (inclusive ? " (inclusive)" : " (exclusive)"); | ||||||
|  | 						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 Integer elemTyped = (Integer) elem; | ||||||
|  | 									if (inclusive) { | ||||||
|  | 										if (elemTyped > maxValue) { | ||||||
|  | 											throw new InputException(baseName + fieldName, exceptionComment); | ||||||
|  | 										} | ||||||
|  | 									} else if (elemTyped >= maxValue) { | ||||||
|  |  | ||||||
|  | 										throw new InputException(baseName + fieldName, exceptionComment); | ||||||
|  | 									} | ||||||
|  | 								}); | ||||||
|  | 					} | ||||||
|  | 					final DecimalMin minValueDecimal = AnnotationTools.getConstraintsDecimalMin(field); | ||||||
|  | 					if (minValueDecimal != null) { | ||||||
|  | 						final int minValue = Integer.parseInt(minValueDecimal.value()); | ||||||
|  | 						final boolean inclusive = minValueDecimal.inclusive(); | ||||||
|  | 						final String exceptionComment = "Value too low min=" + minValue | ||||||
|  | 								+ (inclusive ? " (inclusive)" : " (exclusive)"); | ||||||
|  | 						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 Integer elemTyped = (Integer) elem; | ||||||
|  | 									if (inclusive) { | ||||||
|  | 										if (elemTyped < minValue) { | ||||||
|  | 											throw new InputException(baseName + fieldName, exceptionComment); | ||||||
|  | 										} | ||||||
|  | 									} else if (elemTyped <= minValue) { | ||||||
|  | 										throw new InputException(baseName + fieldName, exceptionComment); | ||||||
|  | 									} | ||||||
|  | 								}); | ||||||
|  | 					} | ||||||
|  | 					final Max maxValueRoot = AnnotationTools.getConstraintsMax(field); | ||||||
|  | 					if (maxValueRoot != null) { | ||||||
|  | 						final int maxValue = (int) maxValueRoot.value(); | ||||||
|  | 						final String exceptionComment = "Value too height max=" + maxValue + " (inclusive)"; | ||||||
|  | 						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 Integer elemTyped = (Integer) elem; | ||||||
|  | 									if (elemTyped > maxValue) { | ||||||
|  | 										throw new InputException(baseName + fieldName, exceptionComment); | ||||||
|  | 									} | ||||||
|  | 								}); | ||||||
|  | 					} | ||||||
|  | 					final Min minValueRoot = AnnotationTools.getConstraintsMin(field); | ||||||
|  | 					if (minValueRoot != null) { | ||||||
|  | 						final int minValue = (int) minValueRoot.value(); | ||||||
|  | 						final String exceptionComment = "Value too low min=" + minValue + " (inclusive)"; | ||||||
|  | 						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 Integer elemTyped = (Integer) elem; | ||||||
|  | 									if (elemTyped < minValue) { | ||||||
|  | 										throw new InputException(baseName + fieldName, exceptionComment); | ||||||
|  | 									} | ||||||
|  | 								}); | ||||||
|  | 					} | ||||||
|  | 				} else if (type == Boolean.class || type == boolean.class) { | ||||||
|  |  | ||||||
|  | 				} else if (type == Float.class || type == float.class) { | ||||||
|  | 					final DecimalMax maxValueDecimal = AnnotationTools.getConstraintsDecimalMax(field); | ||||||
|  | 					if (maxValueDecimal != null) { | ||||||
|  | 						final float maxValue = Float.parseFloat(maxValueDecimal.value()); | ||||||
|  | 						final boolean inclusive = maxValueDecimal.inclusive(); | ||||||
|  | 						final String exceptionComment = "Value too height max=" + maxValue | ||||||
|  | 								+ (inclusive ? " (inclusive)" : " (exclusive)"); | ||||||
|  | 						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 Float elemTyped = (Float) elem; | ||||||
|  | 									if (inclusive) { | ||||||
|  | 										if (elemTyped > maxValue) { | ||||||
|  | 											throw new InputException(baseName + fieldName, exceptionComment); | ||||||
|  | 										} | ||||||
|  | 									} else if (elemTyped >= maxValue) { | ||||||
|  | 										throw new InputException(baseName + fieldName, exceptionComment); | ||||||
|  | 									} | ||||||
|  | 								}); | ||||||
|  | 					} | ||||||
|  | 					final DecimalMin minValueDecimal = AnnotationTools.getConstraintsDecimalMin(field); | ||||||
|  | 					if (minValueDecimal != null) { | ||||||
|  | 						final float minValue = Float.parseFloat(minValueDecimal.value()); | ||||||
|  | 						final boolean inclusive = minValueDecimal.inclusive(); | ||||||
|  | 						final String exceptionComment = "Value too low min=" + minValue | ||||||
|  | 								+ (inclusive ? " (inclusive)" : " (exclusive)"); | ||||||
|  | 						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 Float elemTyped = (Float) elem; | ||||||
|  | 									if (inclusive) { | ||||||
|  | 										if (elemTyped < minValue) { | ||||||
|  | 											throw new InputException(baseName + fieldName, exceptionComment); | ||||||
|  | 										} | ||||||
|  | 									} else if (elemTyped <= minValue) { | ||||||
|  | 										throw new InputException(baseName + fieldName, exceptionComment); | ||||||
|  | 									} | ||||||
|  | 								}); | ||||||
|  | 					} | ||||||
|  | 					final Max maxValueRoot = AnnotationTools.getConstraintsMax(field); | ||||||
|  | 					if (maxValueRoot != null) { | ||||||
|  | 						final float maxValue = maxValueRoot.value(); | ||||||
|  | 						final String exceptionComment = "Value too height max=" + maxValue + " (inclusive)"; | ||||||
|  | 						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 Float elemTyped = (Float) elem; | ||||||
|  |  | ||||||
|  | 									if (elemTyped > maxValue) { | ||||||
|  | 										throw new InputException(baseName + fieldName, exceptionComment); | ||||||
|  | 									} | ||||||
|  | 								}); | ||||||
|  | 					} | ||||||
|  | 					final Min minValueRoot = AnnotationTools.getConstraintsMin(field); | ||||||
|  | 					if (minValueRoot != null) { | ||||||
|  | 						final float minValue = minValueRoot.value(); | ||||||
|  | 						final String exceptionComment = "Value too low min=" + minValue + " (inclusive)"; | ||||||
|  | 						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 Float elemTyped = (Float) elem; | ||||||
|  | 									if (elemTyped < minValue) { | ||||||
|  | 										throw new InputException(baseName + fieldName, exceptionComment); | ||||||
|  | 									} | ||||||
|  | 								}); | ||||||
|  | 					} | ||||||
|  | 				} else if (type == Double.class || type == double.class) { | ||||||
|  | 					final DecimalMax maxValueDecimal = AnnotationTools.getConstraintsDecimalMax(field); | ||||||
|  | 					if (maxValueDecimal != null) { | ||||||
|  | 						final double maxValue = Float.parseFloat(maxValueDecimal.value()); | ||||||
|  | 						final boolean inclusive = maxValueDecimal.inclusive(); | ||||||
|  | 						final String exceptionComment = "Value too height max=" + maxValue | ||||||
|  | 								+ (inclusive ? " (inclusive)" : " (exclusive)"); | ||||||
|  | 						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 Double elemTyped = (Double) elem; | ||||||
|  | 									if (inclusive) { | ||||||
|  | 										if (elemTyped > maxValue) { | ||||||
|  | 											throw new InputException(baseName + fieldName, exceptionComment); | ||||||
|  | 										} | ||||||
|  | 									} else if (elemTyped >= maxValue) { | ||||||
|  | 										throw new InputException(baseName + fieldName, exceptionComment); | ||||||
|  | 									} | ||||||
|  | 								}); | ||||||
|  | 					} | ||||||
|  | 					final DecimalMin minValueDecimal = AnnotationTools.getConstraintsDecimalMin(field); | ||||||
|  | 					if (minValueDecimal != null) { | ||||||
|  | 						final double minValue = Float.parseFloat(minValueDecimal.value()); | ||||||
|  | 						final boolean inclusive = minValueDecimal.inclusive(); | ||||||
|  | 						final String exceptionComment = "Value too low min=" + minValue | ||||||
|  | 								+ (inclusive ? " (inclusive)" : " (exclusive)"); | ||||||
|  | 						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 Double elemTyped = (Double) elem; | ||||||
|  | 									if (inclusive) { | ||||||
|  | 										if (elemTyped < minValue) { | ||||||
|  | 											throw new InputException(baseName + fieldName, | ||||||
|  | 													"Value too Low min: " + minValue); | ||||||
|  | 										} | ||||||
|  | 									} else if (elemTyped <= minValue) { | ||||||
|  | 										throw new InputException(baseName + fieldName, exceptionComment); | ||||||
|  | 									} | ||||||
|  | 								}); | ||||||
|  | 					} | ||||||
|  | 					final Max maxValueRoot = AnnotationTools.getConstraintsMax(field); | ||||||
|  | 					if (maxValueRoot != null) { | ||||||
|  | 						final double maxValue = maxValueRoot.value(); | ||||||
|  | 						final String exceptionComment = "Value too height max=" + maxValue + " (inclusive)"; | ||||||
|  | 						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 Double elemTyped = (Double) elem; | ||||||
|  | 									if (elemTyped > maxValue) { | ||||||
|  | 										throw new InputException(baseName + fieldName, exceptionComment); | ||||||
|  | 									} | ||||||
|  | 								}); | ||||||
|  | 					} | ||||||
|  | 					final Min minValueRoot = AnnotationTools.getConstraintsMin(field); | ||||||
|  | 					if (minValueRoot != null) { | ||||||
|  | 						final double minValue = minValueRoot.value(); | ||||||
|  | 						final String exceptionComment = "Value too low min=" + minValue + " (inclusive)"; | ||||||
|  | 						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 Double elemTyped = (Double) elem; | ||||||
|  | 									if (elemTyped < minValue) { | ||||||
|  | 										throw new InputException(baseName + fieldName, exceptionComment); | ||||||
|  | 									} | ||||||
|  | 								}); | ||||||
|  | 					} | ||||||
|  | 				} else if (type == Date.class || type == Timestamp.class) { | ||||||
|  |  | ||||||
|  | 				} else if (type == LocalDate.class) { | ||||||
|  |  | ||||||
|  | 				} else if (type == LocalTime.class) { | ||||||
|  |  | ||||||
|  | 				} else if (type == String.class) { | ||||||
|  | 					final Size limitSize = AnnotationTools.getConstraintsSize(field); | ||||||
|  | 					if (limitSize != 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 String elemTyped = (String) elem; | ||||||
|  | 									if (elemTyped.length() > limitSize.max()) { | ||||||
|  | 										throw new InputException(baseName + fieldName, | ||||||
|  | 												"Too long size (constraints) must be <= " + limitSize.max()); | ||||||
|  | 									} | ||||||
|  | 									if (elemTyped.length() < limitSize.min()) { | ||||||
|  | 										throw new InputException(baseName + fieldName, | ||||||
|  | 												"Too small size (constraints) must be >= " + limitSize.min()); | ||||||
|  | 									} | ||||||
|  | 								}); | ||||||
|  | 					} | ||||||
|  | 					final jakarta.validation.constraints.Pattern patternString = AnnotationTools | ||||||
|  | 							.getConstraintsPattern(field); | ||||||
|  | 					if (patternString != null && patternString.regexp() != null) { | ||||||
|  | 						final Pattern pattern = Pattern.compile(patternString.regexp()); | ||||||
|  | 						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 (!pattern.matcher(elemTyped).find()) { | ||||||
|  | 										throw new InputException(baseName + fieldName, | ||||||
|  | 												"does not match the required pattern (constraints) must be '" + pattern | ||||||
|  | 														+ "'"); | ||||||
|  | 									} | ||||||
|  | 								}); | ||||||
|  | 					} | ||||||
|  | 					if (AnnotationTools.getConstraintsEmail(field) != null) { | ||||||
|  | 						final String emailPattern = "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$"; | ||||||
|  | 						final Pattern pattern = Pattern.compile(emailPattern); | ||||||
|  | 						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 (!pattern.matcher(elemTyped).find()) { | ||||||
|  | 										throw new InputException(baseName + fieldName, | ||||||
|  | 												"does not match the required pattern[email] (constraints) must be '" | ||||||
|  | 														+ emailPattern + "'"); | ||||||
|  | 									} | ||||||
|  | 								}); | ||||||
|  | 					} | ||||||
|  | 				} else if (type.isEnum()) { | ||||||
|  | 					// nothing to do. | ||||||
|  | 				} | ||||||
|  | 				final Checker[] checkers = AnnotationTools.getConstraintsCheckers(field); | ||||||
|  | 				if (checkers != null) { | ||||||
|  | 					for (final Checker checker : checkers) { | ||||||
|  | 						if (checker == null || checker.value() == CheckFunctionVoid.class) { | ||||||
|  | 							continue; | ||||||
|  | 						} | ||||||
|  | 						final CheckFunctionInterface checkerInstance = checker.value().getDeclaredConstructor() | ||||||
|  | 								.newInstance(); | ||||||
|  | 						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 Collection<?> tmpCollection = (Collection<?>) tmpData; | ||||||
|  | 										final Object[] elements = tmpCollection.toArray(); | ||||||
|  | 										for (int iii = 0; iii < elements.length; iii++) { | ||||||
|  | 											if (elements[iii] != null) { | ||||||
|  | 												checkerInstance.check(ioDb, baseName + fieldName + '[' + iii + "].", | ||||||
|  | 														elements[iii], null, options); | ||||||
|  | 											} | ||||||
|  | 										} | ||||||
|  | 									}); | ||||||
|  | 						} else { | ||||||
|  | 							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; | ||||||
|  | 										} | ||||||
|  | 										checkerInstance.check(ioDb, baseName + fieldName + '.', tmpData, null, options); | ||||||
|  | 									}); | ||||||
|  | 						} | ||||||
|  | 					} | ||||||
|  | 				} | ||||||
|  | 				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); | ||||||
|  | 				if (collectionUnique != null) { | ||||||
|  | 					if (!Collection.class.isAssignableFrom(field.getType())) { | ||||||
|  | 						throw new DataAccessException( | ||||||
|  | 								"Request @CollectionItemUnique on a non collection field: '" + fieldName + "'"); | ||||||
|  | 					} | ||||||
|  | 					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 Collection<?> tmpCollection = (Collection<?>) tmpData; | ||||||
|  | 								final Set<Object> uniqueValues = new HashSet<>(tmpCollection); | ||||||
|  | 								if (uniqueValues.size() != tmpCollection.size()) { | ||||||
|  | 									throw new InputException(baseName + fieldName, | ||||||
|  | 											"Cannot insert multiple times the same elements"); | ||||||
|  | 								} | ||||||
|  | 							}); | ||||||
|  | 				} | ||||||
|  | 				final CollectionItemNotNull collectionNotNull = AnnotationTools.getCollectionItemNotNull(field); | ||||||
|  | 				if (collectionNotNull != null) { | ||||||
|  | 					if (!Collection.class.isAssignableFrom(field.getType())) { | ||||||
|  | 						throw new DataAccessException( | ||||||
|  | 								"Request @CollectionItemNotNull on a non collection field: '" + fieldName + "'"); | ||||||
|  | 					} | ||||||
|  | 					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 Collection<?> tmpCollection = (Collection<?>) tmpData; | ||||||
|  | 								final Object[] elements = tmpCollection.toArray(); | ||||||
|  | 								for (int iii = 0; iii < elements.length; iii++) { | ||||||
|  | 									if (elements[iii] == null) { | ||||||
|  | 										throw new InputException(baseName + fieldName + '[' + iii + ']', | ||||||
|  | 												"Collection can not contain NULL item"); | ||||||
|  | 									} | ||||||
|  | 								} | ||||||
|  | 							}); | ||||||
|  | 				} | ||||||
|  | 				final CollectionNotEmpty collectionNotEmpty = AnnotationTools.getCollectionNotEmpty(field); | ||||||
|  | 				if (collectionNotEmpty != null) { | ||||||
|  | 					if (!Collection.class.isAssignableFrom(field.getType())) { | ||||||
|  | 						throw new DataAccessException( | ||||||
|  | 								"Request @collectionNotEmpty on a non collection field: '" + fieldName + "'"); | ||||||
|  | 					} | ||||||
|  | 					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 Collection<?> tmpCollection = (Collection<?>) tmpData; | ||||||
|  | 								if (tmpCollection.isEmpty()) { | ||||||
|  | 									throw new InputException(baseName + fieldName, "Collection can not be empty"); | ||||||
|  | 								} | ||||||
|  | 							}); | ||||||
|  | 				} | ||||||
|  | 				// keep this is last ==> take more time... | ||||||
|  | 				if (AnnotationTools.isUnique(field)) { | ||||||
|  | 					// Create the request ... | ||||||
|  | 					add(fieldName, | ||||||
|  | 							( | ||||||
|  | 									final DBAccess ioDb, | ||||||
|  | 									final String baseName, | ||||||
|  | 									final T data, | ||||||
|  | 									final List<String> modifiedValue, | ||||||
|  | 									final QueryOptions options) -> { | ||||||
|  | 								final List<ConditionChecker> condCheckers = options.get(ConditionChecker.class); | ||||||
|  | 								Object other = null; | ||||||
|  | 								if (condCheckers.isEmpty()) { | ||||||
|  | 									other = ioDb.getWhere(this.clazz, | ||||||
|  | 											new Condition(new QueryCondition(fieldName, "==", field.get(data)))); | ||||||
|  | 								} else { | ||||||
|  | 									other = ioDb.getWhere(this.clazz, | ||||||
|  | 											new Condition(new QueryCondition(fieldName, "==", field.get(data))), | ||||||
|  | 											condCheckers.get(0).toCondition()); | ||||||
|  | 								} | ||||||
|  | 								if (other != null) { | ||||||
|  | 									throw new InputException(baseName + fieldName, | ||||||
|  | 											"The field is already exist in the DB"); | ||||||
|  | 								} | ||||||
|  | 							}); | ||||||
|  | 				} | ||||||
|  |  | ||||||
|  | 			} | ||||||
|  | 		} catch (final Exception ex) { | ||||||
|  | 			this.checking = null; | ||||||
|  | 			throw ex; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public void check(final Object data) throws Exception { | ||||||
|  | 		check(null, "", data, null, null); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public void check(final String baseName, final Object data) throws Exception { | ||||||
|  | 		check(null, baseName, data, null, null); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public void check(final DBAccess ioDb, final String baseName, final Object data) throws Exception { | ||||||
|  | 		check(ioDb, baseName, data, null, null); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public void check(final DBAccess ioDb, final String baseName, final Object data, final List<String> modifiedValue) | ||||||
|  | 			throws Exception { | ||||||
|  | 		check(ioDb, baseName, data, modifiedValue, null); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	@Override | ||||||
|  | 	public void check( | ||||||
|  | 			final DBAccess ioDb, | ||||||
|  | 			final String baseName, | ||||||
|  | 			final Object data, | ||||||
|  | 			List<String> modifiedValue, | ||||||
|  | 			final QueryOptions options) throws Exception { | ||||||
|  | 		if (this.checking == null) { | ||||||
|  | 			initialize(); | ||||||
|  | 		} | ||||||
|  | 		if (modifiedValue == null) { | ||||||
|  | 			modifiedValue = AnnotationTools.getAllFieldsNames(this.clazz); | ||||||
|  | 		} | ||||||
|  | 		if (!(this.clazz.isAssignableFrom(data.getClass()))) { | ||||||
|  | 			throw new DataAccessException("Incompatatyble type of Object" + data.getClass().getCanonicalName()); | ||||||
|  | 		} | ||||||
|  | 		@SuppressWarnings("unchecked") | ||||||
|  | 		final T dataCasted = (T) data; | ||||||
|  | 		for (final String filter : modifiedValue) { | ||||||
|  | 			final List<CheckInterface<T>> actions = this.checking.get(filter); | ||||||
|  | 			if (actions == null) { | ||||||
|  | 				continue; | ||||||
|  | 			} | ||||||
|  | 			for (final CheckInterface<T> action : actions) { | ||||||
|  | 				action.check(ioDb, baseName, dataCasted, modifiedValue, options); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		checkTyped(dataCasted, modifiedValue, options); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public void checkTyped(final T data, final List<String> modifiedValue, final QueryOptions options) | ||||||
|  | 			throws Exception { | ||||||
|  | 		// nothing to do ... | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | } | ||||||
| @@ -61,20 +61,8 @@ import jakarta.ws.rs.InternalServerErrorException; | |||||||
| public class DBAccessSQL extends DBAccess { | public class DBAccessSQL extends DBAccess { | ||||||
| 	final static Logger LOGGER = LoggerFactory.getLogger(DBAccessSQL.class); | 	final static Logger LOGGER = LoggerFactory.getLogger(DBAccessSQL.class); | ||||||
| 	// by default we manage some add-on that permit to manage non-native model (like json serialization, List of external key as String list...) | 	// by default we manage some add-on that permit to manage non-native model (like json serialization, List of external key as String list...) | ||||||
| 	final static List<DataAccessAddOn> addOn = new ArrayList<>(); | 	final static List<DataAccessAddOn> addOn = List.of(new AddOnManyToMany(), new AddOnManyToOne(), | ||||||
|  | 			new AddOnOneToMany(), new AddOnDataJson()); | ||||||
| 	{ |  | ||||||
| 		addOn.add(new AddOnManyToMany()); |  | ||||||
| 		addOn.add(new AddOnManyToOne()); |  | ||||||
| 		addOn.add(new AddOnOneToMany()); |  | ||||||
| 		addOn.add(new AddOnDataJson()); |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	/** Add a new add-on on the current management. |  | ||||||
| 	 * @param addOn instantiate object on the Add-on */ |  | ||||||
| 	public static void addAddOn(final DataAccessAddOn addOn) { |  | ||||||
| 		DBAccessSQL.addOn.add(addOn); |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	private final DbIoSql db; | 	private final DbIoSql db; | ||||||
|  |  | ||||||
| @@ -170,7 +158,7 @@ public class DBAccessSQL extends DBAccess { | |||||||
| 			} else { | 			} else { | ||||||
| 				// TODO : Maybe connect with a temporary not specified connection interface to a db ... | 				// TODO : Maybe connect with a temporary not specified connection interface to a db ... | ||||||
| 				final PreparedStatement ps = this.db.getConnection() | 				final PreparedStatement ps = this.db.getConnection() | ||||||
| 						.prepareStatement("SHOW TABLES IN `" + this.db.getCongig().getDbName() + "`"); | 						.prepareStatement("SHOW TABLES IN `" + this.db.getConfig().getDbName() + "`"); | ||||||
| 				final ResultSet rs = ps.executeQuery(); | 				final ResultSet rs = ps.executeQuery(); | ||||||
| 				// LOGGER.info("List all tables: equals? '{}'", name); | 				// LOGGER.info("List all tables: equals? '{}'", name); | ||||||
| 				while (rs.next()) { | 				while (rs.next()) { | ||||||
| @@ -827,6 +815,9 @@ public class DBAccessSQL extends DBAccess { | |||||||
| 	@Override | 	@Override | ||||||
| 	@SuppressFBWarnings("SQL_PREPARED_STATEMENT_GENERATED_FROM_NONCONSTANT_STRING") | 	@SuppressFBWarnings("SQL_PREPARED_STATEMENT_GENERATED_FROM_NONCONSTANT_STRING") | ||||||
| 	public <T> T insert(final T data, final QueryOption... option) throws Exception { | 	public <T> T insert(final T data, final QueryOption... option) throws Exception { | ||||||
|  | 		if (data == null) { | ||||||
|  | 			throw new DataAccessException("Try to check a null data ==> wrong API"); | ||||||
|  | 		} | ||||||
| 		final Class<?> clazz = data.getClass(); | 		final Class<?> clazz = data.getClass(); | ||||||
| 		final QueryOptions options = new QueryOptions(option); | 		final QueryOptions options = new QueryOptions(option); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -355,12 +355,12 @@ public class AddOnManyToMany implements DataAccessAddOn { | |||||||
| 		final FieldName columnName = AnnotationTools.getFieldName(field, options); | 		final FieldName columnName = AnnotationTools.getFieldName(field, options); | ||||||
| 		final String linkTableName = generateLinkTableName(tableName, columnName.inTable()); | 		final String linkTableName = generateLinkTableName(tableName, columnName.inTable()); | ||||||
| 		@SuppressWarnings("unchecked") | 		@SuppressWarnings("unchecked") | ||||||
| 		final List<Long> dataCasted = (List<Long>) data; | 		final List<Object> dataCasted = (List<Object>) data; | ||||||
| 		if (dataCasted.size() == 0) { | 		if (dataCasted.size() == 0) { | ||||||
| 			return; | 			return; | ||||||
| 		} | 		} | ||||||
| 		final List<LinkTableGeneric> insertElements = new ArrayList<>(); | 		final List<LinkTableGeneric> insertElements = new ArrayList<>(); | ||||||
| 		for (final Long remoteKey : dataCasted) { | 		for (final Object remoteKey : dataCasted) { | ||||||
| 			if (remoteKey == null) { | 			if (remoteKey == null) { | ||||||
| 				throw new DataAccessException("Try to insert remote key with null value"); | 				throw new DataAccessException("Try to insert remote key with null value"); | ||||||
| 			} | 			} | ||||||
|   | |||||||
| @@ -9,7 +9,7 @@ import org.kar.archidata.dataAccess.QueryOptions; | |||||||
| /** By default some element are not read like createAt and UpdatedAt. This option permit to read it. */ | /** By default some element are not read like createAt and UpdatedAt. This option permit to read it. */ | ||||||
| public interface CheckFunctionInterface { | public interface CheckFunctionInterface { | ||||||
| 	/** This function implementation is design to check if the updated class is valid of not for insertion | 	/** This function implementation is design to check if the updated class is valid of not for insertion | ||||||
| 	 * @param baseName NAme of the object to be precise with the use of what fail. | 	 * @param baseName Name of the object to be precise with the use of what fail. | ||||||
| 	 * @param data The object that might be injected. | 	 * @param data The object that might be injected. | ||||||
| 	 * @param modifiedValue List of fields that might be check. If null, then all column must be checked. | 	 * @param modifiedValue List of fields that might be check. If null, then all column must be checked. | ||||||
| 	 * @throws Exception Exception is generate if the data are incorrect. */ | 	 * @throws Exception Exception is generate if the data are incorrect. */ | ||||||
|   | |||||||
| @@ -1,575 +0,0 @@ | |||||||
| package org.kar.archidata.dataAccess.options; |  | ||||||
|  |  | ||||||
| import java.lang.reflect.Field; |  | ||||||
| import java.sql.Timestamp; |  | ||||||
| import java.time.LocalDate; |  | ||||||
| import java.time.LocalTime; |  | ||||||
| import java.util.ArrayList; |  | ||||||
| import java.util.Date; |  | ||||||
| import java.util.HashMap; |  | ||||||
| import java.util.List; |  | ||||||
| import java.util.Map; |  | ||||||
| import java.util.UUID; |  | ||||||
| import java.util.regex.Pattern; |  | ||||||
|  |  | ||||||
| import org.kar.archidata.annotation.AnnotationTools; |  | ||||||
| import org.kar.archidata.annotation.DataJson; |  | ||||||
| import org.kar.archidata.dataAccess.DBAccess; |  | ||||||
| import org.kar.archidata.dataAccess.DataAccess; |  | ||||||
| import org.kar.archidata.dataAccess.QueryCondition; |  | ||||||
| import org.kar.archidata.dataAccess.QueryOptions; |  | ||||||
| import org.kar.archidata.exception.DataAccessException; |  | ||||||
| import org.kar.archidata.exception.InputException; |  | ||||||
| import org.slf4j.Logger; |  | ||||||
| import org.slf4j.LoggerFactory; |  | ||||||
|  |  | ||||||
| import com.fasterxml.jackson.annotation.JsonValue; |  | ||||||
|  |  | ||||||
| import jakarta.persistence.ManyToOne; |  | ||||||
| import jakarta.validation.constraints.Size; |  | ||||||
|  |  | ||||||
| public class CheckJPA<T> implements CheckFunctionInterface { |  | ||||||
|  |  | ||||||
| 	private static final Logger LOGGER = LoggerFactory.getLogger(CheckJPA.class); |  | ||||||
| 	private final Class<?> clazz; |  | ||||||
|  |  | ||||||
| 	/** By default some element are not read like createAt and UpdatedAt. This option permit to read it. */ |  | ||||||
| 	public interface CheckInterface<K> { |  | ||||||
| 		/** This function implementation is design to check if the updated class is valid of not for insertion |  | ||||||
| 		 * @param ioDb Access on the Data-Base |  | ||||||
| 		 * @param baseName Base of the name input that is displayed in exception generated. |  | ||||||
| 		 * @param data The object that might be injected. |  | ||||||
| 		 * @param modifiedValue List of fields that modification is requested. |  | ||||||
| 		 * @param options Some query option that the checker can need to generate basic check. |  | ||||||
| 		 * @throws Exception Exception is generate if the data are incorrect. */ |  | ||||||
| 		void check( |  | ||||||
| 				final DBAccess ioDb, |  | ||||||
| 				final String baseName, |  | ||||||
| 				final K data, |  | ||||||
| 				List<String> modifiedValue, |  | ||||||
| 				final QueryOptions options) throws Exception; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	protected Map<String, List<CheckInterface<T>>> checking = null; |  | ||||||
|  |  | ||||||
| 	protected void add(final String field, final CheckInterface<T> checkFunction) throws DataAccessException { |  | ||||||
| 		if (!AnnotationTools.hasFieldsName(this.clazz, field)) { |  | ||||||
| 			LOGGER.error("Try to add a JPA Filter on an inexistant Field: '{}' not in {}", field, |  | ||||||
| 					AnnotationTools.getAllFieldsNames(this.clazz)); |  | ||||||
| 			throw new DataAccessException("Try to add a JPA Filter on an inexistant Field: '" + field + "' not in " |  | ||||||
| 					+ AnnotationTools.getAllFieldsNames(this.clazz)); |  | ||||||
| 		} |  | ||||||
| 		List<CheckInterface<T>> actions = this.checking.get(field); |  | ||||||
| 		if (actions == null) { |  | ||||||
| 			actions = new ArrayList<>(); |  | ||||||
| 			this.checking.put(field, actions); |  | ||||||
| 		} |  | ||||||
| 		actions.add(checkFunction); |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	public CheckJPA(final Class<T> clazz) { |  | ||||||
| 		this.clazz = clazz; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	public void initialize() throws Exception { |  | ||||||
| 		if (this.checking != null) { |  | ||||||
| 			return; |  | ||||||
| 		} |  | ||||||
| 		try { |  | ||||||
| 			this.checking = new HashMap<>(); |  | ||||||
| 			// create Table: |  | ||||||
| 			final List<String> primaryKeys = new ArrayList<>(); |  | ||||||
| 			for (final Field field : this.clazz.getFields()) { |  | ||||||
| 				final String fieldName = field.getName(); // AnnotationTools.getFieldName(field); |  | ||||||
| 				if (AnnotationTools.isPrimaryKey(field)) { |  | ||||||
| 					add(fieldName, |  | ||||||
| 							( |  | ||||||
| 									final DBAccess ioDb, |  | ||||||
| 									final String baseName, |  | ||||||
| 									final T data, |  | ||||||
| 									final List<String> modifiedValue, |  | ||||||
| 									final QueryOptions options) -> { |  | ||||||
| 								throw new InputException(baseName + fieldName, |  | ||||||
| 										"This is a '@Id' (primaryKey) ==> can not be change"); |  | ||||||
| 							}); |  | ||||||
| 				} |  | ||||||
| 				if (AnnotationTools.getConstraintsNotNull(field)) { |  | ||||||
| 					add(fieldName, |  | ||||||
| 							( |  | ||||||
| 									final DBAccess ioDb, |  | ||||||
| 									final String baseName, |  | ||||||
| 									final T data, |  | ||||||
| 									final List<String> modifiedValue, |  | ||||||
| 									final QueryOptions options) -> { |  | ||||||
| 								if (field.get(data) == null) { |  | ||||||
| 									throw new InputException(baseName + fieldName, "Can not be null"); |  | ||||||
| 								} |  | ||||||
| 							}); |  | ||||||
| 				} |  | ||||||
| 				if (AnnotationTools.isCreatedAtField(field) || AnnotationTools.isUpdateAtField(field)) { |  | ||||||
| 					add(fieldName, |  | ||||||
| 							( |  | ||||||
| 									final DBAccess ioDb, |  | ||||||
| 									final String baseName, |  | ||||||
| 									final T data, |  | ||||||
| 									final List<String> modifiedValue, |  | ||||||
| 									final QueryOptions options) -> { |  | ||||||
| 								throw new InputException(baseName + fieldName, "It is forbidden to change this field"); |  | ||||||
| 							}); |  | ||||||
| 				} |  | ||||||
|  |  | ||||||
| 				final Class<?> type = field.getType(); |  | ||||||
| 				if (type == Long.class || type == long.class) { |  | ||||||
| 					final Long maxValue = AnnotationTools.getConstraintsMax(field); |  | ||||||
| 					if (maxValue != 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 elemTyped = (Long) elem; |  | ||||||
| 									if (elemTyped > maxValue) { |  | ||||||
| 										throw new InputException(baseName + fieldName, |  | ||||||
| 												"Value too height max: " + maxValue); |  | ||||||
| 									} |  | ||||||
| 								}); |  | ||||||
| 					} |  | ||||||
| 					final Long minValue = AnnotationTools.getConstraintsMin(field); |  | ||||||
| 					if (minValue != 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 elemTyped = (Long) elem; |  | ||||||
| 									if (elemTyped < minValue) { |  | ||||||
| 										throw new InputException(baseName + fieldName, |  | ||||||
| 												"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) { |  | ||||||
| 					final Long maxValueRoot = AnnotationTools.getConstraintsMax(field); |  | ||||||
| 					if (maxValueRoot != null) { |  | ||||||
| 						final int maxValue = maxValueRoot.intValue(); |  | ||||||
| 						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 Integer elemTyped = (Integer) elem; |  | ||||||
| 									if (elemTyped > maxValue) { |  | ||||||
| 										throw new InputException(baseName + fieldName, |  | ||||||
| 												"Value too height max: " + maxValue); |  | ||||||
| 									} |  | ||||||
| 								}); |  | ||||||
| 					} |  | ||||||
| 					final Long minValueRoot = AnnotationTools.getConstraintsMin(field); |  | ||||||
| 					if (minValueRoot != null) { |  | ||||||
| 						final int minValue = minValueRoot.intValue(); |  | ||||||
| 						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 Integer elemTyped = (Integer) elem; |  | ||||||
| 									if (elemTyped < minValue) { |  | ||||||
| 										throw new InputException(baseName + fieldName, |  | ||||||
| 												"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); |  | ||||||
| 									} |  | ||||||
| 								}); |  | ||||||
| 					} |  | ||||||
| 				} else if (type == Boolean.class || type == boolean.class) { |  | ||||||
|  |  | ||||||
| 				} else if (type == Float.class || type == float.class) { |  | ||||||
| 					final Long maxValueRoot = AnnotationTools.getConstraintsMax(field); |  | ||||||
| 					if (maxValueRoot != null) { |  | ||||||
| 						final float maxValue = maxValueRoot.floatValue(); |  | ||||||
| 						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 Float elemTyped = (Float) elem; |  | ||||||
| 									if (elemTyped > maxValue) { |  | ||||||
| 										throw new InputException(baseName + fieldName, |  | ||||||
| 												"Value too height max: " + maxValue); |  | ||||||
| 									} |  | ||||||
| 								}); |  | ||||||
| 					} |  | ||||||
| 					final Long minValueRoot = AnnotationTools.getConstraintsMin(field); |  | ||||||
| 					if (minValueRoot != null) { |  | ||||||
| 						final float minValue = minValueRoot.floatValue(); |  | ||||||
| 						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 Float elemTyped = (Float) elem; |  | ||||||
| 									if (elemTyped < minValue) { |  | ||||||
| 										throw new InputException(baseName + fieldName, |  | ||||||
| 												"Value too Low min: " + minValue); |  | ||||||
| 									} |  | ||||||
| 								}); |  | ||||||
| 					} |  | ||||||
| 				} else if (type == Double.class || type == double.class) { |  | ||||||
| 					final Long maxValueRoot = AnnotationTools.getConstraintsMax(field); |  | ||||||
| 					if (maxValueRoot != null) { |  | ||||||
| 						final double maxValue = maxValueRoot.doubleValue(); |  | ||||||
| 						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 Double elemTyped = (Double) elem; |  | ||||||
| 									if (elemTyped > maxValue) { |  | ||||||
| 										throw new InputException(baseName + fieldName, |  | ||||||
| 												"Value too height max: " + maxValue); |  | ||||||
| 									} |  | ||||||
| 								}); |  | ||||||
| 					} |  | ||||||
| 					final Long minValueRoot = AnnotationTools.getConstraintsMin(field); |  | ||||||
| 					if (minValueRoot != null) { |  | ||||||
| 						final double minValue = minValueRoot.doubleValue(); |  | ||||||
| 						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 Double elemTyped = (Double) elem; |  | ||||||
| 									if (elemTyped < minValue) { |  | ||||||
| 										throw new InputException(baseName + fieldName, |  | ||||||
| 												"Value too Low min: " + minValue); |  | ||||||
| 									} |  | ||||||
| 								}); |  | ||||||
| 					} |  | ||||||
| 				} else if (type == Date.class || type == Timestamp.class) { |  | ||||||
|  |  | ||||||
| 				} else if (type == LocalDate.class) { |  | ||||||
|  |  | ||||||
| 				} else if (type == LocalTime.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); |  | ||||||
| 					if (limitSize != 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 String elemTyped = (String) elem; |  | ||||||
| 									if (elemTyped.length() > limitSize.max()) { |  | ||||||
| 										throw new InputException(baseName + fieldName, |  | ||||||
| 												"Too long size (constraints) must be <= " + limitSize.max()); |  | ||||||
| 									} |  | ||||||
| 									if (elemTyped.length() < limitSize.min()) { |  | ||||||
| 										throw new InputException(baseName + fieldName, |  | ||||||
| 												"Too small size (constraints) must be >= " + limitSize.min()); |  | ||||||
| 									} |  | ||||||
| 								}); |  | ||||||
| 					} |  | ||||||
| 					final String patternString = AnnotationTools.getConstraintsPattern(field); |  | ||||||
| 					if (patternString != null) { |  | ||||||
| 						final Pattern pattern = Pattern.compile(patternString); |  | ||||||
| 						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 (!pattern.matcher(elemTyped).find()) { |  | ||||||
| 										throw new InputException(baseName + fieldName, |  | ||||||
| 												"does not match the required pattern (constraints) must be '" |  | ||||||
| 														+ patternString + "'"); |  | ||||||
| 									} |  | ||||||
| 								}); |  | ||||||
| 					} |  | ||||||
| 					if (AnnotationTools.getConstraintsEmail(field)) { |  | ||||||
| 						final String emailPattern = "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$"; |  | ||||||
| 						final Pattern pattern = Pattern.compile(emailPattern); |  | ||||||
| 						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 (!pattern.matcher(elemTyped).find()) { |  | ||||||
| 										throw new InputException(baseName + fieldName, |  | ||||||
| 												"does not match the required pattern[email] (constraints) must be '" |  | ||||||
| 														+ emailPattern + "'"); |  | ||||||
| 									} |  | ||||||
| 								}); |  | ||||||
| 					} |  | ||||||
| 				} else if (type == JsonValue.class) { |  | ||||||
| 					final DataJson jsonAnnotation = AnnotationTools.getDataJson(field); |  | ||||||
| 					if (jsonAnnotation != null && jsonAnnotation.checker() != CheckFunctionVoid.class) { |  | ||||||
| 						// Here if we have an error it crash at start and no new instance after creation... |  | ||||||
| 						final CheckFunctionInterface instance = jsonAnnotation.checker().getDeclaredConstructor() |  | ||||||
| 								.newInstance(); |  | ||||||
| 						add(fieldName, |  | ||||||
| 								( |  | ||||||
| 										final DBAccess ioDb, |  | ||||||
| 										final String baseName, |  | ||||||
| 										final T data, |  | ||||||
| 										final List<String> modifiedValue, |  | ||||||
| 										final QueryOptions options) -> { |  | ||||||
| 									instance.checkAll(ioDb, baseName + fieldName + ".", field.get(data), options); |  | ||||||
| 								}); |  | ||||||
| 					} |  | ||||||
| 				} else if (type.isEnum()) { |  | ||||||
| 					// nothing to do. |  | ||||||
| 				} |  | ||||||
| 				final DataJson dataJson = AnnotationTools.getDataJson(field); |  | ||||||
| 				if (dataJson != null && dataJson.checker() != null) { |  | ||||||
| 					final CheckFunctionInterface checkerInstance = dataJson.checker().getDeclaredConstructor() |  | ||||||
| 							.newInstance(); |  | ||||||
| 					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); |  | ||||||
| 								checkerInstance.check(ioDb, baseName, tmpData, null, options); |  | ||||||
| 							}); |  | ||||||
| 				} |  | ||||||
| 				// keep this is last ==> take more time... |  | ||||||
| 				if (AnnotationTools.isUnique(field)) { |  | ||||||
| 					// Create the request ... |  | ||||||
| 					add(fieldName, |  | ||||||
| 							( |  | ||||||
| 									final DBAccess ioDb, |  | ||||||
| 									final String baseName, |  | ||||||
| 									final T data, |  | ||||||
| 									final List<String> modifiedValue, |  | ||||||
| 									final QueryOptions options) -> { |  | ||||||
| 								final List<ConditionChecker> condCheckers = options.get(ConditionChecker.class); |  | ||||||
| 								Object other = null; |  | ||||||
| 								if (condCheckers.isEmpty()) { |  | ||||||
| 									other = DataAccess.getWhere(this.clazz, |  | ||||||
| 											new Condition(new QueryCondition(fieldName, "==", field.get(data)))); |  | ||||||
| 								} else { |  | ||||||
| 									other = DataAccess.getWhere(this.clazz, |  | ||||||
| 											new Condition(new QueryCondition(fieldName, "==", field.get(data))), |  | ||||||
| 											condCheckers.get(0).toCondition()); |  | ||||||
| 								} |  | ||||||
| 								if (other != null) { |  | ||||||
| 									throw new InputException(baseName + fieldName, "Name already exist in the DB"); |  | ||||||
| 								} |  | ||||||
| 							}); |  | ||||||
| 				} |  | ||||||
|  |  | ||||||
| 			} |  | ||||||
| 		} catch (final Exception ex) { |  | ||||||
| 			this.checking = null; |  | ||||||
| 			throw ex; |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	public void check(final Object data) throws Exception { |  | ||||||
| 		check(null, "", data, null, null); |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	public void check(final String baseName, final Object data) throws Exception { |  | ||||||
| 		check(null, baseName, data, null, null); |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	public void check(final DBAccess ioDb, final String baseName, final Object data) throws Exception { |  | ||||||
| 		check(ioDb, baseName, data, null, null); |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	public void check(final DBAccess ioDb, final String baseName, final Object data, final List<String> modifiedValue) |  | ||||||
| 			throws Exception { |  | ||||||
| 		check(ioDb, baseName, data, modifiedValue, null); |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	@Override |  | ||||||
| 	public void check( |  | ||||||
| 			final DBAccess ioDb, |  | ||||||
| 			final String baseName, |  | ||||||
| 			final Object data, |  | ||||||
| 			List<String> modifiedValue, |  | ||||||
| 			final QueryOptions options) throws Exception { |  | ||||||
| 		if (this.checking == null) { |  | ||||||
| 			initialize(); |  | ||||||
| 		} |  | ||||||
| 		if (modifiedValue == null) { |  | ||||||
| 			modifiedValue = AnnotationTools.getAllFieldsNames(this.clazz); |  | ||||||
| 		} |  | ||||||
| 		if (!(this.clazz.isAssignableFrom(data.getClass()))) { |  | ||||||
| 			throw new DataAccessException("Incompatatyble type of Object" + data.getClass().getCanonicalName()); |  | ||||||
| 		} |  | ||||||
| 		@SuppressWarnings("unchecked") |  | ||||||
| 		final T dataCasted = (T) data; |  | ||||||
| 		for (final String filter : modifiedValue) { |  | ||||||
| 			final List<CheckInterface<T>> actions = this.checking.get(filter); |  | ||||||
| 			if (actions == null) { |  | ||||||
| 				continue; |  | ||||||
| 			} |  | ||||||
| 			for (final CheckInterface<T> action : actions) { |  | ||||||
| 				action.check(ioDb, baseName, dataCasted, modifiedValue, options); |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 		checkTyped(dataCasted, modifiedValue, options); |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	public void checkTyped(final T data, final List<String> modifiedValue, final QueryOptions options) |  | ||||||
| 			throws Exception { |  | ||||||
| 		// nothing to do ... |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| } |  | ||||||
| @@ -76,7 +76,7 @@ public abstract class DbIo implements Closeable { | |||||||
| 		return this.config.equals(config); | 		return this.config.equals(config); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	public DbConfig getCongig() { | 	public DbConfig getConfig() { | ||||||
| 		return this.config; | 		return this.config; | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|   | |||||||
| @@ -1,17 +1,18 @@ | |||||||
| package org.kar.archidata.exception; | package org.kar.archidata.exception; | ||||||
| 
 | 
 | ||||||
| import java.util.UUID; | import org.bson.types.ObjectId; | ||||||
| 
 | 
 | ||||||
| public class RESTErrorResponseExeption extends Exception { | public class RESTErrorResponseException extends Exception { | ||||||
| 	public UUID uuid; | 	private static final long serialVersionUID = 1L; | ||||||
|  | 	public ObjectId oid; | ||||||
| 	public String time; | 	public String time; | ||||||
| 	public String name; | 	public String name; | ||||||
| 	public String message; | 	public String message; | ||||||
| 	public int status; | 	public int status; | ||||||
| 	public String statusMessage; | 	public String statusMessage; | ||||||
| 
 | 
 | ||||||
| 	public RESTErrorResponseExeption() { | 	public RESTErrorResponseException() { | ||||||
| 		this.uuid = null; | 		this.oid = new ObjectId(); | ||||||
| 		this.time = null; | 		this.time = null; | ||||||
| 		this.name = null; | 		this.name = null; | ||||||
| 		this.message = null; | 		this.message = null; | ||||||
| @@ -19,9 +20,9 @@ public class RESTErrorResponseExeption extends Exception { | |||||||
| 		this.statusMessage = null; | 		this.statusMessage = null; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	public RESTErrorResponseExeption(final UUID uuid, final String time, final String name, final String message, | 	public RESTErrorResponseException(final ObjectId oid, final String time, final String name, final String message, | ||||||
| 			final int status, final String statusMessage) { | 			final int status, final String statusMessage) { | ||||||
| 		this.uuid = uuid; | 		this.oid = oid; | ||||||
| 		this.time = time; | 		this.time = time; | ||||||
| 		this.name = name; | 		this.name = name; | ||||||
| 		this.message = message; | 		this.message = message; | ||||||
| @@ -31,7 +32,7 @@ public class RESTErrorResponseExeption extends Exception { | |||||||
| 
 | 
 | ||||||
| 	@Override | 	@Override | ||||||
| 	public String toString() { | 	public String toString() { | ||||||
| 		return "RESTErrorResponseExeption [uuid=" + this.uuid + ", time=" + this.time + ", name=" + this.name | 		return "RESTErrorResponseExeption [oid=" + this.oid + ", time=" + this.time + ", name=" + this.name | ||||||
| 				+ ", message=" + this.message + ", status=" + this.status + ", statusMessage=" + this.statusMessage | 				+ ", message=" + this.message + ", status=" + this.status + ", statusMessage=" + this.statusMessage | ||||||
| 				+ "]"; | 				+ "]"; | ||||||
| 	} | 	} | ||||||
| @@ -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()"; | ||||||
|   | |||||||
| @@ -7,11 +7,11 @@ import java.util.Arrays; | |||||||
| import java.util.List; | import java.util.List; | ||||||
|  |  | ||||||
| import org.glassfish.jersey.media.multipart.FormDataParam; | import org.glassfish.jersey.media.multipart.FormDataParam; | ||||||
| import org.kar.archidata.annotation.ARCHIVE; |  | ||||||
| import org.kar.archidata.annotation.AsyncType; | import org.kar.archidata.annotation.AsyncType; | ||||||
| import org.kar.archidata.annotation.FormDataOptional; | import org.kar.archidata.annotation.FormDataOptional; | ||||||
| import org.kar.archidata.annotation.RESTORE; |  | ||||||
| import org.kar.archidata.annotation.TypeScriptProgress; | import org.kar.archidata.annotation.TypeScriptProgress; | ||||||
|  | import org.kar.archidata.annotation.method.ARCHIVE; | ||||||
|  | import org.kar.archidata.annotation.method.RESTORE; | ||||||
|  |  | ||||||
| import io.swagger.v3.oas.annotations.Operation; | import io.swagger.v3.oas.annotations.Operation; | ||||||
| import jakarta.ws.rs.Consumes; | import jakarta.ws.rs.Consumes; | ||||||
|   | |||||||
| @@ -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), // | ||||||
|   | |||||||
| @@ -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(); | ||||||
| 	} | 	} | ||||||
|   | |||||||
| @@ -4,7 +4,6 @@ import java.io.IOException; | |||||||
| import java.lang.reflect.Method; | import java.lang.reflect.Method; | ||||||
| import java.util.Arrays; | import java.util.Arrays; | ||||||
| import java.util.List; | import java.util.List; | ||||||
| import java.util.Map; |  | ||||||
| import java.util.Map.Entry; | import java.util.Map.Entry; | ||||||
| // https://stackoverflow.com/questions/26777083/best-practice-for-rest-token-based-authentication-with-jax-rs-and-jersey | // https://stackoverflow.com/questions/26777083/best-practice-for-rest-token-based-authentication-with-jax-rs-and-jersey | ||||||
| // https://stackoverflow.com/questions/26777083/best-practice-for-rest-token-based-authentication-with-jax-rs-and-jersey/45814178#45814178 | // https://stackoverflow.com/questions/26777083/best-practice-for-rest-token-based-authentication-with-jax-rs-and-jersey/45814178#45814178 | ||||||
| @@ -119,7 +118,7 @@ public class AuthenticationFilter implements ContainerRequestFilter { | |||||||
| 		final boolean isApplicationToken = apikeyHeader != null; | 		final boolean isApplicationToken = apikeyHeader != null; | ||||||
| 		final boolean isJwtToken = isTokenBasedAuthentication(authorizationHeader); | 		final boolean isJwtToken = isTokenBasedAuthentication(authorizationHeader); | ||||||
| 		if (!isApplicationToken && !isJwtToken) { | 		if (!isApplicationToken && !isJwtToken) { | ||||||
| 			LOGGER.warn("REJECTED unauthorized: {}", requestContext.getUriInfo().getPath()); | 			LOGGER.warn("REJECTED unauthorized: /{}", requestContext.getUriInfo().getPath()); | ||||||
| 			abortWithUnauthorized(requestContext, "REJECTED unauthorized: " + requestContext.getUriInfo().getPath()); | 			abortWithUnauthorized(requestContext, "REJECTED unauthorized: " + requestContext.getUriInfo().getPath()); | ||||||
| 			return; | 			return; | ||||||
| 		} | 		} | ||||||
| @@ -208,7 +207,7 @@ public class AuthenticationFilter implements ContainerRequestFilter { | |||||||
| 		// The WWW-Authenticate header is sent along with the response | 		// The WWW-Authenticate header is sent along with the response | ||||||
| 		LOGGER.warn("abortWithUnauthorized:"); | 		LOGGER.warn("abortWithUnauthorized:"); | ||||||
| 		final RestErrorResponse ret = new RestErrorResponse(Response.Status.UNAUTHORIZED, "Unauthorized", message); | 		final RestErrorResponse ret = new RestErrorResponse(Response.Status.UNAUTHORIZED, "Unauthorized", message); | ||||||
| 		LOGGER.error("Error UUID={}", ret.uuid); | 		LOGGER.error("Error OID={}", ret.oid); | ||||||
| 		requestContext.abortWith(Response.status(ret.status) | 		requestContext.abortWith(Response.status(ret.status) | ||||||
| 				.header(HttpHeaders.WWW_AUTHENTICATE, | 				.header(HttpHeaders.WWW_AUTHENTICATE, | ||||||
| 						AUTHENTICATION_SCHEME + " base64(HEADER).base64(CONTENT).base64(KEY)") | 						AUTHENTICATION_SCHEME + " base64(HEADER).base64(CONTENT).base64(KEY)") | ||||||
| @@ -217,7 +216,7 @@ public class AuthenticationFilter implements ContainerRequestFilter { | |||||||
|  |  | ||||||
| 	private void abortWithForbidden(final ContainerRequestContext requestContext, final String message) { | 	private void abortWithForbidden(final ContainerRequestContext requestContext, final String message) { | ||||||
| 		final RestErrorResponse ret = new RestErrorResponse(Response.Status.FORBIDDEN, "FORBIDDEN", message); | 		final RestErrorResponse ret = new RestErrorResponse(Response.Status.FORBIDDEN, "FORBIDDEN", message); | ||||||
| 		LOGGER.error("Error UUID={}", ret.uuid); | 		LOGGER.error("Error OID={}", ret.oid); | ||||||
| 		requestContext.abortWith(Response.status(ret.status).header(HttpHeaders.WWW_AUTHENTICATE, message).entity(ret) | 		requestContext.abortWith(Response.status(ret.status).header(HttpHeaders.WWW_AUTHENTICATE, message).entity(ret) | ||||||
| 				.type(MediaType.APPLICATION_JSON).build()); | 				.type(MediaType.APPLICATION_JSON).build()); | ||||||
| 	} | 	} | ||||||
| @@ -246,7 +245,7 @@ public class AuthenticationFilter implements ContainerRequestFilter { | |||||||
| 		final Object rowRight = ret.getClaim("right"); | 		final Object rowRight = ret.getClaim("right"); | ||||||
| 		if (rowRight != null) { | 		if (rowRight != null) { | ||||||
| 			LOGGER.info("Detect right in Authentication Filter: {}", rowRight); | 			LOGGER.info("Detect right in Authentication Filter: {}", rowRight); | ||||||
| 			user.right = (Map<String, Map<String, Object>>) ret.getClaim("right"); | 			user.right = RightSafeCaster.safeCastAndTransform(ret.getClaim("right")); | ||||||
| 			/* | 			/* | ||||||
| 			if (rights.containsKey(this.applicationName)) { | 			if (rights.containsKey(this.applicationName)) { | ||||||
| 				user.right = rights.get(this.applicationName); | 				user.right = rights.get(this.applicationName); | ||||||
|   | |||||||
| @@ -26,7 +26,7 @@ public class MySecurityContext implements SecurityContext { | |||||||
| 		return this.contextPrincipale; | 		return this.contextPrincipale; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	public Object getRightOfRoleInGroup(final String group, final String role) { | 	public PartRight getRightOfRoleInGroup(final String group, final String role) { | ||||||
| 		if (this.contextPrincipale.userByToken != null) { | 		if (this.contextPrincipale.userByToken != null) { | ||||||
| 			return this.contextPrincipale.userByToken.getRight(group, role); | 			return this.contextPrincipale.userByToken.getRight(group, role); | ||||||
| 		} | 		} | ||||||
| @@ -67,21 +67,14 @@ public class MySecurityContext implements SecurityContext { | |||||||
| 			return false; | 			return false; | ||||||
| 		} | 		} | ||||||
| 		// get associated Roles: | 		// get associated Roles: | ||||||
| 		final Object rightPart = getRightOfRoleInGroup(group, role); | 		final PartRight rightPart = getRightOfRoleInGroup(group, role); | ||||||
| 		LOGGER.info("detect : {}", rightPart); | 		if (PartRight.READ_WRITE.equals(rightPart)) { | ||||||
| 		long dataRight = 0; |  | ||||||
| 		if (rightPart instanceof final Long rightPartCasted) { |  | ||||||
| 			dataRight = rightPartCasted; |  | ||||||
| 		} else if (rightPart instanceof final Integer rightPartCasted) { |  | ||||||
| 			dataRight = rightPartCasted; |  | ||||||
| 		} |  | ||||||
| 		if (dataRight == PartRight.READ_WRITE.getValue()) { |  | ||||||
| 			return true; | 			return true; | ||||||
| 		} | 		} | ||||||
| 		if (!needRead && needWrite && dataRight == PartRight.WRITE.getValue()) { | 		if (!needRead && needWrite && PartRight.WRITE.equals(rightPart)) { | ||||||
| 			return true; | 			return true; | ||||||
| 		} | 		} | ||||||
| 		if (needRead && !needWrite && dataRight == PartRight.READ.getValue()) { | 		if (needRead && !needWrite && PartRight.READ.equals(rightPart)) { | ||||||
| 			return true; | 			return true; | ||||||
| 		} | 		} | ||||||
| 		return false; | 		return false; | ||||||
|   | |||||||
| @@ -27,4 +27,27 @@ public enum PartRight { | |||||||
| 		} | 		} | ||||||
| 		throw new IllegalArgumentException("PartRight: Unknown value: " + value); | 		throw new IllegalArgumentException("PartRight: Unknown value: " + value); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	public static PartRight fromValue(final long value) { | ||||||
|  | 		for (final PartRight element : values()) { | ||||||
|  | 			if (element.getValue() == value) { | ||||||
|  | 				return element; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		throw new IllegalArgumentException("PartRight: Unknown value: " + value); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static PartRight fromString(final String value) { | ||||||
|  | 		if (value == null) { | ||||||
|  | 			throw new IllegalArgumentException("La chaîne ne peut pas être nulle"); | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		return switch (value.toUpperCase()) { | ||||||
|  | 			case "NONE" -> NONE; | ||||||
|  | 			case "READ" -> READ; | ||||||
|  | 			case "WRITE" -> WRITE; | ||||||
|  | 			case "READ_WRITE" -> READ_WRITE; | ||||||
|  | 			default -> throw new IllegalArgumentException("Valeur inconnue pour PartRight : " + value); | ||||||
|  | 		}; | ||||||
|  | 	} | ||||||
| } | } | ||||||
|   | |||||||
							
								
								
									
										61
									
								
								src/org/kar/archidata/filter/RightSafeCaster.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								src/org/kar/archidata/filter/RightSafeCaster.java
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,61 @@ | |||||||
|  | package org.kar.archidata.filter; | ||||||
|  |  | ||||||
|  | import java.util.Map; | ||||||
|  |  | ||||||
|  | public class RightSafeCaster { | ||||||
|  |  | ||||||
|  | 	@SuppressWarnings("unchecked") | ||||||
|  | 	public static Map<String, Map<String, PartRight>> safeCastAndTransform(final Object obj) { | ||||||
|  | 		if (!(obj instanceof Map)) { | ||||||
|  | 			throw new IllegalArgumentException("L'objet n'est pas un Map"); | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		final Map<?, ?> outerMap = (Map<?, ?>) obj; | ||||||
|  |  | ||||||
|  | 		// Résultat final après vérification et transformation | ||||||
|  | 		final Map<String, Map<String, PartRight>> resultMap = new java.util.HashMap<>(); | ||||||
|  |  | ||||||
|  | 		for (final Map.Entry<?, ?> outerEntry : outerMap.entrySet()) { | ||||||
|  | 			if (!(outerEntry.getKey() instanceof String)) { | ||||||
|  | 				throw new IllegalArgumentException("Une clé du Map externe n'est pas de type String"); | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			if (!(outerEntry.getValue() instanceof Map)) { | ||||||
|  | 				throw new IllegalArgumentException("Une valeur du Map externe n'est pas un Map"); | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			final String outerKey = (String) outerEntry.getKey(); | ||||||
|  | 			final Map<?, ?> innerMap = (Map<?, ?>) outerEntry.getValue(); | ||||||
|  |  | ||||||
|  | 			final Map<String, PartRight> transformedInnerMap = new java.util.HashMap<>(); | ||||||
|  |  | ||||||
|  | 			for (final Map.Entry<?, ?> innerEntry : innerMap.entrySet()) { | ||||||
|  | 				if (!(innerEntry.getKey() instanceof String)) { | ||||||
|  | 					throw new IllegalArgumentException("Une clé du Map interne n'est pas de type String"); | ||||||
|  | 				} | ||||||
|  |  | ||||||
|  | 				final String innerKey = (String) innerEntry.getKey(); | ||||||
|  | 				final Object value = innerEntry.getValue(); | ||||||
|  |  | ||||||
|  | 				PartRight partRight; | ||||||
|  | 				if (value instanceof PartRight) { | ||||||
|  | 					partRight = (PartRight) value; | ||||||
|  | 				} else if (value instanceof final Integer valueCasted) { | ||||||
|  | 					partRight = PartRight.fromValue(valueCasted); | ||||||
|  | 				} else if (value instanceof final Long valueCasted) { | ||||||
|  | 					partRight = PartRight.fromValue(valueCasted); | ||||||
|  | 				} else if (value instanceof final String valueCasted) { | ||||||
|  | 					partRight = PartRight.fromString(valueCasted); | ||||||
|  | 				} else { | ||||||
|  | 					throw new IllegalArgumentException("The Map Value is neither PartRight nor String nor Integer"); | ||||||
|  | 				} | ||||||
|  |  | ||||||
|  | 				transformedInnerMap.put(innerKey, partRight); | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			resultMap.put(outerKey, transformedInnerMap); | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		return resultMap; | ||||||
|  | 	} | ||||||
|  | } | ||||||
| @@ -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") | ||||||
|   | |||||||
| @@ -48,8 +48,10 @@ public class User extends GenericDataSoftDelete { | |||||||
|  |  | ||||||
| 	@DefaultValue("'0'") | 	@DefaultValue("'0'") | ||||||
| 	@Column(nullable = false) | 	@Column(nullable = false) | ||||||
| 	public boolean blocked = false; | 	@Nullable | ||||||
|  | 	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") | ||||||
|   | |||||||
| @@ -4,6 +4,8 @@ import java.util.HashMap; | |||||||
| import java.util.Map; | import java.util.Map; | ||||||
| import java.util.Set; | import java.util.Set; | ||||||
|  |  | ||||||
|  | import org.kar.archidata.filter.PartRight; | ||||||
|  |  | ||||||
| public class UserByToken { | public class UserByToken { | ||||||
| 	public static final int TYPE_USER = -1; | 	public static final int TYPE_USER = -1; | ||||||
| 	public static final int TYPE_APPLICATION = -2; | 	public static final int TYPE_APPLICATION = -2; | ||||||
| @@ -11,10 +13,11 @@ public class UserByToken { | |||||||
| 	public Integer type = null; | 	public Integer type = null; | ||||||
|  |  | ||||||
| 	public Long id = null; | 	public Long id = null; | ||||||
| 	public Long parentId = null; // FOr application, this is the id of the application, and of user token, this is the USERID | 	// For application, this is the id of the application, and of user token, this is the USERID | ||||||
|  | 	public Long parentId = null; | ||||||
| 	public String name = null; | 	public String name = null; | ||||||
| 	// Right map | 	// Right map | ||||||
| 	public Map<String, Map<String, Object>> right = new HashMap<>(); | 	public Map<String, Map<String, PartRight>> right = new HashMap<>(); | ||||||
|  |  | ||||||
| 	public Set<String> getGroups() { | 	public Set<String> getGroups() { | ||||||
| 		return this.right.keySet(); | 		return this.right.keySet(); | ||||||
| @@ -27,11 +30,11 @@ public class UserByToken { | |||||||
| 		return this.right.containsKey(group); | 		return this.right.containsKey(group); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	public Object getRight(final String group, final String key) { | 	public PartRight getRight(final String group, final String key) { | ||||||
| 		if (!this.right.containsKey(group)) { | 		if (!this.right.containsKey(group)) { | ||||||
| 			return null; | 			return null; | ||||||
| 		} | 		} | ||||||
| 		final Map<String, Object> rightGroup = this.right.get(group); | 		final Map<String, PartRight> rightGroup = this.right.get(group); | ||||||
| 		if (!rightGroup.containsKey(key)) { | 		if (!rightGroup.containsKey(key)) { | ||||||
| 			return null; | 			return null; | ||||||
| 		} | 		} | ||||||
|   | |||||||
| @@ -100,9 +100,6 @@ public class ConfigBaseVariable { | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	public static String getDBName() { | 	public static String getDBName() { | ||||||
| 		if (bdDatabase == null) { |  | ||||||
| 			return "unknown"; |  | ||||||
| 		} |  | ||||||
| 		return bdDatabase; | 		return bdDatabase; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|   | |||||||
| @@ -198,7 +198,7 @@ public class JWTWrapper { | |||||||
| 					.claim("login", userLogin).claim("application", application).issuer(isuer).issueTime(now) | 					.claim("login", userLogin).claim("application", application).issuer(isuer).issueTime(now) | ||||||
| 					.expirationTime(expiration); // Do not ask why we need a "-" here ... this have no meaning | 					.expirationTime(expiration); // Do not ask why we need a "-" here ... this have no meaning | ||||||
| 			// add right if needed: | 			// add right if needed: | ||||||
| 			if (rights != null && !rights.isEmpty()) { | 			if (rights != null) { | ||||||
| 				builder.claim("right", rights); | 				builder.claim("right", rights); | ||||||
| 			} | 			} | ||||||
| 			// Prepare JWT with claims set | 			// Prepare JWT with claims set | ||||||
|   | |||||||
| @@ -11,7 +11,7 @@ import java.net.http.HttpResponse; | |||||||
| import java.util.List; | import java.util.List; | ||||||
| import java.util.Map; | import java.util.Map; | ||||||
|  |  | ||||||
| import org.kar.archidata.exception.RESTErrorResponseExeption; | import org.kar.archidata.exception.RESTErrorResponseException; | ||||||
| import org.slf4j.Logger; | import org.slf4j.Logger; | ||||||
| import org.slf4j.LoggerFactory; | import org.slf4j.LoggerFactory; | ||||||
|  |  | ||||||
| @@ -37,7 +37,7 @@ public class RESTApi { | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	public <T> List<T> gets(final Class<T> clazz, final String urlOffset) | 	public <T> List<T> gets(final Class<T> clazz, final String urlOffset) | ||||||
| 			throws RESTErrorResponseExeption, IOException, InterruptedException { | 			throws RESTErrorResponseException, IOException, InterruptedException { | ||||||
| 		final HttpClient client = HttpClient.newHttpClient(); | 		final HttpClient client = HttpClient.newHttpClient(); | ||||||
| 		Builder requestBuilding = HttpRequest.newBuilder().version(Version.HTTP_1_1) | 		Builder requestBuilding = HttpRequest.newBuilder().version(Version.HTTP_1_1) | ||||||
| 				.uri(URI.create(this.baseUrl + urlOffset)); | 				.uri(URI.create(this.baseUrl + urlOffset)); | ||||||
| @@ -48,71 +48,70 @@ public class RESTApi { | |||||||
| 		final HttpResponse<String> httpResponse = client.send(request, HttpResponse.BodyHandlers.ofString()); | 		final HttpResponse<String> httpResponse = client.send(request, HttpResponse.BodyHandlers.ofString()); | ||||||
| 		if (httpResponse.statusCode() < 200 || httpResponse.statusCode() >= 300) { | 		if (httpResponse.statusCode() < 200 || httpResponse.statusCode() >= 300) { | ||||||
| 			try { | 			try { | ||||||
| 				final RESTErrorResponseExeption out = this.mapper.readValue(httpResponse.body(), | 				final RESTErrorResponseException out = this.mapper.readValue(httpResponse.body(), | ||||||
| 						RESTErrorResponseExeption.class); | 						RESTErrorResponseException.class); | ||||||
| 				throw out; | 				throw out; | ||||||
| 			} catch (final MismatchedInputException ex) { | 			} catch (final MismatchedInputException ex) { | ||||||
| 				throw new IOException( | 				throw new IOException( | ||||||
| 						"Fail to get the data [" + httpResponse.statusCode() + "] " + httpResponse.body()); | 						"Fail to get the data [" + httpResponse.statusCode() + "] " + httpResponse.body()); | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 		//return this.mapper.readValue(httpResponse.body(), new TypeReference<List<T>>() {}); |  | ||||||
| 		return this.mapper.readValue(httpResponse.body(), | 		return this.mapper.readValue(httpResponse.body(), | ||||||
| 				this.mapper.getTypeFactory().constructCollectionType(List.class, clazz)); | 				this.mapper.getTypeFactory().constructCollectionType(List.class, clazz)); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	public <T> T get(final Class<T> clazz, final String urlOffset) | 	public <T> T get(final Class<T> clazz, final String urlOffset) | ||||||
| 			throws RESTErrorResponseExeption, IOException, InterruptedException { | 			throws RESTErrorResponseException, IOException, InterruptedException { | ||||||
| 		return modelSendJson("GET", clazz, urlOffset, null); | 		return modelSendJson("GET", clazz, urlOffset, null); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	public <T, U> T post(final Class<T> clazz, final String urlOffset, final U data) | 	public <T, U> T post(final Class<T> clazz, final String urlOffset, final U data) | ||||||
| 			throws RESTErrorResponseExeption, IOException, InterruptedException { | 			throws RESTErrorResponseException, IOException, InterruptedException { | ||||||
| 		return modelSend("POST", clazz, urlOffset, data); | 		return modelSend("POST", clazz, urlOffset, data); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	public <T, U> T postJson(final Class<T> clazz, final String urlOffset, final String body) | 	public <T, U> T postJson(final Class<T> clazz, final String urlOffset, final String body) | ||||||
| 			throws RESTErrorResponseExeption, IOException, InterruptedException { | 			throws RESTErrorResponseException, IOException, InterruptedException { | ||||||
| 		return modelSendJson("POST", clazz, urlOffset, body); | 		return modelSendJson("POST", clazz, urlOffset, body); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	public <T> T postMap(final Class<T> clazz, final String urlOffset, final Map<String, Object> data) | 	public <T> T postMap(final Class<T> clazz, final String urlOffset, final Map<String, Object> data) | ||||||
| 			throws RESTErrorResponseExeption, IOException, InterruptedException { | 			throws RESTErrorResponseException, IOException, InterruptedException { | ||||||
| 		return modelSendMap("POST", clazz, urlOffset, data); | 		return modelSendMap("POST", clazz, urlOffset, data); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	public <T, U> T put(final Class<T> clazz, final String urlOffset, final U data) | 	public <T, U> T put(final Class<T> clazz, final String urlOffset, final U data) | ||||||
| 			throws RESTErrorResponseExeption, IOException, InterruptedException { | 			throws RESTErrorResponseException, IOException, InterruptedException { | ||||||
| 		return modelSend("PUT", clazz, urlOffset, data); | 		return modelSend("PUT", clazz, urlOffset, data); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	public <T, U> T putJson(final Class<T> clazz, final String urlOffset, final String body) | 	public <T, U> T putJson(final Class<T> clazz, final String urlOffset, final String body) | ||||||
| 			throws RESTErrorResponseExeption, IOException, InterruptedException { | 			throws RESTErrorResponseException, IOException, InterruptedException { | ||||||
| 		return modelSendJson("PUT", clazz, urlOffset, body); | 		return modelSendJson("PUT", clazz, urlOffset, body); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	public <T> T putMap(final Class<T> clazz, final String urlOffset, final Map<String, Object> data) | 	public <T> T putMap(final Class<T> clazz, final String urlOffset, final Map<String, Object> data) | ||||||
| 			throws RESTErrorResponseExeption, IOException, InterruptedException { | 			throws RESTErrorResponseException, IOException, InterruptedException { | ||||||
| 		return modelSendMap("PUT", clazz, urlOffset, data); | 		return modelSendMap("PUT", clazz, urlOffset, data); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	public <T, U> T patch(final Class<T> clazz, final String urlOffset, final U data) | 	public <T, U> T patch(final Class<T> clazz, final String urlOffset, final U data) | ||||||
| 			throws RESTErrorResponseExeption, IOException, InterruptedException { | 			throws RESTErrorResponseException, IOException, InterruptedException { | ||||||
| 		return modelSend("PATCH", clazz, urlOffset, data); | 		return modelSend("PATCH", clazz, urlOffset, data); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	public <T, U> T patchJson(final Class<T> clazz, final String urlOffset, final String body) | 	public <T, U> T patchJson(final Class<T> clazz, final String urlOffset, final String body) | ||||||
| 			throws RESTErrorResponseExeption, IOException, InterruptedException { | 			throws RESTErrorResponseException, IOException, InterruptedException { | ||||||
| 		return modelSendJson("PATCH", clazz, urlOffset, body); | 		return modelSendJson("PATCH", clazz, urlOffset, body); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	public <T> T patchMap(final Class<T> clazz, final String urlOffset, final Map<String, Object> data) | 	public <T> T patchMap(final Class<T> clazz, final String urlOffset, final Map<String, Object> data) | ||||||
| 			throws RESTErrorResponseExeption, IOException, InterruptedException { | 			throws RESTErrorResponseException, IOException, InterruptedException { | ||||||
| 		return modelSendMap("PATCH", clazz, urlOffset, data); | 		return modelSendMap("PATCH", clazz, urlOffset, data); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	protected <T, U> T modelSend(final String model, final Class<T> clazz, final String urlOffset, final U data) | 	protected <T, U> T modelSend(final String model, final Class<T> clazz, final String urlOffset, final U data) | ||||||
| 			throws RESTErrorResponseExeption, IOException, InterruptedException { | 			throws RESTErrorResponseException, IOException, InterruptedException { | ||||||
| 		if (data == null) { | 		if (data == null) { | ||||||
| 			return modelSendJson(model, clazz, urlOffset, null); | 			return modelSendJson(model, clazz, urlOffset, null); | ||||||
| 		} else { | 		} else { | ||||||
| @@ -123,7 +122,7 @@ public class RESTApi { | |||||||
|  |  | ||||||
| 	@SuppressWarnings("unchecked") | 	@SuppressWarnings("unchecked") | ||||||
| 	public <T, U> T modelSendJson(final String model, final Class<T> clazz, final String urlOffset, String body) | 	public <T, U> T modelSendJson(final String model, final Class<T> clazz, final String urlOffset, String body) | ||||||
| 			throws RESTErrorResponseExeption, IOException, InterruptedException { | 			throws RESTErrorResponseException, IOException, InterruptedException { | ||||||
| 		final HttpClient client = HttpClient.newHttpClient(); | 		final HttpClient client = HttpClient.newHttpClient(); | ||||||
| 		// client.property(HttpUrlConnectorProvider.SET_METHOD_WORKAROUND, true); | 		// client.property(HttpUrlConnectorProvider.SET_METHOD_WORKAROUND, true); | ||||||
| 		Builder requestBuilding = HttpRequest.newBuilder().version(Version.HTTP_1_1) | 		Builder requestBuilding = HttpRequest.newBuilder().version(Version.HTTP_1_1) | ||||||
| @@ -138,13 +137,14 @@ public class RESTApi { | |||||||
| 		} else { | 		} else { | ||||||
| 			requestBuilding = requestBuilding.header("Content-Type", "application/json"); | 			requestBuilding = requestBuilding.header("Content-Type", "application/json"); | ||||||
| 		} | 		} | ||||||
|  | 		LOGGER.trace("publish body: {}", body); | ||||||
| 		final HttpRequest request = requestBuilding.method(model, BodyPublishers.ofString(body)).build(); | 		final HttpRequest request = requestBuilding.method(model, BodyPublishers.ofString(body)).build(); | ||||||
| 		final HttpResponse<String> httpResponse = client.send(request, HttpResponse.BodyHandlers.ofString()); | 		final HttpResponse<String> httpResponse = client.send(request, HttpResponse.BodyHandlers.ofString()); | ||||||
| 		if (httpResponse.statusCode() < 200 || httpResponse.statusCode() >= 300) { | 		if (httpResponse.statusCode() < 200 || httpResponse.statusCode() >= 300) { | ||||||
| 			LOGGER.trace("Receive Error: {}", httpResponse.body()); | 			LOGGER.trace("Receive Error: {}", httpResponse.body()); | ||||||
| 			try { | 			try { | ||||||
| 				final RESTErrorResponseExeption out = this.mapper.readValue(httpResponse.body(), | 				final RESTErrorResponseException out = this.mapper.readValue(httpResponse.body(), | ||||||
| 						RESTErrorResponseExeption.class); | 						RESTErrorResponseException.class); | ||||||
| 				throw out; | 				throw out; | ||||||
| 			} catch (final MismatchedInputException ex) { | 			} catch (final MismatchedInputException ex) { | ||||||
| 				throw new IOException( | 				throw new IOException( | ||||||
| @@ -171,7 +171,7 @@ public class RESTApi { | |||||||
| 			final String model, | 			final String model, | ||||||
| 			final Class<T> clazz, | 			final Class<T> clazz, | ||||||
| 			final String urlOffset, | 			final String urlOffset, | ||||||
| 			final Map<String, Object> data) throws RESTErrorResponseExeption, IOException, InterruptedException { | 			final Map<String, Object> data) throws RESTErrorResponseException, IOException, InterruptedException { | ||||||
| 		final HttpClient client = HttpClient.newHttpClient(); | 		final HttpClient client = HttpClient.newHttpClient(); | ||||||
| 		String body = null; | 		String body = null; | ||||||
| 		Builder requestBuilding = HttpRequest.newBuilder().version(Version.HTTP_1_1) | 		Builder requestBuilding = HttpRequest.newBuilder().version(Version.HTTP_1_1) | ||||||
| @@ -189,8 +189,8 @@ public class RESTApi { | |||||||
| 		final HttpResponse<String> httpResponse = client.send(request, HttpResponse.BodyHandlers.ofString()); | 		final HttpResponse<String> httpResponse = client.send(request, HttpResponse.BodyHandlers.ofString()); | ||||||
| 		if (httpResponse.statusCode() < 200 || httpResponse.statusCode() >= 300) { | 		if (httpResponse.statusCode() < 200 || httpResponse.statusCode() >= 300) { | ||||||
| 			try { | 			try { | ||||||
| 				final RESTErrorResponseExeption out = this.mapper.readValue(httpResponse.body(), | 				final RESTErrorResponseException out = this.mapper.readValue(httpResponse.body(), | ||||||
| 						RESTErrorResponseExeption.class); | 						RESTErrorResponseException.class); | ||||||
| 				throw out; | 				throw out; | ||||||
| 			} catch (final MismatchedInputException ex) { | 			} catch (final MismatchedInputException ex) { | ||||||
| 				throw new IOException( | 				throw new IOException( | ||||||
| @@ -210,7 +210,7 @@ public class RESTApi { | |||||||
| 	 * Call a DELETE on a REST API | 	 * Call a DELETE on a REST API | ||||||
| 	 * @param urlOffset Offset to call the API | 	 * @param urlOffset Offset to call the API | ||||||
| 	 */ | 	 */ | ||||||
| 	public void delete(final String urlOffset) throws RESTErrorResponseExeption, IOException, InterruptedException { | 	public void delete(final String urlOffset) throws RESTErrorResponseException, IOException, InterruptedException { | ||||||
| 		delete(Void.class, urlOffset); | 		delete(Void.class, urlOffset); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| @@ -222,7 +222,7 @@ public class RESTApi { | |||||||
| 	 * @return The parsed object received. | 	 * @return The parsed object received. | ||||||
| 	 */ | 	 */ | ||||||
| 	public <T> T delete(final Class<T> clazz, final String urlOffset) | 	public <T> T delete(final Class<T> clazz, final String urlOffset) | ||||||
| 			throws RESTErrorResponseExeption, IOException, InterruptedException { | 			throws RESTErrorResponseException, IOException, InterruptedException { | ||||||
| 		return simpleRequest("DELETE", clazz, urlOffset); | 		return simpleRequest("DELETE", clazz, urlOffset); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| @@ -230,7 +230,7 @@ public class RESTApi { | |||||||
| 	 * Call an ARCHIVE on a REST API | 	 * Call an ARCHIVE on a REST API | ||||||
| 	 * @param urlOffset Offset to call the API | 	 * @param urlOffset Offset to call the API | ||||||
| 	 */ | 	 */ | ||||||
| 	public void archive(final String urlOffset) throws RESTErrorResponseExeption, IOException, InterruptedException { | 	public void archive(final String urlOffset) throws RESTErrorResponseException, IOException, InterruptedException { | ||||||
| 		archive(Void.class, urlOffset); | 		archive(Void.class, urlOffset); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| @@ -242,7 +242,7 @@ public class RESTApi { | |||||||
| 	 * @return The parsed object received. | 	 * @return The parsed object received. | ||||||
| 	 */ | 	 */ | ||||||
| 	public <T> T archive(final Class<T> clazz, final String urlOffset) | 	public <T> T archive(final Class<T> clazz, final String urlOffset) | ||||||
| 			throws RESTErrorResponseExeption, IOException, InterruptedException { | 			throws RESTErrorResponseException, IOException, InterruptedException { | ||||||
| 		return simpleRequest("ARCHIVE", clazz, urlOffset); | 		return simpleRequest("ARCHIVE", clazz, urlOffset); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| @@ -250,7 +250,7 @@ public class RESTApi { | |||||||
| 	 * Call an RESTORE on a REST API | 	 * Call an RESTORE on a REST API | ||||||
| 	 * @param urlOffset Offset to call the API | 	 * @param urlOffset Offset to call the API | ||||||
| 	 */ | 	 */ | ||||||
| 	public void restore(final String urlOffset) throws RESTErrorResponseExeption, IOException, InterruptedException { | 	public void restore(final String urlOffset) throws RESTErrorResponseException, IOException, InterruptedException { | ||||||
| 		restore(Void.class, urlOffset); | 		restore(Void.class, urlOffset); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| @@ -262,7 +262,7 @@ public class RESTApi { | |||||||
| 	 * @return The parsed object received. | 	 * @return The parsed object received. | ||||||
| 	 */ | 	 */ | ||||||
| 	public <T> T restore(final Class<T> clazz, final String urlOffset) | 	public <T> T restore(final Class<T> clazz, final String urlOffset) | ||||||
| 			throws RESTErrorResponseExeption, IOException, InterruptedException { | 			throws RESTErrorResponseException, IOException, InterruptedException { | ||||||
| 		return simpleRequest("RESTORE", clazz, urlOffset); | 		return simpleRequest("RESTORE", clazz, urlOffset); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| @@ -275,7 +275,7 @@ public class RESTApi { | |||||||
| 	 * @return The parsed object received. | 	 * @return The parsed object received. | ||||||
| 	 */ | 	 */ | ||||||
| 	public <T> T simpleRequest(final String model, final Class<T> clazz, final String urlOffset) | 	public <T> T simpleRequest(final String model, final Class<T> clazz, final String urlOffset) | ||||||
| 			throws RESTErrorResponseExeption, IOException, InterruptedException { | 			throws RESTErrorResponseException, IOException, InterruptedException { | ||||||
| 		final HttpClient client = HttpClient.newHttpClient(); | 		final HttpClient client = HttpClient.newHttpClient(); | ||||||
| 		Builder requestBuilding = HttpRequest.newBuilder().version(Version.HTTP_1_1) | 		Builder requestBuilding = HttpRequest.newBuilder().version(Version.HTTP_1_1) | ||||||
| 				.uri(URI.create(this.baseUrl + urlOffset)); | 				.uri(URI.create(this.baseUrl + urlOffset)); | ||||||
| @@ -286,8 +286,8 @@ public class RESTApi { | |||||||
| 		final HttpResponse<String> httpResponse = client.send(request, HttpResponse.BodyHandlers.ofString()); | 		final HttpResponse<String> httpResponse = client.send(request, HttpResponse.BodyHandlers.ofString()); | ||||||
| 		if (httpResponse.statusCode() < 200 || httpResponse.statusCode() >= 300) { | 		if (httpResponse.statusCode() < 200 || httpResponse.statusCode() >= 300) { | ||||||
| 			try { | 			try { | ||||||
| 				final RESTErrorResponseExeption out = this.mapper.readValue(httpResponse.body(), | 				final RESTErrorResponseException out = this.mapper.readValue(httpResponse.body(), | ||||||
| 						RESTErrorResponseExeption.class); | 						RESTErrorResponseException.class); | ||||||
| 				throw out; | 				throw out; | ||||||
| 			} catch (final MismatchedInputException ex) { | 			} catch (final MismatchedInputException ex) { | ||||||
| 				throw new IOException( | 				throw new IOException( | ||||||
|   | |||||||
| @@ -4,9 +4,9 @@ import java.util.ArrayList; | |||||||
| import java.util.Date; | import java.util.Date; | ||||||
| import java.util.List; | import java.util.List; | ||||||
|  |  | ||||||
| import org.kar.archidata.annotation.ARCHIVE; |  | ||||||
| import org.kar.archidata.annotation.AsyncType; | import org.kar.archidata.annotation.AsyncType; | ||||||
| import org.kar.archidata.annotation.RESTORE; | import org.kar.archidata.annotation.method.ARCHIVE; | ||||||
|  | import org.kar.archidata.annotation.method.RESTORE; | ||||||
| import org.kar.archidata.exception.NotFoundException; | import org.kar.archidata.exception.NotFoundException; | ||||||
| import org.slf4j.Logger; | import org.slf4j.Logger; | ||||||
| import org.slf4j.LoggerFactory; | import org.slf4j.LoggerFactory; | ||||||
|   | |||||||
| @@ -2,9 +2,9 @@ package test.kar.archidata.apiExtern.resource; | |||||||
|  |  | ||||||
| import java.util.List; | import java.util.List; | ||||||
|  |  | ||||||
| import org.kar.archidata.annotation.ARCHIVE; |  | ||||||
| import org.kar.archidata.annotation.AsyncType; | import org.kar.archidata.annotation.AsyncType; | ||||||
| import org.kar.archidata.annotation.RESTORE; | import org.kar.archidata.annotation.method.ARCHIVE; | ||||||
|  | import org.kar.archidata.annotation.method.RESTORE; | ||||||
| import org.kar.archidata.dataAccess.DataAccess; | import org.kar.archidata.dataAccess.DataAccess; | ||||||
| import org.slf4j.Logger; | import org.slf4j.Logger; | ||||||
| import org.slf4j.LoggerFactory; | import org.slf4j.LoggerFactory; | ||||||
|   | |||||||
| @@ -0,0 +1,240 @@ | |||||||
|  | package test.kar.archidata.checker; | ||||||
|  |  | ||||||
|  | import org.junit.jupiter.api.Assertions; | ||||||
|  | import org.junit.jupiter.api.Test; | ||||||
|  | import org.kar.archidata.exception.InputException; | ||||||
|  |  | ||||||
|  | import test.kar.archidata.checker.model.JpaBaseModel; | ||||||
|  | import test.kar.archidata.checker.model.JpaBaseModel.JpaBaseModelChecker; | ||||||
|  |  | ||||||
|  | public class TestJPACheckerDecimalMax { | ||||||
|  |  | ||||||
|  | 	@Test | ||||||
|  | 	public void testDecimalMaxIncludeInteger() throws Exception { | ||||||
|  | 		final JpaBaseModelChecker checker = new JpaBaseModelChecker(); | ||||||
|  | 		final JpaBaseModel data = new JpaBaseModel(); | ||||||
|  | 		data.testDecimalMaxIncludeInteger = 75; | ||||||
|  | 		Assertions.assertDoesNotThrow(() -> checker.check(data)); | ||||||
|  | 		data.testDecimalMaxIncludeInteger = 74; | ||||||
|  | 		Assertions.assertDoesNotThrow(() -> checker.check(data)); | ||||||
|  | 		data.testDecimalMaxIncludeInteger = 76; | ||||||
|  | 		Assertions.assertThrows(InputException.class, () -> checker.check(data)); | ||||||
|  | 		data.testDecimalMaxIncludeInteger = 100; | ||||||
|  | 		Assertions.assertThrows(InputException.class, () -> checker.check(data)); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	@Test | ||||||
|  | 	public void testDecimalMaxIncludeIntegerObject() throws Exception { | ||||||
|  | 		final JpaBaseModelChecker checker = new JpaBaseModelChecker(); | ||||||
|  | 		final JpaBaseModel data = new JpaBaseModel(); | ||||||
|  | 		data.testDecimalMaxIncludeIntegerObject = 75; | ||||||
|  | 		Assertions.assertDoesNotThrow(() -> checker.check(data)); | ||||||
|  | 		data.testDecimalMaxIncludeIntegerObject = 74; | ||||||
|  | 		Assertions.assertDoesNotThrow(() -> checker.check(data)); | ||||||
|  | 		data.testDecimalMaxIncludeIntegerObject = 76; | ||||||
|  | 		Assertions.assertThrows(InputException.class, () -> checker.check(data)); | ||||||
|  | 		data.testDecimalMaxIncludeIntegerObject = 100; | ||||||
|  | 		Assertions.assertThrows(InputException.class, () -> checker.check(data)); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	@Test | ||||||
|  | 	public void testDecimalMaxIncludeLong() throws Exception { | ||||||
|  | 		final JpaBaseModelChecker checker = new JpaBaseModelChecker(); | ||||||
|  | 		final JpaBaseModel data = new JpaBaseModel(); | ||||||
|  | 		data.testDecimalMaxIncludeLong = 75; | ||||||
|  | 		Assertions.assertDoesNotThrow(() -> checker.check(data)); | ||||||
|  | 		data.testDecimalMaxIncludeLong = 74; | ||||||
|  | 		Assertions.assertDoesNotThrow(() -> checker.check(data)); | ||||||
|  | 		data.testDecimalMaxIncludeLong = 76; | ||||||
|  | 		Assertions.assertThrows(InputException.class, () -> checker.check(data)); | ||||||
|  | 		data.testDecimalMaxIncludeLong = 100; | ||||||
|  | 		Assertions.assertThrows(InputException.class, () -> checker.check(data)); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	@Test | ||||||
|  | 	public void testDecimalMaxIncludeLongObject() throws Exception { | ||||||
|  | 		final JpaBaseModelChecker checker = new JpaBaseModelChecker(); | ||||||
|  | 		final JpaBaseModel data = new JpaBaseModel(); | ||||||
|  | 		data.testDecimalMaxIncludeLongObject = 75L; | ||||||
|  | 		Assertions.assertDoesNotThrow(() -> checker.check(data)); | ||||||
|  | 		data.testDecimalMaxIncludeLongObject = 74L; | ||||||
|  | 		Assertions.assertDoesNotThrow(() -> checker.check(data)); | ||||||
|  | 		data.testDecimalMaxIncludeLongObject = 76L; | ||||||
|  | 		Assertions.assertThrows(InputException.class, () -> checker.check(data)); | ||||||
|  | 		data.testDecimalMaxIncludeLongObject = 100L; | ||||||
|  | 		Assertions.assertThrows(InputException.class, () -> checker.check(data)); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	@Test | ||||||
|  | 	public void testDecimalMaxIncludeFloat() throws Exception { | ||||||
|  | 		final JpaBaseModelChecker checker = new JpaBaseModelChecker(); | ||||||
|  | 		final JpaBaseModel data = new JpaBaseModel(); | ||||||
|  | 		// can not be tested | ||||||
|  | 		//data.testDecimalMaxIncludeFloat = 75.56f; | ||||||
|  | 		//Assertions.assertDoesNotThrow(() -> checker.check(data)); | ||||||
|  | 		data.testDecimalMaxIncludeFloat = 75.5599f; | ||||||
|  | 		Assertions.assertDoesNotThrow(() -> checker.check(data)); | ||||||
|  | 		data.testDecimalMaxIncludeFloat = 75.5601f; | ||||||
|  | 		Assertions.assertThrows(InputException.class, () -> checker.check(data)); | ||||||
|  | 		data.testDecimalMaxIncludeFloat = 100f; | ||||||
|  | 		Assertions.assertThrows(InputException.class, () -> checker.check(data)); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	@Test | ||||||
|  | 	public void testDecimalMaxIncludeFloatObject() throws Exception { | ||||||
|  | 		final JpaBaseModelChecker checker = new JpaBaseModelChecker(); | ||||||
|  | 		final JpaBaseModel data = new JpaBaseModel(); | ||||||
|  | 		data.testDecimalMaxIncludeFloatObject = 75.56f; | ||||||
|  | 		Assertions.assertDoesNotThrow(() -> checker.check(data)); | ||||||
|  | 		data.testDecimalMaxIncludeFloatObject = 75.5599f; | ||||||
|  | 		Assertions.assertDoesNotThrow(() -> checker.check(data)); | ||||||
|  | 		data.testDecimalMaxIncludeFloatObject = 75.5601f; | ||||||
|  | 		Assertions.assertThrows(InputException.class, () -> checker.check(data)); | ||||||
|  | 		data.testDecimalMaxIncludeFloatObject = 100f; | ||||||
|  | 		Assertions.assertThrows(InputException.class, () -> checker.check(data)); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	@Test | ||||||
|  | 	public void testDecimalMaxIncludeDouble() throws Exception { | ||||||
|  | 		final JpaBaseModelChecker checker = new JpaBaseModelChecker(); | ||||||
|  | 		final JpaBaseModel data = new JpaBaseModel(); | ||||||
|  | 		// can not be tested | ||||||
|  | 		//data.testDecimalMaxIncludeDouble = 75.56d; | ||||||
|  | 		//Assertions.assertDoesNotThrow(() -> checker.check(data)); | ||||||
|  | 		data.testDecimalMaxIncludeDouble = 75.5599d; | ||||||
|  | 		Assertions.assertDoesNotThrow(() -> checker.check(data)); | ||||||
|  | 		data.testDecimalMaxIncludeDouble = 75.5601d; | ||||||
|  | 		Assertions.assertThrows(InputException.class, () -> checker.check(data)); | ||||||
|  | 		data.testDecimalMaxIncludeDouble = 100d; | ||||||
|  | 		Assertions.assertThrows(InputException.class, () -> checker.check(data)); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	@Test | ||||||
|  | 	public void testDecimalMaxIncludeDoubleObject() throws Exception { | ||||||
|  | 		final JpaBaseModelChecker checker = new JpaBaseModelChecker(); | ||||||
|  | 		final JpaBaseModel data = new JpaBaseModel(); | ||||||
|  | 		//data.testDecimalMaxIncludeDoubleObject = 75.56d; | ||||||
|  | 		//Assertions.assertDoesNotThrow(() -> checker.check(data)); | ||||||
|  | 		data.testDecimalMaxIncludeDoubleObject = 75.5599d; | ||||||
|  | 		Assertions.assertDoesNotThrow(() -> checker.check(data)); | ||||||
|  | 		data.testDecimalMaxIncludeDoubleObject = 75.5601d; | ||||||
|  | 		Assertions.assertThrows(InputException.class, () -> checker.check(data)); | ||||||
|  | 		data.testDecimalMaxIncludeDoubleObject = 100d; | ||||||
|  | 		Assertions.assertThrows(InputException.class, () -> checker.check(data)); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// exclude | ||||||
|  |  | ||||||
|  | 	@Test | ||||||
|  | 	public void testDecimalMaxExcludeInteger() throws Exception { | ||||||
|  | 		final JpaBaseModelChecker checker = new JpaBaseModelChecker(); | ||||||
|  | 		final JpaBaseModel data = new JpaBaseModel(); | ||||||
|  | 		data.testDecimalMaxExcludeInteger = 75; | ||||||
|  | 		Assertions.assertThrows(InputException.class, () -> checker.check(data)); | ||||||
|  | 		data.testDecimalMaxExcludeInteger = 74; | ||||||
|  | 		Assertions.assertDoesNotThrow(() -> checker.check(data)); | ||||||
|  | 		data.testDecimalMaxExcludeInteger = 76; | ||||||
|  | 		Assertions.assertThrows(InputException.class, () -> checker.check(data)); | ||||||
|  | 		data.testDecimalMaxExcludeInteger = 100; | ||||||
|  | 		Assertions.assertThrows(InputException.class, () -> checker.check(data)); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	@Test | ||||||
|  | 	public void testDecimalMaxExcludeIntegerObject() throws Exception { | ||||||
|  | 		final JpaBaseModelChecker checker = new JpaBaseModelChecker(); | ||||||
|  | 		final JpaBaseModel data = new JpaBaseModel(); | ||||||
|  | 		data.testDecimalMaxExcludeIntegerObject = 75; | ||||||
|  | 		Assertions.assertThrows(InputException.class, () -> checker.check(data)); | ||||||
|  | 		data.testDecimalMaxExcludeIntegerObject = 74; | ||||||
|  | 		Assertions.assertDoesNotThrow(() -> checker.check(data)); | ||||||
|  | 		data.testDecimalMaxExcludeIntegerObject = 76; | ||||||
|  | 		Assertions.assertThrows(InputException.class, () -> checker.check(data)); | ||||||
|  | 		data.testDecimalMaxExcludeIntegerObject = 100; | ||||||
|  | 		Assertions.assertThrows(InputException.class, () -> checker.check(data)); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	@Test | ||||||
|  | 	public void testDecimalMaxExcludeLong() throws Exception { | ||||||
|  | 		final JpaBaseModelChecker checker = new JpaBaseModelChecker(); | ||||||
|  | 		final JpaBaseModel data = new JpaBaseModel(); | ||||||
|  | 		data.testDecimalMaxExcludeLong = 75; | ||||||
|  | 		Assertions.assertThrows(InputException.class, () -> checker.check(data)); | ||||||
|  | 		data.testDecimalMaxExcludeLong = 74; | ||||||
|  | 		Assertions.assertDoesNotThrow(() -> checker.check(data)); | ||||||
|  | 		data.testDecimalMaxExcludeLong = 76; | ||||||
|  | 		Assertions.assertThrows(InputException.class, () -> checker.check(data)); | ||||||
|  | 		data.testDecimalMaxExcludeLong = 100; | ||||||
|  | 		Assertions.assertThrows(InputException.class, () -> checker.check(data)); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	@Test | ||||||
|  | 	public void testDecimalMaxExcludeLongObject() throws Exception { | ||||||
|  | 		final JpaBaseModelChecker checker = new JpaBaseModelChecker(); | ||||||
|  | 		final JpaBaseModel data = new JpaBaseModel(); | ||||||
|  | 		data.testDecimalMaxExcludeLongObject = 75L; | ||||||
|  | 		Assertions.assertThrows(InputException.class, () -> checker.check(data)); | ||||||
|  | 		data.testDecimalMaxExcludeLongObject = 74L; | ||||||
|  | 		Assertions.assertDoesNotThrow(() -> checker.check(data)); | ||||||
|  | 		data.testDecimalMaxExcludeLongObject = 76L; | ||||||
|  | 		Assertions.assertThrows(InputException.class, () -> checker.check(data)); | ||||||
|  | 		data.testDecimalMaxExcludeLongObject = 100L; | ||||||
|  | 		Assertions.assertThrows(InputException.class, () -> checker.check(data)); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	@Test | ||||||
|  | 	public void testDecimalMaxExcludeFloat() throws Exception { | ||||||
|  | 		final JpaBaseModelChecker checker = new JpaBaseModelChecker(); | ||||||
|  | 		final JpaBaseModel data = new JpaBaseModel(); | ||||||
|  | 		data.testDecimalMaxExcludeFloat = 75.56f; | ||||||
|  | 		Assertions.assertThrows(InputException.class, () -> checker.check(data)); | ||||||
|  | 		data.testDecimalMaxExcludeFloat = 75.5599f; | ||||||
|  | 		Assertions.assertDoesNotThrow(() -> checker.check(data)); | ||||||
|  | 		data.testDecimalMaxExcludeFloat = 75.5601f; | ||||||
|  | 		Assertions.assertThrows(InputException.class, () -> checker.check(data)); | ||||||
|  | 		data.testDecimalMaxExcludeFloat = 100f; | ||||||
|  | 		Assertions.assertThrows(InputException.class, () -> checker.check(data)); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	@Test | ||||||
|  | 	public void testDecimalMaxExcludeFloatObject() throws Exception { | ||||||
|  | 		final JpaBaseModelChecker checker = new JpaBaseModelChecker(); | ||||||
|  | 		final JpaBaseModel data = new JpaBaseModel(); | ||||||
|  | 		data.testDecimalMaxExcludeFloatObject = 75.56f; | ||||||
|  | 		Assertions.assertThrows(InputException.class, () -> checker.check(data)); | ||||||
|  | 		data.testDecimalMaxExcludeFloatObject = 75.5599f; | ||||||
|  | 		Assertions.assertDoesNotThrow(() -> checker.check(data)); | ||||||
|  | 		data.testDecimalMaxExcludeFloatObject = 75.5601f; | ||||||
|  | 		Assertions.assertThrows(InputException.class, () -> checker.check(data)); | ||||||
|  | 		data.testDecimalMaxExcludeFloatObject = 100f; | ||||||
|  | 		Assertions.assertThrows(InputException.class, () -> checker.check(data)); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	@Test | ||||||
|  | 	public void testDecimalMaxExcludeDouble() throws Exception { | ||||||
|  | 		final JpaBaseModelChecker checker = new JpaBaseModelChecker(); | ||||||
|  | 		final JpaBaseModel data = new JpaBaseModel(); | ||||||
|  | 		data.testDecimalMaxExcludeDouble = 75.56d; | ||||||
|  | 		Assertions.assertThrows(InputException.class, () -> checker.check(data)); | ||||||
|  | 		data.testDecimalMaxExcludeDouble = 75.5599d; | ||||||
|  | 		Assertions.assertDoesNotThrow(() -> checker.check(data)); | ||||||
|  | 		data.testDecimalMaxExcludeDouble = 75.5601d; | ||||||
|  | 		Assertions.assertThrows(InputException.class, () -> checker.check(data)); | ||||||
|  | 		data.testDecimalMaxExcludeDouble = 100d; | ||||||
|  | 		Assertions.assertThrows(InputException.class, () -> checker.check(data)); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	@Test | ||||||
|  | 	public void testDecimalMaxExcludeDoubleObject() throws Exception { | ||||||
|  | 		final JpaBaseModelChecker checker = new JpaBaseModelChecker(); | ||||||
|  | 		final JpaBaseModel data = new JpaBaseModel(); | ||||||
|  | 		data.testDecimalMaxExcludeDoubleObject = 75.56d; | ||||||
|  | 		Assertions.assertThrows(InputException.class, () -> checker.check(data)); | ||||||
|  | 		data.testDecimalMaxExcludeDoubleObject = 75.5599d; | ||||||
|  | 		Assertions.assertDoesNotThrow(() -> checker.check(data)); | ||||||
|  | 		data.testDecimalMaxExcludeDoubleObject = 75.5601d; | ||||||
|  | 		Assertions.assertThrows(InputException.class, () -> checker.check(data)); | ||||||
|  | 		data.testDecimalMaxExcludeDoubleObject = 100d; | ||||||
|  | 		Assertions.assertThrows(InputException.class, () -> checker.check(data)); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | } | ||||||
| @@ -0,0 +1,240 @@ | |||||||
|  | package test.kar.archidata.checker; | ||||||
|  |  | ||||||
|  | import org.junit.jupiter.api.Assertions; | ||||||
|  | import org.junit.jupiter.api.Test; | ||||||
|  | import org.kar.archidata.exception.InputException; | ||||||
|  |  | ||||||
|  | import test.kar.archidata.checker.model.JpaBaseModel; | ||||||
|  | import test.kar.archidata.checker.model.JpaBaseModel.JpaBaseModelChecker; | ||||||
|  |  | ||||||
|  | public class TestJPACheckerDecimalMin { | ||||||
|  |  | ||||||
|  | 	@Test | ||||||
|  | 	public void testDecimalMinIncludeInteger() throws Exception { | ||||||
|  | 		final JpaBaseModelChecker checker = new JpaBaseModelChecker(); | ||||||
|  | 		final JpaBaseModel data = new JpaBaseModel(); | ||||||
|  | 		data.testDecimalMinIncludeInteger = -75; | ||||||
|  | 		Assertions.assertDoesNotThrow(() -> checker.check(data)); | ||||||
|  | 		data.testDecimalMinIncludeInteger = -74; | ||||||
|  | 		Assertions.assertDoesNotThrow(() -> checker.check(data)); | ||||||
|  | 		data.testDecimalMinIncludeInteger = -76; | ||||||
|  | 		Assertions.assertThrows(InputException.class, () -> checker.check(data)); | ||||||
|  | 		data.testDecimalMinIncludeInteger = -100; | ||||||
|  | 		Assertions.assertThrows(InputException.class, () -> checker.check(data)); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	@Test | ||||||
|  | 	public void testDecimalMinIncludeIntegerObject() throws Exception { | ||||||
|  | 		final JpaBaseModelChecker checker = new JpaBaseModelChecker(); | ||||||
|  | 		final JpaBaseModel data = new JpaBaseModel(); | ||||||
|  | 		data.testDecimalMinIncludeIntegerObject = -75; | ||||||
|  | 		Assertions.assertDoesNotThrow(() -> checker.check(data)); | ||||||
|  | 		data.testDecimalMinIncludeIntegerObject = -74; | ||||||
|  | 		Assertions.assertDoesNotThrow(() -> checker.check(data)); | ||||||
|  | 		data.testDecimalMinIncludeIntegerObject = -76; | ||||||
|  | 		Assertions.assertThrows(InputException.class, () -> checker.check(data)); | ||||||
|  | 		data.testDecimalMinIncludeIntegerObject = -100; | ||||||
|  | 		Assertions.assertThrows(InputException.class, () -> checker.check(data)); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	@Test | ||||||
|  | 	public void testDecimalMinIncludeLong() throws Exception { | ||||||
|  | 		final JpaBaseModelChecker checker = new JpaBaseModelChecker(); | ||||||
|  | 		final JpaBaseModel data = new JpaBaseModel(); | ||||||
|  | 		data.testDecimalMinIncludeLong = -75; | ||||||
|  | 		Assertions.assertDoesNotThrow(() -> checker.check(data)); | ||||||
|  | 		data.testDecimalMinIncludeLong = -74; | ||||||
|  | 		Assertions.assertDoesNotThrow(() -> checker.check(data)); | ||||||
|  | 		data.testDecimalMinIncludeLong = -76; | ||||||
|  | 		Assertions.assertThrows(InputException.class, () -> checker.check(data)); | ||||||
|  | 		data.testDecimalMinIncludeLong = -100; | ||||||
|  | 		Assertions.assertThrows(InputException.class, () -> checker.check(data)); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	@Test | ||||||
|  | 	public void testDecimalMinIncludeLongObject() throws Exception { | ||||||
|  | 		final JpaBaseModelChecker checker = new JpaBaseModelChecker(); | ||||||
|  | 		final JpaBaseModel data = new JpaBaseModel(); | ||||||
|  | 		data.testDecimalMinIncludeLongObject = -75L; | ||||||
|  | 		Assertions.assertDoesNotThrow(() -> checker.check(data)); | ||||||
|  | 		data.testDecimalMinIncludeLongObject = -74L; | ||||||
|  | 		Assertions.assertDoesNotThrow(() -> checker.check(data)); | ||||||
|  | 		data.testDecimalMinIncludeLongObject = -76L; | ||||||
|  | 		Assertions.assertThrows(InputException.class, () -> checker.check(data)); | ||||||
|  | 		data.testDecimalMinIncludeLongObject = -100L; | ||||||
|  | 		Assertions.assertThrows(InputException.class, () -> checker.check(data)); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	@Test | ||||||
|  | 	public void testDecimalMinIncludeFloat() throws Exception { | ||||||
|  | 		final JpaBaseModelChecker checker = new JpaBaseModelChecker(); | ||||||
|  | 		final JpaBaseModel data = new JpaBaseModel(); | ||||||
|  | 		data.testDecimalMinIncludeFloat = -75.56f; | ||||||
|  | 		Assertions.assertDoesNotThrow(() -> checker.check(data)); | ||||||
|  | 		data.testDecimalMinIncludeFloat = -75.5599f; | ||||||
|  | 		Assertions.assertDoesNotThrow(() -> checker.check(data)); | ||||||
|  | 		data.testDecimalMinIncludeFloat = -75.5601f; | ||||||
|  | 		Assertions.assertThrows(InputException.class, () -> checker.check(data)); | ||||||
|  | 		data.testDecimalMinIncludeFloat = -100f; | ||||||
|  | 		Assertions.assertThrows(InputException.class, () -> checker.check(data)); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	@Test | ||||||
|  | 	public void testDecimalMinIncludeFloatObject() throws Exception { | ||||||
|  | 		final JpaBaseModelChecker checker = new JpaBaseModelChecker(); | ||||||
|  | 		final JpaBaseModel data = new JpaBaseModel(); | ||||||
|  | 		data.testDecimalMinIncludeFloatObject = -75.56f; | ||||||
|  | 		Assertions.assertDoesNotThrow(() -> checker.check(data)); | ||||||
|  | 		data.testDecimalMinIncludeFloatObject = -75.5599f; | ||||||
|  | 		Assertions.assertDoesNotThrow(() -> checker.check(data)); | ||||||
|  | 		data.testDecimalMinIncludeFloatObject = -75.5601f; | ||||||
|  | 		Assertions.assertThrows(InputException.class, () -> checker.check(data)); | ||||||
|  | 		data.testDecimalMinIncludeFloatObject = -100f; | ||||||
|  | 		Assertions.assertThrows(InputException.class, () -> checker.check(data)); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	@Test | ||||||
|  | 	public void testDecimalMinIncludeDouble() throws Exception { | ||||||
|  | 		final JpaBaseModelChecker checker = new JpaBaseModelChecker(); | ||||||
|  | 		final JpaBaseModel data = new JpaBaseModel(); | ||||||
|  | 		// can not be tested | ||||||
|  | 		//data.testDecimalMinIncludeDouble = -75.56d; | ||||||
|  | 		//Assertions.assertDoesNotThrow(() -> checker.check(data)); | ||||||
|  | 		data.testDecimalMinIncludeDouble = -75.5599d; | ||||||
|  | 		Assertions.assertDoesNotThrow(() -> checker.check(data)); | ||||||
|  | 		data.testDecimalMinIncludeDouble = -75.5601d; | ||||||
|  | 		Assertions.assertThrows(InputException.class, () -> checker.check(data)); | ||||||
|  | 		data.testDecimalMinIncludeDouble = -100d; | ||||||
|  | 		Assertions.assertThrows(InputException.class, () -> checker.check(data)); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	@Test | ||||||
|  | 	public void testDecimalMinIncludeDoubleObject() throws Exception { | ||||||
|  | 		final JpaBaseModelChecker checker = new JpaBaseModelChecker(); | ||||||
|  | 		final JpaBaseModel data = new JpaBaseModel(); | ||||||
|  | 		// can not be tested | ||||||
|  | 		//data.testDecimalMinIncludeDoubleObject = -75.56d; | ||||||
|  | 		//Assertions.assertDoesNotThrow(() -> checker.check(data)); | ||||||
|  | 		data.testDecimalMinIncludeDoubleObject = -75.5599d; | ||||||
|  | 		Assertions.assertDoesNotThrow(() -> checker.check(data)); | ||||||
|  | 		data.testDecimalMinIncludeDoubleObject = -75.5601d; | ||||||
|  | 		Assertions.assertThrows(InputException.class, () -> checker.check(data)); | ||||||
|  | 		data.testDecimalMinIncludeDoubleObject = -100d; | ||||||
|  | 		Assertions.assertThrows(InputException.class, () -> checker.check(data)); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// exclude | ||||||
|  |  | ||||||
|  | 	@Test | ||||||
|  | 	public void testDecimalMinExcludeInteger() throws Exception { | ||||||
|  | 		final JpaBaseModelChecker checker = new JpaBaseModelChecker(); | ||||||
|  | 		final JpaBaseModel data = new JpaBaseModel(); | ||||||
|  | 		data.testDecimalMinExcludeInteger = -75; | ||||||
|  | 		Assertions.assertThrows(InputException.class, () -> checker.check(data)); | ||||||
|  | 		data.testDecimalMinExcludeInteger = -74; | ||||||
|  | 		Assertions.assertDoesNotThrow(() -> checker.check(data)); | ||||||
|  | 		data.testDecimalMinExcludeInteger = -76; | ||||||
|  | 		Assertions.assertThrows(InputException.class, () -> checker.check(data)); | ||||||
|  | 		data.testDecimalMinExcludeInteger = -100; | ||||||
|  | 		Assertions.assertThrows(InputException.class, () -> checker.check(data)); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	@Test | ||||||
|  | 	public void testDecimalMinExcludeIntegerObject() throws Exception { | ||||||
|  | 		final JpaBaseModelChecker checker = new JpaBaseModelChecker(); | ||||||
|  | 		final JpaBaseModel data = new JpaBaseModel(); | ||||||
|  | 		data.testDecimalMinExcludeIntegerObject = -75; | ||||||
|  | 		Assertions.assertThrows(InputException.class, () -> checker.check(data)); | ||||||
|  | 		data.testDecimalMinExcludeIntegerObject = -74; | ||||||
|  | 		Assertions.assertDoesNotThrow(() -> checker.check(data)); | ||||||
|  | 		data.testDecimalMinExcludeIntegerObject = -76; | ||||||
|  | 		Assertions.assertThrows(InputException.class, () -> checker.check(data)); | ||||||
|  | 		data.testDecimalMinExcludeIntegerObject = -100; | ||||||
|  | 		Assertions.assertThrows(InputException.class, () -> checker.check(data)); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	@Test | ||||||
|  | 	public void testDecimalMinExcludeLong() throws Exception { | ||||||
|  | 		final JpaBaseModelChecker checker = new JpaBaseModelChecker(); | ||||||
|  | 		final JpaBaseModel data = new JpaBaseModel(); | ||||||
|  | 		data.testDecimalMinExcludeLong = -75; | ||||||
|  | 		Assertions.assertThrows(InputException.class, () -> checker.check(data)); | ||||||
|  | 		data.testDecimalMinExcludeLong = -74; | ||||||
|  | 		Assertions.assertDoesNotThrow(() -> checker.check(data)); | ||||||
|  | 		data.testDecimalMinExcludeLong = -76; | ||||||
|  | 		Assertions.assertThrows(InputException.class, () -> checker.check(data)); | ||||||
|  | 		data.testDecimalMinExcludeLong = -100; | ||||||
|  | 		Assertions.assertThrows(InputException.class, () -> checker.check(data)); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	@Test | ||||||
|  | 	public void testDecimalMinExcludeLongObject() throws Exception { | ||||||
|  | 		final JpaBaseModelChecker checker = new JpaBaseModelChecker(); | ||||||
|  | 		final JpaBaseModel data = new JpaBaseModel(); | ||||||
|  | 		data.testDecimalMinExcludeLongObject = -75L; | ||||||
|  | 		Assertions.assertThrows(InputException.class, () -> checker.check(data)); | ||||||
|  | 		data.testDecimalMinExcludeLongObject = -74L; | ||||||
|  | 		Assertions.assertDoesNotThrow(() -> checker.check(data)); | ||||||
|  | 		data.testDecimalMinExcludeLongObject = -76L; | ||||||
|  | 		Assertions.assertThrows(InputException.class, () -> checker.check(data)); | ||||||
|  | 		data.testDecimalMinExcludeLongObject = -100L; | ||||||
|  | 		Assertions.assertThrows(InputException.class, () -> checker.check(data)); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	@Test | ||||||
|  | 	public void testDecimalMinExcludeFloat() throws Exception { | ||||||
|  | 		final JpaBaseModelChecker checker = new JpaBaseModelChecker(); | ||||||
|  | 		final JpaBaseModel data = new JpaBaseModel(); | ||||||
|  | 		data.testDecimalMinExcludeFloat = -75.56f; | ||||||
|  | 		Assertions.assertThrows(InputException.class, () -> checker.check(data)); | ||||||
|  | 		data.testDecimalMinExcludeFloat = -75.5599f; | ||||||
|  | 		Assertions.assertDoesNotThrow(() -> checker.check(data)); | ||||||
|  | 		data.testDecimalMinExcludeFloat = -75.5601f; | ||||||
|  | 		Assertions.assertThrows(InputException.class, () -> checker.check(data)); | ||||||
|  | 		data.testDecimalMinExcludeFloat = -100f; | ||||||
|  | 		Assertions.assertThrows(InputException.class, () -> checker.check(data)); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	@Test | ||||||
|  | 	public void testDecimalMinExcludeFloatObject() throws Exception { | ||||||
|  | 		final JpaBaseModelChecker checker = new JpaBaseModelChecker(); | ||||||
|  | 		final JpaBaseModel data = new JpaBaseModel(); | ||||||
|  | 		data.testDecimalMinExcludeFloatObject = -75.56f; | ||||||
|  | 		Assertions.assertThrows(InputException.class, () -> checker.check(data)); | ||||||
|  | 		data.testDecimalMinExcludeFloatObject = -75.5599f; | ||||||
|  | 		Assertions.assertDoesNotThrow(() -> checker.check(data)); | ||||||
|  | 		data.testDecimalMinExcludeFloatObject = -75.5601f; | ||||||
|  | 		Assertions.assertThrows(InputException.class, () -> checker.check(data)); | ||||||
|  | 		data.testDecimalMinExcludeFloatObject = -100f; | ||||||
|  | 		Assertions.assertThrows(InputException.class, () -> checker.check(data)); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	@Test | ||||||
|  | 	public void testDecimalMinExcludeDouble() throws Exception { | ||||||
|  | 		final JpaBaseModelChecker checker = new JpaBaseModelChecker(); | ||||||
|  | 		final JpaBaseModel data = new JpaBaseModel(); | ||||||
|  | 		data.testDecimalMinExcludeDouble = -75.56d; | ||||||
|  | 		Assertions.assertThrows(InputException.class, () -> checker.check(data)); | ||||||
|  | 		data.testDecimalMinExcludeDouble = -75.5599d; | ||||||
|  | 		Assertions.assertDoesNotThrow(() -> checker.check(data)); | ||||||
|  | 		data.testDecimalMinExcludeDouble = -75.5601d; | ||||||
|  | 		Assertions.assertThrows(InputException.class, () -> checker.check(data)); | ||||||
|  | 		data.testDecimalMinExcludeDouble = -100d; | ||||||
|  | 		Assertions.assertThrows(InputException.class, () -> checker.check(data)); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	@Test | ||||||
|  | 	public void testDecimalMinExcludeDoubleObject() throws Exception { | ||||||
|  | 		final JpaBaseModelChecker checker = new JpaBaseModelChecker(); | ||||||
|  | 		final JpaBaseModel data = new JpaBaseModel(); | ||||||
|  | 		data.testDecimalMinExcludeDoubleObject = -75.56d; | ||||||
|  | 		Assertions.assertThrows(InputException.class, () -> checker.check(data)); | ||||||
|  | 		data.testDecimalMinExcludeDoubleObject = -75.5599d; | ||||||
|  | 		Assertions.assertDoesNotThrow(() -> checker.check(data)); | ||||||
|  | 		data.testDecimalMinExcludeDoubleObject = -75.5601d; | ||||||
|  | 		Assertions.assertThrows(InputException.class, () -> checker.check(data)); | ||||||
|  | 		data.testDecimalMinExcludeDoubleObject = -100d; | ||||||
|  | 		Assertions.assertThrows(InputException.class, () -> checker.check(data)); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | } | ||||||
							
								
								
									
										30
									
								
								test/src/test/kar/archidata/checker/TestJPACheckerEMail.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								test/src/test/kar/archidata/checker/TestJPACheckerEMail.java
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,30 @@ | |||||||
|  | package test.kar.archidata.checker; | ||||||
|  |  | ||||||
|  | import org.junit.jupiter.api.Assertions; | ||||||
|  | import org.junit.jupiter.api.Test; | ||||||
|  | import org.kar.archidata.exception.InputException; | ||||||
|  |  | ||||||
|  | import test.kar.archidata.checker.model.JpaBaseModel; | ||||||
|  | import test.kar.archidata.checker.model.JpaBaseModel.JpaBaseModelChecker; | ||||||
|  |  | ||||||
|  | public class TestJPACheckerEMail { | ||||||
|  |  | ||||||
|  | 	@Test | ||||||
|  | 	public void testEMail() throws Exception { | ||||||
|  | 		final JpaBaseModelChecker checker = new JpaBaseModelChecker(); | ||||||
|  | 		final JpaBaseModel data = new JpaBaseModel(); | ||||||
|  | 		data.testEMail = "s@s.ds"; | ||||||
|  | 		Assertions.assertDoesNotThrow(() -> checker.check(data)); | ||||||
|  | 		data.testEMail = "yuio.sdf@sqdf.com"; | ||||||
|  | 		Assertions.assertDoesNotThrow(() -> checker.check(data)); | ||||||
|  | 		data.testEMail = "s@s.s"; | ||||||
|  | 		Assertions.assertThrows(InputException.class, () -> checker.check(data)); | ||||||
|  | 		data.testEMail = "sq@qsd"; | ||||||
|  | 		Assertions.assertThrows(InputException.class, () -> checker.check(data)); | ||||||
|  | 		data.testEMail = "sqsdfsdf"; | ||||||
|  | 		Assertions.assertThrows(InputException.class, () -> checker.check(data)); | ||||||
|  | 		data.testEMail = "56465456"; | ||||||
|  | 		Assertions.assertThrows(InputException.class, () -> checker.check(data)); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | } | ||||||
							
								
								
									
										123
									
								
								test/src/test/kar/archidata/checker/TestJPACheckerMax.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										123
									
								
								test/src/test/kar/archidata/checker/TestJPACheckerMax.java
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,123 @@ | |||||||
|  | package test.kar.archidata.checker; | ||||||
|  |  | ||||||
|  | import org.junit.jupiter.api.Assertions; | ||||||
|  | import org.junit.jupiter.api.Test; | ||||||
|  | import org.kar.archidata.exception.InputException; | ||||||
|  |  | ||||||
|  | import test.kar.archidata.checker.model.JpaBaseModel; | ||||||
|  | import test.kar.archidata.checker.model.JpaBaseModel.JpaBaseModelChecker; | ||||||
|  |  | ||||||
|  | public class TestJPACheckerMax { | ||||||
|  |  | ||||||
|  | 	@Test | ||||||
|  | 	public void testMaxInteger() throws Exception { | ||||||
|  | 		final JpaBaseModelChecker checker = new JpaBaseModelChecker(); | ||||||
|  | 		final JpaBaseModel data = new JpaBaseModel(); | ||||||
|  | 		data.testMaxInteger = 75; | ||||||
|  | 		Assertions.assertDoesNotThrow(() -> checker.check(data)); | ||||||
|  | 		data.testMaxInteger = 74; | ||||||
|  | 		Assertions.assertDoesNotThrow(() -> checker.check(data)); | ||||||
|  | 		data.testMaxInteger = 76; | ||||||
|  | 		Assertions.assertThrows(InputException.class, () -> checker.check(data)); | ||||||
|  | 		data.testMaxInteger = 100; | ||||||
|  | 		Assertions.assertThrows(InputException.class, () -> checker.check(data)); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	@Test | ||||||
|  | 	public void testMaxIntegerObject() throws Exception { | ||||||
|  | 		final JpaBaseModelChecker checker = new JpaBaseModelChecker(); | ||||||
|  | 		final JpaBaseModel data = new JpaBaseModel(); | ||||||
|  | 		data.testMaxIntegerObject = 75; | ||||||
|  | 		Assertions.assertDoesNotThrow(() -> checker.check(data)); | ||||||
|  | 		data.testMaxIntegerObject = 74; | ||||||
|  | 		Assertions.assertDoesNotThrow(() -> checker.check(data)); | ||||||
|  | 		data.testMaxIntegerObject = 76; | ||||||
|  | 		Assertions.assertThrows(InputException.class, () -> checker.check(data)); | ||||||
|  | 		data.testMaxIntegerObject = 100; | ||||||
|  | 		Assertions.assertThrows(InputException.class, () -> checker.check(data)); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	@Test | ||||||
|  | 	public void testMaxLong() throws Exception { | ||||||
|  | 		final JpaBaseModelChecker checker = new JpaBaseModelChecker(); | ||||||
|  | 		final JpaBaseModel data = new JpaBaseModel(); | ||||||
|  | 		data.testMaxLong = 75; | ||||||
|  | 		Assertions.assertDoesNotThrow(() -> checker.check(data)); | ||||||
|  | 		data.testMaxLong = 74; | ||||||
|  | 		Assertions.assertDoesNotThrow(() -> checker.check(data)); | ||||||
|  | 		data.testMaxLong = 76; | ||||||
|  | 		Assertions.assertThrows(InputException.class, () -> checker.check(data)); | ||||||
|  | 		data.testMaxLong = 100; | ||||||
|  | 		Assertions.assertThrows(InputException.class, () -> checker.check(data)); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	@Test | ||||||
|  | 	public void testMaxLongObject() throws Exception { | ||||||
|  | 		final JpaBaseModelChecker checker = new JpaBaseModelChecker(); | ||||||
|  | 		final JpaBaseModel data = new JpaBaseModel(); | ||||||
|  | 		data.testMaxLongObject = 75L; | ||||||
|  | 		Assertions.assertDoesNotThrow(() -> checker.check(data)); | ||||||
|  | 		data.testMaxLongObject = 74L; | ||||||
|  | 		Assertions.assertDoesNotThrow(() -> checker.check(data)); | ||||||
|  | 		data.testMaxLongObject = 76L; | ||||||
|  | 		Assertions.assertThrows(InputException.class, () -> checker.check(data)); | ||||||
|  | 		data.testMaxLongObject = 100L; | ||||||
|  | 		Assertions.assertThrows(InputException.class, () -> checker.check(data)); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	@Test | ||||||
|  | 	public void testMaxFloat() throws Exception { | ||||||
|  | 		final JpaBaseModelChecker checker = new JpaBaseModelChecker(); | ||||||
|  | 		final JpaBaseModel data = new JpaBaseModel(); | ||||||
|  | 		data.testMaxFloat = 75f; | ||||||
|  | 		Assertions.assertDoesNotThrow(() -> checker.check(data)); | ||||||
|  | 		data.testMaxFloat = 74.99f; | ||||||
|  | 		Assertions.assertDoesNotThrow(() -> checker.check(data)); | ||||||
|  | 		data.testMaxFloat = 75.01f; | ||||||
|  | 		Assertions.assertThrows(InputException.class, () -> checker.check(data)); | ||||||
|  | 		data.testMaxFloat = 100f; | ||||||
|  | 		Assertions.assertThrows(InputException.class, () -> checker.check(data)); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	@Test | ||||||
|  | 	public void testMaxFloatObject() throws Exception { | ||||||
|  | 		final JpaBaseModelChecker checker = new JpaBaseModelChecker(); | ||||||
|  | 		final JpaBaseModel data = new JpaBaseModel(); | ||||||
|  | 		data.testMaxFloatObject = 75f; | ||||||
|  | 		Assertions.assertDoesNotThrow(() -> checker.check(data)); | ||||||
|  | 		data.testMaxFloatObject = 74.99f; | ||||||
|  | 		Assertions.assertDoesNotThrow(() -> checker.check(data)); | ||||||
|  | 		data.testMaxFloatObject = 75.01f; | ||||||
|  | 		Assertions.assertThrows(InputException.class, () -> checker.check(data)); | ||||||
|  | 		data.testMaxFloatObject = 100f; | ||||||
|  | 		Assertions.assertThrows(InputException.class, () -> checker.check(data)); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	@Test | ||||||
|  | 	public void testMaxDouble() throws Exception { | ||||||
|  | 		final JpaBaseModelChecker checker = new JpaBaseModelChecker(); | ||||||
|  | 		final JpaBaseModel data = new JpaBaseModel(); | ||||||
|  | 		data.testMaxDouble = 75d; | ||||||
|  | 		Assertions.assertDoesNotThrow(() -> checker.check(data)); | ||||||
|  | 		data.testMaxDouble = 74.99d; | ||||||
|  | 		Assertions.assertDoesNotThrow(() -> checker.check(data)); | ||||||
|  | 		data.testMaxDouble = 75.01d; | ||||||
|  | 		Assertions.assertThrows(InputException.class, () -> checker.check(data)); | ||||||
|  | 		data.testMaxDouble = 100d; | ||||||
|  | 		Assertions.assertThrows(InputException.class, () -> checker.check(data)); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	@Test | ||||||
|  | 	public void testMaxDoubleObject() throws Exception { | ||||||
|  | 		final JpaBaseModelChecker checker = new JpaBaseModelChecker(); | ||||||
|  | 		final JpaBaseModel data = new JpaBaseModel(); | ||||||
|  | 		data.testMaxDoubleObject = 75d; | ||||||
|  | 		Assertions.assertDoesNotThrow(() -> checker.check(data)); | ||||||
|  | 		data.testMaxDoubleObject = 74.99d; | ||||||
|  | 		Assertions.assertDoesNotThrow(() -> checker.check(data)); | ||||||
|  | 		data.testMaxDoubleObject = 75.01d; | ||||||
|  | 		Assertions.assertThrows(InputException.class, () -> checker.check(data)); | ||||||
|  | 		data.testMaxDoubleObject = 100d; | ||||||
|  | 		Assertions.assertThrows(InputException.class, () -> checker.check(data)); | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										123
									
								
								test/src/test/kar/archidata/checker/TestJPACheckerMin.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										123
									
								
								test/src/test/kar/archidata/checker/TestJPACheckerMin.java
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,123 @@ | |||||||
|  | package test.kar.archidata.checker; | ||||||
|  |  | ||||||
|  | import org.junit.jupiter.api.Assertions; | ||||||
|  | import org.junit.jupiter.api.Test; | ||||||
|  | import org.kar.archidata.exception.InputException; | ||||||
|  |  | ||||||
|  | import test.kar.archidata.checker.model.JpaBaseModel; | ||||||
|  | import test.kar.archidata.checker.model.JpaBaseModel.JpaBaseModelChecker; | ||||||
|  |  | ||||||
|  | public class TestJPACheckerMin { | ||||||
|  |  | ||||||
|  | 	@Test | ||||||
|  | 	public void testMinInteger() throws Exception { | ||||||
|  | 		final JpaBaseModelChecker checker = new JpaBaseModelChecker(); | ||||||
|  | 		final JpaBaseModel data = new JpaBaseModel(); | ||||||
|  | 		data.testMinInteger = -75; | ||||||
|  | 		Assertions.assertDoesNotThrow(() -> checker.check(data)); | ||||||
|  | 		data.testMinInteger = -74; | ||||||
|  | 		Assertions.assertDoesNotThrow(() -> checker.check(data)); | ||||||
|  | 		data.testMinInteger = -76; | ||||||
|  | 		Assertions.assertThrows(InputException.class, () -> checker.check(data)); | ||||||
|  | 		data.testMinInteger = -100; | ||||||
|  | 		Assertions.assertThrows(InputException.class, () -> checker.check(data)); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	@Test | ||||||
|  | 	public void testMinIntegerObject() throws Exception { | ||||||
|  | 		final JpaBaseModelChecker checker = new JpaBaseModelChecker(); | ||||||
|  | 		final JpaBaseModel data = new JpaBaseModel(); | ||||||
|  | 		data.testMinIntegerObject = -75; | ||||||
|  | 		Assertions.assertDoesNotThrow(() -> checker.check(data)); | ||||||
|  | 		data.testMinIntegerObject = -74; | ||||||
|  | 		Assertions.assertDoesNotThrow(() -> checker.check(data)); | ||||||
|  | 		data.testMinIntegerObject = -76; | ||||||
|  | 		Assertions.assertThrows(InputException.class, () -> checker.check(data)); | ||||||
|  | 		data.testMinIntegerObject = -100; | ||||||
|  | 		Assertions.assertThrows(InputException.class, () -> checker.check(data)); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	@Test | ||||||
|  | 	public void testMinLong() throws Exception { | ||||||
|  | 		final JpaBaseModelChecker checker = new JpaBaseModelChecker(); | ||||||
|  | 		final JpaBaseModel data = new JpaBaseModel(); | ||||||
|  | 		data.testMinLong = -75; | ||||||
|  | 		Assertions.assertDoesNotThrow(() -> checker.check(data)); | ||||||
|  | 		data.testMinLong = -74; | ||||||
|  | 		Assertions.assertDoesNotThrow(() -> checker.check(data)); | ||||||
|  | 		data.testMinLong = -76; | ||||||
|  | 		Assertions.assertThrows(InputException.class, () -> checker.check(data)); | ||||||
|  | 		data.testMinLong = -100; | ||||||
|  | 		Assertions.assertThrows(InputException.class, () -> checker.check(data)); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	@Test | ||||||
|  | 	public void testMinLongObject() throws Exception { | ||||||
|  | 		final JpaBaseModelChecker checker = new JpaBaseModelChecker(); | ||||||
|  | 		final JpaBaseModel data = new JpaBaseModel(); | ||||||
|  | 		data.testMinLongObject = -75L; | ||||||
|  | 		Assertions.assertDoesNotThrow(() -> checker.check(data)); | ||||||
|  | 		data.testMinLongObject = -74L; | ||||||
|  | 		Assertions.assertDoesNotThrow(() -> checker.check(data)); | ||||||
|  | 		data.testMinLongObject = -76L; | ||||||
|  | 		Assertions.assertThrows(InputException.class, () -> checker.check(data)); | ||||||
|  | 		data.testMinLongObject = -100L; | ||||||
|  | 		Assertions.assertThrows(InputException.class, () -> checker.check(data)); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	@Test | ||||||
|  | 	public void testMinFloat() throws Exception { | ||||||
|  | 		final JpaBaseModelChecker checker = new JpaBaseModelChecker(); | ||||||
|  | 		final JpaBaseModel data = new JpaBaseModel(); | ||||||
|  | 		data.testMinFloat = -75f; | ||||||
|  | 		Assertions.assertDoesNotThrow(() -> checker.check(data)); | ||||||
|  | 		data.testMinFloat = -74.99f; | ||||||
|  | 		Assertions.assertDoesNotThrow(() -> checker.check(data)); | ||||||
|  | 		data.testMinFloat = -75.01f; | ||||||
|  | 		Assertions.assertThrows(InputException.class, () -> checker.check(data)); | ||||||
|  | 		data.testMinFloat = -100f; | ||||||
|  | 		Assertions.assertThrows(InputException.class, () -> checker.check(data)); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	@Test | ||||||
|  | 	public void testMinFloatObject() throws Exception { | ||||||
|  | 		final JpaBaseModelChecker checker = new JpaBaseModelChecker(); | ||||||
|  | 		final JpaBaseModel data = new JpaBaseModel(); | ||||||
|  | 		data.testMinFloatObject = -75f; | ||||||
|  | 		Assertions.assertDoesNotThrow(() -> checker.check(data)); | ||||||
|  | 		data.testMinFloatObject = -74.99f; | ||||||
|  | 		Assertions.assertDoesNotThrow(() -> checker.check(data)); | ||||||
|  | 		data.testMinFloatObject = -75.01f; | ||||||
|  | 		Assertions.assertThrows(InputException.class, () -> checker.check(data)); | ||||||
|  | 		data.testMinFloatObject = -100f; | ||||||
|  | 		Assertions.assertThrows(InputException.class, () -> checker.check(data)); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	@Test | ||||||
|  | 	public void testMinDouble() throws Exception { | ||||||
|  | 		final JpaBaseModelChecker checker = new JpaBaseModelChecker(); | ||||||
|  | 		final JpaBaseModel data = new JpaBaseModel(); | ||||||
|  | 		data.testMinDouble = -75d; | ||||||
|  | 		Assertions.assertDoesNotThrow(() -> checker.check(data)); | ||||||
|  | 		data.testMinDouble = -74.99d; | ||||||
|  | 		Assertions.assertDoesNotThrow(() -> checker.check(data)); | ||||||
|  | 		data.testMinDouble = -75.01d; | ||||||
|  | 		Assertions.assertThrows(InputException.class, () -> checker.check(data)); | ||||||
|  | 		data.testMinDouble = -100d; | ||||||
|  | 		Assertions.assertThrows(InputException.class, () -> checker.check(data)); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	@Test | ||||||
|  | 	public void testMinDoubleObject() throws Exception { | ||||||
|  | 		final JpaBaseModelChecker checker = new JpaBaseModelChecker(); | ||||||
|  | 		final JpaBaseModel data = new JpaBaseModel(); | ||||||
|  | 		data.testMinDoubleObject = -75d; | ||||||
|  | 		Assertions.assertDoesNotThrow(() -> checker.check(data)); | ||||||
|  | 		data.testMinDoubleObject = -74.99d; | ||||||
|  | 		Assertions.assertDoesNotThrow(() -> checker.check(data)); | ||||||
|  | 		data.testMinDoubleObject = -75.01d; | ||||||
|  | 		Assertions.assertThrows(InputException.class, () -> checker.check(data)); | ||||||
|  | 		data.testMinDoubleObject = -100d; | ||||||
|  | 		Assertions.assertThrows(InputException.class, () -> checker.check(data)); | ||||||
|  | 	} | ||||||
|  | } | ||||||
| @@ -0,0 +1,26 @@ | |||||||
|  | package test.kar.archidata.checker; | ||||||
|  |  | ||||||
|  | import org.junit.jupiter.api.Assertions; | ||||||
|  | import org.junit.jupiter.api.Test; | ||||||
|  | import org.kar.archidata.exception.InputException; | ||||||
|  |  | ||||||
|  | import test.kar.archidata.checker.model.JpaBaseModel; | ||||||
|  | import test.kar.archidata.checker.model.JpaBaseModel.JpaBaseModelChecker; | ||||||
|  |  | ||||||
|  | public class TestJPACheckerPattern { | ||||||
|  |  | ||||||
|  | 	@Test | ||||||
|  | 	public void testPattern() throws Exception { | ||||||
|  | 		final JpaBaseModelChecker checker = new JpaBaseModelChecker(); | ||||||
|  | 		final JpaBaseModel data = new JpaBaseModel(); | ||||||
|  | 		data.testPattern = "0"; | ||||||
|  | 		Assertions.assertDoesNotThrow(() -> checker.check(data)); | ||||||
|  | 		data.testPattern = "1234567890"; | ||||||
|  | 		Assertions.assertDoesNotThrow(() -> checker.check(data)); | ||||||
|  | 		data.testPattern = "q"; | ||||||
|  | 		Assertions.assertThrows(InputException.class, () -> checker.check(data)); | ||||||
|  | 		data.testPattern = "qsdf4653"; | ||||||
|  | 		Assertions.assertThrows(InputException.class, () -> checker.check(data)); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | } | ||||||
							
								
								
									
										26
									
								
								test/src/test/kar/archidata/checker/TestJPACheckerSize.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								test/src/test/kar/archidata/checker/TestJPACheckerSize.java
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,26 @@ | |||||||
|  | package test.kar.archidata.checker; | ||||||
|  |  | ||||||
|  | import org.junit.jupiter.api.Assertions; | ||||||
|  | import org.junit.jupiter.api.Test; | ||||||
|  | import org.kar.archidata.exception.InputException; | ||||||
|  |  | ||||||
|  | import test.kar.archidata.checker.model.JpaBaseModel; | ||||||
|  | import test.kar.archidata.checker.model.JpaBaseModel.JpaBaseModelChecker; | ||||||
|  |  | ||||||
|  | public class TestJPACheckerSize { | ||||||
|  |  | ||||||
|  | 	@Test | ||||||
|  | 	public void testSize() throws Exception { | ||||||
|  | 		final JpaBaseModelChecker checker = new JpaBaseModelChecker(); | ||||||
|  | 		final JpaBaseModel data = new JpaBaseModel(); | ||||||
|  | 		data.testSize = "000"; | ||||||
|  | 		Assertions.assertDoesNotThrow(() -> checker.check(data)); | ||||||
|  | 		data.testSize = "00000000"; | ||||||
|  | 		Assertions.assertDoesNotThrow(() -> checker.check(data)); | ||||||
|  | 		data.testSize = "00"; | ||||||
|  | 		Assertions.assertThrows(InputException.class, () -> checker.check(data)); | ||||||
|  | 		data.testSize = "000000000"; | ||||||
|  | 		Assertions.assertThrows(InputException.class, () -> checker.check(data)); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | } | ||||||
							
								
								
									
										132
									
								
								test/src/test/kar/archidata/checker/model/JpaBaseModel.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										132
									
								
								test/src/test/kar/archidata/checker/model/JpaBaseModel.java
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,132 @@ | |||||||
|  | package test.kar.archidata.checker.model; | ||||||
|  |  | ||||||
|  | import org.kar.archidata.checker.CheckJPA; | ||||||
|  |  | ||||||
|  | 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; | ||||||
|  |  | ||||||
|  | public class JpaBaseModel { | ||||||
|  | 	// Simple checker declaration | ||||||
|  | 	public static class JpaBaseModelChecker extends CheckJPA<JpaBaseModel> { | ||||||
|  | 		public JpaBaseModelChecker() { | ||||||
|  | 			super(JpaBaseModel.class); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// Simple data to verify if the checker is active | ||||||
|  | 	@Size(min = 3, max = 8) | ||||||
|  | 	public String testSize; | ||||||
|  |  | ||||||
|  | 	@Pattern(regexp = "^[0-9]+$") | ||||||
|  | 	public String testPattern; | ||||||
|  |  | ||||||
|  | 	@Email | ||||||
|  | 	public String testEMail; | ||||||
|  |  | ||||||
|  | 	@Min(-75) | ||||||
|  | 	public int testMinInteger; | ||||||
|  | 	@Min(-75) | ||||||
|  | 	public Integer testMinIntegerObject; | ||||||
|  | 	@Min(-75) | ||||||
|  | 	public long testMinLong; | ||||||
|  | 	@Min(-75) | ||||||
|  | 	public Long testMinLongObject; | ||||||
|  | 	@Min(-75) | ||||||
|  | 	public float testMinFloat; | ||||||
|  | 	@Min(-75) | ||||||
|  | 	public Float testMinFloatObject; | ||||||
|  | 	@Min(-75) | ||||||
|  | 	public double testMinDouble; | ||||||
|  | 	@Min(-75) | ||||||
|  | 	public Double testMinDoubleObject; | ||||||
|  |  | ||||||
|  | 	@Max(75) | ||||||
|  | 	public int testMaxInteger; | ||||||
|  | 	@Max(75) | ||||||
|  | 	public Integer testMaxIntegerObject; | ||||||
|  | 	@Max(75) | ||||||
|  | 	public long testMaxLong; | ||||||
|  | 	@Max(75) | ||||||
|  | 	public Long testMaxLongObject; | ||||||
|  | 	@Max(75) | ||||||
|  | 	public float testMaxFloat; | ||||||
|  | 	@Max(75) | ||||||
|  | 	public Float testMaxFloatObject; | ||||||
|  | 	@Max(75) | ||||||
|  | 	public double testMaxDouble; | ||||||
|  | 	@Max(75) | ||||||
|  | 	public Double testMaxDoubleObject; | ||||||
|  |  | ||||||
|  | 	@DecimalMin("-75") | ||||||
|  | 	public int testDecimalMinIncludeInteger; | ||||||
|  | 	@DecimalMin("-75") | ||||||
|  | 	public Integer testDecimalMinIncludeIntegerObject; | ||||||
|  | 	@DecimalMin("-75") | ||||||
|  | 	public long testDecimalMinIncludeLong; | ||||||
|  | 	@DecimalMin("-75") | ||||||
|  | 	public Long testDecimalMinIncludeLongObject; | ||||||
|  | 	@DecimalMin("-75.56") | ||||||
|  | 	public float testDecimalMinIncludeFloat; | ||||||
|  | 	@DecimalMin("-75.56") | ||||||
|  | 	public Float testDecimalMinIncludeFloatObject; | ||||||
|  | 	@DecimalMin("-75.56") | ||||||
|  | 	public double testDecimalMinIncludeDouble; | ||||||
|  | 	@DecimalMin("-75.56") | ||||||
|  | 	public Double testDecimalMinIncludeDoubleObject; | ||||||
|  |  | ||||||
|  | 	@DecimalMax("75") | ||||||
|  | 	public int testDecimalMaxIncludeInteger; | ||||||
|  | 	@DecimalMax("75") | ||||||
|  | 	public Integer testDecimalMaxIncludeIntegerObject; | ||||||
|  | 	@DecimalMax("75") | ||||||
|  | 	public long testDecimalMaxIncludeLong; | ||||||
|  | 	@DecimalMax("75") | ||||||
|  | 	public Long testDecimalMaxIncludeLongObject; | ||||||
|  | 	@DecimalMax("75.56") | ||||||
|  | 	public float testDecimalMaxIncludeFloat; | ||||||
|  | 	@DecimalMax("75.56") | ||||||
|  | 	public Float testDecimalMaxIncludeFloatObject; | ||||||
|  | 	@DecimalMax("75.56") | ||||||
|  | 	public double testDecimalMaxIncludeDouble; | ||||||
|  | 	@DecimalMax("75.56") | ||||||
|  | 	public Double testDecimalMaxIncludeDoubleObject; | ||||||
|  |  | ||||||
|  | 	@DecimalMin(value = "-75", inclusive = false) | ||||||
|  | 	public int testDecimalMinExcludeInteger; | ||||||
|  | 	@DecimalMin(value = "-75", inclusive = false) | ||||||
|  | 	public Integer testDecimalMinExcludeIntegerObject; | ||||||
|  | 	@DecimalMin(value = "-75", inclusive = false) | ||||||
|  | 	public long testDecimalMinExcludeLong; | ||||||
|  | 	@DecimalMin(value = "-75", inclusive = false) | ||||||
|  | 	public Long testDecimalMinExcludeLongObject; | ||||||
|  | 	@DecimalMin(value = "-75.56", inclusive = false) | ||||||
|  | 	public float testDecimalMinExcludeFloat; | ||||||
|  | 	@DecimalMin(value = "-75.56", inclusive = false) | ||||||
|  | 	public Float testDecimalMinExcludeFloatObject; | ||||||
|  | 	@DecimalMin(value = "-75.56", inclusive = false) | ||||||
|  | 	public double testDecimalMinExcludeDouble; | ||||||
|  | 	@DecimalMin(value = "-75.56", inclusive = false) | ||||||
|  | 	public Double testDecimalMinExcludeDoubleObject; | ||||||
|  |  | ||||||
|  | 	@DecimalMax(value = "75", inclusive = false) | ||||||
|  | 	public int testDecimalMaxExcludeInteger; | ||||||
|  | 	@DecimalMax(value = "75", inclusive = false) | ||||||
|  | 	public Integer testDecimalMaxExcludeIntegerObject; | ||||||
|  | 	@DecimalMax(value = "75", inclusive = false) | ||||||
|  | 	public long testDecimalMaxExcludeLong; | ||||||
|  | 	@DecimalMax(value = "75", inclusive = false) | ||||||
|  | 	public Long testDecimalMaxExcludeLongObject; | ||||||
|  | 	@DecimalMax(value = "75.56", inclusive = false) | ||||||
|  | 	public float testDecimalMaxExcludeFloat; | ||||||
|  | 	@DecimalMax(value = "75.56", inclusive = false) | ||||||
|  | 	public Float testDecimalMaxExcludeFloatObject; | ||||||
|  | 	@DecimalMax(value = "75.56", inclusive = false) | ||||||
|  | 	public double testDecimalMaxExcludeDouble; | ||||||
|  | 	@DecimalMax(value = "75.56", inclusive = false) | ||||||
|  | 	public Double testDecimalMaxExcludeDoubleObject; | ||||||
|  | } | ||||||
| @@ -1,6 +1,6 @@ | |||||||
| package test.kar.archidata.dataAccess.model; | package test.kar.archidata.dataAccess.model; | ||||||
|  |  | ||||||
| import org.kar.archidata.dataAccess.options.CheckJPA; | import org.kar.archidata.checker.CheckJPA; | ||||||
|  |  | ||||||
| import jakarta.validation.constraints.Pattern; | import jakarta.validation.constraints.Pattern; | ||||||
| import jakarta.validation.constraints.Size; | import jakarta.validation.constraints.Size; | ||||||
|   | |||||||
| @@ -1,7 +1,8 @@ | |||||||
| package test.kar.archidata.dataAccess.model; | package test.kar.archidata.dataAccess.model; | ||||||
|  |  | ||||||
| import org.kar.archidata.annotation.DataJson; | import org.kar.archidata.annotation.DataJson; | ||||||
| import org.kar.archidata.dataAccess.options.CheckJPA; | import org.kar.archidata.annotation.checker.Checker; | ||||||
|  | import org.kar.archidata.checker.CheckJPA; | ||||||
|  |  | ||||||
| public class DataWithSubJson { | public class DataWithSubJson { | ||||||
| 	// Simple checker declaration | 	// Simple checker declaration | ||||||
| @@ -11,6 +12,7 @@ public class DataWithSubJson { | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	@DataJson(checker = DataInJson.DataInJsonChecker.class) | 	@DataJson() | ||||||
|  | 	@Checker(DataInJson.DataInJsonChecker.class) | ||||||
| 	public DataInJson dataSerialized; | 	public DataInJson dataSerialized; | ||||||
| } | } | ||||||
|   | |||||||
| @@ -1 +1 @@ | |||||||
| 0.20.2 | 0.23.0 | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user