Compare commits
	
		
			21 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 9a6d712d7a | |||
| 55275e4f26 | |||
| f7de0e1db0 | |||
| 032728f05d | |||
| bfe722f074 | |||
| fddf41bea0 | |||
| 3fa48fc839 | |||
| de08bcfab5 | |||
| 37f1362c3c | |||
| e2ee68cc03 | |||
| f05527ce01 | |||
| 38503fac8e | |||
| ab7259f726 | |||
| cdb4581799 | |||
| 7e81bfef28 | |||
| 84525fd7aa | |||
| d4eb9c2a5f | |||
| 15688f93e5 | |||
| 906216f237 | |||
| b479414bc2 | |||
| 2bc68321e3 | 
							
								
								
									
										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.12.1</version> | 	<version>0.13.1-SNAPSHOT</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> | ||||||
|   | |||||||
| @@ -17,7 +17,9 @@ import jakarta.persistence.Column; | |||||||
| import jakarta.persistence.GeneratedValue; | import jakarta.persistence.GeneratedValue; | ||||||
| import jakarta.persistence.GenerationType; | import jakarta.persistence.GenerationType; | ||||||
| import jakarta.persistence.Id; | import jakarta.persistence.Id; | ||||||
|  | import jakarta.persistence.ManyToMany; | ||||||
| import jakarta.persistence.ManyToOne; | import jakarta.persistence.ManyToOne; | ||||||
|  | import jakarta.persistence.OneToMany; | ||||||
| import jakarta.persistence.Table; | import jakarta.persistence.Table; | ||||||
| import jakarta.validation.constraints.Max; | import jakarta.validation.constraints.Max; | ||||||
| import jakarta.validation.constraints.Min; | import jakarta.validation.constraints.Min; | ||||||
| @@ -136,18 +138,30 @@ public class AnnotationTools { | |||||||
| 		return ((DefaultValue) annotation[0]).value(); | 		return ((DefaultValue) annotation[0]).value(); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	public static ManyToOne getManyToOne(final Field element) throws DataAccessException { | 	public static ManyToOne getManyToOne(final Field element) { | ||||||
| 		final Annotation[] annotation = element.getDeclaredAnnotationsByType(ManyToOne.class); | 		final Annotation[] annotation = element.getDeclaredAnnotationsByType(ManyToOne.class); | ||||||
| 		if (annotation.length == 0) { | 		if (annotation.length == 0) { | ||||||
| 			return null; | 			return null; | ||||||
| 		} | 		} | ||||||
| 		if (annotation.length > 1) { |  | ||||||
| 			throw new DataAccessException( |  | ||||||
| 					"Must not have more than 1 element @ManyToOne on " + element.getClass().getCanonicalName()); |  | ||||||
| 		} |  | ||||||
| 		return (ManyToOne) annotation[0]; | 		return (ManyToOne) annotation[0]; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	public static ManyToMany getManyToMany(final Field element) { | ||||||
|  | 		final Annotation[] annotation = element.getDeclaredAnnotationsByType(ManyToMany.class); | ||||||
|  | 		if (annotation.length == 0) { | ||||||
|  | 			return null; | ||||||
|  | 		} | ||||||
|  | 		return (ManyToMany) annotation[0]; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static OneToMany getOneToMany(final Field element) { | ||||||
|  | 		final Annotation[] annotation = element.getDeclaredAnnotationsByType(OneToMany.class); | ||||||
|  | 		if (annotation.length == 0) { | ||||||
|  | 			return null; | ||||||
|  | 		} | ||||||
|  | 		return (OneToMany) annotation[0]; | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	public static DataJson getDataJson(final Field element) throws DataAccessException { | 	public static DataJson getDataJson(final Field element) throws DataAccessException { | ||||||
| 		final Annotation[] annotation = element.getDeclaredAnnotationsByType(DataJson.class); | 		final Annotation[] annotation = element.getDeclaredAnnotationsByType(DataJson.class); | ||||||
| 		if (annotation.length == 0) { | 		if (annotation.length == 0) { | ||||||
| @@ -244,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 { | ||||||
|  |  | ||||||
|  | } | ||||||
| @@ -326,10 +326,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 +350,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); | ||||||
|   | |||||||
							
								
								
									
										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(); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
| @@ -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); | ||||||
| 	} | 	} | ||||||
| @@ -188,9 +189,21 @@ public class AddOnDataJson implements DataAccessAddOn { | |||||||
| 		DataAccess.update(data, data.id, List.of("covers"), new OverrideTableName(tableName)); | 		DataAccess.update(data, data.id, List.of("covers"), new OverrideTableName(tableName)); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	/** | ||||||
|  | 	 * Adds a remoteKey to the covers list of a data entry identified by the given class type and ID. | ||||||
|  | 	 * If the covers list is null, it initializes it. If the remoteKey already exists in the list, | ||||||
|  | 	 * the method returns without making any changes. | ||||||
|  | 	 * | ||||||
|  | 	 * @param clazz     The class type to retrieve the table name from. | ||||||
|  | 	 * @param id        The ID of the data object to fetch. | ||||||
|  | 	 * @param column    The name of the column (currently not used, but may be used for specifying a field name). | ||||||
|  | 	 * @param remoteKey The UUID to add to the covers list. | ||||||
|  | 	 * @throws Exception If an error occurs during data retrieval or update. | ||||||
|  | 	 */ | ||||||
| 	public static void addLink(final Class<?> clazz, final Long id, final String column, final UUID remoteKey) | 	public static void addLink(final Class<?> clazz, final Long id, final String column, final UUID remoteKey) | ||||||
| 			throws Exception { | 			throws Exception { | ||||||
| 		final String tableName = AnnotationTools.getTableName(clazz); | 		final String tableName = AnnotationTools.getTableName(clazz); | ||||||
|  | 		// TODO: Get primary key name | ||||||
| 		final TableCoversLongUUID data = DataAccess.get(TableCoversLongUUID.class, id, | 		final TableCoversLongUUID data = DataAccess.get(TableCoversLongUUID.class, id, | ||||||
| 				new OverrideTableName(tableName)); | 				new OverrideTableName(tableName)); | ||||||
| 		if (data.covers == null) { | 		if (data.covers == null) { | ||||||
| @@ -205,10 +218,21 @@ public class AddOnDataJson implements DataAccessAddOn { | |||||||
| 		DataAccess.update(data, data.id, List.of("covers"), new OverrideTableName(tableName));// TODO:  ,new OverrideFieldName("covers", column)); | 		DataAccess.update(data, data.id, List.of("covers"), new OverrideTableName(tableName));// TODO:  ,new OverrideFieldName("covers", column)); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	public static void addLink(final Class<?> clazz, final UUID id, final String column, final UUID remoteKey) | 	/** | ||||||
|  | 	 * Adds a remoteKey to the covers list of a data entry identified by the given class type and ID. | ||||||
|  | 	 * If the covers list is null, it initializes it. If the remoteKey already exists in the list, | ||||||
|  | 	 * the method returns without making any changes. | ||||||
|  | 	 * | ||||||
|  | 	 * @param clazz     The class type to retrieve the table name from. | ||||||
|  | 	 * @param id        The ID of the data object to fetch. | ||||||
|  | 	 * @param column    The name of the column (currently not used, but may be used for specifying a field name). | ||||||
|  | 	 * @param remoteKey The UUID to add to the covers list. | ||||||
|  | 	 * @throws Exception If an error occurs during data retrieval or update. | ||||||
|  | 	 */ | ||||||
|  | 	public static void addLink(final Class<?> clazz, final UUID uuid, final String column, final UUID remoteKey) | ||||||
| 			throws Exception { | 			throws Exception { | ||||||
| 		final String tableName = AnnotationTools.getTableName(clazz); | 		final String tableName = AnnotationTools.getTableName(clazz); | ||||||
| 		final TableCoversUUIDUUID data = DataAccess.get(TableCoversUUIDUUID.class, id, | 		final TableCoversUUIDUUID data = DataAccess.get(TableCoversUUIDUUID.class, uuid, | ||||||
| 				new OverrideTableName(tableName)); | 				new OverrideTableName(tableName)); | ||||||
| 		if (data.covers == null) { | 		if (data.covers == null) { | ||||||
| 			data.covers = new ArrayList<>(); | 			data.covers = new ArrayList<>(); | ||||||
| @@ -219,13 +243,13 @@ public class AddOnDataJson implements DataAccessAddOn { | |||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 		data.covers.add(remoteKey); | 		data.covers.add(remoteKey); | ||||||
| 		DataAccess.update(data, data.id, List.of("covers"), new OverrideTableName(tableName)); | 		DataAccess.update(data, data.uuid, List.of("covers"), new OverrideTableName(tableName)); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	public static void addLink(final Class<?> clazz, final UUID id, final String column, final Long remoteKey) | 	public static void addLink(final Class<?> clazz, final UUID uuid, final String column, final Long remoteKey) | ||||||
| 			throws Exception { | 			throws Exception { | ||||||
| 		final String tableName = AnnotationTools.getTableName(clazz); | 		final String tableName = AnnotationTools.getTableName(clazz); | ||||||
| 		final TableCoversUUIDLong data = DataAccess.get(TableCoversUUIDLong.class, id, | 		final TableCoversUUIDLong data = DataAccess.get(TableCoversUUIDLong.class, uuid, | ||||||
| 				new OverrideTableName(tableName)); | 				new OverrideTableName(tableName)); | ||||||
| 		if (data.covers == null) { | 		if (data.covers == null) { | ||||||
| 			data.covers = new ArrayList<>(); | 			data.covers = new ArrayList<>(); | ||||||
| @@ -236,13 +260,13 @@ public class AddOnDataJson implements DataAccessAddOn { | |||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 		data.covers.add(remoteKey); | 		data.covers.add(remoteKey); | ||||||
| 		DataAccess.update(data, data.id, List.of("covers"), new OverrideTableName(tableName)); | 		DataAccess.update(data, data.uuid, List.of("covers"), new OverrideTableName(tableName)); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	public static void removeLink(final Class<?> clazz, final UUID id, final String column, final Long remoteKey) | 	public static void removeLink(final Class<?> clazz, final UUID uuid, final String column, final Long remoteKey) | ||||||
| 			throws Exception { | 			throws Exception { | ||||||
| 		final String tableName = AnnotationTools.getTableName(clazz); | 		final String tableName = AnnotationTools.getTableName(clazz); | ||||||
| 		final TableCoversUUIDLong data = DataAccess.get(TableCoversUUIDLong.class, id, | 		final TableCoversUUIDLong data = DataAccess.get(TableCoversUUIDLong.class, uuid, | ||||||
| 				new OverrideTableName(tableName)); | 				new OverrideTableName(tableName)); | ||||||
| 		if (data.covers == null) { | 		if (data.covers == null) { | ||||||
| 			return; | 			return; | ||||||
| @@ -255,13 +279,13 @@ public class AddOnDataJson implements DataAccessAddOn { | |||||||
| 			newList.add(elem); | 			newList.add(elem); | ||||||
| 		} | 		} | ||||||
| 		data.covers = newList; | 		data.covers = newList; | ||||||
| 		DataAccess.update(data, data.id, List.of("covers"), new OverrideTableName(tableName)); | 		DataAccess.update(data, data.uuid, List.of("covers"), new OverrideTableName(tableName)); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	public static void removeLink(final Class<?> clazz, final UUID id, final String column, final UUID remoteKey) | 	public static void removeLink(final Class<?> clazz, final UUID uuid, final String column, final UUID remoteKey) | ||||||
| 			throws Exception { | 			throws Exception { | ||||||
| 		final String tableName = AnnotationTools.getTableName(clazz); | 		final String tableName = AnnotationTools.getTableName(clazz); | ||||||
| 		final TableCoversUUIDUUID data = DataAccess.get(TableCoversUUIDUUID.class, id, | 		final TableCoversUUIDUUID data = DataAccess.get(TableCoversUUIDUUID.class, uuid, | ||||||
| 				new OverrideTableName(tableName)); | 				new OverrideTableName(tableName)); | ||||||
| 		if (data.covers == null) { | 		if (data.covers == null) { | ||||||
| 			return; | 			return; | ||||||
| @@ -274,7 +298,7 @@ public class AddOnDataJson implements DataAccessAddOn { | |||||||
| 			newList.add(elem); | 			newList.add(elem); | ||||||
| 		} | 		} | ||||||
| 		data.covers = newList; | 		data.covers = newList; | ||||||
| 		DataAccess.update(data, data.id, List.of("covers"), new OverrideTableName(tableName)); | 		DataAccess.update(data, data.uuid, List.of("covers"), new OverrideTableName(tableName)); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	public static void removeLink(final Class<?> clazz, final Long id, final String column, final Long remoteKey) | 	public static void removeLink(final Class<?> clazz, final Long id, final String column, final Long remoteKey) | ||||||
| @@ -314,9 +338,4 @@ public class AddOnDataJson implements DataAccessAddOn { | |||||||
| 		data.covers = newList; | 		data.covers = newList; | ||||||
| 		DataAccess.update(data, data.id, List.of("covers"), new OverrideTableName(tableName)); | 		DataAccess.update(data, data.id, List.of("covers"), new OverrideTableName(tableName)); | ||||||
| 	} | 	} | ||||||
| 	/* public static <TYPE> void addLink(final Class<TYPE> clazz, final Object localKey, final String column, final Object remoteKey) throws Exception { final String tableName = |  | ||||||
| 	 * AnnotationTools.getTableName(clazz); final TYPE data = DataAccess.get(clazz, localKey); // TODO: add filter of the "column" // find the field column: // add the remoteKey in the list: // post |  | ||||||
| 	 * new data in the DB final String linkTableName = generateLinkTableName(this.tableName, this.column); final LinkTable insertElement = new LinkTable(this.localKey, this.remoteKey); |  | ||||||
| 	 * DataAccess.insert(insertElement, new OverrideTableName(linkTableName)); } */ |  | ||||||
|  |  | ||||||
| } | } | ||||||
|   | |||||||
| @@ -108,13 +108,23 @@ 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 "); | 		if (manyToMany.mappedBy() == null || manyToMany.mappedBy().length() == 0) { | ||||||
|  | 			querySelect.append(".object2Id "); | ||||||
|  | 		} else { | ||||||
|  | 			querySelect.append(".object1Id "); | ||||||
|  | 		} | ||||||
| 		if ("sqlite".equals(ConfigBaseVariable.getDBType())) { | 		if ("sqlite".equals(ConfigBaseVariable.getDBType())) { | ||||||
| 			querySelect.append(", "); | 			querySelect.append(", "); | ||||||
| 		} else { | 		} else { | ||||||
| @@ -143,11 +153,19 @@ public class AddOnManyToMany implements DataAccessAddOn { | |||||||
| 		querySelect.append(" = "); | 		querySelect.append(" = "); | ||||||
| 		querySelect.append(tmpVariable); | 		querySelect.append(tmpVariable); | ||||||
| 		querySelect.append("."); | 		querySelect.append("."); | ||||||
| 		querySelect.append("object1Id "); | 		if (manyToMany.mappedBy() == null || manyToMany.mappedBy().length() == 0) { | ||||||
|  | 			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 (manyToMany.mappedBy() == null || manyToMany.mappedBy().length() == 0) { | ||||||
|  | 				querySelect.append(".object1Id"); | ||||||
|  | 			} else { | ||||||
|  | 				querySelect.append(".object2Id"); | ||||||
|  | 			} | ||||||
| 		} | 		} | ||||||
| 		querySelect.append(") AS "); | 		querySelect.append(") AS "); | ||||||
| 		querySelect.append(name); | 		querySelect.append(name); | ||||||
| @@ -509,6 +527,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 +551,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); | ||||||
|   | |||||||
| @@ -3,11 +3,10 @@ package org.kar.archidata.dataAccess.addOn.model; | |||||||
| import java.util.List; | import java.util.List; | ||||||
|  |  | ||||||
| import org.kar.archidata.annotation.DataJson; | import org.kar.archidata.annotation.DataJson; | ||||||
| import org.kar.archidata.model.GenericDataSoftDelete; |  | ||||||
|  |  | ||||||
| import jakarta.persistence.Column; | import jakarta.persistence.Id; | ||||||
|  |  | ||||||
| public class TableCoversLongLong extends GenericDataSoftDelete { | public class TableCoversLongLong { | ||||||
| 	public TableCoversLongLong() { | 	public TableCoversLongLong() { | ||||||
| 		// nothing to do... | 		// nothing to do... | ||||||
| 	} | 	} | ||||||
| @@ -17,8 +16,10 @@ public class TableCoversLongLong extends GenericDataSoftDelete { | |||||||
| 		this.covers = covers; | 		this.covers = covers; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	@Id | ||||||
|  | 	public Long id; | ||||||
|  |  | ||||||
| 	@DataJson() | 	@DataJson() | ||||||
| 	@Column(nullable = false) |  | ||||||
| 	public List<Long> covers; | 	public List<Long> covers; | ||||||
|  |  | ||||||
| } | } | ||||||
|   | |||||||
| @@ -1,25 +1,27 @@ | |||||||
| 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; | ||||||
|  |  | ||||||
| import org.kar.archidata.annotation.DataJson; | import org.kar.archidata.annotation.DataJson; | ||||||
| import org.kar.archidata.model.GenericDataSoftDelete; |  | ||||||
|  |  | ||||||
| import jakarta.persistence.Column; | import jakarta.persistence.Id; | ||||||
|  |  | ||||||
| public class TableCoversLongUUID extends GenericDataSoftDelete { | public class TableCoversLongUUID { | ||||||
| 	public TableCoversLongUUID() { | 	public TableCoversLongUUID() { | ||||||
| 		// nothing to do... | 		// nothing to do... | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	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 | ||||||
|  | 	public Long id; | ||||||
|  |  | ||||||
| 	@DataJson() | 	@DataJson() | ||||||
| 	@Column(nullable = false) |  | ||||||
| 	public List<UUID> covers; | 	public List<UUID> covers; | ||||||
|  |  | ||||||
| } | } | ||||||
|   | |||||||
| @@ -1,29 +1,26 @@ | |||||||
| 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; | ||||||
|  |  | ||||||
| import org.kar.archidata.annotation.DataJson; | import org.kar.archidata.annotation.DataJson; | ||||||
| import org.kar.archidata.model.GenericDataSoftDelete; |  | ||||||
|  |  | ||||||
| import jakarta.persistence.Column; |  | ||||||
| import jakarta.persistence.Id; | import jakarta.persistence.Id; | ||||||
|  |  | ||||||
| public class TableCoversUUIDLong extends GenericDataSoftDelete { | public class TableCoversUUIDLong { | ||||||
| 	public TableCoversUUIDLong() { | 	public TableCoversUUIDLong() { | ||||||
| 		// nothing to do... | 		// nothing to do... | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	public TableCoversUUIDLong(final UUID id, final List<Long> covers) { | 	public TableCoversUUIDLong(final UUID uuid, final List<Long> covers) { | ||||||
| 		this.id = id; | 		this.uuid = uuid; | ||||||
| 		this.covers = covers; | 		this.covers = new ArrayList<>(covers); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	@Column(nullable = false) |  | ||||||
| 	@Id | 	@Id | ||||||
| 	public UUID id; | 	public UUID uuid; | ||||||
| 	@DataJson() | 	@DataJson() | ||||||
| 	@Column(nullable = false) |  | ||||||
| 	public List<Long> covers; | 	public List<Long> covers; | ||||||
|  |  | ||||||
| } | } | ||||||
|   | |||||||
| @@ -4,26 +4,22 @@ import java.util.List; | |||||||
| import java.util.UUID; | import java.util.UUID; | ||||||
|  |  | ||||||
| import org.kar.archidata.annotation.DataJson; | import org.kar.archidata.annotation.DataJson; | ||||||
| import org.kar.archidata.model.GenericDataSoftDelete; |  | ||||||
|  |  | ||||||
| import jakarta.persistence.Column; |  | ||||||
| import jakarta.persistence.Id; | import jakarta.persistence.Id; | ||||||
|  |  | ||||||
| public class TableCoversUUIDUUID extends GenericDataSoftDelete { | public class TableCoversUUIDUUID { | ||||||
| 	public TableCoversUUIDUUID() { | 	public TableCoversUUIDUUID() { | ||||||
| 		// nothing to do... | 		// nothing to do... | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	public TableCoversUUIDUUID(final UUID id, final List<UUID> covers) { | 	public TableCoversUUIDUUID(final UUID uuid, final List<UUID> covers) { | ||||||
| 		this.id = id; | 		this.uuid = uuid; | ||||||
| 		this.covers = covers; | 		this.covers = covers; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	@Column(nullable = false) |  | ||||||
| 	@Id | 	@Id | ||||||
| 	public UUID id; | 	public UUID uuid; | ||||||
| 	@DataJson() | 	@DataJson() | ||||||
| 	@Column(nullable = false) |  | ||||||
| 	public List<UUID> covers; | 	public List<UUID> covers; | ||||||
|  |  | ||||||
| } | } | ||||||
|   | |||||||
| @@ -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()); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
| } | } | ||||||
|   | |||||||
							
								
								
									
										232
									
								
								src/org/kar/archidata/externalRestApi/DotGenerateApi.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										232
									
								
								src/org/kar/archidata/externalRestApi/DotGenerateApi.java
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,232 @@ | |||||||
|  | package org.kar.archidata.externalRestApi; | ||||||
|  |  | ||||||
|  | import java.io.FileWriter; | ||||||
|  | import java.io.InputStream; | ||||||
|  | import java.sql.Timestamp; | ||||||
|  | import java.time.Instant; | ||||||
|  | import java.time.LocalDate; | ||||||
|  | import java.time.LocalTime; | ||||||
|  | import java.util.ArrayList; | ||||||
|  | import java.util.Date; | ||||||
|  | import java.util.List; | ||||||
|  | import java.util.Map; | ||||||
|  | import java.util.UUID; | ||||||
|  |  | ||||||
|  | import org.glassfish.jersey.media.multipart.ContentDisposition; | ||||||
|  | import org.glassfish.jersey.media.multipart.FormDataContentDisposition; | ||||||
|  | import org.kar.archidata.catcher.RestErrorResponse; | ||||||
|  | import org.kar.archidata.externalRestApi.dot.DotApiGeneration; | ||||||
|  | import org.kar.archidata.externalRestApi.dot.DotClassElement; | ||||||
|  | import org.kar.archidata.externalRestApi.dot.DotClassElement.DefinedPosition; | ||||||
|  | import org.kar.archidata.externalRestApi.dot.DotClassElementGroup; | ||||||
|  | import org.kar.archidata.externalRestApi.model.ApiGroupModel; | ||||||
|  | import org.kar.archidata.externalRestApi.model.ClassModel; | ||||||
|  |  | ||||||
|  | public class DotGenerateApi { | ||||||
|  |  | ||||||
|  | 	public static void generateApi(final AnalyzeApi api, final String pathDotFile) throws Exception { | ||||||
|  | 		final List<DotClassElement> localModel = generateApiModel(api); | ||||||
|  | 		final DotClassElementGroup dotGroup = new DotClassElementGroup(localModel); | ||||||
|  |  | ||||||
|  | 		try (final FileWriter myWriter = new FileWriter(pathDotFile)) { | ||||||
|  | 			myWriter.write(""" | ||||||
|  | 					# Architecture auto-generated file | ||||||
|  | 					digraph UML_Class_diagram { | ||||||
|  | 					    #rankdir=NS; | ||||||
|  | 						graph [ | ||||||
|  | 							pad="0.5" | ||||||
|  | 							nodesep="1" | ||||||
|  | 							#ranksep="2" | ||||||
|  | 							label="Rest API server Model" | ||||||
|  | 							labelloc="t" | ||||||
|  | 							fontname="FreeMono,Sans-Mono,Helvetica,Arial,sans-serif" | ||||||
|  | 						] | ||||||
|  | 						node [ | ||||||
|  | 							fontname="FreeMono,Sans-Mono,Helvetica,Arial,sans-serif" | ||||||
|  | 							shape=record | ||||||
|  | 							style=filled | ||||||
|  | 							fillcolor=gray95 | ||||||
|  | 						] | ||||||
|  | 						edge [fontname="FreeMono,Sans-Mono,Helvetica,Arial,sans-serif"] | ||||||
|  | 					"""); | ||||||
|  | 			/* | ||||||
|  | 			myWriter.write(""" | ||||||
|  | 						subgraph REST_API { | ||||||
|  | 						style=filled; | ||||||
|  | 						color=lightgrey; | ||||||
|  | 						label="REST API"; | ||||||
|  | 					    rankdir=LR; | ||||||
|  | 					"""); | ||||||
|  | 			*/ | ||||||
|  | 			for (final ApiGroupModel element : api.apiModels) { | ||||||
|  | 				final String tmp = DotApiGeneration.generateApiFile(element, dotGroup); | ||||||
|  | 				myWriter.write(tmp); | ||||||
|  | 				myWriter.write("\n"); | ||||||
|  | 			} | ||||||
|  | 			// create an invisible link to force all element to be link together: | ||||||
|  | 			if (false) { | ||||||
|  | 				String previous = null; | ||||||
|  | 				for (final ApiGroupModel element : api.apiModels) { | ||||||
|  | 					if (previous == null) { | ||||||
|  | 						previous = element.name; | ||||||
|  | 						continue; | ||||||
|  | 					} | ||||||
|  | 					myWriter.write("\t{ "); | ||||||
|  | 					myWriter.write(previous); | ||||||
|  | 					myWriter.write(":s -> "); | ||||||
|  | 					previous = element.name; | ||||||
|  | 					myWriter.write(previous); | ||||||
|  | 					myWriter.write(":n [style=invis]}\n"); | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 			/* | ||||||
|  | 			myWriter.write(""" | ||||||
|  | 						} | ||||||
|  | 					"""); | ||||||
|  | 			myWriter.write(""" | ||||||
|  | 						subgraph Models { | ||||||
|  | 						style=filled; | ||||||
|  | 						color=lightgrey; | ||||||
|  | 						label="Models"; | ||||||
|  | 					    rankdir=NS; | ||||||
|  | 					"""); | ||||||
|  | 			*/ | ||||||
|  | 			// Generates all MODEL files | ||||||
|  | 			for (final DotClassElement element : localModel) { | ||||||
|  | 				final String tmp = element.generateFile(dotGroup); | ||||||
|  | 				myWriter.write(tmp); | ||||||
|  | 				myWriter.write("\n"); | ||||||
|  | 			} | ||||||
|  | 			/* | ||||||
|  | 			myWriter.write(""" | ||||||
|  | 						} | ||||||
|  | 					"""); | ||||||
|  | 			*/ | ||||||
|  | 			myWriter.write(""" | ||||||
|  | 					} | ||||||
|  | 					"""); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	private static List<DotClassElement> generateApiModel(final AnalyzeApi api) throws Exception { | ||||||
|  | 		// First step is to add all specific basic elements the wrap correctly the model | ||||||
|  | 		final List<DotClassElement> dotModels = new ArrayList<>(); | ||||||
|  | 		List<ClassModel> models = api.getCompatibleModels(List.of(Void.class, void.class)); | ||||||
|  | 		if (models != null) { | ||||||
|  | 			dotModels.add(new DotClassElement(models, "void", "void", null, null, DefinedPosition.NATIVE)); | ||||||
|  | 		} | ||||||
|  | 		models = api.getCompatibleModels(List.of(Object.class)); | ||||||
|  | 		if (models != null) { | ||||||
|  | 			dotModels.add(new DotClassElement(models, "Object", "object", null, "Object", DefinedPosition.NATIVE)); | ||||||
|  | 		} | ||||||
|  | 		// Map is binded to any ==> can not determine this complex model for now | ||||||
|  | 		models = api.getCompatibleModels(List.of(Map.class)); | ||||||
|  | 		if (models != null) { | ||||||
|  | 			dotModels.add(new DotClassElement(models, "Object", "any", null, null, DefinedPosition.NATIVE)); | ||||||
|  | 		} | ||||||
|  | 		models = api.getCompatibleModels(List.of(String.class)); | ||||||
|  | 		if (models != null) { | ||||||
|  | 			dotModels.add(new DotClassElement(models, "String", "string", null, "String", DefinedPosition.NATIVE)); | ||||||
|  | 		} | ||||||
|  | 		models = api.getCompatibleModels( | ||||||
|  | 				List.of(InputStream.class, FormDataContentDisposition.class, ContentDisposition.class)); | ||||||
|  | 		if (models != null) { | ||||||
|  | 			dotModels.add(new DotClassElement(models, "File", "File", null, "File", DefinedPosition.NATIVE)); | ||||||
|  | 		} | ||||||
|  | 		models = api.getCompatibleModels(List.of(Boolean.class)); | ||||||
|  | 		if (models != null) { | ||||||
|  | 			dotModels.add(new DotClassElement(models, "Boolean", "boolean", null, "Boolean", DefinedPosition.NATIVE)); | ||||||
|  | 		} | ||||||
|  | 		models = api.getCompatibleModels(List.of(boolean.class)); | ||||||
|  | 		if (models != null) { | ||||||
|  | 			dotModels.add(new DotClassElement(models, "boolean", "boolean", null, "boolean", DefinedPosition.NATIVE)); | ||||||
|  | 		} | ||||||
|  | 		models = api.getCompatibleModels(List.of(UUID.class)); | ||||||
|  | 		if (models != null) { | ||||||
|  | 			dotModels.add(new DotClassElement(models, "UUID", "UUID", "isUUID", "UUID", DefinedPosition.BASIC)); | ||||||
|  | 		} | ||||||
|  | 		models = api.getCompatibleModels(List.of(long.class)); | ||||||
|  | 		if (models != null) { | ||||||
|  | 			dotModels.add(new DotClassElement(models, "long", "Long", "isLong", "long", DefinedPosition.BASIC)); | ||||||
|  | 		} | ||||||
|  | 		models = api.getCompatibleModels(List.of(Long.class)); | ||||||
|  | 		if (models != null) { | ||||||
|  | 			dotModels.add(new DotClassElement(models, "Long", "Long", "isLong", "Long", DefinedPosition.BASIC)); | ||||||
|  | 		} | ||||||
|  | 		models = api.getCompatibleModels(List.of(short.class)); | ||||||
|  | 		if (models != null) { | ||||||
|  | 			dotModels.add(new DotClassElement(models, "short", "Short", "isShort", "short", DefinedPosition.BASIC)); | ||||||
|  | 		} | ||||||
|  | 		models = api.getCompatibleModels(List.of(Short.class)); | ||||||
|  | 		if (models != null) { | ||||||
|  | 			dotModels.add(new DotClassElement(models, "Short", "Short", "isShort", "Short", DefinedPosition.BASIC)); | ||||||
|  | 		} | ||||||
|  | 		models = api.getCompatibleModels(List.of(int.class)); | ||||||
|  | 		if (models != null) { | ||||||
|  | 			dotModels.add(new DotClassElement(models, "int", "Integer", "isInteger", "int", DefinedPosition.BASIC)); | ||||||
|  | 		} | ||||||
|  | 		models = api.getCompatibleModels(List.of(Integer.class)); | ||||||
|  | 		if (models != null) { | ||||||
|  | 			dotModels.add( | ||||||
|  | 					new DotClassElement(models, "Integer", "Integer", "isInteger", "Integer", DefinedPosition.BASIC)); | ||||||
|  | 		} | ||||||
|  | 		models = api.getCompatibleModels(List.of(double.class)); | ||||||
|  | 		if (models != null) { | ||||||
|  | 			dotModels.add(new DotClassElement(models, "Double", "Double", "isDouble", "double", DefinedPosition.BASIC)); | ||||||
|  | 		} | ||||||
|  | 		models = api.getCompatibleModels(List.of(Double.class)); | ||||||
|  | 		if (models != null) { | ||||||
|  | 			dotModels.add(new DotClassElement(models, "Double", "Double", "isDouble", "Double", DefinedPosition.BASIC)); | ||||||
|  | 		} | ||||||
|  | 		models = api.getCompatibleModels(List.of(float.class)); | ||||||
|  | 		if (models != null) { | ||||||
|  | 			dotModels.add(new DotClassElement(models, "float", "Float", "isFloat", "float", DefinedPosition.BASIC)); | ||||||
|  | 		} | ||||||
|  | 		models = api.getCompatibleModels(List.of(Float.class)); | ||||||
|  | 		if (models != null) { | ||||||
|  | 			dotModels.add(new DotClassElement(models, "Float", "Float", "isFloat", "Float", DefinedPosition.BASIC)); | ||||||
|  | 		} | ||||||
|  | 		models = api.getCompatibleModels(List.of(Instant.class)); | ||||||
|  | 		if (models != null) { | ||||||
|  | 			dotModels.add( | ||||||
|  | 					new DotClassElement(models, "Instant", "Instant", "isInstant", "Instant", DefinedPosition.BASIC)); | ||||||
|  | 		} | ||||||
|  | 		models = api.getCompatibleModels(List.of(Date.class)); | ||||||
|  | 		if (models != null) { | ||||||
|  | 			dotModels.add(new DotClassElement(models, "Date", "IsoDate", "isIsoDate", "Date", DefinedPosition.BASIC)); | ||||||
|  | 		} | ||||||
|  | 		models = api.getCompatibleModels(List.of(Timestamp.class)); | ||||||
|  | 		if (models != null) { | ||||||
|  | 			dotModels.add(new DotClassElement(models, "Timestamp", "Timestamp", "isTimestamp", "Timestamp", | ||||||
|  | 					DefinedPosition.BASIC)); | ||||||
|  | 		} | ||||||
|  | 		models = api.getCompatibleModels(List.of(LocalDate.class)); | ||||||
|  | 		if (models != null) { | ||||||
|  | 			dotModels.add(new DotClassElement(models, "LocalDate", "LocalDate", "isLocalDate", "LocalDate", | ||||||
|  | 					DefinedPosition.BASIC)); | ||||||
|  | 		} | ||||||
|  | 		models = api.getCompatibleModels(List.of(LocalTime.class)); | ||||||
|  | 		if (models != null) { | ||||||
|  | 			dotModels.add(new DotClassElement(models, "LocalTime", "LocalTime", "isLocalTime", "LocalTime", | ||||||
|  | 					DefinedPosition.BASIC)); | ||||||
|  | 		} | ||||||
|  | 		// needed for Rest interface | ||||||
|  | 		api.addModel(RestErrorResponse.class); | ||||||
|  | 		for (final ClassModel model : api.getAllModel()) { | ||||||
|  | 			boolean alreadyExist = false; | ||||||
|  | 			for (final DotClassElement elem : dotModels) { | ||||||
|  | 				if (elem.isCompatible(model)) { | ||||||
|  | 					alreadyExist = true; | ||||||
|  | 					break; | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 			if (alreadyExist) { | ||||||
|  | 				continue; | ||||||
|  | 			} | ||||||
|  | 			dotModels.add(new DotClassElement(model)); | ||||||
|  | 		} | ||||||
|  | 		return dotModels; | ||||||
|  |  | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | } | ||||||
| @@ -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) { | ||||||
|   | |||||||
							
								
								
									
										414
									
								
								src/org/kar/archidata/externalRestApi/dot/DotApiGeneration.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										414
									
								
								src/org/kar/archidata/externalRestApi/dot/DotApiGeneration.java
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,414 @@ | |||||||
|  | package org.kar.archidata.externalRestApi.dot; | ||||||
|  |  | ||||||
|  | import java.io.IOException; | ||||||
|  | import java.util.ArrayList; | ||||||
|  | import java.util.HashSet; | ||||||
|  | import java.util.List; | ||||||
|  | import java.util.Map.Entry; | ||||||
|  | import java.util.Set; | ||||||
|  |  | ||||||
|  | import org.kar.archidata.externalRestApi.dot.DotClassElement.DefinedPosition; | ||||||
|  | import org.kar.archidata.externalRestApi.model.ApiGroupModel; | ||||||
|  | import org.kar.archidata.externalRestApi.model.ApiModel; | ||||||
|  | import org.kar.archidata.externalRestApi.model.ClassEnumModel; | ||||||
|  | import org.kar.archidata.externalRestApi.model.ClassListModel; | ||||||
|  | import org.kar.archidata.externalRestApi.model.ClassMapModel; | ||||||
|  | import org.kar.archidata.externalRestApi.model.ClassModel; | ||||||
|  | import org.kar.archidata.externalRestApi.model.ClassObjectModel; | ||||||
|  | import org.slf4j.Logger; | ||||||
|  | import org.slf4j.LoggerFactory; | ||||||
|  |  | ||||||
|  | public class DotApiGeneration { | ||||||
|  | 	static final Logger LOGGER = LoggerFactory.getLogger(DotApiGeneration.class); | ||||||
|  |  | ||||||
|  | 	public static String generateClassEnumModelTypescript( | ||||||
|  | 			final ClassEnumModel model, | ||||||
|  | 			final DotClassElementGroup dotGroup, | ||||||
|  | 			final Set<ClassModel> imports) throws IOException { | ||||||
|  | 		imports.add(model); | ||||||
|  | 		final DotClassElement dotModel = dotGroup.find(model); | ||||||
|  | 		return dotModel.dotTypeName; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static String generateClassObjectModelTypescript( | ||||||
|  | 			final ClassObjectModel model, | ||||||
|  | 			final DotClassElementGroup dotGroup, | ||||||
|  | 			final Set<ClassModel> imports) throws IOException { | ||||||
|  | 		final DotClassElement dotModel = dotGroup.find(model); | ||||||
|  | 		if (dotModel.nativeType != DefinedPosition.NATIVE) { | ||||||
|  | 			imports.add(model); | ||||||
|  | 		} | ||||||
|  | 		if (dotModel.nativeType != DefinedPosition.NORMAL) { | ||||||
|  | 			return dotModel.dotTypeName; | ||||||
|  | 		} | ||||||
|  | 		return dotModel.dotTypeName; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static String generateClassMapModelTypescript( | ||||||
|  | 			final ClassMapModel model, | ||||||
|  | 			final DotClassElementGroup dotGroup, | ||||||
|  | 			final Set<ClassModel> imports) throws IOException { | ||||||
|  | 		final StringBuilder out = new StringBuilder(); | ||||||
|  | 		out.append("Map<"); | ||||||
|  | 		out.append(generateClassModelTypescript(model.keyModel, dotGroup, imports)); | ||||||
|  | 		out.append(", "); | ||||||
|  | 		out.append(generateClassModelTypescript(model.valueModel, dotGroup, imports)); | ||||||
|  | 		out.append(">"); | ||||||
|  | 		return out.toString(); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static String generateClassListModelTypescript( | ||||||
|  | 			final ClassListModel model, | ||||||
|  | 			final DotClassElementGroup dotGroup, | ||||||
|  | 			final Set<ClassModel> imports) throws IOException { | ||||||
|  | 		final StringBuilder out = new StringBuilder(); | ||||||
|  | 		out.append("List<"); | ||||||
|  | 		out.append(generateClassModelTypescript(model.valueModel, dotGroup, imports)); | ||||||
|  | 		out.append(">"); | ||||||
|  | 		return out.toString(); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static String generateClassModelTypescript( | ||||||
|  | 			final ClassModel model, | ||||||
|  | 			final DotClassElementGroup dotGroup, | ||||||
|  | 			final Set<ClassModel> imports) throws IOException { | ||||||
|  | 		if (model instanceof final ClassObjectModel objectModel) { | ||||||
|  | 			return generateClassObjectModelTypescript(objectModel, dotGroup, imports); | ||||||
|  | 		} | ||||||
|  | 		if (model instanceof final ClassListModel listModel) { | ||||||
|  | 			return generateClassListModelTypescript(listModel, dotGroup, imports); | ||||||
|  | 		} | ||||||
|  | 		if (model instanceof final ClassMapModel mapModel) { | ||||||
|  | 			return generateClassMapModelTypescript(mapModel, dotGroup, imports); | ||||||
|  | 		} | ||||||
|  | 		if (model instanceof final ClassEnumModel enumModel) { | ||||||
|  | 			return generateClassEnumModelTypescript(enumModel, dotGroup, imports); | ||||||
|  | 		} | ||||||
|  | 		throw new IOException("Impossible model:" + model); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static String generateClassModelsTypescript( | ||||||
|  | 			final List<ClassModel> models, | ||||||
|  | 			final DotClassElementGroup dotGroup) throws IOException { | ||||||
|  | 		if (models.size() == 0) { | ||||||
|  | 			return "void"; | ||||||
|  | 		} | ||||||
|  | 		final StringBuilder out = new StringBuilder(); | ||||||
|  | 		if (models.size() > 1) { | ||||||
|  | 			out.append("Union<"); | ||||||
|  | 		} | ||||||
|  | 		boolean isFirst = true; | ||||||
|  | 		for (final ClassModel model : models) { | ||||||
|  | 			if (isFirst) { | ||||||
|  | 				isFirst = false; | ||||||
|  | 			} else { | ||||||
|  | 				out.append(", "); | ||||||
|  | 			} | ||||||
|  | 			final String data = DotClassElement.generateClassModelTypescript(model, dotGroup); | ||||||
|  | 			out.append(data); | ||||||
|  | 		} | ||||||
|  | 		if (models.size() > 1) { | ||||||
|  | 			out.append(">"); | ||||||
|  | 		} | ||||||
|  | 		return out.toString(); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static List<String> generateClassModelsLinks( | ||||||
|  | 			final List<ClassModel> models, | ||||||
|  | 			final DotClassElementGroup dotGroup) throws IOException { | ||||||
|  | 		if (models.size() == 0) { | ||||||
|  | 			return null; | ||||||
|  | 		} | ||||||
|  | 		final List<String> out = new ArrayList<>(); | ||||||
|  | 		final boolean isFirst = true; | ||||||
|  | 		for (final ClassModel model : models) { | ||||||
|  | 			final String data = DotClassElement.generateClassModelTypescriptLink(model, dotGroup); | ||||||
|  | 			if (data != null) { | ||||||
|  | 				out.add(data); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		return out; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static String capitalizeFirstLetter(final String str) { | ||||||
|  | 		if (str == null || str.isEmpty()) { | ||||||
|  | 			return str; | ||||||
|  | 		} | ||||||
|  | 		return str.substring(0, 1).toUpperCase() + str.substring(1); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static String generateApiFile(final ApiGroupModel element, final DotClassElementGroup dotGroup) | ||||||
|  | 			throws IOException { | ||||||
|  | 		final StringBuilder data = new StringBuilder(); | ||||||
|  | 		final StringBuilder outLinks = new StringBuilder(); | ||||||
|  | 		data.append(""" | ||||||
|  | 					%s [ | ||||||
|  | 						shape=plain | ||||||
|  | 						label=<<table color="#FF3333" border="2" cellborder="1" cellspacing="0" cellpadding="4"> | ||||||
|  | 						<tr> | ||||||
|  | 							<td><b>%s</b><br/>(REST)</td> | ||||||
|  | 						</tr> | ||||||
|  | 						<tr> | ||||||
|  | 							<td> | ||||||
|  | 								<table border="0" cellborder="0" cellspacing="0" > | ||||||
|  | 				""".formatted(element.name, element.name)); | ||||||
|  | 		final Set<ClassModel> imports = new HashSet<>(); | ||||||
|  | 		final Set<ClassModel> zodImports = new HashSet<>(); | ||||||
|  | 		final Set<ClassModel> isImports = new HashSet<>(); | ||||||
|  | 		final Set<ClassModel> writeImports = new HashSet<>(); | ||||||
|  | 		final Set<String> toolImports = new HashSet<>(); | ||||||
|  | 		for (final ApiModel interfaceElement : element.interfaces) { | ||||||
|  | 			final List<String> consumes = interfaceElement.consumes; | ||||||
|  | 			final List<String> produces = interfaceElement.produces; | ||||||
|  | 			final boolean needGenerateProgress = interfaceElement.needGenerateProgress; | ||||||
|  | 			/* | ||||||
|  | 			if (returnComplexModel != null) { | ||||||
|  | 				data.append(returnComplexModel.replaceAll("(?m)^", "\t")); | ||||||
|  | 				for (final ClassModel elem : interfaceElement.returnTypes) { | ||||||
|  | 					zodImports.addAll(elem.getDependencyGroupModels()); | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 			*/ | ||||||
|  | 			data.append("\t\t\t\t\t<tr><td  align=\"left\" port=\""); | ||||||
|  | 			data.append(interfaceElement.name); | ||||||
|  | 			data.append("\"><b> + "); | ||||||
|  | 			data.append(interfaceElement.name); | ||||||
|  | 			data.append("("); | ||||||
|  | 			boolean hasParam = false; | ||||||
|  | 			/* | ||||||
|  | 			if (!interfaceElement.queries.isEmpty()) { | ||||||
|  | 				data.append("\n\t\tqueries: {"); | ||||||
|  | 				for (final Entry<String, List<ClassModel>> queryEntry : interfaceElement.queries.entrySet()) { | ||||||
|  | 					data.append("\n\t\t\t"); | ||||||
|  | 					data.append(queryEntry.getKey()); | ||||||
|  | 					data.append("?: "); | ||||||
|  | 					data.append(generateClassModelsTypescript(queryEntry.getValue(), dotGroup, imports, false)); | ||||||
|  | 					data.append(","); | ||||||
|  | 				} | ||||||
|  | 				data.append("\n\t\t},"); | ||||||
|  | 			} | ||||||
|  | 			*/ | ||||||
|  | 			/* fonctionnel mais trop de donnée | ||||||
|  | 			if (!interfaceElement.parameters.isEmpty()) { | ||||||
|  | 				//data.append("params: {"); | ||||||
|  | 				for (final Entry<String, List<ClassModel>> paramEntry : interfaceElement.parameters.entrySet()) { | ||||||
|  | 					data.append(""); | ||||||
|  | 					data.append(paramEntry.getKey()); | ||||||
|  | 					data.append(": "); | ||||||
|  | 					data.append(generateClassModelsTypescript(paramEntry.getValue(), dotGroup, imports, false)); | ||||||
|  | 					data.append(","); | ||||||
|  | 				} | ||||||
|  | 				//data.append("},"); | ||||||
|  | 			} | ||||||
|  | 			*/ | ||||||
|  | 			if (interfaceElement.unnamedElement.size() == 1) { | ||||||
|  | 				if (hasParam) { | ||||||
|  | 					data.append(", "); | ||||||
|  | 				} | ||||||
|  | 				hasParam = true; | ||||||
|  | 				data.append("data: "); | ||||||
|  | 				data.append( | ||||||
|  | 						generateClassModelTypescript(interfaceElement.unnamedElement.get(0), dotGroup, writeImports)); | ||||||
|  | 			} else if (interfaceElement.multiPartParameters.size() != 0) { | ||||||
|  | 				if (hasParam) { | ||||||
|  | 					data.append(", "); | ||||||
|  | 				} | ||||||
|  | 				hasParam = true; | ||||||
|  | 				boolean hasParam2 = false; | ||||||
|  | 				data.append("data: {"); | ||||||
|  | 				for (final Entry<String, List<ClassModel>> pathEntry : interfaceElement.multiPartParameters | ||||||
|  | 						.entrySet()) { | ||||||
|  | 					if (hasParam2) { | ||||||
|  | 						data.append(", "); | ||||||
|  | 					} | ||||||
|  | 					hasParam2 = true; | ||||||
|  | 					data.append(pathEntry.getKey()); | ||||||
|  | 					data.append(": "); | ||||||
|  | 					data.append(generateClassModelsTypescript(pathEntry.getValue(), dotGroup)); | ||||||
|  | 				} | ||||||
|  | 				data.append("}"); | ||||||
|  | 			} | ||||||
|  | 			data.append("): "); | ||||||
|  | 			/* | ||||||
|  | 			String tmp = DotClassElement.generateLocalModel( | ||||||
|  | 					final String ModelName, | ||||||
|  | 					final List<ClassModel> models, | ||||||
|  | 					final DotClassElementGroup dotGroup) | ||||||
|  | 					public static String generateClassModelsTypescript( | ||||||
|  | 							final List<ClassModel> models, | ||||||
|  | 							final DotClassElementGroup dotGroup, | ||||||
|  | 							final Set<ClassModel> imports) throws IOException { | ||||||
|  | 			*/ | ||||||
|  | 			final String returnType = generateClassModelsTypescript(interfaceElement.returnTypes, dotGroup); | ||||||
|  | 			data.append(returnType); | ||||||
|  | 			final List<String> returnLinks = generateClassModelsLinks(interfaceElement.returnTypes, dotGroup); | ||||||
|  | 			for (final String link : returnLinks) { | ||||||
|  | 				outLinks.append("\t"); | ||||||
|  | 				outLinks.append(element.name); | ||||||
|  | 				outLinks.append(":"); | ||||||
|  | 				outLinks.append(interfaceElement.name); | ||||||
|  | 				outLinks.append(":e -> "); | ||||||
|  | 				outLinks.append(link); | ||||||
|  | 				outLinks.append(":NAME:w\n"); | ||||||
|  | 			} | ||||||
|  | 			data.append("</b>"); | ||||||
|  | 			//data.append("<br align=\"left\"/>    "); | ||||||
|  | 			data.append("</td></tr>\n\t\t\t\t\t\t\t<tr><td  align=\"left\">    "); | ||||||
|  | 			/* | ||||||
|  | 			data.append("\n\t\t\trestModel: {"); | ||||||
|  | 			data.append("\n\t\t\t\tendPoint: \""); | ||||||
|  | 			*/ | ||||||
|  | 			data.append(interfaceElement.restEndPoint); | ||||||
|  | 			/* | ||||||
|  | 			data.append("\","); | ||||||
|  | 			data.append("\n\t\t\t\trequestType: HTTPRequestModel."); | ||||||
|  | 			toolImports.add("HTTPRequestModel"); | ||||||
|  | 			data.append(interfaceElement.restTypeRequest); | ||||||
|  | 			data.append(","); | ||||||
|  | 			if (consumes != null) { | ||||||
|  | 				for (final String elem : consumes) { | ||||||
|  | 					if (MediaType.APPLICATION_JSON.equals(elem)) { | ||||||
|  | 						data.append("\n\t\t\t\tcontentType: HTTPMimeType.JSON,"); | ||||||
|  | 						toolImports.add("HTTPMimeType"); | ||||||
|  | 						break; | ||||||
|  | 					} else if (MediaType.MULTIPART_FORM_DATA.equals(elem)) { | ||||||
|  | 						data.append("\n\t\t\t\tcontentType: HTTPMimeType.MULTIPART,"); | ||||||
|  | 						toolImports.add("HTTPMimeType"); | ||||||
|  | 						break; | ||||||
|  | 					} else if (MediaType.TEXT_PLAIN.equals(elem)) { | ||||||
|  | 						data.append("\n\t\t\t\tcontentType: HTTPMimeType.TEXT_PLAIN,"); | ||||||
|  | 						toolImports.add("HTTPMimeType"); | ||||||
|  | 						break; | ||||||
|  | 					} | ||||||
|  | 				} | ||||||
|  | 			} else if (RestTypeRequest.DELETE.equals(interfaceElement.restTypeRequest)) { | ||||||
|  | 				data.append("\n\t\t\t\tcontentType: HTTPMimeType.TEXT_PLAIN,"); | ||||||
|  | 				toolImports.add("HTTPMimeType"); | ||||||
|  | 			} | ||||||
|  | 			if (produces != null) { | ||||||
|  | 				if (produces.size() > 1) { | ||||||
|  | 					data.append("\n\t\t\t\taccept: produce,"); | ||||||
|  | 				} else { | ||||||
|  | 					final String returnType = generateClassModelsTypescript(interfaceElement.returnTypes, dotGroup, | ||||||
|  | 							imports, false); | ||||||
|  | 					if (!"void".equals(returnType)) { | ||||||
|  | 						for (final String elem : produces) { | ||||||
|  | 							if (MediaType.APPLICATION_JSON.equals(elem)) { | ||||||
|  | 								data.append("\n\t\t\t\taccept: HTTPMimeType.JSON,"); | ||||||
|  | 								toolImports.add("HTTPMimeType"); | ||||||
|  | 								break; | ||||||
|  | 							} | ||||||
|  | 						} | ||||||
|  | 					} | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 			data.append("\n\t\t\t},"); | ||||||
|  | 			data.append("\n\t\t\trestConfig,"); | ||||||
|  | 			if (!interfaceElement.parameters.isEmpty()) { | ||||||
|  | 				data.append("\n\t\t\tparams,"); | ||||||
|  | 			} | ||||||
|  | 			if (!interfaceElement.queries.isEmpty()) { | ||||||
|  | 				data.append("\n\t\t\tqueries,"); | ||||||
|  | 			} | ||||||
|  | 			if (interfaceElement.unnamedElement.size() == 1) { | ||||||
|  | 				data.append("\n\t\t\tdata,"); | ||||||
|  | 			} else if (interfaceElement.multiPartParameters.size() != 0) { | ||||||
|  | 				data.append("\n\t\t\tdata,"); | ||||||
|  | 			} | ||||||
|  | 			if (needGenerateProgress) { | ||||||
|  | 				data.append("\n\t\t\tcallback,"); | ||||||
|  | 			} | ||||||
|  | 			data.append("\n\t\t}"); | ||||||
|  | 			if (returnComplexModel != null) { | ||||||
|  | 				data.append(", is"); | ||||||
|  | 				data.append(returnModelNameIfComplex); | ||||||
|  | 			} else { | ||||||
|  | 				final DotClassElement retType = dotGroup.find(interfaceElement.returnTypes.get(0)); | ||||||
|  | 				if (retType.dotCheckType != null) { | ||||||
|  | 					data.append(", "); | ||||||
|  | 					data.append(retType.dotCheckType); | ||||||
|  | 					imports.add(interfaceElement.returnTypes.get(0)); | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 			*/ | ||||||
|  | 			data.append("</td></tr>\n"); | ||||||
|  | 		} | ||||||
|  | 		/* | ||||||
|  | 		data.append("\n}\n"); | ||||||
|  |  | ||||||
|  | 		final StringBuilder out = new StringBuilder(); | ||||||
|  |  | ||||||
|  | 		final List<String> toolImportsList = new ArrayList<>(toolImports); | ||||||
|  | 		Collections.sort(toolImportsList); | ||||||
|  | 		if (toolImportsList.size() != 0) { | ||||||
|  | 			out.append("import {"); | ||||||
|  | 			for (final String elem : toolImportsList) { | ||||||
|  | 				out.append("\n\t"); | ||||||
|  | 				out.append(elem); | ||||||
|  | 				out.append(","); | ||||||
|  | 			} | ||||||
|  | 			out.append("\n} from \"../rest-tools\";\n\n"); | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		if (zodImports.size() != 0) { | ||||||
|  | 			out.append("import { z as zod } from \"zod\"\n"); | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		final Set<String> finalImportSet = new TreeSet<>(); | ||||||
|  |  | ||||||
|  | 		for (final ClassModel model : imports) { | ||||||
|  | 			final DotClassElement dotModel = dotGroup.find(model); | ||||||
|  | 			if (dotModel.nativeType == DefinedPosition.NATIVE) { | ||||||
|  | 				continue; | ||||||
|  | 			} | ||||||
|  | 			finalImportSet.add(dotModel.dotTypeName); | ||||||
|  | 		} | ||||||
|  | 		for (final ClassModel model : isImports) { | ||||||
|  | 			final DotClassElement dotModel = dotGroup.find(model); | ||||||
|  | 			if (dotModel.nativeType == DefinedPosition.NATIVE) { | ||||||
|  | 				continue; | ||||||
|  | 			} | ||||||
|  | 			if (dotModel.dotCheckType != null) { | ||||||
|  | 				finalImportSet.add(dotModel.dotCheckType); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		for (final ClassModel model : zodImports) { | ||||||
|  | 			final DotClassElement dotModel = dotGroup.find(model); | ||||||
|  | 			if (dotModel.nativeType == DefinedPosition.NATIVE) { | ||||||
|  | 				continue; | ||||||
|  | 			} | ||||||
|  | 			finalImportSet.add("Zod" + dotModel.dotTypeName); | ||||||
|  | 		} | ||||||
|  | 		for (final ClassModel model : writeImports) { | ||||||
|  | 			final DotClassElement dotModel = dotGroup.find(model); | ||||||
|  | 			if (dotModel.nativeType == DefinedPosition.NATIVE) { | ||||||
|  | 				continue; | ||||||
|  | 			} | ||||||
|  | 			finalImportSet.add(dotModel.dotTypeName + "Write"); | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		if (finalImportSet.size() != 0) { | ||||||
|  | 			out.append("import {"); | ||||||
|  | 			for (final String elem : finalImportSet) { | ||||||
|  | 				out.append("\n\t"); | ||||||
|  | 				out.append(elem); | ||||||
|  | 				out.append(","); | ||||||
|  | 			} | ||||||
|  | 			out.append("\n} from \"../model\";\n\n"); | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		out.append(data.toString()); | ||||||
|  | 		*/ | ||||||
|  |  | ||||||
|  | 		data.append(""" | ||||||
|  | 									</table> | ||||||
|  | 								</td> | ||||||
|  | 							</tr> | ||||||
|  | 						</table>> | ||||||
|  | 					] | ||||||
|  | 				"""); | ||||||
|  | 		data.append(outLinks.toString()); | ||||||
|  | 		return data.toString(); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | } | ||||||
							
								
								
									
										485
									
								
								src/org/kar/archidata/externalRestApi/dot/DotClassElement.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										485
									
								
								src/org/kar/archidata/externalRestApi/dot/DotClassElement.java
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,485 @@ | |||||||
|  | package org.kar.archidata.externalRestApi.dot; | ||||||
|  |  | ||||||
|  | import java.io.IOException; | ||||||
|  | import java.util.List; | ||||||
|  | import java.util.Map.Entry; | ||||||
|  |  | ||||||
|  | import org.kar.archidata.externalRestApi.model.ClassEnumModel; | ||||||
|  | import org.kar.archidata.externalRestApi.model.ClassListModel; | ||||||
|  | import org.kar.archidata.externalRestApi.model.ClassMapModel; | ||||||
|  | import org.kar.archidata.externalRestApi.model.ClassModel; | ||||||
|  | import org.kar.archidata.externalRestApi.model.ClassObjectModel; | ||||||
|  | import org.kar.archidata.externalRestApi.model.ClassObjectModel.FieldProperty; | ||||||
|  | import org.slf4j.Logger; | ||||||
|  | import org.slf4j.LoggerFactory; | ||||||
|  |  | ||||||
|  | public class DotClassElement { | ||||||
|  | 	static final Logger LOGGER = LoggerFactory.getLogger(DotClassElement.class); | ||||||
|  |  | ||||||
|  | 	public enum DefinedPosition { | ||||||
|  | 		NATIVE, // Native element of  dot language. | ||||||
|  | 		BASIC, // basic wrapping for JAVA type. | ||||||
|  | 		NORMAL // Normal Object to interpret. | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public List<ClassModel> models; | ||||||
|  | 	public String zodName; | ||||||
|  | 	public String dotTypeName; | ||||||
|  | 	public String dotCheckType; | ||||||
|  | 	public String declaration; | ||||||
|  | 	public String fileName = null; | ||||||
|  | 	public String comment = null; | ||||||
|  | 	public DefinedPosition nativeType = DefinedPosition.NORMAL; | ||||||
|  |  | ||||||
|  | 	public static String determineFileName(final String className) { | ||||||
|  | 		return className.replaceAll("([a-z])([A-Z])", "$1-$2").replaceAll("([A-Z])([A-Z][a-z])", "$1-$2").toLowerCase(); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public DotClassElement(final List<ClassModel> model, final String zodName, final String dotTypeName, | ||||||
|  | 			final String dotCheckType, final String declaration, final DefinedPosition nativeType) { | ||||||
|  | 		this.models = model; | ||||||
|  | 		this.zodName = zodName; | ||||||
|  | 		this.dotTypeName = dotTypeName; | ||||||
|  | 		this.declaration = declaration; | ||||||
|  | 		this.nativeType = nativeType; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public DotClassElement(final ClassModel model) { | ||||||
|  | 		this.models = List.of(model); | ||||||
|  | 		this.dotTypeName = model.getOriginClasses().getSimpleName(); | ||||||
|  | 		this.declaration = null; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public boolean isCompatible(final ClassModel model) { | ||||||
|  | 		return this.models.contains(model); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public String generateEnum(final ClassEnumModel model, final DotClassElementGroup dotGroup) throws IOException { | ||||||
|  | 		final StringBuilder out = new StringBuilder(); | ||||||
|  | 		out.append(""" | ||||||
|  | 					%s [ | ||||||
|  | 						shape=plain | ||||||
|  | 						label=<<table color="#33FF33" border="2" cellborder="1" cellspacing="0" cellpadding="4"> | ||||||
|  | 							<tr> | ||||||
|  | 								<td port="NAME"><b>%s</b><br/>(ENUM)</td> | ||||||
|  | 							</tr> | ||||||
|  | 							<tr> | ||||||
|  | 								<td> | ||||||
|  | 									<table border="0" cellborder="0" cellspacing="0" > | ||||||
|  | 				""".formatted(this.dotTypeName, this.dotTypeName)); | ||||||
|  | 		final boolean first = true; | ||||||
|  | 		for (final Entry<String, Object> elem : model.getListOfValues().entrySet()) { | ||||||
|  | 			out.append("\t\t\t\t\t\t<tr><td  align=\"left\"><b> + "); | ||||||
|  | 			out.append(elem.getKey()); | ||||||
|  | 			out.append("</b> = "); | ||||||
|  | 			if (elem.getValue() instanceof final Integer value) { | ||||||
|  | 				out.append(value); | ||||||
|  | 			} else { | ||||||
|  | 				out.append("'"); | ||||||
|  | 				out.append(elem.getValue()); | ||||||
|  | 				out.append("'"); | ||||||
|  | 			} | ||||||
|  | 			out.append("</td></tr>\n"); | ||||||
|  | 		} | ||||||
|  | 		out.append(""" | ||||||
|  | 									</table> | ||||||
|  | 								</td> | ||||||
|  | 							</tr> | ||||||
|  | 						</table>> | ||||||
|  | 					] | ||||||
|  | 				"""); | ||||||
|  | 		return out.toString(); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public String generateImporDot(final List<ClassModel> depModels, final DotClassElementGroup dotGroup) | ||||||
|  | 			throws IOException { | ||||||
|  | 		final StringBuilder out = new StringBuilder(); | ||||||
|  | 		for (final ClassModel depModel : depModels) { | ||||||
|  | 			final DotClassElement dotModel = dotGroup.find(depModel); | ||||||
|  | 			if (dotModel.nativeType != DefinedPosition.NATIVE) { | ||||||
|  | 				out.append("import {"); | ||||||
|  | 				out.append(dotModel.zodName); | ||||||
|  | 				out.append("} from \"./"); | ||||||
|  | 				out.append(dotModel.fileName); | ||||||
|  | 				out.append("\";\n"); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		return out.toString(); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	private Object generateComment(final ClassObjectModel model) { | ||||||
|  | 		final StringBuilder out = new StringBuilder(); | ||||||
|  | 		if (model.getDescription() != null || model.getExample() != null) { | ||||||
|  | 			out.append("/**\n"); | ||||||
|  | 			if (model.getDescription() != null) { | ||||||
|  | 				for (final String elem : model.getDescription().split("\n")) { | ||||||
|  | 					out.append(" * "); | ||||||
|  | 					out.append(elem); | ||||||
|  | 					out.append("\n"); | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 			if (model.getExample() != null) { | ||||||
|  | 				out.append(" * Example:\n"); | ||||||
|  | 				out.append(" * ```\n"); | ||||||
|  | 				for (final String elem : model.getExample().split("\n")) { | ||||||
|  | 					out.append(" * "); | ||||||
|  | 					out.append(elem); | ||||||
|  | 					out.append("\n"); | ||||||
|  | 				} | ||||||
|  | 				out.append(" * ```\n"); | ||||||
|  | 			} | ||||||
|  | 			out.append(" */\n"); | ||||||
|  | 		} | ||||||
|  | 		return out.toString(); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public String optionalTypeZod(final FieldProperty field) { | ||||||
|  | 		// Common checking element (apply to List, Map, ...) | ||||||
|  | 		if (field.nullable()) { | ||||||
|  | 			return ".optional()"; | ||||||
|  | 		} | ||||||
|  | 		if (field.notNull()) { | ||||||
|  | 			return ""; | ||||||
|  | 		} | ||||||
|  | 		// Other object: | ||||||
|  | 		if (field.model().getOriginClasses() == null || field.model().getOriginClasses().isPrimitive()) { | ||||||
|  | 			return ""; | ||||||
|  | 		} | ||||||
|  | 		if (field.columnNotNull()) { | ||||||
|  | 			return ""; | ||||||
|  | 		} | ||||||
|  | 		return ".optional()"; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public String maxSizeZod(final FieldProperty field) { | ||||||
|  | 		final StringBuilder builder = new StringBuilder(); | ||||||
|  | 		final Class<?> clazz = field.model().getOriginClasses(); | ||||||
|  | 		if (clazz == String.class) { | ||||||
|  | 			if (field.sizeMin() > 0) { | ||||||
|  | 				builder.append(".min("); | ||||||
|  | 				builder.append(field.sizeMin()); | ||||||
|  | 				builder.append(")"); | ||||||
|  | 			} | ||||||
|  | 			if (field.sizeMax() > 0) { | ||||||
|  | 				builder.append(".max("); | ||||||
|  | 				builder.append(field.sizeMax()); | ||||||
|  | 				builder.append(")"); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		if (clazz == short.class || clazz == Short.class || clazz == int.class || clazz == Integer.class | ||||||
|  | 				|| clazz == long.class || clazz == Long.class || clazz == float.class || clazz == Float.class | ||||||
|  | 				|| clazz == double.class || clazz == Double.class) { | ||||||
|  | 			if (field.min() != null && field.min() > 0) { | ||||||
|  | 				builder.append(".min("); | ||||||
|  | 				builder.append(field.min()); | ||||||
|  | 				builder.append(")"); | ||||||
|  | 			} | ||||||
|  | 			if (field.max() != null && field.max() > 0) { | ||||||
|  | 				builder.append(".max("); | ||||||
|  | 				builder.append(field.max()); | ||||||
|  | 				builder.append(")"); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		return builder.toString(); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public String readOnlyZod(final FieldProperty field) { | ||||||
|  | 		if (field.readOnly()) { | ||||||
|  | 			return ".readonly()"; | ||||||
|  | 		} | ||||||
|  | 		return ""; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public String generateBaseObject() { | ||||||
|  | 		final StringBuilder out = new StringBuilder(); | ||||||
|  | 		return out.toString(); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public String convertHtml(final String data) { | ||||||
|  | 		return data.replace("<", "<").replace(">", ">"); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static String generateClassModelTypescript(final ClassModel model, final DotClassElementGroup dotGroup) | ||||||
|  | 			throws IOException { | ||||||
|  | 		if (model instanceof ClassEnumModel) { | ||||||
|  | 			final DotClassElement dotFieldModel = dotGroup.find(model); | ||||||
|  | 			return dotFieldModel.dotTypeName; | ||||||
|  | 		} else if (model instanceof ClassObjectModel) { | ||||||
|  | 			final DotClassElement dotFieldModel = dotGroup.find(model); | ||||||
|  | 			return dotFieldModel.dotTypeName; | ||||||
|  | 		} else if (model instanceof final ClassListModel fieldListModel) { | ||||||
|  | 			return generateDotList(fieldListModel, dotGroup); | ||||||
|  | 		} else if (model instanceof final ClassMapModel fieldMapModel) { | ||||||
|  | 			return generateDotMap(fieldMapModel, dotGroup); | ||||||
|  | 		} | ||||||
|  | 		throw new IOException("Impossible model:" + model); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static String generateClassModelTypescriptLink(final ClassModel model, final DotClassElementGroup dotGroup) | ||||||
|  | 			throws IOException { | ||||||
|  | 		if (model instanceof ClassEnumModel) { | ||||||
|  | 			final DotClassElement dotFieldModel = dotGroup.find(model); | ||||||
|  | 			return dotFieldModel.dotTypeName; | ||||||
|  | 		} else if (model instanceof ClassObjectModel) { | ||||||
|  | 			final DotClassElement dotFieldModel = dotGroup.find(model); | ||||||
|  | 			if (dotFieldModel.nativeType == DefinedPosition.NORMAL) { | ||||||
|  | 				return dotFieldModel.dotTypeName; | ||||||
|  | 			} | ||||||
|  | 		} else if (model instanceof final ClassListModel fieldListModel) { | ||||||
|  | 			final String className = generateDotListClassName(fieldListModel, dotGroup); | ||||||
|  | 			if (className != null) { | ||||||
|  | 				return className; | ||||||
|  | 			} | ||||||
|  | 		} else if (model instanceof final ClassMapModel fieldMapModel) { | ||||||
|  | 			final String className = generateDotMapClassName(fieldMapModel, dotGroup); | ||||||
|  | 			if (className != null) { | ||||||
|  | 				return className; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		return null; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public String generateObject(final ClassObjectModel model, final DotClassElementGroup dotGroup) throws IOException { | ||||||
|  | 		final StringBuilder out = new StringBuilder(); | ||||||
|  | 		final StringBuilder outLinks = new StringBuilder(); | ||||||
|  | 		out.append(""" | ||||||
|  | 					%s [ | ||||||
|  | 						shape=plain | ||||||
|  | 						ranksep="2" | ||||||
|  | 						label=<<table color="#000000" border="2" cellborder="1" cellspacing="0" cellpadding="4"> | ||||||
|  | 							<tr> | ||||||
|  | 								<td port="NAME"><b>%s</b></td> | ||||||
|  | 							</tr> | ||||||
|  | 							<tr> | ||||||
|  | 								<td> | ||||||
|  | 									<table border="0" cellborder="0" cellspacing="0" > | ||||||
|  | 				""".formatted(this.dotTypeName, this.dotTypeName)); | ||||||
|  | 		String inheritence = null; | ||||||
|  | 		if (model.getExtendsClass() != null) { | ||||||
|  | 			final ClassModel parentClass = model.getExtendsClass(); | ||||||
|  | 			final DotClassElement dotParentModel = dotGroup.find(parentClass); | ||||||
|  | 			inheritence = dotParentModel.dotTypeName; | ||||||
|  | 		} | ||||||
|  | 		if (model.getFields().size() == 0) { | ||||||
|  | 			out.append("\t\t\t\t\t\t<tr><td> <i>(empty)</i> </td></tr>"); | ||||||
|  | 		} | ||||||
|  | 		for (final FieldProperty field : model.getFields()) { | ||||||
|  | 			final ClassModel fieldModel = field.model(); | ||||||
|  | 			if (field.comment() != null) { | ||||||
|  | 				out.append("\t\t\t\t\t\t<tr><td  align=\"left\"><i> // "); | ||||||
|  | 				out.append(convertHtml(field.comment())); | ||||||
|  | 				out.append("</i></td></tr>\n"); | ||||||
|  | 			} | ||||||
|  | 			out.append("\t\t\t\t\t\t<tr><td  align=\"left\" port=\""); | ||||||
|  | 			out.append(field.name()); | ||||||
|  | 			out.append("\"><b> + "); | ||||||
|  | 			out.append(field.name()); | ||||||
|  | 			out.append("</b>: "); | ||||||
|  |  | ||||||
|  | 			out.append(generateClassModelTypescript(fieldModel, dotGroup)); | ||||||
|  | 			final String remoteType = generateClassModelTypescriptLink(fieldModel, dotGroup); | ||||||
|  | 			if (remoteType != null) { | ||||||
|  | 				outLinks.append("\t"); | ||||||
|  | 				outLinks.append(this.dotTypeName); | ||||||
|  | 				outLinks.append(":"); | ||||||
|  | 				outLinks.append(field.name()); | ||||||
|  | 				outLinks.append(":e -> "); | ||||||
|  | 				outLinks.append(remoteType); | ||||||
|  | 				outLinks.append(":NAME:w\n"); | ||||||
|  | 			} else if (field.linkClass() != null) { | ||||||
|  | 				final String remoteLinkType = generateClassModelTypescriptLink(field.linkClass(), dotGroup); | ||||||
|  | 				if (remoteLinkType != null) { | ||||||
|  | 					outLinks.append("\t"); | ||||||
|  | 					outLinks.append(this.dotTypeName); | ||||||
|  | 					outLinks.append(":"); | ||||||
|  | 					outLinks.append(field.name()); | ||||||
|  | 					outLinks.append(":e -> "); | ||||||
|  | 					outLinks.append(remoteLinkType); | ||||||
|  | 					outLinks.append(":NAME:w\n"); | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 			out.append("</td></tr>\n"); | ||||||
|  | 		} | ||||||
|  | 		out.append(""" | ||||||
|  | 									</table> | ||||||
|  | 								</td> | ||||||
|  | 							</tr> | ||||||
|  | 						</table>> | ||||||
|  | 					] | ||||||
|  | 				"""); | ||||||
|  | 		if (inheritence != null) { | ||||||
|  | 			out.append("\tedge [dir=back arrowtail=empty arrowsize=2]\n"); | ||||||
|  | 			out.append("\t"); | ||||||
|  | 			out.append(inheritence); | ||||||
|  | 			// heritage stop link on the "s" South | ||||||
|  | 			out.append(":s -> "); | ||||||
|  | 			out.append(this.dotTypeName); | ||||||
|  | 			// heritage start link on the "n" North | ||||||
|  | 			out.append(":n\n"); | ||||||
|  | 		} | ||||||
|  | 		if (!outLinks.isEmpty()) { | ||||||
|  | 			out.append("\tedge [dir=back arrowtail=diamond arrowsize=2]\n"); | ||||||
|  | 			//out.append("\tedge [arrowhead=diamond arrowsize=2]\n"); | ||||||
|  | 			out.append(outLinks.toString()); | ||||||
|  |  | ||||||
|  | 		} | ||||||
|  | 		return out.toString(); | ||||||
|  |  | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	private static String generateDotMap(final ClassMapModel model, final DotClassElementGroup dotGroup) { | ||||||
|  | 		final StringBuilder out = new StringBuilder(); | ||||||
|  | 		out.append("Map<"); | ||||||
|  | 		if (model.keyModel instanceof final ClassListModel fieldListModel) { | ||||||
|  | 			final String tmp = generateDotList(fieldListModel, dotGroup); | ||||||
|  | 			out.append(tmp); | ||||||
|  | 		} else if (model.keyModel instanceof final ClassMapModel fieldMapModel) { | ||||||
|  | 			final String tmp = generateDotMap(fieldMapModel, dotGroup); | ||||||
|  | 			out.append(tmp); | ||||||
|  | 		} else if (model.keyModel instanceof final ClassObjectModel fieldObjectModel) { | ||||||
|  | 			final String tmp = generateDotObject(fieldObjectModel, dotGroup); | ||||||
|  | 			out.append(tmp); | ||||||
|  | 		} else if (model.keyModel instanceof final ClassEnumModel fieldEnumModel) { | ||||||
|  | 			final String tmp = generateDotEnum(fieldEnumModel, dotGroup); | ||||||
|  | 			out.append(tmp); | ||||||
|  | 		} | ||||||
|  | 		out.append(", "); | ||||||
|  | 		if (model.valueModel instanceof final ClassListModel fieldListModel) { | ||||||
|  | 			final String tmp = generateDotList(fieldListModel, dotGroup); | ||||||
|  | 			out.append(tmp); | ||||||
|  | 		} else if (model.valueModel instanceof final ClassMapModel fieldMapModel) { | ||||||
|  | 			final String tmp = generateDotMap(fieldMapModel, dotGroup); | ||||||
|  | 			out.append(tmp); | ||||||
|  | 		} else if (model.valueModel instanceof final ClassObjectModel fieldObjectModel) { | ||||||
|  | 			final String tmp = generateDotObject(fieldObjectModel, dotGroup); | ||||||
|  | 			out.append(tmp); | ||||||
|  | 		} else if (model.valueModel instanceof final ClassEnumModel fieldEnumModel) { | ||||||
|  | 			final String tmp = generateDotEnum(fieldEnumModel, dotGroup); | ||||||
|  | 			out.append(tmp); | ||||||
|  | 		} | ||||||
|  | 		out.append(">"); | ||||||
|  | 		return out.toString(); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	private static String generateDotEnum(final ClassEnumModel model, final DotClassElementGroup dotGroup) { | ||||||
|  | 		final DotClassElement dotParentModel = dotGroup.find(model); | ||||||
|  | 		return dotParentModel.dotTypeName; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	private static String generateDotObject(final ClassObjectModel model, final DotClassElementGroup dotGroup) { | ||||||
|  | 		final DotClassElement dotParentModel = dotGroup.find(model); | ||||||
|  | 		return dotParentModel.dotTypeName; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	private static String generateDotObjectClassName( | ||||||
|  | 			final ClassObjectModel model, | ||||||
|  | 			final DotClassElementGroup dotGroup) { | ||||||
|  | 		final DotClassElement dotParentModel = dotGroup.find(model); | ||||||
|  | 		if (dotParentModel.nativeType == DefinedPosition.NORMAL) { | ||||||
|  | 			return dotParentModel.dotTypeName; | ||||||
|  | 		} | ||||||
|  | 		return null; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	private static String generateDotListClassName(final ClassListModel model, final DotClassElementGroup dotGroup) { | ||||||
|  | 		if (model.valueModel instanceof final ClassListModel fieldListModel) { | ||||||
|  | 			return generateDotListClassName(fieldListModel, dotGroup); | ||||||
|  | 		} else if (model.valueModel instanceof final ClassMapModel fieldMapModel) { | ||||||
|  | 			return generateDotMapClassName(fieldMapModel, dotGroup); | ||||||
|  | 		} else if (model.valueModel instanceof final ClassObjectModel fieldObjectModel) { | ||||||
|  | 			return generateDotObjectClassName(fieldObjectModel, dotGroup); | ||||||
|  | 		} | ||||||
|  | 		return null; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	private static String generateDotMapClassName(final ClassMapModel model, final DotClassElementGroup dotGroup) { | ||||||
|  | 		if (model.valueModel instanceof final ClassListModel fieldListModel) { | ||||||
|  | 			return generateDotListClassName(fieldListModel, dotGroup); | ||||||
|  | 		} else if (model.valueModel instanceof final ClassMapModel fieldMapModel) { | ||||||
|  | 			return generateDotMapClassName(fieldMapModel, dotGroup); | ||||||
|  | 		} else if (model.valueModel instanceof final ClassObjectModel fieldObjectModel) { | ||||||
|  | 			return generateDotObjectClassName(fieldObjectModel, dotGroup); | ||||||
|  | 		} else if (model.valueModel instanceof final ClassEnumModel fieldEnumModel) { | ||||||
|  | 			return generateDotEnum(fieldEnumModel, dotGroup); | ||||||
|  | 		} | ||||||
|  | 		return null; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	private static String generateDotList(final ClassListModel model, final DotClassElementGroup dotGroup) { | ||||||
|  | 		final StringBuilder out = new StringBuilder(); | ||||||
|  | 		out.append("List<"); | ||||||
|  | 		if (model.valueModel instanceof final ClassListModel fieldListModel) { | ||||||
|  | 			final String tmp = generateDotList(fieldListModel, dotGroup); | ||||||
|  | 			out.append(tmp); | ||||||
|  | 		} else if (model.valueModel instanceof final ClassMapModel fieldMapModel) { | ||||||
|  | 			final String tmp = generateDotMap(fieldMapModel, dotGroup); | ||||||
|  | 			out.append(tmp); | ||||||
|  | 		} else if (model.valueModel instanceof final ClassObjectModel fieldObjectModel) { | ||||||
|  | 			final String tmp = generateDotObject(fieldObjectModel, dotGroup); | ||||||
|  | 			out.append(tmp); | ||||||
|  | 		} | ||||||
|  | 		out.append(">"); | ||||||
|  | 		return out.toString(); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public String generateFile(final DotClassElementGroup dotGroup) throws IOException { | ||||||
|  | 		if (this.nativeType == DefinedPosition.NATIVE) { | ||||||
|  | 			return ""; | ||||||
|  | 		} | ||||||
|  | 		final ClassModel model = this.models.get(0); | ||||||
|  | 		String data = ""; | ||||||
|  | 		if (this.nativeType == DefinedPosition.BASIC && model instanceof ClassObjectModel) { | ||||||
|  | 			// nothing to do___ data = generateBaseObject(); | ||||||
|  | 		} else if (model instanceof final ClassEnumModel modelEnum) { | ||||||
|  | 			data = generateEnum(modelEnum, dotGroup); | ||||||
|  | 		} else if (model instanceof final ClassObjectModel modelObject) { | ||||||
|  | 			data = generateObject(modelObject, dotGroup); | ||||||
|  | 		} | ||||||
|  | 		return data; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	private static String generateLocalModelBase(final ClassModel model, final DotClassElementGroup dotGroup) | ||||||
|  | 			throws IOException { | ||||||
|  | 		if (model instanceof final ClassObjectModel objectModel) { | ||||||
|  | 			return generateDotObject(objectModel, dotGroup); | ||||||
|  | 		} | ||||||
|  | 		if (model instanceof final ClassEnumModel enumModel) { | ||||||
|  | 			return generateDotEnum(enumModel, dotGroup); | ||||||
|  | 		} | ||||||
|  | 		if (model instanceof final ClassListModel listModel) { | ||||||
|  | 			return generateDotList(listModel, dotGroup); | ||||||
|  | 		} | ||||||
|  | 		if (model instanceof final ClassMapModel mapModel) { | ||||||
|  | 			return generateDotMap(mapModel, dotGroup); | ||||||
|  | 		} | ||||||
|  | 		return ""; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static String generateLocalModel( | ||||||
|  | 			final String ModelName, | ||||||
|  | 			final List<ClassModel> models, | ||||||
|  | 			final DotClassElementGroup dotGroup) throws IOException { | ||||||
|  | 		if (models.size() == 1) { | ||||||
|  | 			if (models.get(0) instanceof ClassObjectModel) { | ||||||
|  | 				return null; | ||||||
|  | 			} | ||||||
|  | 			if (models.get(0) instanceof ClassEnumModel) { | ||||||
|  | 				return null; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		final StringBuilder out = new StringBuilder(); | ||||||
|  | 		if (models.size() == 1) { | ||||||
|  | 			out.append(generateLocalModelBase(models.get(0), dotGroup)); | ||||||
|  | 		} else { | ||||||
|  | 			out.append("Union<"); | ||||||
|  | 			for (final ClassModel model : models) { | ||||||
|  | 				out.append("\t"); | ||||||
|  | 				out.append(generateLocalModelBase(models.get(0), dotGroup)); | ||||||
|  | 				out.append(",\n"); | ||||||
|  | 			} | ||||||
|  | 			out.append(">"); | ||||||
|  | 		} | ||||||
|  | 		return out.toString(); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | } | ||||||
| @@ -0,0 +1,27 @@ | |||||||
|  | package org.kar.archidata.externalRestApi.dot; | ||||||
|  |  | ||||||
|  | import java.util.List; | ||||||
|  |  | ||||||
|  | import org.kar.archidata.externalRestApi.model.ClassModel; | ||||||
|  |  | ||||||
|  | public class DotClassElementGroup { | ||||||
|  | 	private final List<DotClassElement> dotElements; | ||||||
|  |  | ||||||
|  | 	public List<DotClassElement> getDotElements() { | ||||||
|  | 		return this.dotElements; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public DotClassElementGroup(final List<DotClassElement> tsElements) { | ||||||
|  | 		this.dotElements = tsElements; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public DotClassElement find(final ClassModel model) { | ||||||
|  | 		for (final DotClassElement elem : this.dotElements) { | ||||||
|  | 			if (elem.isCompatible(model)) { | ||||||
|  | 				return elem; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		return null; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | } | ||||||
| @@ -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); | ||||||
|   | |||||||
| @@ -8,6 +8,7 @@ import java.util.List; | |||||||
|  |  | ||||||
| import org.glassfish.jersey.media.multipart.FormDataParam; | import org.glassfish.jersey.media.multipart.FormDataParam; | ||||||
| import org.kar.archidata.annotation.AsyncType; | import org.kar.archidata.annotation.AsyncType; | ||||||
|  | import org.kar.archidata.annotation.FormDataOptional; | ||||||
| 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; | ||||||
| @@ -144,6 +145,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) { | ||||||
|   | |||||||
| @@ -15,6 +15,9 @@ import org.kar.archidata.exception.DataAccessException; | |||||||
| import org.slf4j.Logger; | import org.slf4j.Logger; | ||||||
| import org.slf4j.LoggerFactory; | import org.slf4j.LoggerFactory; | ||||||
|  |  | ||||||
|  | import jakarta.persistence.ManyToMany; | ||||||
|  | import jakarta.persistence.ManyToOne; | ||||||
|  | import jakarta.persistence.OneToMany; | ||||||
| import jakarta.validation.constraints.Size; | import jakarta.validation.constraints.Size; | ||||||
|  |  | ||||||
| public class ClassObjectModel extends ClassModel { | public class ClassObjectModel extends ClassModel { | ||||||
| @@ -56,6 +59,7 @@ public class ClassObjectModel extends ClassModel { | |||||||
| 	public record FieldProperty( | 	public record FieldProperty( | ||||||
| 			String name, | 			String name, | ||||||
| 			ClassModel model, | 			ClassModel model, | ||||||
|  | 			ClassModel linkClass, // link class when use remote ID (ex: list<UUID>) | ||||||
| 			String comment, | 			String comment, | ||||||
| 			int sizeMin, // String SizeMin | 			int sizeMin, // String SizeMin | ||||||
| 			int sizeMax, // String SizeMax | 			int sizeMax, // String SizeMax | ||||||
| @@ -66,11 +70,12 @@ public class ClassObjectModel extends ClassModel { | |||||||
| 			Boolean columnNotNull, | 			Boolean columnNotNull, | ||||||
| 			Boolean nullable) { | 			Boolean nullable) { | ||||||
|  |  | ||||||
| 		public FieldProperty(final String name, final ClassModel model, final String comment, final int sizeMin, | 		public FieldProperty(final String name, final ClassModel model, final ClassModel linkClass, | ||||||
| 				final int sizeMax, final Long min, final Long max, final Boolean readOnly, final Boolean notNull, | 				final String comment, final int sizeMin, final int sizeMax, final Long min, final Long max, | ||||||
| 				final Boolean columnNotNull, final Boolean nullable) { | 				final Boolean readOnly, final Boolean notNull, final Boolean columnNotNull, final Boolean nullable) { | ||||||
| 			this.name = name; | 			this.name = name; | ||||||
| 			this.model = model; | 			this.model = model; | ||||||
|  | 			this.linkClass = linkClass; | ||||||
| 			this.comment = comment; | 			this.comment = comment; | ||||||
| 			this.sizeMin = sizeMin; | 			this.sizeMin = sizeMin; | ||||||
| 			this.sizeMax = sizeMax; | 			this.sizeMax = sizeMax; | ||||||
| @@ -85,7 +90,6 @@ public class ClassObjectModel extends ClassModel { | |||||||
|  |  | ||||||
| 		private static int getStringMinSize(final Field field) throws DataAccessException { | 		private static int getStringMinSize(final Field field) throws DataAccessException { | ||||||
| 			final Size size = AnnotationTools.getConstraintsSize(field); | 			final Size size = AnnotationTools.getConstraintsSize(field); | ||||||
| 			final int colomnLimitSize = AnnotationTools.getLimitSize(field); |  | ||||||
| 			return size != null ? size.min() : 0; | 			return size != null ? size.min() : 0; | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| @@ -95,9 +99,43 @@ public class ClassObjectModel extends ClassModel { | |||||||
| 			return size == null ? colomnLimitSize : colomnLimitSize < size.max() ? colomnLimitSize : size.max(); | 			return size == null ? colomnLimitSize : colomnLimitSize < size.max() ? colomnLimitSize : size.max(); | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|  | 		private static Class<?> getSubModelIfExist2(final Field field) { | ||||||
|  | 			final ManyToOne manyToOne = AnnotationTools.getManyToOne(field); | ||||||
|  | 			if (manyToOne != null) { | ||||||
|  | 				if (manyToOne.targetEntity() != null && manyToOne.targetEntity() != void.class) { | ||||||
|  | 					return manyToOne.targetEntity(); | ||||||
|  | 				} | ||||||
|  | 				return null; | ||||||
|  | 			} | ||||||
|  | 			final ManyToMany manyToMany = AnnotationTools.getManyToMany(field); | ||||||
|  | 			if (manyToMany != null) { | ||||||
|  | 				if (manyToMany.targetEntity() != null && manyToMany.targetEntity() != void.class) { | ||||||
|  | 					return manyToMany.targetEntity(); | ||||||
|  | 				} | ||||||
|  | 				return null; | ||||||
|  | 			} | ||||||
|  | 			final OneToMany oneToMany = AnnotationTools.getOneToMany(field); | ||||||
|  | 			if (oneToMany != null) { | ||||||
|  | 				if (oneToMany.targetEntity() != null && oneToMany.targetEntity() != void.class) { | ||||||
|  | 					return oneToMany.targetEntity(); | ||||||
|  | 				} | ||||||
|  | 				return null; | ||||||
|  | 			} | ||||||
|  | 			return null; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		private static ClassModel getSubModelIfExist(final Field field, final ModelGroup previous) throws IOException { | ||||||
|  | 			final Class<?> tmp = getSubModelIfExist2(field); | ||||||
|  | 			if (tmp == null) { | ||||||
|  | 				return null; | ||||||
|  | 			} | ||||||
|  | 			return ClassModel.getModel(tmp, previous); | ||||||
|  | 		} | ||||||
|  |  | ||||||
| 		public FieldProperty(final Field field, final ModelGroup previous) throws DataAccessException, IOException { | 		public FieldProperty(final Field field, final ModelGroup previous) throws DataAccessException, IOException { | ||||||
| 			this(field.getName(), // | 			this(field.getName(), // | ||||||
| 					ClassModel.getModel(field.getGenericType(), previous), // | 					ClassModel.getModel(field.getGenericType(), previous), // | ||||||
|  | 					getSubModelIfExist(field, previous), // | ||||||
| 					AnnotationTools.getComment(field), // | 					AnnotationTools.getComment(field), // | ||||||
| 					getStringMinSize(field), // | 					getStringMinSize(field), // | ||||||
| 					getStringMaxSize(field), // | 					getStringMaxSize(field), // | ||||||
|   | |||||||
| @@ -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; | ||||||
| @@ -192,7 +196,7 @@ public class TsApiGeneration { | |||||||
| 				data.append("\n\t\t\tdata,"); | 				data.append("\n\t\t\tdata,"); | ||||||
| 			} | 			} | ||||||
| 			if (needGenerateProgress) { | 			if (needGenerateProgress) { | ||||||
| 				data.append("\n\t\t\tcallback,"); | 				data.append("\n\t\t\tcallbacks,"); | ||||||
| 			} | 			} | ||||||
| 			data.append("\n\t\t}: {"); | 			data.append("\n\t\t}: {"); | ||||||
| 			data.append("\n\t\trestConfig: RESTConfig,"); | 			data.append("\n\t\trestConfig: RESTConfig,"); | ||||||
| @@ -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},"); | ||||||
| @@ -350,7 +358,7 @@ public class TsApiGeneration { | |||||||
| 				data.append("\n\t\t\tdata,"); | 				data.append("\n\t\t\tdata,"); | ||||||
| 			} | 			} | ||||||
| 			if (needGenerateProgress) { | 			if (needGenerateProgress) { | ||||||
| 				data.append("\n\t\t\tcallback,"); | 				data.append("\n\t\t\tcallbacks,"); | ||||||
| 			} | 			} | ||||||
| 			data.append("\n\t\t}"); | 			data.append("\n\t\t}"); | ||||||
| 			if (returnComplexModel != null) { | 			if (returnComplexModel != null) { | ||||||
| @@ -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"); | ||||||
|   | |||||||
| @@ -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; | ||||||
| @@ -22,10 +24,15 @@ import org.kar.archidata.dataAccess.QueryCondition; | |||||||
| import org.kar.archidata.dataAccess.addOn.AddOnDataJson; | import org.kar.archidata.dataAccess.addOn.AddOnDataJson; | ||||||
| import org.kar.archidata.dataAccess.options.Condition; | import org.kar.archidata.dataAccess.options.Condition; | ||||||
| import org.kar.archidata.dataAccess.options.ReadAllColumn; | import org.kar.archidata.dataAccess.options.ReadAllColumn; | ||||||
|  | import org.kar.archidata.exception.FailException; | ||||||
|  | import org.kar.archidata.exception.InputException; | ||||||
| import org.kar.archidata.model.Data; | 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 { | ||||||
| @@ -35,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))) { | ||||||
| @@ -89,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(); | ||||||
| @@ -128,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); | ||||||
| @@ -141,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))) { | ||||||
| @@ -186,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 | ||||||
| @@ -214,73 +262,138 @@ public class DataTools { | |||||||
| 		return data; | 		return data; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	public static <CLASS_TYPE, ID_TYPE> Response uploadCover( | 	public static String getMimeType(final byte[] data) { | ||||||
| 			final Class<CLASS_TYPE> clazz, | 		final Tika tika = new Tika(); | ||||||
| 			final ID_TYPE id, | 		final String mimeType = tika.detect(data); | ||||||
| 			final InputStream fileInputStream, | 		return mimeType; | ||||||
| 			final FormDataContentDisposition fileMetaData) { |  | ||||||
| 		return uploadCover(clazz, id, fileMetaData.getFileName(), fileInputStream, fileMetaData); |  | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	@Deprecated | 	public static <CLASS_TYPE, ID_TYPE> void uploadCoverFromUri( | ||||||
| 	public static <CLASS_TYPE, ID_TYPE> Response uploadCover( |  | ||||||
| 			final Class<CLASS_TYPE> clazz, | 			final Class<CLASS_TYPE> clazz, | ||||||
| 			final ID_TYPE id, | 			final ID_TYPE id, | ||||||
| 			String fileName, | 			final String url) throws Exception { | ||||||
| 			final InputStream fileInputStream, |  | ||||||
| 			final FormDataContentDisposition fileMetaData) { |  | ||||||
| 		try { |  | ||||||
| 			// correct input string stream : |  | ||||||
| 			fileName = multipartCorrection(fileName); |  | ||||||
|  |  | ||||||
| 			// public NodeSmall uploadFile(final FormDataMultiPart form) { | 		LOGGER.info("    - id: {}", id); | ||||||
| 			LOGGER.info("Upload media file: {}", fileMetaData); | 		LOGGER.info("    - url: {} ", url); | ||||||
| 			LOGGER.info("    - id: {}", id); | 		final CLASS_TYPE media = DataAccess.get(clazz, id); | ||||||
| 			LOGGER.info("    - file_name: ", fileName); | 		if (media == null) { | ||||||
| 			LOGGER.info("    - fileInputStream: {}", fileInputStream); | 			throw new InputException(clazz.getCanonicalName(), | ||||||
| 			LOGGER.info("    - fileMetaData: {}", fileMetaData); | 					"[" + id.toString() + "] Id does not exist or removed..."); | ||||||
| 			final CLASS_TYPE media = DataAccess.get(clazz, id); | 		} | ||||||
| 			if (media == null) { | 		// Download data: | ||||||
| 				return Response.notModified("Media Id does not exist or removed...").build(); |  | ||||||
| 			} | 		final Client client = ClientBuilder.newClient(); | ||||||
|  | 		byte[] dataResponse = null; | ||||||
| 			final long tmpUID = getTmpDataId(); | 		try { | ||||||
| 			final String sha512 = saveTemporaryFile(fileInputStream, tmpUID); | 			final WebTarget target = client.target(url); | ||||||
| 			Data data = getWithSha512(sha512); | 			final Response response = target.request().get(); | ||||||
| 			if (data == null) { | 			if (response.getStatus() != 200) { | ||||||
| 				LOGGER.info("Need to add the data in the BDD ... "); | 				throw new FailException(Response.Status.BAD_GATEWAY, | ||||||
| 				try { | 						clazz.getCanonicalName() + "[" + id.toString() + "] Can not download the media"); | ||||||
| 					data = createNewData(tmpUID, fileName, sha512); | 			} | ||||||
| 				} catch (final IOException ex) { | 			dataResponse = response.readEntity(byte[].class); | ||||||
| 					removeTemporaryFile(tmpUID); | 		} catch (final Exception ex) { | ||||||
| 					ex.printStackTrace(); | 			throw new FailException(Response.Status.INTERNAL_SERVER_ERROR, | ||||||
| 					return Response.notModified("can not create input media").build(); | 					clazz.getCanonicalName() + "[" + id.toString() + "] can not create input media", ex); | ||||||
| 				} catch (final SQLException ex) { | 		} | ||||||
| 					ex.printStackTrace(); | 		if (dataResponse == null) { | ||||||
| 					removeTemporaryFile(tmpUID); | 			throw new FailException(Response.Status.NOT_ACCEPTABLE, | ||||||
| 					return Response.notModified("Error in SQL insertion ...").build(); | 					clazz.getCanonicalName() + "[" + id.toString() + "] Data does not exist"); | ||||||
| 				} | 		} | ||||||
| 			} else if (data.deleted) { | 		if (dataResponse.length == 0 || dataResponse.length == 50 * 1024 * 1024) { | ||||||
| 				LOGGER.error("Data already exist but deleted"); | 			throw new FailException(Response.Status.NOT_ACCEPTABLE, clazz.getCanonicalName() + "[" + id.toString() | ||||||
| 				undelete(data.uuid); | 					+ "] Data size is not correct " + dataResponse.length); | ||||||
| 				data.deleted = false; | 		} | ||||||
| 			} else { |  | ||||||
| 				LOGGER.error("Data already exist ... all good"); | 		final long tmpUID = getTmpDataId(); | ||||||
| 			} | 		final String sha512 = saveTemporaryFile(dataResponse, tmpUID); | ||||||
| 			// Fist step: retrieve all the Id of each parents:... | 		Data data = getWithSha512(sha512); | ||||||
| 			LOGGER.info("Find typeNode"); | 		final String mimeType = getMimeType(dataResponse); | ||||||
| 			if (id instanceof final Long idLong) { | 		if (!Arrays.asList(SUPPORTED_IMAGE_MIME_TYPE).contains(mimeType)) { | ||||||
| 				AddOnDataJson.addLink(clazz, idLong, "covers", data.uuid); | 			throw new FailException(Response.Status.NOT_ACCEPTABLE, | ||||||
| 			} else if (id instanceof final UUID idUUID) { | 					clazz.getCanonicalName() + "[" + id.toString() + "] Data CoverType is not accesptable: " + mimeType | ||||||
| 				AddOnDataJson.addLink(clazz, idUUID, "covers", data.uuid); | 							+ "support only: " + String.join(", ", SUPPORTED_IMAGE_MIME_TYPE)); | ||||||
| 			} else { |  | ||||||
| 				throw new IOException("Fail to add Cover can not detect type..."); | 		} | ||||||
| 			} | 		if (data == null) { | ||||||
| 			return Response.ok(DataAccess.get(clazz, id)).build(); | 			LOGGER.info("Need to add the data in the BDD ... "); | ||||||
| 		} catch (final Exception ex) { | 			try { | ||||||
| 			System.out.println("Cat ann unexpected error ... "); | 				data = createNewData(tmpUID, url, sha512, mimeType); | ||||||
| 			ex.printStackTrace(); | 			} 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( | ||||||
|  | 			final Class<CLASS_TYPE> clazz, | ||||||
|  | 			final ID_TYPE id, | ||||||
|  | 			final InputStream fileInputStream, | ||||||
|  | 			final FormDataContentDisposition fileMetaData) throws Exception { | ||||||
|  | 		// public NodeSmall uploadFile(final FormDataMultiPart form) { | ||||||
|  | 		LOGGER.info("Upload media file: {}", fileMetaData); | ||||||
|  | 		LOGGER.info("    - id: {}", id); | ||||||
|  | 		LOGGER.info("    - file_name: {} ", fileMetaData.getFileName()); | ||||||
|  | 		LOGGER.info("    - fileInputStream: {}", fileInputStream); | ||||||
|  | 		LOGGER.info("    - fileMetaData: {}", fileMetaData); | ||||||
|  | 		final CLASS_TYPE media = DataAccess.get(clazz, id); | ||||||
|  | 		if (media == null) { | ||||||
|  | 			throw new InputException(clazz.getCanonicalName(), | ||||||
|  | 					"[" + id.toString() + "] Id does not exist or removed..."); | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		final long tmpUID = getTmpDataId(); | ||||||
|  | 		final String sha512 = saveTemporaryFile(fileInputStream, tmpUID); | ||||||
|  | 		Data data = getWithSha512(sha512); | ||||||
|  | 		if (data == null) { | ||||||
|  | 			LOGGER.info("Need to add the data in the BDD ... "); | ||||||
|  | 			try { | ||||||
|  | 				data = createNewData(tmpUID, fileMetaData.getFileName(), sha512); | ||||||
|  | 			} 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..."); | ||||||
| 		} | 		} | ||||||
| 		return Response.serverError().build(); |  | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|   | |||||||
| @@ -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); | ||||||
|   | |||||||
| @@ -237,7 +237,7 @@ export function RESTRequest({ | |||||||
|   data, |   data, | ||||||
|   params, |   params, | ||||||
|   queries, |   queries, | ||||||
|   callback, |   callbacks, | ||||||
| }: RESTRequestType): Promise<ModelResponseHttp> { | }: RESTRequestType): Promise<ModelResponseHttp> { | ||||||
|   // Create the URL PATH: |   // Create the URL PATH: | ||||||
|   let generateUrl = RESTUrl({ restModel, restConfig, data, params, queries }); |   let generateUrl = RESTUrl({ restModel, restConfig, data, params, queries }); | ||||||
| @@ -268,10 +268,10 @@ export function RESTRequest({ | |||||||
|   return new Promise((resolve, reject) => { |   return new Promise((resolve, reject) => { | ||||||
|     let action: undefined | Promise<Response> = undefined; |     let action: undefined | Promise<Response> = undefined; | ||||||
|     if ( |     if ( | ||||||
|       isNullOrUndefined(callback) || |       isNullOrUndefined(callbacks) || | ||||||
|       (isNullOrUndefined(callback.progressDownload) && |       (isNullOrUndefined(callbacks.progressDownload) && | ||||||
|         isNullOrUndefined(callback.progressUpload) && |         isNullOrUndefined(callbacks.progressUpload) && | ||||||
|         isNullOrUndefined(callback.abortHandle)) |         isNullOrUndefined(callbacks.abortHandle)) | ||||||
|     ) { |     ) { | ||||||
|       // No information needed: call the generic fetch interface |       // No information needed: call the generic fetch interface | ||||||
|       action = fetch(generateUrl, { |       action = fetch(generateUrl, { | ||||||
| @@ -288,7 +288,7 @@ export function RESTRequest({ | |||||||
|           headers, |           headers, | ||||||
|           body, |           body, | ||||||
|         }, |         }, | ||||||
|         callback |         callbacks | ||||||
|       ); |       ); | ||||||
|     } |     } | ||||||
|     action |     action | ||||||
|   | |||||||
							
								
								
									
										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.12.1 | 0.14.0 | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user