/*
|
* Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license
|
* Click nbfs://nbhost/SystemFileSystem/Templates/Classes/Class.java to edit this template
|
*/
|
package com.megatim.dynamicjsonparser.extender;
|
|
import com.megatim.dynamicjsonparser.pojo.JsonField;
|
import java.io.Serializable;
|
import java.lang.reflect.Modifier;
|
import java.time.LocalDate;
|
import java.util.List;
|
import org.burningwave.core.Virtual;
|
import org.burningwave.core.assembler.ComponentContainer;
|
import org.burningwave.core.assembler.ComponentSupplier;
|
import org.burningwave.core.classes.AnnotationSourceGenerator;
|
import org.burningwave.core.classes.ClassFactory;
|
import org.burningwave.core.classes.ClassSourceGenerator;
|
import org.burningwave.core.classes.FunctionSourceGenerator;
|
import org.burningwave.core.classes.GenericSourceGenerator;
|
import org.burningwave.core.classes.TypeDeclarationSourceGenerator;
|
import org.burningwave.core.classes.UnitSourceGenerator;
|
import org.burningwave.core.classes.VariableSourceGenerator;
|
|
/**
|
*
|
* @author ASUS
|
*/
|
public class RuntimeClassBuilder {
|
|
/**
|
* Méthode qui crée dynamiquement une classe Java
|
* @param packagename : nom du package de la classe
|
* @param fields : liste des chmaps de la classe
|
* @param classPathFolder : chemin où sera stocké la classe sur le disque
|
* @return
|
*/
|
public static UnitSourceGenerator createRuntimeClass(final String packagename, List<JsonField> fields,String classPathFolder) {
|
final String className = fields.get(0).getClassName();
|
|
//Ajout modificateur d'accès de la classe
|
ClassSourceGenerator clazz = ClassSourceGenerator
|
.create(TypeDeclarationSourceGenerator.create(className))
|
.addModifier(Modifier.PUBLIC);
|
|
//Ajout des interfaces à implémenter
|
clazz.addConcretizedType(Serializable.class)
|
.addConcretizedType(Virtual.class);
|
|
//Déclaration des champs de la classe
|
fields.forEach(f -> {
|
|
//Si le type du champ est encore à construire
|
if (f.getDynamicFields() != null && !f.getDynamicFields().isEmpty()) {
|
|
//Appel récursif afin de construire le sous-type
|
UnitSourceGenerator subUnitSG = createRuntimeClass(packagename, f.getDynamicFields(),classPathFolder);
|
|
ComponentSupplier componentSupplier = ComponentContainer.getInstance();
|
ClassFactory classFactory = componentSupplier.getClassFactory();
|
|
try ( ClassFactory.ClassRetriever classRetriever = classFactory.loadOrBuildAndDefine(subUnitSG)) {
|
|
Class classOfField = classRetriever.get(packagename + "." + f.getDynamicFields().get(0).getClassName());
|
f.setClazz(classOfField);
|
}
|
|
}
|
|
//Si le type du champ est connu
|
if (f.getClazz() != null) {
|
|
if (f.isCollection()) {
|
clazz.addField(VariableSourceGenerator.create(TypeDeclarationSourceGenerator.create(List.class).addGeneric(GenericSourceGenerator.create(f.getClazz())), f.getName())
|
.addModifier(Modifier.PRIVATE));
|
} else {
|
Class realClass = f.getClazz().equals(LocalDate.class) ? String.class : f.getClazz();
|
clazz.addField(
|
VariableSourceGenerator.create(realClass, f.getName())
|
.addModifier(Modifier.PRIVATE)
|
);
|
}
|
|
}
|
});
|
|
//Déclaration du constructeur sans argument
|
clazz.addConstructor(FunctionSourceGenerator.create().addModifier(Modifier.PUBLIC).addBodyCodeLine());
|
|
fields.forEach(f -> {
|
String fieldName = String.valueOf(f.getName().charAt(0)).toUpperCase() + f.getName().substring(1);
|
|
if (f.getClazz() != null) {
|
|
//Déclaration du getter de chaque attribut
|
FunctionSourceGenerator getter = FunctionSourceGenerator.create("get" + fieldName)
|
.addModifier(Modifier.PUBLIC)
|
.addBodyCodeLine("return this." + f.getName() + ";");
|
|
Class realClass = f.getClazz().equals(LocalDate.class) ? String.class : f.getClazz();
|
|
if(f.isCollection()) {
|
getter.setReturnType(TypeDeclarationSourceGenerator.create(List.class).addGeneric(GenericSourceGenerator.create(realClass)));
|
|
} else {
|
getter.setReturnType(realClass);
|
}
|
clazz.addMethod(getter);
|
|
//Déclaration du setter de chaque attribut
|
FunctionSourceGenerator setter = FunctionSourceGenerator.create("set" + fieldName)
|
.addModifier(Modifier.PUBLIC)
|
.setReturnType(void.class)
|
.addBodyCodeLine("this." + f.getName() + " = " + f.getName() + ";");
|
|
if(f.isCollection()) {
|
setter.addParameter(VariableSourceGenerator.create(TypeDeclarationSourceGenerator.create(List.class).addGeneric(GenericSourceGenerator.create(realClass)), f.getName()));
|
} else {
|
setter.addParameter(VariableSourceGenerator.create(realClass, f.getName()));
|
}
|
clazz.addMethod(setter);
|
}
|
});
|
|
//Définition de la valeur de retour de la méthode toString()
|
StringBuilder toString = new StringBuilder();
|
for (JsonField f : fields) {
|
toString.append("this.").append(f.getName()).append("+").append("\",\"").append("+");
|
}
|
|
//Retirer les caractères +","+
|
toString.replace(toString.length() - 5, toString.length(), "");
|
|
//Déclaration de la méthode toString
|
clazz.addMethod(
|
FunctionSourceGenerator.create("toString")
|
.addAnnotation(AnnotationSourceGenerator.create(Override.class))
|
.addModifier(Modifier.PUBLIC)
|
.setReturnType(String.class)
|
.addBodyCodeLine("return " + toString + ";")
|
);
|
|
UnitSourceGenerator unitSG = UnitSourceGenerator.create(packagename).addClass(clazz);
|
unitSG.make();
|
|
//Enregistre la classe sur le disque
|
if(classPathFolder != null && !classPathFolder.isEmpty()) {
|
unitSG.storeToClassPath(classPathFolder);
|
}
|
|
return unitSG;
|
}
|
|
}
|