Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[JAVA] Enumérations représentant totalement l'entité #384

Open
wants to merge 1 commit into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions TopModel.Generator.Jpa/GeneratorRegistration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ public void Register(IServiceCollection services, JpaConfig config, int number)
TrimSlashes(config, c => c.DtosPath);
TrimSlashes(config, c => c.EnumsPath);
TrimSlashes(config, c => c.ApiPath);
TrimSlashes(config, c => c.EnumConverterPath);
TrimSlashes(config, c => c.ResourcesPath);

config.Language ??= "java";
Expand All @@ -23,6 +24,11 @@ public void Register(IServiceCollection services, JpaConfig config, int number)
services.AddGenerator<JpaModelInterfaceGenerator, JpaConfig>(config, number);
services.AddGenerator<JpaMapperGenerator, JpaConfig>(config, number);
services.AddGenerator<JpaEnumGenerator, JpaConfig>(config, number);
if (config.EnumsAsEnum)
{
services.AddGenerator<JpaConverterGenerator, JpaConfig>(config, number);
}

if (config.DaosPath != null)
{
services.AddGenerator<JpaDaoGenerator, JpaConfig>(config, number);
Expand Down
7 changes: 4 additions & 3 deletions TopModel.Generator.Jpa/JavaWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,8 @@ public void WriteAttribute(int indentLevel, string attributeName, params string[
/// <param name="modifier">Modifier.</param>
/// <param name="inheritedClass">Classe parente.</param>
/// <param name="implementingInterfaces">Interfaces implémentées.</param>
public void WriteClassDeclaration(string name, string? modifier, string? inheritedClass = null, IList<string>? implementingInterfaces = null)
/// <param name="classType">Class type (enum, class).</param>
public void WriteClassDeclaration(string name, string? modifier, string? inheritedClass = null, IList<string>? implementingInterfaces = null, string classType = "class")
{
if (string.IsNullOrEmpty(name))
{
Expand All @@ -86,11 +87,11 @@ public void WriteClassDeclaration(string name, string? modifier, string? inherit

if (string.IsNullOrEmpty(modifier))
{
sb.Append($"public class ");
sb.Append($"public {classType} ");
}
else
{
sb.Append($"public {modifier} class ");
sb.Append($"public {modifier} {classType} ");
}

sb.Append(name);
Expand Down
13 changes: 12 additions & 1 deletion TopModel.Generator.Jpa/JpaConfig.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,11 @@ public class JpaConfig : GeneratorConfigBase
/// </summary>
public string? DaosPath { get; set; }

/// <summary>
/// Localisation des DAOs, relative au répertoire de génération.
/// </summary>
public string? EnumConverterPath { get; set; } = "javagen:{app}/converters/{module}";

/// <summary>
/// Localisation des classses non persistées du modèle, relative au répertoire de génération. Par défaut, 'javagen/{app}/dtos/{module}'.
/// </summary>
Expand Down Expand Up @@ -59,6 +64,11 @@ public class JpaConfig : GeneratorConfigBase
/// </summary>
public bool EnumShortcutMode { get; set; }

/// <summary>
/// Option pour remplacer les classes de listes de références par des enums
/// </summary>
public bool EnumsAsEnum { get; set; }

/// <summary>
/// Nom du schéma sur lequel les entités sont sauvegardées
/// </summary>
Expand Down Expand Up @@ -170,7 +180,8 @@ public class JpaConfig : GeneratorConfigBase
nameof(DtosPath),
nameof(ApiPath),
nameof(EnumsPath),
nameof(DataFlowsPath)
nameof(DataFlowsPath),
nameof(EnumConverterPath)
];

public override bool CanClassUseEnums(Class classe, IEnumerable<Class>? availableClasses = null, IProperty? prop = null)
Expand Down
72 changes: 72 additions & 0 deletions TopModel.Generator.Jpa/JpaConverterGenerator.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
using Microsoft.Extensions.Logging;
using TopModel.Core;
using TopModel.Generator.Core;

namespace TopModel.Generator.Jpa;

/// <summary>
/// Générateur de DAOs JPA.
/// </summary>
public class JpaConverterGenerator : ClassGeneratorBase<JpaConfig>
{
private readonly ILogger<JpaConverterGenerator> _logger;

public JpaConverterGenerator(ILogger<JpaConverterGenerator> logger)
: base(logger)
{
_logger = logger;
}

public override string Name => "JpaConverterGen";

protected override bool FilterClass(Class classe)
{
return classe.IsPersistent && (!Config.UseJdbc || classe.PrimaryKey.Count() <= 1) && Config.CanClassUseEnums(classe) && Config.EnumsAsEnum;
}

protected override string GetFileName(Class classe, string tag)
{
string path = $"{classe.NamePascal}Converter.java";
return Path.Combine(
Config.OutputDirectory,
Config.ResolveVariables(Config.EnumConverterPath!, tag, module: classe.Namespace.Module).ToFilePath(),
path);
}

protected override void HandleClass(string fileName, Class classe, string tag)
{
var packageName = Config.ResolveVariables(
Config.EnumConverterPath!,
tag,
module: classe.Namespace.Module).ToPackageName();

using var fw = new JavaWriter(fileName, _logger, packageName, null);
fw.WriteLine();
fw.AddImport(classe.GetImport(Config, tag));
var javaOrJakarta = Config.PersistenceMode.ToString().ToLower();
fw.AddImport($"{javaOrJakarta}.persistence.AttributeConverter");
List<string> implements = new()
{
$"AttributeConverter<{classe.NamePascal}, String>"
};
fw.WriteClassDeclaration($"{classe.NamePascal}Converter", null, null, implements);

fw.WriteLine();
fw.WriteLine(1, "@Override");
fw.WriteLine(1, $@"public String convertToDatabaseColumn({classe.NamePascal} item) {{");
fw.WriteLine(2, $"return item == null ? null : item.get{classe.EnumKey.NamePascal}().name();");

Check warning on line 57 in TopModel.Generator.Jpa/JpaConverterGenerator.cs

View workflow job for this annotation

GitHub Actions / build

Dereference of a possibly null reference.
fw.WriteLine(1, "}");
WriteEnumEntityToAttribute(fw, classe);
fw.WriteLine("}");
}

private void WriteEnumEntityToAttribute(JavaWriter fw, Class classe)
{
fw.WriteLine();
fw.WriteLine(1, "@Override");
fw.WriteLine(1, $"public {classe.NamePascal} convertToEntityAttribute(String {classe.EnumKey!.NameCamel}) {{");
fw.WriteLine(2, $@"return {classe.NamePascal}.from({classe.EnumKey!.NameCamel});");

fw.WriteLine(1, $"}}");
}
}
2 changes: 1 addition & 1 deletion TopModel.Generator.Jpa/JpaDaoGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public JpaDaoGenerator(ILogger<JpaDaoGenerator> logger)

protected override bool FilterClass(Class classe)
{
return classe.IsPersistent && (!Config.UseJdbc || classe.PrimaryKey.Count() <= 1);
return classe.IsPersistent && (!Config.UseJdbc || classe.PrimaryKey.Count() <= 1) && !(Config.CanClassUseEnums(classe) && Config.EnumsAsEnum);
}

protected override string GetFileName(Class classe, string tag)
Expand Down
10 changes: 9 additions & 1 deletion TopModel.Generator.Jpa/JpaMapperGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,15 @@ protected override void HandleFile(string fileName, string tag, IList<(Class Cla
}
else
{
getter = $"new {apTarget.Association.NamePascal}({sourceName}.{propertySource.NameByClassPascal.WithPrefix(getterPrefix)}())";
if (!Config.EnumsAsEnum)
{
getter = $"new {apTarget.Association.NamePascal}({sourceName}.{propertySource.NameByClassPascal.WithPrefix(getterPrefix)}())";
}
else
{
getter = $"{apTarget.Association.NamePascal}.from({sourceName}.{propertySource.NameByClassPascal.WithPrefix(getterPrefix)}())";
}

fw.AddImport(apTarget.Association.GetImport(Config, tag));
checkSourceNull = true;
}
Expand Down
22 changes: 13 additions & 9 deletions TopModel.Generator.Jpa/JpaModelConstructorGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,22 @@ public JpaModelConstructorGenerator(JpaConfig config)
public void WriteEnumConstructor(JavaWriter fw, Class classe, List<Class> availableClasses, string tag, ModelConfig modelConfig)
{
var codeProperty = classe.EnumKey!;
fw.WriteLine();
foreach (var refValue in classe.Values.OrderBy(x => x.Name, StringComparer.Ordinal))

if (!_config.EnumsAsEnum)
{
var code = refValue.Value[codeProperty];
fw.WriteLine(1, $@"public static final {classe.NamePascal} {code} = new {classe.NamePascal}({_config.GetEnumName(codeProperty, classe)}.{code});");
fw.WriteLine();
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.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, $"{(_config.EnumsAsEnum ? "private" : "public")} {classe.NamePascal}({_config.GetType(classe.EnumKey!)} {classe.EnumKey!.NameCamel}) {{");
if (classe.Extends != null || classe.Decorators.Any(d => _config.GetImplementation(d.Decorator)?.Extends is not null))
{
fw.WriteLine(2, $"super();");
Expand All @@ -42,7 +46,7 @@ public void WriteEnumConstructor(JavaWriter fw, Class classe, List<Class> availa
foreach (var refValue in classe.Values.OrderBy(x => x.Name, StringComparer.Ordinal))
{
var code = refValue.Value[codeProperty];
fw.WriteLine(2, $@"case {code} :");
fw.WriteLine(3, $@"case {code} :");
foreach (var prop in classe.GetProperties(availableClasses).Where(p => p != codeProperty))
{
var isString = _config.GetType(prop) == "String";
Expand All @@ -65,13 +69,13 @@ public void WriteEnumConstructor(JavaWriter fw, Class classe, List<Class> availa

var quote = isString ? "\"" : string.Empty;
var val = quote + value + quote;
fw.WriteLine(3, $@"this.{prop.NameByClassCamel} = {val};");
fw.WriteLine(4, $@"this.{prop.NameByClassCamel} = {val};");
}

fw.WriteLine(3, $@"break;");
fw.WriteLine(4, $@"break;");
}

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

fw.WriteLine(1, $"}}");
Expand Down
74 changes: 61 additions & 13 deletions TopModel.Generator.Jpa/JpaModelGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -80,31 +80,43 @@ protected override void HandleClass(string fileName, Class classe, string tag)

var implements = Config.GetClassImplements(classe).ToList();

if (!classe.IsPersistent)
if (!classe.IsPersistent && !(Config.EnumsAsEnum && Config.CanClassUseEnums(classe, AvailableClasses)))
{
implements.Add("Serializable");
fw.AddImport("java.io.Serializable");
}

fw.WriteClassDeclaration(classe.NamePascal, null, extends, implements);
var classType = Config.EnumsAsEnum && Config.CanClassUseEnums(classe, AvailableClasses) ? "enum" : "class";
fw.WriteClassDeclaration(classe.NamePascal, null, extends, implements, classType);

if (!classe.IsPersistent)
if (!classe.IsPersistent && !(Config.EnumsAsEnum && Config.CanClassUseEnums(classe, AvailableClasses)))
{
fw.WriteLine(" /** Serial ID */");
fw.WriteLine(1, "private static final long serialVersionUID = 1L;");
}

if (Config.EnumsAsEnum && Config.CanClassUseEnums(classe, AvailableClasses))
{
var codeProperty = classe.EnumKey!;
var refValues = classe.Values.OrderBy(x => x.Name, StringComparer.Ordinal).ToList();
foreach (var refValue in refValues)
{
var code = refValue.Value[codeProperty];
fw.WriteLine(1, $@"{refValue.Name}({Config.GetEnumName(codeProperty, classe)}.{code}){(refValues.IndexOf(refValue) == refValues.Count - 1 ? ";" : ",")}");
}
}

JpaModelPropertyGenerator.WriteProperties(fw, classe, tag);
if (!Config.UseJdbc)
{
JpaModelPropertyGenerator.WriteCompositePrimaryKeyClass(fw, classe, tag);
}

if (Config.CanClassUseEnums(classe, Classes)
|| Config.MappersInClass && classe.FromMappers.Any(c => c.ClassParams.All(p => AvailableClasses.Contains(p.Class)))
if (Config.CanClassUseEnums(classe, Classes) && !Config.EnumsAsEnum
|| Config.MappersInClass && classe.FromMappers.Exists(c => c.ClassParams.All(p => AvailableClasses.Contains(p.Class)))
|| classe.Extends != null
|| AvailableClasses.Any(c => c.Extends == classe)
|| classe.Decorators.Any(d => Config.GetImplementation(d.Decorator)?.Extends is not null))
|| AvailableClasses.Exists(c => c.Extends == classe)
|| classe.Decorators.Exists(d => Config.GetImplementation(d.Decorator)?.Extends is not null))
{
JpaModelConstructorGenerator.WriteNoArgConstructor(fw, classe);
}
Expand All @@ -119,8 +131,17 @@ protected override void HandleClass(string fileName, Class classe, string tag)
JpaModelConstructorGenerator.WriteEnumConstructor(fw, classe, AvailableClasses, tag, _modelConfig);
}

if (Config.CanClassUseEnums(classe, Classes))
{
WriteEnumFrom(fw, classe);
}

WriteGetters(fw, classe, tag);
WriteSetters(fw, classe, tag);
if (!(Config.EnumsAsEnum && Config.CanClassUseEnums(classe, AvailableClasses)))
{
WriteSetters(fw, classe, tag);
}

if (!Config.UseJdbc)
{
WriteAdders(fw, classe, tag);
Expand Down Expand Up @@ -187,7 +208,7 @@ private void WriteAnnotations(JavaWriter fw, Class classe, string tag)
fw.WriteLine("@Generated(\"TopModel : https://github.com/klee-contrib/topmodel\")");
}

if (classe.IsPersistent)
if (classe.IsPersistent && !(Config.EnumsAsEnum && Config.CanClassUseEnums(classe, AvailableClasses)))
{
if (Config.UseJdbc)
{
Expand Down Expand Up @@ -272,10 +293,37 @@ private void WriteAnnotations(JavaWriter fw, Class classe, string tag)

foreach (var a in Config.GetDecoratorAnnotations(classe, tag))
{
fw.WriteLine($"{(a.StartsWith("@") ? string.Empty : "@")}{a}");
fw.WriteLine($"{(a.StartsWith('@') ? string.Empty : '@')}{a}");
}
}

private void WriteEnumFrom(JavaWriter fw, Class classe)
{
var codeProperty = classe.EnumKey!;
fw.WriteLine();
fw.WriteLine(1, $"public static {classe.NamePascal} from(String {classe.EnumKey!.NameCamel}) {{");
fw.WriteLine(2, $"return from({Config.GetType(codeProperty)}.valueOf({classe.EnumKey!.NameCamel}));");
fw.WriteLine(1, $"}}");

fw.WriteLine();
fw.WriteLine(1, $"public static {classe.NamePascal} from({Config.GetType(codeProperty)} {classe.EnumKey!.NameCamel}) {{");
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(3, $@"case {code}:");
fw.WriteLine(4, $@"return {refValue.Name};");
}

fw.WriteLine(3, $@"default:");
fw.AddImport("java.util.NoSuchElementException");
fw.WriteLine(4, $@"throw new NoSuchElementException({classe.EnumKey!.NameCamel} + "" value unrecognized"");");

fw.WriteLine(2, "}");

fw.WriteLine(1, $"}}");
}

private void WriteEnumShortcuts(JavaWriter fw, Class classe, string tag)
{
foreach (var ap in classe.GetProperties(AvailableClasses).OfType<AssociationProperty>().Where(ap => Config.CanClassUseEnums(ap.Association)))
Expand Down Expand Up @@ -467,13 +515,13 @@ private void WriteSetters(JavaWriter fw, Class classe, string tag)

private void WriteToMappers(JavaWriter fw, Class classe, string tag)
{
var toMappers = classe.ToMappers.Where(p => AvailableClasses.Contains(p.Class)).Select(m => (classe, m))
.OrderBy(m => m.m.Name)
var toMappers = classe.ToMappers.Where(p => AvailableClasses.Contains(p.Class)).Select(mapper => (classe, mapper))
.OrderBy(m => m.mapper.Name)
.ToList();

foreach (var toMapper in toMappers)
{
var (clazz, mapper) = toMapper;
var mapper = toMapper.mapper;

fw.WriteLine();
fw.WriteDocStart(1, $"Mappe '{classe}' vers '{mapper.Class.NamePascal}'");
Expand Down
Loading
Loading