[DEV] add API generation (base)
This commit is contained in:
parent
42ac2f3056
commit
526f902eae
@ -35,5 +35,11 @@
|
||||
<attribute name="optional" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="src" output="target/test-classes" path="target/generated-test-sources/test-annotations">
|
||||
<attributes>
|
||||
<attribute name="optional" value="true"/>
|
||||
<attribute name="test" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="output" path="target/classes"/>
|
||||
</classpath>
|
||||
|
13
src/org/kar/archidata/annotation/AsyncType.java
Normal file
13
src/org/kar/archidata/annotation/AsyncType.java
Normal file
@ -0,0 +1,13 @@
|
||||
package org.kar.archidata.annotation;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/** In case of the update parameter with String input to detect null element. */
|
||||
@Target(ElementType.PARAMETER)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface AsyncType {
|
||||
Class<?> value();
|
||||
}
|
@ -93,12 +93,13 @@ public class DataResource {
|
||||
}
|
||||
return filePath;
|
||||
}
|
||||
|
||||
public static String getFileData(final UUID uuid) {
|
||||
final String stringUUID = uuid.toString();
|
||||
final String part1 = stringUUID.substring(0, 2);
|
||||
final String part2 = stringUUID.substring(2, 4);
|
||||
final String part3 = stringUUID.substring(4);
|
||||
final String finalPath = part1 + File.separator + part2+ File.separator + part3;
|
||||
final String finalPath = part1 + File.separator + part2 + File.separator + part3;
|
||||
String filePath = ConfigBaseVariable.getMediaDataFolder() + "_uuid" + File.separator + finalPath + File.separator;
|
||||
try {
|
||||
createFolder(filePath);
|
||||
@ -164,6 +165,7 @@ public class DataResource {
|
||||
LOGGER.info("Move done");
|
||||
return injectedData;
|
||||
}
|
||||
|
||||
public static void modeFileOldModelToNewModel(final long id, final UUID uuid) throws IOException {
|
||||
String mediaCurentPath = getFileData(id);
|
||||
String mediaDestPath = getFileData(uuid);
|
||||
@ -174,8 +176,8 @@ public class DataResource {
|
||||
Files.move(Paths.get(mediaCurentPath), Paths.get(mediaDestPath), StandardCopyOption.ATOMIC_MOVE);
|
||||
}
|
||||
// Move old meta-data...
|
||||
mediaCurentPath = mediaCurentPath.substring(mediaCurentPath.length()-4) + "meta.json";
|
||||
mediaDestPath = mediaCurentPath.substring(mediaDestPath.length()-4) + "meta.json";
|
||||
mediaCurentPath = mediaCurentPath.substring(mediaCurentPath.length() - 4) + "meta.json";
|
||||
mediaDestPath = mediaCurentPath.substring(mediaDestPath.length() - 4) + "meta.json";
|
||||
if (Files.exists(Paths.get(mediaCurentPath))) {
|
||||
LOGGER.info("moveM: {} ==> {}", mediaCurentPath, mediaDestPath);
|
||||
Files.move(Paths.get(mediaCurentPath), Paths.get(mediaDestPath), StandardCopyOption.ATOMIC_MOVE);
|
||||
@ -316,8 +318,8 @@ public class DataResource {
|
||||
return Response.status(404).entity("{\"error\":\"media Does not exist: " + id + "\"}").type("application/json").build();
|
||||
}
|
||||
if (value.mimeType.contentEquals("image/jpeg") || value.mimeType.contentEquals("image/png")
|
||||
// || value.mimeType.contentEquals("image/webp")
|
||||
) {
|
||||
// || value.mimeType.contentEquals("image/webp")
|
||||
) {
|
||||
// reads input image
|
||||
final BufferedImage inputImage = ImageIO.read(inputFile);
|
||||
final int scaledWidth = 250;
|
||||
|
432
src/org/kar/archidata/dataAccess/DataFactoryTsApi.java
Normal file
432
src/org/kar/archidata/dataAccess/DataFactoryTsApi.java
Normal file
@ -0,0 +1,432 @@
|
||||
package org.kar.archidata.dataAccess;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileWriter;
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Parameter;
|
||||
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.Arrays;
|
||||
import java.util.Date;
|
||||
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 java.util.UUID;
|
||||
|
||||
import org.kar.archidata.annotation.AnnotationTools;
|
||||
import org.kar.archidata.annotation.AsyncType;
|
||||
import org.kar.archidata.exception.DataAccessException;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import jakarta.ws.rs.Consumes;
|
||||
import jakarta.ws.rs.DELETE;
|
||||
import jakarta.ws.rs.GET;
|
||||
import jakarta.ws.rs.PATCH;
|
||||
import jakarta.ws.rs.POST;
|
||||
import jakarta.ws.rs.PUT;
|
||||
import jakarta.ws.rs.Path;
|
||||
import jakarta.ws.rs.PathParam;
|
||||
import jakarta.ws.rs.QueryParam;
|
||||
import jakarta.ws.rs.core.Context;
|
||||
import jakarta.ws.rs.core.MediaType;
|
||||
|
||||
public class DataFactoryTsApi {
|
||||
static final Logger LOGGER = LoggerFactory.getLogger(DataFactoryTsApi.class);
|
||||
|
||||
public static String convertTypeZodSimpleType(final Class<?> type, final Map<String, String> previousClassesGenerated, final List<String> order) throws Exception {
|
||||
if (type == UUID.class) {
|
||||
return "string";
|
||||
}
|
||||
if (type == Long.class) {
|
||||
return "Bigint";
|
||||
}
|
||||
if (type == long.class) {
|
||||
return "Bigint";
|
||||
}
|
||||
if (type == Integer.class || type == int.class) {
|
||||
return "number";
|
||||
}
|
||||
if (type == Boolean.class || type == boolean.class) {
|
||||
return "boolean";
|
||||
}
|
||||
if (type == double.class || type == float.class || type == Double.class || type == Float.class) {
|
||||
return "number";
|
||||
}
|
||||
if (type == Instant.class) {
|
||||
return "string";
|
||||
}
|
||||
if (type == Date.class || type == Timestamp.class) {
|
||||
return "string";
|
||||
}
|
||||
if (type == LocalDate.class) {
|
||||
return "string";
|
||||
}
|
||||
if (type == LocalTime.class) {
|
||||
return "string";
|
||||
}
|
||||
if (type == String.class) {
|
||||
return "string";
|
||||
}
|
||||
if (type.isEnum()) {
|
||||
final Object[] arr = type.getEnumConstants();
|
||||
final StringBuilder out = new StringBuilder();
|
||||
boolean first = true;
|
||||
out.append("zod.enum([");
|
||||
for (final Object elem : arr) {
|
||||
if (!first) {
|
||||
out.append(", ");
|
||||
}
|
||||
first = false;
|
||||
out.append("\"");
|
||||
out.append(elem.toString());
|
||||
out.append("\"");
|
||||
}
|
||||
out.append("])");
|
||||
return out.toString();
|
||||
}
|
||||
if (type == List.class) {
|
||||
return null;
|
||||
}
|
||||
// createTable(type, previousClassesGenerated, order);
|
||||
return "Zod" + type.getSimpleName();
|
||||
}
|
||||
|
||||
public static String convertTypeZod(final Field field, final Map<String, String> previousClassesGenerated, final List<String> order) throws Exception {
|
||||
final Class<?> type = field.getType();
|
||||
final String simpleType = convertTypeZodSimpleType(type, previousClassesGenerated, order);
|
||||
if (simpleType != null) {
|
||||
return simpleType;
|
||||
}
|
||||
if (type == List.class) {
|
||||
final ParameterizedType listType = (ParameterizedType) field.getGenericType();
|
||||
final Class<?> listClass = (Class<?>) listType.getActualTypeArguments()[0];
|
||||
final String simpleSubType = convertTypeZodSimpleType(listClass, previousClassesGenerated, order);
|
||||
return "zod.array(" + simpleSubType + ")";
|
||||
}
|
||||
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 Map<String, String> previousClassesGenerated, final List<String> order)
|
||||
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, previousClassesGenerated, order));
|
||||
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));
|
||||
}
|
||||
|
||||
/** 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 createApi(final List<Class<?>> classs, final Set<Class<?>> classNeeded) throws Exception {
|
||||
final List<String> apis = new ArrayList<>();
|
||||
for (final Class<?> clazz : classs) {
|
||||
final String api = createSingleApi(clazz, classNeeded);
|
||||
apis.add(api);
|
||||
}
|
||||
final StringBuilder generatedDataElems = new StringBuilder();
|
||||
for (final String elem : apis) {
|
||||
generatedDataElems.append(elem);
|
||||
generatedDataElems.append("\n\n");
|
||||
}
|
||||
final StringBuilder generatedData = new StringBuilder();
|
||||
generatedData.append("""
|
||||
/**
|
||||
* API of the server (auto-generated code)
|
||||
*/
|
||||
import {""");
|
||||
for (final Class<?> elem : classNeeded) {
|
||||
generatedData.append(elem.getSimpleName());
|
||||
generatedData.append(", ");
|
||||
}
|
||||
generatedData.append("} from \"./model.ts\"\n\n");
|
||||
return generatedData.toString() + generatedDataElems.toString();
|
||||
}
|
||||
|
||||
public static String apiAnnotationGetPath(final Class<?> element) throws Exception {
|
||||
final Annotation[] annotation = element.getDeclaredAnnotationsByType(Path.class);
|
||||
if (annotation.length == 0) {
|
||||
return null;
|
||||
}
|
||||
return ((Path) annotation[0]).value();
|
||||
}
|
||||
|
||||
public static String apiAnnotationGetOperationDescription(final Method element) throws Exception {
|
||||
final Annotation[] annotation = element.getDeclaredAnnotationsByType(Operation.class);
|
||||
if (annotation.length == 0) {
|
||||
return null;
|
||||
}
|
||||
return ((Operation) annotation[0]).description();
|
||||
}
|
||||
|
||||
public static String apiAnnotationGetPath(final Method element) throws Exception {
|
||||
final Annotation[] annotation = element.getDeclaredAnnotationsByType(Path.class);
|
||||
if (annotation.length == 0) {
|
||||
return null;
|
||||
}
|
||||
return ((Path) annotation[0]).value();
|
||||
}
|
||||
|
||||
public static String apiAnnotationGetTypeRequest(final Method element) throws Exception {
|
||||
if (element.getDeclaredAnnotationsByType(GET.class).length == 1) {
|
||||
return "GET";
|
||||
}
|
||||
if (element.getDeclaredAnnotationsByType(POST.class).length == 1) {
|
||||
return "POST";
|
||||
}
|
||||
if (element.getDeclaredAnnotationsByType(PUT.class).length == 1) {
|
||||
return "PUT";
|
||||
}
|
||||
if (element.getDeclaredAnnotationsByType(PATCH.class).length == 1) {
|
||||
return "PATCH";
|
||||
}
|
||||
if (element.getDeclaredAnnotationsByType(DELETE.class).length == 1) {
|
||||
return "DELETE";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static String apiAnnotationGetPathParam(final Parameter element) throws Exception {
|
||||
final Annotation[] annotation = element.getDeclaredAnnotationsByType(PathParam.class);
|
||||
if (annotation.length == 0) {
|
||||
return null;
|
||||
}
|
||||
return ((PathParam) annotation[0]).value();
|
||||
}
|
||||
|
||||
public static String apiAnnotationGetQueryParam(final Parameter element) throws Exception {
|
||||
final Annotation[] annotation = element.getDeclaredAnnotationsByType(QueryParam.class);
|
||||
if (annotation.length == 0) {
|
||||
return null;
|
||||
}
|
||||
return ((QueryParam) annotation[0]).value();
|
||||
}
|
||||
|
||||
public static Class<?> apiAnnotationGetAsyncType(final Parameter element) throws Exception {
|
||||
final Annotation[] annotation = element.getDeclaredAnnotationsByType(AsyncType.class);
|
||||
if (annotation.length == 0) {
|
||||
return null;
|
||||
}
|
||||
return ((AsyncType) annotation[0]).value();
|
||||
}
|
||||
|
||||
public static List<String> apiAnnotationGetConsumes(final Method element) throws Exception {
|
||||
final Annotation[] annotation = element.getDeclaredAnnotationsByType(Consumes.class);
|
||||
if (annotation.length == 0) {
|
||||
return null;
|
||||
}
|
||||
return Arrays.asList(((Consumes) annotation[0]).value());
|
||||
}
|
||||
|
||||
public static boolean apiAnnotationIsContext(final Parameter element) throws Exception {
|
||||
return element.getDeclaredAnnotationsByType(Context.class).length != 0;
|
||||
}
|
||||
|
||||
public static String createSingleApi(final Class<?> clazz, final Set<Class<?>> classNeeded) throws Exception {
|
||||
final StringBuilder builder = new StringBuilder();
|
||||
// the basic path has no specific elements...
|
||||
final String basicPath = apiAnnotationGetPath(clazz);
|
||||
final String classSimpleName = clazz.getSimpleName();
|
||||
|
||||
builder.append("export namespace ");
|
||||
builder.append(classSimpleName);
|
||||
builder.append("API {\n");
|
||||
LOGGER.info("Parse Class for path: {} => {}", classSimpleName, basicPath);
|
||||
for (final Method method : clazz.getDeclaredMethods()) {
|
||||
final String methodName = method.getName();
|
||||
final String methodPath = apiAnnotationGetPath(method);
|
||||
final String methodType = apiAnnotationGetTypeRequest(method);
|
||||
final String methodDescription = apiAnnotationGetOperationDescription(method);
|
||||
final List<String> consumes = apiAnnotationGetConsumes(method);
|
||||
if (consumes != null && consumes.contains(MediaType.MULTIPART_FORM_DATA)) {
|
||||
LOGGER.error(" [{}] {} => {}/{} ==> Multipart is not managed ...", methodType, methodName, basicPath, methodPath);
|
||||
continue;
|
||||
}
|
||||
LOGGER.trace(" [{}] {} => {}/{}", methodType, methodName, basicPath, methodPath);
|
||||
final Class<?> returnType = method.getReturnType();
|
||||
if (methodDescription != null) {
|
||||
LOGGER.trace(" description: {}", methodDescription);
|
||||
}
|
||||
LOGGER.trace(" return: {}", returnType.getSimpleName());
|
||||
final Map<String, Class<?>> queryParams = new HashMap<>();
|
||||
final Map<String, Class<?>> pathParams = new HashMap<>();
|
||||
final List<Class<?>> emptyElement = new ArrayList<>();
|
||||
// LOGGER.info(" Parameters:");
|
||||
for (final Parameter parameter : method.getParameters()) {
|
||||
if (apiAnnotationIsContext(parameter)) {
|
||||
continue;
|
||||
}
|
||||
final Class<?> parameterType = parameter.getType();
|
||||
final String pathParam = apiAnnotationGetPathParam(parameter);
|
||||
final String queryParam = apiAnnotationGetQueryParam(parameter);
|
||||
if (queryParam != null) {
|
||||
queryParams.put(queryParam, parameterType);
|
||||
} else if (pathParam != null) {
|
||||
pathParams.put(pathParam, parameterType);
|
||||
} else {
|
||||
final Class<?> asyncType = apiAnnotationGetAsyncType(parameter);
|
||||
if (asyncType != null) {
|
||||
emptyElement.add(asyncType);
|
||||
} else {
|
||||
emptyElement.add(parameterType);
|
||||
}
|
||||
// LOGGER.info(" - {} ", parameterType.getSimpleName());
|
||||
}
|
||||
}
|
||||
if (!queryParams.isEmpty()) {
|
||||
LOGGER.trace(" Query parameter:");
|
||||
for (final Entry<String, Class<?>> queryEntry : queryParams.entrySet()) {
|
||||
LOGGER.trace(" - {}: {}", queryEntry.getKey(), queryEntry.getValue().getSimpleName());
|
||||
}
|
||||
}
|
||||
if (!pathParams.isEmpty()) {
|
||||
LOGGER.trace(" Path parameter:");
|
||||
for (final Entry<String, Class<?>> pathEntry : pathParams.entrySet()) {
|
||||
LOGGER.trace(" - {}: {}", pathEntry.getKey(), pathEntry.getValue().getSimpleName());
|
||||
|
||||
}
|
||||
}
|
||||
if (emptyElement.size() > 1) {
|
||||
LOGGER.error(" Fail to parse: Too much element in the model for the data ...");
|
||||
continue;
|
||||
} else if (emptyElement.size() == 1) {
|
||||
LOGGER.trace(" data type: {}", emptyElement.get(0).getSimpleName());
|
||||
}
|
||||
// ALL is good can generate the Elements
|
||||
|
||||
if (methodDescription != null) {
|
||||
builder.append("\n\t/**\n\t * ");
|
||||
builder.append(methodDescription);
|
||||
builder.append("\n\t */");
|
||||
}
|
||||
builder.append("\n\texport function ");
|
||||
builder.append(methodName);
|
||||
builder.append("({");
|
||||
builder.append("options,");
|
||||
builder.append(" serverUrl,");
|
||||
if (!queryParams.isEmpty()) {
|
||||
builder.append(" queries,");
|
||||
}
|
||||
if (!pathParams.isEmpty()) {
|
||||
builder.append(" params,");
|
||||
}
|
||||
if (emptyElement.size() == 1) {
|
||||
builder.append(" data,");
|
||||
}
|
||||
builder.append(" } : {");
|
||||
builder.append("\n\t\t\toptions: any,");
|
||||
builder.append("\n\t\t\tserverUrl: string,");
|
||||
if (!queryParams.isEmpty()) {
|
||||
builder.append("\n\t\t\tqueries: {");
|
||||
for (final Entry<String, Class<?>> queryEntry : queryParams.entrySet()) {
|
||||
classNeeded.add(queryEntry.getValue());
|
||||
builder.append("\n\t\t\t\t");
|
||||
builder.append(queryEntry.getKey());
|
||||
builder.append(": ");
|
||||
builder.append(queryEntry.getValue().getSimpleName());
|
||||
builder.append(",");
|
||||
}
|
||||
builder.append("\n\t\t\t},");
|
||||
}
|
||||
if (!pathParams.isEmpty()) {
|
||||
builder.append("\n\t\t\tparams: {");
|
||||
for (final Entry<String, Class<?>> pathEntry : pathParams.entrySet()) {
|
||||
classNeeded.add(pathEntry.getValue());
|
||||
builder.append("\n\t\t\t\t");
|
||||
builder.append(pathEntry.getKey());
|
||||
builder.append(": ");
|
||||
builder.append(pathEntry.getValue().getSimpleName());
|
||||
builder.append(",");
|
||||
}
|
||||
builder.append("\n\t\t\t},");
|
||||
}
|
||||
if (emptyElement.size() == 1) {
|
||||
builder.append("\n\t\t\tdata: ");
|
||||
classNeeded.add(emptyElement.get(0));
|
||||
builder.append(emptyElement.get(0).getSimpleName());
|
||||
builder.append(",");
|
||||
}
|
||||
builder.append("\n\t\t}) : Promise<");
|
||||
if (returnType == Void.class) {
|
||||
builder.append("void");
|
||||
} else {
|
||||
classNeeded.add(returnType);
|
||||
builder.append(returnType.getSimpleName());
|
||||
}
|
||||
builder.append("> {");
|
||||
builder.append("\n\t\treturn new Promise((resolve, reject) => {");
|
||||
/* fetch('https://example.com?' + new URLSearchParams({ foo: 'value', bar: 2, })) */
|
||||
builder.append("\n\t\t});");
|
||||
builder.append("\n\t};");
|
||||
}
|
||||
|
||||
builder.append("\n}\n");
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
public static void generatePackage(final List<Class<?>> classApi, final List<Class<?>> classModel, final String pathPackage) throws Exception {
|
||||
final Set<Class<?>> classNeeded = new HashSet<>(classModel);
|
||||
final String data = createApi(classApi, classNeeded);
|
||||
FileWriter myWriter = new FileWriter(pathPackage + File.separator + "api.ts");
|
||||
myWriter.write(data);
|
||||
myWriter.close();
|
||||
final String packageApi = DataFactoryZod.createTables(new ArrayList<>(classNeeded));
|
||||
myWriter = new FileWriter(pathPackage + File.separator + "model.ts");
|
||||
myWriter.write(packageApi.toString());
|
||||
myWriter.close();
|
||||
final String index = """
|
||||
/**
|
||||
* Global import of the package
|
||||
*/
|
||||
export * from "./model.ts";
|
||||
export * from "./api.ts";
|
||||
|
||||
""";
|
||||
myWriter = new FileWriter(pathPackage + File.separator + "index.ts");
|
||||
myWriter.write(index);
|
||||
myWriter.close();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
@ -1,5 +1,7 @@
|
||||
package org.kar.archidata.dataAccess;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileWriter;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.sql.Timestamp;
|
||||
@ -20,37 +22,40 @@ import org.slf4j.LoggerFactory;
|
||||
|
||||
public class DataFactoryZod {
|
||||
static final Logger LOGGER = LoggerFactory.getLogger(DataFactoryZod.class);
|
||||
|
||||
|
||||
public static String convertTypeZodSimpleType(final Class<?> type, final Map<String, String> previousClassesGenerated, final List<String> order) throws Exception {
|
||||
if (type == UUID.class) {
|
||||
return "zod.string().uuid()";
|
||||
return "ZodUUID";
|
||||
}
|
||||
if (type == Long.class) {
|
||||
return "zod.bigint()";
|
||||
return "ZodLong";
|
||||
}
|
||||
if (type == long.class) {
|
||||
return "zod.bigint()";
|
||||
return "ZodLong";
|
||||
}
|
||||
if (type == Integer.class || type == int.class) {
|
||||
return "zod.number().safe()";
|
||||
return "ZodInteger";
|
||||
}
|
||||
if (type == Boolean.class || type == boolean.class) {
|
||||
return "zod.boolean()";
|
||||
}
|
||||
if (type == double.class || type == float.class || type == Double.class || type == Float.class) {
|
||||
return "zod.number()";
|
||||
if (type == double.class || type == Double.class) {
|
||||
return "ZodDouble";
|
||||
}
|
||||
if (type == float.class || type == Float.class) {
|
||||
return "ZodFloat";
|
||||
}
|
||||
if (type == Instant.class) {
|
||||
return "zod.string().utc()";
|
||||
return "ZodInstant";
|
||||
}
|
||||
if (type == Date.class || type == Timestamp.class) {
|
||||
return "zod.date()";
|
||||
return "ZodDate";
|
||||
}
|
||||
if (type == LocalDate.class) {
|
||||
return "zod.date()";
|
||||
return "ZodLocalDate";
|
||||
}
|
||||
if (type == LocalTime.class) {
|
||||
return "zod.date()";
|
||||
return "ZodLocalTime";
|
||||
}
|
||||
if (type == String.class) {
|
||||
return "zod.string()";
|
||||
@ -78,6 +83,7 @@ public class DataFactoryZod {
|
||||
createTable(type, previousClassesGenerated, order);
|
||||
return "Zod" + type.getSimpleName();
|
||||
}
|
||||
|
||||
public static String convertTypeZod(final Field field, final Map<String, String> previousClassesGenerated, final List<String> order) throws Exception {
|
||||
final Class<?> type = field.getType();
|
||||
final String simpleType = convertTypeZodSimpleType(type, previousClassesGenerated, order);
|
||||
@ -92,21 +98,22 @@ public class DataFactoryZod {
|
||||
}
|
||||
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 Map<String, String> previousClassesGenerated, final List<String> order) throws Exception {
|
||||
|
||||
public static void createTablesSpecificType(final Field elem, final int fieldId, final StringBuilder builder, final Map<String, String> previousClassesGenerated, final List<String> order)
|
||||
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(",");
|
||||
}
|
||||
@ -128,7 +135,7 @@ public class DataFactoryZod {
|
||||
}
|
||||
builder.append(optionalTypeZod(classModel));
|
||||
}
|
||||
|
||||
|
||||
private static boolean isFieldFromSuperClass(final Class<?> model, final String filedName) {
|
||||
final Class<?> superClass = model.getSuperclass();
|
||||
if (superClass == null) {
|
||||
@ -148,7 +155,7 @@ public class DataFactoryZod {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/** 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
|
||||
@ -165,7 +172,36 @@ public class DataFactoryZod {
|
||||
* Interface of the server (auto-generated code)
|
||||
*/
|
||||
import { z as zod } from \"zod\";
|
||||
|
||||
|
||||
export const ZodUUID = zod.string().uuid();
|
||||
export type UUID = zod.infer<typeof ZodUUID>;
|
||||
|
||||
export const ZodLong = zod.bigint();
|
||||
export type Long = zod.infer<typeof ZodLong>;
|
||||
|
||||
export const ZodInteger = zod.number().safe();
|
||||
export type Integer = zod.infer<typeof ZodInteger>;
|
||||
|
||||
export const ZodDouble = zod.number();
|
||||
export type Double = zod.infer<typeof ZodDouble>;
|
||||
|
||||
export const ZodFloat = zod.number();
|
||||
export type Float = zod.infer<typeof ZodFloat>;
|
||||
|
||||
export const ZodInstant = zod.string();
|
||||
export type Instant = zod.infer<typeof ZodInstant>;
|
||||
|
||||
export const ZodDate = zod.date();
|
||||
export type Date = zod.infer<typeof ZodDate>;
|
||||
|
||||
export const ZodTimestamp = zod.date();
|
||||
export type Timestamp = zod.infer<typeof ZodTimestamp>;
|
||||
|
||||
export const ZodLocalDate = zod.date();
|
||||
export type LocalDate = zod.infer<typeof ZodLocalDate>;
|
||||
|
||||
export const ZodLocalTime = zod.date();
|
||||
export type LocalTime = zod.infer<typeof ZodLocalTime>;
|
||||
""");
|
||||
for (final String elem : order) {
|
||||
final String data = previousClassesGenerated.get(elem);
|
||||
@ -175,8 +211,19 @@ public class DataFactoryZod {
|
||||
LOGGER.info("generated: {}", generatedData.toString());
|
||||
return generatedData.toString();
|
||||
}
|
||||
|
||||
|
||||
public static void createTable(final Class<?> clazz, final Map<String, String> previousClassesGenerated, final List<String> order) throws Exception {
|
||||
if (clazz == null) {
|
||||
return;
|
||||
}
|
||||
if (clazz.isPrimitive()) {
|
||||
return;
|
||||
}
|
||||
if (clazz == Double.class || clazz == Float.class || clazz == Integer.class || clazz == Long.class || clazz == UUID.class || clazz == Instant.class || clazz == Date.class
|
||||
|| clazz == Timestamp.class || clazz == LocalDate.class || clazz == LocalTime.class || clazz == String.class) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (previousClassesGenerated.get(clazz.getCanonicalName()) != null) {
|
||||
return;
|
||||
}
|
||||
@ -214,7 +261,7 @@ public class DataFactoryZod {
|
||||
DataFactoryZod.createTablesSpecificType(elem, fieldId, internalBuilder, previousClassesGenerated, order);
|
||||
fieldId++;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
final String description = AnnotationTools.getSchemaDescription(clazz);
|
||||
final String example = AnnotationTools.getSchemaExample(clazz);
|
||||
@ -244,7 +291,7 @@ public class DataFactoryZod {
|
||||
generatedData.append(clazz.getSimpleName());
|
||||
generatedData.append(" = ");
|
||||
final Class<?> parentClass = clazz.getSuperclass();
|
||||
if (parentClass != Object.class) {
|
||||
if (parentClass != null && parentClass != Object.class) {
|
||||
createTable(parentClass, previousClassesGenerated, order);
|
||||
generatedData.append("Zod");
|
||||
generatedData.append(parentClass.getSimpleName());
|
||||
@ -280,5 +327,22 @@ public class DataFactoryZod {
|
||||
previousClassesGenerated.put(clazz.getCanonicalName(), generatedData.toString());
|
||||
order.add(clazz.getCanonicalName());
|
||||
}
|
||||
|
||||
|
||||
public static void generatePackage(final List<Class<?>> classs, final String pathPackage) throws Exception {
|
||||
final String packageApi = createTables(classs);
|
||||
FileWriter myWriter = new FileWriter(pathPackage + File.separator + "model.ts");
|
||||
myWriter.write(packageApi.toString());
|
||||
myWriter.close();
|
||||
final String index = """
|
||||
/**
|
||||
* Global import of the package
|
||||
*/
|
||||
export * from "./model.ts";
|
||||
|
||||
""";
|
||||
myWriter = new FileWriter(pathPackage + File.separator + "index.ts");
|
||||
myWriter.write(index);
|
||||
myWriter.close();
|
||||
}
|
||||
|
||||
}
|
@ -7,7 +7,6 @@ import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
import java.nio.file.StandardCopyOption;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.sql.SQLException;
|
||||
@ -17,7 +16,6 @@ import org.glassfish.jersey.media.multipart.FormDataContentDisposition;
|
||||
import org.kar.archidata.dataAccess.DataAccess;
|
||||
import org.kar.archidata.dataAccess.QueryAnd;
|
||||
import org.kar.archidata.dataAccess.QueryCondition;
|
||||
import org.kar.archidata.dataAccess.addOn.AddOnManyToMany;
|
||||
import org.kar.archidata.dataAccess.options.Condition;
|
||||
import org.kar.archidata.dataAccess.options.ReadAllColumn;
|
||||
import org.kar.archidata.model.Data;
|
||||
@ -96,41 +94,13 @@ public class DataTools {
|
||||
}
|
||||
|
||||
public static Data createNewData(final long tmpUID, final String originalFileName, final String sha512) throws IOException, SQLException {
|
||||
// determine mime type:
|
||||
String mimeType = "";
|
||||
final String extension = originalFileName.substring(originalFileName.lastIndexOf('.') + 1);
|
||||
mimeType = switch (extension.toLowerCase()) {
|
||||
case "jpg", "jpeg" -> "image/jpeg";
|
||||
case "png" -> "image/png";
|
||||
case "webp" -> "image/webp";
|
||||
case "mka" -> "audio/x-matroska";
|
||||
case "mkv" -> "video/x-matroska";
|
||||
case "webm" -> "video/webm";
|
||||
default -> throw new IOException("Can not find the mime type of data input: '" + extension + "'");
|
||||
};
|
||||
final String tmpPath = getTmpFileInData(tmpUID);
|
||||
final long fileSize = Files.size(Paths.get(tmpPath));
|
||||
Data out = new Data();
|
||||
|
||||
try {
|
||||
out.sha512 = sha512;
|
||||
out.mimeType = mimeType;
|
||||
out.size = fileSize;
|
||||
out = DataAccess.insert(out);
|
||||
} catch (final Exception e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
|
||||
final String mediaPath = getFileData(out.id);
|
||||
LOGGER.info("src = {}", tmpPath);
|
||||
LOGGER.info("dst = {}", mediaPath);
|
||||
Files.move(Paths.get(tmpPath), Paths.get(mediaPath), StandardCopyOption.ATOMIC_MOVE);
|
||||
|
||||
LOGGER.info("Move done");
|
||||
// all is done the file is correctly installed...
|
||||
return out;
|
||||
/* // determine mime type: String mimeType = ""; final String extension = originalFileName.substring(originalFileName.lastIndexOf('.') + 1); mimeType = switch (extension.toLowerCase()) { case
|
||||
* "jpg", "jpeg" -> "image/jpeg"; case "png" -> "image/png"; case "webp" -> "image/webp"; case "mka" -> "audio/x-matroska"; case "mkv" -> "video/x-matroska"; case "webm" -> "video/webm";
|
||||
* default -> throw new IOException("Can not find the mime type of data input: '" + extension + "'"); }; final String tmpPath = getTmpFileInData(tmpUID); final long fileSize =
|
||||
* Files.size(Paths.get(tmpPath)); Data out = new Data(); try { out.sha512 = sha512; out.mimeType = mimeType; out.size = fileSize; out = DataAccess.insert(out); } catch (final Exception e) {
|
||||
* // TODO Auto-generated catch block e.printStackTrace(); return null; } final String mediaPath = getFileData(out.id); LOGGER.info("src = {}", tmpPath); LOGGER.info("dst = {}", mediaPath);
|
||||
* Files.move(Paths.get(tmpPath), Paths.get(mediaPath), StandardCopyOption.ATOMIC_MOVE); LOGGER.info("Move done"); // all is done the file is correctly installed... return out; */
|
||||
return null;
|
||||
}
|
||||
|
||||
public static void undelete(final Long id) {
|
||||
@ -219,53 +189,17 @@ public class DataTools {
|
||||
return data;
|
||||
}
|
||||
|
||||
public static <T> Response uploadCover(final Class<T> clazz, final Long id, String fileName, final InputStream fileInputStream, final FormDataContentDisposition fileMetaData) {
|
||||
try {
|
||||
// correct input string stream :
|
||||
fileName = multipartCorrection(fileName);
|
||||
|
||||
// public NodeSmall uploadFile(final FormDataMultiPart form) {
|
||||
LOGGER.info("Upload media file: {}", fileMetaData);
|
||||
LOGGER.info(" - id: {}", id);
|
||||
LOGGER.info(" - file_name: ", fileName);
|
||||
LOGGER.info(" - fileInputStream: {}", fileInputStream);
|
||||
LOGGER.info(" - fileMetaData: {}", fileMetaData);
|
||||
final T media = DataAccess.get(clazz, id);
|
||||
if (media == null) {
|
||||
return Response.notModified("Media Id does not exist or removed...").build();
|
||||
}
|
||||
|
||||
final long tmpUID = getTmpDataId();
|
||||
final String sha512 = saveTemporaryFile(fileInputStream, tmpUID);
|
||||
Data data = getWithSha512(sha512);
|
||||
if (data == null) {
|
||||
LOGGER.info("Need to add the data in the BDD ... ");
|
||||
try {
|
||||
data = createNewData(tmpUID, fileName, sha512);
|
||||
} catch (final IOException ex) {
|
||||
removeTemporaryFile(tmpUID);
|
||||
ex.printStackTrace();
|
||||
return Response.notModified("can not create input media").build();
|
||||
} catch (final SQLException ex) {
|
||||
ex.printStackTrace();
|
||||
removeTemporaryFile(tmpUID);
|
||||
return Response.notModified("Error in SQL insertion ...").build();
|
||||
}
|
||||
} else if (data.deleted) {
|
||||
LOGGER.error("Data already exist but deleted");
|
||||
undelete(data.id);
|
||||
data.deleted = false;
|
||||
} else {
|
||||
LOGGER.error("Data already exist ... all good");
|
||||
}
|
||||
// Fist step: retrieve all the Id of each parents:...
|
||||
LOGGER.info("Find typeNode");
|
||||
AddOnManyToMany.addLink(clazz, id, "cover", data.id);
|
||||
return Response.ok(DataAccess.get(clazz, id)).build();
|
||||
} catch (final Exception ex) {
|
||||
System.out.println("Cat ann unexpected error ... ");
|
||||
ex.printStackTrace();
|
||||
}
|
||||
return Response.serverError().build();
|
||||
public static <T> Response uploadCover(final Class<T> clazz, final Long id, final String fileName, final InputStream fileInputStream, final FormDataContentDisposition fileMetaData) {
|
||||
/* try { // correct input string stream : fileName = multipartCorrection(fileName); // public NodeSmall uploadFile(final FormDataMultiPart form) { LOGGER.info("Upload media file: {}",
|
||||
* fileMetaData); LOGGER.info(" - id: {}", id); LOGGER.info(" - file_name: ", fileName); LOGGER.info(" - fileInputStream: {}", fileInputStream); LOGGER.info(" - fileMetaData: {}",
|
||||
* fileMetaData); final T media = DataAccess.get(clazz, id); if (media == null) { return Response.notModified("Media Id does not exist or removed...").build(); } final long tmpUID =
|
||||
* getTmpDataId(); final String sha512 = saveTemporaryFile(fileInputStream, tmpUID); Data data = getWithSha512(sha512); if (data == null) { LOGGER.info("Need to add the data in the BDD ... ");
|
||||
* try { data = createNewData(tmpUID, fileName, sha512); } catch (final IOException ex) { removeTemporaryFile(tmpUID); ex.printStackTrace(); return
|
||||
* Response.notModified("can not create input media").build(); } catch (final SQLException ex) { ex.printStackTrace(); removeTemporaryFile(tmpUID); return
|
||||
* Response.notModified("Error in SQL insertion ...").build(); } } else if (data.deleted) { LOGGER.error("Data already exist but deleted"); undelete(data.id); data.deleted = false; } else {
|
||||
* LOGGER.error("Data already exist ... all good"); } // Fist step: retrieve all the Id of each parents:... LOGGER.info("Find typeNode"); AddOnManyToMany.addLink(clazz, id, "cover", data.id);
|
||||
* return Response.ok(DataAccess.get(clazz, id)).build(); } catch (final Exception ex) { System.out.println("Cat ann unexpected error ... "); ex.printStackTrace(); } return
|
||||
* Response.serverError().build(); */
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user