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

Fix #373 : [JAVA] Enumérations représentant totalement l'entité #373 #407

Draft
wants to merge 1 commit into
base: develop
Choose a base branch
from
Draft
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
7 changes: 7 additions & 0 deletions TopModel.Generator.Jpa/GeneratorRegistration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,16 @@ public class GeneratorRegistration : IGeneratorRegistration<JpaConfig>
/// <inheritdoc cref="IGeneratorRegistration{T}.Register" />
public void Register(IServiceCollection services, JpaConfig config, int number)
{
if (config.EnumsValuesPath == "default")
{
config.EnumsValuesPath = config.EnumsPath;
}

TrimSlashes(config, c => c.EntitiesPath);
TrimSlashes(config, c => c.DaosPath);
TrimSlashes(config, c => c.DtosPath);
TrimSlashes(config, c => c.EnumsPath);
TrimSlashes(config, c => c.EnumsValuesPath);
TrimSlashes(config, c => c.ApiPath);
TrimSlashes(config, c => c.ResourcesPath);

Expand All @@ -23,6 +29,7 @@ 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);
services.AddGenerator<JpaEnumValueGenerator, JpaConfig>(config, number);
if (config.DaosPath != null)
{
services.AddGenerator<JpaDaoGenerator, JpaConfig>(config, number);
Expand Down
27 changes: 26 additions & 1 deletion TopModel.Generator.Jpa/JpaConfig.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

namespace TopModel.Generator.Jpa;

public class JpaConfig : GeneratorConfigBase

Check warning on line 10 in TopModel.Generator.Jpa/JpaConfig.cs

View workflow job for this annotation

GitHub Actions / build

Les éléments de la classe ne sont pas dans le bon ordre

Check warning on line 10 in TopModel.Generator.Jpa/JpaConfig.cs

View workflow job for this annotation

GitHub Actions / build

Les éléments de la classe ne sont pas dans le bon ordre
{
/// <summary>
/// Localisation des classes persistées du modèle, relative au répertoire de génération. Par défaut, 'javagen/{app}/entities/{module}'.
Expand All @@ -15,10 +15,15 @@
public string EntitiesPath { get; set; } = "javagen:{app}/entities/{module}";

/// <summary>
/// Localisation des classes persistées du modèle, relative au répertoire de génération. Par défaut, 'javagen/{app}/entities/{module}'.
/// Localisation des enums, relative au répertoire de génération. Par défaut, 'javagen:{app}/enums/{module}'.
/// </summary>
public string EnumsPath { get; set; } = "javagen:{app}/enums/{module}";

/// <summary>
/// Localisation des enums de valeurs, relative au répertoire de génération. Par défaut, 'javagen:{app}/enums/{module}'.
/// </summary>
public string EnumsValuesPath { get; set; } = "default";

/// <summary>
/// Localisation des DAOs, relative au répertoire de génération.
/// </summary>
Expand Down Expand Up @@ -158,6 +163,7 @@
nameof(DtosPath),
nameof(ApiPath),
nameof(EnumsPath),
nameof(EnumsValuesPath),
nameof(ApiGeneration),
nameof(ResourcesPath),
nameof(DbSchema)
Expand All @@ -170,6 +176,7 @@
nameof(DtosPath),
nameof(ApiPath),
nameof(EnumsPath),
nameof(EnumsValuesPath),
nameof(DataFlowsPath)
];

Expand Down Expand Up @@ -232,6 +239,14 @@
$"{GetEnumName(property, classe)}.java");
}

public string GetEnumValueFileName(IProperty property, Class classe, string tag)
{
return Path.Combine(
OutputDirectory,
ResolveVariables(EnumsValuesPath, tag, module: classe.Namespace.Module).ToFilePath(),
$"{classe.NamePascal}_Value.java");
}

public string GetEnumName(IProperty property, Class classe)
{
return $"{classe.NamePascal}{property.Name.ToPascalCase()}";
Expand All @@ -242,6 +257,11 @@
return GetPackageName(classe.Namespace, EnumsPath, tag);
}

public string GetEnumValuePackageName(Class classe, string tag)
{
return GetPackageName(classe.Namespace, EnumsValuesPath, tag);
}

public string GetMapperFilePath((Class Classe, FromMapper Mapper) mapper, string tag)
{
var (ns, modelPath) = GetMapperLocation(mapper);
Expand Down Expand Up @@ -333,4 +353,9 @@
{
return base.IsEnumNameValid(name) && !Regex.IsMatch(name ?? string.Empty, "(?<=[^$\\w'\"\\])(?!(abstract|assert|boolean|break|byte|case|catch|char|class|const|continue|default|double|do|else|enum|extends|false|final|finally|float|for|goto|if|implements|import|instanceof|int|interface|long|native|new|null|package|private|protected|public|return|short|static|strictfp|super|switch|synchronized|this|throw|throws|transient|true|try|void|volatile|while|_\\b))([A-Za-z_$][$\\w]*)");
}

public bool IsEnumNameJavaValid(string name)

Check warning on line 357 in TopModel.Generator.Jpa/JpaConfig.cs

View workflow job for this annotation

GitHub Actions / build

Check warning on line 357 in TopModel.Generator.Jpa/JpaConfig.cs

View workflow job for this annotation

GitHub Actions / build

{
return IsEnumNameValid(name);
}
}
213 changes: 213 additions & 0 deletions TopModel.Generator.Jpa/JpaEnumValueGenerator.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,213 @@
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 JpaEnumValueGenerator : GeneratorBase<JpaConfig>

Check warning on line 12 in TopModel.Generator.Jpa/JpaEnumValueGenerator.cs

View workflow job for this annotation

GitHub Actions / build

Les éléments de la classe ne sont pas dans le bon ordre

Check warning on line 12 in TopModel.Generator.Jpa/JpaEnumValueGenerator.cs

View workflow job for this annotation

GitHub Actions / build

Les éléments de la classe ne sont pas dans le bon ordre
{
private readonly ILogger<JpaEnumValueGenerator> _logger;

public JpaEnumValueGenerator(ILogger<JpaEnumValueGenerator> 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 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}_Value {{");
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}_Value");
value = ap.Association.NamePascal + "_Value." + 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}_Value {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);
if (prop is AssociationProperty ap)
{
fieldName = $"{ap.NameByClassCamel}Value";
fw.WriteLine(1, $@"public {ap.Association.NamePascal}_Value get{fieldName.ToFirstUpper()}() {{");
}
else
{
fw.WriteLine(1, $@"public {Config.GetType(prop)} get{fieldName.ToFirstUpper()}() {{");
}

fw.WriteLine(2, $@"return this.{fieldName};");
fw.WriteLine(1, $@"}}");
}

fw.WriteLine("}");
}

private void WriteConstructor(Class classe, JavaWriter fw, IEnumerable<IProperty> properties)
{
// Constructeur
fw.WriteDocStart(1, "Enum constructor");
fw.WriteDocEnd(1);
string constructorAsString =
$@"{classe.NamePascal}_Value(" +
string.Join(", ", properties.Select((prop, index) =>
{
var fieldName = prop.NameByClassCamel;
if (prop is AssociationProperty ap)
{
fieldName = $"{ap.NameByClassCamel}Value";
return $@"final {ap.Association.NamePascal}_Value {fieldName}";
}

return $@"final {Config.GetType(prop)} {fieldName}";
})) + "){";
fw.WriteLine(1, constructorAsString);
foreach (var prop in properties)
{
var fieldName = prop.NameByClassCamel;
if (prop is AssociationProperty ap)
{
fieldName = $"{ap.NameByClassCamel}Value";
}

// Constructeur set
fw.WriteLine(2, $@" this.{fieldName} = {fieldName};");
}

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