Compare commits

..

7 Commits

40 changed files with 1503 additions and 615 deletions

View File

@@ -1,14 +1,4 @@
#!/bin/bash #!/bin/bash
version_file="version.txt"
# update the Maven version number mvn versions:set -DnewVersion=$(cat version.txt)
mvn versions:set -DnewVersion=$(sed 's/dev/SNAPSHOT/g' $version_file)
if grep -q "DEV" "$version_file"; then
# update all versions release of dependency
mvn versions:use-latest-releases
# update our manage dependency as snapshoot
mvn versions:use-latest-versions -Dincludes=kangaroo-and-rabbit
else
# update our manage dependency as release (must be done before)
mvn versions:use-latest-releases -Dincludes=kangaroo-and-rabbit
fi

14
pom.xml
View File

@@ -3,7 +3,7 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>kangaroo-and-rabbit</groupId> <groupId>kangaroo-and-rabbit</groupId>
<artifactId>archidata</artifactId> <artifactId>archidata</artifactId>
<version>0.10.2</version> <version>0.8.10-SNAPSHOOT</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>
@@ -136,24 +136,24 @@
<dependency> <dependency>
<groupId>org.xerial</groupId> <groupId>org.xerial</groupId>
<artifactId>sqlite-jdbc</artifactId> <artifactId>sqlite-jdbc</artifactId>
<version>3.45.3.0</version> <version>3.40.0.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.1</version> <version>9.39</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>jakarta.persistence</groupId> <groupId>jakarta.persistence</groupId>
<artifactId>jakarta.persistence-api</artifactId> <artifactId>jakarta.persistence-api</artifactId>
<version>3.2.0</version> <version>3.2.0-M2</version>
</dependency> </dependency>
<!-- Swagger dependencies --> <!-- Swagger dependencies -->
<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.21</version>
</dependency> </dependency>
<!-- <!--
************************************************************ ************************************************************
@@ -163,13 +163,13 @@
<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-M1</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-M1</version>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency> <dependency>

View File

@@ -11,7 +11,6 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.annotation.Nullable;
import jakarta.persistence.Column; import jakarta.persistence.Column;
import jakarta.persistence.GeneratedValue; import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType; import jakarta.persistence.GenerationType;
@@ -259,14 +258,6 @@ public class AnnotationTools {
return !((Column) annotation[0]).nullable(); return !((Column) annotation[0]).nullable();
} }
public static boolean getNullable(final Field element) throws Exception {
final Annotation[] annotation = element.getDeclaredAnnotationsByType(Nullable.class);
if (annotation.length == 0) {
return false;
}
return true;
}
public static boolean getConstraintsNotNull(final Field element) throws Exception { public static boolean getConstraintsNotNull(final Field element) throws Exception {
final Annotation[] annotation = element.getDeclaredAnnotationsByType(NotNull.class); final Annotation[] annotation = element.getDeclaredAnnotationsByType(NotNull.class);
if (annotation.length == 0) { if (annotation.length == 0) {

View File

@@ -5,25 +5,21 @@ import java.util.UUID;
import org.kar.archidata.tools.UuidUtils; import org.kar.archidata.tools.UuidUtils;
import jakarta.persistence.Column;
import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.NotNull;
import jakarta.ws.rs.core.Response; import jakarta.ws.rs.core.Response;
public class RestErrorResponse { public class RestErrorResponse {
@NotNull
public UUID uuid = UuidUtils.nextUUID(); public UUID uuid = UuidUtils.nextUUID();
@NotNull @NotNull
@Column(length = 0)
public String name; // Mandatory for TS generic error public String name; // Mandatory for TS generic error
@NotNull @NotNull
@Column(length = 0)
public String message; // Mandatory for TS generic error public String message; // Mandatory for TS generic error
@NotNull @NotNull
@Column(length = 0)
public String time; public String time;
@NotNull @NotNull
final public int status; final public int status;
@NotNull @NotNull
@Column(length = 0)
final public String statusMessage; final public String statusMessage;
public RestErrorResponse(final Response.Status status, final String time, final String error, public RestErrorResponse(final Response.Status status, final String time, final String error,

View File

@@ -796,7 +796,7 @@ public class DataAccess {
// External checker of data: // External checker of data:
final List<CheckFunction> checks = options.get(CheckFunction.class); final List<CheckFunction> checks = options.get(CheckFunction.class);
for (final CheckFunction check : checks) { for (final CheckFunction check : checks) {
check.getChecker().check("", data, AnnotationTools.getFieldsNames(clazz), options); check.getChecker().check("", data, AnnotationTools.getFieldsNames(clazz));
} }
final DBEntry entry = DBInterfaceOption.getAutoEntry(options); final DBEntry entry = DBInterfaceOption.getAutoEntry(options);
@@ -1119,7 +1119,7 @@ public class DataAccess {
if (options != null) { if (options != null) {
final List<CheckFunction> checks = options.get(CheckFunction.class); final List<CheckFunction> checks = options.get(CheckFunction.class);
for (final CheckFunction check : checks) { for (final CheckFunction check : checks) {
check.getChecker().check("", data, filter.getValues(), options); check.getChecker().check("", data, filter.getValues());
} }
} }
final List<LazyGetter> asyncActions = new ArrayList<>(); final List<LazyGetter> asyncActions = new ArrayList<>();
@@ -1293,7 +1293,8 @@ public class DataAccess {
return stmt.execute(query); return stmt.execute(query);
} }
public static <T> T getWhere(final Class<T> clazz, final QueryOptions options) throws Exception { public static <T> T getWhere(final Class<T> clazz, final QueryOption... option) throws Exception {
final QueryOptions options = new QueryOptions(option);
options.add(new Limit(1)); options.add(new Limit(1));
final List<T> values = getsWhere(clazz, options); final List<T> values = getsWhere(clazz, options);
if (values.size() == 0) { if (values.size() == 0) {
@@ -1302,11 +1303,6 @@ public class DataAccess {
return values.get(0); return values.get(0);
} }
public static <T> T getWhere(final Class<T> clazz, final QueryOption... option) throws Exception {
final QueryOptions options = new QueryOptions(option);
return getWhere(clazz, options);
}
public static void generateSelectField(// public static void generateSelectField(//
final StringBuilder querySelect, // final StringBuilder querySelect, //
final StringBuilder query, // final StringBuilder query, //
@@ -1488,19 +1484,12 @@ public class DataAccess {
return data; return data;
} }
public static <ID_TYPE> long count(final Class<?> clazz, final ID_TYPE id, final QueryOption... option) public static <ID_TYPE> long count(final Class<?> clazz, final ID_TYPE id) throws Exception {
throws Exception { return DataAccess.countWhere(clazz, new Condition(getTableIdCondition(clazz, id)));
final QueryOptions options = new QueryOptions(option);
options.add(new Condition(getTableIdCondition(clazz, id)));
return DataAccess.countWhere(clazz, options);
} }
public static long countWhere(final Class<?> clazz, final QueryOption... option) throws Exception { public static long countWhere(final Class<?> clazz, final QueryOption... option) throws Exception {
final QueryOptions options = new QueryOptions(option); final QueryOptions options = new QueryOptions(option);
return countWhere(clazz, options);
}
public static long countWhere(final Class<?> clazz, final QueryOptions options) throws Exception {
final Condition condition = conditionFusionOrEmpty(options, false); final Condition condition = conditionFusionOrEmpty(options, false);
final String deletedFieldName = AnnotationTools.getDeletedFieldName(clazz); final String deletedFieldName = AnnotationTools.getDeletedFieldName(clazz);
DBEntry entry = DBInterfaceOption.getAutoEntry(options); DBEntry entry = DBInterfaceOption.getAutoEntry(options);

View File

@@ -0,0 +1,524 @@
package org.kar.archidata.dataAccess;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileWriter;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.lang.reflect.ParameterizedType;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import org.kar.archidata.catcher.RestErrorResponse;
import org.kar.archidata.dataAccess.DataFactoryZod.ClassElement;
import org.kar.archidata.dataAccess.DataFactoryZod.GeneratedTypes;
import org.kar.archidata.externalRestApi.model.ApiTool;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
public class DataFactoryTsApi {
static final Logger LOGGER = LoggerFactory.getLogger(DataFactoryTsApi.class);
record APIModel(
String data,
String className) {}
/** Request the generation of the TypeScript file for the "Zod" export model
* @param classs List of class used in the model
* @throws Exception */
public static List<String> createApi(
final List<Class<?>> classs,
final GeneratedTypes previous,
final String pathPackage) throws Exception {
final List<String> apis = new ArrayList<>();
final String globalheader = """
/**
* API of the server (auto-generated code)
*/
import {
HTTPMimeType,
HTTPRequestModel,
ModelResponseHttp,
RESTCallbacks,
RESTConfig,
RESTRequestJson,
RESTRequestJsonArray,
RESTRequestVoid
} from "./rest-tools"
import {""";
for (final Class<?> clazz : classs) {
final Set<Class<?>> includeModel = new HashSet<>();
final Set<Class<?>> includeCheckerModel = new HashSet<>();
final APIModel api = createSingleApi(clazz, includeModel, includeCheckerModel, previous);
final StringBuilder generatedData = new StringBuilder();
generatedData.append(globalheader);
final List<String> includedElements = new ArrayList<>();
for (final Class<?> elem : includeModel) {
if (elem == null) {
continue;
}
final ClassElement classElement = DataFactoryZod.createTable(elem, previous);
if (classElement.nativeType) {
continue;
}
includedElements.add(classElement.tsTypeName);
}
Collections.sort(includedElements);
for (final String elem : includedElements) {
generatedData.append("\n ");
generatedData.append(elem);
generatedData.append(",");
}
for (final Class<?> elem : includeCheckerModel) {
if (elem == null) {
continue;
}
final ClassElement classElement = DataFactoryZod.createTable(elem, previous);
if (classElement.nativeType) {
continue;
}
generatedData.append("\n ");
generatedData.append(classElement.tsCheckType);
generatedData.append(",");
}
generatedData.append("\n} from \"./model\"\n");
generatedData.append(api.data());
String fileName = api.className();
fileName = fileName.replaceAll("([A-Z])", "-$1").toLowerCase();
fileName = fileName.replaceAll("^\\-*", "");
apis.add(fileName);
final FileWriter myWriter = new FileWriter(pathPackage + File.separator + fileName + ".ts");
myWriter.write(generatedData.toString());
myWriter.close();
}
return apis;
}
record OrderedElement(
String methodName,
Method method) {}
public static APIModel createSingleApi(
final Class<?> clazz,
final Set<Class<?>> includeModel,
final Set<Class<?>> includeCheckerModel,
final GeneratedTypes previous) throws Exception {
final StringBuilder builder = new StringBuilder();
// the basic path has no specific elements...
final String basicPath = ApiTool.apiAnnotationGetPath(clazz);
final String classSimpleName = clazz.getSimpleName();
builder.append("export namespace ");
builder.append(classSimpleName);
builder.append(" {\n");
LOGGER.info("Parse Class for path: {} => {}", classSimpleName, basicPath);
final List<OrderedElement> orderedElements = new ArrayList<>();
for (final Method method : clazz.getDeclaredMethods()) {
final String methodName = method.getName();
orderedElements.add(new OrderedElement(methodName, method));
}
final Comparator<OrderedElement> comparator = Comparator.comparing(OrderedElement::methodName);
Collections.sort(orderedElements, comparator);
for (final OrderedElement orderedElement : orderedElements) {
final Method method = orderedElement.method();
final String methodName = orderedElement.methodName();
final String methodPath = ApiTool.apiAnnotationGetPath(method);
final String methodType = ApiTool.apiAnnotationGetTypeRequest(method);
if (methodType == null) {
LOGGER.error(" [{}] {} => {}/{} ==> No methode type @PATH, @GET ...", methodType, methodName,
basicPath, methodPath);
continue;
}
final String methodDescription = ApiTool.apiAnnotationGetOperationDescription(method);
final List<String> consumes = ApiTool.apiAnnotationGetConsumes(clazz, method);
List<String> produces = ApiTool.apiAnnotationProduces(clazz, method);
LOGGER.trace(" [{}] {} => {}/{}", methodType, methodName, basicPath, methodPath);
if (methodDescription != null) {
LOGGER.trace(" description: {}", methodDescription);
}
final boolean needGenerateProgress = ApiTool.apiAnnotationTypeScriptProgress(method);
Class<?>[] returnTypeModel = ApiTool.apiAnnotationGetAsyncType(method);
boolean isUnmanagedReturnType = false;
boolean returnModelIsArray = false;
List<ClassElement> tmpReturn;
if (returnTypeModel == null) {
Class<?> returnTypeModelRaw = method.getReturnType();
LOGGER.info("Get type: {}", returnTypeModelRaw);
if (returnTypeModelRaw == Response.class) {
LOGGER.info("Get type: {}", returnTypeModelRaw);
}
if (returnTypeModelRaw == Response.class || returnTypeModelRaw == void.class
|| returnTypeModelRaw == Void.class) {
if (returnTypeModelRaw == Response.class) {
isUnmanagedReturnType = true;
}
returnTypeModel = new Class<?>[] { Void.class };
tmpReturn = new ArrayList<>();
produces = null;
} else if (returnTypeModelRaw == Map.class) {
LOGGER.warn("Not manage the Map Model ... set any");
returnTypeModel = new Class<?>[] { Map.class };
tmpReturn = DataFactoryZod.createTables(returnTypeModel, previous);
} else if (returnTypeModelRaw == List.class) {
final ParameterizedType listType = (ParameterizedType) method.getGenericReturnType();
returnTypeModelRaw = (Class<?>) listType.getActualTypeArguments()[0];
returnModelIsArray = true;
returnTypeModel = new Class<?>[] { returnTypeModelRaw };
tmpReturn = DataFactoryZod.createTables(returnTypeModel, previous);
} else {
returnTypeModel = new Class<?>[] { returnTypeModelRaw };
tmpReturn = DataFactoryZod.createTables(returnTypeModel, previous);
}
} else if (returnTypeModel.length >= 0 && (returnTypeModel[0] == Response.class
|| returnTypeModel[0] == Void.class || returnTypeModel[0] == void.class)) {
if (returnTypeModel[0] == Response.class) {
isUnmanagedReturnType = true;
}
returnTypeModel = new Class<?>[] { Void.class };
tmpReturn = new ArrayList<>();
produces = null;
} else if (returnTypeModel.length > 0 && returnTypeModel[0] == Map.class) {
LOGGER.warn("Not manage the Map Model ...");
returnTypeModel = new Class<?>[] { Map.class };
tmpReturn = DataFactoryZod.createTables(returnTypeModel, previous);
} else {
tmpReturn = DataFactoryZod.createTables(returnTypeModel, previous);
}
for (final ClassElement elem : tmpReturn) {
includeModel.add(elem.model[0]);
includeCheckerModel.add(elem.model[0]);
}
LOGGER.trace(" return: {}", tmpReturn.size());
for (final ClassElement elem : tmpReturn) {
LOGGER.trace(" - {}", elem.tsTypeName);
}
final Map<String, String> queryParams = new HashMap<>();
final Map<String, String> pathParams = new HashMap<>();
final Map<String, String> formDataParams = new HashMap<>();
final List<String> emptyElement = new ArrayList<>();
// LOGGER.info(" Parameters:");
for (final Parameter parameter : method.getParameters()) {
// Security context are internal parameter (not available from API)
if (ApiTool.apiAnnotationIsContext(parameter)) {
continue;
}
final Class<?> parameterType = parameter.getType();
String parameterTypeString;
final Class<?>[] asyncType = ApiTool.apiAnnotationGetAsyncType(parameter);
if (parameterType == List.class) {
if (asyncType == null) {
LOGGER.warn("Detect List param ==> not managed type ==> any[] !!!");
parameterTypeString = "any[]";
} else {
final List<ClassElement> tmp = DataFactoryZod.createTables(asyncType, previous);
for (final ClassElement elem : tmp) {
includeModel.add(elem.model[0]);
}
parameterTypeString = ApiTool.convertInTypeScriptType(tmp, true);
}
} else if (asyncType == null) {
final ClassElement tmp = DataFactoryZod.createTable(parameterType, previous);
includeModel.add(tmp.model[0]);
parameterTypeString = tmp.tsTypeName;
} else {
final List<ClassElement> tmp = DataFactoryZod.createTables(asyncType, previous);
for (final ClassElement elem : tmp) {
includeModel.add(elem.model[0]);
}
parameterTypeString = ApiTool.convertInTypeScriptType(tmp, true);
}
final String pathParam = ApiTool.apiAnnotationGetPathParam(parameter);
final String queryParam = ApiTool.apiAnnotationGetQueryParam(parameter);
final String formDataParam = ApiTool.apiAnnotationGetFormDataParam(parameter);
if (queryParam != null) {
queryParams.put(queryParam, parameterTypeString);
} else if (pathParam != null) {
pathParams.put(pathParam, parameterTypeString);
} else if (formDataParam != null) {
formDataParams.put(formDataParam, parameterTypeString);
} else if (asyncType != null) {
final List<ClassElement> tmp = DataFactoryZod.createTables(asyncType, previous);
parameterTypeString = "";
for (final ClassElement elem : tmp) {
includeModel.add(elem.model[0]);
if (parameterTypeString.length() != 0) {
parameterTypeString += " | ";
}
parameterTypeString += elem.tsTypeName;
}
emptyElement.add(parameterTypeString);
} else if (parameterType == List.class) {
parameterTypeString = "any[]";
final Class<?> plop = parameterType.arrayType();
LOGGER.info("ArrayType = {}", plop);
emptyElement.add(parameterTypeString);
} else {
final ClassElement tmp = DataFactoryZod.createTable(parameterType, previous);
includeModel.add(tmp.model[0]);
emptyElement.add(tmp.tsTypeName);
}
}
if (!queryParams.isEmpty()) {
LOGGER.trace(" Query parameter:");
for (final Entry<String, String> queryEntry : queryParams.entrySet()) {
LOGGER.trace(" - {}: {}", queryEntry.getKey(), queryEntry.getValue());
}
}
if (!pathParams.isEmpty()) {
LOGGER.trace(" Path parameter:");
for (final Entry<String, String> pathEntry : pathParams.entrySet()) {
LOGGER.trace(" - {}: {}", pathEntry.getKey(), pathEntry.getValue());
}
}
if (emptyElement.size() > 1) {
LOGGER.error(" Fail to parse: Too much element in the model for the data ...");
continue;
} else if (emptyElement.size() == 1 && formDataParams.size() != 0) {
LOGGER.error(" Fail to parse: Incompatible form data & direct data ...");
continue;
} else if (emptyElement.size() == 1) {
LOGGER.trace(" data type: {}", emptyElement.get(0));
}
// ALL is good can generate the Elements
if (methodDescription != null) {
builder.append("\n\t/**\n\t * ");
builder.append(methodDescription);
builder.append("\n\t */");
}
if (isUnmanagedReturnType) {
builder.append(
"\n\t// TODO: unmanaged \"Response\" type: please specify @AsyncType or considered as 'void'.");
}
builder.append("\n\texport function ");
builder.append(methodName);
builder.append("({\n\t\t\trestConfig,");
if (!queryParams.isEmpty()) {
builder.append("\n\t\t\tqueries,");
}
if (!pathParams.isEmpty()) {
builder.append("\n\t\t\tparams,");
}
if (produces != null && produces.size() > 1) {
builder.append("\n\t\t\tproduce,");
}
if (emptyElement.size() == 1 || formDataParams.size() != 0) {
builder.append("\n\t\t\tdata,");
}
if (needGenerateProgress) {
builder.append("\n\t\t\tcallback,");
}
builder.append("\n\t\t}: {");
builder.append("\n\t\trestConfig: RESTConfig,");
if (!queryParams.isEmpty()) {
builder.append("\n\t\tqueries: {");
for (final Entry<String, String> queryEntry : queryParams.entrySet()) {
builder.append("\n\t\t\t");
builder.append(queryEntry.getKey());
builder.append("?: ");
builder.append(queryEntry.getValue());
builder.append(",");
}
builder.append("\n\t\t},");
}
if (!pathParams.isEmpty()) {
builder.append("\n\t\tparams: {");
for (final Entry<String, String> pathEntry : pathParams.entrySet()) {
builder.append("\n\t\t\t");
builder.append(pathEntry.getKey());
builder.append(": ");
builder.append(pathEntry.getValue());
builder.append(",");
}
builder.append("\n\t\t},");
}
if (emptyElement.size() == 1) {
builder.append("\n\t\tdata: ");
builder.append(emptyElement.get(0));
builder.append(",");
} else if (formDataParams.size() != 0) {
builder.append("\n\t\tdata: {");
for (final Entry<String, String> pathEntry : formDataParams.entrySet()) {
builder.append("\n\t\t\t");
builder.append(pathEntry.getKey());
builder.append(": ");
builder.append(pathEntry.getValue());
builder.append(",");
}
builder.append("\n\t\t},");
}
if (produces != null && produces.size() > 1) {
builder.append("\n\t\tproduce: ");
String isFist = null;
for (final String elem : produces) {
String lastElement = null;
if (MediaType.APPLICATION_JSON.equals(elem)) {
lastElement = "HTTPMimeType.JSON";
}
if (MediaType.MULTIPART_FORM_DATA.equals(elem)) {
lastElement = "HTTPMimeType.MULTIPART";
}
if (DataExport.CSV_TYPE.equals(elem)) {
lastElement = "HTTPMimeType.CSV";
}
if (lastElement != null) {
if (isFist == null) {
isFist = lastElement;
} else {
builder.append(" | ");
}
builder.append(lastElement);
} else {
LOGGER.error("Unmanaged model type: {}", elem);
}
}
builder.append(",");
}
if (needGenerateProgress) {
builder.append("\n\t\tcallback?: RESTCallbacks,");
}
builder.append("\n\t}): Promise<");
if (tmpReturn.size() == 0 //
|| tmpReturn.get(0).tsTypeName == null //
|| tmpReturn.get(0).tsTypeName.equals("void")) {
builder.append("void");
} else {
builder.append(ApiTool.convertInTypeScriptType(tmpReturn, returnModelIsArray));
}
builder.append("> {");
if (tmpReturn.size() == 0 //
|| tmpReturn.get(0).tsTypeName == null //
|| tmpReturn.get(0).tsTypeName.equals("void")) {
builder.append("\n\t\treturn RESTRequestVoid({");
} else if (returnModelIsArray) {
builder.append("\n\t\treturn RESTRequestJsonArray({");
} else {
builder.append("\n\t\treturn RESTRequestJson({");
}
builder.append("\n\t\t\trestModel: {");
builder.append("\n\t\t\t\tendPoint: \"");
builder.append(basicPath);
if (methodPath != null) {
builder.append("/");
builder.append(methodPath);
}
builder.append("\",");
builder.append("\n\t\t\t\trequestType: HTTPRequestModel.");
builder.append(methodType);
builder.append(",");
if (consumes != null) {
for (final String elem : consumes) {
if (MediaType.APPLICATION_JSON.equals(elem)) {
builder.append("\n\t\t\t\tcontentType: HTTPMimeType.JSON,");
break;
} else if (MediaType.MULTIPART_FORM_DATA.equals(elem)) {
builder.append("\n\t\t\t\tcontentType: HTTPMimeType.MULTIPART,");
break;
} else if (MediaType.TEXT_PLAIN.equals(elem)) {
builder.append("\n\t\t\t\tcontentType: HTTPMimeType.TEXT_PLAIN,");
break;
}
}
} else if ("DELETE".equals(methodType)) {
builder.append("\n\t\t\t\tcontentType: HTTPMimeType.TEXT_PLAIN,");
}
if (produces != null) {
if (produces.size() > 1) {
builder.append("\n\t\t\t\taccept: produce,");
} else {
for (final String elem : produces) {
if (MediaType.APPLICATION_JSON.equals(elem)) {
builder.append("\n\t\t\t\taccept: HTTPMimeType.JSON,");
break;
}
}
}
}
builder.append("\n\t\t\t},");
builder.append("\n\t\t\trestConfig,");
if (!pathParams.isEmpty()) {
builder.append("\n\t\t\tparams,");
}
if (!queryParams.isEmpty()) {
builder.append("\n\t\t\tqueries,");
}
if (emptyElement.size() == 1) {
builder.append("\n\t\t\tdata,");
} else if (formDataParams.size() != 0) {
builder.append("\n\t\t\tdata,");
}
if (needGenerateProgress) {
builder.append("\n\t\t\tcallback,");
}
builder.append("\n\t\t}");
if (tmpReturn.size() != 0 && tmpReturn.get(0).tsTypeName != null
&& !tmpReturn.get(0).tsTypeName.equals("void")) {
builder.append(", ");
// TODO: correct this it is really bad ...
builder.append(ApiTool.convertInTypeScriptCheckType(tmpReturn));
}
builder.append(");");
builder.append("\n\t};");
}
builder.append("\n}\n");
return new APIModel(builder.toString(), classSimpleName);
}
public static void generatePackage(
final List<Class<?>> classApi,
final List<Class<?>> classModel,
final String pathPackage) throws Exception {
final GeneratedTypes previous = DataFactoryZod.createBasicType();
DataFactoryZod.createTable(RestErrorResponse.class, previous);
final List<String> listApi = createApi(classApi, previous, pathPackage);
final String packageApi = DataFactoryZod.createTables(new ArrayList<>(classModel), previous);
FileWriter myWriter = new FileWriter(pathPackage + File.separator + "model.ts");
myWriter.write(packageApi.toString());
myWriter.close();
final StringBuilder index = new StringBuilder("""
/**
* Global import of the package
*/
export * from "./model";
""");
for (final String api : listApi) {
index.append("export * from \"./").append(api).append("\";\n");
}
myWriter = new FileWriter(pathPackage + File.separator + "index.ts");
myWriter.write(index.toString());
myWriter.close();
final InputStream ioStream = DataFactoryTsApi.class.getClassLoader().getResourceAsStream("rest-tools.ts");
if (ioStream == null) {
throw new IllegalArgumentException("rest-tools.ts is not found");
}
final BufferedReader buffer = new BufferedReader(new InputStreamReader(ioStream));
myWriter = new FileWriter(pathPackage + File.separator + "rest-tools.ts");
String line;
while ((line = buffer.readLine()) != null) {
myWriter.write(line);
myWriter.write("\n");
}
ioStream.close();
myWriter.close();
return;
}
}

View File

@@ -0,0 +1,471 @@
package org.kar.archidata.dataAccess;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
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.FormDataContentDisposition;
import org.kar.archidata.annotation.AnnotationTools;
import org.kar.archidata.exception.DataAccessException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import jakarta.ws.rs.core.Response;
public class DataFactoryZod {
static final Logger LOGGER = LoggerFactory.getLogger(DataFactoryZod.class);
static public class ClassElement {
public Class<?>[] model;
public String zodName;
public String tsTypeName;
public String tsCheckType;
public String declaration;
public String comment = null;
public boolean isEnum = false;
public boolean nativeType;
public ClassElement(final Class<?> model[], final String zodName, final String tsTypeName,
final String tsCheckType, final String declaration, final boolean nativeType) {
this.model = model;
this.zodName = zodName;
this.tsTypeName = tsTypeName;
this.tsCheckType = tsCheckType;
this.declaration = declaration;
this.nativeType = nativeType;
}
public ClassElement(final Class<?> model) {
this(new Class<?>[] { model });
}
public ClassElement(final Class<?> model[]) {
this.model = model;
this.zodName = "Zod" + model[0].getSimpleName();
this.tsTypeName = model[0].getSimpleName();
this.tsCheckType = "is" + model[0].getSimpleName();
this.declaration = null;
this.nativeType = false;
}
}
public static class GeneratedTypes {
final List<ClassElement> previousGeneration = new ArrayList<>();
final List<Class<?>> order = new ArrayList<>();
public ClassElement find(final Class<?> clazz) {
for (final ClassElement elem : this.previousGeneration) {
for (final Class<?> elemClass : elem.model) {
if (elemClass == clazz) {
return elem;
}
}
}
return null;
}
public void add(final ClassElement elem) {
this.previousGeneration.add(elem);
}
public void add(final ClassElement elem, final boolean addOrder) {
this.previousGeneration.add(elem);
if (addOrder) {
this.order.add(elem.model[0]);
}
}
public void addOrder(final ClassElement elem) {
this.order.add(elem.model[0]);
}
}
public static ClassElement convertTypeZodEnum(final Class<?> clazz, final GeneratedTypes previous)
throws Exception {
final ClassElement element = new ClassElement(clazz);
previous.add(element);
final Object[] arr = clazz.getEnumConstants();
final StringBuilder out = new StringBuilder();
if (System.getenv("ARCHIDATA_GENERATE_ZOD_ENUM") != null) {
boolean first = true;
out.append("zod.enum([");
for (final Object elem : arr) {
if (!first) {
out.append(",\n\t");
} else {
out.append("\n\t");
first = false;
}
out.append("'");
out.append(elem.toString());
out.append("'");
}
if (first) {
out.append("]}");
} else {
out.append("\n\t])");
}
} else {
element.isEnum = true;
boolean first = true;
out.append("{");
for (final Object elem : arr) {
if (!first) {
out.append(",\n\t");
} else {
out.append("\n\t");
first = false;
}
out.append(elem.toString());
out.append(" = '");
out.append(elem.toString());
out.append("'");
}
if (first) {
out.append("}");
} else {
out.append(",\n\t}");
}
}
element.declaration = out.toString();
previous.addOrder(element);
return element;
}
public static String convertTypeZod(final Class<?> type, final GeneratedTypes previous) throws Exception {
final ClassElement previousType = previous.find(type);
if (previousType != null) {
return previousType.zodName;
}
if (type.isEnum()) {
return convertTypeZodEnum(type, previous).zodName;
}
if (type == List.class) {
throw new DataAccessException("Imcompatible type of element in object for: " + type.getCanonicalName()
+ " Unmanaged List of List ... ");
}
final ClassElement elemCreated = createTable(type, previous);
if (elemCreated != null) {
return elemCreated.zodName;
}
throw new DataAccessException("Imcompatible type of element in object for: " + type.getCanonicalName());
}
public static String convertTypeZod(final Field field, final GeneratedTypes previous) throws Exception {
final Class<?> type = field.getType();
final ClassElement previousType = previous.find(type);
if (previousType != null) {
return previousType.zodName;
}
if (type.isEnum()) {
return convertTypeZodEnum(type, previous).zodName;
}
if (type == List.class) {
final ParameterizedType listType = (ParameterizedType) field.getGenericType();
final Class<?> listClass = (Class<?>) listType.getActualTypeArguments()[0];
final String simpleSubType = convertTypeZod(listClass, previous);
return "zod.array(" + simpleSubType + ")";
}
final ClassElement elemCreated = createTable(type, previous);
if (elemCreated != null) {
return elemCreated.zodName;
}
throw new DataAccessException("Imcompatible type of element in object for: " + type.getCanonicalName());
}
public static String optionalTypeZod(final Class<?> type) throws Exception {
if (type.isPrimitive()) {
return "";
}
return ".optional()";
}
public static void createTablesSpecificType(
final Field elem,
final int fieldId,
final StringBuilder builder,
final GeneratedTypes previous) throws Exception {
final String name = elem.getName();
final Class<?> classModel = elem.getType();
final int limitSize = AnnotationTools.getLimitSize(elem);
final String comment = AnnotationTools.getComment(elem);
if (fieldId != 0) {
builder.append(",");
}
if (comment != null) {
builder.append("\n\t// ");
builder.append(comment);
}
builder.append("\n\t");
builder.append(name);
builder.append(": ");
builder.append(convertTypeZod(elem, previous));
if (limitSize > 0 && classModel == String.class) {
builder.append(".max(");
builder.append(limitSize);
builder.append(")");
}
if (AnnotationTools.getSchemaReadOnly(elem)) {
builder.append(".readonly()");
}
builder.append(optionalTypeZod(classModel));
}
private static boolean isFieldFromSuperClass(final Class<?> model, final String filedName) {
final Class<?> superClass = model.getSuperclass();
if (superClass == null) {
return false;
}
for (final Field field : superClass.getFields()) {
String name;
try {
name = AnnotationTools.getFieldName(field);
if (filedName.equals(name)) {
return true;
}
} catch (final Exception e) {
// TODO Auto-generated catch block
LOGGER.trace("Catch error field name in parent create data table: {}", e.getMessage());
}
}
return false;
}
public static GeneratedTypes createBasicType() throws Exception {
final GeneratedTypes previous = new GeneratedTypes();
previous.add(new ClassElement(new Class<?>[] { Void.class, void.class }, "void", "void", null, null, true));
// Map is binded to any ==> can not determine this complex model for now
previous.add(new ClassElement(new Class<?>[] { Map.class }, "any", "any", null, null, true));
previous.add(new ClassElement(new Class<?>[] { String.class }, "zod.string()", "string", null, "zod.string()",
true));
previous.add(new ClassElement(new Class<?>[] { InputStream.class, FormDataContentDisposition.class },
"z.instanceof(File)", "File", null, "z.instanceof(File)", true));
previous.add(new ClassElement(new Class<?>[] { Boolean.class, boolean.class }, "zod.boolean()", "boolean", null,
"zod.boolean()", true));
previous.add(new ClassElement(new Class<?>[] { UUID.class }, "ZodUUID", "UUID", "isUUID", "zod.string().uuid()",
false), true);
previous.add(new ClassElement(new Class<?>[] { Long.class, long.class }, "ZodLong", "Long", "isLong",
// "zod.bigint()",
"zod.number()", false), true);
previous.add(new ClassElement(new Class<?>[] { Integer.class, int.class }, "ZodInteger", "Integer", "isInteger",
"zod.number().safe()", false), true);
previous.add(new ClassElement(new Class<?>[] { Double.class, double.class }, "ZodDouble", "Double", "isDouble",
"zod.number()", true), true);
previous.add(new ClassElement(new Class<?>[] { Float.class, float.class }, "ZodFloat", "Float", "isFloat",
"zod.number()", false), true);
previous.add(new ClassElement(new Class<?>[] { Instant.class }, "ZodInstant", "Instant", "isInstant",
"zod.string()", false), true);
previous.add(new ClassElement(new Class<?>[] { Date.class }, "ZodDate", "Date", "isDate",
"zod.string().datetime({ precision: 3 })", false), true);
previous.add(new ClassElement(new Class<?>[] { Timestamp.class }, "ZodTimestamp", "Timestamp", "isTimestamp",
"zod.string().datetime({ precision: 3 })", false), true);
previous.add(new ClassElement(new Class<?>[] { LocalDate.class }, "ZodLocalDate", "LocalDate", "isLocalDate",
"zod.string().date()", false), true);
previous.add(new ClassElement(new Class<?>[] { LocalTime.class }, "ZodLocalTime", "LocalTime", "isLocalTime",
"zod.string().time()", false), true);
return previous;
}
/** Request the generation of the TypeScript file for the "Zod" export model
* @param classs List of class used in the model
* @return A string representing the Server models
* @throws Exception */
public static String createTables(final List<Class<?>> classs) throws Exception {
return createTables(classs, createBasicType());
}
public static String createTables(final List<Class<?>> classs, final GeneratedTypes previous) throws Exception {
for (final Class<?> clazz : classs) {
createTable(clazz, previous);
}
final StringBuilder generatedData = new StringBuilder();
generatedData.append("""
/**
* Interface of the server (auto-generated code)
*/
import { z as zod } from \"zod\";
""");
for (final Class<?> elem : previous.order) {
final ClassElement data = previous.find(elem);
if (!data.nativeType) {
if (data.comment != null) {
generatedData.append(data.comment);
}
generatedData.append(createDeclaration(data));
generatedData.append("\n\n");
}
}
LOGGER.info("generated: {}", generatedData.toString());
return generatedData.toString();
}
public static List<ClassElement> createTables(final Class<?>[] classs, final GeneratedTypes previous)
throws Exception {
final List<ClassElement> out = new ArrayList<>();
for (final Class<?> clazz : classs) {
if (clazz == Response.class) {
throw new IOException("Can not generate a Zod element for an unknow type Response");
}
out.add(createTable(clazz, previous));
}
return out;
}
public static ClassElement createTable(final Class<?> clazz, final GeneratedTypes previous) throws Exception {
if (clazz == null) {
return null;
}
if (clazz == Response.class) {
throw new IOException("Can not generate a Zod element for an unknow type Response");
}
final ClassElement alreadyExist = previous.find(clazz);
if (previous.find(clazz) != null) {
return alreadyExist;
}
if (clazz.isPrimitive()) {
return null;
}
if (clazz.isEnum()) {
return convertTypeZodEnum(clazz, previous);
}
// add the current class to prevent multiple creation
final ClassElement curentElementClass = new ClassElement(clazz);
previous.add(curentElementClass);
// Local generation of class:
final StringBuilder internalBuilder = new StringBuilder();
final List<String> alreadyAdded = new ArrayList<>();
LOGGER.trace("parse class: '{}'", clazz.getCanonicalName());
int fieldId = 0;
for (final Field elem : clazz.getFields()) {
// static field is only for internal global declaration ==> remove it ..
if (java.lang.reflect.Modifier.isStatic(elem.getModifiers())) {
continue;
}
final String dataName = elem.getName();
if (isFieldFromSuperClass(clazz, dataName)) {
LOGGER.trace(" SKIP: '{}'", elem.getName());
continue;
}
if (alreadyAdded.contains(dataName)) {
LOGGER.trace(" SKIP2: '{}'", elem.getName());
continue;
}
alreadyAdded.add(dataName);
LOGGER.trace(" + '{}'", elem.getName());
if (false && DataAccess.isAddOnField(elem)) {
final DataAccessAddOn addOn = DataAccess.findAddOnforField(elem);
LOGGER.error("Create type for: {} ==> {} (ADD-ON) ==> Not managed now ....",
AnnotationTools.getFieldName(elem), elem.getType());
/* LOGGER.trace("Create type for: {} ==> {} (ADD-ON)", AnnotationTools.getFieldName(elem), elem.getType()); if (addOn != null) { addOn.createTables(tableName, elem, tmpOut,
* preActionList, postActionList, createIfNotExist, createDrop, fieldId); } else { throw new DataAccessException( "Element matked as add-on but add-on does not loaded: table:" +
* tableName + " field name=" + AnnotationTools.getFieldName(elem) + " type=" + elem.getType()); } fieldId++; */
} else {
LOGGER.trace("Create type for: {} ==> {}", AnnotationTools.getFieldName(elem), elem.getType());
DataFactoryZod.createTablesSpecificType(elem, fieldId, internalBuilder, previous);
fieldId++;
}
}
final String description = AnnotationTools.getSchemaDescription(clazz);
final String example = AnnotationTools.getSchemaExample(clazz);
final StringBuilder generatedCommentedData = new StringBuilder();
if (description != null || example != null) {
generatedCommentedData.append("/**\n");
if (description != null) {
for (final String elem : description.split("\n")) {
generatedCommentedData.append(" * ");
generatedCommentedData.append(elem);
generatedCommentedData.append("\n");
}
}
if (example != null) {
generatedCommentedData.append(" * Example:\n");
generatedCommentedData.append(" * ```\n");
for (final String elem : example.split("\n")) {
generatedCommentedData.append(" * ");
generatedCommentedData.append(elem);
generatedCommentedData.append("\n");
}
generatedCommentedData.append(" * ```\n");
}
generatedCommentedData.append(" */\n");
}
curentElementClass.comment = generatedCommentedData.toString();
final StringBuilder generatedData = new StringBuilder();
final Class<?> parentClass = clazz.getSuperclass();
if (parentClass != null && parentClass != Object.class && parentClass != Record.class) {
final ClassElement parentDeclaration = createTable(parentClass, previous);
generatedData.append(parentDeclaration.zodName);
generatedData.append(".extend({");
} else {
generatedData.append("zod.object({");
}
generatedData.append(internalBuilder.toString());
generatedData.append("\n})");
// Remove the previous to reorder the map ==> parent must be inserted before us.
curentElementClass.declaration = generatedData.toString();
previous.addOrder(curentElementClass);
return curentElementClass;
}
public static String createDeclaration(final ClassElement elem) {
final StringBuilder generatedData = new StringBuilder();
if (elem.isEnum) {
generatedData.append("export enum ");
generatedData.append(elem.tsTypeName);
generatedData.append(" ");
generatedData.append(elem.declaration);
generatedData.append(";");
generatedData.append("\nexport const ");
generatedData.append(elem.zodName);
generatedData.append(" = zod.nativeEnum(");
generatedData.append(elem.tsTypeName);
generatedData.append(");");
} else {
generatedData.append("export const ");
generatedData.append(elem.zodName);
generatedData.append(" = ");
generatedData.append(elem.declaration);
generatedData.append(";");
generatedData.append("\nexport type ");
generatedData.append(elem.tsTypeName);
generatedData.append(" = zod.infer<typeof ");
generatedData.append(elem.zodName);
generatedData.append(">;");
}
// declare generic isXXX:
generatedData.append("\nexport function ");
generatedData.append(elem.tsCheckType);
generatedData.append("(data: any): data is ");
generatedData.append(elem.tsTypeName);
generatedData.append(" {\n\ttry {\n\t\t");
generatedData.append(elem.zodName);
generatedData.append("""
.parse(data);
return true;
} catch (e: any) {
console.log(`Fail to parse data ${e}`);
return false;
}
}
""");
return generatedData.toString();
}
}

View File

@@ -1,6 +1,7 @@
package org.kar.archidata.dataAccess; package org.kar.archidata.dataAccess;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections;
import java.util.List; import java.util.List;
import org.kar.archidata.dataAccess.options.AccessDeletedItems; import org.kar.archidata.dataAccess.options.AccessDeletedItems;
@@ -24,16 +25,10 @@ public class QueryOptions {
if (elems == null || elems.length == 0) { if (elems == null || elems.length == 0) {
return; return;
} }
for (final QueryOption elem : elems) { Collections.addAll(this.options, elems);
add(elem);
}
} }
public void add(final QueryOption option) { public void add(final QueryOption option) {
if (option == null) {
return;
}
this.options.add(option); this.options.add(option);
} }

View File

@@ -3,7 +3,6 @@ package org.kar.archidata.dataAccess.options;
import java.util.List; import java.util.List;
import org.kar.archidata.annotation.AnnotationTools; import org.kar.archidata.annotation.AnnotationTools;
import org.kar.archidata.dataAccess.QueryOptions;
/** By default some element are not read like createAt and UpdatedAt. This option permit to read it. */ /** By default some element are not read like createAt and UpdatedAt. This option permit to read it. */
public interface CheckFunctionInterface { public interface CheckFunctionInterface {
@@ -12,11 +11,10 @@ public interface CheckFunctionInterface {
* @param data The object that might be injected. * @param data The object that might be injected.
* @param filterValue List of fields that might be check. If null, then all column must be checked. * @param filterValue List of fields that might be check. If null, then all column must be checked.
* @throws Exception Exception is generate if the data are incorrect. */ * @throws Exception Exception is generate if the data are incorrect. */
void check(final String baseName, Object data, List<String> filterValue, final QueryOptions options) void check(final String baseName, Object data, List<String> filterValue) throws Exception;
throws Exception;
default void checkAll(final String baseName, final Object data, final QueryOptions options) throws Exception { default void checkAll(final String baseName, final Object data) throws Exception {
check(baseName, data, AnnotationTools.getAllFieldsNames(data.getClass()), options); check(baseName, data, AnnotationTools.getAllFieldsNames(data.getClass()));
} }
} }

View File

@@ -2,16 +2,10 @@ package org.kar.archidata.dataAccess.options;
import java.util.List; import java.util.List;
import org.kar.archidata.dataAccess.QueryOptions;
/** By default some element are not read like createAt and UpdatedAt. This option permit to read it. */ /** By default some element are not read like createAt and UpdatedAt. This option permit to read it. */
public class CheckFunctionVoid implements CheckFunctionInterface { public class CheckFunctionVoid implements CheckFunctionInterface {
@Override @Override
public void check( public void check(final String baseName, Object data, List<String> filterValue) {
final String baseName,
final Object data,
final List<String> filterValue,
final QueryOptions options) {
} }

View File

@@ -16,7 +16,6 @@ import org.kar.archidata.annotation.AnnotationTools;
import org.kar.archidata.annotation.DataJson; import org.kar.archidata.annotation.DataJson;
import org.kar.archidata.dataAccess.DataAccess; import org.kar.archidata.dataAccess.DataAccess;
import org.kar.archidata.dataAccess.QueryCondition; import org.kar.archidata.dataAccess.QueryCondition;
import org.kar.archidata.dataAccess.QueryOptions;
import org.kar.archidata.exception.DataAccessException; import org.kar.archidata.exception.DataAccessException;
import org.kar.archidata.exception.InputException; import org.kar.archidata.exception.InputException;
import org.slf4j.Logger; import org.slf4j.Logger;
@@ -38,7 +37,7 @@ public class CheckJPA<T> implements CheckFunctionInterface {
* @param data The object that might be injected. * @param data The object that might be injected.
* @param filterValue List of fields that might be check. If null, then all column must be checked. * @param filterValue List of fields that might be check. If null, then all column must be checked.
* @throws Exception Exception is generate if the data are incorrect. */ * @throws Exception Exception is generate if the data are incorrect. */
void check(final String baseName, final K data, final QueryOptions options) throws Exception; void check(final String baseName, final K data) throws Exception;
} }
protected Map<String, List<CheckInterface<T>>> checking = null; protected Map<String, List<CheckInterface<T>>> checking = null;
@@ -67,20 +66,20 @@ public class CheckJPA<T> implements CheckFunctionInterface {
for (final Field field : this.clazz.getFields()) { for (final Field field : this.clazz.getFields()) {
final String fieldName = field.getName(); // AnnotationTools.getFieldName(field); final String fieldName = field.getName(); // AnnotationTools.getFieldName(field);
if (AnnotationTools.isPrimaryKey(field)) { if (AnnotationTools.isPrimaryKey(field)) {
add(fieldName, (final String baseName, final T data, final QueryOptions options) -> { add(fieldName, (final String baseName, final T data) -> {
throw new InputException(baseName + fieldName, throw new InputException(baseName + fieldName,
"This is a '@Id' (primaryKey) ==> can not be change"); "This is a '@Id' (primaryKey) ==> can not be change");
}); });
} }
if (AnnotationTools.getConstraintsNotNull(field)) { if (AnnotationTools.getConstraintsNotNull(field)) {
add(fieldName, (final String baseName, final T data, final QueryOptions options) -> { add(fieldName, (final String baseName, final T data) -> {
if (field.get(data) == null) { if (field.get(data) == null) {
throw new InputException(baseName + fieldName, "Can not be null"); throw new InputException(baseName + fieldName, "Can not be null");
} }
}); });
} }
if (AnnotationTools.isCreatedAtField(field) || AnnotationTools.isUpdateAtField(field)) { if (AnnotationTools.isCreatedAtField(field) || AnnotationTools.isUpdateAtField(field)) {
add(fieldName, (final String baseName, final T data, final QueryOptions options) -> { add(fieldName, (final String baseName, final T data) -> {
throw new InputException(baseName + fieldName, "It is forbidden to change this field"); throw new InputException(baseName + fieldName, "It is forbidden to change this field");
}); });
} }
@@ -89,7 +88,7 @@ public class CheckJPA<T> implements CheckFunctionInterface {
if (type == Long.class || type == long.class) { if (type == Long.class || type == long.class) {
final Long maxValue = AnnotationTools.getConstraintsMax(field); final Long maxValue = AnnotationTools.getConstraintsMax(field);
if (maxValue != null) { if (maxValue != null) {
add(fieldName, (final String baseName, final T data, final QueryOptions options) -> { add(fieldName, (final String baseName, final T data) -> {
final Object elem = field.get(data); final Object elem = field.get(data);
if (elem == null) { if (elem == null) {
return; return;
@@ -102,7 +101,7 @@ public class CheckJPA<T> implements CheckFunctionInterface {
} }
final Long minValue = AnnotationTools.getConstraintsMin(field); final Long minValue = AnnotationTools.getConstraintsMin(field);
if (minValue != null) { if (minValue != null) {
add(fieldName, (final String baseName, final T data, final QueryOptions options) -> { add(fieldName, (final String baseName, final T data) -> {
final Object elem = field.get(data); final Object elem = field.get(data);
if (elem == null) { if (elem == null) {
return; return;
@@ -115,19 +114,12 @@ public class CheckJPA<T> implements CheckFunctionInterface {
} }
final ManyToOne annotationManyToOne = AnnotationTools.getManyToOne(field); final ManyToOne annotationManyToOne = AnnotationTools.getManyToOne(field);
if (annotationManyToOne != null && annotationManyToOne.targetEntity() != null) { if (annotationManyToOne != null && annotationManyToOne.targetEntity() != null) {
add(fieldName, (final String baseName, final T data, final QueryOptions options) -> { add(fieldName, (final String baseName, final T data) -> {
final Object elem = field.get(data); final Object elem = field.get(data);
if (elem == null) { if (elem == null) {
return; return;
} }
final List<ConditionChecker> condCheckers = options.get(ConditionChecker.class); final long count = DataAccess.count(annotationManyToOne.targetEntity(), elem);
long count = 0;
if (condCheckers.isEmpty()) {
count = DataAccess.count(annotationManyToOne.targetEntity(), elem);
} else {
count = DataAccess.count(annotationManyToOne.targetEntity(), elem,
condCheckers.get(0).toCondition());
}
if (count == 0) { if (count == 0) {
throw new InputException(baseName + fieldName, throw new InputException(baseName + fieldName,
"Foreign element does not exist in the DB:" + elem); "Foreign element does not exist in the DB:" + elem);
@@ -139,7 +131,7 @@ public class CheckJPA<T> implements CheckFunctionInterface {
final Long maxValueRoot = AnnotationTools.getConstraintsMax(field); final Long maxValueRoot = AnnotationTools.getConstraintsMax(field);
if (maxValueRoot != null) { if (maxValueRoot != null) {
final int maxValue = maxValueRoot.intValue(); final int maxValue = maxValueRoot.intValue();
add(fieldName, (final String baseName, final T data, final QueryOptions options) -> { add(fieldName, (final String baseName, final T data) -> {
final Object elem = field.get(data); final Object elem = field.get(data);
if (elem == null) { if (elem == null) {
return; return;
@@ -153,7 +145,7 @@ public class CheckJPA<T> implements CheckFunctionInterface {
final Long minValueRoot = AnnotationTools.getConstraintsMin(field); final Long minValueRoot = AnnotationTools.getConstraintsMin(field);
if (minValueRoot != null) { if (minValueRoot != null) {
final int minValue = minValueRoot.intValue(); final int minValue = minValueRoot.intValue();
add(fieldName, (final String baseName, final T data, final QueryOptions options) -> { add(fieldName, (final String baseName, final T data) -> {
final Object elem = field.get(data); final Object elem = field.get(data);
if (elem == null) { if (elem == null) {
return; return;
@@ -166,7 +158,7 @@ public class CheckJPA<T> implements CheckFunctionInterface {
} }
final ManyToOne annotationManyToOne = AnnotationTools.getManyToOne(field); final ManyToOne annotationManyToOne = AnnotationTools.getManyToOne(field);
if (annotationManyToOne != null && annotationManyToOne.targetEntity() != null) { if (annotationManyToOne != null && annotationManyToOne.targetEntity() != null) {
add(fieldName, (final String baseName, final T data, final QueryOptions options) -> { add(fieldName, (final String baseName, final T data) -> {
final Object elem = field.get(data); final Object elem = field.get(data);
if (elem == null) { if (elem == null) {
return; return;
@@ -181,7 +173,7 @@ public class CheckJPA<T> implements CheckFunctionInterface {
} else if (type == UUID.class) { } else if (type == UUID.class) {
final ManyToOne annotationManyToOne = AnnotationTools.getManyToOne(field); final ManyToOne annotationManyToOne = AnnotationTools.getManyToOne(field);
if (annotationManyToOne != null && annotationManyToOne.targetEntity() != null) { if (annotationManyToOne != null && annotationManyToOne.targetEntity() != null) {
add(fieldName, (final String baseName, final T data, final QueryOptions options) -> { add(fieldName, (final String baseName, final T data) -> {
final Object elem = field.get(data); final Object elem = field.get(data);
if (elem == null) { if (elem == null) {
return; return;
@@ -199,7 +191,7 @@ public class CheckJPA<T> implements CheckFunctionInterface {
final Long maxValueRoot = AnnotationTools.getConstraintsMax(field); final Long maxValueRoot = AnnotationTools.getConstraintsMax(field);
if (maxValueRoot != null) { if (maxValueRoot != null) {
final float maxValue = maxValueRoot.floatValue(); final float maxValue = maxValueRoot.floatValue();
add(fieldName, (final String baseName, final T data, final QueryOptions options) -> { add(fieldName, (final String baseName, final T data) -> {
final Object elem = field.get(data); final Object elem = field.get(data);
if (elem == null) { if (elem == null) {
return; return;
@@ -213,7 +205,7 @@ public class CheckJPA<T> implements CheckFunctionInterface {
final Long minValueRoot = AnnotationTools.getConstraintsMin(field); final Long minValueRoot = AnnotationTools.getConstraintsMin(field);
if (minValueRoot != null) { if (minValueRoot != null) {
final float minValue = minValueRoot.floatValue(); final float minValue = minValueRoot.floatValue();
add(fieldName, (final String baseName, final T data, final QueryOptions options) -> { add(fieldName, (final String baseName, final T data) -> {
final Object elem = field.get(data); final Object elem = field.get(data);
if (elem == null) { if (elem == null) {
return; return;
@@ -228,7 +220,7 @@ public class CheckJPA<T> implements CheckFunctionInterface {
final Long maxValueRoot = AnnotationTools.getConstraintsMax(field); final Long maxValueRoot = AnnotationTools.getConstraintsMax(field);
if (maxValueRoot != null) { if (maxValueRoot != null) {
final double maxValue = maxValueRoot.doubleValue(); final double maxValue = maxValueRoot.doubleValue();
add(fieldName, (final String baseName, final T data, final QueryOptions options) -> { add(fieldName, (final String baseName, final T data) -> {
final Object elem = field.get(data); final Object elem = field.get(data);
if (elem == null) { if (elem == null) {
return; return;
@@ -242,7 +234,7 @@ public class CheckJPA<T> implements CheckFunctionInterface {
final Long minValueRoot = AnnotationTools.getConstraintsMin(field); final Long minValueRoot = AnnotationTools.getConstraintsMin(field);
if (minValueRoot != null) { if (minValueRoot != null) {
final double minValue = minValueRoot.doubleValue(); final double minValue = minValueRoot.doubleValue();
add(fieldName, (final String baseName, final T data, final QueryOptions options) -> { add(fieldName, (final String baseName, final T data) -> {
final Object elem = field.get(data); final Object elem = field.get(data);
if (elem == null) { if (elem == null) {
return; return;
@@ -262,7 +254,7 @@ public class CheckJPA<T> implements CheckFunctionInterface {
} else if (type == String.class) { } else if (type == String.class) {
final int maxSizeString = AnnotationTools.getLimitSize(field); final int maxSizeString = AnnotationTools.getLimitSize(field);
if (maxSizeString > 0) { if (maxSizeString > 0) {
add(fieldName, (final String baseName, final T data, final QueryOptions options) -> { add(fieldName, (final String baseName, final T data) -> {
final Object elem = field.get(data); final Object elem = field.get(data);
if (elem == null) { if (elem == null) {
return; return;
@@ -276,7 +268,7 @@ public class CheckJPA<T> implements CheckFunctionInterface {
} }
final Size limitSize = AnnotationTools.getConstraintsSize(field); final Size limitSize = AnnotationTools.getConstraintsSize(field);
if (limitSize != null) { if (limitSize != null) {
add(fieldName, (final String baseName, final T data, final QueryOptions options) -> { add(fieldName, (final String baseName, final T data) -> {
final Object elem = field.get(data); final Object elem = field.get(data);
if (elem == null) { if (elem == null) {
return; return;
@@ -288,14 +280,14 @@ public class CheckJPA<T> implements CheckFunctionInterface {
} }
if (elemTyped.length() < limitSize.min()) { if (elemTyped.length() < limitSize.min()) {
throw new InputException(baseName + fieldName, throw new InputException(baseName + fieldName,
"Too small size (constraints) must be >= " + limitSize.min()); "Too small size (constraints) must be >= " + limitSize.max());
} }
}); });
} }
final String patternString = AnnotationTools.getConstraintsPattern(field); final String patternString = AnnotationTools.getConstraintsPattern(field);
if (patternString != null) { if (patternString != null) {
final Pattern pattern = Pattern.compile(patternString); final Pattern pattern = Pattern.compile(patternString);
add(fieldName, (final String baseName, final T data, final QueryOptions options) -> { add(fieldName, (final String baseName, final T data) -> {
final Object elem = field.get(data); final Object elem = field.get(data);
if (elem == null) { if (elem == null) {
return; return;
@@ -314,8 +306,8 @@ public class CheckJPA<T> implements CheckFunctionInterface {
// Here if we have an error it crash at start and no new instance after creation... // Here if we have an error it crash at start and no new instance after creation...
final CheckFunctionInterface instance = jsonAnnotation.checker().getDeclaredConstructor() final CheckFunctionInterface instance = jsonAnnotation.checker().getDeclaredConstructor()
.newInstance(); .newInstance();
add(fieldName, (final String baseName, final T data, final QueryOptions options) -> { add(fieldName, (final String baseName, final T data) -> {
instance.checkAll(baseName + fieldName + ".", field.get(data), options); instance.checkAll(baseName + fieldName + ".", field.get(data));
}); });
} }
} else if (type.isEnum()) { } else if (type.isEnum()) {
@@ -324,17 +316,9 @@ public class CheckJPA<T> implements CheckFunctionInterface {
// keep this is last ==> take more time... // keep this is last ==> take more time...
if (AnnotationTools.isUnique(field)) { if (AnnotationTools.isUnique(field)) {
// Create the request ... // Create the request ...
add(fieldName, (final String baseName, final T data, final QueryOptions options) -> { add(fieldName, (final String baseName, final T data) -> {
final List<ConditionChecker> condCheckers = options.get(ConditionChecker.class); final Object other = DataAccess.getWhere(this.clazz,
Object other = null; new Condition(new QueryCondition(fieldName, "==", field.get(data))));
if (condCheckers.isEmpty()) {
other = DataAccess.getWhere(this.clazz,
new Condition(new QueryCondition(fieldName, "==", field.get(data))));
} else {
other = DataAccess.getWhere(this.clazz,
new Condition(new QueryCondition(fieldName, "==", field.get(data))),
condCheckers.get(0).toCondition());
}
if (other != null) { if (other != null) {
throw new InputException(baseName + fieldName, "Name already exist in the DB"); throw new InputException(baseName + fieldName, "Name already exist in the DB");
} }
@@ -349,11 +333,7 @@ public class CheckJPA<T> implements CheckFunctionInterface {
} }
@Override @Override
public void check( public void check(final String baseName, final Object data, final List<String> filterValue) throws Exception {
final String baseName,
final Object data,
final List<String> filterValue,
final QueryOptions options) throws Exception {
if (this.checking == null) { if (this.checking == null) {
initialize(); initialize();
} }
@@ -368,13 +348,13 @@ public class CheckJPA<T> implements CheckFunctionInterface {
continue; continue;
} }
for (final CheckInterface<T> action : actions) { for (final CheckInterface<T> action : actions) {
action.check(baseName, dataCasted, options); action.check(baseName, dataCasted);
} }
} }
checkTyped(dataCasted, filterValue, options); checkTyped(dataCasted, filterValue);
} }
public void checkTyped(final T data, final List<String> filterValue, final QueryOptions options) throws Exception { public void checkTyped(final T data, final List<String> filterValue) throws Exception {
// nothing to do ... // nothing to do ...
} }
} }

View File

@@ -1,21 +0,0 @@
package org.kar.archidata.dataAccess.options;
import org.kar.archidata.dataAccess.QueryItem;
/** Condition model apply to the check models. */
public class ConditionChecker extends QueryOption {
public final QueryItem condition;
public ConditionChecker(final QueryItem items) {
this.condition = items;
}
public ConditionChecker() {
this.condition = null;
}
public Condition toCondition() {
return new Condition(this.condition);
}
}

View File

@@ -13,7 +13,7 @@ public class AnalyzeApi {
static final Logger LOGGER = LoggerFactory.getLogger(AnalyzeApi.class); static final Logger LOGGER = LoggerFactory.getLogger(AnalyzeApi.class);
protected final List<ApiGroupModel> apiModels = new ArrayList<>(); protected final List<ApiGroupModel> apiModels = new ArrayList<>();
protected final ModelGroup modelGroup = new ModelGroup(); protected final ModelGroup modelGroup = new ModelGroup();
public void addAllModel(final List<Class<?>> classes) throws Exception { public void addAllModel(final List<Class<?>> classes) throws Exception {
this.modelGroup.addAll(classes); this.modelGroup.addAll(classes);
analyzeModels(); analyzeModels();
@@ -35,15 +35,15 @@ public class AnalyzeApi {
} }
analyzeModels(); analyzeModels();
} }
public List<ApiGroupModel> getAllApi() { public List<ApiGroupModel> getAllApi() {
return this.apiModels; return this.apiModels;
} }
public List<ClassModel> getAllModel() { public List<ClassModel> getAllModel() {
return this.modelGroup.getModels(); return this.modelGroup.getModels();
} }
private void analyzeModels() throws Exception { private void analyzeModels() throws Exception {
final List<ClassModel> dones = new ArrayList<>(); final List<ClassModel> dones = new ArrayList<>();
while (dones.size() < getAllModel().size()) { while (dones.size() < getAllModel().size()) {

View File

@@ -1,8 +1,8 @@
package org.kar.archidata.externalRestApi; package org.kar.archidata.externalRestApi;
public class PythonGenerateApi { public class PythonGenerateApi {
public static void generateApi(final AnalyzeApi api) { public static void generateApi(final AnalyzeApi api) {
} }
} }

View File

@@ -27,7 +27,7 @@ import jakarta.ws.rs.core.MediaType;
public class TsApiGeneration { public class TsApiGeneration {
static final Logger LOGGER = LoggerFactory.getLogger(TsApiGeneration.class); static final Logger LOGGER = LoggerFactory.getLogger(TsApiGeneration.class);
public static String getBaseHeader() { public static String getBaseHeader() {
return """ return """
/** /**
@@ -55,7 +55,7 @@ public class TsApiGeneration {
if (tsModel.nativeType != DefinedPosition.NATIVE) { if (tsModel.nativeType != DefinedPosition.NATIVE) {
imports.add(model); imports.add(model);
} }
if (tsModel.nativeType != DefinedPosition.NORMAL) { if (tsModel.nativeType == DefinedPosition.BASIC) {
return tsModel.tsTypeName; return tsModel.tsTypeName;
} }
if (writeMode) { if (writeMode) {
@@ -130,14 +130,14 @@ public class TsApiGeneration {
} }
return out.toString(); return out.toString();
} }
public static String capitalizeFirstLetter(final String str) { public static String capitalizeFirstLetter(final String str) {
if (str == null || str.isEmpty()) { if (str == null || str.isEmpty()) {
return str; return str;
} }
return str.substring(0, 1).toUpperCase() + str.substring(1); return str.substring(0, 1).toUpperCase() + str.substring(1);
} }
public static void generateApiFile( public static void generateApiFile(
final ApiGroupModel element, final ApiGroupModel element,
final String pathPackage, final String pathPackage,
@@ -348,11 +348,11 @@ public class TsApiGeneration {
data.append(", is"); data.append(", is");
data.append(returnModelNameIfComplex); data.append(returnModelNameIfComplex);
} else { } else {
final TsClassElement retType = tsGroup.find(interfaceElement.returnTypes.get(0)); final String returnType = generateClassModelsTypescript(interfaceElement.returnTypes, tsGroup, imports,
if (retType.tsCheckType != null) { false);
data.append(", "); if (!"void".equals(returnType)) {
data.append(retType.tsCheckType); data.append(", is");
imports.add(interfaceElement.returnTypes.get(0)); data.append(returnType);
} }
} }
data.append(");"); data.append(");");
@@ -393,9 +393,7 @@ public class TsApiGeneration {
if (tsModel.nativeType == DefinedPosition.NATIVE) { if (tsModel.nativeType == DefinedPosition.NATIVE) {
continue; continue;
} }
if (tsModel.tsCheckType != null) { finalImportList.add("is" + tsModel.tsTypeName);
finalImportList.add(tsModel.tsCheckType);
}
} }
for (final ClassModel model : zodImports) { for (final ClassModel model : zodImports) {
final TsClassElement tsModel = tsGroup.find(model); final TsClassElement tsModel = tsGroup.find(model);
@@ -431,5 +429,5 @@ public class TsApiGeneration {
myWriter.write(out.toString()); myWriter.write(out.toString());
myWriter.close(); myWriter.close();
} }
} }

View File

@@ -7,7 +7,6 @@ import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.util.List; import java.util.List;
import java.util.Map.Entry;
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;
@@ -20,13 +19,13 @@ import org.slf4j.LoggerFactory;
public class TsClassElement { public class TsClassElement {
static final Logger LOGGER = LoggerFactory.getLogger(TsClassElement.class); static final Logger LOGGER = LoggerFactory.getLogger(TsClassElement.class);
public enum DefinedPosition { public enum DefinedPosition {
NATIVE, // Native element of TS language. NATIVE, // Native element of TS language.
BASIC, // basic wrapping for JAVA type. BASIC, // basic wrapping for JAVA type.
NORMAL // Normal Object to interpret. NORMAL // Normal Object to interpret.
} }
public List<ClassModel> models; public List<ClassModel> models;
public String zodName; public String zodName;
public String tsTypeName; public String tsTypeName;
@@ -35,7 +34,7 @@ public class TsClassElement {
public String fileName = null; public String fileName = null;
public String comment = null; public String comment = null;
public DefinedPosition nativeType = DefinedPosition.NORMAL; public DefinedPosition nativeType = DefinedPosition.NORMAL;
public static String determineFileName(final String className) { 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(); return className.replaceAll("([a-z])([A-Z])", "$1-$2").replaceAll("([A-Z])([A-Z][a-z])", "$1-$2").toLowerCase();
} }
@@ -50,7 +49,7 @@ public class TsClassElement {
this.nativeType = nativeType; this.nativeType = nativeType;
this.fileName = determineFileName(tsTypeName); this.fileName = determineFileName(tsTypeName);
} }
public TsClassElement(final ClassModel model) { public TsClassElement(final ClassModel model) {
this.models = List.of(model); this.models = List.of(model);
this.zodName = "Zod" + model.getOriginClasses().getSimpleName(); this.zodName = "Zod" + model.getOriginClasses().getSimpleName();
@@ -59,34 +58,34 @@ public class TsClassElement {
this.declaration = null; this.declaration = null;
this.fileName = determineFileName(this.tsTypeName); this.fileName = determineFileName(this.tsTypeName);
} }
public boolean isCompatible(final ClassModel model) { public boolean isCompatible(final ClassModel model) {
return this.models.contains(model); return this.models.contains(model);
} }
public String getBaseHeader() { public String getBaseHeader() {
return """ return """
/** /**
* Interface of the server (auto-generated code) * Interface of the server (auto-generated code)
*/ */
import { z as zod } from "zod"; import { z as zod } from "zod";
"""; """;
} }
public String generateEnum(final ClassEnumModel model, final TsClassElementGroup tsGroup) throws IOException { public String generateEnum(final ClassEnumModel model, final TsClassElementGroup tsGroup) throws IOException {
final StringBuilder out = new StringBuilder(); final StringBuilder out = new StringBuilder();
out.append(getBaseHeader()); out.append(getBaseHeader());
out.append("\n"); out.append("\n");
//out.append(generateComment(model)); //out.append(generateComment(model));
if (System.getenv("ARCHIDATA_GENERATE_ZOD_ENUM") != null) { if (System.getenv("ARCHIDATA_GENERATE_ZOD_ENUM") != null) {
boolean first = true; boolean first = true;
out.append("export const "); out.append("export const ");
out.append(this.tsTypeName); out.append(this.tsTypeName);
out.append(" = "); out.append(" = ");
out.append("zod.enum(["); out.append("zod.enum([");
for (final Entry<String, Object> elem : model.getListOfValues().entrySet()) { for (final String elem : model.getListOfValues()) {
if (!first) { if (!first) {
out.append(",\n\t"); out.append(",\n\t");
} else { } else {
@@ -94,7 +93,7 @@ public class TsClassElement {
first = false; first = false;
} }
out.append("'"); out.append("'");
out.append(elem.getKey()); out.append(elem);
out.append("'"); out.append("'");
} }
if (first) { if (first) {
@@ -109,22 +108,17 @@ public class TsClassElement {
out.append("export enum "); out.append("export enum ");
out.append(this.tsTypeName); out.append(this.tsTypeName);
out.append(" {"); out.append(" {");
for (final Entry<String, Object> elem : model.getListOfValues().entrySet()) { for (final String elem : model.getListOfValues()) {
if (!first) { if (!first) {
out.append(",\n\t"); out.append(",\n\t");
} else { } else {
out.append("\n\t"); out.append("\n\t");
first = false; first = false;
} }
out.append(elem.getKey()); out.append(elem);
out.append(" = "); out.append(" = '");
if (elem.getValue() instanceof final Integer value) { out.append(elem);
out.append(value); out.append("'");
} else {
out.append("'");
out.append(elem.getValue());
out.append("'");
}
} }
if (first) { if (first) {
out.append("}"); out.append("}");
@@ -141,7 +135,7 @@ public class TsClassElement {
out.append(generateExportCheckFunctionWrite("")); out.append(generateExportCheckFunctionWrite(""));
return out.toString(); return out.toString();
} }
private static String generateExportCheckFunction( private static String generateExportCheckFunction(
final String tsCheckType, final String tsCheckType,
final String tsTypeName, final String tsTypeName,
@@ -167,12 +161,12 @@ public class TsClassElement {
"""); """);
return out.toString(); return out.toString();
} }
private String generateExportCheckFunctionWrite(final String writeString) { private String generateExportCheckFunctionWrite(final String writeString) {
return generateExportCheckFunction(this.tsCheckType + writeString, this.tsTypeName + writeString, return generateExportCheckFunction(this.tsCheckType + writeString, this.tsTypeName + writeString,
this.zodName + writeString); this.zodName + writeString);
} }
public String generateImports(final List<ClassModel> depModels, final TsClassElementGroup tsGroup) public String generateImports(final List<ClassModel> depModels, final TsClassElementGroup tsGroup)
throws IOException { throws IOException {
final StringBuilder out = new StringBuilder(); final StringBuilder out = new StringBuilder();
@@ -188,7 +182,7 @@ public class TsClassElement {
} }
return out.toString(); return out.toString();
} }
private Object generateComment(final ClassObjectModel model) { private Object generateComment(final ClassObjectModel model) {
final StringBuilder out = new StringBuilder(); final StringBuilder out = new StringBuilder();
if (model.getDescription() != null || model.getExample() != null) { if (model.getDescription() != null || model.getExample() != null) {
@@ -214,20 +208,12 @@ public class TsClassElement {
} }
return out.toString(); return out.toString();
} }
public String optionalTypeZod(final FieldProperty field) { 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()) { if (field.model().getOriginClasses() == null || field.model().getOriginClasses().isPrimitive()) {
return ""; return "";
} }
if (field.columnNotNull()) { if (field.notNull()) {
return ""; return "";
} }
return ".optional()"; return ".optional()";
@@ -250,12 +236,12 @@ public class TsClassElement {
} }
return ""; return "";
} }
public String generateBaseObject() { public String generateBaseObject() {
final StringBuilder out = new StringBuilder(); final StringBuilder out = new StringBuilder();
out.append(getBaseHeader()); out.append(getBaseHeader());
out.append("\n"); out.append("\n");
out.append("export const "); out.append("export const ");
out.append(this.zodName); out.append(this.zodName);
out.append(" = "); out.append(" = ");
@@ -270,12 +256,12 @@ public class TsClassElement {
out.append(getBaseHeader()); out.append(getBaseHeader());
out.append(generateImports(model.getDependencyModels(), tsGroup)); out.append(generateImports(model.getDependencyModels(), tsGroup));
out.append("\n"); out.append("\n");
out.append(generateComment(model)); out.append(generateComment(model));
out.append("export const "); out.append("export const ");
out.append(this.zodName); out.append(this.zodName);
out.append(" = "); out.append(" = ");
if (model.getExtendsClass() != null) { if (model.getExtendsClass() != null) {
final ClassModel parentClass = model.getExtendsClass(); final ClassModel parentClass = model.getExtendsClass();
final TsClassElement tsParentModel = tsGroup.find(parentClass); final TsClassElement tsParentModel = tsGroup.find(parentClass);
@@ -315,7 +301,7 @@ public class TsClassElement {
out.append("\n});\n"); out.append("\n});\n");
out.append(generateZodInfer(this.tsTypeName, this.zodName)); out.append(generateZodInfer(this.tsTypeName, this.zodName));
out.append(generateExportCheckFunctionWrite("")); out.append(generateExportCheckFunctionWrite(""));
// Generate the Write Type associated. // Generate the Write Type associated.
out.append("\nexport const "); out.append("\nexport const ");
out.append(this.zodName); out.append(this.zodName);
@@ -332,10 +318,10 @@ public class TsClassElement {
} }
out.append(".partial();\n"); out.append(".partial();\n");
out.append(generateZodInfer(this.tsTypeName + "Write", this.zodName + "Write")); out.append(generateZodInfer(this.tsTypeName + "Write", this.zodName + "Write"));
// Check only the input value ==> no need of the output // Check only the input value ==> no need of the output
out.append(generateExportCheckFunctionWrite("Write")); out.append(generateExportCheckFunctionWrite("Write"));
return out.toString(); return out.toString();
} }
@@ -382,17 +368,17 @@ public class TsClassElement {
out.append(")"); out.append(")");
return out.toString(); return out.toString();
} }
private static String generateTsEnum(final ClassEnumModel model, final TsClassElementGroup tsGroup) { private static String generateTsEnum(final ClassEnumModel model, final TsClassElementGroup tsGroup) {
final TsClassElement tsParentModel = tsGroup.find(model); final TsClassElement tsParentModel = tsGroup.find(model);
return tsParentModel.zodName; return tsParentModel.zodName;
} }
private static String generateTsObject(final ClassObjectModel model, final TsClassElementGroup tsGroup) { private static String generateTsObject(final ClassObjectModel model, final TsClassElementGroup tsGroup) {
final TsClassElement tsParentModel = tsGroup.find(model); final TsClassElement tsParentModel = tsGroup.find(model);
return tsParentModel.zodName; return tsParentModel.zodName;
} }
private static String generateTsList(final ClassListModel model, final TsClassElementGroup tsGroup) { private static String generateTsList(final ClassListModel model, final TsClassElementGroup tsGroup) {
final StringBuilder out = new StringBuilder(); final StringBuilder out = new StringBuilder();
out.append("zod.array("); out.append("zod.array(");
@@ -409,7 +395,7 @@ public class TsClassElement {
out.append(")"); out.append(")");
return out.toString(); return out.toString();
} }
public void generateFile(final String pathPackage, final TsClassElementGroup tsGroup) throws IOException { public void generateFile(final String pathPackage, final TsClassElementGroup tsGroup) throws IOException {
if (this.nativeType == DefinedPosition.NATIVE) { if (this.nativeType == DefinedPosition.NATIVE) {
return; return;
@@ -483,5 +469,5 @@ public class TsClassElement {
out.append(generateExportCheckFunction("is" + ModelName, ModelName, "Zod" + ModelName)); out.append(generateExportCheckFunction("is" + ModelName, ModelName, "Zod" + ModelName));
return out.toString(); return out.toString();
} }
} }

View File

@@ -17,9 +17,8 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.UUID; 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.catcher.RestErrorResponse;
import org.kar.archidata.dataAccess.DataFactoryTsApi;
import org.kar.archidata.externalRestApi.TsClassElement.DefinedPosition; import org.kar.archidata.externalRestApi.TsClassElement.DefinedPosition;
import org.kar.archidata.externalRestApi.model.ApiGroupModel; import org.kar.archidata.externalRestApi.model.ApiGroupModel;
import org.kar.archidata.externalRestApi.model.ClassModel; import org.kar.archidata.externalRestApi.model.ClassModel;
@@ -35,7 +34,7 @@ public class TsGenerateApi {
} }
// Generate index of model files // Generate index of model files
createModelIndex(pathPackage, tsGroup); createModelIndex(pathPackage, tsGroup);
for (final ApiGroupModel element : api.apiModels) { for (final ApiGroupModel element : api.apiModels) {
TsApiGeneration.generateApiFile(element, pathPackage, tsGroup); TsApiGeneration.generateApiFile(element, pathPackage, tsGroup);
} }
@@ -44,7 +43,7 @@ public class TsGenerateApi {
createIndex(pathPackage); createIndex(pathPackage);
copyResourceFile("rest-tools.ts", pathPackage + File.separator + "rest-tools.ts"); copyResourceFile("rest-tools.ts", pathPackage + File.separator + "rest-tools.ts");
} }
private static void createIndex(final String pathPackage) throws IOException { private static void createIndex(final String pathPackage) throws IOException {
final String out = """ final String out = """
/** /**
@@ -81,7 +80,7 @@ public class TsGenerateApi {
myWriter.write(out.toString()); myWriter.write(out.toString());
myWriter.close(); myWriter.close();
} }
private static void createModelIndex(final String pathPackage, final TsClassElementGroup tsGroup) private static void createModelIndex(final String pathPackage, final TsClassElementGroup tsGroup)
throws IOException { throws IOException {
final StringBuilder out = new StringBuilder(""" final StringBuilder out = new StringBuilder("""
@@ -107,7 +106,7 @@ public class TsGenerateApi {
myWriter.write(out.toString()); myWriter.write(out.toString());
myWriter.close(); myWriter.close();
} }
private static List<TsClassElement> generateApiModel(final AnalyzeApi api) throws Exception { private static List<TsClassElement> generateApiModel(final AnalyzeApi api) throws Exception {
// 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<>();
@@ -130,8 +129,7 @@ public class TsGenerateApi {
tsModels.add( tsModels.add(
new TsClassElement(models, "zod.string()", "string", null, "zod.string()", DefinedPosition.NATIVE)); new TsClassElement(models, "zod.string()", "string", null, "zod.string()", DefinedPosition.NATIVE));
} }
models = api.getCompatibleModels( models = api.getCompatibleModels(List.of(InputStream.class));
List.of(InputStream.class, FormDataContentDisposition.class, ContentDisposition.class));
if (models != null) { if (models != null) {
tsModels.add(new TsClassElement(models, "z.instanceof(File)", "File", null, "z.instanceof(File)", tsModels.add(new TsClassElement(models, "z.instanceof(File)", "File", null, "z.instanceof(File)",
DefinedPosition.NATIVE)); DefinedPosition.NATIVE));
@@ -212,11 +210,11 @@ public class TsGenerateApi {
tsModels.add(new TsClassElement(model)); tsModels.add(new TsClassElement(model));
} }
return tsModels; return tsModels;
} }
public static void copyResourceFile(final String name, final String destinationPath) throws IOException { public static void copyResourceFile(final String name, final String destinationPath) throws IOException {
final InputStream ioStream = TsGenerateApi.class.getClassLoader().getResourceAsStream(name); final InputStream ioStream = DataFactoryTsApi.class.getClassLoader().getResourceAsStream(name);
if (ioStream == null) { if (ioStream == null) {
throw new IllegalArgumentException("rest-tools.ts is not found"); throw new IllegalArgumentException("rest-tools.ts is not found");
} }

View File

@@ -14,10 +14,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);
Class<?> originClass; Class<?> originClass;
Method orignMethod; Method orignMethod;
// Name of the REST end-point name // Name of the REST end-point name
public String restEndPoint; public String restEndPoint;
// Type of the request: // Type of the request:
@@ -26,7 +26,7 @@ public class ApiModel {
public String description; public String description;
// need to generate the progression of stream (if possible) // need to generate the progression of stream (if possible)
public boolean needGenerateProgress; public boolean needGenerateProgress;
// List of types returned by the API // List of types returned by the API
public List<ClassModel> returnTypes = new ArrayList<>();; public List<ClassModel> returnTypes = new ArrayList<>();;
// Name of the API (function name) // Name of the API (function name)
@@ -39,12 +39,12 @@ public class ApiModel {
public final Map<String, List<ClassModel>> multiPartParameters = new HashMap<>(); public final Map<String, List<ClassModel>> 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<>();
// Possible input type of the REST API // Possible input type of the REST API
public List<String> consumes = new ArrayList<>(); public List<String> consumes = new ArrayList<>();
// Possible output type of the REST API // Possible output type of the REST API
public List<String> produces = new ArrayList<>(); public List<String> produces = new ArrayList<>();
private void updateReturnTypes(final Method method, final ModelGroup previousModel) throws Exception { private void updateReturnTypes(final Method method, final ModelGroup previousModel) throws Exception {
// get return type from the user specification: // get return type from the user specification:
final Class<?>[] returnTypeModel = ApiTool.apiAnnotationGetAsyncType(method); final Class<?>[] returnTypeModel = ApiTool.apiAnnotationGetAsyncType(method);
@@ -66,7 +66,7 @@ public class ApiModel {
} }
return; return;
} }
final Class<?> returnTypeModelRaw = method.getReturnType(); final Class<?> returnTypeModelRaw = method.getReturnType();
LOGGER.info("Get return Type RAW = {}", returnTypeModelRaw.getCanonicalName()); LOGGER.info("Get return Type RAW = {}", returnTypeModelRaw.getCanonicalName());
if (returnTypeModelRaw == Map.class) { if (returnTypeModelRaw == Map.class) {
@@ -92,12 +92,12 @@ public class ApiModel {
LOGGER.warn(" - {}", elem); LOGGER.warn(" - {}", elem);
} }
} }
public ApiModel(final Class<?> clazz, final Method method, final String baseRestEndPoint, public ApiModel(final Class<?> clazz, final Method method, final String baseRestEndPoint,
final List<String> consume, final List<String> produce, final ModelGroup previousModel) throws Exception { final List<String> consume, final List<String> produce, final ModelGroup previousModel) throws Exception {
this.originClass = clazz; this.originClass = clazz;
this.orignMethod = method; this.orignMethod = method;
String tmpPath = ApiTool.apiAnnotationGetPath(method); String tmpPath = ApiTool.apiAnnotationGetPath(method);
if (tmpPath == null) { if (tmpPath == null) {
tmpPath = ""; tmpPath = "";
@@ -105,19 +105,19 @@ public class ApiModel {
this.restEndPoint = baseRestEndPoint + "/" + tmpPath; this.restEndPoint = baseRestEndPoint + "/" + tmpPath;
this.restTypeRequest = ApiTool.apiAnnotationGetTypeRequest2(method); this.restTypeRequest = ApiTool.apiAnnotationGetTypeRequest2(method);
this.name = method.getName(); this.name = method.getName();
this.description = ApiTool.apiAnnotationGetOperationDescription(method); this.description = ApiTool.apiAnnotationGetOperationDescription(method);
this.consumes = ApiTool.apiAnnotationGetConsumes2(consume, method); this.consumes = ApiTool.apiAnnotationGetConsumes2(consume, method);
this.produces = ApiTool.apiAnnotationProduces2(produce, method); this.produces = ApiTool.apiAnnotationProduces2(produce, method);
LOGGER.trace(" [{}] {} => {}/{}", baseRestEndPoint, this.name, this.restEndPoint); LOGGER.trace(" [{}] {} => {}/{}", baseRestEndPoint, this.name, this.restEndPoint);
this.needGenerateProgress = ApiTool.apiAnnotationTypeScriptProgress(method); this.needGenerateProgress = ApiTool.apiAnnotationTypeScriptProgress(method);
updateReturnTypes(method, previousModel); updateReturnTypes(method, previousModel);
LOGGER.trace(" return: {}", this.returnTypes.size()); LOGGER.trace(" return: {}", this.returnTypes.size());
for (final ClassModel elem : this.returnTypes) { for (final ClassModel elem : this.returnTypes) {
LOGGER.trace(" - {}", elem); LOGGER.trace(" - {}", elem);
} }
// LOGGER.info(" Parameters:"); // LOGGER.info(" Parameters:");
for (final Parameter parameter : method.getParameters()) { for (final Parameter parameter : method.getParameters()) {
// Security context are internal parameter (not available from API) // Security context are internal parameter (not available from API)
@@ -129,8 +129,7 @@ public class ApiModel {
final Class<?>[] asyncType = ApiTool.apiAnnotationGetAsyncType(parameter); final Class<?>[] asyncType = ApiTool.apiAnnotationGetAsyncType(parameter);
if (asyncType != null) { if (asyncType != null) {
for (final Class<?> elem : asyncType) { for (final Class<?> elem : asyncType) {
final ClassModel modelGenerated = ClassModel.getModel(elem, previousModel); parameterModel.add(new ClassListModel(elem, previousModel));
parameterModel.add(modelGenerated);
} }
} else if (parameterType == List.class) { } else if (parameterType == List.class) {
final Type parameterrizedType = parameter.getParameterizedType(); final Type parameterrizedType = parameter.getParameterizedType();
@@ -143,22 +142,16 @@ public class ApiModel {
} else { } else {
parameterModel.add(previousModel.add(parameterType)); parameterModel.add(previousModel.add(parameterType));
} }
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);
if (queryParam != null) { if (queryParam != null) {
if (!this.queries.containsKey(queryParam)) { this.queries.put(queryParam, parameterModel);
this.queries.put(queryParam, parameterModel);
}
} else if (pathParam != null) { } else if (pathParam != null) {
if (!this.parameters.containsKey(pathParam)) { this.parameters.put(pathParam, parameterModel);
this.parameters.put(pathParam, parameterModel);
}
} else if (formDataParam != null) { } else if (formDataParam != null) {
if (!this.multiPartParameters.containsKey(formDataParam)) { this.multiPartParameters.put(formDataParam, parameterModel);
this.multiPartParameters.put(formDataParam, parameterModel);
}
} else { } else {
this.unnamedElement.addAll(parameterModel); this.unnamedElement.addAll(parameterModel);
} }
@@ -166,6 +159,6 @@ public class ApiModel {
if (this.unnamedElement.size() > 1) { if (this.unnamedElement.size() > 1) {
throw new IOException("Can not parse the API, enmpty element is more than 1 in " + this.name); throw new IOException("Can not parse the API, enmpty element is more than 1 in " + this.name);
} }
} }
} }

View File

@@ -9,6 +9,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.TypeScriptProgress; import org.kar.archidata.annotation.TypeScriptProgress;
import org.kar.archidata.dataAccess.DataFactoryZod.ClassElement;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
import jakarta.ws.rs.Consumes; import jakarta.ws.rs.Consumes;
@@ -205,4 +206,28 @@ public class ApiTool {
return element.getDeclaredAnnotationsByType(Context.class).length != 0; return element.getDeclaredAnnotationsByType(Context.class).length != 0;
} }
public static String convertInTypeScriptType(final List<ClassElement> tmp, final boolean isList) {
String out = "";
for (final ClassElement elem : tmp) {
if (out.length() != 0) {
out += " | ";
}
out += elem.tsTypeName;
if (isList) {
out += "[]";
}
}
return out;
}
public static String convertInTypeScriptCheckType(final List<ClassElement> tmp) {
String out = "";
for (final ClassElement elem : tmp) {
if (out.length() != 0) {
out += " | ";
}
out += elem.tsCheckType;
}
return out;
}
} }

View File

@@ -1,17 +1,16 @@
package org.kar.archidata.externalRestApi.model; package org.kar.archidata.externalRestApi.model;
import java.io.IOException; import java.io.IOException;
import java.lang.reflect.Method; import java.util.ArrayList;
import java.util.HashMap; import java.util.List;
import java.util.Map;
import java.util.Set; import java.util.Set;
public class ClassEnumModel extends ClassModel { public class ClassEnumModel extends ClassModel {
protected ClassEnumModel(final Class<?> clazz) { protected ClassEnumModel(final Class<?> clazz) {
this.originClasses = clazz; this.originClasses = clazz;
} }
@Override @Override
public String toString() { public String toString() {
final StringBuilder out = new StringBuilder(); final StringBuilder out = new StringBuilder();
@@ -20,45 +19,33 @@ public class ClassEnumModel extends ClassModel {
out.append("]"); out.append("]");
return out.toString(); return out.toString();
} }
final Map<String, Object> listOfValues = new HashMap<>(); final List<String> listOfValues = new ArrayList<>();
@Override @Override
public void analyze(final ModelGroup group) throws IOException { public void analyze(final ModelGroup group) throws IOException {
if (this.analyzeDone) { if (this.analyzeDone) {
return; return;
} }
this.analyzeDone = true; this.analyzeDone = true;
// TODO: check if we really need to have multiple type for enums ???
// TODO: manage enum with int, String and bitField ...
final Class<?> clazz = this.originClasses; final Class<?> clazz = this.originClasses;
final Object[] constants = clazz.getEnumConstants(); final Object[] arr = clazz.getEnumConstants();
for (final Object elem : arr) {
// Try to get a get Value element to serialize: this.listOfValues.add(elem.toString());
try {
final Method getValueMethod = clazz.getMethod("getValue");
for (final Object constant : constants) {
final String name = constant.toString();
final Object value = getValueMethod.invoke(constant);
this.listOfValues.put(name, value);
}
return;
} catch (final Exception e) {
//e.printStackTrace();
}
for (final Object elem : constants) {
this.listOfValues.put(elem.toString(), elem.toString());
} }
} }
public Map<String, Object> getListOfValues() { public List<String> getListOfValues() {
return this.listOfValues; return this.listOfValues;
} }
@Override @Override
public Set<ClassModel> getAlls() { public Set<ClassModel> getAlls() {
return Set.of(this); return Set.of(this);
} }
@Override @Override
public Set<ClassModel> getDependencyGroupModels() { public Set<ClassModel> getDependencyGroupModels() {
return Set.of(this); return Set.of(this);

View File

@@ -7,39 +7,39 @@ import java.util.Set;
public class ClassListModel extends ClassModel { public class ClassListModel extends ClassModel {
public ClassModel valueModel; public ClassModel valueModel;
public ClassListModel(final ClassModel valueModel) { public ClassListModel(final ClassModel valueModel) {
this.valueModel = valueModel; this.valueModel = valueModel;
} }
public ClassListModel(final Class<?> clazz, final ModelGroup previousModel) throws IOException { public ClassListModel(final Class<?> clazz, final ModelGroup previousModel) throws IOException {
this.valueModel = getModel(clazz, previousModel); this.valueModel = getModel(clazz, previousModel);
} }
public ClassListModel(final Type model, final ModelGroup previousModel) throws IOException { public ClassListModel(final Type model, final ModelGroup previousModel) throws IOException {
this.valueModel = getModel(model, previousModel); this.valueModel = getModel(model, previousModel);
} }
public ClassListModel(final ParameterizedType listType, final ModelGroup previousModel) throws IOException { public ClassListModel(final ParameterizedType listType, final ModelGroup previousModel) throws IOException {
final Type model = listType.getActualTypeArguments()[0]; final Type model = listType.getActualTypeArguments()[0];
this.valueModel = getModel(model, previousModel); this.valueModel = getModel(model, previousModel);
} }
@Override @Override
public String toString() { public String toString() {
return "ClassListModel [valueModel=" + this.valueModel + "]"; return "ClassListModel [valueModel=" + this.valueModel + "]";
} }
@Override @Override
public void analyze(final ModelGroup group) throws IOException { public void analyze(final ModelGroup group) throws IOException {
throw new IOException("Analyze can not be done at this phase for List..."); throw new IOException("Analyze can not be done at this phase for List...");
} }
@Override @Override
public Set<ClassModel> getAlls() { public Set<ClassModel> getAlls() {
return this.valueModel.getAlls(); return this.valueModel.getAlls();
} }
@Override @Override
public Set<ClassModel> getDependencyGroupModels() { public Set<ClassModel> getDependencyGroupModels() {
return this.valueModel.getDependencyGroupModels(); return this.valueModel.getDependencyGroupModels();

View File

@@ -9,40 +9,40 @@ import java.util.Set;
public class ClassMapModel extends ClassModel { public class ClassMapModel extends ClassModel {
public ClassModel keyModel; public ClassModel keyModel;
public ClassModel valueModel; public ClassModel valueModel;
public ClassMapModel(final ClassModel keyModel, final ClassModel valueModel) { public ClassMapModel(final ClassModel keyModel, final ClassModel valueModel) {
this.keyModel = keyModel; this.keyModel = keyModel;
this.valueModel = valueModel; this.valueModel = valueModel;
} }
public ClassMapModel(final Type listTypeKey, final Type listTypeValue, final ModelGroup previousModel) public ClassMapModel(final Type listTypeKey, final Type listTypeValue, final ModelGroup previousModel)
throws IOException { throws IOException {
this.keyModel = getModel(listTypeKey, previousModel); this.keyModel = getModel(listTypeKey, previousModel);
this.valueModel = getModel(listTypeValue, previousModel); this.valueModel = getModel(listTypeValue, previousModel);
} }
public ClassMapModel(final ParameterizedType listType, final ModelGroup previousModel) throws IOException { public ClassMapModel(final ParameterizedType listType, final ModelGroup previousModel) throws IOException {
this.keyModel = getModel(listType.getActualTypeArguments()[0], previousModel); this.keyModel = getModel(listType.getActualTypeArguments()[0], previousModel);
this.valueModel = getModel(listType.getActualTypeArguments()[1], previousModel); this.valueModel = getModel(listType.getActualTypeArguments()[1], previousModel);
} }
@Override @Override
public String toString() { public String toString() {
return "ClassMapModel [keyModel=" + this.keyModel + ", valueModel=" + this.valueModel + "]"; return "ClassMapModel [keyModel=" + this.keyModel + ", valueModel=" + this.valueModel + "]";
} }
@Override @Override
public void analyze(final ModelGroup group) throws IOException { public void analyze(final ModelGroup group) throws IOException {
throw new IOException("Analyze can not be done at this phase for Map..."); throw new IOException("Analyze can not be done at this phase for Map...");
} }
@Override @Override
public Set<ClassModel> getAlls() { public Set<ClassModel> getAlls() {
final Set<ClassModel> out = new HashSet<>(this.keyModel.getAlls()); final Set<ClassModel> out = new HashSet<>(this.keyModel.getAlls());
out.addAll(this.valueModel.getAlls()); out.addAll(this.valueModel.getAlls());
return out; return out;
} }
@Override @Override
public Set<ClassModel> getDependencyGroupModels() { public Set<ClassModel> getDependencyGroupModels() {
final Set<ClassModel> out = new HashSet<>(this.valueModel.getDependencyGroupModels()); final Set<ClassModel> out = new HashSet<>(this.valueModel.getDependencyGroupModels());

View File

@@ -24,7 +24,7 @@ public abstract class ClassModel {
public List<ClassModel> getDependencyModels() { public List<ClassModel> getDependencyModels() {
return this.dependencyModels; return this.dependencyModels;
} }
public abstract Set<ClassModel> getDependencyGroupModels(); public abstract Set<ClassModel> getDependencyGroupModels();
public static ClassModel getModel(final Type type, final ModelGroup previousModel) throws IOException { public static ClassModel getModel(final Type type, final ModelGroup previousModel) throws IOException {
@@ -70,7 +70,7 @@ public abstract class ClassModel {
public abstract void analyze(final ModelGroup group) throws Exception; public abstract void analyze(final ModelGroup group) throws Exception;
public abstract Set<ClassModel> getAlls(); public abstract Set<ClassModel> getAlls();
public List<String> getReadOnlyField() { public List<String> getReadOnlyField() {
return List.of(); return List.of();
} }

View File

@@ -15,11 +15,11 @@ import org.slf4j.LoggerFactory;
public class ClassObjectModel extends ClassModel { public class ClassObjectModel extends ClassModel {
static final Logger LOGGER = LoggerFactory.getLogger(ClassObjectModel.class); static final Logger LOGGER = LoggerFactory.getLogger(ClassObjectModel.class);
public ClassObjectModel(final Class<?> clazz) { public ClassObjectModel(final Class<?> clazz) {
this.originClasses = clazz; this.originClasses = clazz;
} }
@Override @Override
public String toString() { public String toString() {
final StringBuilder out = new StringBuilder(); final StringBuilder out = new StringBuilder();
@@ -28,7 +28,7 @@ public class ClassObjectModel extends ClassModel {
out.append("]"); out.append("]");
return out.toString(); return out.toString();
} }
private static boolean isFieldFromSuperClass(final Class<?> model, final String filedName) { private static boolean isFieldFromSuperClass(final Class<?> model, final String filedName) {
final Class<?> superClass = model.getSuperclass(); final Class<?> superClass = model.getSuperclass();
if (superClass == null) { if (superClass == null) {
@@ -48,30 +48,28 @@ public class ClassObjectModel extends ClassModel {
} }
return false; return false;
} }
public record FieldProperty( public record FieldProperty(
String name, String name,
ClassModel model, ClassModel model,
String comment, String comment,
int limitSize, int limitSize,
Boolean readOnly, boolean readOnly,
Boolean notNull, boolean notNull,
Boolean columnNotNull, boolean nullable) {
Boolean nullable) {
public FieldProperty(final String name, final ClassModel model, final String comment, final int limitSize, public FieldProperty(final String name, final ClassModel model, final String comment, final int limitSize,
final Boolean readOnly, final Boolean notNull, final Boolean columnNotNull, final Boolean nullable) { final boolean readOnly, final boolean notNull, final boolean nullable) {
this.name = name; this.name = name;
this.model = model; this.model = model;
this.comment = comment; this.comment = comment;
this.limitSize = limitSize; this.limitSize = limitSize;
this.readOnly = readOnly; this.readOnly = readOnly;
this.notNull = notNull; this.notNull = notNull;
this.columnNotNull = columnNotNull;
this.nullable = nullable; this.nullable = nullable;
} }
public FieldProperty(final Field field, final ModelGroup previous) throws Exception { public FieldProperty(final Field field, final ModelGroup previous) throws Exception {
this(field.getName(), // this(field.getName(), //
ClassModel.getModel(field.getGenericType(), previous), // ClassModel.getModel(field.getGenericType(), previous), //
@@ -79,43 +77,42 @@ public class ClassObjectModel extends ClassModel {
AnnotationTools.getLimitSize(field), // AnnotationTools.getLimitSize(field), //
AnnotationTools.getSchemaReadOnly(field), // AnnotationTools.getSchemaReadOnly(field), //
AnnotationTools.getConstraintsNotNull(field), // AnnotationTools.getConstraintsNotNull(field), //
AnnotationTools.getColumnNotNull(field), // AnnotationTools.getColumnNotNull(field));
AnnotationTools.getNullable(field));
} }
} }
String name = ""; String name = "";
boolean isPrimitive = false; boolean isPrimitive = false;
String description = null; String description = null;
String example = null; String example = null;
ClassModel extendsClass = null; ClassModel extendsClass = null;
List<FieldProperty> fields = new ArrayList<>(); List<FieldProperty> fields = new ArrayList<>();
public String getName() { public String getName() {
return this.name; return this.name;
} }
public boolean isPrimitive() { public boolean isPrimitive() {
return this.isPrimitive; return this.isPrimitive;
} }
public String getDescription() { public String getDescription() {
return this.description; return this.description;
} }
public String getExample() { public String getExample() {
return this.example; return this.example;
} }
public ClassModel getExtendsClass() { public ClassModel getExtendsClass() {
return this.extendsClass; return this.extendsClass;
} }
public List<FieldProperty> getFields() { public List<FieldProperty> getFields() {
return this.fields; return this.fields;
} }
@Override @Override
public void analyze(final ModelGroup previous) throws Exception { public void analyze(final ModelGroup previous) throws Exception {
if (this.analyzeDone) { if (this.analyzeDone) {
@@ -177,17 +174,17 @@ public class ClassObjectModel extends ClassModel {
this.dependencyModels.add(this.extendsClass); this.dependencyModels.add(this.extendsClass);
} }
} }
@Override @Override
public Set<ClassModel> getDependencyGroupModels() { public Set<ClassModel> getDependencyGroupModels() {
return Set.of(this); return Set.of(this);
} }
@Override @Override
public Set<ClassModel> getAlls() { public Set<ClassModel> getAlls() {
return Set.of(this); return Set.of(this);
} }
@Override @Override
public List<String> getReadOnlyField() { public List<String> getReadOnlyField() {
final List<String> out = new ArrayList<>(); final List<String> out = new ArrayList<>();
@@ -201,5 +198,5 @@ public class ClassObjectModel extends ClassModel {
} }
return out; return out;
} }
} }

View File

@@ -13,13 +13,13 @@ public class ModelGroup {
public List<ClassModel> models = new ArrayList<>(); public List<ClassModel> models = new ArrayList<>();
public ModelGroup() {} public ModelGroup() {}
public void addAll(final List<Class<?>> classes) { public void addAll(final List<Class<?>> classes) {
for (final Class<?> clazz : classes) { for (final Class<?> clazz : classes) {
add(clazz); add(clazz);
} }
} }
public ClassModel add(Class<?> clazz) { public ClassModel add(Class<?> clazz) {
if (clazz == Response.class) { if (clazz == Response.class) {
clazz = Object.class; clazz = Object.class;

View File

@@ -4,7 +4,6 @@ import org.kar.archidata.annotation.DataDeleted;
import org.kar.archidata.annotation.DataNotRead; import org.kar.archidata.annotation.DataNotRead;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.annotation.Nullable;
import jakarta.persistence.Column; import jakarta.persistence.Column;
import jakarta.ws.rs.DefaultValue; import jakarta.ws.rs.DefaultValue;
@@ -14,6 +13,5 @@ public class GenericDataSoftDelete extends GenericData {
@DefaultValue("'0'") @DefaultValue("'0'")
@DataDeleted @DataDeleted
@Schema(description = "Deleted state", hidden = true, required = false, readOnly = true) @Schema(description = "Deleted state", hidden = true, required = false, readOnly = true)
@Nullable
public Boolean deleted = null; public Boolean deleted = null;
} }

View File

@@ -9,7 +9,6 @@ import org.kar.archidata.annotation.UpdateTimestamp;
import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.annotation.Nullable;
import jakarta.persistence.Column; import jakarta.persistence.Column;
public class GenericTiming { public class GenericTiming {
@@ -18,7 +17,6 @@ public class GenericTiming {
@Column(nullable = false) @Column(nullable = false)
@Schema(description = "Create time of the object", required = false, example = "2000-01-23T01:23:45.678+01:00", readOnly = true) @Schema(description = "Create time of the object", required = false, example = "2000-01-23T01:23:45.678+01:00", readOnly = true)
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSXXX") @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSXXX")
@Nullable
public Date createdAt = null; public Date createdAt = null;
@DataNotRead @DataNotRead
@UpdateTimestamp @UpdateTimestamp
@@ -26,6 +24,5 @@ public class GenericTiming {
@Schema(description = "When update the object", required = false, example = "2000-01-23T00:23:45.678Z", readOnly = true) @Schema(description = "When update the object", required = false, example = "2000-01-23T00:23:45.678Z", readOnly = true)
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSXXX") @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSXXX")
// public Instant updatedAt = null; // public Instant updatedAt = null;
@Nullable
public Date updatedAt = null; public Date updatedAt = null;
} }

View File

@@ -8,13 +8,13 @@ import jakarta.persistence.Column;
public class GetToken { public class GetToken {
@Column(length = -1, nullable = false) @Column(length = -1, nullable = false)
public String jwt; public String jwt;
public GetToken() { public GetToken() {
} }
public GetToken(final String jwt) { public GetToken(final String jwt) {
this.jwt = jwt; this.jwt = jwt;
} }
} }

View File

@@ -9,9 +9,9 @@ public class Token {
public String token; public String token;
public String createTime; public String createTime;
public String endValidityTime; public String endValidityTime;
public Token() {} public Token() {}
public Token(final long id, final long userId, final String token, final String createTime, public Token(final long id, final long userId, final String token, final String createTime,
final String endValidityTime) { final String endValidityTime) {
this.id = id; this.id = id;
@@ -20,7 +20,7 @@ public class Token {
this.createTime = createTime; this.createTime = createTime;
this.endValidityTime = endValidityTime; this.endValidityTime = endValidityTime;
} }
public Token(final ResultSet rs) { public Token(final ResultSet rs) {
int iii = 1; int iii = 1;
try { try {
@@ -33,7 +33,7 @@ public class Token {
ex.printStackTrace(); ex.printStackTrace();
} }
} }
@Override @Override
public String toString() { public String toString() {
return "Token{" + "id=" + this.id + ", userId=" + this.userId + ", token='" + this.token + '\'' return "Token{" + "id=" + this.id + ", userId=" + this.userId + ", token='" + this.token + '\''

View File

@@ -4,7 +4,6 @@ import org.kar.archidata.annotation.DataDeleted;
import org.kar.archidata.annotation.DataNotRead; import org.kar.archidata.annotation.DataNotRead;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.annotation.Nullable;
import jakarta.persistence.Column; import jakarta.persistence.Column;
import jakarta.ws.rs.DefaultValue; import jakarta.ws.rs.DefaultValue;
@@ -14,6 +13,5 @@ public class UUIDGenericDataSoftDelete extends UUIDGenericData {
@DefaultValue("'0'") @DefaultValue("'0'")
@DataDeleted @DataDeleted
@Schema(description = "Deleted state", hidden = true, required = false, readOnly = true) @Schema(description = "Deleted state", hidden = true, required = false, readOnly = true)
@Nullable
public Boolean deleted = null; public Boolean deleted = null;
} }

View File

@@ -4,25 +4,25 @@
* @license MPL-2 * @license MPL-2
*/ */
import { RestErrorResponse } from "./model"; import { RestErrorResponse } from "./model"
export enum HTTPRequestModel { export enum HTTPRequestModel {
DELETE = "DELETE", DELETE = 'DELETE',
GET = "GET", GET = 'GET',
PATCH = "PATCH", PATCH = 'PATCH',
POST = "POST", POST = 'POST',
PUT = "PUT", PUT = 'PUT',
} }
export enum HTTPMimeType { export enum HTTPMimeType {
ALL = "*/*", ALL = '*/*',
CSV = "text/csv", CSV = 'text/csv',
IMAGE = "image/*", IMAGE = 'image/*',
IMAGE_JPEG = "image/jpeg", IMAGE_JPEG = 'image/jpeg',
IMAGE_PNG = "image/png", IMAGE_PNG = 'image/png',
JSON = "application/json", JSON = 'application/json',
MULTIPART = "multipart/form-data", MULTIPART = 'multipart/form-data',
OCTET_STREAM = "application/octet-stream", OCTET_STREAM = 'application/octet-stream',
TEXT_PLAIN = "text/plain", TEXT_PLAIN = 'text/plain',
} }
export interface RESTConfig { export interface RESTConfig {
@@ -58,61 +58,52 @@ function isNullOrUndefined(data: any): data is undefined | null {
export type ProgressCallback = (count: number, total: number) => void; export type ProgressCallback = (count: number, total: number) => void;
export interface RESTAbort { export interface RESTAbort {
abort?: () => boolean; abort?: () => boolean
} }
// Rest generic callback have a basic model to upload and download advancement. // Rest generic callback have a basic model to upload and download advancement.
export interface RESTCallbacks { export interface RESTCallbacks {
progressUpload?: ProgressCallback; progressUpload?: ProgressCallback,
progressDownload?: ProgressCallback; progressDownload?: ProgressCallback,
abortHandle?: RESTAbort; abortHandle?: RESTAbort,
} };
export interface RESTRequestType { export interface RESTRequestType {
restModel: RESTModel; restModel: RESTModel,
restConfig: RESTConfig; restConfig: RESTConfig,
data?: any; data?: any,
params?: object; params?: object,
queries?: object; queries?: object,
callback?: RESTCallbacks; callback?: RESTCallbacks,
} };
function replaceAll(input, searchValue, replaceValue) { function replaceAll(input, searchValue, replaceValue) {
return input.split(searchValue).join(replaceValue); return input.split(searchValue).join(replaceValue);
} }
function removeTrailingSlashes(input: string): string { function removeTrailingSlashes(input: string): string {
if (isNullOrUndefined(input)) { if (isNullOrUndefined(input)) {
return "undefined"; return "undefined";
} }
return input.replace(/\/+$/, ""); return input.replace(/\/+$/, '');
} }
function removeLeadingSlashes(input: string): string { function removeLeadingSlashes(input: string): string {
if (isNullOrUndefined(input)) { if (isNullOrUndefined(input)) {
return ""; return "";
} }
return input.replace(/^\/+/, ""); return input.replace(/^\/+/, '');
} }
export function RESTUrl({ export function RESTUrl({ restModel, restConfig, params, queries }: RESTRequestType): string {
restModel,
restConfig,
params,
queries,
}: RESTRequestType): string {
// Create the URL PATH: // Create the URL PATH:
let generateUrl = `${removeTrailingSlashes( let generateUrl = `${removeTrailingSlashes(restConfig.server)}/${removeLeadingSlashes(restModel.endPoint)}`;
restConfig.server
)}/${removeLeadingSlashes(restModel.endPoint)}`;
if (params !== undefined) { if (params !== undefined) {
for (let key of Object.keys(params)) { for (let key of Object.keys(params)) {
generateUrl = replaceAll(generateUrl, `{${key}}`, `${params[key]}`); generateUrl = replaceAll(generateUrl, `{${key}}`, `${params[key]}`);
} }
} }
if ( if (queries === undefined && (restConfig.token === undefined || restModel.tokenInUrl !== true)) {
queries === undefined &&
(restConfig.token === undefined || restModel.tokenInUrl !== true)
) {
return generateUrl; return generateUrl;
} }
const searchParams = new URLSearchParams(); const searchParams = new URLSearchParams();
@@ -120,8 +111,8 @@ export function RESTUrl({
for (let key of Object.keys(queries)) { for (let key of Object.keys(queries)) {
const value = queries[key]; const value = queries[key];
if (Array.isArray(value)) { if (Array.isArray(value)) {
for (const element of value) { for (let iii = 0; iii < value.length; iii++) {
searchParams.append(`${key}`, `${element}`); searchParams.append(`${key}`, `${value[iii]}`);
} }
} else { } else {
searchParams.append(`${key}`, `${value}`); searchParams.append(`${key}`, `${value}`);
@@ -129,43 +120,36 @@ export function RESTUrl({
} }
} }
if (restConfig.token !== undefined && restModel.tokenInUrl === true) { if (restConfig.token !== undefined && restModel.tokenInUrl === true) {
searchParams.append("Authorization", `Bearer ${restConfig.token}`); searchParams.append('Authorization', `Bearer ${restConfig.token}`);
} }
return generateUrl + "?" + searchParams.toString(); return generateUrl + "?" + searchParams.toString();
} }
export function fetchProgress(
generateUrl: string, export function fetchProgress(generateUrl: string, { method, headers, body }: {
{ method: HTTPRequestModel,
method, headers: any,
headers, body: any,
body, }, { progressUpload, progressDownload, abortHandle }: RESTCallbacks): Promise<Response> {
}: { const xhr = {
method: HTTPRequestModel; io: new XMLHttpRequest()
headers: any; }
body: any;
},
{ progressUpload, progressDownload, abortHandle }: RESTCallbacks
): Promise<Response> {
const xhr: {
io?: XMLHttpRequest;
} = {
io: new XMLHttpRequest(),
};
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
// Stream the upload progress // Stream the upload progress
if (progressUpload) { if (progressUpload) {
xhr.io?.upload.addEventListener("progress", (dataEvent) => { xhr.io.upload.addEventListener("progress", (dataEvent) => {
if (dataEvent.lengthComputable) { if (dataEvent.lengthComputable) {
//console.log(` ==> has a progress event: ${dataEvent.loaded} / ${dataEvent.total}`);
progressUpload(dataEvent.loaded, dataEvent.total); progressUpload(dataEvent.loaded, dataEvent.total);
} }
}); });
} }
// Stream the download progress // Stream the download progress
if (progressDownload) { if (progressDownload) {
xhr.io?.addEventListener("progress", (dataEvent) => { xhr.io.addEventListener("progress", (dataEvent) => {
if (dataEvent.lengthComputable) { if (dataEvent.lengthComputable) {
progressDownload(dataEvent.loaded, dataEvent.total); //console.log(` ==> download progress:: ${dataEvent.loaded} / ${dataEvent.total}`);
progressUpload(dataEvent.loaded, dataEvent.total);
} }
}); });
} }
@@ -176,43 +160,38 @@ export function fetchProgress(
xhr.io.abort(); xhr.io.abort();
return true; return true;
} }
console.log( console.log(`Request abort (FAIL) on the XMLHttpRequest: ${generateUrl}`);
`Request abort (FAIL) on the XMLHttpRequest: ${generateUrl}`
);
return false; return false;
}; }
} }
// Check if we have an internal Fail: // Check if we have an internal Fail:
xhr.io?.addEventListener("error", () => { xhr.io.addEventListener('error', () => {
xhr.io = undefined; xhr.io = undefined;
reject(new TypeError("Failed to fetch")); reject(new TypeError('Failed to fetch'))
}); });
// Capture the end of the stream // Capture the end of the stream
xhr.io?.addEventListener("loadend", () => { xhr.io.addEventListener("loadend", () => {
if (xhr.io?.readyState !== XMLHttpRequest.DONE) { if (xhr.io.readyState !== XMLHttpRequest.DONE) {
//console.log(` ==> READY state`);
return; return;
} }
if (xhr.io?.status === 0) { if (xhr.io.status === 0) {
//the stream has been aborted //the stream has been aborted
reject(new TypeError("Fetch has been aborted")); reject(new TypeError('Fetch has been aborted'));
return; return;
} }
// Stream is ended, transform in a generic response: // Stream is ended, transform in a generic response:
const response = new Response(xhr.io.response, { const response = new Response(xhr.io.response, {
status: xhr.io.status, status: xhr.io.status,
statusText: xhr.io.statusText, statusText: xhr.io.statusText
}); });
const headersArray = replaceAll( const headersArray = replaceAll(xhr.io.getAllResponseHeaders().trim(), "\r\n", "\n").split('\n');
xhr.io.getAllResponseHeaders().trim(),
"\r\n",
"\n"
).split("\n");
headersArray.forEach(function (header) { headersArray.forEach(function (header) {
const firstColonIndex = header.indexOf(":"); const firstColonIndex = header.indexOf(':');
if (firstColonIndex !== -1) { if (firstColonIndex !== -1) {
const key = header.substring(0, firstColonIndex).trim(); var key = header.substring(0, firstColonIndex).trim();
const value = header.substring(firstColonIndex + 1).trim(); var value = header.substring(firstColonIndex + 1).trim();
response.headers.set(key, value); response.headers.set(key, value);
} else { } else {
response.headers.set(header, ""); response.headers.set(header, "");
@@ -221,38 +200,31 @@ export function fetchProgress(
xhr.io = undefined; xhr.io = undefined;
resolve(response); resolve(response);
}); });
xhr.io?.open(method, generateUrl, true); xhr.io.open(method, generateUrl, true);
if (!isNullOrUndefined(headers)) { if (!isNullOrUndefined(headers)) {
for (const [key, value] of Object.entries(headers)) { for (const [key, value] of Object.entries(headers)) {
xhr.io?.setRequestHeader(key, value as string); xhr.io.setRequestHeader(key, value as string);
} }
} }
xhr.io?.send(body); xhr.io.send(body);
}); });
} }
export function RESTRequest({ export function RESTRequest({ restModel, restConfig, data, params, queries, callback }: RESTRequestType): Promise<ModelResponseHttp> {
restModel,
restConfig,
data,
params,
queries,
callback,
}: 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 });
let headers: any = {}; let headers: any = {};
if (restConfig.token !== undefined && restModel.tokenInUrl !== true) { if (restConfig.token !== undefined && restModel.tokenInUrl !== true) {
headers["Authorization"] = `Bearer ${restConfig.token}`; headers['Authorization'] = `Bearer ${restConfig.token}`;
} }
if (restModel.accept !== undefined) { if (restModel.accept !== undefined) {
headers["Accept"] = restModel.accept; headers['Accept'] = restModel.accept;
} }
if (restModel.requestType !== HTTPRequestModel.GET) { if (restModel.requestType !== HTTPRequestModel.GET) {
// if Get we have not a content type, the body is empty // if Get we have not a content type, the body is empty
if (restModel.contentType !== HTTPMimeType.MULTIPART) { if (restModel.contentType !== HTTPMimeType.MULTIPART) {
// special case of multi-part ==> no content type otherwise the browser does not set the ";bundary=--****" // special case of multi-part ==> no content type otherwise the browser does not set the ";bundary=--****"
headers["Content-Type"] = restModel.contentType; headers['Content-Type'] = restModel.contentType;
} }
} }
let body = data; let body = data;
@@ -263,16 +235,14 @@ export function RESTRequest({
for (const name in data) { for (const name in data) {
formData.append(name, data[name]); formData.append(name, data[name]);
} }
body = formData; body = formData
} }
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(callback) || || (isNullOrUndefined(callback.progressDownload)
(isNullOrUndefined(callback.progressDownload) && && isNullOrUndefined(callback.progressUpload)
isNullOrUndefined(callback.progressUpload) && && isNullOrUndefined(callback.abortHandle))) {
isNullOrUndefined(callback.abortHandle))
) {
// No information needed: call the generic fetch interface // No information needed: call the generic fetch interface
action = fetch(generateUrl, { action = fetch(generateUrl, {
method: restModel.requestType, method: restModel.requestType,
@@ -281,112 +251,92 @@ export function RESTRequest({
}); });
} else { } else {
// need progression information: call old fetch model (XMLHttpRequest) that permit to keep % upload and % download for HTTP1.x // need progression information: call old fetch model (XMLHttpRequest) that permit to keep % upload and % download for HTTP1.x
action = fetchProgress( action = fetchProgress(generateUrl, {
generateUrl, method: restModel.requestType ?? HTTPRequestModel.GET,
{ headers,
method: restModel.requestType ?? HTTPRequestModel.GET, body,
headers, }, callback);
body,
},
callback
);
} }
action action.then((response: Response) => {
.then((response: Response) => { if (response.status >= 200 && response.status <= 299) {
if (response.status >= 200 && response.status <= 299) { const contentType = response.headers.get('Content-Type');
const contentType = response.headers.get("Content-Type"); if (!isNullOrUndefined(restModel.accept) && restModel.accept !== contentType) {
if (
!isNullOrUndefined(restModel.accept) &&
restModel.accept !== contentType
) {
reject({
name: "Model accept type incompatible",
time: Date().toString(),
status: 901,
error: `REST check wrong type: ${restModel.accept} != ${contentType}`,
statusMessage: "Fetch error",
message: "rest-tools.ts Wrong type in the message return type",
} as RestErrorResponse);
} else if (contentType === HTTPMimeType.JSON) {
response
.json()
.then((value: any) => {
resolve({ status: response.status, data: value });
})
.catch((reason: any) => {
reject({
name: "API serialization error",
time: Date().toString(),
status: 902,
error: `REST parse json fail: ${reason}`,
statusMessage: "Fetch parse error",
message: "rest-tools.ts Wrong message model to parse",
} as RestErrorResponse);
});
} else {
resolve({ status: response.status, data: response.body });
}
} else {
reject({ reject({
name: "REST return no OK status",
time: Date().toString(), time: Date().toString(),
status: response.status, status: 901,
error: `${response.body}`, error: `REST check wrong type: ${restModel.accept} != ${contentType}`,
statusMessage: "Fetch code error", statusMessage: "Fetch error",
message: "rest-tools.ts Wrong return code", message: "rest-tools.ts Wrong type in the message return type"
} as RestErrorResponse); } as RestErrorResponse);
} else if (contentType === HTTPMimeType.JSON) {
response
.json()
.then((value: any) => {
//console.log(`RECEIVE ==> ${response.status}=${ JSON.stringify(value, null, 2)}`);
resolve({ status: response.status, data: value });
})
.catch((reason: any) => {
reject({
time: Date().toString(),
status: 902,
error: `REST parse json fail: ${reason}`,
statusMessage: "Fetch parse error",
message: "rest-tools.ts Wrong message model to parse"
} as RestErrorResponse);
});
} else {
resolve({ status: response.status, data: response.body });
} }
}) } else {
.catch((error: any) => {
reject({ reject({
name: "Request fail", time: Date().toString(),
time: Date(), status: response.status,
status: 999, error: `${response.body}`,
error: error, statusMessage: "Fetch code error",
statusMessage: "Fetch catch error", message: "rest-tools.ts Wrong return code"
message: "rest-tools.ts detect an error in the fetch request", } as RestErrorResponse);
}); }
}).catch((error: any) => {
reject({
time: Date(),
status: 999,
error: error,
statusMessage: "Fetch catch error",
message: "rest-tools.ts detect an error in the fetch request"
}); });
});
}); });
} }
export function RESTRequestJson<TYPE>( export function RESTRequestJson<TYPE>(request: RESTRequestType, checker: (data: any) => data is TYPE): Promise<TYPE> {
request: RESTRequestType,
checker?: (data: any) => data is TYPE
): Promise<TYPE> {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
RESTRequest(request) RESTRequest(request).then((value: ModelResponseHttp) => {
.then((value: ModelResponseHttp) => { if (isNullOrUndefined(checker)) {
if (isNullOrUndefined(checker)) { console.log(`Have no check of MODEL in API: ${RESTUrl(request)}`);
console.log(`Have no check of MODEL in API: ${RESTUrl(request)}`); resolve(value.data);
resolve(value.data); } else if (checker(value.data)) {
} else if (checker === undefined || checker(value.data)) { resolve(value.data);
resolve(value.data); } else {
} else { reject({
reject({ time: Date().toString(),
name: "Model check fail", status: 950,
time: Date().toString(), error: "REST Fail to verify the data",
status: 950, statusMessage: "API cast ERROR",
error: "REST Fail to verify the data", message: "api.ts Check type as fail"
statusMessage: "API cast ERROR", } as RestErrorResponse);
message: "api.ts Check type as fail", }
} as RestErrorResponse); }).catch((reason: RestErrorResponse) => {
} reject(reason);
}) });
.catch((reason: RestErrorResponse) => {
reject(reason);
});
}); });
} }
export function RESTRequestVoid(request: RESTRequestType): Promise<void> { export function RESTRequestVoid(request: RESTRequestType): Promise<void> {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
RESTRequest(request) RESTRequest(request).then((value: ModelResponseHttp) => {
.then((value: ModelResponseHttp) => { resolve();
resolve(); }).catch((reason: RestErrorResponse) => {
}) reject(reason);
.catch((reason: RestErrorResponse) => { });
reject(reason);
});
}); });
} }

View File

@@ -31,15 +31,15 @@ public class TestAnalyzeApiName {
final AnalyzeApi api = new AnalyzeApi(); final AnalyzeApi api = new AnalyzeApi();
api.addAllApi(List.of(ApiName.class)); api.addAllApi(List.of(ApiName.class));
Assertions.assertEquals(1, api.getAllApi().size()); Assertions.assertEquals(1, api.apiModels.size());
Assertions.assertEquals("ApiName", api.getAllApi().get(0).name); Assertions.assertEquals("ApiName", api.apiModels.get(0).name);
Assertions.assertEquals(2, api.getAllApi().get(0).interfaces.size()); Assertions.assertEquals(2, api.apiModels.get(0).interfaces.size());
{ {
final ApiModel model = api.getAllApi().get(0).getInterfaceNamed("firstName"); final ApiModel model = api.apiModels.get(0).getInterfaceNamed("firstName");
Assertions.assertNotNull(model); Assertions.assertNotNull(model);
} }
{ {
final ApiModel model = api.getAllApi().get(0).getInterfaceNamed("SecondName"); final ApiModel model = api.apiModels.get(0).getInterfaceNamed("SecondName");
Assertions.assertNotNull(model); Assertions.assertNotNull(model);
} }
} }

View File

@@ -0,0 +1,17 @@
package test.kar.archidata.externalRestApi;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class TestAnalyzeApiParameterParamQuery {
final static private Logger LOGGER = LoggerFactory.getLogger(TestAnalyzeApiParameterParamQuery.class);
@Test
public void testNotImplemented() throws Exception {
Assertions.assertEquals(1, 0);
}
}

View File

@@ -49,10 +49,10 @@ public class TestAnalyzeApiParameterType {
final AnalyzeApi api = new AnalyzeApi(); final AnalyzeApi api = new AnalyzeApi();
api.addAllApi(List.of(BasicParameter.class)); api.addAllApi(List.of(BasicParameter.class));
Assertions.assertEquals(1, api.getAllApi().size()); Assertions.assertEquals(1, api.apiModels.size());
Assertions.assertEquals(5, api.getAllApi().get(0).interfaces.size()); Assertions.assertEquals(5, api.apiModels.get(0).interfaces.size());
{ {
final ApiModel model = api.getAllApi().get(0).getInterfaceNamed("setInteger1"); final ApiModel model = api.apiModels.get(0).getInterfaceNamed("setInteger1");
Assertions.assertNotNull(model); Assertions.assertNotNull(model);
Assertions.assertEquals(1, model.unnamedElement.size()); Assertions.assertEquals(1, model.unnamedElement.size());
final ClassObjectModel classModel = Assertions.assertInstanceOf(ClassObjectModel.class, final ClassObjectModel classModel = Assertions.assertInstanceOf(ClassObjectModel.class,
@@ -60,7 +60,7 @@ public class TestAnalyzeApiParameterType {
Assertions.assertEquals(int.class, classModel.getOriginClasses()); Assertions.assertEquals(int.class, classModel.getOriginClasses());
} }
{ {
final ApiModel model = api.getAllApi().get(0).getInterfaceNamed("setInteger2"); final ApiModel model = api.apiModels.get(0).getInterfaceNamed("setInteger2");
Assertions.assertNotNull(model); Assertions.assertNotNull(model);
Assertions.assertEquals(1, model.unnamedElement.size()); Assertions.assertEquals(1, model.unnamedElement.size());
final ClassObjectModel classModel = Assertions.assertInstanceOf(ClassObjectModel.class, final ClassObjectModel classModel = Assertions.assertInstanceOf(ClassObjectModel.class,
@@ -68,7 +68,7 @@ public class TestAnalyzeApiParameterType {
Assertions.assertEquals(Integer.class, classModel.getOriginClasses()); Assertions.assertEquals(Integer.class, classModel.getOriginClasses());
} }
{ {
final ApiModel model = api.getAllApi().get(0).getInterfaceNamed("setString"); final ApiModel model = api.apiModels.get(0).getInterfaceNamed("setString");
Assertions.assertNotNull(model); Assertions.assertNotNull(model);
Assertions.assertEquals(1, model.unnamedElement.size()); Assertions.assertEquals(1, model.unnamedElement.size());
final ClassObjectModel classModel = Assertions.assertInstanceOf(ClassObjectModel.class, final ClassObjectModel classModel = Assertions.assertInstanceOf(ClassObjectModel.class,
@@ -76,7 +76,7 @@ public class TestAnalyzeApiParameterType {
Assertions.assertEquals(String.class, classModel.getOriginClasses()); Assertions.assertEquals(String.class, classModel.getOriginClasses());
} }
{ {
final ApiModel model = api.getAllApi().get(0).getInterfaceNamed("setObject"); final ApiModel model = api.apiModels.get(0).getInterfaceNamed("setObject");
Assertions.assertNotNull(model); Assertions.assertNotNull(model);
Assertions.assertEquals(1, model.unnamedElement.size()); Assertions.assertEquals(1, model.unnamedElement.size());
final ClassObjectModel classModel = Assertions.assertInstanceOf(ClassObjectModel.class, final ClassObjectModel classModel = Assertions.assertInstanceOf(ClassObjectModel.class,
@@ -84,7 +84,7 @@ public class TestAnalyzeApiParameterType {
Assertions.assertEquals(TestObject.class, classModel.getOriginClasses()); Assertions.assertEquals(TestObject.class, classModel.getOriginClasses());
} }
{ {
final ApiModel model = api.getAllApi().get(0).getInterfaceNamed("setEnum"); final ApiModel model = api.apiModels.get(0).getInterfaceNamed("setEnum");
Assertions.assertNotNull(model); Assertions.assertNotNull(model);
Assertions.assertEquals(1, model.unnamedElement.size()); Assertions.assertEquals(1, model.unnamedElement.size());
final ClassEnumModel classModel = Assertions.assertInstanceOf(ClassEnumModel.class, final ClassEnumModel classModel = Assertions.assertInstanceOf(ClassEnumModel.class,
@@ -104,9 +104,9 @@ public class TestAnalyzeApiParameterType {
final AnalyzeApi api = new AnalyzeApi(); final AnalyzeApi api = new AnalyzeApi();
api.addAllApi(List.of(ListParameter.class)); api.addAllApi(List.of(ListParameter.class));
Assertions.assertEquals(1, api.getAllApi().size()); Assertions.assertEquals(1, api.apiModels.size());
Assertions.assertEquals(1, api.getAllApi().get(0).interfaces.size()); Assertions.assertEquals(1, api.apiModels.get(0).interfaces.size());
final ApiModel model = api.getAllApi().get(0).getInterfaceNamed("setList"); final ApiModel model = api.apiModels.get(0).getInterfaceNamed("setList");
Assertions.assertNotNull(model); Assertions.assertNotNull(model);
Assertions.assertEquals(1, model.unnamedElement.size()); Assertions.assertEquals(1, model.unnamedElement.size());
final ClassListModel classModel = Assertions.assertInstanceOf(ClassListModel.class, final ClassListModel classModel = Assertions.assertInstanceOf(ClassListModel.class,
@@ -127,9 +127,9 @@ public class TestAnalyzeApiParameterType {
final AnalyzeApi api = new AnalyzeApi(); final AnalyzeApi api = new AnalyzeApi();
api.addAllApi(List.of(MapParameter.class)); api.addAllApi(List.of(MapParameter.class));
Assertions.assertEquals(1, api.getAllApi().size()); Assertions.assertEquals(1, api.apiModels.size());
Assertions.assertEquals(1, api.getAllApi().get(0).interfaces.size()); Assertions.assertEquals(1, api.apiModels.get(0).interfaces.size());
final ApiModel model = api.getAllApi().get(0).getInterfaceNamed("setMap"); final ApiModel model = api.apiModels.get(0).getInterfaceNamed("setMap");
Assertions.assertNotNull(model); Assertions.assertNotNull(model);
Assertions.assertEquals(1, model.unnamedElement.size()); Assertions.assertEquals(1, model.unnamedElement.size());
final ClassMapModel classModel = Assertions.assertInstanceOf(ClassMapModel.class, model.unnamedElement.get(0)); final ClassMapModel classModel = Assertions.assertInstanceOf(ClassMapModel.class, model.unnamedElement.get(0));

View File

@@ -0,0 +1,17 @@
package test.kar.archidata.externalRestApi;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class TestAnalyzeApiParameterTypeAsync {
final static private Logger LOGGER = LoggerFactory.getLogger(TestAnalyzeApiParameterTypeAsync.class);
@Test
public void testNotImplemented() throws Exception {
Assertions.assertEquals(1, 0);
}
}

View File

@@ -39,21 +39,21 @@ public class TestAnalyzeApiPath {
final AnalyzeApi api = new AnalyzeApi(); final AnalyzeApi api = new AnalyzeApi();
api.addAllApi(List.of(NoPath.class)); api.addAllApi(List.of(NoPath.class));
Assertions.assertEquals(1, api.getAllApi().size()); Assertions.assertEquals(1, api.apiModels.size());
Assertions.assertEquals("", api.getAllApi().get(0).restEndPoint); Assertions.assertEquals("", api.apiModels.get(0).restEndPoint);
Assertions.assertEquals(3, api.getAllApi().get(0).interfaces.size()); Assertions.assertEquals(3, api.apiModels.get(0).interfaces.size());
{ {
final ApiModel model = api.getAllApi().get(0).getInterfaceNamed("noPath"); final ApiModel model = api.apiModels.get(0).getInterfaceNamed("noPath");
Assertions.assertNotNull(model); Assertions.assertNotNull(model);
Assertions.assertEquals("/", model.restEndPoint); Assertions.assertEquals("/", model.restEndPoint);
} }
{ {
final ApiModel model = api.getAllApi().get(0).getInterfaceNamed("withPath"); final ApiModel model = api.apiModels.get(0).getInterfaceNamed("withPath");
Assertions.assertNotNull(model); Assertions.assertNotNull(model);
Assertions.assertEquals("/plop", model.restEndPoint); Assertions.assertEquals("/plop", model.restEndPoint);
} }
{ {
final ApiModel model = api.getAllApi().get(0).getInterfaceNamed("withPath2"); final ApiModel model = api.apiModels.get(0).getInterfaceNamed("withPath2");
Assertions.assertNotNull(model); Assertions.assertNotNull(model);
Assertions.assertEquals("//plop", model.restEndPoint); Assertions.assertEquals("//plop", model.restEndPoint);
} }
@@ -84,21 +84,21 @@ public class TestAnalyzeApiPath {
final AnalyzeApi api = new AnalyzeApi(); final AnalyzeApi api = new AnalyzeApi();
api.addAllApi(List.of(WithPath.class)); api.addAllApi(List.of(WithPath.class));
Assertions.assertEquals(1, api.getAllApi().size()); Assertions.assertEquals(1, api.apiModels.size());
Assertions.assertEquals("/kaboom", api.getAllApi().get(0).restEndPoint); Assertions.assertEquals("/kaboom", api.apiModels.get(0).restEndPoint);
Assertions.assertEquals(3, api.getAllApi().get(0).interfaces.size()); Assertions.assertEquals(3, api.apiModels.get(0).interfaces.size());
{ {
final ApiModel model = api.getAllApi().get(0).getInterfaceNamed("noPath"); final ApiModel model = api.apiModels.get(0).getInterfaceNamed("noPath");
Assertions.assertNotNull(model); Assertions.assertNotNull(model);
Assertions.assertEquals("/kaboom/", model.restEndPoint); Assertions.assertEquals("/kaboom/", model.restEndPoint);
} }
{ {
final ApiModel model = api.getAllApi().get(0).getInterfaceNamed("withPath"); final ApiModel model = api.apiModels.get(0).getInterfaceNamed("withPath");
Assertions.assertNotNull(model); Assertions.assertNotNull(model);
Assertions.assertEquals("/kaboom/plop", model.restEndPoint); Assertions.assertEquals("/kaboom/plop", model.restEndPoint);
} }
{ {
final ApiModel model = api.getAllApi().get(0).getInterfaceNamed("withPath2"); final ApiModel model = api.apiModels.get(0).getInterfaceNamed("withPath2");
Assertions.assertNotNull(model); Assertions.assertNotNull(model);
Assertions.assertEquals("/kaboom//plop", model.restEndPoint); Assertions.assertEquals("/kaboom//plop", model.restEndPoint);
} }

View File

@@ -43,10 +43,10 @@ public class TestAnalyzeApiReturn {
final AnalyzeApi api = new AnalyzeApi(); final AnalyzeApi api = new AnalyzeApi();
api.addAllApi(List.of(ReturnValueVoid.class)); api.addAllApi(List.of(ReturnValueVoid.class));
Assertions.assertEquals(1, api.getAllApi().size()); Assertions.assertEquals(1, api.apiModels.size());
Assertions.assertEquals(2, api.getAllApi().get(0).interfaces.size()); Assertions.assertEquals(2, api.apiModels.get(0).interfaces.size());
{ {
final ApiModel model = api.getAllApi().get(0).getInterfaceNamed("getVoid1"); final ApiModel model = api.apiModels.get(0).getInterfaceNamed("getVoid1");
Assertions.assertNotNull(model); Assertions.assertNotNull(model);
Assertions.assertEquals(1, model.returnTypes.size()); Assertions.assertEquals(1, model.returnTypes.size());
final ClassObjectModel classModel = Assertions.assertInstanceOf(ClassObjectModel.class, final ClassObjectModel classModel = Assertions.assertInstanceOf(ClassObjectModel.class,
@@ -54,7 +54,7 @@ public class TestAnalyzeApiReturn {
Assertions.assertEquals(void.class, classModel.getOriginClasses()); Assertions.assertEquals(void.class, classModel.getOriginClasses());
} }
{ {
final ApiModel model = api.getAllApi().get(0).getInterfaceNamed("getVoid2"); final ApiModel model = api.apiModels.get(0).getInterfaceNamed("getVoid2");
Assertions.assertNotNull(model); Assertions.assertNotNull(model);
Assertions.assertEquals(1, model.returnTypes.size()); Assertions.assertEquals(1, model.returnTypes.size());
final ClassObjectModel classModel = Assertions.assertInstanceOf(ClassObjectModel.class, final ClassObjectModel classModel = Assertions.assertInstanceOf(ClassObjectModel.class,
@@ -82,11 +82,11 @@ public class TestAnalyzeApiReturn {
final AnalyzeApi api = new AnalyzeApi(); final AnalyzeApi api = new AnalyzeApi();
api.addAllApi(List.of(ReturnValueInteger.class)); api.addAllApi(List.of(ReturnValueInteger.class));
Assertions.assertEquals(1, api.getAllApi().size()); Assertions.assertEquals(1, api.apiModels.size());
Assertions.assertEquals(2, api.getAllApi().get(0).interfaces.size()); Assertions.assertEquals(2, api.apiModels.get(0).interfaces.size());
// Check int // Check int
{ {
final ApiModel model = api.getAllApi().get(0).getInterfaceNamed("getInteger1"); final ApiModel model = api.apiModels.get(0).getInterfaceNamed("getInteger1");
Assertions.assertNotNull(model); Assertions.assertNotNull(model);
Assertions.assertEquals(1, model.returnTypes.size()); Assertions.assertEquals(1, model.returnTypes.size());
final ClassObjectModel classModel = Assertions.assertInstanceOf(ClassObjectModel.class, final ClassObjectModel classModel = Assertions.assertInstanceOf(ClassObjectModel.class,
@@ -95,7 +95,7 @@ public class TestAnalyzeApiReturn {
} }
// Check Integer // Check Integer
{ {
final ApiModel model = api.getAllApi().get(0).getInterfaceNamed("getInteger2"); final ApiModel model = api.apiModels.get(0).getInterfaceNamed("getInteger2");
Assertions.assertNotNull(model); Assertions.assertNotNull(model);
Assertions.assertEquals(1, model.returnTypes.size()); Assertions.assertEquals(1, model.returnTypes.size());
final ClassObjectModel classModel = Assertions.assertInstanceOf(ClassObjectModel.class, final ClassObjectModel classModel = Assertions.assertInstanceOf(ClassObjectModel.class,
@@ -123,11 +123,11 @@ public class TestAnalyzeApiReturn {
final AnalyzeApi api = new AnalyzeApi(); final AnalyzeApi api = new AnalyzeApi();
api.addAllApi(List.of(ReturnValueShort.class)); api.addAllApi(List.of(ReturnValueShort.class));
Assertions.assertEquals(1, api.getAllApi().size()); Assertions.assertEquals(1, api.apiModels.size());
Assertions.assertEquals(2, api.getAllApi().get(0).interfaces.size()); Assertions.assertEquals(2, api.apiModels.get(0).interfaces.size());
// Check short // Check short
{ {
final ApiModel model = api.getAllApi().get(0).getInterfaceNamed("getShort1"); final ApiModel model = api.apiModels.get(0).getInterfaceNamed("getShort1");
Assertions.assertNotNull(model); Assertions.assertNotNull(model);
Assertions.assertEquals(1, model.returnTypes.size()); Assertions.assertEquals(1, model.returnTypes.size());
final ClassObjectModel classModel = Assertions.assertInstanceOf(ClassObjectModel.class, final ClassObjectModel classModel = Assertions.assertInstanceOf(ClassObjectModel.class,
@@ -136,7 +136,7 @@ public class TestAnalyzeApiReturn {
} }
// Check Short // Check Short
{ {
final ApiModel model = api.getAllApi().get(0).getInterfaceNamed("getShort2"); final ApiModel model = api.apiModels.get(0).getInterfaceNamed("getShort2");
Assertions.assertNotNull(model); Assertions.assertNotNull(model);
Assertions.assertEquals(1, model.returnTypes.size()); Assertions.assertEquals(1, model.returnTypes.size());
final ClassObjectModel classModel = Assertions.assertInstanceOf(ClassObjectModel.class, final ClassObjectModel classModel = Assertions.assertInstanceOf(ClassObjectModel.class,
@@ -164,11 +164,11 @@ public class TestAnalyzeApiReturn {
final AnalyzeApi api = new AnalyzeApi(); final AnalyzeApi api = new AnalyzeApi();
api.addAllApi(List.of(ReturnValueLong.class)); api.addAllApi(List.of(ReturnValueLong.class));
Assertions.assertEquals(1, api.getAllApi().size()); Assertions.assertEquals(1, api.apiModels.size());
Assertions.assertEquals(2, api.getAllApi().get(0).interfaces.size()); Assertions.assertEquals(2, api.apiModels.get(0).interfaces.size());
// Check long // Check long
{ {
final ApiModel model = api.getAllApi().get(0).getInterfaceNamed("getLong1"); final ApiModel model = api.apiModels.get(0).getInterfaceNamed("getLong1");
Assertions.assertNotNull(model); Assertions.assertNotNull(model);
Assertions.assertEquals(1, model.returnTypes.size()); Assertions.assertEquals(1, model.returnTypes.size());
final ClassObjectModel classModel = Assertions.assertInstanceOf(ClassObjectModel.class, final ClassObjectModel classModel = Assertions.assertInstanceOf(ClassObjectModel.class,
@@ -177,7 +177,7 @@ public class TestAnalyzeApiReturn {
} }
// Check Long // Check Long
{ {
final ApiModel model = api.getAllApi().get(0).getInterfaceNamed("getLong2"); final ApiModel model = api.apiModels.get(0).getInterfaceNamed("getLong2");
Assertions.assertNotNull(model); Assertions.assertNotNull(model);
Assertions.assertEquals(1, model.returnTypes.size()); Assertions.assertEquals(1, model.returnTypes.size());
Assertions.assertInstanceOf(ClassObjectModel.class, model.returnTypes.get(0)); Assertions.assertInstanceOf(ClassObjectModel.class, model.returnTypes.get(0));
@@ -206,11 +206,11 @@ public class TestAnalyzeApiReturn {
final AnalyzeApi api = new AnalyzeApi(); final AnalyzeApi api = new AnalyzeApi();
api.addAllApi(List.of(ReturnValueFloat.class)); api.addAllApi(List.of(ReturnValueFloat.class));
Assertions.assertEquals(1, api.getAllApi().size()); Assertions.assertEquals(1, api.apiModels.size());
Assertions.assertEquals(2, api.getAllApi().get(0).interfaces.size()); Assertions.assertEquals(2, api.apiModels.get(0).interfaces.size());
// Check float // Check float
{ {
final ApiModel model = api.getAllApi().get(0).getInterfaceNamed("getFloat1"); final ApiModel model = api.apiModels.get(0).getInterfaceNamed("getFloat1");
Assertions.assertNotNull(model); Assertions.assertNotNull(model);
Assertions.assertEquals(1, model.returnTypes.size()); Assertions.assertEquals(1, model.returnTypes.size());
final ClassObjectModel classModel = Assertions.assertInstanceOf(ClassObjectModel.class, final ClassObjectModel classModel = Assertions.assertInstanceOf(ClassObjectModel.class,
@@ -219,7 +219,7 @@ public class TestAnalyzeApiReturn {
} }
// Check Float // Check Float
{ {
final ApiModel model = api.getAllApi().get(0).getInterfaceNamed("getFloat2"); final ApiModel model = api.apiModels.get(0).getInterfaceNamed("getFloat2");
Assertions.assertNotNull(model); Assertions.assertNotNull(model);
Assertions.assertEquals(1, model.returnTypes.size()); Assertions.assertEquals(1, model.returnTypes.size());
final ClassObjectModel classModel = Assertions.assertInstanceOf(ClassObjectModel.class, final ClassObjectModel classModel = Assertions.assertInstanceOf(ClassObjectModel.class,
@@ -247,11 +247,11 @@ public class TestAnalyzeApiReturn {
final AnalyzeApi api = new AnalyzeApi(); final AnalyzeApi api = new AnalyzeApi();
api.addAllApi(List.of(ReturnValueDouble.class)); api.addAllApi(List.of(ReturnValueDouble.class));
Assertions.assertEquals(1, api.getAllApi().size()); Assertions.assertEquals(1, api.apiModels.size());
Assertions.assertEquals(2, api.getAllApi().get(0).interfaces.size()); Assertions.assertEquals(2, api.apiModels.get(0).interfaces.size());
// Check double // Check double
{ {
final ApiModel model = api.getAllApi().get(0).getInterfaceNamed("getDouble1"); final ApiModel model = api.apiModels.get(0).getInterfaceNamed("getDouble1");
Assertions.assertNotNull(model); Assertions.assertNotNull(model);
Assertions.assertEquals(1, model.returnTypes.size()); Assertions.assertEquals(1, model.returnTypes.size());
final ClassObjectModel classModel = Assertions.assertInstanceOf(ClassObjectModel.class, final ClassObjectModel classModel = Assertions.assertInstanceOf(ClassObjectModel.class,
@@ -260,7 +260,7 @@ public class TestAnalyzeApiReturn {
} }
// Check Double // Check Double
{ {
final ApiModel model = api.getAllApi().get(0).getInterfaceNamed("getDouble2"); final ApiModel model = api.apiModels.get(0).getInterfaceNamed("getDouble2");
Assertions.assertNotNull(model); Assertions.assertNotNull(model);
Assertions.assertEquals(1, model.returnTypes.size()); Assertions.assertEquals(1, model.returnTypes.size());
final ClassObjectModel classModel = Assertions.assertInstanceOf(ClassObjectModel.class, final ClassObjectModel classModel = Assertions.assertInstanceOf(ClassObjectModel.class,
@@ -283,11 +283,11 @@ public class TestAnalyzeApiReturn {
final AnalyzeApi api = new AnalyzeApi(); final AnalyzeApi api = new AnalyzeApi();
api.addAllApi(List.of(ReturnValueString.class)); api.addAllApi(List.of(ReturnValueString.class));
Assertions.assertEquals(1, api.getAllApi().size()); Assertions.assertEquals(1, api.apiModels.size());
Assertions.assertEquals(1, api.getAllApi().get(0).interfaces.size()); Assertions.assertEquals(1, api.apiModels.get(0).interfaces.size());
// Check String // Check String
{ {
final ApiModel model = api.getAllApi().get(0).getInterfaceNamed("getString"); final ApiModel model = api.apiModels.get(0).getInterfaceNamed("getString");
Assertions.assertNotNull(model); Assertions.assertNotNull(model);
Assertions.assertEquals(1, model.returnTypes.size()); Assertions.assertEquals(1, model.returnTypes.size());
final ClassObjectModel classModel = Assertions.assertInstanceOf(ClassObjectModel.class, final ClassObjectModel classModel = Assertions.assertInstanceOf(ClassObjectModel.class,
@@ -314,11 +314,11 @@ public class TestAnalyzeApiReturn {
final AnalyzeApi api = new AnalyzeApi(); final AnalyzeApi api = new AnalyzeApi();
api.addAllApi(List.of(ReturnValueAny.class)); api.addAllApi(List.of(ReturnValueAny.class));
Assertions.assertEquals(1, api.getAllApi().size()); Assertions.assertEquals(1, api.apiModels.size());
Assertions.assertEquals(2, api.getAllApi().get(0).interfaces.size()); Assertions.assertEquals(2, api.apiModels.get(0).interfaces.size());
// Check Response ==> represent a Any value then it wrapped as Object // Check Response ==> represent a Any value then it wrapped as Object
{ {
final ApiModel model = api.getAllApi().get(0).getInterfaceNamed("getResponse"); final ApiModel model = api.apiModels.get(0).getInterfaceNamed("getResponse");
Assertions.assertNotNull(model); Assertions.assertNotNull(model);
Assertions.assertEquals(1, model.returnTypes.size()); Assertions.assertEquals(1, model.returnTypes.size());
final ClassObjectModel classModel = Assertions.assertInstanceOf(ClassObjectModel.class, final ClassObjectModel classModel = Assertions.assertInstanceOf(ClassObjectModel.class,
@@ -327,7 +327,7 @@ public class TestAnalyzeApiReturn {
} }
// Check Object // Check Object
{ {
final ApiModel model = api.getAllApi().get(0).getInterfaceNamed("getObject"); final ApiModel model = api.apiModels.get(0).getInterfaceNamed("getObject");
Assertions.assertNotNull(model); Assertions.assertNotNull(model);
Assertions.assertEquals(1, model.returnTypes.size()); Assertions.assertEquals(1, model.returnTypes.size());
final ClassObjectModel classModel = Assertions.assertInstanceOf(ClassObjectModel.class, final ClassObjectModel classModel = Assertions.assertInstanceOf(ClassObjectModel.class,
@@ -350,11 +350,11 @@ public class TestAnalyzeApiReturn {
final AnalyzeApi api = new AnalyzeApi(); final AnalyzeApi api = new AnalyzeApi();
api.addAllApi(List.of(ReturnValueEnum.class)); api.addAllApi(List.of(ReturnValueEnum.class));
Assertions.assertEquals(1, api.getAllApi().size()); Assertions.assertEquals(1, api.apiModels.size());
Assertions.assertEquals(1, api.getAllApi().get(0).interfaces.size()); Assertions.assertEquals(1, api.apiModels.get(0).interfaces.size());
// Check Enum // Check Enum
{ {
final ApiModel model = api.getAllApi().get(0).getInterfaceNamed("getEnum"); final ApiModel model = api.apiModels.get(0).getInterfaceNamed("getEnum");
Assertions.assertNotNull(model); Assertions.assertNotNull(model);
Assertions.assertEquals(1, model.returnTypes.size()); Assertions.assertEquals(1, model.returnTypes.size());
final ClassEnumModel classModel = Assertions.assertInstanceOf(ClassEnumModel.class, final ClassEnumModel classModel = Assertions.assertInstanceOf(ClassEnumModel.class,
@@ -396,11 +396,11 @@ public class TestAnalyzeApiReturn {
final AnalyzeApi api = new AnalyzeApi(); final AnalyzeApi api = new AnalyzeApi();
api.addAllApi(List.of(ReturnValueList.class)); api.addAllApi(List.of(ReturnValueList.class));
Assertions.assertEquals(1, api.getAllApi().size()); Assertions.assertEquals(1, api.apiModels.size());
Assertions.assertEquals(5, api.getAllApi().get(0).interfaces.size()); Assertions.assertEquals(5, api.apiModels.get(0).interfaces.size());
// Check List<Integer> // Check List<Integer>
{ {
final ApiModel model = api.getAllApi().get(0).getInterfaceNamed("getListInteger"); final ApiModel model = api.apiModels.get(0).getInterfaceNamed("getListInteger");
Assertions.assertNotNull(model); Assertions.assertNotNull(model);
Assertions.assertEquals(1, model.returnTypes.size()); Assertions.assertEquals(1, model.returnTypes.size());
// Level 0 // Level 0
@@ -413,7 +413,7 @@ public class TestAnalyzeApiReturn {
} }
// Check List<TestEnum> // Check List<TestEnum>
{ {
final ApiModel model = api.getAllApi().get(0).getInterfaceNamed("getListEnum"); final ApiModel model = api.apiModels.get(0).getInterfaceNamed("getListEnum");
Assertions.assertNotNull(model); Assertions.assertNotNull(model);
Assertions.assertEquals(1, model.returnTypes.size()); Assertions.assertEquals(1, model.returnTypes.size());
// Level 0 // Level 0
@@ -426,7 +426,7 @@ public class TestAnalyzeApiReturn {
} }
// Check List<TestObject> // Check List<TestObject>
{ {
final ApiModel model = api.getAllApi().get(0).getInterfaceNamed("getListObject"); final ApiModel model = api.apiModels.get(0).getInterfaceNamed("getListObject");
Assertions.assertNotNull(model); Assertions.assertNotNull(model);
Assertions.assertEquals(1, model.returnTypes.size()); Assertions.assertEquals(1, model.returnTypes.size());
// Level 0 // Level 0
@@ -435,11 +435,11 @@ public class TestAnalyzeApiReturn {
// Level 1 // Level 1
final ClassObjectModel classModelOfValue = Assertions.assertInstanceOf(ClassObjectModel.class, final ClassObjectModel classModelOfValue = Assertions.assertInstanceOf(ClassObjectModel.class,
classListModel.valueModel); classListModel.valueModel);
Assertions.assertEquals(TestObject.class, classModelOfValue.getOriginClasses()); Assertions.assertEquals(Integer.class, classModelOfValue.getOriginClasses());
} }
// Check List<List<Integer>> // Check List<List<Integer>>
{ {
final ApiModel model = api.getAllApi().get(0).getInterfaceNamed("getListListInteger"); final ApiModel model = api.apiModels.get(0).getInterfaceNamed("getListListInteger");
Assertions.assertNotNull(model); Assertions.assertNotNull(model);
Assertions.assertEquals(1, model.returnTypes.size()); Assertions.assertEquals(1, model.returnTypes.size());
// Level 0 // Level 0
@@ -455,7 +455,7 @@ public class TestAnalyzeApiReturn {
} }
// Check List<Map<String, Integer>> // Check List<Map<String, Integer>>
{ {
final ApiModel model = api.getAllApi().get(0).getInterfaceNamed("getListMapInteger"); final ApiModel model = api.apiModels.get(0).getInterfaceNamed("getListMapInteger");
Assertions.assertNotNull(model); Assertions.assertNotNull(model);
Assertions.assertEquals(1, model.returnTypes.size()); Assertions.assertEquals(1, model.returnTypes.size());
// Level 0 // Level 0
@@ -509,11 +509,11 @@ public class TestAnalyzeApiReturn {
final AnalyzeApi api = new AnalyzeApi(); final AnalyzeApi api = new AnalyzeApi();
api.addAllApi(List.of(ReturnValueMap.class)); api.addAllApi(List.of(ReturnValueMap.class));
Assertions.assertEquals(1, api.getAllApi().size()); Assertions.assertEquals(1, api.apiModels.size());
Assertions.assertEquals(5, api.getAllApi().get(0).interfaces.size()); Assertions.assertEquals(5, api.apiModels.get(0).interfaces.size());
// Check Map<String, Integer> // Check Map<String, Integer>
{ {
final ApiModel model = api.getAllApi().get(0).getInterfaceNamed("getMapInteger"); final ApiModel model = api.apiModels.get(0).getInterfaceNamed("getMapInteger");
Assertions.assertNotNull(model); Assertions.assertNotNull(model);
Assertions.assertEquals(1, model.returnTypes.size()); Assertions.assertEquals(1, model.returnTypes.size());
// Level 0 // Level 0
@@ -529,7 +529,7 @@ public class TestAnalyzeApiReturn {
} }
// Check Map<String, TestEnum> // Check Map<String, TestEnum>
{ {
final ApiModel model = api.getAllApi().get(0).getInterfaceNamed("getMapEnum"); final ApiModel model = api.apiModels.get(0).getInterfaceNamed("getMapEnum");
Assertions.assertNotNull(model); Assertions.assertNotNull(model);
Assertions.assertEquals(1, model.returnTypes.size()); Assertions.assertEquals(1, model.returnTypes.size());
// Level 0 // Level 0
@@ -545,7 +545,7 @@ public class TestAnalyzeApiReturn {
} }
// Check Map<String, TestObject> // Check Map<String, TestObject>
{ {
final ApiModel model = api.getAllApi().get(0).getInterfaceNamed("getMapObject"); final ApiModel model = api.apiModels.get(0).getInterfaceNamed("getMapObject");
Assertions.assertNotNull(model); Assertions.assertNotNull(model);
Assertions.assertEquals(1, model.returnTypes.size()); Assertions.assertEquals(1, model.returnTypes.size());
// Level 0 // Level 0
@@ -561,7 +561,7 @@ public class TestAnalyzeApiReturn {
} }
// Check Map<String, Map<String, Integer>> // Check Map<String, Map<String, Integer>>
{ {
final ApiModel model = api.getAllApi().get(0).getInterfaceNamed("getMapMap"); final ApiModel model = api.apiModels.get(0).getInterfaceNamed("getMapMap");
Assertions.assertNotNull(model); Assertions.assertNotNull(model);
Assertions.assertEquals(1, model.returnTypes.size()); Assertions.assertEquals(1, model.returnTypes.size());
// Level 0 // Level 0
@@ -583,7 +583,7 @@ public class TestAnalyzeApiReturn {
} }
// Check Map<String, List<Integer>> // Check Map<String, List<Integer>>
{ {
final ApiModel model = api.getAllApi().get(0).getInterfaceNamed("getMapList"); final ApiModel model = api.apiModels.get(0).getInterfaceNamed("getMapList");
Assertions.assertNotNull(model); Assertions.assertNotNull(model);
Assertions.assertEquals(1, model.returnTypes.size()); Assertions.assertEquals(1, model.returnTypes.size());
// Level 0 // Level 0

View File

@@ -0,0 +1,17 @@
package test.kar.archidata.externalRestApi;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class TestAnalyzeApiReturnAsync {
final static private Logger LOGGER = LoggerFactory.getLogger(TestAnalyzeApiReturnAsync.class);
@Test
public void testNotImplemented() throws Exception {
Assertions.assertEquals(1, 0);
}
}

View File

@@ -1,8 +1,12 @@
package test.kar.archidata.externalRestApi; package test.kar.archidata.externalRestApi;
import java.util.ArrayList;
import java.util.List;
import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.kar.archidata.externalRestApi.AnalyzeApi; import org.kar.archidata.externalRestApi.AnalyzeModel;
import org.kar.archidata.externalRestApi.model.ClassModel;
import org.kar.archidata.externalRestApi.model.ClassObjectModel; import org.kar.archidata.externalRestApi.model.ClassObjectModel;
import org.kar.archidata.externalRestApi.model.ClassObjectModel.FieldProperty; import org.kar.archidata.externalRestApi.model.ClassObjectModel.FieldProperty;
import org.slf4j.Logger; import org.slf4j.Logger;
@@ -17,11 +21,10 @@ public class TestAnalyzeModel {
@Test @Test
public void testNames() throws Exception { public void testNames() throws Exception {
final AnalyzeApi apiInterface = new AnalyzeApi(); final ClassObjectModel model = new ClassObjectModel(TestObject.class);
apiInterface.addModel(TestObject.class); final List<ClassModel> models = new ArrayList<>();
Assertions.assertEquals(2, apiInterface.getAllModel().size()); models.add(model);
final ClassObjectModel model = Assertions.assertInstanceOf(ClassObjectModel.class, AnalyzeModel.fillModel(models);
apiInterface.getAllModel().get(0));
Assertions.assertEquals("TestObject", model.getName()); Assertions.assertEquals("TestObject", model.getName());
Assertions.assertEquals(false, model.isPrimitive()); Assertions.assertEquals(false, model.isPrimitive());

View File

@@ -1 +1 @@
0.10.2 0.8.9