Skip to content

Commit

Permalink
Fix #373 : [JAVA] Enumérations représentant totalement l'entité #373
Browse files Browse the repository at this point in the history
  • Loading branch information
gideruette committed Jan 20, 2025
1 parent 29ede3f commit 739fc83
Show file tree
Hide file tree
Showing 19 changed files with 588 additions and 125 deletions.
4 changes: 2 additions & 2 deletions TopModel.Generator.Jpa/ClassGeneration/JavaDtoGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ protected override void HandleClass(string fileName, Class classe, string tag)

fw.WriteClassDeclaration(classe.NamePascal, null, extends, implements);

WriteStaticMembers(fw, classe);
WriteStaticMembers(fw, classe, tag);
JpaModelPropertyGenerator.WriteProperties(fw, classe, tag);
WriteConstuctors(fw, classe, tag);

Expand Down Expand Up @@ -92,7 +92,7 @@ protected virtual void WriteConstuctors(JavaWriter fw, Class classe, string tag)
}
}

protected virtual void WriteStaticMembers(JavaWriter fw, Class classe)
protected virtual void WriteStaticMembers(JavaWriter fw, Class classe, string tag)
{
fw.WriteLine(" /** Serial ID */");
fw.WriteLine(1, "private static final long serialVersionUID = 1L;");
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using TopModel.Core;
using TopModel.Generator.Core;
using TopModel.Utils;

namespace TopModel.Generator.Jpa;

Expand All @@ -13,59 +14,54 @@ public JavaEnumConstructorGenerator(JpaConfig config)
{
}

public void WriteEnumConstructor(JavaWriter fw, Class classe, IEnumerable<Class> availableClasses, string tag)
public void WriteEnumConstructor(JavaWriter fw, Class classe, string tag)
{
var codeProperty = classe.EnumKey!;
fw.WriteLine();
fw.WriteDocStart(1, "Enum constructor");
fw.WriteParam(classe.EnumKey!.NameCamel, "Code dont on veut obtenir l'instance");
fw.WriteDocEnd(1);
fw.WriteLine(1, $"public {classe.NamePascal}({Config.GetType(classe.EnumKey!)} {classe.EnumKey!.NameCamel}) {{");
fw.WriteLine(1, $"public {classe.NamePascal}({Config.GetType(classe.EnumKey!)} {codeProperty.Name.ToCamelCase()}) {{");
if (classe.Extends != null || classe.Decorators.Any(d => Config.GetImplementation(d.Decorator)?.Extends is not null))
{
fw.WriteLine(2, $"super();");
}

fw.WriteLine(2, $@"this.{classe.EnumKey!.NameCamel} = {classe.EnumKey!.NameCamel};");
if (classe.GetProperties(availableClasses).Count > 1)
{
fw.WriteLine(2, $@"switch({classe.EnumKey!.NameCamel}) {{");
foreach (var refValue in classe.Values.OrderBy(x => x.Name, StringComparer.Ordinal))
{
var code = refValue.Value[codeProperty];
fw.WriteLine(2, $@"case {code} :");
foreach (var prop in classe.GetProperties(availableClasses).Where(p => p != codeProperty))
{
var isString = Config.GetType(prop) == "String";
var value = refValue.Value.ContainsKey(prop) ? refValue.Value[prop] : "null";
if (value == "null")
{
isString = false;
}
else if (prop is AssociationProperty ap && Config.CanClassUseEnums(ap.Association, prop: ap.Property) && ap.Association.Values.Any(r => r.Value.ContainsKey(ap.Property) && r.Value[ap.Property] == value))
{
value = ap.Association.NamePascal + "." + value;
isString = false;
fw.AddImport(ap.Association.GetImport(Config, tag));
}
else if (prop is AliasProperty alp && Config.CanClassUseEnums(alp.Property.Class, prop: alp.Property))
{
value = Config.GetType(alp.Property) + "." + value;
}
else if (Config.TranslateReferences == true && classe.DefaultProperty == prop && !Config.CanClassUseEnums(classe, prop: prop))
{
value = refValue.ResourceKey;
}
fw.AddImport("java.util.Arrays");
fw.AddImport($"{Config.GetEnumValuePackageName(classe, tag)}.{classe.NamePascal}_Value");
fw.WriteLine(2, $"this(Arrays.stream({classe.NamePascal}_Value.values()).filter(t -> t.get{codeProperty.NamePascal}() == {codeProperty.Name.ToCamelCase()}).findFirst().orElseThrow());");
fw.WriteLine(1, $"}}");
}

var quote = isString ? "\"" : string.Empty;
var val = quote + value + quote;
fw.WriteLine(3, $@"this.{prop.NameByClassCamel} = {val};");
}
public void WriteEnumValueConstructor(JavaWriter fw, Class classe, IEnumerable<Class> availableClasses, string tag)
{
var codeProperty = classe.EnumKey!;
fw.WriteLine();
fw.WriteDocStart(1, "Enum constructor");
fw.WriteParam($"{classe.NameCamel}Value", "Enum de valeur dont on veut obtenir l'entité");
fw.WriteDocEnd(1);
fw.WriteLine(1, $"public {classe.NamePascal}({classe.NamePascal}_Value {classe.NameCamel}Value) {{");
if (classe.Extends != null || classe.Decorators.Any(d => Config.GetImplementation(d.Decorator)?.Extends is not null))
{
fw.WriteLine(2, $"super();");
}

fw.WriteLine(3, $@"break;");
foreach (var prop in classe.GetProperties(availableClasses))
{
var value = $"{classe.NameCamel}Value.get{prop.NameByClassPascal}()";
if (prop is AssociationProperty ap && Config.CanClassUseEnums(ap.Association, prop: ap.Property))
{
value = $"new {ap.Association.NamePascal}({classe.NameCamel}Value.get{prop.NameByClassPascal}Value())";
fw.AddImport(ap.Association.GetImport(Config, tag));
fw.AddImport($"{Config.GetEnumValuePackageName(ap.Association, tag)}.{ap.Association.NamePascal}_Value");
fw.WriteLine(2, $@"if ({classe.NameCamel}Value.get{prop.NameByClassPascal}Value() != null) {{");
fw.WriteLine(3, $@"this.{prop.NameByClassCamel} = {value};");
fw.WriteLine(2, "}");
}
else
{
fw.WriteLine(2, $@"this.{prop.NameByClassCamel} = {value};");
}

fw.WriteLine(2, $@"}}");
}

fw.WriteLine(1, $"}}");
Expand Down
12 changes: 7 additions & 5 deletions TopModel.Generator.Jpa/ClassGeneration/JavaEnumDtoGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,23 +34,25 @@ protected override bool FilterClass(Class classe)
protected override void WriteConstuctors(JavaWriter fw, Class classe, string tag)
{
ConstructorGenerator.WriteNoArgConstructor(fw, classe);
ConstructorGenerator.WriteEnumConstructor(fw, classe, Classes, tag);
ConstructorGenerator.WriteEnumConstructor(fw, classe, tag);
ConstructorGenerator.WriteEnumValueConstructor(fw, classe, Classes, tag);
}

protected override void WriteSetters(JavaWriter fw, Class classe, string tag)
{
return;
}

protected override void WriteStaticMembers(JavaWriter fw, Class classe)
protected override void WriteStaticMembers(JavaWriter fw, Class classe, string tag)
{
base.WriteStaticMembers(fw, classe);
base.WriteStaticMembers(fw, classe, tag);
fw.WriteLine();
var codeProperty = classe.EnumKey!;
foreach (var refValue in classe.Values.OrderBy(x => x.Name, StringComparer.Ordinal))
{
var code = refValue.Value[codeProperty];
fw.WriteLine(1, $@"public static final {classe.NamePascal} {code} = new {classe.NamePascal}({Config.GetEnumName(codeProperty, classe)}.{code});");
fw.AddImport($"{Config.GetEnumValuePackageName(classe, tag)}.{classe.NamePascal}Enum");
fw.WriteLine(1, $@"public static final {classe.NamePascal} {code} = new {classe.NamePascal}({classe.NamePascal}Enum.{code});");
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ protected override void HandleClass(string fileName, Class classe, string tag)

if (Config.CanClassUseEnums(classe, Classes))
{
ConstructorGenerator.WriteEnumConstructor(fw, classe, Classes, tag);
ConstructorGenerator.WriteEnumConstructor(fw, classe, tag);
}

WriteGetters(fw, classe, tag);
Expand Down
18 changes: 9 additions & 9 deletions TopModel.Generator.Jpa/ClassGeneration/JpaEnumEntityGenerator.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using Microsoft.Extensions.Logging;
using TopModel.Core;
using TopModel.Utils;

Check warning on line 3 in TopModel.Generator.Jpa/ClassGeneration/JpaEnumEntityGenerator.cs

View workflow job for this annotation

GitHub Actions / build

Check warning on line 3 in TopModel.Generator.Jpa/ClassGeneration/JpaEnumEntityGenerator.cs

View workflow job for this annotation

GitHub Actions / build

using TopModel.Core.Model.Implementation;

namespace TopModel.Generator.Jpa;
Expand Down Expand Up @@ -57,14 +58,12 @@ protected override void HandleClass(string fileName, Class classe, string tag)
var codeProperty = classe.EnumKey!;
foreach (var refValue in classe.Values.OrderBy(x => x.Name, StringComparer.Ordinal))
{
var code = refValue.Value[codeProperty];
if (classe.IsPersistent)
{
fw.AddImport($"{JavaxOrJakarta}.persistence.Transient");
fw.WriteLine(1, "@Transient");
}

fw.WriteLine(1, $@"public static final {classe.NamePascal} {code} = new {classe.NamePascal}({Config.GetEnumName(codeProperty, classe)}.{code});");
var code = refValue.Name.ToConstantCase();
fw.AddImport($"{JavaxOrJakarta}.persistence.Transient");
fw.WriteLine(1, "@Transient");

fw.AddImport($"{Config.GetEnumValuePackageName(classe, tag)}.{classe.NamePascal}Enum");
fw.WriteLine(1, $@"public static final {classe.NamePascal} {code} = new {classe.NamePascal}({classe.NamePascal}Enum.{code});");
}

JpaModelPropertyGenerator.WriteProperties(fw, classe, tag);
Expand All @@ -88,7 +87,8 @@ protected override void HandleClass(string fileName, Class classe, string tag)
protected override void WriteConstructors(Class classe, string tag, JavaWriter fw)
{
ConstructorGenerator.WriteNoArgConstructor(fw, classe);
ConstructorGenerator.WriteEnumConstructor(fw, classe, Classes, tag);
ConstructorGenerator.WriteEnumConstructor(fw, classe, tag);
ConstructorGenerator.WriteEnumValueConstructor(fw, classe, Classes, tag);
}

protected override void WriteSetters(JavaWriter fw, Class classe, string tag)
Expand Down
199 changes: 199 additions & 0 deletions TopModel.Generator.Jpa/ClassGeneration/JpaEnumValuesGenerator.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,199 @@
using Microsoft.Extensions.Logging;
using TopModel.Core;
using TopModel.Core.FileModel;
using TopModel.Generator.Core;
using TopModel.Utils;

namespace TopModel.Generator.Jpa;

/// <summary>
/// Générateur de fichiers de modèles JPA.
/// </summary>
public class JpaEnumValuesGenerator : GeneratorBase<JpaConfig>
{
private readonly ILogger<JpaEnumValuesGenerator> _logger;

public JpaEnumValuesGenerator(ILogger<JpaEnumValuesGenerator> logger, ModelConfig modelConfig)
: base(logger)
{
_logger = logger;
}

public override string Name => "JpaEnumValuesGen";

public override IEnumerable<string> GeneratedFiles => Files
.Values
.SelectMany(f => f.Classes.Where(FilterClass))
.SelectMany(c => Config.Tags.Intersect(c.Tags).SelectMany(tag => GetEnumProperties(c).Select(p => GetFileName(p, c, tag)))).Distinct();

protected bool FilterClass(Class classe)
{
return !classe.Abstract
&& Config.CanClassUseEnums(classe, Classes.ToList())
&& GetAllValues(classe).All(v => Config.IsEnumNameJavaValid(v.Name));
}

protected string GetFileName(IProperty property, Class classe, string tag)
{
return Config.GetEnumValueFileName(property, classe, tag);
}

protected void HandleClass(Class classe, string tag)
{
foreach (var p in GetEnumProperties(classe))
{
WriteEnum(p, classe, tag);
}
}

protected override void HandleFiles(IEnumerable<ModelFile> files)
{
foreach (var file in files)
{
foreach (var classe in file.Classes.Where(FilterClass))
{
foreach (var tag in Config.Tags.Intersect(classe.Tags))
{
HandleClass(classe, tag);
}
}
}
}

private IEnumerable<IProperty> GetEnumProperties(Class classe)
{
List<IProperty> result = new();
if (classe.EnumKey != null && Config.CanClassUseEnums(classe, prop: classe.EnumKey) && !(classe.Extends != null && Config.CanClassUseEnums(classe.Extends, Classes, prop: classe.EnumKey)))
{
result.Add(classe.EnumKey);
}

var uks = classe.UniqueKeys.Where(uk => uk.Count == 1 && Config.CanClassUseEnums(classe, Classes, uk.Single()) && !(classe.Extends != null && Config.CanClassUseEnums(classe.Extends, Classes, prop: classe.EnumKey))).Select(uk => uk.Single());
result.AddRange(uks);
return result;
}

private void WriteConstructor(Class classe, JavaWriter fw, IEnumerable<IProperty> properties)
{
// Constructeur
fw.WriteDocStart(1, "Enum constructor");
fw.WriteDocEnd(1);
var constructor = new JavaConstructor(classe.NamePascal + "Enum");
var methodParams = properties.Select((prop, index) =>
{
var fieldName = prop.NameByClassCamel;
var fieldType = Config.GetType(prop);
if (prop is AssociationProperty ap)
{
fieldName = $"{ap.NameByClassCamel}Value";
fieldType = $"{ap.Association.NamePascal}Enum";
}

return new JavaMethodParameter(fieldType, fieldName) { Final = true };
});
constructor.AddParameters(methodParams);
fw.Write(1, constructor);
}

private void WriteEnum(IProperty property, Class classe, string tag)
{
var packageName = Config.GetEnumValuePackageName(classe, tag);
using var fw = new JavaWriter(Config.GetEnumValueFileName(property, classe, tag), _logger, packageName, null);
fw.WriteLine();
var codeProperty = classe.EnumKey!;
fw.WriteDocStart(0, $"Enumération des valeurs possibles de la classe {classe.NamePascal}");
fw.WriteDocEnd(0);
fw.WriteLine($@"public enum {classe.NamePascal}Enum {{");
var i = 0;

var refs = GetAllValues(classe)
.ToList();

foreach (var refValue in refs)
{
if (i > 0)
{
fw.WriteLine();
}

i++;
var isLast = i == refs.Count();
if (classe.DefaultProperty != null)
{
fw.WriteDocStart(1, $"{refValue.Value[classe.DefaultProperty]}");
fw.WriteDocEnd(1);
}

List<string> enumAsString = [$"{refValue.Name.ToConstantCase()}("];
foreach (var prop in classe.Properties)
{
var isString = Config.GetType(prop) == "String";
var isInt = Config.GetType(prop) == "int";
var isBoolean = Config.GetType(prop) == "Boolean";
var value = refValue.Value.ContainsKey(prop) ? refValue.Value[prop] : "null";

if (prop is AssociationProperty ap && ap.Association.Values.Any(r => r.Value.ContainsKey(ap.Property) && r.Value[ap.Property] == value))
{
fw.AddImport($"{Config.GetEnumValuePackageName(ap.Association.EnumKey!.Class, tag)}.{ap.Association.NamePascal}Enum");
value = ap.Association.NamePascal + "Enum." + value;
isString = false;
}
else if (Config.CanClassUseEnums(classe, prop: prop))
{
value = Config.GetType(prop) + "." + value;
}

if (Config.TranslateReferences == true && classe.DefaultProperty == prop && !Config.CanClassUseEnums(classe, prop: prop))
{
value = refValue.ResourceKey;
}

var quote = isString ? "\"" : string.Empty;
var val = quote + value + quote;
enumAsString.Add($@"{val}{(prop == classe.Properties.Last() ? string.Empty : ", ")}");
}

enumAsString.Add($"){(isLast ? ";" : ",")} ");
fw.WriteLine(1, enumAsString.Aggregate(string.Empty, (acc, curr) => acc + curr));
}

foreach (var prop in classe.Properties)
{
fw.WriteLine();
fw.WriteDocStart(1, $@"{prop.NameByClassPascal}");
fw.WriteDocEnd(1);
var fieldName = prop.NameByClassCamel;
if (prop is AssociationProperty ap)
{
fieldName = $"{ap.NameByClassCamel}Value";
fw.WriteLine(1, $@"private final {ap.Association.NamePascal}Enum {fieldName};");
}
else
{
fw.WriteLine(1, $@"private final {Config.GetType(prop)} {fieldName};");
}
}

WriteConstructor(classe, fw, classe.Properties);

foreach (var prop in classe.Properties)
{
fw.WriteLine();
var fieldName = prop.NameByClassCamel;
fw.WriteDocStart(1, $"Getter for {fieldName}");
fw.WriteDocEnd(1);
var fieldType = Config.GetType(prop);
if (prop is AssociationProperty ap && Config.CanClassUseEnums(ap.Association, Classes))
{
fieldName = $"{ap.NameByClassCamel}Value";
fieldType = $"{ap.Association.NamePascal}Enum";
}

var method = new JavaMethod(fieldType, $"get{fieldName.ToFirstUpper()}") { Visibility = "public" };
method.AddBodyLine($@"return this.{fieldName};");
fw.Write(1, method);
}

fw.WriteLine("}");
}
}
Loading

0 comments on commit 739fc83

Please sign in to comment.