Compare commits
	
		
			29 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| abf1ddcf24 | |||
| 3bbbea87fa | |||
| 25a163d4fa | |||
| c9b9d38efe | |||
| cd3a6a1d8b | |||
|   | 5c1b7cd193 | ||
|   | 9ed09d4fed | ||
|   | 33665d47b8 | ||
|   | b907d2212a | ||
| a0f4680271 | |||
| d9e118afaa | |||
| 9f43ebc782 | |||
| 8b831522dc | |||
| 4f5d55bb01 | |||
| 9cbeee66c9 | |||
| d25be53b77 | |||
| d36f9c005a | |||
| 9a6d712d7a | |||
| 55275e4f26 | |||
| f7de0e1db0 | |||
| 032728f05d | |||
| bfe722f074 | |||
| fddf41bea0 | |||
| 3fa48fc839 | |||
| de08bcfab5 | |||
| 37f1362c3c | |||
| e2ee68cc03 | |||
| f05527ce01 | |||
| 38503fac8e | 
							
								
								
									
										17
									
								
								.classpath
									
									
									
									
									
								
							
							
						
						
									
										17
									
								
								.classpath
									
									
									
									
									
								
							| @@ -25,21 +25,24 @@ | |||||||
| 			<attribute name="optional" value="true"/> | 			<attribute name="optional" value="true"/> | ||||||
| 		</attributes> | 		</attributes> | ||||||
| 	</classpathentry> | 	</classpathentry> | ||||||
| 	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"> | 	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-21"> | ||||||
| 		<attributes> | 		<attributes> | ||||||
| 			<attribute name="maven.pomderived" value="true"/> | 			<attribute name="maven.pomderived" value="true"/> | ||||||
| 		</attributes> | 		</attributes> | ||||||
| 	</classpathentry> | 	</classpathentry> | ||||||
|  | 	<classpathentry kind="src" output="target/test-classes" path="target/generated-test-sources/test-annotations"> | ||||||
|  | 		<attributes> | ||||||
|  | 			<attribute name="test" value="true"/> | ||||||
|  | 			<attribute name="optional" value="true"/> | ||||||
|  | 			<attribute name="maven.pomderived" value="true"/> | ||||||
|  | 			<attribute name="ignore_optional_problems" value="true"/> | ||||||
|  | 			<attribute name="m2e-apt" value="true"/> | ||||||
|  | 		</attributes> | ||||||
|  | 	</classpathentry> | ||||||
| 	<classpathentry kind="src" path="target/generated-sources/annotations"> | 	<classpathentry kind="src" path="target/generated-sources/annotations"> | ||||||
| 		<attributes> | 		<attributes> | ||||||
| 			<attribute name="optional" value="true"/> | 			<attribute name="optional" value="true"/> | ||||||
| 		</attributes> | 		</attributes> | ||||||
| 	</classpathentry> | 	</classpathentry> | ||||||
| 	<classpathentry kind="src" output="target/test-classes" path="target/generated-test-sources/test-annotations"> |  | ||||||
| 		<attributes> |  | ||||||
| 			<attribute name="test" value="true"/> |  | ||||||
| 			<attribute name="optional" value="true"/> |  | ||||||
| 		</attributes> |  | ||||||
| 	</classpathentry> |  | ||||||
| 	<classpathentry kind="output" path="target/classes"/> | 	<classpathentry kind="output" path="target/classes"/> | ||||||
| </classpath> | </classpath> | ||||||
|   | |||||||
							
								
								
									
										55
									
								
								pom.xml
									
									
									
									
									
								
							
							
						
						
									
										55
									
								
								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.13.0</version> | 	<version>0.17.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> | ||||||
| @@ -54,6 +54,30 @@ | |||||||
| 			<version>2.1.0-alpha1</version> | 			<version>2.1.0-alpha1</version> | ||||||
| 			<scope>test</scope> | 			<scope>test</scope> | ||||||
| 		</dependency> | 		</dependency> | ||||||
|  | 		<!-- Decode webP images --> | ||||||
|  | 		<dependency> | ||||||
|  | 			<groupId>com.twelvemonkeys.imageio</groupId> | ||||||
|  | 			<artifactId>imageio-webp</artifactId> | ||||||
|  | 			<version>3.11.0</version> | ||||||
|  | 		</dependency> | ||||||
|  | 		<!-- Decode JPEG image --> | ||||||
|  | 		<dependency> | ||||||
|  | 			<groupId>com.twelvemonkeys.imageio</groupId> | ||||||
|  | 			<artifactId>imageio-jpeg</artifactId> | ||||||
|  | 			<version>3.11.0</version> | ||||||
|  | 		</dependency> | ||||||
|  | 		<!-- Encode file in webp --> | ||||||
|  | 		<dependency> | ||||||
|  | 			<groupId>com.github.gotson</groupId> | ||||||
|  | 			<artifactId>webp-imageio</artifactId> | ||||||
|  | 			<version>0.2.2</version> | ||||||
|  | 		</dependency> | ||||||
|  | 		<!-- Detect type of a file with mime type --> | ||||||
|  | 		<dependency> | ||||||
|  | 			<groupId>org.apache.tika</groupId> | ||||||
|  | 			<artifactId>tika-core</artifactId> | ||||||
|  | 			<version>3.0.0-BETA2</version> | ||||||
|  | 		</dependency> | ||||||
| 		<!-- https://mvnrepository.com/artifact/org.glassfish.jersey.media/jersey-media-multipart --> | 		<!-- https://mvnrepository.com/artifact/org.glassfish.jersey.media/jersey-media-multipart --> | ||||||
| 		<dependency> | 		<dependency> | ||||||
| 			<groupId>org.glassfish.jersey.media</groupId> | 			<groupId>org.glassfish.jersey.media</groupId> | ||||||
| @@ -96,11 +120,13 @@ | |||||||
| 			<artifactId>istack-commons-runtime</artifactId> | 			<artifactId>istack-commons-runtime</artifactId> | ||||||
| 			<version>${istack.version}</version> | 			<version>${istack.version}</version> | ||||||
| 		</dependency> | 		</dependency> | ||||||
|  | 		<!-- continu to be needed ??? --> | ||||||
| 		<dependency> | 		<dependency> | ||||||
| 			<groupId>org.glassfish.jersey.test-framework.providers</groupId> | 			<groupId>org.glassfish.jersey.test-framework.providers</groupId> | ||||||
| 			<artifactId>jersey-test-framework-provider-grizzly2</artifactId> | 			<artifactId>jersey-test-framework-provider-grizzly2</artifactId> | ||||||
| 			<scope>test</scope> | 			<scope>test</scope> | ||||||
| 		</dependency> | 		</dependency> | ||||||
|  | 		<!-- Serialize and un-serialize request in JSON--> | ||||||
| 		<dependency> | 		<dependency> | ||||||
| 			<groupId>org.glassfish.jersey.media</groupId> | 			<groupId>org.glassfish.jersey.media</groupId> | ||||||
| 			<artifactId>jersey-media-json-jackson</artifactId> | 			<artifactId>jersey-media-json-jackson</artifactId> | ||||||
| @@ -108,40 +134,41 @@ | |||||||
| 		<dependency> | 		<dependency> | ||||||
| 			<groupId>com.fasterxml.jackson.core</groupId> | 			<groupId>com.fasterxml.jackson.core</groupId> | ||||||
| 			<artifactId>jackson-databind</artifactId> | 			<artifactId>jackson-databind</artifactId> | ||||||
| 			<version>2.17.1</version> | 			<version>2.18.0-rc1</version> | ||||||
| 		</dependency> | 		</dependency> | ||||||
|  | 		<!-- encode output in CSV --> | ||||||
| 		<dependency> | 		<dependency> | ||||||
| 			<groupId>com.fasterxml.jackson.dataformat</groupId> | 			<groupId>com.fasterxml.jackson.dataformat</groupId> | ||||||
| 			<artifactId>jackson-dataformat-csv</artifactId> | 			<artifactId>jackson-dataformat-csv</artifactId> | ||||||
| 			<version>2.17.1</version> | 			<version>2.18.0-rc1</version> | ||||||
| 		</dependency> | 		</dependency> | ||||||
| 		<dependency> | 		<dependency> | ||||||
| 			<groupId>com.fasterxml.jackson.datatype</groupId> | 			<groupId>com.fasterxml.jackson.datatype</groupId> | ||||||
| 			<artifactId>jackson-datatype-jsr310</artifactId> | 			<artifactId>jackson-datatype-jsr310</artifactId> | ||||||
| 			<version>2.17.1</version> | 			<version>2.18.0-rc1</version> | ||||||
| 		</dependency> | 		</dependency> | ||||||
| 		<dependency> | 		<dependency> | ||||||
| 			<groupId>jakarta.servlet</groupId> | 			<groupId>jakarta.servlet</groupId> | ||||||
| 			<artifactId>jakarta.servlet-api</artifactId> | 			<artifactId>jakarta.servlet-api</artifactId> | ||||||
| 			<version>6.1.0-M2</version> | 			<version>6.1.0</version> | ||||||
| 			<scope>provided</scope> | 			<scope>provided</scope> | ||||||
| 		</dependency> | 		</dependency> | ||||||
| 		<!-- Interface for My-sql & sqlite DB --> | 		<!-- Interface for My-sql & sqlite DB --> | ||||||
| 		<dependency> | 		<dependency> | ||||||
| 			<groupId>com.mysql</groupId> | 			<groupId>com.mysql</groupId> | ||||||
| 			<artifactId>mysql-connector-j</artifactId> | 			<artifactId>mysql-connector-j</artifactId> | ||||||
| 			<version>8.4.0</version> | 			<version>9.0.0</version> | ||||||
| 		</dependency> | 		</dependency> | ||||||
| 		<dependency> | 		<dependency> | ||||||
| 			<groupId>org.xerial</groupId> | 			<groupId>org.xerial</groupId> | ||||||
| 			<artifactId>sqlite-jdbc</artifactId> | 			<artifactId>sqlite-jdbc</artifactId> | ||||||
| 			<version>3.46.0.0</version> | 			<version>3.46.1.0</version> | ||||||
| 		</dependency> | 		</dependency> | ||||||
| 		<!-- Interface for JWT token --> | 		<!-- Interface for JWT token --> | ||||||
| 		<dependency> | 		<dependency> | ||||||
| 			<groupId>com.nimbusds</groupId> | 			<groupId>com.nimbusds</groupId> | ||||||
| 			<artifactId>nimbus-jose-jwt</artifactId> | 			<artifactId>nimbus-jose-jwt</artifactId> | ||||||
| 			<version>9.39.3</version> | 			<version>9.41.1</version> | ||||||
| 		</dependency> | 		</dependency> | ||||||
| 		<dependency> | 		<dependency> | ||||||
| 			<groupId>jakarta.persistence</groupId> | 			<groupId>jakarta.persistence</groupId> | ||||||
| @@ -152,13 +179,13 @@ | |||||||
| 		<dependency> | 		<dependency> | ||||||
| 			<groupId>io.swagger.core.v3</groupId> | 			<groupId>io.swagger.core.v3</groupId> | ||||||
| 			<artifactId>swagger-jaxrs2-jakarta</artifactId> | 			<artifactId>swagger-jaxrs2-jakarta</artifactId> | ||||||
| 			<version>2.2.22</version> | 			<version>2.2.23</version> | ||||||
| 		</dependency> | 		</dependency> | ||||||
| 		<!-- spotbug tooling --> | 		<!-- spotbug tooling --> | ||||||
| 		<dependency> | 		<dependency> | ||||||
| 			<groupId>com.github.spotbugs</groupId> | 			<groupId>com.github.spotbugs</groupId> | ||||||
| 			<artifactId>spotbugs-annotations</artifactId> | 			<artifactId>spotbugs-annotations</artifactId> | ||||||
| 			<version>4.8.5</version> | 			<version>4.8.6</version> | ||||||
| 			<scope>compile</scope> | 			<scope>compile</scope> | ||||||
| 		</dependency> | 		</dependency> | ||||||
| 		<!-- | 		<!-- | ||||||
| @@ -169,24 +196,24 @@ | |||||||
| 		<dependency> | 		<dependency> | ||||||
| 			<groupId>org.junit.jupiter</groupId> | 			<groupId>org.junit.jupiter</groupId> | ||||||
| 			<artifactId>junit-jupiter-api</artifactId> | 			<artifactId>junit-jupiter-api</artifactId> | ||||||
| 			<version>5.11.0-M2</version> | 			<version>5.11.0</version> | ||||||
| 			<scope>test</scope> | 			<scope>test</scope> | ||||||
| 		</dependency> | 		</dependency> | ||||||
| 		<dependency> | 		<dependency> | ||||||
| 			<groupId>org.junit.jupiter</groupId> | 			<groupId>org.junit.jupiter</groupId> | ||||||
| 			<artifactId>junit-jupiter-engine</artifactId> | 			<artifactId>junit-jupiter-engine</artifactId> | ||||||
| 			<version>5.11.0-M2</version> | 			<version>5.11.0</version> | ||||||
| 			<scope>test</scope> | 			<scope>test</scope> | ||||||
| 		</dependency> | 		</dependency> | ||||||
| 		<dependency> | 		<dependency> | ||||||
| 			<groupId>net.revelc.code.formatter</groupId> | 			<groupId>net.revelc.code.formatter</groupId> | ||||||
| 			<artifactId>formatter-maven-plugin</artifactId> | 			<artifactId>formatter-maven-plugin</artifactId> | ||||||
| 			<version>2.24.0</version> | 			<version>2.24.1</version> | ||||||
| 		</dependency> | 		</dependency> | ||||||
| 		<dependency> | 		<dependency> | ||||||
| 			<groupId>org.apache.maven.plugins</groupId> | 			<groupId>org.apache.maven.plugins</groupId> | ||||||
| 			<artifactId>maven-checkstyle-plugin</artifactId> | 			<artifactId>maven-checkstyle-plugin</artifactId> | ||||||
| 			<version>3.3.1</version> | 			<version>3.5.0</version> | ||||||
| 		</dependency> | 		</dependency> | ||||||
| 	</dependencies> | 	</dependencies> | ||||||
| 	<build> | 	<build> | ||||||
|   | |||||||
							
								
								
									
										19
									
								
								src/org/kar/archidata/annotation/ARCHIVE.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								src/org/kar/archidata/annotation/ARCHIVE.java
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,19 @@ | |||||||
|  | package org.kar.archidata.annotation; | ||||||
|  |  | ||||||
|  | import java.lang.annotation.ElementType; | ||||||
|  | import java.lang.annotation.Retention; | ||||||
|  | import java.lang.annotation.RetentionPolicy; | ||||||
|  | import java.lang.annotation.Target; | ||||||
|  |  | ||||||
|  | import jakarta.ws.rs.HttpMethod; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  | * Indicates that the annotated method responds to HTTP ARCHIVE requests. | ||||||
|  | * | ||||||
|  | * @author Edouard DUPIN | ||||||
|  | * @see HttpMethod | ||||||
|  | */ | ||||||
|  | @Target({ ElementType.METHOD }) | ||||||
|  | @Retention(RetentionPolicy.RUNTIME) | ||||||
|  | @HttpMethod("ARCHIVE") | ||||||
|  | public @interface ARCHIVE {} | ||||||
| @@ -258,15 +258,11 @@ public class AnnotationTools { | |||||||
| 		return false; | 		return false; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	public static String getFieldName(final Field element) throws DataAccessException { | 	public static String getFieldName(final Field element) { | ||||||
| 		final Annotation[] annotation = element.getDeclaredAnnotationsByType(Column.class); | 		final Annotation[] annotation = element.getDeclaredAnnotationsByType(Column.class); | ||||||
| 		if (annotation.length == 0) { | 		if (annotation.length == 0) { | ||||||
| 			return element.getName(); | 			return element.getName(); | ||||||
| 		} | 		} | ||||||
| 		if (annotation.length > 1) { |  | ||||||
| 			throw new DataAccessException( |  | ||||||
| 					"Must not have more than 1 element @Column on " + element.getClass().getCanonicalName()); |  | ||||||
| 		} |  | ||||||
| 		final String name = ((Column) annotation[0]).name(); | 		final String name = ((Column) annotation[0]).name(); | ||||||
| 		if (name.isBlank()) { | 		if (name.isBlank()) { | ||||||
| 			return element.getName(); | 			return element.getName(); | ||||||
|   | |||||||
							
								
								
									
										12
									
								
								src/org/kar/archidata/annotation/FormDataOptional.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								src/org/kar/archidata/annotation/FormDataOptional.java
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,12 @@ | |||||||
|  | package org.kar.archidata.annotation; | ||||||
|  |  | ||||||
|  | import java.lang.annotation.ElementType; | ||||||
|  | import java.lang.annotation.Retention; | ||||||
|  | import java.lang.annotation.RetentionPolicy; | ||||||
|  | import java.lang.annotation.Target; | ||||||
|  |  | ||||||
|  | @Target({ ElementType.PARAMETER }) | ||||||
|  | @Retention(RetentionPolicy.RUNTIME) | ||||||
|  | public @interface FormDataOptional { | ||||||
|  |  | ||||||
|  | } | ||||||
							
								
								
									
										19
									
								
								src/org/kar/archidata/annotation/RESTORE.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								src/org/kar/archidata/annotation/RESTORE.java
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,19 @@ | |||||||
|  | package org.kar.archidata.annotation; | ||||||
|  |  | ||||||
|  | import java.lang.annotation.ElementType; | ||||||
|  | import java.lang.annotation.Retention; | ||||||
|  | import java.lang.annotation.RetentionPolicy; | ||||||
|  | import java.lang.annotation.Target; | ||||||
|  |  | ||||||
|  | import jakarta.ws.rs.HttpMethod; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  | * Indicates that the annotated method responds to HTTP RESTORE requests. | ||||||
|  | * | ||||||
|  | * @author Edouard DUPIN | ||||||
|  | * @see HttpMethod | ||||||
|  | */ | ||||||
|  | @Target({ ElementType.METHOD }) | ||||||
|  | @Retention(RetentionPolicy.RUNTIME) | ||||||
|  | @HttpMethod("RESTORE") | ||||||
|  | public @interface RESTORE {} | ||||||
| @@ -304,9 +304,11 @@ public class DataResource { | |||||||
| 		// logger.info("==================================================="); | 		// logger.info("==================================================="); | ||||||
| 		final Data value = getSmall(uuid); | 		final Data value = getSmall(uuid); | ||||||
| 		if (value == null) { | 		if (value == null) { | ||||||
|  | 			LOGGER.warn("Request data that does not exist : {}", uuid); | ||||||
| 			return Response.status(404).entity("media NOT FOUND: " + uuid).type("text/plain").build(); | 			return Response.status(404).entity("media NOT FOUND: " + uuid).type("text/plain").build(); | ||||||
| 		} | 		} | ||||||
| 		try { | 		try { | ||||||
|  | 			LOGGER.warn("Generate stream : {}", uuid); | ||||||
| 			return buildStream(getFileData(uuid), range, | 			return buildStream(getFileData(uuid), range, | ||||||
| 					value.mimeType == null ? "application/octet-stream" : value.mimeType); | 					value.mimeType == null ? "application/octet-stream" : value.mimeType); | ||||||
| 		} catch (final Exception ex) { | 		} catch (final Exception ex) { | ||||||
| @@ -326,10 +328,10 @@ public class DataResource { | |||||||
| 			@QueryParam(HttpHeaders.AUTHORIZATION) final String token, | 			@QueryParam(HttpHeaders.AUTHORIZATION) final String token, | ||||||
| 			@HeaderParam("Range") final String range, | 			@HeaderParam("Range") final String range, | ||||||
| 			@PathParam("uuid") final UUID uuid) throws FailException { | 			@PathParam("uuid") final UUID uuid) throws FailException { | ||||||
| 		// GenericContext gc = (GenericContext) sc.getUserPrincipal(); | 		final GenericContext gc = (GenericContext) sc.getUserPrincipal(); | ||||||
| 		// logger.info("==================================================="); | 		LOGGER.info("==================================================="); | ||||||
| 		// logger.info("== DATA retrieveDataThumbnailId ? {}", (gc==null?"null":gc.user)); | 		LOGGER.info("== DATA retrieveDataThumbnailId ? {}", (gc == null ? "null" : gc.userByToken)); | ||||||
| 		// logger.info("==================================================="); | 		LOGGER.info("==================================================="); | ||||||
| 		final Data value = getSmall(uuid); | 		final Data value = getSmall(uuid); | ||||||
| 		if (value == null) { | 		if (value == null) { | ||||||
| 			return Response.status(404).entity("media NOT FOUND: " + uuid).type("text/plain").build(); | 			return Response.status(404).entity("media NOT FOUND: " + uuid).type("text/plain").build(); | ||||||
| @@ -350,31 +352,43 @@ public class DataResource { | |||||||
| 			} catch (final IOException ex) { | 			} catch (final IOException ex) { | ||||||
| 				throw new FailException(Response.Status.INTERNAL_SERVER_ERROR, "Fail to READ the image", ex); | 				throw new FailException(Response.Status.INTERNAL_SERVER_ERROR, "Fail to READ the image", ex); | ||||||
| 			} | 			} | ||||||
|  | 			LOGGER.info("input size image: {}x{} type={}", inputImage.getWidth(), inputImage.getHeight(), | ||||||
|  | 					inputImage.getType()); | ||||||
| 			final int scaledWidth = 250; | 			final int scaledWidth = 250; | ||||||
| 			final int scaledHeight = (int) ((float) inputImage.getHeight() / (float) inputImage.getWidth() | 			final int scaledHeight = (int) ((float) inputImage.getHeight() / (float) inputImage.getWidth() | ||||||
| 					* scaledWidth); | 					* scaledWidth); | ||||||
|  |  | ||||||
| 			// creates output image | 			// creates output image | ||||||
| 			final BufferedImage outputImage = new BufferedImage(scaledWidth, scaledHeight, inputImage.getType()); | 			final BufferedImage outputImage = new BufferedImage(scaledWidth, scaledHeight, inputImage.getType()); | ||||||
|  |  | ||||||
| 			// scales the input image to the output image | 			// scales the input image to the output image | ||||||
| 			final Graphics2D g2d = outputImage.createGraphics(); | 			final Graphics2D g2d = outputImage.createGraphics(); | ||||||
|  | 			LOGGER.info("output size image: {}x{}", scaledWidth, scaledHeight); | ||||||
| 			g2d.drawImage(inputImage, 0, 0, scaledWidth, scaledHeight, null); | 			g2d.drawImage(inputImage, 0, 0, scaledWidth, scaledHeight, null); | ||||||
| 			g2d.dispose(); | 			g2d.dispose(); | ||||||
|  | 			for (final String data : ImageIO.getWriterFormatNames()) { | ||||||
|  | 				LOGGER.info("availlable format: {}", data); | ||||||
|  | 			} | ||||||
| 			// create the output stream: | 			// create the output stream: | ||||||
| 			final ByteArrayOutputStream baos = new ByteArrayOutputStream(); | 			final ByteArrayOutputStream baos = new ByteArrayOutputStream(); | ||||||
| 			try { | 			try { | ||||||
| 				// TODO: check how to remove buffer file !!! here, it is not needed at all... | 				// TODO: check how to remove buffer file !!! here, it is not needed at all... | ||||||
| 				ImageIO.write(outputImage, "JPG", baos); | 				//ImageIO.write(outputImage, "JPEG", baos); | ||||||
|  | 				//ImageIO.write(outputImage, "png", baos); | ||||||
|  | 				ImageIO.write(outputImage, "WebP", baos); | ||||||
| 			} catch (final IOException e) { | 			} catch (final IOException e) { | ||||||
| 				e.printStackTrace(); | 				e.printStackTrace(); | ||||||
| 				return Response.status(500).entity("Internal Error: resize fail: " + e.getMessage()).type("text/plain") | 				return Response.status(500).entity("Internal Error: resize fail: " + e.getMessage()).type("text/plain") | ||||||
| 						.build(); | 						.build(); | ||||||
| 			} | 			} | ||||||
| 			final byte[] imageData = baos.toByteArray(); | 			final byte[] imageData = baos.toByteArray(); | ||||||
|  | 			LOGGER.info("output length {}", imageData.length); | ||||||
| 			// Response.ok(new ByteArrayInputStream(imageData)).build(); | 			// Response.ok(new ByteArrayInputStream(imageData)).build(); | ||||||
| 			final Response.ResponseBuilder out = Response.ok(imageData).header(HttpHeaders.CONTENT_LENGTH, | 			final Response.ResponseBuilder out = Response.ok(imageData).header(HttpHeaders.CONTENT_LENGTH, | ||||||
| 					imageData.length); | 					imageData.length); | ||||||
| 			out.type("image/jpeg"); | 			//out.type("image/jpeg"); | ||||||
|  | 			out.type("image/webp"); | ||||||
|  | 			//out.type("image/png"); | ||||||
| 			// TODO: move this in a decorator !!! | 			// TODO: move this in a decorator !!! | ||||||
| 			final CacheControl cc = new CacheControl(); | 			final CacheControl cc = new CacheControl(); | ||||||
| 			cc.setMaxAge(3600); | 			cc.setMaxAge(3600); | ||||||
| @@ -466,8 +480,9 @@ public class DataResource { | |||||||
| 			to = file.length() - 1; | 			to = file.length() - 1; | ||||||
| 		} | 		} | ||||||
| 		final String responseRange = String.format("bytes %d-%d/%d", from, to, file.length()); | 		final String responseRange = String.format("bytes %d-%d/%d", from, to, file.length()); | ||||||
| 		// logger.info("responseRange: {}", responseRange); | 		// LOGGER.info("responseRange: {}", responseRange); | ||||||
| 		try (final RandomAccessFile raf = new RandomAccessFile(file, "r")) { | 		try { | ||||||
|  | 			final RandomAccessFile raf = new RandomAccessFile(file, "r"); | ||||||
| 			raf.seek(from); | 			raf.seek(from); | ||||||
|  |  | ||||||
| 			final long len = to - from + 1; | 			final long len = to - from + 1; | ||||||
|   | |||||||
| @@ -58,5 +58,4 @@ public class MediaStreamer implements StreamingOutput { | |||||||
| 	public long getLenth() { | 	public long getLenth() { | ||||||
| 		return this.length; | 		return this.length; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| } | } | ||||||
|   | |||||||
							
								
								
									
										43
									
								
								src/org/kar/archidata/api/ProxyResource.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								src/org/kar/archidata/api/ProxyResource.java
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,43 @@ | |||||||
|  | package org.kar.archidata.api; | ||||||
|  |  | ||||||
|  | import org.slf4j.Logger; | ||||||
|  | import org.slf4j.LoggerFactory; | ||||||
|  |  | ||||||
|  | import jakarta.ws.rs.GET; | ||||||
|  | import jakarta.ws.rs.Path; | ||||||
|  | import jakarta.ws.rs.Produces; | ||||||
|  | import jakarta.ws.rs.QueryParam; | ||||||
|  | import jakarta.ws.rs.client.Client; | ||||||
|  | import jakarta.ws.rs.client.ClientBuilder; | ||||||
|  | import jakarta.ws.rs.client.WebTarget; | ||||||
|  | import jakarta.ws.rs.core.MediaType; | ||||||
|  | import jakarta.ws.rs.core.Response; | ||||||
|  | import jakarta.ws.rs.core.Response.Status; | ||||||
|  |  | ||||||
|  | @Path("/proxy") | ||||||
|  | //@Produces(MediaType.APPLICATION_JSON) | ||||||
|  | public class ProxyResource { | ||||||
|  | 	private static final Logger LOGGER = LoggerFactory.getLogger(ProxyResource.class); | ||||||
|  |  | ||||||
|  | 	@GET | ||||||
|  | 	@Produces(MediaType.APPLICATION_OCTET_STREAM) | ||||||
|  | 	public Response getImageFromUrl(@QueryParam("url") final String url) { | ||||||
|  | 		if (url == null || url.isEmpty()) { | ||||||
|  | 			return Response.status(Status.BAD_REQUEST).entity("URL manquante").build(); | ||||||
|  | 		} | ||||||
|  | 		final Client client = ClientBuilder.newClient(); | ||||||
|  | 		try { | ||||||
|  | 			final WebTarget target = client.target(url); | ||||||
|  | 			final Response response = target.request().get(); | ||||||
|  | 			if (response.getStatus() != 200) { | ||||||
|  | 				return Response.status(Status.BAD_GATEWAY).entity("Can not get the image : " + response.getStatus()) | ||||||
|  | 						.build(); | ||||||
|  | 			} | ||||||
|  | 			return Response.ok(response.readEntity(byte[].class)).header("Access-Control-Allow-Origin", "*") | ||||||
|  | 					.header("Content-Type", response.getHeaderString("Content-Type")).build(); | ||||||
|  | 		} catch (final Exception e) { | ||||||
|  | 			return Response.status(Status.INTERNAL_SERVER_ERROR).entity("SERVER internal error : " + e.getMessage()) | ||||||
|  | 					.build(); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
| @@ -20,6 +20,7 @@ public class WebApplicationExceptionCatcher implements ExceptionMapper<WebApplic | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	private RestErrorResponse build(final WebApplicationException exception) { | 	private RestErrorResponse build(final WebApplicationException exception) { | ||||||
|  | 		exception.printStackTrace(); | ||||||
| 		return new RestErrorResponse(exception.getResponse().getStatusInfo().toEnum(), "Catch system exception", | 		return new RestErrorResponse(exception.getResponse().getStatusInfo().toEnum(), "Catch system exception", | ||||||
| 				exception.getMessage()); | 				exception.getMessage()); | ||||||
| 	} | 	} | ||||||
|   | |||||||
| @@ -1297,6 +1297,7 @@ public class DataAccess { | |||||||
| 			throws SQLException, IOException { | 			throws SQLException, IOException { | ||||||
| 		final QueryOptions options = new QueryOptions(option); | 		final QueryOptions options = new QueryOptions(option); | ||||||
| 		final DBEntry entry = DBInterfaceOption.getAutoEntry(options); | 		final DBEntry entry = DBInterfaceOption.getAutoEntry(options); | ||||||
|  | 		LOGGER.info("Query : '{}'", query); | ||||||
| 		try (final Statement stmt = entry.connection.createStatement()) { | 		try (final Statement stmt = entry.connection.createStatement()) { | ||||||
| 			return stmt.executeUpdate(query); | 			return stmt.executeUpdate(query); | ||||||
| 		} | 		} | ||||||
|   | |||||||
| @@ -27,7 +27,7 @@ import jakarta.persistence.GenerationType; | |||||||
| public class DataFactory { | public class DataFactory { | ||||||
| 	static final Logger LOGGER = LoggerFactory.getLogger(DataFactory.class); | 	static final Logger LOGGER = LoggerFactory.getLogger(DataFactory.class); | ||||||
|  |  | ||||||
| 	public static String convertTypeInSQL(final Class<?> type, final String fieldName) throws Exception { | 	public static String convertTypeInSQL(final Class<?> type, final String fieldName) throws DataAccessException { | ||||||
| 		if (!"sqlite".equals(ConfigBaseVariable.getDBType())) { | 		if (!"sqlite".equals(ConfigBaseVariable.getDBType())) { | ||||||
| 			if (type == UUID.class) { | 			if (type == UUID.class) { | ||||||
| 				return "binary(16)"; | 				return "binary(16)"; | ||||||
| @@ -165,7 +165,7 @@ public class DataFactory { | |||||||
| 		final String comment = AnnotationTools.getComment(elem); | 		final String comment = AnnotationTools.getComment(elem); | ||||||
| 		final String defaultValue = AnnotationTools.getDefault(elem); | 		final String defaultValue = AnnotationTools.getDefault(elem); | ||||||
|  |  | ||||||
| 		if (fieldId == 0) { | 		if (mainTableBuilder.toString().length() == 0) { | ||||||
| 			mainTableBuilder.append("\n\t\t`"); | 			mainTableBuilder.append("\n\t\t`"); | ||||||
| 		} else { | 		} else { | ||||||
| 			mainTableBuilder.append(",\n\t\t`"); | 			mainTableBuilder.append(",\n\t\t`"); | ||||||
| @@ -404,6 +404,7 @@ public class DataFactory { | |||||||
| 			} | 			} | ||||||
| 			final boolean dataInThisObject = tmpOut.toString().length() > 0; | 			final boolean dataInThisObject = tmpOut.toString().length() > 0; | ||||||
| 			if (dataInThisObject) { | 			if (dataInThisObject) { | ||||||
|  | 				LOGGER.info("Previous Object : '{}'", reverseOut.toString()); | ||||||
| 				final boolean dataInPreviousObject = reverseOut.toString().length() > 0; | 				final boolean dataInPreviousObject = reverseOut.toString().length() > 0; | ||||||
| 				if (dataInPreviousObject) { | 				if (dataInPreviousObject) { | ||||||
| 					tmpOut.append(", "); | 					tmpOut.append(", "); | ||||||
|   | |||||||
| @@ -23,6 +23,7 @@ import org.kar.archidata.dataAccess.addOn.model.TableCoversLongUUID; | |||||||
| import org.kar.archidata.dataAccess.addOn.model.TableCoversUUIDLong; | import org.kar.archidata.dataAccess.addOn.model.TableCoversUUIDLong; | ||||||
| import org.kar.archidata.dataAccess.addOn.model.TableCoversUUIDUUID; | import org.kar.archidata.dataAccess.addOn.model.TableCoversUUIDUUID; | ||||||
| import org.kar.archidata.dataAccess.options.OverrideTableName; | import org.kar.archidata.dataAccess.options.OverrideTableName; | ||||||
|  | import org.kar.archidata.exception.DataAccessException; | ||||||
| import org.slf4j.Logger; | import org.slf4j.Logger; | ||||||
| import org.slf4j.LoggerFactory; | import org.slf4j.LoggerFactory; | ||||||
|  |  | ||||||
| @@ -42,7 +43,7 @@ public class AddOnDataJson implements DataAccessAddOn { | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	@Override | 	@Override | ||||||
| 	public String getSQLFieldType(final Field elem) throws Exception { | 	public String getSQLFieldType(final Field elem) throws DataAccessException { | ||||||
| 		final String fieldName = AnnotationTools.getFieldName(elem); | 		final String fieldName = AnnotationTools.getFieldName(elem); | ||||||
| 		return DataFactory.convertTypeInSQL(String.class, fieldName); | 		return DataFactory.convertTypeInSQL(String.class, fieldName); | ||||||
| 	} | 	} | ||||||
|   | |||||||
| @@ -108,16 +108,28 @@ public class AddOnManyToMany implements DataAccessAddOn { | |||||||
| 			@NotNull final String name, | 			@NotNull final String name, | ||||||
| 			@NotNull final CountInOut count, | 			@NotNull final CountInOut count, | ||||||
| 			final QueryOptions options) throws Exception { | 			final QueryOptions options) throws Exception { | ||||||
| 		final String linkTableName = generateLinkTableName(tableName, name); | 		final ManyToMany manyToMany = AnnotationTools.getManyToMany(field); | ||||||
|  | 		String linkTableName = generateLinkTableName(tableName, name); | ||||||
|  | 		if (manyToMany.mappedBy() != null && manyToMany.mappedBy().length() != 0) { | ||||||
|  | 			// TODO:  get the remote table name ..... | ||||||
|  | 			final String remoteTableName = AnnotationTools.getTableName(manyToMany.targetEntity()); | ||||||
|  | 			linkTableName = generateLinkTableName(remoteTableName, manyToMany.mappedBy()); | ||||||
|  | 		} | ||||||
| 		final Class<?> objectClass = (Class<?>) ((ParameterizedType) field.getGenericType()) | 		final Class<?> objectClass = (Class<?>) ((ParameterizedType) field.getGenericType()) | ||||||
| 				.getActualTypeArguments()[0]; | 				.getActualTypeArguments()[0]; | ||||||
| 		final String tmpVariable = "tmp_" + Integer.toString(count.value); | 		final String tmpVariable = "tmp_" + Integer.toString(count.value); | ||||||
| 		querySelect.append(" (SELECT GROUP_CONCAT("); | 		querySelect.append(" (SELECT GROUP_CONCAT("); | ||||||
| 		querySelect.append(tmpVariable); | 		querySelect.append(tmpVariable); | ||||||
| 		querySelect.append(".object2Id "); | 		final boolean mode = manyToMany.mappedBy() == null || manyToMany.mappedBy().length() == 0; | ||||||
|  | 		if (mode) { | ||||||
|  | 			querySelect.append(".object2Id "); | ||||||
|  | 		} else { | ||||||
|  | 			querySelect.append(".object1Id "); | ||||||
|  | 		} | ||||||
| 		if ("sqlite".equals(ConfigBaseVariable.getDBType())) { | 		if ("sqlite".equals(ConfigBaseVariable.getDBType())) { | ||||||
| 			querySelect.append(", "); | 			querySelect.append(", "); | ||||||
| 		} else { | 		} else { | ||||||
|  | 			querySelect.append("ORDER BY uuid ASC "); | ||||||
| 			querySelect.append("SEPARATOR "); | 			querySelect.append("SEPARATOR "); | ||||||
| 		} | 		} | ||||||
| 		querySelect.append("'"); | 		querySelect.append("'"); | ||||||
| @@ -143,11 +155,19 @@ public class AddOnManyToMany implements DataAccessAddOn { | |||||||
| 		querySelect.append(" = "); | 		querySelect.append(" = "); | ||||||
| 		querySelect.append(tmpVariable); | 		querySelect.append(tmpVariable); | ||||||
| 		querySelect.append("."); | 		querySelect.append("."); | ||||||
| 		querySelect.append("object1Id "); | 		if (mode) { | ||||||
|  | 			querySelect.append("object1Id "); | ||||||
|  | 		} else { | ||||||
|  | 			querySelect.append("object2Id "); | ||||||
|  | 		} | ||||||
| 		if (!"sqlite".equals(ConfigBaseVariable.getDBType())) { | 		if (!"sqlite".equals(ConfigBaseVariable.getDBType())) { | ||||||
| 			querySelect.append(" GROUP BY "); | 			querySelect.append(" GROUP BY "); | ||||||
| 			querySelect.append(tmpVariable); | 			querySelect.append(tmpVariable); | ||||||
| 			querySelect.append(".object1Id"); | 			if (mode) { | ||||||
|  | 				querySelect.append(".object1Id"); | ||||||
|  | 			} else { | ||||||
|  | 				querySelect.append(".object2Id"); | ||||||
|  | 			} | ||||||
| 		} | 		} | ||||||
| 		querySelect.append(") AS "); | 		querySelect.append(") AS "); | ||||||
| 		querySelect.append(name); | 		querySelect.append(name); | ||||||
| @@ -509,6 +529,12 @@ public class AddOnManyToMany implements DataAccessAddOn { | |||||||
| 			final boolean createIfNotExist, | 			final boolean createIfNotExist, | ||||||
| 			final boolean createDrop, | 			final boolean createDrop, | ||||||
| 			final int fieldId) throws Exception { | 			final int fieldId) throws Exception { | ||||||
|  |  | ||||||
|  | 		final ManyToMany manyToMany = AnnotationTools.getManyToMany(field); | ||||||
|  | 		if (manyToMany.mappedBy() != null && manyToMany.mappedBy().length() != 0) { | ||||||
|  | 			// not the reference model to create base: | ||||||
|  | 			return; | ||||||
|  | 		} | ||||||
| 		final String linkTableName = generateLinkTableNameField(tableName, field); | 		final String linkTableName = generateLinkTableNameField(tableName, field); | ||||||
| 		final QueryOptions options = new QueryOptions(new OverrideTableName(linkTableName)); | 		final QueryOptions options = new QueryOptions(new OverrideTableName(linkTableName)); | ||||||
| 		final Class<?> objectClass = (Class<?>) ((ParameterizedType) field.getGenericType()) | 		final Class<?> objectClass = (Class<?>) ((ParameterizedType) field.getGenericType()) | ||||||
| @@ -527,7 +553,6 @@ public class AddOnManyToMany implements DataAccessAddOn { | |||||||
| 				postActionList.addAll(sqlCommand); | 				postActionList.addAll(sqlCommand); | ||||||
| 			} | 			} | ||||||
| 		} else if (primaryType == UUID.class) { | 		} else if (primaryType == UUID.class) { | ||||||
|  |  | ||||||
| 			if (objectClass == Long.class) { | 			if (objectClass == Long.class) { | ||||||
| 				final List<String> sqlCommand = DataFactory.createTable(LinkTableUUIDLong.class, options); | 				final List<String> sqlCommand = DataFactory.createTable(LinkTableUUIDLong.class, options); | ||||||
| 				postActionList.addAll(sqlCommand); | 				postActionList.addAll(sqlCommand); | ||||||
|   | |||||||
| @@ -1,5 +1,6 @@ | |||||||
| package org.kar.archidata.dataAccess.addOn.model; | package org.kar.archidata.dataAccess.addOn.model; | ||||||
|  |  | ||||||
|  | import java.util.ArrayList; | ||||||
| import java.util.List; | import java.util.List; | ||||||
| import java.util.UUID; | import java.util.UUID; | ||||||
|  |  | ||||||
| @@ -14,7 +15,7 @@ public class TableCoversLongUUID { | |||||||
|  |  | ||||||
| 	public TableCoversLongUUID(final Long id, final List<UUID> covers) { | 	public TableCoversLongUUID(final Long id, final List<UUID> covers) { | ||||||
| 		this.id = id; | 		this.id = id; | ||||||
| 		this.covers = covers; | 		this.covers = new ArrayList<>(covers); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	@Id | 	@Id | ||||||
|   | |||||||
| @@ -1,5 +1,6 @@ | |||||||
| package org.kar.archidata.dataAccess.addOn.model; | package org.kar.archidata.dataAccess.addOn.model; | ||||||
|  |  | ||||||
|  | import java.util.ArrayList; | ||||||
| import java.util.List; | import java.util.List; | ||||||
| import java.util.UUID; | import java.util.UUID; | ||||||
|  |  | ||||||
| @@ -14,7 +15,7 @@ public class TableCoversUUIDLong { | |||||||
|  |  | ||||||
| 	public TableCoversUUIDLong(final UUID uuid, final List<Long> covers) { | 	public TableCoversUUIDLong(final UUID uuid, final List<Long> covers) { | ||||||
| 		this.uuid = uuid; | 		this.uuid = uuid; | ||||||
| 		this.covers = covers; | 		this.covers = new ArrayList<>(covers); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	@Id | 	@Id | ||||||
|   | |||||||
| @@ -10,9 +10,9 @@ 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 filterValue 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. */ | ||||||
| 	void check(final String baseName, Object data, List<String> filterValue, final QueryOptions options) | 	void check(final String baseName, Object data, List<String> modifiedValue, final QueryOptions options) | ||||||
| 			throws Exception; | 			throws Exception; | ||||||
|  |  | ||||||
| 	default void checkAll(final String baseName, final Object data, final QueryOptions options) throws Exception { | 	default void checkAll(final String baseName, final Object data, final QueryOptions options) throws Exception { | ||||||
|   | |||||||
| @@ -35,10 +35,13 @@ public class CheckJPA<T> implements CheckFunctionInterface { | |||||||
| 	/** 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 CheckInterface<K> { | 	public interface CheckInterface<K> { | ||||||
| 		/** 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 Base of the name input that is displayed in exception generated. | ||||||
| 		 * @param data The object that might be injected. | 		 * @param data The object that might be injected. | ||||||
| 		 * @param filterValue List of fields that might be check. If null, then all column must be checked. | 		 * @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. */ | 		 * @throws Exception Exception is generate if the data are incorrect. */ | ||||||
| 		void check(final String baseName, final K data, final QueryOptions options) throws Exception; | 		void check(final String baseName, final K data, List<String> modifiedValue, final QueryOptions options) | ||||||
|  | 				throws Exception; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	protected Map<String, List<CheckInterface<T>>> checking = null; | 	protected Map<String, List<CheckInterface<T>>> checking = null; | ||||||
| @@ -67,128 +70,182 @@ public class CheckJPA<T> implements CheckFunctionInterface { | |||||||
| 			for (final Field field : this.clazz.getFields()) { | 			for (final Field field : this.clazz.getFields()) { | ||||||
| 				final String fieldName = field.getName(); // AnnotationTools.getFieldName(field); | 				final String fieldName = field.getName(); // AnnotationTools.getFieldName(field); | ||||||
| 				if (AnnotationTools.isPrimaryKey(field)) { | 				if (AnnotationTools.isPrimaryKey(field)) { | ||||||
| 					add(fieldName, (final String baseName, final T data, final QueryOptions options) -> { | 					add(fieldName, | ||||||
| 						throw new InputException(baseName + fieldName, | 							( | ||||||
| 								"This is a '@Id' (primaryKey) ==> can not be change"); | 									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)) { | 				if (AnnotationTools.getConstraintsNotNull(field)) { | ||||||
| 					add(fieldName, (final String baseName, final T data, final QueryOptions options) -> { | 					add(fieldName, | ||||||
| 						if (field.get(data) == null) { | 							( | ||||||
| 							throw new InputException(baseName + fieldName, "Can not be null"); | 									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)) { | 				if (AnnotationTools.isCreatedAtField(field) || AnnotationTools.isUpdateAtField(field)) { | ||||||
| 					add(fieldName, (final String baseName, final T data, final QueryOptions options) -> { | 					add(fieldName, | ||||||
| 						throw new InputException(baseName + fieldName, "It is forbidden to change this field"); | 							( | ||||||
| 					}); | 									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(); | 				final Class<?> type = field.getType(); | ||||||
| 				if (type == Long.class || type == long.class) { | 				if (type == Long.class || type == long.class) { | ||||||
| 					final Long maxValue = AnnotationTools.getConstraintsMax(field); | 					final Long maxValue = AnnotationTools.getConstraintsMax(field); | ||||||
| 					if (maxValue != null) { | 					if (maxValue != null) { | ||||||
| 						add(fieldName, (final String baseName, final T data, final QueryOptions options) -> { | 						add(fieldName, | ||||||
| 							final Object elem = field.get(data); | 								( | ||||||
| 							if (elem == null) { | 										final String baseName, | ||||||
| 								return; | 										final T data, | ||||||
| 							} | 										final List<String> modifiedValue, | ||||||
| 							final Long elemTyped = (Long) elem; | 										final QueryOptions options) -> { | ||||||
| 							if (elemTyped > maxValue) { | 									final Object elem = field.get(data); | ||||||
| 								throw new InputException(baseName + fieldName, "Value too height max: " + maxValue); | 									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); | 					final Long minValue = AnnotationTools.getConstraintsMin(field); | ||||||
| 					if (minValue != null) { | 					if (minValue != null) { | ||||||
| 						add(fieldName, (final String baseName, final T data, final QueryOptions options) -> { | 						add(fieldName, | ||||||
| 							final Object elem = field.get(data); | 								( | ||||||
| 							if (elem == null) { | 										final String baseName, | ||||||
| 								return; | 										final T data, | ||||||
| 							} | 										final List<String> modifiedValue, | ||||||
| 							final Long elemTyped = (Long) elem; | 										final QueryOptions options) -> { | ||||||
| 							if (elemTyped < minValue) { | 									final Object elem = field.get(data); | ||||||
| 								throw new InputException(baseName + fieldName, "Value too Low min: " + minValue); | 									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); | 					final ManyToOne annotationManyToOne = AnnotationTools.getManyToOne(field); | ||||||
| 					if (annotationManyToOne != null && annotationManyToOne.targetEntity() != null) { | 					if (annotationManyToOne != null && annotationManyToOne.targetEntity() != null) { | ||||||
| 						add(fieldName, (final String baseName, final T data, final QueryOptions options) -> { | 						add(fieldName, | ||||||
| 							final Object elem = field.get(data); | 								( | ||||||
| 							if (elem == null) { | 										final String baseName, | ||||||
| 								return; | 										final T data, | ||||||
| 							} | 										final List<String> modifiedValue, | ||||||
| 							final List<ConditionChecker> condCheckers = options.get(ConditionChecker.class); | 										final QueryOptions options) -> { | ||||||
| 							final Condition conditionCheck = condCheckers.isEmpty() ? null | 									final Object elem = field.get(data); | ||||||
| 									: condCheckers.get(0).toCondition(); | 									if (elem == null) { | ||||||
| 							final long count = DataAccess.count(annotationManyToOne.targetEntity(), elem, | 										return; | ||||||
| 									conditionCheck); | 									} | ||||||
| 							if (count == 0) { | 									final List<ConditionChecker> condCheckers = options.get(ConditionChecker.class); | ||||||
| 								throw new InputException(baseName + fieldName, | 									final Condition conditionCheck = condCheckers.isEmpty() ? null | ||||||
| 										"Foreign element does not exist in the DB:" + elem); | 											: condCheckers.get(0).toCondition(); | ||||||
| 							} | 									final long count = DataAccess.count(annotationManyToOne.targetEntity(), elem, | ||||||
| 						}); | 											conditionCheck); | ||||||
|  | 									if (count == 0) { | ||||||
|  | 										throw new InputException(baseName + fieldName, | ||||||
|  | 												"Foreign element does not exist in the DB:" + elem); | ||||||
|  | 									} | ||||||
|  | 								}); | ||||||
| 					} | 					} | ||||||
|  |  | ||||||
| 				} else if (type == Integer.class || type == int.class) { | 				} else if (type == Integer.class || type == int.class) { | ||||||
| 					final Long maxValueRoot = AnnotationTools.getConstraintsMax(field); | 					final Long maxValueRoot = AnnotationTools.getConstraintsMax(field); | ||||||
| 					if (maxValueRoot != null) { | 					if (maxValueRoot != null) { | ||||||
| 						final int maxValue = maxValueRoot.intValue(); | 						final int maxValue = maxValueRoot.intValue(); | ||||||
| 						add(fieldName, (final String baseName, final T data, final QueryOptions options) -> { | 						add(fieldName, | ||||||
| 							final Object elem = field.get(data); | 								( | ||||||
| 							if (elem == null) { | 										final String baseName, | ||||||
| 								return; | 										final T data, | ||||||
| 							} | 										final List<String> modifiedValue, | ||||||
| 							final Integer elemTyped = (Integer) elem; | 										final QueryOptions options) -> { | ||||||
| 							if (elemTyped > maxValue) { | 									final Object elem = field.get(data); | ||||||
| 								throw new InputException(baseName + fieldName, "Value too height max: " + maxValue); | 									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); | 					final Long minValueRoot = AnnotationTools.getConstraintsMin(field); | ||||||
| 					if (minValueRoot != null) { | 					if (minValueRoot != null) { | ||||||
| 						final int minValue = minValueRoot.intValue(); | 						final int minValue = minValueRoot.intValue(); | ||||||
| 						add(fieldName, (final String baseName, final T data, final QueryOptions options) -> { | 						add(fieldName, | ||||||
| 							final Object elem = field.get(data); | 								( | ||||||
| 							if (elem == null) { | 										final String baseName, | ||||||
| 								return; | 										final T data, | ||||||
| 							} | 										final List<String> modifiedValue, | ||||||
| 							final Integer elemTyped = (Integer) elem; | 										final QueryOptions options) -> { | ||||||
| 							if (elemTyped < minValue) { | 									final Object elem = field.get(data); | ||||||
| 								throw new InputException(baseName + fieldName, "Value too Low min: " + minValue); | 									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); | 					final ManyToOne annotationManyToOne = AnnotationTools.getManyToOne(field); | ||||||
| 					if (annotationManyToOne != null && annotationManyToOne.targetEntity() != null) { | 					if (annotationManyToOne != null && annotationManyToOne.targetEntity() != null) { | ||||||
| 						add(fieldName, (final String baseName, final T data, final QueryOptions options) -> { | 						add(fieldName, | ||||||
| 							final Object elem = field.get(data); | 								( | ||||||
| 							if (elem == null) { | 										final String baseName, | ||||||
| 								return; | 										final T data, | ||||||
| 							} | 										final List<String> modifiedValue, | ||||||
| 							final long count = DataAccess.count(annotationManyToOne.targetEntity(), elem); | 										final QueryOptions options) -> { | ||||||
| 							if (count == 0) { | 									final Object elem = field.get(data); | ||||||
| 								throw new InputException(baseName + fieldName, | 									if (elem == null) { | ||||||
| 										"Foreign element does not exist in the DB:" + elem); | 										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) { | 				} else if (type == UUID.class) { | ||||||
| 					final ManyToOne annotationManyToOne = AnnotationTools.getManyToOne(field); | 					final ManyToOne annotationManyToOne = AnnotationTools.getManyToOne(field); | ||||||
| 					if (annotationManyToOne != null && annotationManyToOne.targetEntity() != null) { | 					if (annotationManyToOne != null && annotationManyToOne.targetEntity() != null) { | ||||||
| 						add(fieldName, (final String baseName, final T data, final QueryOptions options) -> { | 						add(fieldName, | ||||||
| 							final Object elem = field.get(data); | 								( | ||||||
| 							if (elem == null) { | 										final String baseName, | ||||||
| 								return; | 										final T data, | ||||||
| 							} | 										final List<String> modifiedValue, | ||||||
| 							final long count = DataAccess.count(annotationManyToOne.targetEntity(), elem); | 										final QueryOptions options) -> { | ||||||
| 							if (count == 0) { | 									final Object elem = field.get(data); | ||||||
| 								throw new InputException(baseName + fieldName, | 									if (elem == null) { | ||||||
| 										"Foreign element does not exist in the DB:" + elem); | 										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 == Boolean.class || type == boolean.class) { | ||||||
|  |  | ||||||
| @@ -196,59 +253,83 @@ public class CheckJPA<T> implements CheckFunctionInterface { | |||||||
| 					final Long maxValueRoot = AnnotationTools.getConstraintsMax(field); | 					final Long maxValueRoot = AnnotationTools.getConstraintsMax(field); | ||||||
| 					if (maxValueRoot != null) { | 					if (maxValueRoot != null) { | ||||||
| 						final float maxValue = maxValueRoot.floatValue(); | 						final float maxValue = maxValueRoot.floatValue(); | ||||||
| 						add(fieldName, (final String baseName, final T data, final QueryOptions options) -> { | 						add(fieldName, | ||||||
| 							final Object elem = field.get(data); | 								( | ||||||
| 							if (elem == null) { | 										final String baseName, | ||||||
| 								return; | 										final T data, | ||||||
| 							} | 										final List<String> modifiedValue, | ||||||
| 							final Float elemTyped = (Float) elem; | 										final QueryOptions options) -> { | ||||||
| 							if (elemTyped > maxValue) { | 									final Object elem = field.get(data); | ||||||
| 								throw new InputException(baseName + fieldName, "Value too height max: " + maxValue); | 									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); | 					final Long minValueRoot = AnnotationTools.getConstraintsMin(field); | ||||||
| 					if (minValueRoot != null) { | 					if (minValueRoot != null) { | ||||||
| 						final float minValue = minValueRoot.floatValue(); | 						final float minValue = minValueRoot.floatValue(); | ||||||
| 						add(fieldName, (final String baseName, final T data, final QueryOptions options) -> { | 						add(fieldName, | ||||||
| 							final Object elem = field.get(data); | 								( | ||||||
| 							if (elem == null) { | 										final String baseName, | ||||||
| 								return; | 										final T data, | ||||||
| 							} | 										final List<String> modifiedValue, | ||||||
| 							final Float elemTyped = (Float) elem; | 										final QueryOptions options) -> { | ||||||
| 							if (elemTyped < minValue) { | 									final Object elem = field.get(data); | ||||||
| 								throw new InputException(baseName + fieldName, "Value too Low min: " + minValue); | 									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) { | 				} else if (type == Double.class || type == double.class) { | ||||||
| 					final Long maxValueRoot = AnnotationTools.getConstraintsMax(field); | 					final Long maxValueRoot = AnnotationTools.getConstraintsMax(field); | ||||||
| 					if (maxValueRoot != null) { | 					if (maxValueRoot != null) { | ||||||
| 						final double maxValue = maxValueRoot.doubleValue(); | 						final double maxValue = maxValueRoot.doubleValue(); | ||||||
| 						add(fieldName, (final String baseName, final T data, final QueryOptions options) -> { | 						add(fieldName, | ||||||
| 							final Object elem = field.get(data); | 								( | ||||||
| 							if (elem == null) { | 										final String baseName, | ||||||
| 								return; | 										final T data, | ||||||
| 							} | 										final List<String> modifiedValue, | ||||||
| 							final Double elemTyped = (Double) elem; | 										final QueryOptions options) -> { | ||||||
| 							if (elemTyped > maxValue) { | 									final Object elem = field.get(data); | ||||||
| 								throw new InputException(baseName + fieldName, "Value too height max: " + maxValue); | 									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); | 					final Long minValueRoot = AnnotationTools.getConstraintsMin(field); | ||||||
| 					if (minValueRoot != null) { | 					if (minValueRoot != null) { | ||||||
| 						final double minValue = minValueRoot.doubleValue(); | 						final double minValue = minValueRoot.doubleValue(); | ||||||
| 						add(fieldName, (final String baseName, final T data, final QueryOptions options) -> { | 						add(fieldName, | ||||||
| 							final Object elem = field.get(data); | 								( | ||||||
| 							if (elem == null) { | 										final String baseName, | ||||||
| 								return; | 										final T data, | ||||||
| 							} | 										final List<String> modifiedValue, | ||||||
| 							final Double elemTyped = (Double) elem; | 										final QueryOptions options) -> { | ||||||
| 							if (elemTyped < minValue) { | 									final Object elem = field.get(data); | ||||||
| 								throw new InputException(baseName + fieldName, "Value too Low min: " + minValue); | 									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 == Date.class || type == Timestamp.class) { | ||||||
|  |  | ||||||
| @@ -259,51 +340,66 @@ public class CheckJPA<T> implements CheckFunctionInterface { | |||||||
| 				} else if (type == String.class) { | 				} else if (type == String.class) { | ||||||
| 					final int maxSizeString = AnnotationTools.getLimitSize(field); | 					final int maxSizeString = AnnotationTools.getLimitSize(field); | ||||||
| 					if (maxSizeString > 0) { | 					if (maxSizeString > 0) { | ||||||
| 						add(fieldName, (final String baseName, final T data, final QueryOptions options) -> { | 						add(fieldName, | ||||||
| 							final Object elem = field.get(data); | 								( | ||||||
| 							if (elem == null) { | 										final String baseName, | ||||||
| 								return; | 										final T data, | ||||||
| 							} | 										final List<String> modifiedValue, | ||||||
| 							final String elemTyped = (String) elem; | 										final QueryOptions options) -> { | ||||||
| 							if (elemTyped.length() > maxSizeString) { | 									final Object elem = field.get(data); | ||||||
| 								throw new InputException(baseName + fieldName, | 									if (elem == null) { | ||||||
| 										"Too long size must be <= " + maxSizeString); | 										return; | ||||||
| 							} | 									} | ||||||
| 						}); | 									final String elemTyped = (String) elem; | ||||||
|  | 									if (elemTyped.length() > maxSizeString) { | ||||||
|  | 										throw new InputException(baseName + fieldName, | ||||||
|  | 												"Too long size must be <= " + maxSizeString); | ||||||
|  | 									} | ||||||
|  | 								}); | ||||||
| 					} | 					} | ||||||
| 					final Size limitSize = AnnotationTools.getConstraintsSize(field); | 					final Size limitSize = AnnotationTools.getConstraintsSize(field); | ||||||
| 					if (limitSize != null) { | 					if (limitSize != null) { | ||||||
| 						add(fieldName, (final String baseName, final T data, final QueryOptions options) -> { | 						add(fieldName, | ||||||
| 							final Object elem = field.get(data); | 								( | ||||||
| 							if (elem == null) { | 										final String baseName, | ||||||
| 								return; | 										final T data, | ||||||
| 							} | 										final List<String> modifiedValue, | ||||||
| 							final String elemTyped = (String) elem; | 										final QueryOptions options) -> { | ||||||
| 							if (elemTyped.length() > limitSize.max()) { | 									final Object elem = field.get(data); | ||||||
| 								throw new InputException(baseName + fieldName, | 									if (elem == null) { | ||||||
| 										"Too long size (constraints) must be <= " + limitSize.max()); | 										return; | ||||||
| 							} | 									} | ||||||
| 							if (elemTyped.length() < limitSize.min()) { | 									final String elemTyped = (String) elem; | ||||||
| 								throw new InputException(baseName + fieldName, | 									if (elemTyped.length() > limitSize.max()) { | ||||||
| 										"Too small size (constraints) must be >= " + limitSize.min()); | 										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); | 					final String patternString = AnnotationTools.getConstraintsPattern(field); | ||||||
| 					if (patternString != null) { | 					if (patternString != null) { | ||||||
| 						final Pattern pattern = Pattern.compile(patternString); | 						final Pattern pattern = Pattern.compile(patternString); | ||||||
| 						add(fieldName, (final String baseName, final T data, final QueryOptions options) -> { | 						add(fieldName, | ||||||
| 							final Object elem = field.get(data); | 								( | ||||||
| 							if (elem == null) { | 										final String baseName, | ||||||
| 								return; | 										final T data, | ||||||
| 							} | 										final List<String> modifiedValue, | ||||||
| 							final String elemTyped = (String) elem; | 										final QueryOptions options) -> { | ||||||
| 							if (!pattern.matcher(elemTyped).find()) { | 									final Object elem = field.get(data); | ||||||
| 								throw new InputException(baseName + fieldName, | 									if (elem == null) { | ||||||
| 										"does not match the required pattern (constraints) must be '" + patternString | 										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 + "'"); | ||||||
|  | 									} | ||||||
|  | 								}); | ||||||
| 					} | 					} | ||||||
| 				} else if (type == JsonValue.class) { | 				} else if (type == JsonValue.class) { | ||||||
| 					final DataJson jsonAnnotation = AnnotationTools.getDataJson(field); | 					final DataJson jsonAnnotation = AnnotationTools.getDataJson(field); | ||||||
| @@ -311,9 +407,14 @@ public class CheckJPA<T> implements CheckFunctionInterface { | |||||||
| 						// Here if we have an error it crash at start and no new instance after creation... | 						// Here if we have an error it crash at start and no new instance after creation... | ||||||
| 						final CheckFunctionInterface instance = jsonAnnotation.checker().getDeclaredConstructor() | 						final CheckFunctionInterface instance = jsonAnnotation.checker().getDeclaredConstructor() | ||||||
| 								.newInstance(); | 								.newInstance(); | ||||||
| 						add(fieldName, (final String baseName, final T data, final QueryOptions options) -> { | 						add(fieldName, | ||||||
| 							instance.checkAll(baseName + fieldName + ".", field.get(data), options); | 								( | ||||||
| 						}); | 										final String baseName, | ||||||
|  | 										final T data, | ||||||
|  | 										final List<String> modifiedValue, | ||||||
|  | 										final QueryOptions options) -> { | ||||||
|  | 									instance.checkAll(baseName + fieldName + ".", field.get(data), options); | ||||||
|  | 								}); | ||||||
| 					} | 					} | ||||||
| 				} else if (type.isEnum()) { | 				} else if (type.isEnum()) { | ||||||
| 					// nothing to do. | 					// nothing to do. | ||||||
| @@ -321,21 +422,26 @@ public class CheckJPA<T> implements CheckFunctionInterface { | |||||||
| 				// keep this is last ==> take more time... | 				// keep this is last ==> take more time... | ||||||
| 				if (AnnotationTools.isUnique(field)) { | 				if (AnnotationTools.isUnique(field)) { | ||||||
| 					// Create the request ... | 					// Create the request ... | ||||||
| 					add(fieldName, (final String baseName, final T data, final QueryOptions options) -> { | 					add(fieldName, | ||||||
| 						final List<ConditionChecker> condCheckers = options.get(ConditionChecker.class); | 							( | ||||||
| 						Object other = null; | 									final String baseName, | ||||||
| 						if (condCheckers.isEmpty()) { | 									final T data, | ||||||
| 							other = DataAccess.getWhere(this.clazz, | 									final List<String> modifiedValue, | ||||||
| 									new Condition(new QueryCondition(fieldName, "==", field.get(data)))); | 									final QueryOptions options) -> { | ||||||
| 						} else { | 								final List<ConditionChecker> condCheckers = options.get(ConditionChecker.class); | ||||||
| 							other = DataAccess.getWhere(this.clazz, | 								Object other = null; | ||||||
| 									new Condition(new QueryCondition(fieldName, "==", field.get(data))), | 								if (condCheckers.isEmpty()) { | ||||||
| 									condCheckers.get(0).toCondition()); | 									other = DataAccess.getWhere(this.clazz, | ||||||
| 						} | 											new Condition(new QueryCondition(fieldName, "==", field.get(data)))); | ||||||
| 						if (other != null) { | 								} else { | ||||||
| 							throw new InputException(baseName + fieldName, "Name already exist in the DB"); | 									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"); | ||||||
|  | 								} | ||||||
|  | 							}); | ||||||
| 				} | 				} | ||||||
|  |  | ||||||
| 			} | 			} | ||||||
| @@ -349,7 +455,7 @@ public class CheckJPA<T> implements CheckFunctionInterface { | |||||||
| 	public void check( | 	public void check( | ||||||
| 			final String baseName, | 			final String baseName, | ||||||
| 			final Object data, | 			final Object data, | ||||||
| 			final List<String> filterValue, | 			final List<String> modifiedValue, | ||||||
| 			final QueryOptions options) throws Exception { | 			final QueryOptions options) throws Exception { | ||||||
| 		if (this.checking == null) { | 		if (this.checking == null) { | ||||||
| 			initialize(); | 			initialize(); | ||||||
| @@ -359,19 +465,20 @@ public class CheckJPA<T> implements CheckFunctionInterface { | |||||||
| 		} | 		} | ||||||
| 		@SuppressWarnings("unchecked") | 		@SuppressWarnings("unchecked") | ||||||
| 		final T dataCasted = (T) data; | 		final T dataCasted = (T) data; | ||||||
| 		for (final String filter : filterValue) { | 		for (final String filter : modifiedValue) { | ||||||
| 			final List<CheckInterface<T>> actions = this.checking.get(filter); | 			final List<CheckInterface<T>> actions = this.checking.get(filter); | ||||||
| 			if (actions == null) { | 			if (actions == null) { | ||||||
| 				continue; | 				continue; | ||||||
| 			} | 			} | ||||||
| 			for (final CheckInterface<T> action : actions) { | 			for (final CheckInterface<T> action : actions) { | ||||||
| 				action.check(baseName, dataCasted, options); | 				action.check(baseName, dataCasted, modifiedValue, options); | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 		checkTyped(dataCasted, filterValue, options); | 		checkTyped(dataCasted, modifiedValue, options); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	public void checkTyped(final T data, final List<String> filterValue, final QueryOptions options) throws Exception { | 	public void checkTyped(final T data, final List<String> modifiedValue, final QueryOptions options) | ||||||
|  | 			throws Exception { | ||||||
| 		// nothing to do ... | 		// nothing to do ... | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|   | |||||||
| @@ -63,6 +63,7 @@ public class DBEntry implements Closeable { | |||||||
| 			this.connection = DriverManager.getConnection(this.config.getUrl(), this.config.getLogin(), | 			this.connection = DriverManager.getConnection(this.config.getUrl(), this.config.getLogin(), | ||||||
| 					this.config.getPassword()); | 					this.config.getPassword()); | ||||||
| 		} catch (final SQLException ex) { | 		} catch (final SQLException ex) { | ||||||
|  | 			LOGGER.error("Connection db fail: " + ex.getMessage() + " On URL: " + this.config.getUrl(true)); | ||||||
| 			throw new IOException("Connection db fail: " + ex.getMessage() + " On URL: " + this.config.getUrl(true)); | 			throw new IOException("Connection db fail: " + ex.getMessage() + " On URL: " + this.config.getUrl(true)); | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|   | |||||||
| @@ -71,4 +71,25 @@ public class AnalyzeApi { | |||||||
| 		} | 		} | ||||||
| 		return out; | 		return out; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	public void displayAllApi() { | ||||||
|  | 		LOGGER.info("List all API:"); | ||||||
|  | 		for (final ApiGroupModel model : getAllApi()) { | ||||||
|  | 			LOGGER.info("    - {}: {}", model.name, model.getClass().getCanonicalName()); | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public void displayAllModel() { | ||||||
|  | 		LOGGER.info("List all Model:"); | ||||||
|  | 		for (final ClassModel model : getAllModel()) { | ||||||
|  | 			final StringBuilder out = new StringBuilder(); | ||||||
|  | 			for (final ClassModel classModel : model.getAlls()) { | ||||||
|  | 				out.append(classModel.getOriginClasses().getCanonicalName()); | ||||||
|  | 				out.append(","); | ||||||
|  | 			} | ||||||
|  | 			LOGGER.info("    - {}", out.toString()); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
| } | } | ||||||
|   | |||||||
| @@ -30,7 +30,7 @@ import org.kar.archidata.externalRestApi.typescript.TsClassElementGroup; | |||||||
| public class TsGenerateApi { | public class TsGenerateApi { | ||||||
| 	/** | 	/** | ||||||
| 	 * Generate a full API tree for Typescript in a specific folder. | 	 * Generate a full API tree for Typescript in a specific folder. | ||||||
| 	 * This generate a folder containing a full API with "model" filder and "api" folder. | 	 * This generate a folder containing a full API with "model" folder and "api" folder. | ||||||
| 	 * The generation depend of Zod and can be strict compile. | 	 * The generation depend of Zod and can be strict compile. | ||||||
| 	 * @param api Data model to generate the api | 	 * @param api Data model to generate the api | ||||||
| 	 * @param pathPackage Path to store the api. | 	 * @param pathPackage Path to store the api. | ||||||
| @@ -118,6 +118,8 @@ public class TsGenerateApi { | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	private static List<TsClassElement> generateApiModel(final AnalyzeApi api) throws Exception { | 	private static List<TsClassElement> generateApiModel(final AnalyzeApi api) throws Exception { | ||||||
|  | 		// needed for Rest interface | ||||||
|  | 		api.addModel(RestErrorResponse.class); | ||||||
| 		// First step is to add all specific basic elements the wrap correctly the model | 		// First step is to add all specific basic elements the wrap correctly the model | ||||||
| 		final List<TsClassElement> tsModels = new ArrayList<>(); | 		final List<TsClassElement> tsModels = new ArrayList<>(); | ||||||
| 		List<ClassModel> models = api.getCompatibleModels(List.of(Void.class, void.class)); | 		List<ClassModel> models = api.getCompatibleModels(List.of(Void.class, void.class)); | ||||||
| @@ -205,8 +207,6 @@ public class TsGenerateApi { | |||||||
| 			tsModels.add(new TsClassElement(models, "ZodLocalTime", "LocalTime", "isLocalTime", "zod.string().time()", | 			tsModels.add(new TsClassElement(models, "ZodLocalTime", "LocalTime", "isLocalTime", "zod.string().time()", | ||||||
| 					DefinedPosition.BASIC)); | 					DefinedPosition.BASIC)); | ||||||
| 		} | 		} | ||||||
| 		// needed for Rest interface |  | ||||||
| 		api.addModel(RestErrorResponse.class); |  | ||||||
| 		for (final ClassModel model : api.getAllModel()) { | 		for (final ClassModel model : api.getAllModel()) { | ||||||
| 			boolean alreadyExist = false; | 			boolean alreadyExist = false; | ||||||
| 			for (final TsClassElement elem : tsModels) { | 			for (final TsClassElement elem : tsModels) { | ||||||
|   | |||||||
| @@ -10,6 +10,7 @@ import java.util.Set; | |||||||
| import org.kar.archidata.externalRestApi.dot.DotClassElement.DefinedPosition; | import org.kar.archidata.externalRestApi.dot.DotClassElement.DefinedPosition; | ||||||
| import org.kar.archidata.externalRestApi.model.ApiGroupModel; | import org.kar.archidata.externalRestApi.model.ApiGroupModel; | ||||||
| import org.kar.archidata.externalRestApi.model.ApiModel; | import org.kar.archidata.externalRestApi.model.ApiModel; | ||||||
|  | import org.kar.archidata.externalRestApi.model.ApiModel.OptionalClassModel; | ||||||
| import org.kar.archidata.externalRestApi.model.ClassEnumModel; | import org.kar.archidata.externalRestApi.model.ClassEnumModel; | ||||||
| import org.kar.archidata.externalRestApi.model.ClassListModel; | import org.kar.archidata.externalRestApi.model.ClassListModel; | ||||||
| import org.kar.archidata.externalRestApi.model.ClassMapModel; | import org.kar.archidata.externalRestApi.model.ClassMapModel; | ||||||
| @@ -216,7 +217,7 @@ public class DotApiGeneration { | |||||||
| 				hasParam = true; | 				hasParam = true; | ||||||
| 				boolean hasParam2 = false; | 				boolean hasParam2 = false; | ||||||
| 				data.append("data: {"); | 				data.append("data: {"); | ||||||
| 				for (final Entry<String, List<ClassModel>> pathEntry : interfaceElement.multiPartParameters | 				for (final Entry<String, OptionalClassModel> pathEntry : interfaceElement.multiPartParameters | ||||||
| 						.entrySet()) { | 						.entrySet()) { | ||||||
| 					if (hasParam2) { | 					if (hasParam2) { | ||||||
| 						data.append(", "); | 						data.append(", "); | ||||||
| @@ -224,7 +225,7 @@ public class DotApiGeneration { | |||||||
| 					hasParam2 = true; | 					hasParam2 = true; | ||||||
| 					data.append(pathEntry.getKey()); | 					data.append(pathEntry.getKey()); | ||||||
| 					data.append(": "); | 					data.append(": "); | ||||||
| 					data.append(generateClassModelsTypescript(pathEntry.getValue(), dotGroup)); | 					data.append(generateClassModelsTypescript(pathEntry.getValue().model(), dotGroup)); | ||||||
| 				} | 				} | ||||||
| 				data.append("}"); | 				data.append("}"); | ||||||
| 			} | 			} | ||||||
|   | |||||||
| @@ -15,6 +15,10 @@ import org.slf4j.LoggerFactory; | |||||||
| public class ApiModel { | public class ApiModel { | ||||||
| 	static final Logger LOGGER = LoggerFactory.getLogger(ApiModel.class); | 	static final Logger LOGGER = LoggerFactory.getLogger(ApiModel.class); | ||||||
|  |  | ||||||
|  | 	public record OptionalClassModel( | ||||||
|  | 			List<ClassModel> model, | ||||||
|  | 			boolean optional) {} | ||||||
|  |  | ||||||
| 	Class<?> originClass; | 	Class<?> originClass; | ||||||
| 	Method orignMethod; | 	Method orignMethod; | ||||||
|  |  | ||||||
| @@ -36,7 +40,7 @@ public class ApiModel { | |||||||
| 	// list of all query (?key...) | 	// list of all query (?key...) | ||||||
| 	public final Map<String, List<ClassModel>> queries = new HashMap<>(); | 	public final Map<String, List<ClassModel>> queries = new HashMap<>(); | ||||||
| 	// when request multi-part, need to separate it. | 	// when request multi-part, need to separate it. | ||||||
| 	public final Map<String, List<ClassModel>> multiPartParameters = new HashMap<>(); | 	public final Map<String, OptionalClassModel> multiPartParameters = new HashMap<>(); | ||||||
| 	// model of data available | 	// model of data available | ||||||
| 	public final List<ClassModel> unnamedElement = new ArrayList<>(); | 	public final List<ClassModel> unnamedElement = new ArrayList<>(); | ||||||
|  |  | ||||||
| @@ -153,6 +157,7 @@ public class ApiModel { | |||||||
| 			final String pathParam = ApiTool.apiAnnotationGetPathParam(parameter); | 			final String pathParam = ApiTool.apiAnnotationGetPathParam(parameter); | ||||||
| 			final String queryParam = ApiTool.apiAnnotationGetQueryParam(parameter); | 			final String queryParam = ApiTool.apiAnnotationGetQueryParam(parameter); | ||||||
| 			final String formDataParam = ApiTool.apiAnnotationGetFormDataParam(parameter); | 			final String formDataParam = ApiTool.apiAnnotationGetFormDataParam(parameter); | ||||||
|  | 			final boolean formDataParamOptional = ApiTool.apiAnnotationGetFormDataOptional(parameter); | ||||||
| 			if (queryParam != null) { | 			if (queryParam != null) { | ||||||
| 				if (!this.queries.containsKey(queryParam)) { | 				if (!this.queries.containsKey(queryParam)) { | ||||||
| 					this.queries.put(queryParam, parameterModel); | 					this.queries.put(queryParam, parameterModel); | ||||||
| @@ -163,7 +168,8 @@ public class ApiModel { | |||||||
| 				} | 				} | ||||||
| 			} else if (formDataParam != null) { | 			} else if (formDataParam != null) { | ||||||
| 				if (!this.multiPartParameters.containsKey(formDataParam)) { | 				if (!this.multiPartParameters.containsKey(formDataParam)) { | ||||||
| 					this.multiPartParameters.put(formDataParam, parameterModel); | 					this.multiPartParameters.put(formDataParam, | ||||||
|  | 							new OptionalClassModel(parameterModel, formDataParamOptional)); | ||||||
| 				} | 				} | ||||||
| 			} else { | 			} else { | ||||||
| 				this.unnamedElement.addAll(parameterModel); | 				this.unnamedElement.addAll(parameterModel); | ||||||
|   | |||||||
| @@ -7,7 +7,10 @@ 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.RESTORE; | ||||||
| import org.kar.archidata.annotation.TypeScriptProgress; | import org.kar.archidata.annotation.TypeScriptProgress; | ||||||
|  |  | ||||||
| import io.swagger.v3.oas.annotations.Operation; | import io.swagger.v3.oas.annotations.Operation; | ||||||
| @@ -106,6 +109,12 @@ public class ApiTool { | |||||||
| 		if (element.getDeclaredAnnotationsByType(DELETE.class).length == 1) { | 		if (element.getDeclaredAnnotationsByType(DELETE.class).length == 1) { | ||||||
| 			return "DELETE"; | 			return "DELETE"; | ||||||
| 		} | 		} | ||||||
|  | 		if (element.getDeclaredAnnotationsByType(RESTORE.class).length == 1) { | ||||||
|  | 			return "RESTORE"; | ||||||
|  | 		} | ||||||
|  | 		if (element.getDeclaredAnnotationsByType(ARCHIVE.class).length == 1) { | ||||||
|  | 			return "ARCHIVE"; | ||||||
|  | 		} | ||||||
| 		return null; | 		return null; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| @@ -125,6 +134,12 @@ public class ApiTool { | |||||||
| 		if (element.getDeclaredAnnotationsByType(DELETE.class).length == 1) { | 		if (element.getDeclaredAnnotationsByType(DELETE.class).length == 1) { | ||||||
| 			return RestTypeRequest.DELETE; | 			return RestTypeRequest.DELETE; | ||||||
| 		} | 		} | ||||||
|  | 		if (element.getDeclaredAnnotationsByType(RESTORE.class).length == 1) { | ||||||
|  | 			return RestTypeRequest.RESTORE; | ||||||
|  | 		} | ||||||
|  | 		if (element.getDeclaredAnnotationsByType(ARCHIVE.class).length == 1) { | ||||||
|  | 			return RestTypeRequest.ARCHIVE; | ||||||
|  | 		} | ||||||
| 		return null; | 		return null; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| @@ -144,6 +159,14 @@ public class ApiTool { | |||||||
| 		return ((QueryParam) annotation[0]).value(); | 		return ((QueryParam) annotation[0]).value(); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	public static boolean apiAnnotationGetFormDataOptional(final Parameter element) throws Exception { | ||||||
|  | 		final Annotation[] annotation = element.getDeclaredAnnotationsByType(FormDataOptional.class); | ||||||
|  | 		if (annotation.length == 0) { | ||||||
|  | 			return false; | ||||||
|  | 		} | ||||||
|  | 		return true; | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	public static String apiAnnotationGetFormDataParam(final Parameter element) throws Exception { | 	public static String apiAnnotationGetFormDataParam(final Parameter element) throws Exception { | ||||||
| 		final Annotation[] annotation = element.getDeclaredAnnotationsByType(FormDataParam.class); | 		final Annotation[] annotation = element.getDeclaredAnnotationsByType(FormDataParam.class); | ||||||
| 		if (annotation.length == 0) { | 		if (annotation.length == 0) { | ||||||
|   | |||||||
| @@ -1,5 +1,5 @@ | |||||||
| package org.kar.archidata.externalRestApi.model; | package org.kar.archidata.externalRestApi.model; | ||||||
|  |  | ||||||
| public enum RestTypeRequest { | public enum RestTypeRequest { | ||||||
| 	GET, POST, PUT, PATCH, DELETE | 	GET, POST, PUT, PATCH, DELETE, RESTORE, ARCHIVE | ||||||
| } | } | ||||||
|   | |||||||
| @@ -3,6 +3,9 @@ package org.kar.archidata.externalRestApi.typescript; | |||||||
| import java.io.File; | import java.io.File; | ||||||
| import java.io.FileWriter; | import java.io.FileWriter; | ||||||
| import java.io.IOException; | import java.io.IOException; | ||||||
|  | import java.nio.file.Files; | ||||||
|  | import java.nio.file.Path; | ||||||
|  | import java.nio.file.Paths; | ||||||
| import java.util.ArrayList; | import java.util.ArrayList; | ||||||
| import java.util.Collections; | import java.util.Collections; | ||||||
| import java.util.HashSet; | import java.util.HashSet; | ||||||
| @@ -14,6 +17,7 @@ import java.util.TreeSet; | |||||||
| import org.kar.archidata.dataAccess.DataExport; | import org.kar.archidata.dataAccess.DataExport; | ||||||
| import org.kar.archidata.externalRestApi.model.ApiGroupModel; | import org.kar.archidata.externalRestApi.model.ApiGroupModel; | ||||||
| import org.kar.archidata.externalRestApi.model.ApiModel; | import org.kar.archidata.externalRestApi.model.ApiModel; | ||||||
|  | import org.kar.archidata.externalRestApi.model.ApiModel.OptionalClassModel; | ||||||
| import org.kar.archidata.externalRestApi.model.ClassEnumModel; | import org.kar.archidata.externalRestApi.model.ClassEnumModel; | ||||||
| import org.kar.archidata.externalRestApi.model.ClassListModel; | import org.kar.archidata.externalRestApi.model.ClassListModel; | ||||||
| import org.kar.archidata.externalRestApi.model.ClassMapModel; | import org.kar.archidata.externalRestApi.model.ClassMapModel; | ||||||
| @@ -226,12 +230,16 @@ public class TsApiGeneration { | |||||||
| 				data.append(","); | 				data.append(","); | ||||||
| 			} else if (interfaceElement.multiPartParameters.size() != 0) { | 			} else if (interfaceElement.multiPartParameters.size() != 0) { | ||||||
| 				data.append("\n\t\tdata: {"); | 				data.append("\n\t\tdata: {"); | ||||||
| 				for (final Entry<String, List<ClassModel>> pathEntry : interfaceElement.multiPartParameters | 				for (final Entry<String, OptionalClassModel> pathEntry : interfaceElement.multiPartParameters | ||||||
| 						.entrySet()) { | 						.entrySet()) { | ||||||
| 					data.append("\n\t\t\t"); | 					data.append("\n\t\t\t"); | ||||||
| 					data.append(pathEntry.getKey()); | 					data.append(pathEntry.getKey()); | ||||||
|  | 					if (pathEntry.getValue().optional()) { | ||||||
|  | 						data.append("?"); | ||||||
|  | 					} | ||||||
| 					data.append(": "); | 					data.append(": "); | ||||||
| 					data.append(generateClassModelsTypescript(pathEntry.getValue(), tsGroup, imports, writeImports)); | 					data.append(generateClassModelsTypescript(pathEntry.getValue().model(), tsGroup, imports, | ||||||
|  | 							writeImports)); | ||||||
| 					data.append(","); | 					data.append(","); | ||||||
| 				} | 				} | ||||||
| 				data.append("\n\t\t},"); | 				data.append("\n\t\t},"); | ||||||
| @@ -415,7 +423,10 @@ public class TsApiGeneration { | |||||||
| 		} | 		} | ||||||
| 		for (final ClassModel model : writeImports) { | 		for (final ClassModel model : writeImports) { | ||||||
| 			final TsClassElement tsModel = tsGroup.find(model); | 			final TsClassElement tsModel = tsGroup.find(model); | ||||||
| 			if (tsModel.nativeType == DefinedPosition.NATIVE) { | 			if (tsModel.nativeType != DefinedPosition.NORMAL) { | ||||||
|  | 				continue; | ||||||
|  | 			} | ||||||
|  | 			if (tsModel.models.get(0).isNoWriteSpecificMode()) { | ||||||
| 				continue; | 				continue; | ||||||
| 			} | 			} | ||||||
| 			finalImportSet.add(tsModel.tsTypeName + "Write"); | 			finalImportSet.add(tsModel.tsTypeName + "Write"); | ||||||
| @@ -433,6 +444,10 @@ public class TsApiGeneration { | |||||||
|  |  | ||||||
| 		out.append(data.toString()); | 		out.append(data.toString()); | ||||||
|  |  | ||||||
|  | 		final Path path = Paths.get(pathPackage + File.separator + "api"); | ||||||
|  | 		if (Files.notExists(path)) { | ||||||
|  | 			Files.createDirectories(path); | ||||||
|  | 		} | ||||||
| 		final String fileName = TsClassElement.determineFileName(element.name); | 		final String fileName = TsClassElement.determineFileName(element.name); | ||||||
| 		final FileWriter myWriter = new FileWriter( | 		final FileWriter myWriter = new FileWriter( | ||||||
| 				pathPackage + File.separator + "api" + File.separator + fileName + ".ts"); | 				pathPackage + File.separator + "api" + File.separator + fileName + ".ts"); | ||||||
|   | |||||||
| @@ -16,9 +16,12 @@ public class CORSFilter implements ContainerResponseFilter { | |||||||
| 		// System.err.println("filter cors ..." + request.toString()); | 		// System.err.println("filter cors ..." + request.toString()); | ||||||
|  |  | ||||||
| 		response.getHeaders().add("Access-Control-Allow-Origin", "*"); | 		response.getHeaders().add("Access-Control-Allow-Origin", "*"); | ||||||
|  | 		response.getHeaders().add("Access-Control-Allow-Range", "bytes"); | ||||||
|  | 		response.getHeaders().add("access-control-expose-headers", "range"); | ||||||
| 		response.getHeaders().add("Access-Control-Allow-Headers", | 		response.getHeaders().add("Access-Control-Allow-Headers", | ||||||
| 				"Origin, content-type, Content-type, Accept, Authorization, mime-type, filename"); | 				"Origin, content-type, Content-type, Accept, Authorization, mime-type, filename, Range"); | ||||||
| 		response.getHeaders().add("Access-Control-Allow-Credentials", "true"); | 		response.getHeaders().add("Access-Control-Allow-Credentials", "true"); | ||||||
| 		response.getHeaders().add("Access-Control-Allow-Methods", "GET, POST, PUT, PATCH, DELETE, OPTIONS, HEAD"); | 		response.getHeaders().add("Access-Control-Allow-Methods", | ||||||
|  | 				"GET, POST, PUT, PATCH, DELETE, ARCHIVE, RESTORE, OPTIONS, HEAD"); | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|   | |||||||
| @@ -11,9 +11,11 @@ import java.nio.file.StandardCopyOption; | |||||||
| import java.security.MessageDigest; | import java.security.MessageDigest; | ||||||
| import java.security.NoSuchAlgorithmException; | import java.security.NoSuchAlgorithmException; | ||||||
| import java.sql.SQLException; | import java.sql.SQLException; | ||||||
|  | import java.util.Arrays; | ||||||
| import java.util.List; | import java.util.List; | ||||||
| import java.util.UUID; | import java.util.UUID; | ||||||
|  |  | ||||||
|  | import org.apache.tika.Tika; | ||||||
| import org.glassfish.jersey.media.multipart.FormDataContentDisposition; | import org.glassfish.jersey.media.multipart.FormDataContentDisposition; | ||||||
| import org.kar.archidata.api.DataResource; | import org.kar.archidata.api.DataResource; | ||||||
| import org.kar.archidata.dataAccess.DataAccess; | import org.kar.archidata.dataAccess.DataAccess; | ||||||
| @@ -28,6 +30,9 @@ import org.kar.archidata.model.Data; | |||||||
| import org.slf4j.Logger; | import org.slf4j.Logger; | ||||||
| import org.slf4j.LoggerFactory; | import org.slf4j.LoggerFactory; | ||||||
|  |  | ||||||
|  | import jakarta.ws.rs.client.Client; | ||||||
|  | import jakarta.ws.rs.client.ClientBuilder; | ||||||
|  | import jakarta.ws.rs.client.WebTarget; | ||||||
| import jakarta.ws.rs.core.Response; | import jakarta.ws.rs.core.Response; | ||||||
|  |  | ||||||
| public class DataTools { | public class DataTools { | ||||||
| @@ -37,6 +42,9 @@ public class DataTools { | |||||||
| 	public final static int CHUNK_SIZE_IN = 50 * 1024 * 1024; // 1MB chunks | 	public final static int CHUNK_SIZE_IN = 50 * 1024 * 1024; // 1MB chunks | ||||||
| 	/** Upload some data */ | 	/** Upload some data */ | ||||||
| 	private static long tmpFolderId = 1; | 	private static long tmpFolderId = 1; | ||||||
|  | 	public final static String[] SUPPORTED_IMAGE_MIME_TYPE = { "image/jpeg", "image/png", "image/webp" }; | ||||||
|  | 	public final static String[] SUPPORTED_AUDIO_MIME_TYPE = { "audio/x-matroska" }; | ||||||
|  | 	public final static String[] SUPPORTED_VIDEO_MIME_TYPE = { "video/x-matroska", "video/webm" }; | ||||||
|  |  | ||||||
| 	public static void createFolder(final String path) throws IOException { | 	public static void createFolder(final String path) throws IOException { | ||||||
| 		if (!Files.exists(java.nio.file.Path.of(path))) { | 		if (!Files.exists(java.nio.file.Path.of(path))) { | ||||||
| @@ -91,20 +99,12 @@ public class DataTools { | |||||||
| 		return null; | 		return null; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	public static Data createNewData(final long tmpUID, final String originalFileName, final String sha512) | 	public static Data createNewData( | ||||||
| 			throws IOException, SQLException { | 			final long tmpUID, | ||||||
| 		// determine mime type: | 			final String originalFileName, | ||||||
| 		String mimeType = ""; | 			final String sha512, | ||||||
| 		final String extension = originalFileName.substring(originalFileName.lastIndexOf('.') + 1); | 			final String mimeType) throws IOException, SQLException { | ||||||
| 		mimeType = switch (extension.toLowerCase()) { |  | ||||||
| 			case "jpg", "jpeg" -> "image/jpeg"; |  | ||||||
| 			case "png" -> "image/png"; |  | ||||||
| 			case "webp" -> "image/webp"; |  | ||||||
| 			case "mka" -> "audio/x-matroska"; |  | ||||||
| 			case "mkv" -> "video/x-matroska"; |  | ||||||
| 			case "webm" -> "video/webm"; |  | ||||||
| 			default -> throw new IOException("Can not find the mime type of data input: '" + extension + "'"); |  | ||||||
| 		}; |  | ||||||
| 		final String tmpPath = getTmpFileInData(tmpUID); | 		final String tmpPath = getTmpFileInData(tmpUID); | ||||||
| 		final long fileSize = Files.size(Paths.get(tmpPath)); | 		final long fileSize = Files.size(Paths.get(tmpPath)); | ||||||
| 		Data out = new Data(); | 		Data out = new Data(); | ||||||
| @@ -130,6 +130,23 @@ public class DataTools { | |||||||
| 		return out; | 		return out; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	public static Data createNewData(final long tmpUID, final String originalFileName, final String sha512) | ||||||
|  | 			throws IOException, SQLException { | ||||||
|  | 		// determine mime type: | ||||||
|  | 		String mimeType = ""; | ||||||
|  | 		final String extension = originalFileName.substring(originalFileName.lastIndexOf('.') + 1); | ||||||
|  | 		mimeType = switch (extension.toLowerCase()) { | ||||||
|  | 			case "jpg", "jpeg" -> "image/jpeg"; | ||||||
|  | 			case "png" -> "image/png"; | ||||||
|  | 			case "webp" -> "image/webp"; | ||||||
|  | 			case "mka" -> "audio/x-matroska"; | ||||||
|  | 			case "mkv" -> "video/x-matroska"; | ||||||
|  | 			case "webm" -> "video/webm"; | ||||||
|  | 			default -> throw new IOException("Can not find the mime type of data input: '" + extension + "'"); | ||||||
|  | 		}; | ||||||
|  | 		return createNewData(tmpUID, originalFileName, sha512, mimeType); | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	public static void undelete(final UUID id) { | 	public static void undelete(final UUID id) { | ||||||
| 		try { | 		try { | ||||||
| 			DataAccess.unsetDelete(Data.class, id); | 			DataAccess.unsetDelete(Data.class, id); | ||||||
| @@ -143,6 +160,10 @@ public class DataTools { | |||||||
| 		return saveFile(uploadedInputStream, getTmpFileInData(idData)); | 		return saveFile(uploadedInputStream, getTmpFileInData(idData)); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	public static String saveTemporaryFile(final byte[] uploadedInputStream, final long idData) { | ||||||
|  | 		return saveFile(uploadedInputStream, getTmpFileInData(idData)); | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	public static void removeTemporaryFile(final long idData) { | 	public static void removeTemporaryFile(final long idData) { | ||||||
| 		final String filepath = getTmpFileInData(idData); | 		final String filepath = getTmpFileInData(idData); | ||||||
| 		if (Files.exists(Paths.get(filepath))) { | 		if (Files.exists(Paths.get(filepath))) { | ||||||
| @@ -188,6 +209,31 @@ public class DataTools { | |||||||
| 		return out; | 		return out; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	public static String saveFile(final byte[] bytes, final String serverLocation) { | ||||||
|  | 		String out = ""; | ||||||
|  | 		try { | ||||||
|  | 			final OutputStream outpuStream = new FileOutputStream(new File(serverLocation)); | ||||||
|  | 			final MessageDigest md = MessageDigest.getInstance("SHA-512"); | ||||||
|  | 			md.update(bytes, 0, bytes.length); | ||||||
|  | 			outpuStream.write(bytes, 0, bytes.length); | ||||||
|  |  | ||||||
|  | 			LOGGER.info("Flush input stream ... {}", serverLocation); | ||||||
|  | 			outpuStream.flush(); | ||||||
|  | 			outpuStream.close(); | ||||||
|  | 			// create the end of sha512 | ||||||
|  | 			final byte[] sha512Digest = md.digest(); | ||||||
|  | 			// convert in hexadecimal | ||||||
|  | 			out = bytesToHex(sha512Digest); | ||||||
|  | 		} catch (final IOException ex) { | ||||||
|  | 			LOGGER.error("Can not write in temporary file ... "); | ||||||
|  | 			ex.printStackTrace(); | ||||||
|  | 		} catch (final NoSuchAlgorithmException ex) { | ||||||
|  | 			LOGGER.error("Can not find sha512 algorithms"); | ||||||
|  | 			ex.printStackTrace(); | ||||||
|  | 		} | ||||||
|  | 		return out; | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	// curl http://localhost:9993/api/users/3 | 	// curl http://localhost:9993/api/users/3 | ||||||
| 	// @Secured | 	// @Secured | ||||||
| 	/* @GET | 	/* @GET | ||||||
| @@ -213,9 +259,96 @@ public class DataTools { | |||||||
| 		if (data.contentEquals("null")) { | 		if (data.contentEquals("null")) { | ||||||
| 			return null; | 			return null; | ||||||
| 		} | 		} | ||||||
|  | 		if (data.contentEquals("undefined")) { | ||||||
|  | 			return null; | ||||||
|  | 		} | ||||||
| 		return data; | 		return data; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	public static String getMimeType(final byte[] data) { | ||||||
|  | 		final Tika tika = new Tika(); | ||||||
|  | 		final String mimeType = tika.detect(data); | ||||||
|  | 		return mimeType; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static <CLASS_TYPE, ID_TYPE> void uploadCoverFromUri( | ||||||
|  | 			final Class<CLASS_TYPE> clazz, | ||||||
|  | 			final ID_TYPE id, | ||||||
|  | 			final String url) throws Exception { | ||||||
|  |  | ||||||
|  | 		LOGGER.info("    - id: {}", id); | ||||||
|  | 		LOGGER.info("    - url: {} ", url); | ||||||
|  | 		final CLASS_TYPE media = DataAccess.get(clazz, id); | ||||||
|  | 		if (media == null) { | ||||||
|  | 			throw new InputException(clazz.getCanonicalName(), | ||||||
|  | 					"[" + id.toString() + "] Id does not exist or removed..."); | ||||||
|  | 		} | ||||||
|  | 		// Download data: | ||||||
|  |  | ||||||
|  | 		final Client client = ClientBuilder.newClient(); | ||||||
|  | 		byte[] dataResponse = null; | ||||||
|  | 		try { | ||||||
|  | 			final WebTarget target = client.target(url); | ||||||
|  | 			final Response response = target.request().get(); | ||||||
|  | 			if (response.getStatus() != 200) { | ||||||
|  | 				throw new FailException(Response.Status.BAD_GATEWAY, | ||||||
|  | 						clazz.getCanonicalName() + "[" + id.toString() + "] Can not download the media"); | ||||||
|  | 			} | ||||||
|  | 			dataResponse = response.readEntity(byte[].class); | ||||||
|  | 		} catch (final Exception ex) { | ||||||
|  | 			throw new FailException(Response.Status.INTERNAL_SERVER_ERROR, | ||||||
|  | 					clazz.getCanonicalName() + "[" + id.toString() + "] can not create input media", ex); | ||||||
|  | 		} | ||||||
|  | 		if (dataResponse == null) { | ||||||
|  | 			throw new FailException(Response.Status.NOT_ACCEPTABLE, | ||||||
|  | 					clazz.getCanonicalName() + "[" + id.toString() + "] Data does not exist"); | ||||||
|  | 		} | ||||||
|  | 		if (dataResponse.length == 0 || dataResponse.length == 50 * 1024 * 1024) { | ||||||
|  | 			throw new FailException(Response.Status.NOT_ACCEPTABLE, clazz.getCanonicalName() + "[" + id.toString() | ||||||
|  | 					+ "] Data size is not correct " + dataResponse.length); | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		final long tmpUID = getTmpDataId(); | ||||||
|  | 		final String sha512 = saveTemporaryFile(dataResponse, tmpUID); | ||||||
|  | 		Data data = getWithSha512(sha512); | ||||||
|  | 		final String mimeType = getMimeType(dataResponse); | ||||||
|  | 		if (!Arrays.asList(SUPPORTED_IMAGE_MIME_TYPE).contains(mimeType)) { | ||||||
|  | 			throw new FailException(Response.Status.NOT_ACCEPTABLE, | ||||||
|  | 					clazz.getCanonicalName() + "[" + id.toString() + "] Data CoverType is not accesptable: " + mimeType | ||||||
|  | 							+ "support only: " + String.join(", ", SUPPORTED_IMAGE_MIME_TYPE)); | ||||||
|  |  | ||||||
|  | 		} | ||||||
|  | 		if (data == null) { | ||||||
|  | 			LOGGER.info("Need to add the data in the BDD ... "); | ||||||
|  | 			try { | ||||||
|  | 				data = createNewData(tmpUID, url, sha512, mimeType); | ||||||
|  | 			} catch (final IOException ex) { | ||||||
|  | 				removeTemporaryFile(tmpUID); | ||||||
|  | 				throw new FailException(Response.Status.NOT_MODIFIED, | ||||||
|  | 						clazz.getCanonicalName() + "[" + id.toString() + "] can not create input media", ex); | ||||||
|  | 			} catch (final SQLException ex) { | ||||||
|  | 				removeTemporaryFile(tmpUID); | ||||||
|  | 				throw new FailException(Response.Status.NOT_MODIFIED, | ||||||
|  | 						clazz.getCanonicalName() + "[" + id.toString() + "] Error in SQL insertion", ex); | ||||||
|  | 			} | ||||||
|  | 		} else if (data.deleted) { | ||||||
|  | 			LOGGER.error("Data already exist but deleted"); | ||||||
|  | 			undelete(data.uuid); | ||||||
|  | 			data.deleted = false; | ||||||
|  | 		} else { | ||||||
|  | 			LOGGER.error("Data already exist ... all good"); | ||||||
|  | 		} | ||||||
|  | 		// Fist step: retrieve all the Id of each parents:... | ||||||
|  | 		LOGGER.info("Find typeNode"); | ||||||
|  | 		if (id instanceof final Long idLong) { | ||||||
|  | 			AddOnDataJson.addLink(clazz, idLong, "covers", data.uuid); | ||||||
|  | 		} else if (id instanceof final UUID idUUID) { | ||||||
|  | 			AddOnDataJson.addLink(clazz, idUUID, "covers", data.uuid); | ||||||
|  | 		} else { | ||||||
|  | 			throw new IOException("Fail to add Cover can not detect type..."); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	public static <CLASS_TYPE, ID_TYPE> void uploadCover( | 	public static <CLASS_TYPE, ID_TYPE> void uploadCover( | ||||||
| 			final Class<CLASS_TYPE> clazz, | 			final Class<CLASS_TYPE> clazz, | ||||||
| 			final ID_TYPE id, | 			final ID_TYPE id, | ||||||
|   | |||||||
| @@ -107,7 +107,7 @@ public class JWTWrapper { | |||||||
| 			} | 			} | ||||||
| 			in.close(); | 			in.close(); | ||||||
| 			// print result | 			// print result | ||||||
| 			// LOGGER.debug(response.toString()); | 			LOGGER.debug(response.toString()); | ||||||
| 			final ObjectMapper mapper = new ObjectMapper(); | 			final ObjectMapper mapper = new ObjectMapper(); | ||||||
| 			final PublicKey values = mapper.readValue(response.toString(), PublicKey.class); | 			final PublicKey values = mapper.readValue(response.toString(), PublicKey.class); | ||||||
| 			rsaPublicJWK = RSAKey.parse(values.key); | 			rsaPublicJWK = RSAKey.parse(values.key); | ||||||
|   | |||||||
| @@ -222,13 +222,66 @@ public class RESTApi { | |||||||
| 	 */ | 	 */ | ||||||
| 	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 RESTErrorResponseExeption, IOException, InterruptedException { | ||||||
|  | 		return simpleRequest("DELETE", clazz, urlOffset); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	/** | ||||||
|  | 	 * Call an ARCHIVE on a REST API | ||||||
|  | 	 * @param urlOffset Offset to call the API | ||||||
|  | 	 */ | ||||||
|  | 	public void archive(final String urlOffset) throws RESTErrorResponseExeption, IOException, InterruptedException { | ||||||
|  | 		archive(Void.class, urlOffset); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	/** | ||||||
|  | 	 * Call a ARCHIVE on a REST API with retrieving some data | ||||||
|  | 	 * @param <T> Type of data that might be received. | ||||||
|  | 	 * @param clazz Class model of the data that might be parsed. | ||||||
|  | 	 * @param urlOffset Offset to call the API | ||||||
|  | 	 * @return The parsed object received. | ||||||
|  | 	 */ | ||||||
|  | 	public <T> T archive(final Class<T> clazz, final String urlOffset) | ||||||
|  | 			throws RESTErrorResponseExeption, IOException, InterruptedException { | ||||||
|  | 		return simpleRequest("ARCHIVE", clazz, urlOffset); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	/** | ||||||
|  | 	 * Call an RESTORE on a REST API | ||||||
|  | 	 * @param urlOffset Offset to call the API | ||||||
|  | 	 */ | ||||||
|  | 	public void restore(final String urlOffset) throws RESTErrorResponseExeption, IOException, InterruptedException { | ||||||
|  | 		restore(Void.class, urlOffset); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	/** | ||||||
|  | 	 * Call a RESTORE on a REST API with retrieving some data | ||||||
|  | 	 * @param <T> Type of data that might be received. | ||||||
|  | 	 * @param clazz Class model of the data that might be parsed. | ||||||
|  | 	 * @param urlOffset Offset to call the API | ||||||
|  | 	 * @return The parsed object received. | ||||||
|  | 	 */ | ||||||
|  | 	public <T> T restore(final Class<T> clazz, final String urlOffset) | ||||||
|  | 			throws RESTErrorResponseExeption, IOException, InterruptedException { | ||||||
|  | 		return simpleRequest("RESTORE", clazz, urlOffset); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	/** | ||||||
|  | 	 * Call a key on a REST API with retrieving some data | ||||||
|  | 	 * @param <T> Type of data that might be received. | ||||||
|  | 	 * @param model name of the key for the REST call | ||||||
|  | 	 * @param clazz Class model of the data that might be parsed. | ||||||
|  | 	 * @param urlOffset Offset to call the API | ||||||
|  | 	 * @return The parsed object received. | ||||||
|  | 	 */ | ||||||
|  | 	public <T> T simpleRequest(final String model, final Class<T> clazz, final String urlOffset) | ||||||
|  | 			throws RESTErrorResponseExeption, 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)); | ||||||
| 		if (this.token != null) { | 		if (this.token != null) { | ||||||
| 			requestBuilding = requestBuilding.header(HttpHeaders.AUTHORIZATION, "Bearer " + this.token); | 			requestBuilding = requestBuilding.header(HttpHeaders.AUTHORIZATION, "Bearer " + this.token); | ||||||
| 		} | 		} | ||||||
| 		final HttpRequest request = requestBuilding.DELETE().build(); | 		final HttpRequest request = requestBuilding.method(model, BodyPublishers.ofString("")).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) { | ||||||
| 			try { | 			try { | ||||||
|   | |||||||
| @@ -7,11 +7,15 @@ | |||||||
| import { RestErrorResponse, isRestErrorResponse } from "./model"; | import { RestErrorResponse, isRestErrorResponse } from "./model"; | ||||||
|  |  | ||||||
| export enum HTTPRequestModel { | export enum HTTPRequestModel { | ||||||
|  |   ARCHIVE = "ARCHIVE", | ||||||
|   DELETE = "DELETE", |   DELETE = "DELETE", | ||||||
|  |   HEAD = "HEAD", | ||||||
|   GET = "GET", |   GET = "GET", | ||||||
|  |   OPTION = "OPTION", | ||||||
|   PATCH = "PATCH", |   PATCH = "PATCH", | ||||||
|   POST = "POST", |   POST = "POST", | ||||||
|   PUT = "PUT", |   PUT = "PUT", | ||||||
|  |   RESTORE = "RESTORE", | ||||||
| } | } | ||||||
| export enum HTTPMimeType { | export enum HTTPMimeType { | ||||||
|   ALL = "*/*", |   ALL = "*/*", | ||||||
| @@ -248,9 +252,14 @@ export function RESTRequest({ | |||||||
|   if (restModel.accept !== undefined) { |   if (restModel.accept !== undefined) { | ||||||
|     headers["Accept"] = restModel.accept; |     headers["Accept"] = restModel.accept; | ||||||
|   } |   } | ||||||
|   if (restModel.requestType !== HTTPRequestModel.GET) { |   if (restModel.requestType !== HTTPRequestModel.GET && | ||||||
|  | 	restModel.requestType !== HTTPRequestModel.ARCHIVE && | ||||||
|  | 	restModel.requestType !== HTTPRequestModel.RESTORE | ||||||
|  |   ) { | ||||||
|     // if Get we have not a content type, the body is empty |     // if Get we have not a content type, the body is empty | ||||||
|     if (restModel.contentType !== HTTPMimeType.MULTIPART) { |     if (restModel.contentType !== HTTPMimeType.MULTIPART && | ||||||
|  | 	  restModel.contentType !== undefined | ||||||
|  | 	) { | ||||||
|       // special case of multi-part ==> no content type otherwise the browser does not set the ";bundary=--****" |       // special case of multi-part ==> no content type otherwise the browser does not set the ";bundary=--****" | ||||||
|       headers["Content-Type"] = restModel.contentType; |       headers["Content-Type"] = restModel.contentType; | ||||||
|     } |     } | ||||||
|   | |||||||
							
								
								
									
										40
									
								
								test/src/test/kar/archidata/ConfigureDb.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								test/src/test/kar/archidata/ConfigureDb.java
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,40 @@ | |||||||
|  | package test.kar.archidata; | ||||||
|  |  | ||||||
|  | import java.io.IOException; | ||||||
|  |  | ||||||
|  | import org.kar.archidata.GlobalConfiguration; | ||||||
|  | import org.kar.archidata.db.DBEntry; | ||||||
|  | import org.kar.archidata.tools.ConfigBaseVariable; | ||||||
|  | import org.slf4j.Logger; | ||||||
|  | import org.slf4j.LoggerFactory; | ||||||
|  |  | ||||||
|  | public class ConfigureDb { | ||||||
|  | 	final static private Logger LOGGER = LoggerFactory.getLogger(ConfigureDb.class); | ||||||
|  |  | ||||||
|  | 	public static void configure() throws IOException { | ||||||
|  | 		if (true) { | ||||||
|  | 			if (!"true".equalsIgnoreCase(System.getenv("TEST_E2E_MODE"))) { | ||||||
|  | 				ConfigBaseVariable.dbType = "sqlite"; | ||||||
|  | 				ConfigBaseVariable.dbHost = "memory"; | ||||||
|  | 				// for test we need to connect all time the DB | ||||||
|  | 				ConfigBaseVariable.dbKeepConnected = "true"; | ||||||
|  | 			} | ||||||
|  | 		} else { | ||||||
|  | 			// Enable this if you want to access to a local MySQL base to test with an adminer | ||||||
|  | 			ConfigBaseVariable.bdDatabase = "test_db"; | ||||||
|  | 			ConfigBaseVariable.dbPort = "3906"; | ||||||
|  | 			ConfigBaseVariable.dbUser = "root"; | ||||||
|  | 			//ConfigBaseVariable.dbPassword = "password"; | ||||||
|  | 		} | ||||||
|  | 		// Connect the dataBase... | ||||||
|  | 		final DBEntry entry = DBEntry.createInterface(GlobalConfiguration.dbConfig); | ||||||
|  | 		entry.connect(); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static void clear() throws IOException { | ||||||
|  | 		LOGGER.info("Remove the test db"); | ||||||
|  | 		DBEntry.closeAllForceMode(); | ||||||
|  | 		ConfigBaseVariable.clearAllValue(); | ||||||
|  |  | ||||||
|  | 	} | ||||||
|  | } | ||||||
| @@ -11,11 +11,8 @@ import org.junit.jupiter.api.Order; | |||||||
| import org.junit.jupiter.api.Test; | import org.junit.jupiter.api.Test; | ||||||
| import org.junit.jupiter.api.TestMethodOrder; | import org.junit.jupiter.api.TestMethodOrder; | ||||||
| import org.junit.jupiter.api.extension.ExtendWith; | import org.junit.jupiter.api.extension.ExtendWith; | ||||||
| import org.kar.archidata.GlobalConfiguration; |  | ||||||
| import org.kar.archidata.dataAccess.DataAccess; | import org.kar.archidata.dataAccess.DataAccess; | ||||||
| import org.kar.archidata.dataAccess.DataFactory; | import org.kar.archidata.dataAccess.DataFactory; | ||||||
| import org.kar.archidata.db.DBEntry; |  | ||||||
| import org.kar.archidata.tools.ConfigBaseVariable; |  | ||||||
| import org.slf4j.Logger; | import org.slf4j.Logger; | ||||||
| import org.slf4j.LoggerFactory; | import org.slf4j.LoggerFactory; | ||||||
|  |  | ||||||
| @@ -29,22 +26,12 @@ public class TestJson { | |||||||
|  |  | ||||||
| 	@BeforeAll | 	@BeforeAll | ||||||
| 	public static void configureWebServer() throws Exception { | 	public static void configureWebServer() throws Exception { | ||||||
| 		if (!"true".equalsIgnoreCase(System.getenv("TEST_E2E_MODE"))) { | 		ConfigureDb.configure(); | ||||||
| 			ConfigBaseVariable.dbType = "sqlite"; |  | ||||||
| 			ConfigBaseVariable.dbHost = "memory"; |  | ||||||
| 			// for test we need to connect all time the DB |  | ||||||
| 			ConfigBaseVariable.dbKeepConnected = "true"; |  | ||||||
| 		} |  | ||||||
| 		// Connect the dataBase... |  | ||||||
| 		final DBEntry entry = DBEntry.createInterface(GlobalConfiguration.dbConfig); |  | ||||||
| 		entry.connect(); |  | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	@AfterAll | 	@AfterAll | ||||||
| 	public static void removeDataBase() throws IOException { | 	public static void removeDataBase() throws IOException { | ||||||
| 		LOGGER.info("Remove the test db"); | 		ConfigureDb.clear(); | ||||||
| 		DBEntry.closeAllForceMode(); |  | ||||||
| 		ConfigBaseVariable.clearAllValue(); |  | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	@Order(1) | 	@Order(1) | ||||||
|   | |||||||
| @@ -12,11 +12,8 @@ import org.junit.jupiter.api.Order; | |||||||
| import org.junit.jupiter.api.Test; | import org.junit.jupiter.api.Test; | ||||||
| import org.junit.jupiter.api.TestMethodOrder; | import org.junit.jupiter.api.TestMethodOrder; | ||||||
| import org.junit.jupiter.api.extension.ExtendWith; | import org.junit.jupiter.api.extension.ExtendWith; | ||||||
| import org.kar.archidata.GlobalConfiguration; |  | ||||||
| import org.kar.archidata.dataAccess.DataAccess; | import org.kar.archidata.dataAccess.DataAccess; | ||||||
| import org.kar.archidata.dataAccess.DataFactory; | import org.kar.archidata.dataAccess.DataFactory; | ||||||
| import org.kar.archidata.db.DBEntry; |  | ||||||
| import org.kar.archidata.tools.ConfigBaseVariable; |  | ||||||
| import org.slf4j.Logger; | import org.slf4j.Logger; | ||||||
| import org.slf4j.LoggerFactory; | import org.slf4j.LoggerFactory; | ||||||
|  |  | ||||||
| @@ -29,22 +26,12 @@ public class TestListJson { | |||||||
|  |  | ||||||
| 	@BeforeAll | 	@BeforeAll | ||||||
| 	public static void configureWebServer() throws Exception { | 	public static void configureWebServer() throws Exception { | ||||||
| 		if (!"true".equalsIgnoreCase(System.getenv("TEST_E2E_MODE"))) { | 		ConfigureDb.configure(); | ||||||
| 			ConfigBaseVariable.dbType = "sqlite"; |  | ||||||
| 			ConfigBaseVariable.dbHost = "memory"; |  | ||||||
| 			// for test we need to connect all time the DB |  | ||||||
| 			ConfigBaseVariable.dbKeepConnected = "true"; |  | ||||||
| 		} |  | ||||||
| 		// Connect the dataBase... |  | ||||||
| 		final DBEntry entry = DBEntry.createInterface(GlobalConfiguration.dbConfig); |  | ||||||
| 		entry.connect(); |  | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	@AfterAll | 	@AfterAll | ||||||
| 	public static void removeDataBase() throws IOException { | 	public static void removeDataBase() throws IOException { | ||||||
| 		LOGGER.info("Remove the test db"); | 		ConfigureDb.clear(); | ||||||
| 		DBEntry.closeAllForceMode(); |  | ||||||
| 		ConfigBaseVariable.clearAllValue(); |  | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	@Order(1) | 	@Order(1) | ||||||
|   | |||||||
| @@ -11,12 +11,9 @@ import org.junit.jupiter.api.Order; | |||||||
| import org.junit.jupiter.api.Test; | import org.junit.jupiter.api.Test; | ||||||
| import org.junit.jupiter.api.TestMethodOrder; | import org.junit.jupiter.api.TestMethodOrder; | ||||||
| import org.junit.jupiter.api.extension.ExtendWith; | import org.junit.jupiter.api.extension.ExtendWith; | ||||||
| import org.kar.archidata.GlobalConfiguration; |  | ||||||
| import org.kar.archidata.dataAccess.DataAccess; | import org.kar.archidata.dataAccess.DataAccess; | ||||||
| import org.kar.archidata.dataAccess.DataFactory; | import org.kar.archidata.dataAccess.DataFactory; | ||||||
| import org.kar.archidata.dataAccess.addOn.AddOnManyToMany; | import org.kar.archidata.dataAccess.addOn.AddOnManyToMany; | ||||||
| import org.kar.archidata.db.DBEntry; |  | ||||||
| import org.kar.archidata.tools.ConfigBaseVariable; |  | ||||||
| import org.slf4j.Logger; | import org.slf4j.Logger; | ||||||
| import org.slf4j.LoggerFactory; | import org.slf4j.LoggerFactory; | ||||||
|  |  | ||||||
| @@ -31,22 +28,12 @@ public class TestManyToMany { | |||||||
|  |  | ||||||
| 	@BeforeAll | 	@BeforeAll | ||||||
| 	public static void configureWebServer() throws Exception { | 	public static void configureWebServer() throws Exception { | ||||||
| 		if (!"true".equalsIgnoreCase(System.getenv("TEST_E2E_MODE"))) { | 		ConfigureDb.configure(); | ||||||
| 			ConfigBaseVariable.dbType = "sqlite"; |  | ||||||
| 			ConfigBaseVariable.dbHost = "memory"; |  | ||||||
| 			// for test we need to connect all time the DB |  | ||||||
| 			ConfigBaseVariable.dbKeepConnected = "true"; |  | ||||||
| 		} |  | ||||||
| 		// Connect the dataBase... |  | ||||||
| 		final DBEntry entry = DBEntry.createInterface(GlobalConfiguration.dbConfig); |  | ||||||
| 		entry.connect(); |  | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	@AfterAll | 	@AfterAll | ||||||
| 	public static void removeDataBase() throws IOException { | 	public static void removeDataBase() throws IOException { | ||||||
| 		LOGGER.info("Remove the test db"); | 		ConfigureDb.clear(); | ||||||
| 		DBEntry.closeAllForceMode(); |  | ||||||
| 		ConfigBaseVariable.clearAllValue(); |  | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	@Order(1) | 	@Order(1) | ||||||
| @@ -129,7 +116,7 @@ public class TestManyToMany { | |||||||
| 		Assertions.assertNotNull(retrieve.otherData); | 		Assertions.assertNotNull(retrieve.otherData); | ||||||
| 		Assertions.assertEquals(insertedData.otherData, retrieve.otherData); | 		Assertions.assertEquals(insertedData.otherData, retrieve.otherData); | ||||||
| 		Assertions.assertNotNull(retrieve.remote); | 		Assertions.assertNotNull(retrieve.remote); | ||||||
| 		Assertions.assertEquals(retrieve.remote.size(), 2); | 		Assertions.assertEquals(2, retrieve.remote.size()); | ||||||
| 		Assertions.assertEquals(retrieve.remote.get(0), insertedRemote1.id); | 		Assertions.assertEquals(retrieve.remote.get(0), insertedRemote1.id); | ||||||
| 		Assertions.assertEquals(retrieve.remote.get(1), insertedRemote2.id); | 		Assertions.assertEquals(retrieve.remote.get(1), insertedRemote2.id); | ||||||
|  |  | ||||||
| @@ -141,7 +128,7 @@ public class TestManyToMany { | |||||||
| 		Assertions.assertNotNull(retrieveExpand.otherData); | 		Assertions.assertNotNull(retrieveExpand.otherData); | ||||||
| 		Assertions.assertEquals(insertedData.otherData, retrieveExpand.otherData); | 		Assertions.assertEquals(insertedData.otherData, retrieveExpand.otherData); | ||||||
| 		Assertions.assertNotNull(retrieveExpand.remote); | 		Assertions.assertNotNull(retrieveExpand.remote); | ||||||
| 		Assertions.assertEquals(retrieveExpand.remote.size(), 2); | 		Assertions.assertEquals(2, retrieveExpand.remote.size()); | ||||||
| 		Assertions.assertEquals(retrieveExpand.remote.get(0).id, insertedRemote1.id); | 		Assertions.assertEquals(retrieveExpand.remote.get(0).id, insertedRemote1.id); | ||||||
| 		Assertions.assertEquals(retrieveExpand.remote.get(1).id, insertedRemote2.id); | 		Assertions.assertEquals(retrieveExpand.remote.get(1).id, insertedRemote2.id); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -11,11 +11,8 @@ import org.junit.jupiter.api.Order; | |||||||
| import org.junit.jupiter.api.Test; | import org.junit.jupiter.api.Test; | ||||||
| import org.junit.jupiter.api.TestMethodOrder; | import org.junit.jupiter.api.TestMethodOrder; | ||||||
| import org.junit.jupiter.api.extension.ExtendWith; | import org.junit.jupiter.api.extension.ExtendWith; | ||||||
| import org.kar.archidata.GlobalConfiguration; |  | ||||||
| import org.kar.archidata.dataAccess.DataAccess; | import org.kar.archidata.dataAccess.DataAccess; | ||||||
| import org.kar.archidata.dataAccess.DataFactory; | import org.kar.archidata.dataAccess.DataFactory; | ||||||
| import org.kar.archidata.db.DBEntry; |  | ||||||
| import org.kar.archidata.tools.ConfigBaseVariable; |  | ||||||
| import org.slf4j.Logger; | import org.slf4j.Logger; | ||||||
| import org.slf4j.LoggerFactory; | import org.slf4j.LoggerFactory; | ||||||
|  |  | ||||||
| @@ -33,22 +30,12 @@ public class TestManyToOne { | |||||||
|  |  | ||||||
| 	@BeforeAll | 	@BeforeAll | ||||||
| 	public static void configureWebServer() throws Exception { | 	public static void configureWebServer() throws Exception { | ||||||
| 		if (!"true".equalsIgnoreCase(System.getenv("TEST_E2E_MODE"))) { | 		ConfigureDb.configure(); | ||||||
| 			ConfigBaseVariable.dbType = "sqlite"; |  | ||||||
| 			ConfigBaseVariable.dbHost = "memory"; |  | ||||||
| 			// for test we need to connect all time the DB |  | ||||||
| 			ConfigBaseVariable.dbKeepConnected = "true"; |  | ||||||
| 		} |  | ||||||
| 		// Connect the dataBase... |  | ||||||
| 		final DBEntry entry = DBEntry.createInterface(GlobalConfiguration.dbConfig); |  | ||||||
| 		entry.connect(); |  | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	@AfterAll | 	@AfterAll | ||||||
| 	public static void removeDataBase() throws IOException { | 	public static void removeDataBase() throws IOException { | ||||||
| 		LOGGER.info("Remove the test db"); | 		ConfigureDb.clear(); | ||||||
| 		DBEntry.closeAllForceMode(); |  | ||||||
| 		ConfigBaseVariable.clearAllValue(); |  | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	@Order(1) | 	@Order(1) | ||||||
|   | |||||||
| @@ -11,11 +11,8 @@ import org.junit.jupiter.api.Order; | |||||||
| import org.junit.jupiter.api.Test; | import org.junit.jupiter.api.Test; | ||||||
| import org.junit.jupiter.api.TestMethodOrder; | import org.junit.jupiter.api.TestMethodOrder; | ||||||
| import org.junit.jupiter.api.extension.ExtendWith; | import org.junit.jupiter.api.extension.ExtendWith; | ||||||
| import org.kar.archidata.GlobalConfiguration; |  | ||||||
| import org.kar.archidata.dataAccess.DataAccess; | import org.kar.archidata.dataAccess.DataAccess; | ||||||
| import org.kar.archidata.dataAccess.DataFactory; | import org.kar.archidata.dataAccess.DataFactory; | ||||||
| import org.kar.archidata.db.DBEntry; |  | ||||||
| import org.kar.archidata.tools.ConfigBaseVariable; |  | ||||||
| import org.slf4j.Logger; | import org.slf4j.Logger; | ||||||
| import org.slf4j.LoggerFactory; | import org.slf4j.LoggerFactory; | ||||||
|  |  | ||||||
| @@ -33,22 +30,12 @@ public class TestOneToMany { | |||||||
|  |  | ||||||
| 	@BeforeAll | 	@BeforeAll | ||||||
| 	public static void configureWebServer() throws Exception { | 	public static void configureWebServer() throws Exception { | ||||||
| 		if (!"true".equalsIgnoreCase(System.getenv("TEST_E2E_MODE"))) { | 		ConfigureDb.configure(); | ||||||
| 			ConfigBaseVariable.dbType = "sqlite"; |  | ||||||
| 			ConfigBaseVariable.dbHost = "memory"; |  | ||||||
| 			// for test we need to connect all time the DB |  | ||||||
| 			ConfigBaseVariable.dbKeepConnected = "true"; |  | ||||||
| 		} |  | ||||||
| 		// Connect the dataBase... |  | ||||||
| 		final DBEntry entry = DBEntry.createInterface(GlobalConfiguration.dbConfig); |  | ||||||
| 		entry.connect(); |  | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	@AfterAll | 	@AfterAll | ||||||
| 	public static void removeDataBase() throws IOException { | 	public static void removeDataBase() throws IOException { | ||||||
| 		LOGGER.info("Remove the test db"); | 		ConfigureDb.clear(); | ||||||
| 		DBEntry.closeAllForceMode(); |  | ||||||
| 		ConfigBaseVariable.clearAllValue(); |  | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	@Order(1) | 	@Order(1) | ||||||
|   | |||||||
| @@ -11,11 +11,8 @@ import org.junit.jupiter.api.Order; | |||||||
| import org.junit.jupiter.api.Test; | import org.junit.jupiter.api.Test; | ||||||
| import org.junit.jupiter.api.TestMethodOrder; | import org.junit.jupiter.api.TestMethodOrder; | ||||||
| import org.junit.jupiter.api.extension.ExtendWith; | import org.junit.jupiter.api.extension.ExtendWith; | ||||||
| import org.kar.archidata.GlobalConfiguration; |  | ||||||
| import org.kar.archidata.dataAccess.DataAccess; | import org.kar.archidata.dataAccess.DataAccess; | ||||||
| import org.kar.archidata.dataAccess.DataFactory; | import org.kar.archidata.dataAccess.DataFactory; | ||||||
| import org.kar.archidata.db.DBEntry; |  | ||||||
| import org.kar.archidata.tools.ConfigBaseVariable; |  | ||||||
| import org.slf4j.Logger; | import org.slf4j.Logger; | ||||||
| import org.slf4j.LoggerFactory; | import org.slf4j.LoggerFactory; | ||||||
|  |  | ||||||
| @@ -28,22 +25,12 @@ public class TestRawQuery { | |||||||
|  |  | ||||||
| 	@BeforeAll | 	@BeforeAll | ||||||
| 	public static void configureWebServer() throws Exception { | 	public static void configureWebServer() throws Exception { | ||||||
| 		if (!"true".equalsIgnoreCase(System.getenv("TEST_E2E_MODE"))) { | 		ConfigureDb.configure(); | ||||||
| 			ConfigBaseVariable.dbType = "sqlite"; |  | ||||||
| 			ConfigBaseVariable.dbHost = "memory"; |  | ||||||
| 			// for test we need to connect all time the DB |  | ||||||
| 			ConfigBaseVariable.dbKeepConnected = "true"; |  | ||||||
| 		} |  | ||||||
| 		// Connect the dataBase... |  | ||||||
| 		final DBEntry entry = DBEntry.createInterface(GlobalConfiguration.dbConfig); |  | ||||||
| 		entry.connect(); |  | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	@AfterAll | 	@AfterAll | ||||||
| 	public static void removeDataBase() throws IOException { | 	public static void removeDataBase() throws IOException { | ||||||
| 		LOGGER.info("Remove the test db"); | 		ConfigureDb.clear(); | ||||||
| 		DBEntry.closeAllForceMode(); |  | ||||||
| 		ConfigBaseVariable.clearAllValue(); |  | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	@Order(1) | 	@Order(1) | ||||||
| @@ -83,13 +70,13 @@ public class TestRawQuery { | |||||||
| 		test.floatData = 7.0F; | 		test.floatData = 7.0F; | ||||||
| 		DataAccess.insert(test); | 		DataAccess.insert(test); | ||||||
| 		{ | 		{ | ||||||
| 			String query = """ | 			final String query = """ | ||||||
| 					SELECT * | 					SELECT * | ||||||
| 					FROM TypesTable | 					FROM TypesTable | ||||||
| 					WHERE `intData` = ? | 					WHERE `intData` = ? | ||||||
| 					ORDER BY id DESC | 					ORDER BY id DESC | ||||||
| 					"""; | 					"""; | ||||||
| 			List<Object> parameters = List.of(Integer.valueOf(99)); | 			final List<Object> parameters = List.of(Integer.valueOf(99)); | ||||||
| 			// Try to retrieve all the data: | 			// Try to retrieve all the data: | ||||||
| 			final List<TypesTable> retrieve = DataAccess.query(TypesTable.class, query, parameters); | 			final List<TypesTable> retrieve = DataAccess.query(TypesTable.class, query, parameters); | ||||||
|  |  | ||||||
| @@ -102,13 +89,13 @@ public class TestRawQuery { | |||||||
| 		} | 		} | ||||||
| 		{ | 		{ | ||||||
|  |  | ||||||
| 			String query = """ | 			final String query = """ | ||||||
| 					SELECT DISTINCT intData | 					SELECT DISTINCT intData | ||||||
| 					FROM TypesTable | 					FROM TypesTable | ||||||
| 					WHERE `intData` = ? | 					WHERE `intData` = ? | ||||||
| 					ORDER BY id DESC | 					ORDER BY id DESC | ||||||
| 					"""; | 					"""; | ||||||
| 			List<Object> parameters = List.of(Integer.valueOf(99)); | 			final List<Object> parameters = List.of(Integer.valueOf(99)); | ||||||
| 			// Try to retrieve all the data: | 			// Try to retrieve all the data: | ||||||
| 			final List<TypesTable> retrieve = DataAccess.query(TypesTable.class, query, parameters); | 			final List<TypesTable> retrieve = DataAccess.query(TypesTable.class, query, parameters); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -14,12 +14,9 @@ import org.junit.jupiter.api.Order; | |||||||
| import org.junit.jupiter.api.Test; | import org.junit.jupiter.api.Test; | ||||||
| import org.junit.jupiter.api.TestMethodOrder; | import org.junit.jupiter.api.TestMethodOrder; | ||||||
| import org.junit.jupiter.api.extension.ExtendWith; | import org.junit.jupiter.api.extension.ExtendWith; | ||||||
| import org.kar.archidata.GlobalConfiguration; |  | ||||||
| import org.kar.archidata.dataAccess.DataAccess; | import org.kar.archidata.dataAccess.DataAccess; | ||||||
| import org.kar.archidata.dataAccess.DataFactory; | import org.kar.archidata.dataAccess.DataFactory; | ||||||
| import org.kar.archidata.dataAccess.QueryOptions; | import org.kar.archidata.dataAccess.QueryOptions; | ||||||
| import org.kar.archidata.db.DBEntry; |  | ||||||
| import org.kar.archidata.tools.ConfigBaseVariable; |  | ||||||
| import org.slf4j.Logger; | import org.slf4j.Logger; | ||||||
| import org.slf4j.LoggerFactory; | import org.slf4j.LoggerFactory; | ||||||
|  |  | ||||||
| @@ -36,26 +33,15 @@ public class TestSimpleTable { | |||||||
|  |  | ||||||
| 	@BeforeAll | 	@BeforeAll | ||||||
| 	public static void configureWebServer() throws Exception { | 	public static void configureWebServer() throws Exception { | ||||||
| 		if (!"true".equalsIgnoreCase(System.getenv("TEST_E2E_MODE"))) { |  | ||||||
| 			ConfigBaseVariable.dbType = "sqlite"; |  | ||||||
| 			ConfigBaseVariable.dbHost = "memory"; |  | ||||||
| 			// for test we need to connect all time the DB |  | ||||||
| 			ConfigBaseVariable.dbKeepConnected = "true"; |  | ||||||
| 		} |  | ||||||
| 		// Clear the static test: | 		// Clear the static test: | ||||||
| 		idOfTheObject = null; | 		idOfTheObject = null; | ||||||
| 		startAction = null; | 		startAction = null; | ||||||
|  | 		ConfigureDb.configure(); | ||||||
| 		// Connect the dataBase... |  | ||||||
| 		final DBEntry entry = DBEntry.createInterface(GlobalConfiguration.dbConfig); |  | ||||||
| 		entry.connect(); |  | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	@AfterAll | 	@AfterAll | ||||||
| 	public static void removeDataBase() throws IOException { | 	public static void removeDataBase() throws IOException { | ||||||
| 		LOGGER.info("Remove the test db"); | 		ConfigureDb.clear(); | ||||||
| 		DBEntry.closeAllForceMode(); |  | ||||||
| 		ConfigBaseVariable.clearAllValue(); |  | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	@Order(1) | 	@Order(1) | ||||||
|   | |||||||
| @@ -14,11 +14,9 @@ import org.junit.jupiter.api.Order; | |||||||
| import org.junit.jupiter.api.Test; | import org.junit.jupiter.api.Test; | ||||||
| import org.junit.jupiter.api.TestMethodOrder; | import org.junit.jupiter.api.TestMethodOrder; | ||||||
| import org.junit.jupiter.api.extension.ExtendWith; | import org.junit.jupiter.api.extension.ExtendWith; | ||||||
| import org.kar.archidata.GlobalConfiguration; |  | ||||||
| import org.kar.archidata.dataAccess.DataAccess; | import org.kar.archidata.dataAccess.DataAccess; | ||||||
| import org.kar.archidata.dataAccess.DataFactory; | import org.kar.archidata.dataAccess.DataFactory; | ||||||
| import org.kar.archidata.dataAccess.QueryOptions; | import org.kar.archidata.dataAccess.QueryOptions; | ||||||
| import org.kar.archidata.db.DBEntry; |  | ||||||
| import org.kar.archidata.tools.ConfigBaseVariable; | import org.kar.archidata.tools.ConfigBaseVariable; | ||||||
| import org.slf4j.Logger; | import org.slf4j.Logger; | ||||||
| import org.slf4j.LoggerFactory; | import org.slf4j.LoggerFactory; | ||||||
| @@ -36,26 +34,16 @@ public class TestSimpleTableSoftDelete { | |||||||
|  |  | ||||||
| 	@BeforeAll | 	@BeforeAll | ||||||
| 	public static void configureWebServer() throws Exception { | 	public static void configureWebServer() throws Exception { | ||||||
| 		if (!"true".equalsIgnoreCase(System.getenv("TEST_E2E_MODE"))) { |  | ||||||
| 			ConfigBaseVariable.dbType = "sqlite"; |  | ||||||
| 			ConfigBaseVariable.dbHost = "memory"; |  | ||||||
| 			// for test we need to connect all time the DB |  | ||||||
| 			ConfigBaseVariable.dbKeepConnected = "true"; |  | ||||||
| 		} |  | ||||||
| 		// Clear the static test: | 		// Clear the static test: | ||||||
| 		idOfTheObject = null; | 		idOfTheObject = null; | ||||||
| 		startAction = null; | 		startAction = null; | ||||||
|  |  | ||||||
| 		// Connect the dataBase... | 		ConfigureDb.configure(); | ||||||
| 		final DBEntry entry = DBEntry.createInterface(GlobalConfiguration.dbConfig); |  | ||||||
| 		entry.connect(); |  | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	@AfterAll | 	@AfterAll | ||||||
| 	public static void removeDataBase() throws IOException { | 	public static void removeDataBase() throws IOException { | ||||||
| 		LOGGER.info("Remove the test db"); | 		ConfigureDb.clear(); | ||||||
| 		DBEntry.closeAllForceMode(); |  | ||||||
| 		ConfigBaseVariable.clearAllValue(); |  | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	@Order(1) | 	@Order(1) | ||||||
|   | |||||||
| @@ -11,11 +11,8 @@ import org.junit.jupiter.api.Order; | |||||||
| import org.junit.jupiter.api.Test; | import org.junit.jupiter.api.Test; | ||||||
| import org.junit.jupiter.api.TestMethodOrder; | import org.junit.jupiter.api.TestMethodOrder; | ||||||
| import org.junit.jupiter.api.extension.ExtendWith; | import org.junit.jupiter.api.extension.ExtendWith; | ||||||
| import org.kar.archidata.GlobalConfiguration; |  | ||||||
| import org.kar.archidata.dataAccess.DataAccess; | import org.kar.archidata.dataAccess.DataAccess; | ||||||
| import org.kar.archidata.dataAccess.DataFactory; | import org.kar.archidata.dataAccess.DataFactory; | ||||||
| import org.kar.archidata.db.DBEntry; |  | ||||||
| import org.kar.archidata.tools.ConfigBaseVariable; |  | ||||||
| import org.slf4j.Logger; | import org.slf4j.Logger; | ||||||
| import org.slf4j.LoggerFactory; | import org.slf4j.LoggerFactory; | ||||||
|  |  | ||||||
| @@ -29,22 +26,12 @@ public class TestTypeEnum1 { | |||||||
|  |  | ||||||
| 	@BeforeAll | 	@BeforeAll | ||||||
| 	public static void configureWebServer() throws Exception { | 	public static void configureWebServer() throws Exception { | ||||||
| 		if (!"true".equalsIgnoreCase(System.getenv("TEST_E2E_MODE"))) { | 		ConfigureDb.configure(); | ||||||
| 			ConfigBaseVariable.dbType = "sqlite"; |  | ||||||
| 			ConfigBaseVariable.dbHost = "memory"; |  | ||||||
| 			// for test we need to connect all time the DB |  | ||||||
| 			ConfigBaseVariable.dbKeepConnected = "true"; |  | ||||||
| 		} |  | ||||||
| 		// Connect the dataBase... |  | ||||||
| 		final DBEntry entry = DBEntry.createInterface(GlobalConfiguration.dbConfig); |  | ||||||
| 		entry.connect(); |  | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	@AfterAll | 	@AfterAll | ||||||
| 	public static void removeDataBase() throws IOException { | 	public static void removeDataBase() throws IOException { | ||||||
| 		LOGGER.info("Remove the test db"); | 		ConfigureDb.clear(); | ||||||
| 		DBEntry.closeAllForceMode(); |  | ||||||
| 		ConfigBaseVariable.clearAllValue(); |  | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	@Order(1) | 	@Order(1) | ||||||
|   | |||||||
| @@ -11,11 +11,8 @@ import org.junit.jupiter.api.Order; | |||||||
| import org.junit.jupiter.api.Test; | import org.junit.jupiter.api.Test; | ||||||
| import org.junit.jupiter.api.TestMethodOrder; | import org.junit.jupiter.api.TestMethodOrder; | ||||||
| import org.junit.jupiter.api.extension.ExtendWith; | import org.junit.jupiter.api.extension.ExtendWith; | ||||||
| import org.kar.archidata.GlobalConfiguration; |  | ||||||
| import org.kar.archidata.dataAccess.DataAccess; | import org.kar.archidata.dataAccess.DataAccess; | ||||||
| import org.kar.archidata.dataAccess.DataFactory; | import org.kar.archidata.dataAccess.DataFactory; | ||||||
| import org.kar.archidata.db.DBEntry; |  | ||||||
| import org.kar.archidata.tools.ConfigBaseVariable; |  | ||||||
| import org.slf4j.Logger; | import org.slf4j.Logger; | ||||||
| import org.slf4j.LoggerFactory; | import org.slf4j.LoggerFactory; | ||||||
|  |  | ||||||
| @@ -29,22 +26,12 @@ public class TestTypeEnum2 { | |||||||
|  |  | ||||||
| 	@BeforeAll | 	@BeforeAll | ||||||
| 	public static void configureWebServer() throws Exception { | 	public static void configureWebServer() throws Exception { | ||||||
| 		if (!"true".equalsIgnoreCase(System.getenv("TEST_E2E_MODE"))) { | 		ConfigureDb.configure(); | ||||||
| 			ConfigBaseVariable.dbType = "sqlite"; |  | ||||||
| 			ConfigBaseVariable.dbHost = "memory"; |  | ||||||
| 			// for test we need to connect all time the DB |  | ||||||
| 			ConfigBaseVariable.dbKeepConnected = "true"; |  | ||||||
| 		} |  | ||||||
| 		// Connect the dataBase... |  | ||||||
| 		final DBEntry entry = DBEntry.createInterface(GlobalConfiguration.dbConfig); |  | ||||||
| 		entry.connect(); |  | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	@AfterAll | 	@AfterAll | ||||||
| 	public static void removeDataBase() throws IOException { | 	public static void removeDataBase() throws IOException { | ||||||
| 		LOGGER.info("Remove the test db"); | 		ConfigureDb.clear(); | ||||||
| 		DBEntry.closeAllForceMode(); |  | ||||||
| 		ConfigBaseVariable.clearAllValue(); |  | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	@Order(1) | 	@Order(1) | ||||||
|   | |||||||
| @@ -16,11 +16,8 @@ import org.junit.jupiter.api.Order; | |||||||
| import org.junit.jupiter.api.Test; | import org.junit.jupiter.api.Test; | ||||||
| import org.junit.jupiter.api.TestMethodOrder; | import org.junit.jupiter.api.TestMethodOrder; | ||||||
| import org.junit.jupiter.api.extension.ExtendWith; | import org.junit.jupiter.api.extension.ExtendWith; | ||||||
| import org.kar.archidata.GlobalConfiguration; |  | ||||||
| import org.kar.archidata.dataAccess.DataAccess; | import org.kar.archidata.dataAccess.DataAccess; | ||||||
| import org.kar.archidata.dataAccess.DataFactory; | import org.kar.archidata.dataAccess.DataFactory; | ||||||
| import org.kar.archidata.db.DBEntry; |  | ||||||
| import org.kar.archidata.tools.ConfigBaseVariable; |  | ||||||
| import org.slf4j.Logger; | import org.slf4j.Logger; | ||||||
| import org.slf4j.LoggerFactory; | import org.slf4j.LoggerFactory; | ||||||
|  |  | ||||||
| @@ -33,22 +30,12 @@ public class TestTypes { | |||||||
|  |  | ||||||
| 	@BeforeAll | 	@BeforeAll | ||||||
| 	public static void configureWebServer() throws Exception { | 	public static void configureWebServer() throws Exception { | ||||||
| 		if (!"true".equalsIgnoreCase(System.getenv("TEST_E2E_MODE"))) { | 		ConfigureDb.configure(); | ||||||
| 			ConfigBaseVariable.dbType = "sqlite"; |  | ||||||
| 			ConfigBaseVariable.dbHost = "memory"; |  | ||||||
| 			// for test we need to connect all time the DB |  | ||||||
| 			ConfigBaseVariable.dbKeepConnected = "true"; |  | ||||||
| 		} |  | ||||||
| 		// Connect the dataBase... |  | ||||||
| 		final DBEntry entry = DBEntry.createInterface(GlobalConfiguration.dbConfig); |  | ||||||
| 		entry.connect(); |  | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	@AfterAll | 	@AfterAll | ||||||
| 	public static void removeDataBase() throws IOException { | 	public static void removeDataBase() throws IOException { | ||||||
| 		LOGGER.info("Remove the test db"); | 		ConfigureDb.clear(); | ||||||
| 		DBEntry.closeAllForceMode(); |  | ||||||
| 		ConfigBaseVariable.clearAllValue(); |  | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	@Order(1) | 	@Order(1) | ||||||
|   | |||||||
| @@ -1,8 +1,15 @@ | |||||||
| package test.kar.archidata.model; | package test.kar.archidata.model; | ||||||
|  |  | ||||||
|  | import java.util.List; | ||||||
|  |  | ||||||
| import org.kar.archidata.model.GenericData; | import org.kar.archidata.model.GenericData; | ||||||
|  |  | ||||||
| public class TypeManyToManyRemote extends GenericData { | import jakarta.persistence.FetchType; | ||||||
|  | import jakarta.persistence.ManyToMany; | ||||||
|  |  | ||||||
|  | public class TypeManyToManyRemote extends GenericData { | ||||||
|  | 	@ManyToMany(fetch = FetchType.LAZY, targetEntity = TypeManyToManyRoot.class, mappedBy = "remote") | ||||||
|  | 	public List<Long> remoteToParent; | ||||||
| 	public String data; | 	public String data; | ||||||
|  |  | ||||||
| } | } | ||||||
| @@ -1 +1 @@ | |||||||
| 0.13.0 | 0.17.0 | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user