From dd2ea83b50618e2cc35ed6b18bb6c555473bcf9c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gild=C3=A9ric=20DERUETTE?= Date: Mon, 18 Nov 2024 23:09:26 +0100 Subject: [PATCH 1/5] =?UTF-8?q?[JPA]=20Big=20Bang=20:=20simplification=20e?= =?UTF-8?q?t=20s=C3=A9paration=20des=20g=C3=A9n=C3=A9rateurs=20(pour=20fac?= =?UTF-8?q?iliter=20les=20futures=20=C3=A9vols)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../GeneratorConfigBase.cs | 15 +- .../CSharpClassGenerator.cs | 4 +- TopModel.Generator.Jpa/CHANGELOG.md | 7 + .../GeneratorRegistration.cs | 13 +- .../ImportsJpaExtensions.cs | 20 - TopModel.Generator.Jpa/JavaAnnotation.cs | 73 +++ .../JavaClassGeneratorBase.cs | 175 ++++++ .../JavaConstructorGenerator.cs | 84 +++ TopModel.Generator.Jpa/JavaDtoGenerator.cs | 102 ++++ .../JavaEnumConstructorGenerator.cs | 73 +++ .../JavaEnumDtoGenerator.cs | 58 ++ TopModel.Generator.Jpa/JavaWriter.cs | 24 + TopModel.Generator.Jpa/JdbcEntityGenerator.cs | 161 +++++ TopModel.Generator.Jpa/JpaConfig.cs | 5 - TopModel.Generator.Jpa/JpaEntityGenerator.cs | 231 +++++++ .../JpaEnumEntityGenerator.cs | 98 +++ TopModel.Generator.Jpa/JpaMapperGenerator.cs | 8 +- .../JpaModelConstructorGenerator.cs | 139 ----- TopModel.Generator.Jpa/JpaModelGenerator.cs | 525 ---------------- .../JpaModelInterfaceGenerator.cs | 8 +- .../JpaModelPropertyGenerator.cs | 577 ++++++++++-------- .../SpringClientApiGenerator.cs | 8 +- .../SpringDataFlowGenerator.cs | 8 +- .../SpringRestTemplateApiGenerator.cs | 4 +- .../SpringServerApiGenerator.cs | 8 +- TopModel.Generator.Jpa/jpa.config.json | 5 - .../PhpModelPropertyGenerator.cs | 2 +- docs/generator/jpa.md | 28 - .../demo/dtos/securite/profil/ProfilRead.java | 4 +- .../dtos/securite/profil/ProfilWrite.java | 4 +- .../securite/utilisateur/UtilisateurRead.java | 10 +- .../utilisateur/UtilisateurWrite.java | 10 +- .../demo/entities/securite/profil/Droit.java | 4 +- .../demo/entities/securite/profil/Profil.java | 10 +- .../entities/securite/profil/TypeDroit.java | 4 +- .../securite/utilisateur/TypeUtilisateur.java | 4 +- .../securite/utilisateur/Utilisateur.java | 10 +- samples/generators/jpa/topmodel.config | 1 - .../jpa/topmodel.config.schema.json | 5 - samples/model/jpa.topmodel.lock | 2 +- 40 files changed, 1473 insertions(+), 1058 deletions(-) create mode 100644 TopModel.Generator.Jpa/JavaAnnotation.cs create mode 100644 TopModel.Generator.Jpa/JavaClassGeneratorBase.cs create mode 100644 TopModel.Generator.Jpa/JavaConstructorGenerator.cs create mode 100644 TopModel.Generator.Jpa/JavaDtoGenerator.cs create mode 100644 TopModel.Generator.Jpa/JavaEnumConstructorGenerator.cs create mode 100644 TopModel.Generator.Jpa/JavaEnumDtoGenerator.cs create mode 100644 TopModel.Generator.Jpa/JdbcEntityGenerator.cs create mode 100644 TopModel.Generator.Jpa/JpaEntityGenerator.cs create mode 100644 TopModel.Generator.Jpa/JpaEnumEntityGenerator.cs delete mode 100644 TopModel.Generator.Jpa/JpaModelConstructorGenerator.cs delete mode 100644 TopModel.Generator.Jpa/JpaModelGenerator.cs diff --git a/TopModel.Generator.Core/GeneratorConfigBase.cs b/TopModel.Generator.Core/GeneratorConfigBase.cs index f7f8b6f0..3e7ed45b 100644 --- a/TopModel.Generator.Core/GeneratorConfigBase.cs +++ b/TopModel.Generator.Core/GeneratorConfigBase.cs @@ -184,15 +184,14 @@ public IEnumerable GetDecoratorImports(Endpoint endpoint, string tag) .Distinct(); } - public IEnumerable GetDomainAnnotations(IProperty property, string tag) + public IEnumerable<(string Annotation, IEnumerable Imports)> GetDomainAnnotations(IProperty property, string tag) { if (property.Domain is not null) { foreach (var annotation in GetImplementation(property.Domain)!.Annotations - .Where(a => FilterAnnotations(a, property, tag)) - .Select(a => a.Text.ParseTemplate(property, this, tag))) + .Where(a => FilterAnnotations(a, property, tag))) { - yield return annotation; + yield return (Annotation: annotation.Text.ParseTemplate(property, this, tag), Imports: annotation.Imports.Select(i => i.ParseTemplate(property, this, tag))); } } } @@ -213,14 +212,6 @@ public IEnumerable GetDomainImports(IProperty property, string tag) { yield return import; } - - var op = property switch - { - AssociationProperty ap => ap.Property, - AliasProperty { OriginalProperty: AssociationProperty ap } => ap.Property, - AliasProperty alp => alp.OriginalProperty, - _ => property - }; } } diff --git a/TopModel.Generator.Csharp/CSharpClassGenerator.cs b/TopModel.Generator.Csharp/CSharpClassGenerator.cs index 890b2ab7..8f793973 100644 --- a/TopModel.Generator.Csharp/CSharpClassGenerator.cs +++ b/TopModel.Generator.Csharp/CSharpClassGenerator.cs @@ -368,7 +368,7 @@ protected virtual void GenerateProperty(CSharpWriter w, IProperty property, Hash && !sameColumnSet.Contains(property.SqlName)) { var sqlName = Config.UseLowerCaseSqlNames ? property.SqlName.ToLower() : property.SqlName; - if (!Config.GetDomainAnnotations(property, tag).Any(a => a.TrimStart('[').StartsWith("Column"))) + if (!Config.GetDomainAnnotations(property, tag).Any(a => a.Annotation.TrimStart('[').StartsWith("Column"))) { w.WriteAttribute(1, "Column", $@"""{sqlName}"""); } @@ -404,7 +404,7 @@ protected virtual void GenerateProperty(CSharpWriter w, IProperty property, Hash foreach (var annotation in Config.GetDomainAnnotations(property, tag)) { - w.WriteAttribute(1, annotation); + w.WriteAttribute(1, annotation.Annotation); } if (Config.IsPersistent(property.Class, tag) && property is AssociationProperty { Type: AssociationType.OneToMany or AssociationType.ManyToMany }) diff --git a/TopModel.Generator.Jpa/CHANGELOG.md b/TopModel.Generator.Jpa/CHANGELOG.md index 2bc528ac..6ae0a3c8 100644 --- a/TopModel.Generator.Jpa/CHANGELOG.md +++ b/TopModel.Generator.Jpa/CHANGELOG.md @@ -1,3 +1,10 @@ +## 1.1.0 + +Breaking changes : +- Suppression du mode `enumShortcut` +- Les DAO des listes de références ne sont plus générés. La première génération risque de les supprimer + - Annuler la suppression des DAO utilisés. Normalement, il y en a peu, d'où la suppression de la génération automatique... + ## 1.0.11 - [d31beb](https://github.com/klee-contrib/topmodel/commit/d31beb5e0d42178e62f6b19316abcbbccde8884d) Fix Initialisation enum dans le cas d'alias ou d'association : cas null diff --git a/TopModel.Generator.Jpa/GeneratorRegistration.cs b/TopModel.Generator.Jpa/GeneratorRegistration.cs index 82c73edc..f16bccb1 100644 --- a/TopModel.Generator.Jpa/GeneratorRegistration.cs +++ b/TopModel.Generator.Jpa/GeneratorRegistration.cs @@ -19,7 +19,18 @@ public void Register(IServiceCollection services, JpaConfig config, int number) config.Language ??= "java"; - services.AddGenerator(config, number); + services.AddGenerator(config, number); + if (config.UseJdbc) + { + services.AddGenerator(config, number); + } + else + { + services.AddGenerator(config, number); + services.AddGenerator(config, number); + services.AddGenerator(config, number); + } + services.AddGenerator(config, number); services.AddGenerator(config, number); services.AddGenerator(config, number); diff --git a/TopModel.Generator.Jpa/ImportsJpaExtensions.cs b/TopModel.Generator.Jpa/ImportsJpaExtensions.cs index 5b59ea11..7e5de28d 100644 --- a/TopModel.Generator.Jpa/ImportsJpaExtensions.cs +++ b/TopModel.Generator.Jpa/ImportsJpaExtensions.cs @@ -9,26 +9,6 @@ public static string GetImport(this Class classe, JpaConfig config, string tag) return $"{config.GetPackageName(classe, config.GetBestClassTag(classe, tag))}.{classe.NamePascal}"; } - public static List GetImports(this Class classe, JpaConfig config, string tag, IEnumerable availableClasses) - { - var imports = new List(); - - if (classe.Extends != null) - { - imports.Add(classe.GetImport(config, config.GetBestClassTag(classe, tag))); - } - - if (config.MappersInClass) - { - imports - .AddRange(classe.FromMappers.Where(fm => fm.ClassParams.All(fmp => availableClasses.Contains(fmp.Class))).SelectMany(fm => fm.ClassParams).Select(fmp => fmp.Class.GetImport(config, tag))); - imports - .AddRange(classe.ToMappers.Where(tm => availableClasses.Contains(tm.Class)).Select(fmp => fmp.Class.GetImport(config, config.GetBestClassTag(classe, tag)))); - } - - return imports; - } - public static List GetKindImports(this CompositionProperty cp, JpaConfig config, string tag) { return config.GetDomainImports(cp, config.GetBestClassTag(cp.Composition, tag)).ToList(); diff --git a/TopModel.Generator.Jpa/JavaAnnotation.cs b/TopModel.Generator.Jpa/JavaAnnotation.cs new file mode 100644 index 00000000..7cbf68dd --- /dev/null +++ b/TopModel.Generator.Jpa/JavaAnnotation.cs @@ -0,0 +1,73 @@ +namespace TopModel.Generator.Jpa; + +public class JavaAnnotation +{ + public JavaAnnotation(string name, string import) + { + Name = name.Trim('@'); + Imports = [import]; + } + + public JavaAnnotation(string name, IEnumerable imports) + { + Name = name.Trim('@'); + Imports.AddRange(imports); + } + + public JavaAnnotation(string name, string value, string import) + { + Name = name.Trim('@'); + Imports = [import]; + Attributes.Add(("value", value)); + } + + public string Name { get; set; } + + public List Imports { get; set; } = new(); + + private List<(string Name, object Value)> Attributes { get; } = new(); + + public JavaAnnotation AddAttribute(string name, string value, string import) + { + Attributes.Add((name, value)); + Imports.Add(import); + return this; + } + + public JavaAnnotation AddAttribute(string name, string value) + { + Attributes.Add((name, value)); + return this; + } + + public JavaAnnotation AddAttribute(string value) + { + Attributes.Add(("value", value)); + return this; + } + + public JavaAnnotation AddAttribute(string name, JavaAnnotation value) + { + Attributes.Add((name, value)); + Imports.AddRange(value.Imports); + return this; + } + + public override string ToString() + { + var name = Name.StartsWith('@') ? Name : $"@{Name}"; + if (!Attributes.Any()) + { + return name; + } + else if (Attributes.Count() == 1 && Attributes.Any(a => a.Name == "value")) + { + return $"{name}({Attributes.First().Value})"; + } + else + { + var attributes = string.Join(", ", Attributes.Select(a => $"{a.Name} = {a.Value}")); + return $"{name}({attributes})"; + } + } +} \ No newline at end of file diff --git a/TopModel.Generator.Jpa/JavaClassGeneratorBase.cs b/TopModel.Generator.Jpa/JavaClassGeneratorBase.cs new file mode 100644 index 00000000..fe941991 --- /dev/null +++ b/TopModel.Generator.Jpa/JavaClassGeneratorBase.cs @@ -0,0 +1,175 @@ +using Microsoft.Extensions.Logging; +using TopModel.Core; +using TopModel.Core.Model.Implementation; +using TopModel.Generator.Core; +using TopModel.Utils; + +namespace TopModel.Generator.Jpa; + +/// +/// Générateur de fichiers de modèles JPA. +/// +public abstract class JavaClassGeneratorBase : ClassGeneratorBase +{ + private JavaConstructorGenerator? _jpaModelConstructorGenerator; + private JpaModelPropertyGenerator? _jpaModelPropertyGenerator; + + public JavaClassGeneratorBase(ILogger logger) + : base(logger) + { + } + + protected static Dictionary NewableTypes => new() + { + ["List"] = "ArrayList", + ["Set"] = "HashSet" + }; + + protected string JavaxOrJakarta => Config.PersistenceMode.ToString().ToLower(); + + protected virtual JavaConstructorGenerator ConstructorGenerator + { + get + { + _jpaModelConstructorGenerator ??= new JavaConstructorGenerator(Config); + return _jpaModelConstructorGenerator; + } + } + + protected JpaModelPropertyGenerator JpaModelPropertyGenerator + { + get + { + _jpaModelPropertyGenerator ??= new JpaModelPropertyGenerator(Config, Classes, NewableTypes); + return _jpaModelPropertyGenerator; + } + } + + protected virtual void WriteAnnotations(JavaWriter fw, Class classe, string tag) + { + fw.WriteDocStart(0, classe.Comment); + fw.WriteDocEnd(0); + if (Config.GeneratedHint) + { + fw.AddImport($"{JavaxOrJakarta}.annotation.Generated"); + fw.WriteLine("@Generated(\"TopModel : https://github.com/klee-contrib/topmodel\")"); + } + + fw.AddImports(Config.GetDecoratorImports(classe, tag).ToList()); + foreach (var a in Config.GetDecoratorAnnotations(classe, tag)) + { + fw.WriteLine($"{(a.StartsWith("@") ? string.Empty : "@")}{a}"); + } + } + + protected void WriteFieldsEnum(JavaWriter fw, Class classe, string tag) + { + if (!classe.Properties.Any()) + { + return; + } + + if (Config.FieldsEnumInterface != null) + { + fw.AddImport(Config.FieldsEnumInterface.Replace("<>", string.Empty)); + } + + fw.WriteLine(); + fw.WriteDocStart(1, $"Enumération des champs de la classe {{@link {classe.GetImport(Config, tag)} {classe.NamePascal}}}"); + fw.WriteDocEnd(1); + string enumDeclaration = @$"public enum Fields "; + if (Config.FieldsEnumInterface != null) + { + enumDeclaration += $"implements {Config.FieldsEnumInterface.Split(".").Last().Replace("<>", $"<{classe.NamePascal}>")}"; + } + + enumDeclaration += " {"; + fw.WriteLine(1, enumDeclaration); + + var props = classe.GetProperties(Classes).Select(prop => + { + string name; + if (prop is AssociationProperty ap && ap.Association.IsPersistent && !Config.UseJdbc) + { + name = ap.NameByClassCamel.ToConstantCase(); + } + else + { + name = prop.NameCamel.ToConstantCase(); + } + + var javaType = Config.GetType(prop, useClassForAssociation: classe.IsPersistent && !Config.UseJdbc && prop is AssociationProperty asp && asp.Association.IsPersistent); + javaType = javaType.Split("<")[0]; + return $" {name}({javaType}.class)"; + }); + + fw.WriteLine(string.Join(", //\n", props) + ";"); + + fw.WriteLine(); + + fw.WriteLine(2, "private final Class type;"); + fw.WriteLine(); + fw.WriteLine(2, "Fields(Class type) {"); + fw.WriteLine(3, "this.type = type;"); + fw.WriteLine(2, "}"); + + fw.WriteLine(); + + fw.WriteLine(2, "public Class getType() {"); + fw.WriteLine(3, "return this.type;"); + fw.WriteLine(2, "}"); + + fw.WriteLine(1, "}"); + } + + protected virtual void WriteGetters(JavaWriter fw, Class classe, string tag) + { + foreach (var property in classe.GetProperties(Classes)) + { + JpaModelPropertyGenerator.WriteGetter(fw, tag, property); + } + } + + protected virtual void WriteSetters(JavaWriter fw, Class classe, string tag) + { + foreach (var property in classe.GetProperties(Classes)) + { + JpaModelPropertyGenerator.WriteSetter(fw, tag, property); + } + } + + protected void WriteToMappers(JavaWriter fw, Class classe, string tag) + { + var toMappers = classe.ToMappers.Where(p => Classes.Contains(p.Class)).Select(m => (classe, m)) + .OrderBy(m => m.m.Name) + .ToList(); + + foreach (var toMapper in toMappers) + { + var (clazz, mapper) = toMapper; + fw.AddImport(mapper.Class.GetImport(Config, tag)); + fw.WriteLine(); + fw.WriteDocStart(1, $"Mappe '{classe}' vers '{mapper.Class.NamePascal}'"); + if (mapper.Comment != null) + { + fw.WriteLine(1, $" * {mapper.Comment}"); + } + + fw.WriteParam("target", $"Instance pré-existante de '{mapper.Class.NamePascal}'. Une nouvelle instance sera créée si non spécifié."); + fw.WriteReturns(1, $"Une instance de '{mapper.Class.NamePascal}'"); + + fw.WriteDocEnd(1); + var (mapperNs, mapperModelPath) = Config.GetMapperLocation(toMapper); + + fw.WriteLine(1, $"public {mapper.Class.NamePascal} {mapper.Name.Value.ToCamelCase()}({mapper.Class.NamePascal} target) {{"); + fw.WriteLine(2, $"return {Config.GetMapperName(mapperNs, mapperModelPath)}.{mapper.Name.Value.ToCamelCase()}(this, target);"); + fw.AddImport(Config.GetMapperImport(mapperNs, mapperModelPath, tag)!); + fw.WriteLine(1, "}"); + + if (toMappers.IndexOf(toMapper) < toMappers.Count - 1) + { + fw.WriteLine(); + } + } + } +} \ No newline at end of file diff --git a/TopModel.Generator.Jpa/JavaConstructorGenerator.cs b/TopModel.Generator.Jpa/JavaConstructorGenerator.cs new file mode 100644 index 00000000..5b20458b --- /dev/null +++ b/TopModel.Generator.Jpa/JavaConstructorGenerator.cs @@ -0,0 +1,84 @@ +using TopModel.Core; +using TopModel.Generator.Core; + +namespace TopModel.Generator.Jpa; + +/// +/// Générateur de fichiers de modèles JPA. +/// +public class JavaConstructorGenerator +{ + + public JavaConstructorGenerator(JpaConfig config) + { + Config = config; + } + + protected JpaConfig Config { get; set; } + + public void WriteFromMappers(JavaWriter fw, Class classe, IEnumerable availableClasses, string tag) + { + var fromMappers = classe.FromMappers.Where(c => c.ClassParams.All(p => availableClasses.Contains(p.Class))).Select(m => (classe, m)) + .OrderBy(m => m.classe.NamePascal) + .ToList(); + + foreach (var fromMapper in fromMappers) + { + var (clazz, mapper) = fromMapper; + fw.AddImport(clazz.GetImport(Config, tag)); + fw.WriteLine(); + fw.WriteDocStart(1, $"Crée une nouvelle instance de '{classe.NamePascal}'"); + if (mapper.Comment != null) + { + fw.WriteLine(1, $" * {mapper.Comment}"); + } + + foreach (var param in mapper.ClassParams) + { + if (param.Comment != null) + { + fw.WriteLine(1, $" * {param.Comment}"); + } + + fw.AddImport(param.Class.GetImport(Config, tag)); + fw.WriteParam(param.Name.ToCamelCase(), $"Instance de '{param.Class.NamePascal}'"); + } + + foreach (var param in mapper.PropertyParams) + { + fw.WriteParam(param.Property.NameCamel, param.Property.Comment); + } + + fw.WriteReturns(1, $"Une nouvelle instance de '{classe.NamePascal}'"); + fw.WriteDocEnd(1); + var entryParams = mapper.ClassParams.Select(p => $"{p.Class} {p.Name.ToCamelCase()}").Concat(mapper.PropertyParams.Select(p => $"{Config.GetType(p.Property, availableClasses)} {p.Property.NameCamel}")); + var entryParamImports = mapper.PropertyParams.Select(p => p.Property.GetTypeImports(Config, tag)).SelectMany(p => p); + fw.AddImports(entryParamImports.ToList()); + fw.WriteLine(1, $"public {classe.NamePascal}({string.Join(", ", entryParams)}) {{"); + if (classe.Extends != null) + { + fw.WriteLine(2, $"super();"); + } + + var (mapperNs, mapperModelPath) = Config.GetMapperLocation(fromMapper); + fw.WriteLine(2, $"{Config.GetMapperName(mapperNs, mapperModelPath)}.create{classe.NamePascal}({string.Join(", ", mapper.ClassParams.Select(p => p.Name.ToCamelCase()).Concat(mapper.PropertyParams.Select(p => p.Property.NameCamel)))}, this);"); + fw.AddImport(Config.GetMapperImport(mapperNs, mapperModelPath, tag)!); + fw.WriteLine(1, "}"); + } + } + + public void WriteNoArgConstructor(JavaWriter fw, Class classe) + { + fw.WriteLine(); + fw.WriteDocStart(1, "No arg constructor"); + fw.WriteDocEnd(1); + fw.WriteLine(1, $"public {classe.NamePascal}() {{"); + if (classe.Extends != null || classe.Decorators.Any(d => Config.GetImplementation(d.Decorator)?.Extends is not null)) + { + fw.WriteLine(2, $"super();"); + } + + fw.WriteLine(2, "// No arg constructor"); + fw.WriteLine(1, $"}}"); + } +} diff --git a/TopModel.Generator.Jpa/JavaDtoGenerator.cs b/TopModel.Generator.Jpa/JavaDtoGenerator.cs new file mode 100644 index 00000000..35309041 --- /dev/null +++ b/TopModel.Generator.Jpa/JavaDtoGenerator.cs @@ -0,0 +1,102 @@ +using Microsoft.Extensions.Logging; +using TopModel.Core; +using TopModel.Core.Model.Implementation; +using TopModel.Generator.Core; +using TopModel.Utils; + +namespace TopModel.Generator.Jpa; + +/// +/// Générateur de fichiers de modèles JPA. +/// +public class JavaDtoGenerator : JavaClassGeneratorBase +{ + private readonly ILogger _logger; + + public JavaDtoGenerator(ILogger logger) + : base(logger) + { + _logger = logger; + } + + public override string Name => "JavaDtoGen"; + + private List AvailableClasses => Classes.ToList(); + + protected override bool FilterClass(Class classe) + { + return !classe.Abstract && !classe.IsPersistent && !Config.CanClassUseEnums(classe, Classes); + } + + protected override string GetFileName(Class classe, string tag) + { + return Path.Combine( + Config.OutputDirectory, + Config.ResolveVariables(Config.DtosPath, tag, module: classe.Namespace.Module).ToFilePath(), + $"{classe.NamePascal}.java"); + } + + protected virtual void WriteConstuctors(JavaWriter fw, Class classe, string tag) + { + if (Config.MappersInClass && classe.FromMappers.Any(c => c.ClassParams.All(p => Classes.Contains(p.Class))) + || classe.Extends != null + || Classes.Any(c => c.Extends == classe) + || classe.Decorators.Any(d => Config.GetImplementation(d.Decorator)?.Extends is not null)) + { + ConstructorGenerator.WriteNoArgConstructor(fw, classe); + } + + if (Config.MappersInClass) + { + ConstructorGenerator.WriteFromMappers(fw, classe, AvailableClasses, tag); + } + } + + protected virtual void WriteStaticMembers(JavaWriter fw, Class classe) + { + fw.WriteLine(" /** Serial ID */"); + fw.WriteLine(1, "private static final long serialVersionUID = 1L;"); + } + + protected override void HandleClass(string fileName, Class classe, string tag) + { + var packageName = Config.GetPackageName(classe, tag); + using var fw = new JavaWriter(fileName, _logger, packageName, null); + + fw.WriteLine(); + + WriteAnnotations(fw, classe, tag); + + var extends = Config.GetClassExtends(classe); + if (classe.Extends is not null) + { + fw.AddImport($"{Config.GetPackageName(classe.Extends, tag)}.{classe.Extends.NamePascal}"); + fw.AddImport(classe.Extends.GetImport(Config, Config.GetBestClassTag(classe.Extends, tag))); + } + + var implements = Config.GetClassImplements(classe).ToList(); + + implements.Add("Serializable"); + fw.AddImport("java.io.Serializable"); + + fw.WriteClassDeclaration(classe.NamePascal, null, extends, implements); + + WriteStaticMembers(fw, classe); + JpaModelPropertyGenerator.WriteProperties(fw, classe, tag); + WriteConstuctors(fw, classe, tag); + + WriteGetters(fw, classe, tag); + WriteSetters(fw, classe, tag); + if (Config.MappersInClass) + { + WriteToMappers(fw, classe, tag); + } + + if ((Config.FieldsEnum & Target.Dto) > 0) + { + WriteFieldsEnum(fw, classe, tag); + } + + fw.WriteLine("}"); + } +} \ No newline at end of file diff --git a/TopModel.Generator.Jpa/JavaEnumConstructorGenerator.cs b/TopModel.Generator.Jpa/JavaEnumConstructorGenerator.cs new file mode 100644 index 00000000..ced691c5 --- /dev/null +++ b/TopModel.Generator.Jpa/JavaEnumConstructorGenerator.cs @@ -0,0 +1,73 @@ +using TopModel.Core; +using TopModel.Generator.Core; + +namespace TopModel.Generator.Jpa; + +/// +/// Générateur de fichiers de modèles JPA. +/// +public class JavaEnumConstructorGenerator : JavaConstructorGenerator +{ + public JavaEnumConstructorGenerator(JpaConfig config) + : base(config) + { + } + + public void WriteEnumConstructor(JavaWriter fw, Class classe, IEnumerable availableClasses, 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}) {{"); + 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; + } + + var quote = isString ? "\"" : string.Empty; + var val = quote + value + quote; + fw.WriteLine(3, $@"this.{prop.NameByClassCamel} = {val};"); + } + + fw.WriteLine(3, $@"break;"); + } + + fw.WriteLine(2, $@"}}"); + } + + fw.WriteLine(1, $"}}"); + } +} diff --git a/TopModel.Generator.Jpa/JavaEnumDtoGenerator.cs b/TopModel.Generator.Jpa/JavaEnumDtoGenerator.cs new file mode 100644 index 00000000..0bb513a7 --- /dev/null +++ b/TopModel.Generator.Jpa/JavaEnumDtoGenerator.cs @@ -0,0 +1,58 @@ +using Microsoft.Extensions.Logging; +using TopModel.Core; +using TopModel.Core.Model.Implementation; + +namespace TopModel.Generator.Jpa; + +/// +/// Générateur de fichiers de modèles JPA. +/// +public class JavaEnumDtoGenerator : JavaDtoGenerator +{ + + private JavaEnumConstructorGenerator? _jpaModelConstructorGenerator; + + public JavaEnumDtoGenerator(ILogger logger) + : base(logger) + { + } + + public override string Name => "JpaEnumDtoGen"; + + protected override JavaEnumConstructorGenerator ConstructorGenerator + { + get + { + _jpaModelConstructorGenerator ??= new JavaEnumConstructorGenerator(Config); + return _jpaModelConstructorGenerator; + } + } + + protected override bool FilterClass(Class classe) + { + return !classe.Abstract && Config.CanClassUseEnums(classe, Classes) && !classe.IsPersistent; + } + + protected override void WriteConstuctors(JavaWriter fw, Class classe, string tag) + { + ConstructorGenerator.WriteNoArgConstructor(fw, classe); + ConstructorGenerator.WriteEnumConstructor(fw, classe, Classes, tag); + } + + protected override void WriteStaticMembers(JavaWriter fw, Class classe) + { + base.WriteStaticMembers(fw, classe); + 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});"); + } + } + + protected override void WriteSetters(JavaWriter fw, Class classe, string tag) + { + return; + } +} \ No newline at end of file diff --git a/TopModel.Generator.Jpa/JavaWriter.cs b/TopModel.Generator.Jpa/JavaWriter.cs index c940c5ee..494c09c3 100644 --- a/TopModel.Generator.Jpa/JavaWriter.cs +++ b/TopModel.Generator.Jpa/JavaWriter.cs @@ -126,6 +126,30 @@ public void WriteDocStart(int indentationLevel, string value) } } + /// + /// Ecrit l'annotation avec le niveau indenté. + /// + /// Niveau d'indentation. + /// Valeur à écrire dans le flux. + public void WriteAnnotation(int indentationLevel, JavaAnnotation javaAnnotation) + { + AddImports(javaAnnotation.Imports); + _toWrite.Add(new WriterLine() { Line = javaAnnotation.ToString(), Indent = indentationLevel }); + } + + /// + /// Ecrit l'annotation avec le niveau indenté. + /// + /// Niveau d'indentation. + /// Valeurs à écrire dans le flux. + public void WriteAnnotations(int indentationLevel, IEnumerable javaAnnotations) + { + foreach (var annotation in javaAnnotations.DistinctBy(e => e.Name.Split('(').First())) + { + WriteAnnotation(indentationLevel, annotation); + } + } + /// /// Ecrit la chaine de caractère dans le flux. /// diff --git a/TopModel.Generator.Jpa/JdbcEntityGenerator.cs b/TopModel.Generator.Jpa/JdbcEntityGenerator.cs new file mode 100644 index 00000000..94206b33 --- /dev/null +++ b/TopModel.Generator.Jpa/JdbcEntityGenerator.cs @@ -0,0 +1,161 @@ +using Microsoft.Extensions.Logging; +using TopModel.Core; +using TopModel.Core.Model.Implementation; +using TopModel.Generator.Core; +using TopModel.Utils; + +namespace TopModel.Generator.Jpa; + +/// +/// Générateur de fichiers de modèles JPA. +/// +public class JdbcEntityGenerator : JavaClassGeneratorBase +{ + private readonly ILogger _logger; + + private JavaEnumConstructorGenerator? _javaEnumConstructorGenerator; + + public JdbcEntityGenerator(ILogger logger) + : base(logger) + { + _logger = logger; + } + + public override string Name => "JdbcEntityGen"; + + protected override JavaEnumConstructorGenerator ConstructorGenerator + { + get + { + _javaEnumConstructorGenerator ??= new JavaEnumConstructorGenerator(Config); + return _javaEnumConstructorGenerator; + } + } + + protected override bool FilterClass(Class classe) + { + return !classe.Abstract && classe.IsPersistent; + } + + protected override string GetFileName(Class classe, string tag) + { + return Config.GetClassFileName(classe, tag); + } + + protected override void HandleClass(string fileName, Class classe, string tag) + { + var packageName = Config.GetPackageName(classe, tag); + using var fw = new JavaWriter(fileName, _logger, packageName, null); + + fw.WriteLine(); + + WriteAnnotations(fw, classe, tag); + + var extends = Config.GetClassExtends(classe); + if (classe.Extends is not null) + { + fw.AddImport($"{Config.GetPackageName(classe.Extends, tag)}.{classe.Extends.NamePascal}"); + } + + var implements = Config.GetClassImplements(classe).ToList(); + + if (!classe.IsPersistent) + { + implements.Add("Serializable"); + fw.AddImport("java.io.Serializable"); + } + + fw.WriteClassDeclaration(classe.NamePascal, null, extends, implements); + + if (!classe.IsPersistent) + { + fw.WriteLine(" /** Serial ID */"); + fw.WriteLine(1, "private static final long serialVersionUID = 1L;"); + } + + if (Config.CanClassUseEnums(classe, Classes)) + { + fw.WriteLine(); + 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});"); + } + } + + JpaModelPropertyGenerator.WriteProperties(fw, classe, tag); + + if (Config.CanClassUseEnums(classe, Classes) + || Config.MappersInClass && classe.FromMappers.Any(c => c.ClassParams.All(p => Classes.Contains(p.Class))) + || classe.Extends != null + || Classes.Any(c => c.Extends == classe) + || classe.Decorators.Any(d => Config.GetImplementation(d.Decorator)?.Extends is not null)) + { + ConstructorGenerator.WriteNoArgConstructor(fw, classe); + } + + if (Config.MappersInClass) + { + ConstructorGenerator.WriteFromMappers(fw, classe, Classes, tag); + } + + if (Config.CanClassUseEnums(classe, Classes)) + { + ConstructorGenerator.WriteEnumConstructor(fw, classe, Classes, tag); + } + + WriteGetters(fw, classe, tag); + WriteSetters(fw, classe, tag); + + if (Config.MappersInClass) + { + WriteToMappers(fw, classe, tag); + } + + if ((Config.FieldsEnum & Target.Persisted) > 0 && classe.IsPersistent + || (Config.FieldsEnum & Target.Dto) > 0 && !classe.IsPersistent) + { + WriteFieldsEnum(fw, classe, tag); + } + + fw.WriteLine("}"); + } + + protected override void WriteGetters(JavaWriter fw, Class classe, string tag) + { + var properties = Config.UseJdbc ? classe.Properties.Where(p => !(p is AssociationProperty ap && (ap.Type == AssociationType.OneToMany || ap.Type == AssociationType.ManyToMany))) : classe.GetProperties(Classes); + foreach (var property in properties) + { + JpaModelPropertyGenerator!.WriteGetter(fw, tag, property); + } + } + + protected override void WriteSetters(JavaWriter fw, Class classe, string tag) + { + var properties = Config.UseJdbc ? classe.Properties.Where(p => !(p is AssociationProperty ap && (ap.Type == AssociationType.OneToMany || ap.Type == AssociationType.ManyToMany))) : classe.GetProperties(Classes); + if (Config.CanClassUseEnums(classe, Classes)) + { + return; + } + + foreach (var property in properties) + { + JpaModelPropertyGenerator!.WriteSetter(fw, tag, property); + } + } + + protected override void WriteAnnotations(JavaWriter fw, Class classe, string tag) + { + base.WriteAnnotations(fw, classe, tag); + var table = @$"@Table(name = ""{classe.SqlName.ToLower()}"")"; + fw.AddImport($"org.springframework.data.relational.core.mapping.Table"); + fw.WriteLine(table); + } +} \ No newline at end of file diff --git a/TopModel.Generator.Jpa/JpaConfig.cs b/TopModel.Generator.Jpa/JpaConfig.cs index cda9e144..25b5e5cf 100644 --- a/TopModel.Generator.Jpa/JpaConfig.cs +++ b/TopModel.Generator.Jpa/JpaConfig.cs @@ -54,11 +54,6 @@ public class JpaConfig : GeneratorConfigBase /// public ResourcesEncoding? ResourcesEncoding { get; set; } = Jpa.ResourcesEncoding.Latin1; - /// - /// Option pour générer des getters et setters vers l'enum des références plutôt que sur la table - /// - public bool EnumShortcutMode { get; set; } - /// /// Nom du schéma sur lequel les entités sont sauvegardées /// diff --git a/TopModel.Generator.Jpa/JpaEntityGenerator.cs b/TopModel.Generator.Jpa/JpaEntityGenerator.cs new file mode 100644 index 00000000..c58ff9ea --- /dev/null +++ b/TopModel.Generator.Jpa/JpaEntityGenerator.cs @@ -0,0 +1,231 @@ +using Microsoft.Extensions.Logging; +using TopModel.Core; +using TopModel.Core.Model.Implementation; +using TopModel.Generator.Core; +using TopModel.Utils; + +namespace TopModel.Generator.Jpa; + +/// +/// Générateur de fichiers de modèles JPA. +/// +public class JpaEntityGenerator : JavaClassGeneratorBase +{ + private readonly ILogger _logger; + + public JpaEntityGenerator(ILogger logger) + : base(logger) + { + _logger = logger; + } + + public override string Name => "JpaEntityGen"; + + protected override bool FilterClass(Class classe) + { + return !classe.Abstract && classe.IsPersistent && !Config.CanClassUseEnums(classe, Classes); + } + + protected override string GetFileName(Class classe, string tag) + { + return Path.Combine( + Config.OutputDirectory, + Config.ResolveVariables(Config.EntitiesPath, tag, module: classe.Namespace.Module).ToFilePath(), + $"{classe.NamePascal}.java"); + } + + protected override void HandleClass(string fileName, Class classe, string tag) + { + var packageName = Config.GetPackageName(classe, tag); + using var fw = new JavaWriter(fileName, _logger, packageName, null); + + fw.WriteLine(); + + WriteAnnotations(fw, classe, tag); + + var extends = Config.GetClassExtends(classe); + if (classe.Extends is not null) + { + fw.AddImport($"{Config.GetPackageName(classe.Extends, tag)}.{classe.Extends.NamePascal}"); + } + + var implements = Config.GetClassImplements(classe).ToList(); + + fw.WriteClassDeclaration(classe.NamePascal, null, extends, implements); + + JpaModelPropertyGenerator.WriteProperties(fw, classe, tag); + JpaModelPropertyGenerator.WriteCompositePrimaryKeyClass(fw, classe, tag); + + WriteConstructors(classe, tag, fw); + + WriteGetters(fw, classe, tag); + WriteSetters(fw, classe, tag); + WriteAdders(fw, classe, tag); + WriteRemovers(fw, classe, tag); + + if (Config.MappersInClass) + { + WriteToMappers(fw, classe, tag); + } + + if ((Config.FieldsEnum & Target.Persisted) > 0) + { + WriteFieldsEnum(fw, classe, tag); + } + + fw.WriteLine("}"); + } + + protected virtual void WriteConstructors(Class classe, string tag, JavaWriter fw) + { + if (Config.MappersInClass && classe.FromMappers.Any(c => c.ClassParams.All(p => Classes.Contains(p.Class))) + || classe.Extends != null + || Classes.Any(c => c.Extends == classe) + || classe.Decorators.Any(d => Config.GetImplementation(d.Decorator)?.Extends is not null)) + { + ConstructorGenerator.WriteNoArgConstructor(fw, classe); + } + + if (Config.MappersInClass) + { + ConstructorGenerator.WriteFromMappers(fw, classe, Classes, tag); + } + } + + protected override void WriteAnnotations(JavaWriter fw, Class classe, string tag) + { + base.WriteAnnotations(fw, classe, tag); + if (Classes.Any(c => c.Extends == classe)) + { + fw.WriteLine("@Inheritance(strategy = InheritanceType.JOINED)"); + fw.AddImport($"{JavaxOrJakarta}.persistence.Inheritance"); + fw.AddImport($"{JavaxOrJakarta}.persistence.InheritanceType"); + } + + var table = @$"@Table(name = ""{classe.SqlName}"""; + fw.AddImport($"{JavaxOrJakarta}.persistence.Table"); + if (classe.UniqueKeys.Any()) + { + fw.AddImport($"{JavaxOrJakarta}.persistence.UniqueConstraint"); + table += ", uniqueConstraints = {"; + var isFirstConstraint = true; + foreach (var unique in classe.UniqueKeys) + { + if (!isFirstConstraint) + { + table += ","; + } + + table += "\n "; + isFirstConstraint = false; + table += "@UniqueConstraint(columnNames = {"; + var isFirstColumn = true; + foreach (var u in unique) + { + if (!isFirstColumn) + { + table += ","; + } + + isFirstColumn = false; + table += $"\"{u.SqlName}\""; + } + + table += "})"; + } + + table += "}"; + } + + table += ")"; + fw.AddImport($"{JavaxOrJakarta}.persistence.Entity"); + fw.WriteLine("@Entity"); + fw.WriteLine(table); + if (classe.PrimaryKey.Count() > 1) + { + fw.WriteLine($"@IdClass({classe.NamePascal}.{classe.NamePascal}Id.class)"); + fw.AddImport($"{JavaxOrJakarta}.persistence.IdClass"); + } + + if (classe.Reference) + { + fw.AddImports(new List() + { + "org.hibernate.annotations.Cache", + "org.hibernate.annotations.CacheConcurrencyStrategy" + }); + if (Config.CanClassUseEnums(classe)) + { + fw.AddImport("org.hibernate.annotations.Immutable"); + fw.WriteLine("@Immutable"); + fw.WriteLine("@Cache(usage = CacheConcurrencyStrategy.READ_ONLY)"); + } + else + { + fw.WriteLine("@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)"); + } + } + } + + private void WriteAdders(JavaWriter fw, Class classe, string tag) + { + if (classe.IsPersistent && Config.AssociationAdders) + { + foreach (var ap in classe.GetProperties(Classes).OfType().Where(t => t.Type.IsToMany())) + { + var reverse = ap is ReverseAssociationProperty rap ? rap.ReverseProperty : ap.Association.GetProperties(Classes).OfType().FirstOrDefault(r => r.ReverseProperty == ap); + if (reverse != null) + { + var propertyName = ap.NameByClassCamel; + fw.WriteLine(); + fw.WriteDocStart(1, $"Add a value to {{@link {classe.GetImport(Config, tag)}#{propertyName} {propertyName}}}"); + fw.WriteLine(1, $" * @param {ap.Association.NameCamel} value to add"); + fw.WriteDocEnd(1); + fw.WriteLine(1, @$"public void add{ap.Association.NamePascal}{ap.Role}({ap.Association.NamePascal} {ap.Association.NameCamel}) {{"); + fw.WriteLine(2, @$"this.{propertyName}.add({ap.Association.NameCamel});"); + if (reverse.Type.IsToMany()) + { + fw.WriteLine(2, @$"{ap.Association.NameCamel}.get{reverse.NameByClassPascal}().add(this);"); + } + else + { + fw.WriteLine(2, @$"{ap.Association.NameCamel}.set{reverse.NameByClassPascal}(this);"); + } + + fw.WriteLine(1, "}"); + } + } + } + } + + private void WriteRemovers(JavaWriter fw, Class classe, string tag) + { + if (classe.IsPersistent && Config.AssociationRemovers) + { + foreach (var ap in classe.GetProperties(Classes).OfType().Where(t => t.Type.IsToMany())) + { + var reverse = ap is ReverseAssociationProperty rap ? rap.ReverseProperty : ap.Association.GetProperties(Classes).OfType().FirstOrDefault(r => r.ReverseProperty == ap); + if (reverse != null) + { + var propertyName = ap.NameByClassCamel; + fw.WriteLine(); + fw.WriteDocStart(1, $"Remove a value from {{@link {classe.GetImport(Config, tag)}#{propertyName} {propertyName}}}"); + fw.WriteLine(1, $" * @param {ap.Association.NameCamel} value to remove"); + fw.WriteDocEnd(1); + fw.WriteLine(1, @$"public void remove{ap.Association.NamePascal}{ap.Role}({ap.Association.NamePascal} {ap.Association.NameCamel}) {{"); + fw.WriteLine(2, @$"this.{propertyName}.remove({ap.Association.NameCamel});"); + if (reverse.Type.IsToMany()) + { + fw.WriteLine(2, @$"{ap.Association.NameCamel}.get{reverse.NameByClassPascal}().remove(this);"); + } + else + { + fw.WriteLine(2, @$"{ap.Association.NameCamel}.set{reverse.NameByClassPascal}(null);"); + } + + fw.WriteLine(1, "}"); + } + } + } + } +} \ No newline at end of file diff --git a/TopModel.Generator.Jpa/JpaEnumEntityGenerator.cs b/TopModel.Generator.Jpa/JpaEnumEntityGenerator.cs new file mode 100644 index 00000000..03fd7127 --- /dev/null +++ b/TopModel.Generator.Jpa/JpaEnumEntityGenerator.cs @@ -0,0 +1,98 @@ +using Microsoft.Extensions.Logging; +using TopModel.Core; +using TopModel.Core.Model.Implementation; + +namespace TopModel.Generator.Jpa; + +/// +/// Générateur de fichiers de modèles JPA. +/// +public class JpaEnumEntityGenerator : JpaEntityGenerator +{ + private readonly ILogger _logger; + + private JavaEnumConstructorGenerator? _javaEnumConstructorGenerator; + + public JpaEnumEntityGenerator(ILogger logger) + : base(logger) + { + _logger = logger; + } + + public override string Name => "JpaEnumEntityGen"; + + protected override JavaEnumConstructorGenerator ConstructorGenerator + { + get + { + _javaEnumConstructorGenerator ??= new JavaEnumConstructorGenerator(Config); + return _javaEnumConstructorGenerator; + } + } + + protected override bool FilterClass(Class classe) + { + return !classe.Abstract && Config.CanClassUseEnums(classe, Classes) && classe.IsPersistent; + } + + protected override void HandleClass(string fileName, Class classe, string tag) + { + var packageName = Config.GetPackageName(classe, tag); + using var fw = new JavaWriter(fileName, _logger, packageName, null); + + fw.WriteLine(); + WriteAnnotations(fw, classe, tag); + + var extends = Config.GetClassExtends(classe); + if (classe.Extends is not null) + { + fw.AddImport($"{Config.GetPackageName(classe.Extends, tag)}.{classe.Extends.NamePascal}"); + } + + var implements = Config.GetClassImplements(classe).ToList(); + + fw.WriteClassDeclaration(classe.NamePascal, null, extends, implements); + fw.WriteLine(); + + 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});"); + } + + JpaModelPropertyGenerator.WriteProperties(fw, classe, tag); + WriteConstructors(classe, tag, fw); + + WriteGetters(fw, classe, tag); + + if (Config.MappersInClass) + { + WriteToMappers(fw, classe, tag); + } + + if ((Config.FieldsEnum & Target.Persisted) > 0) + { + WriteFieldsEnum(fw, classe, tag); + } + + fw.WriteLine("}"); + } + + protected override void WriteConstructors(Class classe, string tag, JavaWriter fw) + { + ConstructorGenerator.WriteNoArgConstructor(fw, classe); + ConstructorGenerator.WriteEnumConstructor(fw, classe, Classes, tag); + } + + protected override void WriteSetters(JavaWriter fw, Class classe, string tag) + { + return; + } +} \ No newline at end of file diff --git a/TopModel.Generator.Jpa/JpaMapperGenerator.cs b/TopModel.Generator.Jpa/JpaMapperGenerator.cs index 93d6b189..f2738e0a 100644 --- a/TopModel.Generator.Jpa/JpaMapperGenerator.cs +++ b/TopModel.Generator.Jpa/JpaMapperGenerator.cs @@ -36,11 +36,11 @@ protected override void HandleFile(string fileName, string tag, IList<(Class Cla ? Config.GetMapperLocation(sampleFromMapper) : Config.GetMapperLocation(sampleToMapper); - var package = Config.GetPackageName(mapperNs, modelPath, GetBestClassTag(fromMappers.FirstOrDefault().Classe, tag)); + var package = Config.GetPackageName(mapperNs, modelPath, GetBestClassTag(sampleFromMapper.Classe != null ? sampleFromMapper.Classe : sampleToMapper.Classe, tag)); using var fw = new JavaWriter(fileName, _logger, package, null); - var imports = fromMappers.SelectMany(m => m.Mapper.ClassParams.Select(p => p.Class).Concat(new[] { m.Classe })) + var imports = fromMappers.SelectMany(m => m.Mapper.ClassParams.Select(p => p.Class).Concat([m.Classe])) .Concat(toMappers.SelectMany(m => new[] { m.Classe, m.Mapper.Class })) .Where(c => Classes.Contains(c)) .Select(c => c.GetImport(Config, c.Tags.Contains(tag) ? tag : c.Tags.Intersect(Config.Tags).First())) @@ -53,10 +53,10 @@ protected override void HandleFile(string fileName, string tag, IList<(Class Cla fw.WriteLine(); } - var javaOrJakarta = Config.PersistenceMode.ToString().ToLower(); + var javaxOrJakarta = Config.PersistenceMode.ToString().ToLower(); if (Config.GeneratedHint) { - fw.AddImport($"{javaOrJakarta}.annotation.Generated"); + fw.AddImport($"{javaxOrJakarta}.annotation.Generated"); fw.WriteLine("@Generated(\"TopModel : https://github.com/klee-contrib/topmodel\")"); } diff --git a/TopModel.Generator.Jpa/JpaModelConstructorGenerator.cs b/TopModel.Generator.Jpa/JpaModelConstructorGenerator.cs deleted file mode 100644 index 4a545d78..00000000 --- a/TopModel.Generator.Jpa/JpaModelConstructorGenerator.cs +++ /dev/null @@ -1,139 +0,0 @@ -using TopModel.Core; -using TopModel.Generator.Core; - -namespace TopModel.Generator.Jpa; - -/// -/// Générateur de fichiers de modèles JPA. -/// -public class JpaModelConstructorGenerator -{ - private readonly JpaConfig _config; - - public JpaModelConstructorGenerator(JpaConfig config) - { - _config = config; - } - - public void WriteEnumConstructor(JavaWriter fw, Class classe, List availableClasses, string tag, ModelConfig modelConfig) - { - 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}) {{"); - 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; - } - - var quote = isString ? "\"" : string.Empty; - var val = quote + value + quote; - fw.WriteLine(3, $@"this.{prop.NameByClassCamel} = {val};"); - } - - fw.WriteLine(3, $@"break;"); - } - - fw.WriteLine(2, $@"}}"); - } - - fw.WriteLine(1, $"}}"); - } - - public void WriteFromMappers(JavaWriter fw, Class classe, List availableClasses, string tag) - { - var fromMappers = classe.FromMappers.Where(c => c.ClassParams.All(p => availableClasses.Contains(p.Class))).Select(m => (classe, m)) - .OrderBy(m => m.classe.NamePascal) - .ToList(); - - foreach (var fromMapper in fromMappers) - { - var (clazz, mapper) = fromMapper; - fw.WriteLine(); - fw.WriteDocStart(1, $"Crée une nouvelle instance de '{classe.NamePascal}'"); - if (mapper.Comment != null) - { - fw.WriteLine(1, $" * {mapper.Comment}"); - } - - foreach (var param in mapper.ClassParams) - { - if (param.Comment != null) - { - fw.WriteLine(1, $" * {param.Comment}"); - } - - fw.WriteParam(param.Name.ToCamelCase(), $"Instance de '{param.Class.NamePascal}'"); - } - - foreach (var param in mapper.PropertyParams) - { - fw.WriteParam(param.Property.NameCamel, param.Property.Comment); - } - - fw.WriteReturns(1, $"Une nouvelle instance de '{classe.NamePascal}'"); - fw.WriteDocEnd(1); - var entryParams = mapper.ClassParams.Select(p => $"{p.Class} {p.Name.ToCamelCase()}").Concat(mapper.PropertyParams.Select(p => $"{_config.GetType(p.Property, availableClasses)} {p.Property.NameCamel}")); - var entryParamImports = mapper.PropertyParams.Select(p => p.Property.GetTypeImports(_config, tag)).SelectMany(p => p); - fw.AddImports(entryParamImports.ToList()); - fw.WriteLine(1, $"public {classe.NamePascal}({string.Join(", ", entryParams)}) {{"); - if (classe.Extends != null) - { - fw.WriteLine(2, $"super();"); - } - - var (mapperNs, mapperModelPath) = _config.GetMapperLocation(fromMapper); - fw.WriteLine(2, $"{_config.GetMapperName(mapperNs, mapperModelPath)}.create{classe.NamePascal}({string.Join(", ", mapper.ClassParams.Select(p => p.Name.ToCamelCase()).Concat(mapper.PropertyParams.Select(p => p.Property.NameCamel)))}, this);"); - fw.AddImport(_config.GetMapperImport(mapperNs, mapperModelPath, tag)!); - fw.WriteLine(1, "}"); - } - } - - public void WriteNoArgConstructor(JavaWriter fw, Class classe) - { - fw.WriteLine(); - fw.WriteDocStart(1, "No arg constructor"); - fw.WriteDocEnd(1); - fw.WriteLine(1, $"public {classe.NamePascal}() {{"); - if (classe.Extends != null || classe.Decorators.Any(d => _config.GetImplementation(d.Decorator)?.Extends is not null)) - { - fw.WriteLine(2, $"super();"); - } - - fw.WriteLine(2, "// No arg constructor"); - fw.WriteLine(1, $"}}"); - } -} diff --git a/TopModel.Generator.Jpa/JpaModelGenerator.cs b/TopModel.Generator.Jpa/JpaModelGenerator.cs deleted file mode 100644 index be5006d1..00000000 --- a/TopModel.Generator.Jpa/JpaModelGenerator.cs +++ /dev/null @@ -1,525 +0,0 @@ -using Microsoft.Extensions.Logging; -using TopModel.Core; -using TopModel.Core.Model.Implementation; -using TopModel.Generator.Core; -using TopModel.Utils; - -namespace TopModel.Generator.Jpa; - -/// -/// Générateur de fichiers de modèles JPA. -/// -public class JpaModelGenerator : ClassGeneratorBase -{ - private readonly ILogger _logger; - private readonly ModelConfig _modelConfig; - - private readonly Dictionary _newableTypes = new() - { - ["List"] = "ArrayList", - ["Set"] = "HashSet" - }; - - private JpaModelConstructorGenerator? _jpaModelConstructorGenerator; - private JpaModelPropertyGenerator? _jpaModelPropertyGenerator; - - public JpaModelGenerator(ILogger logger, ModelConfig modelConfig) - : base(logger) - { - _logger = logger; - _modelConfig = modelConfig; - } - - public override string Name => "JpaModelGen"; - - private List AvailableClasses => Classes.ToList(); - - private JpaModelConstructorGenerator JpaModelConstructorGenerator - { - get - { - _jpaModelConstructorGenerator ??= new JpaModelConstructorGenerator(Config); - return _jpaModelConstructorGenerator; - } - } - - private JpaModelPropertyGenerator JpaModelPropertyGenerator - { - get - { - _jpaModelPropertyGenerator ??= new JpaModelPropertyGenerator(Config, Classes, _newableTypes); - return _jpaModelPropertyGenerator; - } - } - - protected override bool FilterClass(Class classe) - { - return !classe.Abstract; - } - - protected override string GetFileName(Class classe, string tag) - { - return Config.GetClassFileName(classe, tag); - } - - protected override void HandleClass(string fileName, Class classe, string tag) - { - var packageName = Config.GetPackageName(classe, tag); - using var fw = new JavaWriter(fileName, _logger, packageName, null); - - WriteImports(fw, classe, tag); - fw.WriteLine(); - - WriteAnnotations(fw, classe, tag); - - var extends = Config.GetClassExtends(classe); - if (classe.Extends is not null) - { - fw.AddImport($"{Config.GetPackageName(classe.Extends, tag)}.{classe.Extends.NamePascal}"); - } - - var implements = Config.GetClassImplements(classe).ToList(); - - if (!classe.IsPersistent) - { - implements.Add("Serializable"); - fw.AddImport("java.io.Serializable"); - } - - fw.WriteClassDeclaration(classe.NamePascal, null, extends, implements); - - if (!classe.IsPersistent) - { - fw.WriteLine(" /** Serial ID */"); - fw.WriteLine(1, "private static final long serialVersionUID = 1L;"); - } - - if (Config.CanClassUseEnums(classe, Classes)) - { - fw.WriteLine(); - var codeProperty = classe.EnumKey!; - var javaOrJakarta = Config.PersistenceMode.ToString().ToLower(); - foreach (var refValue in classe.Values.OrderBy(x => x.Name, StringComparer.Ordinal)) - { - var code = refValue.Value[codeProperty]; - if (classe.IsPersistent) - { - fw.AddImport($"{javaOrJakarta}.persistence.Transient"); - fw.WriteLine(1, "@Transient"); - } - - fw.WriteLine(1, $@"public static final {classe.NamePascal} {code} = new {classe.NamePascal}({Config.GetEnumName(codeProperty, classe)}.{code});"); - } - } - - 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))) - || classe.Extends != null - || AvailableClasses.Any(c => c.Extends == classe) - || classe.Decorators.Any(d => Config.GetImplementation(d.Decorator)?.Extends is not null)) - { - JpaModelConstructorGenerator.WriteNoArgConstructor(fw, classe); - } - - if (Config.MappersInClass) - { - JpaModelConstructorGenerator.WriteFromMappers(fw, classe, AvailableClasses, tag); - } - - if (Config.CanClassUseEnums(classe, Classes)) - { - JpaModelConstructorGenerator.WriteEnumConstructor(fw, classe, AvailableClasses, tag, _modelConfig); - } - - WriteGetters(fw, classe, tag); - WriteSetters(fw, classe, tag); - if (!Config.UseJdbc) - { - WriteAdders(fw, classe, tag); - WriteRemovers(fw, classe, tag); - if (Config.EnumShortcutMode) - { - WriteEnumShortcuts(fw, classe, tag); - } - } - - if (Config.MappersInClass) - { - WriteToMappers(fw, classe, tag); - } - - if ((Config.FieldsEnum & Target.Persisted) > 0 && classe.IsPersistent - || (Config.FieldsEnum & Target.Dto) > 0 && !classe.IsPersistent) - { - WriteFieldsEnum(fw, classe, tag); - } - - fw.WriteLine("}"); - } - - private void WriteAdders(JavaWriter fw, Class classe, string tag) - { - if (classe.IsPersistent && Config.AssociationAdders) - { - foreach (var ap in classe.GetProperties(AvailableClasses).OfType().Where(t => t.Type.IsToMany())) - { - var reverse = ap is ReverseAssociationProperty rap ? rap.ReverseProperty : ap.Association.GetProperties(AvailableClasses).OfType().FirstOrDefault(r => r.ReverseProperty == ap); - if (reverse != null) - { - var propertyName = ap.NameByClassCamel; - fw.WriteLine(); - fw.WriteDocStart(1, $"Add a value to {{@link {classe.GetImport(Config, tag)}#{propertyName} {propertyName}}}"); - fw.WriteLine(1, $" * @param {ap.Association.NameCamel} value to add"); - fw.WriteDocEnd(1); - fw.WriteLine(1, @$"public void add{ap.Association.NamePascal}{ap.Role}({ap.Association.NamePascal} {ap.Association.NameCamel}) {{"); - fw.WriteLine(2, @$"this.{propertyName}.add({ap.Association.NameCamel});"); - if (reverse.Type.IsToMany()) - { - fw.WriteLine(2, @$"{ap.Association.NameCamel}.get{reverse.NameByClassPascal}().add(this);"); - } - else - { - fw.WriteLine(2, @$"{ap.Association.NameCamel}.set{reverse.NameByClassPascal}(this);"); - } - - fw.WriteLine(1, "}"); - } - } - } - } - - private void WriteAnnotations(JavaWriter fw, Class classe, string tag) - { - fw.WriteDocStart(0, classe.Comment); - fw.WriteDocEnd(0); - var javaOrJakarta = Config.PersistenceMode.ToString().ToLower(); - if (Config.GeneratedHint) - { - fw.AddImport($"{javaOrJakarta}.annotation.Generated"); - fw.WriteLine("@Generated(\"TopModel : https://github.com/klee-contrib/topmodel\")"); - } - - if (classe.IsPersistent) - { - if (Config.UseJdbc) - { - var table = @$"@Table(name = ""{classe.SqlName.ToLower()}"")"; - fw.AddImport($"org.springframework.data.relational.core.mapping.Table"); - fw.WriteLine(table); - } - else - { - if (AvailableClasses.Any(c => c.Extends == classe)) - { - fw.WriteLine("@Inheritance(strategy = InheritanceType.JOINED)"); - fw.AddImport($"{javaOrJakarta}.persistence.Inheritance"); - fw.AddImport($"{javaOrJakarta}.persistence.InheritanceType"); - } - - var table = @$"@Table(name = ""{classe.SqlName}"""; - fw.AddImport($"{javaOrJakarta}.persistence.Table"); - if (classe.UniqueKeys.Any()) - { - fw.AddImport($"{javaOrJakarta}.persistence.UniqueConstraint"); - table += ", uniqueConstraints = {"; - var isFirstConstraint = true; - foreach (var unique in classe.UniqueKeys) - { - if (!isFirstConstraint) - { - table += ","; - } - - table += "\n "; - isFirstConstraint = false; - table += "@UniqueConstraint(columnNames = {"; - var isFirstColumn = true; - foreach (var u in unique) - { - if (!isFirstColumn) - { - table += ","; - } - - isFirstColumn = false; - table += $"\"{u.SqlName}\""; - } - - table += "})"; - } - - table += "}"; - } - - table += ")"; - fw.AddImport($"{javaOrJakarta}.persistence.Entity"); - fw.WriteLine("@Entity"); - fw.WriteLine(table); - if (classe.PrimaryKey.Count() > 1) - { - fw.WriteLine($"@IdClass({classe.NamePascal}.{classe.NamePascal}Id.class)"); - fw.AddImport($"{javaOrJakarta}.persistence.IdClass"); - } - - if (classe.Reference) - { - fw.AddImports(new List() - { - "org.hibernate.annotations.Cache", - "org.hibernate.annotations.CacheConcurrencyStrategy" - }); - if (Config.CanClassUseEnums(classe)) - { - fw.AddImport("org.hibernate.annotations.Immutable"); - fw.WriteLine("@Immutable"); - fw.WriteLine("@Cache(usage = CacheConcurrencyStrategy.READ_ONLY)"); - } - else - { - fw.WriteLine("@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)"); - } - } - } - } - - foreach (var a in Config.GetDecoratorAnnotations(classe, tag)) - { - fw.WriteLine($"{(a.StartsWith("@") ? string.Empty : "@")}{a}"); - } - } - - private void WriteEnumShortcuts(JavaWriter fw, Class classe, string tag) - { - foreach (var ap in classe.GetProperties(AvailableClasses).OfType().Where(ap => Config.CanClassUseEnums(ap.Association))) - { - fw.AddImport($"{Config.GetEnumPackageName(ap.Association, tag)}.{Config.GetEnumName(ap.Association.PrimaryKey.Single(), ap.Association)}"); - var isMultiple = ap.Type.IsToMany(); - { - var propertyName = ap.NameCamel; - fw.WriteLine(); - fw.WriteDocStart(1, $"Set the value of {{@link {classe.GetImport(Config, tag)}#{propertyName} {propertyName}}}"); - fw.WriteLine(1, " * Cette méthode permet définir la valeur de la FK directement"); - fw.WriteLine(1, $" * @param {propertyName} value to set"); - fw.WriteDocEnd(1); - fw.WriteLine(1, @$"public void {(isMultiple ? ap.NameCamel + ap.Property.NamePascal : ap.NameCamel).WithPrefix("set")}({(isMultiple ? $"List<{Config.GetType(ap.Property)}>" : Config.GetType(ap.Property))} {propertyName}) {{"); - fw.WriteLine(2, $"if ({propertyName} != null) {{"); - if (!isMultiple) - { - fw.WriteLine(3, @$"this.{ap.NameByClassCamel} = new {ap.Association.NamePascal}({propertyName});"); - } - else - { - var type = Config.GetType(ap, AvailableClasses, useClassForAssociation: classe.IsPersistent && !Config.UseJdbc && ap.Association.IsPersistent).Split('<').First(); - - if (_newableTypes.TryGetValue(type, out var newableType)) - { - fw.WriteLine(3, @$"if (this.{ap.NameByClassCamel} != null) {{"); - fw.WriteLine(4, @$"this.{ap.NameByClassCamel}.clear();"); - fw.WriteLine(3, "} else {"); - fw.AddImport($"java.util.{newableType}"); - fw.WriteLine(4, @$"this.{ap.NameByClassCamel} = new {newableType}<>();"); - fw.WriteLine(3, "}"); - fw.WriteLine(3, @$"this.{ap.NameByClassCamel}.addAll({propertyName}.stream().map({ap.Association.NamePascal}::new).collect(Collectors.to{type}()));"); - fw.AddImport("java.util.stream.Collectors"); - } - } - - fw.WriteLine(2, "} else {"); - fw.WriteLine(3, @$"this.{ap.NameByClassCamel} = null;"); - fw.WriteLine(2, "}"); - fw.WriteLine(1, "}"); - } - - { - fw.WriteLine(); - fw.WriteDocStart(1, $"Getter for {ap.NameCamel}"); - fw.WriteLine(1, " * Cette méthode permet de manipuler directement la foreign key de la liste de référence"); - fw.WriteReturns(1, $"value of {{@link {classe.GetImport(Config, tag)}#{ap.NameByClassCamel} {ap.NameByClassCamel}}}"); - fw.WriteDocEnd(1); - fw.WriteLine(1, "@Transient"); - fw.AddImport(Config.PersistenceMode.ToString().ToLower() + ".persistence.Transient"); - fw.WriteLine(1, @$"public {(isMultiple ? $"List<{Config.GetType(ap.Property)}>" : Config.GetType(ap.Property))} get{(isMultiple ? ap.NameCamel.ToFirstUpper() + ap.Property.NameCamel.ToFirstUpper() : ap.NameCamel.ToFirstUpper())}() {{"); - if (!isMultiple) - { - fw.WriteLine(2, @$"return this.{ap.NameByClassCamel} != null ? this.{ap.NameByClassCamel}.get{ap.Property.NameCamel.ToFirstUpper()}() : null;"); - } - else - { - var listOrSet = Config.GetType(ap, AvailableClasses, useClassForAssociation: classe.IsPersistent && !Config.UseJdbc && ap.Association.IsPersistent).Split('<').First(); - fw.WriteLine(2, @$"return this.{ap.NameByClassCamel} != null ? this.{ap.NameByClassCamel}.stream().map({ap.Association.NamePascal}::get{ap.Property.NameCamel.ToFirstUpper()}).collect(Collectors.to{listOrSet}()) : null;"); - fw.AddImport("java.util.stream.Collectors"); - } - - fw.WriteLine(1, "}"); - } - } - } - - private void WriteFieldsEnum(JavaWriter fw, Class classe, string tag) - { - if (!classe.Properties.Any()) - { - return; - } - - if (Config.FieldsEnumInterface != null) - { - fw.AddImport(Config.FieldsEnumInterface.Replace("<>", string.Empty)); - } - - fw.WriteLine(); - fw.WriteDocStart(1, $"Enumération des champs de la classe {{@link {classe.GetImport(Config, tag)} {classe.NamePascal}}}"); - fw.WriteDocEnd(1); - string enumDeclaration = @$"public enum Fields "; - if (Config.FieldsEnumInterface != null) - { - enumDeclaration += $"implements {Config.FieldsEnumInterface.Split(".").Last().Replace("<>", $"<{classe.NamePascal}>")}"; - } - - enumDeclaration += " {"; - fw.WriteLine(1, enumDeclaration); - - var props = classe.GetProperties(AvailableClasses).Select(prop => - { - string name; - if (prop is AssociationProperty ap && ap.Association.IsPersistent && !Config.UseJdbc) - { - name = ap.NameByClassCamel.ToConstantCase(); - } - else - { - name = prop.NameCamel.ToConstantCase(); - } - - var javaType = Config.GetType(prop, useClassForAssociation: classe.IsPersistent && !Config.UseJdbc && prop is AssociationProperty asp && asp.Association.IsPersistent); - javaType = javaType.Split("<")[0]; - return $" {name}({javaType}.class)"; - }); - - fw.WriteLine(string.Join(", //\n", props) + ";"); - - fw.WriteLine(); - - fw.WriteLine(2, "private Class type;"); - fw.WriteLine(); - fw.WriteLine(2, "private Fields(Class type) {"); - fw.WriteLine(3, "this.type = type;"); - fw.WriteLine(2, "}"); - - fw.WriteLine(); - - fw.WriteLine(2, "public Class getType() {"); - fw.WriteLine(3, "return this.type;"); - fw.WriteLine(2, "}"); - - fw.WriteLine(1, "}"); - } - - private void WriteGetters(JavaWriter fw, Class classe, string tag) - { - var properties = Config.UseJdbc ? classe.Properties.Where(p => !(p is AssociationProperty ap && (ap.Type == AssociationType.OneToMany || ap.Type == AssociationType.ManyToMany))) : classe.GetProperties(AvailableClasses); - foreach (var property in properties) - { - _jpaModelPropertyGenerator!.WriteGetter(fw, classe, tag, property); - } - } - - private void WriteImports(JavaWriter fw, Class classe, string tag) - { - var imports = classe.GetImports(Config, tag, AvailableClasses); - imports.AddRange(Config.GetDecoratorImports(classe, tag)); - var properties = Config.UseJdbc ? classe.Properties.Where(p => !(p is AssociationProperty ap && (ap.Type == AssociationType.OneToMany || ap.Type == AssociationType.ManyToMany))) : classe.GetProperties(AvailableClasses); - foreach (var property in properties) - { - imports.AddRange(property.GetTypeImports(Config, tag)); - } - - fw.AddImports(imports); - } - - private void WriteRemovers(JavaWriter fw, Class classe, string tag) - { - if (classe.IsPersistent && Config.AssociationRemovers) - { - foreach (var ap in classe.GetProperties(AvailableClasses).OfType().Where(t => t.Type.IsToMany())) - { - var reverse = ap is ReverseAssociationProperty rap ? rap.ReverseProperty : ap.Association.GetProperties(AvailableClasses).OfType().FirstOrDefault(r => r.ReverseProperty == ap); - if (reverse != null) - { - var propertyName = ap.NameByClassCamel; - fw.WriteLine(); - fw.WriteDocStart(1, $"Remove a value from {{@link {classe.GetImport(Config, tag)}#{propertyName} {propertyName}}}"); - fw.WriteLine(1, $" * @param {ap.Association.NameCamel} value to remove"); - fw.WriteDocEnd(1); - fw.WriteLine(1, @$"public void remove{ap.Association.NamePascal}{ap.Role}({ap.Association.NamePascal} {ap.Association.NameCamel}) {{"); - fw.WriteLine(2, @$"this.{propertyName}.remove({ap.Association.NameCamel});"); - if (reverse.Type.IsToMany()) - { - fw.WriteLine(2, @$"{ap.Association.NameCamel}.get{reverse.NameByClassPascal}().remove(this);"); - } - else - { - fw.WriteLine(2, @$"{ap.Association.NameCamel}.set{reverse.NameByClassPascal}(null);"); - } - - fw.WriteLine(1, "}"); - } - } - } - } - - private void WriteSetters(JavaWriter fw, Class classe, string tag) - { - var properties = Config.UseJdbc ? classe.Properties.Where(p => !(p is AssociationProperty ap && (ap.Type == AssociationType.OneToMany || ap.Type == AssociationType.ManyToMany))) : classe.GetProperties(AvailableClasses); - if (Config.CanClassUseEnums(classe, Classes)) - { - return; - } - - foreach (var property in properties) - { - _jpaModelPropertyGenerator!.WriteSetter(fw, classe, tag, property); - } - } - - 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) - .ToList(); - - foreach (var toMapper in toMappers) - { - var (clazz, mapper) = toMapper; - - fw.WriteLine(); - fw.WriteDocStart(1, $"Mappe '{classe}' vers '{mapper.Class.NamePascal}'"); - if (mapper.Comment != null) - { - fw.WriteLine(1, $" * {mapper.Comment}"); - } - - fw.WriteParam("target", $"Instance pré-existante de '{mapper.Class.NamePascal}'. Une nouvelle instance sera créée si non spécifié."); - fw.WriteReturns(1, $"Une instance de '{mapper.Class.NamePascal}'"); - - fw.WriteDocEnd(1); - var (mapperNs, mapperModelPath) = Config.GetMapperLocation(toMapper); - - fw.WriteLine(1, $"public {mapper.Class.NamePascal} {mapper.Name.Value.ToCamelCase()}({mapper.Class.NamePascal} target) {{"); - fw.WriteLine(2, $"return {Config.GetMapperName(mapperNs, mapperModelPath)}.{mapper.Name.Value.ToCamelCase()}(this, target);"); - fw.AddImport(Config.GetMapperImport(mapperNs, mapperModelPath, tag)!); - fw.WriteLine(1, "}"); - - if (toMappers.IndexOf(toMapper) < toMappers.Count - 1) - { - fw.WriteLine(); - } - } - } -} \ No newline at end of file diff --git a/TopModel.Generator.Jpa/JpaModelInterfaceGenerator.cs b/TopModel.Generator.Jpa/JpaModelInterfaceGenerator.cs index e876502e..0056298b 100644 --- a/TopModel.Generator.Jpa/JpaModelInterfaceGenerator.cs +++ b/TopModel.Generator.Jpa/JpaModelInterfaceGenerator.cs @@ -33,7 +33,7 @@ protected override void HandleClass(string fileName, Class classe, string tag) { var packageName = Config.GetPackageName(classe, tag); using var fw = new JavaWriter(fileName, _logger, packageName, null); - var javaOrJakarta = Config.PersistenceMode.ToString().ToLower(); + var javaxOrJakarta = Config.PersistenceMode.ToString().ToLower(); WriteImports(fw, classe, tag); fw.WriteLine(); @@ -43,7 +43,7 @@ protected override void HandleClass(string fileName, Class classe, string tag) if (Config.GeneratedHint) { - fw.AddImport($"{javaOrJakarta}.annotation.Generated"); + fw.AddImport($"{javaxOrJakarta}.annotation.Generated"); fw.WriteLine("@Generated(\"TopModel : https://github.com/klee-contrib/topmodel\")"); } @@ -61,7 +61,7 @@ protected override void HandleClass(string fileName, Class classe, string tag) private void WriteGetters(JavaWriter fw, Class classe, string tag) { - foreach (var property in classe.Properties.Where(p => !Config.EnumShortcutMode || !(p is AssociationProperty apo && apo.Association.Reference && (apo.Type == AssociationType.OneToOne || apo.Type == AssociationType.ManyToOne)))) + foreach (var property in classe.Properties.Where(p => !(p is AssociationProperty apo && apo.Association.Reference && (apo.Type == AssociationType.OneToOne || apo.Type == AssociationType.ManyToOne)))) { var getterPrefix = Config.GetType(property) == "boolean" ? "is" : "get"; fw.WriteLine(); @@ -76,7 +76,7 @@ private void WriteHydrate(JavaWriter fw, Class classe) { var properties = classe.Properties .Where(p => !p.Readonly) - .Where(p => !Config.EnumShortcutMode || !(p is AssociationProperty apo && apo.Association.Reference && (apo.Type == AssociationType.OneToOne || apo.Type == AssociationType.ManyToOne))); + .Where(p => !(p is AssociationProperty apo && apo.Association.Reference && (apo.Type == AssociationType.OneToOne || apo.Type == AssociationType.ManyToOne))); if (!properties.Any()) { diff --git a/TopModel.Generator.Jpa/JpaModelPropertyGenerator.cs b/TopModel.Generator.Jpa/JpaModelPropertyGenerator.cs index bbfc4e24..fd7fd659 100644 --- a/TopModel.Generator.Jpa/JpaModelPropertyGenerator.cs +++ b/TopModel.Generator.Jpa/JpaModelPropertyGenerator.cs @@ -14,6 +14,8 @@ public class JpaModelPropertyGenerator private readonly JpaConfig _config; private readonly Dictionary _newableTypes; + private string JavaxOrJakarta => _config.PersistenceMode.ToString().ToLower(); + public JpaModelPropertyGenerator(JpaConfig config, IEnumerable classes, Dictionary newableTypes) { _classes = classes; @@ -33,23 +35,25 @@ public void WriteCompositePrimaryKeyClass(JavaWriter fw, Class classe, string ta foreach (var pk in classe.PrimaryKey) { fw.WriteLine(); + var annotations = new List(); + annotations.AddRange(GetDomainAnnotations(pk, tag)); if (pk is AssociationProperty ap) { - WriteAssociationAnnotations(fw, classe, ap, 2); + annotations.AddRange(GetJpaAssociationAnnotations(ap, tag)); } - else if (ShouldWriteColumnAnnotation(classe, pk)) + else if (ShouldWriteColumnAnnotation(pk)) { - WriteColumnAnnotation(fw, pk, 2); + annotations.Add(GetColumnAnnotation(pk)); } - WriteDomainAnnotations(fw, pk, tag, 2); - fw.WriteLine(2, $"private {_config.GetType(pk, _classes, true)} {pk.NameByClassCamel};"); + fw.WriteAnnotations(2, annotations); + fw.WriteLine(2, $"private {GetPropertyType(pk)} {GetPropertyName(pk)};"); } foreach (var pk in classe.PrimaryKey) { - WriteGetter(fw, classe, tag, pk, 2); - WriteSetter(fw, classe, tag, pk, 2); + WriteGetter(fw, tag, pk, 2); + WriteSetter(fw, tag, pk, 2); } fw.WriteLine(); @@ -89,40 +93,20 @@ public void WriteCompositePrimaryKeyClass(JavaWriter fw, Class classe, string ta fw.WriteLine(1, "}"); } - public void WriteCompositionProperty(JavaWriter fw, CompositionProperty property, string tag) - { - fw.WriteDocEnd(1); - if (property.Class.IsPersistent) - { - WriteConvertAnnotation(fw, property, 1, tag); - WriteColumnAnnotation(fw, property, 1); - } - - fw.AddImport(property.Composition.GetImport(_config, tag)); - fw.WriteLine(1, $"private {_config.GetType(property)} {property.NameCamel};"); - } - - public void WriteGetter(JavaWriter fw, Class classe, string tag, IProperty property, int indentLevel = 1) + public void WriteGetter(JavaWriter fw, string tag, IProperty property, int indentLevel = 1) { - var isAssociationNotPersistent = property is AssociationProperty apr && !apr.Association.IsPersistent; - var propertyName = _config.UseJdbc || isAssociationNotPersistent ? property.NameCamel : property.NameByClassCamel; + var propertyName = GetPropertyName(property); + var propertyType = GetPropertyType(property); fw.WriteLine(); fw.WriteDocStart(indentLevel, $"Getter for {propertyName}"); - fw.WriteReturns(indentLevel, $"value of {{@link {classe.GetImport(_config, tag)}#{propertyName} {propertyName}}}"); + fw.WriteReturns(indentLevel, $"value of {{@link {property.Class.GetImport(_config, tag)}#{propertyName} {propertyName}}}"); fw.WriteDocEnd(indentLevel); + string getterName = GetGetterName(property); - var getterPrefix = _config.GetType(property, _classes, true) == "boolean" ? "is" : "get"; - var getterName = propertyName.ToPascalCase().WithPrefix(getterPrefix); - if (property.Class.PreservePropertyCasing) - { - getterName = propertyName.ToFirstUpper().WithPrefix(getterPrefix); - } - - var useClassForAssociation = classe.IsPersistent && !isAssociationNotPersistent && !_config.UseJdbc; - fw.WriteLine(indentLevel, @$"public {_config.GetType(property, useClassForAssociation: useClassForAssociation)} {getterName}() {{"); + fw.WriteLine(indentLevel, @$"public {propertyType} {getterName}() {{"); if (property is AssociationProperty ap && ap.Type.IsToMany()) { - var type = _config.GetType(ap, _classes, useClassForAssociation: useClassForAssociation).Split('<').First(); + var type = propertyType.Split('<').First(); if (_newableTypes.TryGetValue(type, out var newableType)) { fw.WriteLine(indentLevel + 1, $"if(this.{propertyName} == null) {{"); @@ -136,432 +120,503 @@ public void WriteGetter(JavaWriter fw, Class classe, string tag, IProperty prope fw.WriteLine(indentLevel, "}"); } + public string GetGetterName(IProperty property) + { + var propertyName = GetPropertyName(property); + var propertyType = GetPropertyType(property); + var getterPrefix = propertyType == "boolean" ? "is" : "get"; + if (property.Class.PreservePropertyCasing) + { + return propertyName.ToFirstUpper().WithPrefix(getterPrefix); + } + + return propertyName.ToPascalCase().WithPrefix(getterPrefix); + } + public void WriteProperties(JavaWriter fw, Class classe, string tag) { var properties = _config.UseJdbc ? classe.Properties.Where(p => !(p is AssociationProperty ap && (ap.Type == AssociationType.OneToMany || ap.Type == AssociationType.ManyToMany))) : classe.GetProperties(_classes); foreach (var property in properties) { - WriteProperty(fw, classe, property, tag); + WriteProperty(fw, property, tag); } } - public void WriteProperty(JavaWriter fw, Class classe, IProperty property, string tag) + public void WriteProperty(JavaWriter fw, IProperty property, string tag) { fw.WriteLine(); + fw.AddImports(property.GetTypeImports(_config, tag)); fw.WriteDocStart(1, property.Comment); - switch (property) - { - case CompositionProperty cp: - WriteCompositionProperty(fw, cp, tag); - break; - case AssociationProperty { Association.IsPersistent: true } ap: - WriteAssociationProperty(fw, classe, ap, tag); - break; - case AliasProperty alp: - WriteAliasProperty(fw, classe, alp, tag); - break; - default: - WriteIFieldProperty(fw, classe, property, tag); - break; + IEnumerable annotations = GetAnnotations(property, tag); + if (property is AliasProperty ap && _classes.Contains(ap.Property.Class)) + { + fw.WriteLine(1, $" * Alias of {{@link {ap.Property.Class.GetImport(_config, tag)}#get{GetPropertyName(ap.Property).ToFirstUpper()}() {ap.Property.Class.NamePascal}#get{GetPropertyName(ap.Property).ToFirstUpper()}()}} "); + } + + fw.WriteDocEnd(1); + + if (property.Domain != null && !property.PrimaryKey || property.Class.PrimaryKey.Count() <= 1) + { + annotations = GetDomainAnnotations(property, tag).Concat(annotations).ToList(); } + + fw.WriteAnnotations(1, annotations); + string defaultValue = GetDefaultValue(property); + fw.AddImports(GetDefaultValueImports(property, tag)); + fw.WriteLine(1, $"private {GetPropertyType(property)} {GetPropertyName(property)}{defaultValue};"); ; } - public void WriteSetter(JavaWriter fw, Class classe, string tag, IProperty property, int indentLevel = 1) + public void WriteSetter(JavaWriter fw, string tag, IProperty property, int indentLevel = 1) { - var isAssociationNotPersistent = property is AssociationProperty apr && !apr.Association.IsPersistent; - var propertyName = _config.UseJdbc || isAssociationNotPersistent ? property.NameCamel : property.NameByClassCamel; + var propertyName = GetPropertyName(property); fw.WriteLine(); - fw.WriteDocStart(indentLevel, $"Set the value of {{@link {classe.GetImport(_config, tag)}#{propertyName} {propertyName}}}"); + fw.WriteDocStart(indentLevel, $"Set the value of {{@link {property.Class.GetImport(_config, tag)}#{propertyName} {propertyName}}}"); fw.WriteLine(indentLevel, $" * @param {propertyName} value to set"); fw.WriteDocEnd(indentLevel); - var useClassForAssociation = classe.IsPersistent && !isAssociationNotPersistent && !_config.UseJdbc; - fw.WriteLine(indentLevel, @$"public void {propertyName.WithPrefix("set")}({_config.GetType(property, useClassForAssociation: useClassForAssociation)} {propertyName}) {{"); + fw.WriteLine(indentLevel, @$"public void {propertyName.WithPrefix("set")}({GetPropertyType(property)} {propertyName}) {{"); fw.WriteLine(indentLevel + 1, @$"this.{propertyName} = {propertyName};"); fw.WriteLine(indentLevel, "}"); } - private static void WriteEnumAnnotation(JavaWriter fw, string javaOrJakarta) + protected IEnumerable GetAnnotations(CompositionProperty property, string tag) { - fw.AddImports(new List - { - $"{javaOrJakarta}.persistence.Enumerated", - $"{javaOrJakarta}.persistence.EnumType", - }); - fw.WriteLine(1, "@Enumerated(EnumType.STRING)"); + if (property.Class.IsPersistent) + { + return [GetConvertAnnotation(property, tag), GetColumnAnnotation(property)]; + } + + return []; } - private static void WriteValidationAnnotations(JavaWriter fw, string javaOrJakarta) + protected string GetPropertyName(IProperty property) { - fw.WriteLine(1, @$"@NotNull"); - fw.AddImport($"{javaOrJakarta}.validation.constraints.NotNull"); + var isAssociationNotPersistent = property is AssociationProperty apr && !apr.Association.IsPersistent; + return _config.UseJdbc || isAssociationNotPersistent ? property.NameCamel : property.NameByClassCamel; + } + + protected string GetPropertyType(IProperty property) + { + var isAssociationNotPersistent = property is AssociationProperty apr && !apr.Association.IsPersistent; + var useClassForAssociation = property.Class.IsPersistent && !isAssociationNotPersistent && !_config.UseJdbc; + return _config.GetType(property, useClassForAssociation: useClassForAssociation); + } + + private JavaAnnotation GetEnumAnnotation() + { + return new JavaAnnotation("Enumerated", $"{JavaxOrJakarta}.persistence.Enumerated") + .AddAttribute("value", "EnumType.STRING", $"{JavaxOrJakarta}.persistence.EnumType"); } private string GetterToCompareCompositePkPk(IProperty pk) { if (pk is AssociationProperty ap) { - return $".get{ap.Property.NamePascal}()"; + return $".{GetGetterName(ap.Property)}()"; } else if (pk is AliasProperty al && al.Property is AssociationProperty asp) { - return $".get{asp.Property.NamePascal}()"; + return $".get{GetGetterName(asp.Property)}()"; } return string.Empty; } - private bool ShouldWriteColumnAnnotation(Class classe, IProperty property) + private bool ShouldWriteColumnAnnotation(IProperty property) { - return (classe.IsPersistent || _config.UseJdbc) && (property.Domain is null || !_config.GetImplementation(property.Domain)!.Annotations - .Where(i => - classe.IsPersistent && (Target.Persisted & i.Target) > 0 - || !classe.IsPersistent && (Target.Dto & i.Target) > 0) - .Any(a => a.Text.Replace("@", string.Empty).StartsWith("Column"))); + return property.Class.IsPersistent || _config.UseJdbc; } - private void WriteAliasProperty(JavaWriter fw, Class classe, AliasProperty property, string tag) + private IEnumerable GetAnnotations(AliasProperty property, string tag) { - if (_classes.Contains(property.Property.Class)) - { - fw.WriteLine(1, $" * Alias of {{@link {property.Property.Class.GetImport(_config, tag)}#get{property.Property.NameCamel.ToFirstUpper()}() {property.Property.Class.NamePascal}#get{property.Property.NameCamel.ToFirstUpper()}()}} "); - } - - fw.WriteDocEnd(1); - var javaOrJakarta = _config.PersistenceMode.ToString().ToLower(); - var shouldWriteAssociation = classe.IsPersistent && property.Property is AssociationProperty; - - if (property.PrimaryKey && classe.IsPersistent) - { - WriteIdAnnotation(fw, classe, property); - } - - if (!shouldWriteAssociation && ShouldWriteColumnAnnotation(classe, property) && (_config.UseJdbc || !(property.PrimaryKey && classe.PrimaryKey.Count() > 1))) + var shouldWriteAssociation = property.Class.IsPersistent && property.Property is AssociationProperty; + if (property.PrimaryKey && property.Class.IsPersistent) { - WriteColumnAnnotation(fw, property, 1); + foreach (var a in GetIdAnnotations(property)) + { + yield return a; + } } if (shouldWriteAssociation) { - WriteAssociationAnnotations(fw, classe, (AssociationProperty)property.Property, 1); - } - - if (property.Property is CompositionProperty cp) - { - fw.AddImport(cp.Composition.GetImport(_config, tag)); - if (classe.IsPersistent) + foreach (var a in GetJpaAssociationAnnotations((AssociationProperty)property.Property, tag)) { - WriteConvertAnnotation(fw, cp, 1, tag); + yield return a; } } + else if (ShouldWriteColumnAnnotation(property) && (_config.UseJdbc || !(property.PrimaryKey && property.Class.PrimaryKey.Count() > 1))) + { + yield return GetColumnAnnotation(property); + } - if (property.Required && !property.PrimaryKey && (!classe.IsPersistent || _config.UseJdbc)) + if (property.Property is CompositionProperty cp) { - WriteValidationAnnotations(fw, javaOrJakarta); + GetAnnotations(cp, tag); } - if (_config.CanClassUseEnums(property.Property.Class) && property.Property.PrimaryKey && classe.IsPersistent && !_config.UseJdbc) + if (property.Required && !property.PrimaryKey && (!property.Class.IsPersistent || _config.UseJdbc)) { - WriteEnumAnnotation(fw, javaOrJakarta); + yield return new JavaAnnotation("NotNull", $"{JavaxOrJakarta}.validation.constraints.NotNull"); } - if (property.Domain is not null && (!property.PrimaryKey || classe.PrimaryKey.Count() <= 1)) + if (_config.CanClassUseEnums(property.Property.Class) && property.Property.PrimaryKey && property.Class.IsPersistent && !_config.UseJdbc) { - WriteDomainAnnotations(fw, property, tag, 1); + yield return GetEnumAnnotation(); } + } - var defaultValue = _config.GetValue(property, _classes); - var suffix = defaultValue != "null" ? $" = {defaultValue}" : string.Empty; - var isAssociationNotPersistent = property.Property is AssociationProperty ap && !ap.Association.IsPersistent; - var useClassForAssociation = classe.IsPersistent && !isAssociationNotPersistent && !_config.UseJdbc; - fw.WriteLine(1, $"private {_config.GetType(property, useClassForAssociation: useClassForAssociation)} {(isAssociationNotPersistent && !shouldWriteAssociation ? property.NameCamel : property.NameByClassCamel)}{suffix};"); + private IEnumerable GetJpaAssociationAnnotations(AssociationProperty property, string tag) + { + return property.Type switch + { + AssociationType.ManyToOne => GetManyToOneAnnotations(property, tag), + AssociationType.OneToMany => GetOneToManyAnnotations(property), + AssociationType.ManyToMany => GetManyToManyAnnotations(property), + AssociationType.OneToOne => GetOneToOneAnnotations(property), + _ => [], + }; } - private void WriteAssociationAnnotations(JavaWriter fw, Class classe, AssociationProperty property, int indentLevel) + private IEnumerable GetAnnotations(IProperty property, string tag) { - switch (property.Type) - { - case AssociationType.ManyToOne: - WriteManyToOneAnnotations(fw, property, indentLevel); - break; - case AssociationType.OneToMany: - WriteOneToManyAnnotations(fw, classe, property, indentLevel); - break; - case AssociationType.ManyToMany: - WriteManyToManyAnnotations(fw, classe, property, indentLevel); - break; - case AssociationType.OneToOne: - WriteOneToOneAnnotations(fw, property, indentLevel); - break; - } + return property switch + { + AliasProperty alp => GetAnnotations(alp, tag), + AssociationProperty ap => GetAnnotations(ap, tag), + CompositionProperty cp => GetAnnotations(cp, tag), + IProperty ip => GetAnnotations(ip), + _ => [], + }; } - private void WriteAssociationProperty(JavaWriter fw, Class classe, AssociationProperty property, string tag) + private IEnumerable GetAnnotations(AssociationProperty property, string tag) { - fw.WriteDocEnd(1); - if (!_config.UseJdbc) + if (property.Class.IsPersistent) { - var javaOrJakarta = _config.PersistenceMode.ToString().ToLower(); - fw.AddImport($"{javaOrJakarta}.persistence.FetchType"); - fw.AddImport($"{javaOrJakarta}.persistence.{property.Type}"); - - if (!property.PrimaryKey || classe.PrimaryKey.Count() <= 1) + if (!_config.UseJdbc) { - WriteAssociationAnnotations(fw, classe, property, 1); - } + if (!property.PrimaryKey || property.Class.PrimaryKey.Count() <= 1) + { + foreach (var a in GetJpaAssociationAnnotations(property, tag)) + { + yield return a; + } + } - if (property.Type == AssociationType.ManyToMany || property.Type == AssociationType.OneToMany) - { - if (property.Association.OrderProperty != null && _config.GetType(property, _classes, classe.IsPersistent).Contains("List")) + if (property.Type == AssociationType.ManyToMany || property.Type == AssociationType.OneToMany) { - fw.WriteLine(1, @$"@OrderBy(""{property.Association.OrderProperty.NameByClassCamel} ASC"")"); - fw.AddImport($"{javaOrJakarta}.persistence.OrderBy"); + if (property.Association.OrderProperty != null && GetPropertyType(property).Contains("List")) + { + yield return new JavaAnnotation("OrderBy", $@"""{property.Association.OrderProperty.NameByClassCamel} ASC""", $"{JavaxOrJakarta}.persistence.OrderBy"); + } } - } - var suffix = string.Empty; - if (property.Association.PrimaryKey.Count() == 1 && _config.CanClassUseEnums(property.Association, _classes, prop: property.Association.PrimaryKey.Single())) - { - var defaultValue = _config.GetValue(property, _classes); - if (defaultValue != "null") + if (property.PrimaryKey) { - fw.AddImport($"{_config.GetEnumPackageName(classe, _config.GetBestClassTag(classe, tag))}.{_config.GetType(property.Association.PrimaryKey.Single())}"); - suffix = $" = new {property.Association.NamePascal}({defaultValue})"; + foreach (var a in GetIdAnnotations(property)) + { + yield return a; + } } } - - if (property.PrimaryKey) + else { - fw.AddImport($"{javaOrJakarta}.persistence.Id"); - fw.WriteLine(1, "@Id"); - } + if (property.PrimaryKey && property.Class.PrimaryKey.Count() <= 1) + { + foreach (var a in GetIdAnnotations(property)) + { + yield return a; + } + } - var isAssociationNotPersistent = !property.Association.IsPersistent; - var useClassForAssociation = classe.IsPersistent && !isAssociationNotPersistent && !_config.UseJdbc; - fw.WriteLine(1, $"private {_config.GetType(property, useClassForAssociation: useClassForAssociation)} {property.NameByClassCamel}{suffix};"); - } - else - { - if (property.PrimaryKey && classe.PrimaryKey.Count() <= 1) - { - fw.AddImport("org.springframework.data.annotation.Id"); - fw.WriteLine(1, "@Id"); + yield return new JavaAnnotation("Column", @$"""{((IProperty)property).SqlName.ToLower()}""", "org.springframework.data.relational.core.mapping.Column"); } - - fw.AddImport("org.springframework.data.relational.core.mapping.Column"); - fw.WriteLine(1, $@"@Column(""{((IProperty)property).SqlName.ToLower()}"")"); - fw.WriteLine(1, $"private {_config.GetType(property)} {property.NameCamel};"); } } - private void WriteAutogeneratedAnnotations(JavaWriter fw, Class classe, string javaOrJakarta) + private IEnumerable GetAutogeneratedAnnotations(Class classe) { - fw.AddImports(new List - { - $"{javaOrJakarta}.persistence.GeneratedValue", - $"{javaOrJakarta}.persistence.GenerationType" - }); - + var autoGenerated = new JavaAnnotation("GeneratedValue", $"{JavaxOrJakarta}.persistence.GeneratedValue"); if (_config.Identity.Mode == IdentityMode.IDENTITY) { - fw.WriteLine(1, @$"@GeneratedValue(strategy = GenerationType.IDENTITY)"); + autoGenerated.AddAttribute("strategy", "GenerationType.IDENTITY", $"{JavaxOrJakarta}.persistence.GenerationType"); } else if (_config.Identity.Mode == IdentityMode.SEQUENCE) { - fw.AddImport($"{javaOrJakarta}.persistence.SequenceGenerator"); + autoGenerated.AddAttribute("strategy", "GenerationType.SEQUENCE", $"{JavaxOrJakarta}.persistence.GenerationType"); + var sequenceGenerator = new JavaAnnotation("SequenceGenerator", $"{JavaxOrJakarta}.persistence.SequenceGenerator"); var seqName = $"SEQ_{classe.SqlName}"; - var initialValue = _config.Identity.Start != null ? $", initialValue = {_config.Identity.Start}" : string.Empty; - var increment = _config.Identity.Increment != null ? $", allocationSize = {_config.Identity.Increment}" : string.Empty; - fw.WriteLine(1, @$"@SequenceGenerator(name = ""{seqName}"", sequenceName = ""{seqName}""{initialValue}{increment})"); - fw.WriteLine(1, @$"@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = ""{seqName}"")"); + sequenceGenerator.AddAttribute("sequenceName", $@"""{seqName}"""); + if (_config.Identity.Start != null) + { + sequenceGenerator.AddAttribute("initialValue", $"{_config.Identity.Start}"); + } + + if (_config.Identity.Increment != null) + { + sequenceGenerator.AddAttribute("allocationSize", $"{_config.Identity.Increment}"); + } + + yield return sequenceGenerator; } + + yield return autoGenerated; } - private void WriteColumnAnnotation(JavaWriter fw, IProperty property, int indentLevel) + private JavaAnnotation GetColumnAnnotation(IProperty property) { - var javaOrJakarta = _config.PersistenceMode.ToString().ToLower(); - string column; + JavaAnnotation column; if (!_config.UseJdbc) { - var nullable = property.Required ? ", nullable = false" : string.Empty; - column = @$"@Column(name = ""{property.SqlName}""{nullable}"; + column = new JavaAnnotation("Column", $"{JavaxOrJakarta}.persistence.Column"); + column.AddAttribute("name", $@"""{property.SqlName}"""); + if (property.Required) + { + column.AddAttribute("nullable", "false"); + } + if (property.Domain != null) { if (property.Domain.Length != null) { if (_config.GetImplementation(property.Domain)?.Type?.ToUpper() == "STRING") { - column += $", length = {property.Domain.Length}"; + column.AddAttribute("length", $"{property.Domain.Length}"); } else { - column += $", precision = {property.Domain.Length}"; + column.AddAttribute("precision", $"{property.Domain.Length}"); } } if (property.Domain.Scale != null) { - column += $", scale = {property.Domain.Scale}"; + column.AddAttribute("scale", $"{property.Domain.Scale}"); } - column += @$", columnDefinition = ""{property.Domain.Implementations["sql"].Type}"""; + column.AddAttribute("columnDefinition", @$"""{property.Domain.Implementations["sql"].Type}"""); } if (property is CompositionProperty && property.Domain is null) { - column += @$", columnDefinition = ""jsonb"""; + column.AddAttribute("columnDefinition", @$"""jsonb"""); } - - column += ")"; - fw.AddImport($"{javaOrJakarta}.persistence.Column"); } else { - fw.AddImport("org.springframework.data.relational.core.mapping.Column"); - column = $@"@Column(""{property.SqlName.ToLower()}"")"; + column = new JavaAnnotation("Column", "org.springframework.data.relational.core.mapping.Column"); + column.AddAttribute("value", $@"""{property.SqlName.ToLower()}"""); } - fw.WriteLine(indentLevel, column); + return column; } - private void WriteConvertAnnotation(JavaWriter fw, CompositionProperty property, int indentLevel, string tag) + private JavaAnnotation GetConvertAnnotation(CompositionProperty property, string tag) { - var javaOrJakarta = _config.PersistenceMode.ToString().ToLower(); - fw.AddImport($"{javaOrJakarta}.persistence.Convert"); - fw.AddImport(_config.CompositionConverterCanonicalName + var convert = new JavaAnnotation("Convert", $"{JavaxOrJakarta}.persistence.Convert"); + var import = _config.CompositionConverterCanonicalName .Replace("{class}", property.Composition.Name) - .Replace("{package}", _config.GetPackageName(property.Composition, _config.GetBestClassTag(property.Composition, tag)))); - fw.WriteLine(indentLevel, $"@Convert(converter = {_config.CompositionConverterSimpleName.Replace("{class}", property.Composition.Name)}.class)"); + .Replace("{package}", _config.GetPackageName(property.Composition, _config.GetBestClassTag(property.Composition, tag))); + convert.AddAttribute("converter", $"{_config.CompositionConverterSimpleName.Replace("{class}", property.Composition.Name)}.class", import); + return convert; } - private void WriteDomainAnnotations(JavaWriter fw, IProperty property, string tag, int indentLevel) + private IEnumerable GetDomainAnnotations(IProperty property, string tag) { foreach (var annotation in _config.GetDomainAnnotations(property, tag)) { - fw.WriteLine(indentLevel, $"{(annotation.StartsWith('@') ? string.Empty : '@')}{annotation}"); + yield return new JavaAnnotation(annotation.Annotation, annotation.Imports); } } - private void WriteIFieldProperty(JavaWriter fw, Class classe, IProperty property, string tag) + private string GetDefaultValue(IProperty property) { - var javaOrJakarta = _config.PersistenceMode.ToString().ToLower(); + if (property is AssociationProperty ap) + { + if (!_config.UseJdbc && ap.Association.PrimaryKey.Count() == 1 && _config.CanClassUseEnums(ap.Association, _classes, prop: ap.Association.PrimaryKey.Single())) + { + var defaultValue = _config.GetValue(property, _classes); + if (defaultValue != "null") + { + return $" = new {ap.Association.NamePascal}({defaultValue})"; + } + } - fw.WriteDocEnd(1); - if (property.PrimaryKey && classe.IsPersistent) + return string.Empty; + } + else { - WriteIdAnnotation(fw, classe, property); + var defaultValue = _config.GetValue(property, _classes); + var suffix = defaultValue != "null" ? $" = {defaultValue}" : string.Empty; + return suffix; } + } - if (ShouldWriteColumnAnnotation(classe, property) && (_config.UseJdbc || !(property.PrimaryKey && classe.PrimaryKey.Count() > 1))) + private IEnumerable GetDefaultValueImports(IProperty property, string tag) + { + if (property is AssociationProperty ap) { - WriteColumnAnnotation(fw, property, 1); + if (!_config.UseJdbc && ap.Association.PrimaryKey.Count() == 1 && _config.CanClassUseEnums(ap.Association, _classes, prop: ap.Association.PrimaryKey.Single())) + { + var defaultValue = _config.GetValue(property, _classes); + if (defaultValue != "null") + { + return [$"{_config.GetEnumPackageName(property.Class, _config.GetBestClassTag(property.Class, tag))}.{GetPropertyType(ap.Association.PrimaryKey.Single())}"]; + } + } + + return []; } + else + { + return _config.GetValueImports(property, tag); + } + } - if (property.Required && !property.PrimaryKey && (!classe.IsPersistent || _config.UseJdbc)) + private IEnumerable GetAnnotations(IProperty property) + { + if (property.PrimaryKey && property.Class.IsPersistent) { - WriteValidationAnnotations(fw, javaOrJakarta); + foreach (var a in GetIdAnnotations(property)) + { + yield return a; + } } - if (_config.CanClassUseEnums(classe) && property.PrimaryKey && !_config.UseJdbc) + if (ShouldWriteColumnAnnotation(property) && (_config.UseJdbc || !(property.PrimaryKey && property.Class.PrimaryKey.Count() > 1))) { - WriteEnumAnnotation(fw, javaOrJakarta); + yield return GetColumnAnnotation(property); } - if (!property.PrimaryKey || classe.PrimaryKey.Count() <= 1) + if (property.Required && !property.PrimaryKey && (!property.Class.IsPersistent || _config.UseJdbc)) { - WriteDomainAnnotations(fw, property, tag, 1); + yield return new JavaAnnotation("NotNull", $"{JavaxOrJakarta}.validation.constraints.NotNull"); } - var defaultValue = _config.GetValue(property, _classes); - var suffix = defaultValue != "null" ? $" = {defaultValue}" : string.Empty; - var isAssociationNotPersistent = property is AssociationProperty ap && !ap.Association.IsPersistent; - var useClassForAssociation = classe.IsPersistent && !isAssociationNotPersistent && !_config.UseJdbc; - fw.WriteLine(1, $"private {_config.GetType(property, useClassForAssociation: useClassForAssociation)} {(isAssociationNotPersistent ? property.NameCamel : property.NameByClassCamel)}{suffix};"); + if (_config.CanClassUseEnums(property.Class) && property.PrimaryKey && !_config.UseJdbc) + { + yield return GetEnumAnnotation(); + } } - private void WriteIdAnnotation(JavaWriter fw, Class classe, IProperty property) + private IEnumerable GetIdAnnotations(IProperty property) { - var javaOrJakarta = _config.PersistenceMode.ToString().ToLower(); + string idImport; if (!_config.UseJdbc) { - fw.AddImport($"{javaOrJakarta}.persistence.Id"); + idImport = $"{JavaxOrJakarta}.persistence.Id"; - if (property.Domain.AutoGeneratedValue && classe.PrimaryKey.Count() == 1) + if (property.Domain.AutoGeneratedValue && property.Class.PrimaryKey.Count() == 1) { - WriteAutogeneratedAnnotations(fw, classe, javaOrJakarta); + foreach (var a in GetAutogeneratedAnnotations(property.Class)) + { + yield return a; + } } } else { - fw.AddImport("org.springframework.data.annotation.Id"); + idImport = "org.springframework.data.annotation.Id"; } - fw.WriteLine(1, "@Id"); + yield return new JavaAnnotation("Id", idImport); } - private void WriteManyToManyAnnotations(JavaWriter fw, Class classe, AssociationProperty property, int indentLevel) + private IEnumerable GetManyToManyAnnotations(AssociationProperty property) { var role = property.Role is not null ? "_" + property.Role.ToConstantCase() : string.Empty; var fk = ((IProperty)property).SqlName; - var pk = classe.PrimaryKey.Single().SqlName + role; - var javaOrJakarta = _config.PersistenceMode.ToString().ToLower(); + var pk = property.Class.PrimaryKey.Single().SqlName + role; + var association = new JavaAnnotation($"{property.Type}", $"{JavaxOrJakarta}.persistence.{property.Type}") + .AddAttribute("fetch", "FetchType.LAZY", $"{JavaxOrJakarta}.persistence.FetchType"); if (!_config.CanClassUseEnums(property.Association)) { - fw.AddImport($"{javaOrJakarta}.persistence.CascadeType"); + association.AddAttribute("cascade", "{ CascadeType.PERSIST, CascadeType.MERGE }", $"{JavaxOrJakarta}.persistence.CascadeType"); } - var cascade = _config.CanClassUseEnums(property.Association) ? string.Empty : $", cascade = {{ CascadeType.PERSIST, CascadeType.MERGE }}"; if (property is ReverseAssociationProperty rap) { - fw.WriteLine(indentLevel, @$"@{property.Type}(fetch = FetchType.LAZY, mappedBy = ""{rap.ReverseProperty.NameByClassCamel}""{cascade})"); + association.AddAttribute("mappedBy", $@"""{rap.ReverseProperty.NameByClassCamel}"""); } - else + + yield return association; + + if (property is not ReverseAssociationProperty) { - fw.AddImport($"{javaOrJakarta}.persistence.JoinTable"); - fw.AddImport($"{javaOrJakarta}.persistence.JoinColumn"); - fw.WriteLine(indentLevel, @$"@{property.Type}(fetch = FetchType.LAZY{cascade})"); - fw.WriteLine(indentLevel, @$"@JoinTable(name = ""{property.Class.SqlName}_{property.Association.SqlName}{(property.Role != null ? "_" + property.Role.ToConstantCase() : string.Empty)}"", joinColumns = @JoinColumn(name = ""{pk}""), inverseJoinColumns = @JoinColumn(name = ""{fk}""))"); + var joinColumns = new JavaAnnotation("JoinColumn", $"{JavaxOrJakarta}.persistence.JoinColumn").AddAttribute("name", $@"""{pk}"""); + var inverseJoinColumns = new JavaAnnotation("JoinColumn", $"{JavaxOrJakarta}.persistence.JoinColumn").AddAttribute("name", $@"""{fk}"""); + var joinTable = new JavaAnnotation("JoinTable", $"{JavaxOrJakarta}.persistence.JoinTable") + .AddAttribute("name", $@"""{property.Class.SqlName}_{property.Association.SqlName}{(property.Role != null ? "_" + property.Role.ToConstantCase() : string.Empty)}""") + .AddAttribute("joinColumns", joinColumns) + .AddAttribute("inverseJoinColumns", inverseJoinColumns); + yield return joinTable; } } - private void WriteManyToOneAnnotations(JavaWriter fw, AssociationProperty property, int indentLevel) + private IEnumerable GetManyToOneAnnotations(AssociationProperty property, string tag) { + var association = new JavaAnnotation(@$"{property.Type}", $"{JavaxOrJakarta}.persistence.{property.Type}") + .AddAttribute("fetch", "FetchType.LAZY", $"{JavaxOrJakarta}.persistence.FetchType") + .AddAttribute("optional", property.Required ? "false" : "true") + .AddAttribute("targetEntity", $"{property.Association.NamePascal}.class", property.Association.GetImport(_config, _config.GetBestClassTag(property.Association, tag))); + yield return association; + var fk = ((IProperty)property).SqlName; var apk = property.Property.SqlName; - var javaOrJakarta = _config.PersistenceMode.ToString().ToLower(); - fw.WriteLine(indentLevel, @$"@{property.Type}(fetch = FetchType.LAZY, optional = {(property.Required ? "false" : "true")}, targetEntity = {property.Association.NamePascal}.class)"); - fw.WriteLine(indentLevel, @$"@JoinColumn(name = ""{fk}"", referencedColumnName = ""{apk}"")"); - fw.AddImport($"{javaOrJakarta}.persistence.JoinColumn"); + var joinColumn = new JavaAnnotation("JoinColumn", $"{JavaxOrJakarta}.persistence.JoinColumn") + .AddAttribute("name", $@"""{fk}""") + .AddAttribute("referencedColumnName", $@"""{apk}"""); + yield return joinColumn; } - private void WriteOneToManyAnnotations(JavaWriter fw, Class classe, AssociationProperty property, int indentLevel) + private IEnumerable GetOneToManyAnnotations(AssociationProperty property) { - var javaOrJakarta = _config.PersistenceMode.ToString().ToLower(); - fw.AddImport($"{javaOrJakarta}.persistence.CascadeType"); + var association = new JavaAnnotation(@$"{property.Type}", $"{JavaxOrJakarta}.persistence.{property.Type}"); if (property is ReverseAssociationProperty rap) { - fw.WriteLine(1, @$"@{property.Type}(cascade = {{CascadeType.PERSIST, CascadeType.MERGE}}, fetch = FetchType.LAZY, mappedBy = ""{rap.ReverseProperty.NameByClassCamel}"")"); + association + .AddAttribute("cascade", "{CascadeType.PERSIST, CascadeType.MERGE}", $"{JavaxOrJakarta}.persistence.CascadeType") + .AddAttribute("fetch", "FetchType.LAZY", $"{JavaxOrJakarta}.persistence.FetchType") + .AddAttribute("mappedBy", $@"""{rap.ReverseProperty.NameByClassCamel}"""); } else { - var pk = classe.PrimaryKey.Single().SqlName; + var pk = property.Class.PrimaryKey.Single().SqlName; var hasReverse = property.Class.Namespace.RootModule == property.Association.Namespace.RootModule; - fw.WriteLine(indentLevel, @$"@{property.Type}(cascade = CascadeType.ALL, fetch = FetchType.LAZY{(hasReverse ? @$", mappedBy = ""{property.Class.NameCamel}{property.Role ?? string.Empty}""" : string.Empty)})"); - if (!hasReverse) + + association + .AddAttribute("cascade", "CascadeType.ALL", $"{JavaxOrJakarta}.persistence.CascadeType") + .AddAttribute("fetch", "FetchType.LAZY", $"{JavaxOrJakarta}.persistence.FetchType"); + if (hasReverse) + { + association.AddAttribute("mappedBy", @$"""{property.Class.NameCamel}{property.Role ?? string.Empty}"""); + } + else { - fw.WriteLine(indentLevel, @$"@JoinColumn(name = ""{pk}"", referencedColumnName = ""{pk}"")"); - fw.AddImport($"{javaOrJakarta}.persistence.JoinColumn"); + var joinColumn = new JavaAnnotation("JoinColumn", $"{JavaxOrJakarta}.persistence.JoinColumn") + .AddAttribute("name", $@"""{pk}""") + .AddAttribute("referencedColumnName", $@"""{pk}"""); + yield return joinColumn; } } + + yield return association; } - private void WriteOneToOneAnnotations(JavaWriter fw, AssociationProperty property, int indentLevel) + private IEnumerable GetOneToOneAnnotations(AssociationProperty property) { var fk = ((IProperty)property).SqlName; var apk = property.Property.SqlName; - var javaOrJakarta = _config.PersistenceMode.ToString().ToLower(); - fw.AddImport($"{javaOrJakarta}.persistence.CascadeType"); - fw.WriteLine(indentLevel, @$"@{property.Type}(fetch = FetchType.LAZY, cascade = CascadeType.ALL, optional = {(!property.Required).ToString().ToLower()})"); - fw.WriteLine(indentLevel, @$"@JoinColumn(name = ""{fk}"", referencedColumnName = ""{apk}"", unique = true)"); - fw.AddImport($"{javaOrJakarta}.persistence.JoinColumn"); + var association = new JavaAnnotation(@$"{property.Type}", $"{JavaxOrJakarta}.persistence.{property.Type}") + .AddAttribute("fetch", "FetchType.LAZY", $"{JavaxOrJakarta}.persistence.FetchType") + .AddAttribute("cascade", @"CascadeType.ALL", $"{JavaxOrJakarta}.persistence.CascadeType") + .AddAttribute("optional", (!property.Required).ToString().ToLower()); + yield return association; + + var joinColumn = new JavaAnnotation("JoinColumn", $"{JavaxOrJakarta}.persistence.JoinColumn") + .AddAttribute("name", $@"""{fk}""") + .AddAttribute("referencedColumnName", $@"""{apk}""") + .AddAttribute("unique", "true"); + yield return joinColumn; } } diff --git a/TopModel.Generator.Jpa/SpringClientApiGenerator.cs b/TopModel.Generator.Jpa/SpringClientApiGenerator.cs index 3d8712c9..8c004c5e 100644 --- a/TopModel.Generator.Jpa/SpringClientApiGenerator.cs +++ b/TopModel.Generator.Jpa/SpringClientApiGenerator.cs @@ -45,10 +45,10 @@ protected override void HandleFile(string filePath, string fileName, string tag, fw.AddImport("org.springframework.web.service.annotation.HttpExchange"); } - var javaOrJakarta = Config.PersistenceMode.ToString().ToLower(); + var javaxOrJakarta = Config.PersistenceMode.ToString().ToLower(); if (Config.GeneratedHint) { - fw.AddImport($"{javaOrJakarta}.annotation.Generated"); + fw.AddImport($"{javaxOrJakarta}.annotation.Generated"); fw.WriteLine("@Generated(\"TopModel : https://github.com/klee-contrib/topmodel\")"); } @@ -131,7 +131,7 @@ private void WriteEndpoint(JavaWriter fw, Endpoint endpoint, string tag) fw.AddImport("org.springframework.web.bind.annotation.PathVariable"); fw.AddImports(Config.GetDomainImports(param, tag)); - var decoratorAnnotations = string.Join(' ', Config.GetDomainAnnotations(param, tag).Select(a => a.StartsWith("@") ? a : "@" + a)); + var decoratorAnnotations = string.Join(' ', Config.GetDomainAnnotations(param, tag).Select(a => a.Annotation).Select(a => a.StartsWith("@") ? a : "@" + a)); methodParams.Add($"{pathParamAnnotation}{(decoratorAnnotations.Length > 0 ? $" {decoratorAnnotations}" : string.Empty)} {Config.GetType(param)} {param.GetParamName()}"); } @@ -141,7 +141,7 @@ private void WriteEndpoint(JavaWriter fw, Endpoint endpoint, string tag) ann += @$"@RequestParam(value = ""{param.GetParamName()}"", required = {param.Required.ToString().ToFirstLower()}) "; fw.AddImport("org.springframework.web.bind.annotation.RequestParam"); fw.AddImports(Config.GetDomainImports(param, tag)); - var decoratorAnnotations = string.Join(' ', Config.GetDomainAnnotations(param, tag).Select(a => a.StartsWith("@") ? a : "@" + a)); + var decoratorAnnotations = string.Join(' ', Config.GetDomainAnnotations(param, tag).Select(a => a.Annotation).Select(a => a.StartsWith("@") ? a : "@" + a)); methodParams.Add($"{ann}{(decoratorAnnotations.Length > 0 ? $" {decoratorAnnotations}" : string.Empty)}{Config.GetType(param)} {param.GetParamName()}"); } diff --git a/TopModel.Generator.Jpa/SpringDataFlowGenerator.cs b/TopModel.Generator.Jpa/SpringDataFlowGenerator.cs index c27a9b20..3d7d07e6 100644 --- a/TopModel.Generator.Jpa/SpringDataFlowGenerator.cs +++ b/TopModel.Generator.Jpa/SpringDataFlowGenerator.cs @@ -303,10 +303,10 @@ private void WriteClassFlow(string fileName, DataFlow dataFlow, string tag) fw.AddImport("org.springframework.context.annotation.Configuration"); fw.WriteLine(); fw.WriteLine("@Configuration"); - var javaOrJakarta = Config.PersistenceMode.ToString().ToLower(); + var javaxOrJakarta = Config.PersistenceMode.ToString().ToLower(); if (Config.GeneratedHint) { - fw.AddImport($"{javaOrJakarta}.annotation.Generated"); + fw.AddImport($"{javaxOrJakarta}.annotation.Generated"); fw.WriteLine("@Generated(\"TopModel : https://github.com/klee-contrib/topmodel\")"); } @@ -352,10 +352,10 @@ private void WriteModuleConfig(string module, IEnumerable flows) fw.AddImport("org.springframework.context.annotation.Import"); fw.WriteLine(); fw.WriteLine("@Configuration"); - var javaOrJakarta = Config.PersistenceMode.ToString().ToLower(); + var javaxOrJakarta = Config.PersistenceMode.ToString().ToLower(); if (Config.GeneratedHint) { - fw.AddImport($"{javaOrJakarta}.annotation.Generated"); + fw.AddImport($"{javaxOrJakarta}.annotation.Generated"); fw.WriteLine("@Generated(\"TopModel : https://github.com/klee-contrib/topmodel\")"); } diff --git a/TopModel.Generator.Jpa/SpringRestTemplateApiGenerator.cs b/TopModel.Generator.Jpa/SpringRestTemplateApiGenerator.cs index ce3896c4..64deb093 100644 --- a/TopModel.Generator.Jpa/SpringRestTemplateApiGenerator.cs +++ b/TopModel.Generator.Jpa/SpringRestTemplateApiGenerator.cs @@ -40,10 +40,10 @@ protected override void HandleFile(string filePath, string fileName, string tag, WriteImports(endpoints, fw, tag); fw.WriteLine(); - var javaOrJakarta = Config.PersistenceMode.ToString().ToLower(); + var javaxOrJakarta = Config.PersistenceMode.ToString().ToLower(); if (Config.GeneratedHint) { - fw.AddImport($"{javaOrJakarta}.annotation.Generated"); + fw.AddImport($"{javaxOrJakarta}.annotation.Generated"); fw.WriteLine("@Generated(\"TopModel : https://github.com/klee-contrib/topmodel\")"); } diff --git a/TopModel.Generator.Jpa/SpringServerApiGenerator.cs b/TopModel.Generator.Jpa/SpringServerApiGenerator.cs index 5cea13d5..5fd274ba 100644 --- a/TopModel.Generator.Jpa/SpringServerApiGenerator.cs +++ b/TopModel.Generator.Jpa/SpringServerApiGenerator.cs @@ -45,10 +45,10 @@ protected override void HandleFile(string filePath, string fileName, string tag, fw.AddImport("org.springframework.web.bind.annotation.RequestMapping"); } - var javaOrJakarta = Config.PersistenceMode.ToString().ToLower(); + var javaxOrJakarta = Config.PersistenceMode.ToString().ToLower(); if (Config.GeneratedHint) { - fw.AddImport($"{javaOrJakarta}.annotation.Generated"); + fw.AddImport($"{javaxOrJakarta}.annotation.Generated"); fw.WriteLine("@Generated(\"TopModel : https://github.com/klee-contrib/topmodel\")"); } @@ -136,7 +136,7 @@ private void WriteEndpoint(JavaWriter fw, Endpoint endpoint, string tag) fw.AddImport("org.springframework.web.bind.annotation.PathVariable"); fw.AddImports(Config.GetDomainImports(param, tag)); - var decoratorAnnotations = string.Join(' ', Config.GetDomainAnnotations(param, tag).Select(a => a.StartsWith('@') ? a : "@" + a)); + var decoratorAnnotations = string.Join(' ', Config.GetDomainAnnotations(param, tag).Select(a => a.Annotation).Select(a => a.StartsWith('@') ? a : "@" + a)); methodParams.Add($"{(pathParamAnnotation.Length > 0 ? $"{pathParamAnnotation} " : string.Empty)}{(decoratorAnnotations.Length > 0 ? $"{decoratorAnnotations} " : string.Empty)}{Config.GetType(param)} {param.GetParamName()}"); } @@ -146,7 +146,7 @@ private void WriteEndpoint(JavaWriter fw, Endpoint endpoint, string tag) ann += @$"@RequestParam(value = ""{param.GetParamName()}"", required = {param.Required.ToString().ToFirstLower()}) "; fw.AddImport("org.springframework.web.bind.annotation.RequestParam"); fw.AddImports(Config.GetDomainImports(param, tag)); - var decoratorAnnotations = string.Join(' ', Config.GetDomainAnnotations(param, tag).Select(a => a.StartsWith("@") ? a : "@" + a)); + var decoratorAnnotations = string.Join(' ', Config.GetDomainAnnotations(param, tag).Select(a => a.Annotation).Select(a => a.StartsWith("@") ? a : "@" + a)); methodParams.Add($"{ann}{(decoratorAnnotations.Length > 0 ? $" {decoratorAnnotations}" : string.Empty)}{Config.GetType(param)} {param.GetParamName()}"); } diff --git a/TopModel.Generator.Jpa/jpa.config.json b/TopModel.Generator.Jpa/jpa.config.json index 03a63598..785f6299 100644 --- a/TopModel.Generator.Jpa/jpa.config.json +++ b/TopModel.Generator.Jpa/jpa.config.json @@ -180,11 +180,6 @@ "type": "string", "description": "Nom du schéma sur lequel les entités sont sauvegardées" }, - "enumShortcutMode": { - "type": "boolean", - "description": "Option pour générer des getters et setters vers l'enum des références plutôt que sur la table", - "default": "false" - }, "associationAdders": { "type": "boolean", "description": "Option pour générer des méthodes d'ajouts pour les associations oneToMany et manyToMany. Ces méthodes permettent de synchroniser les objets ajoutés", diff --git a/TopModel.Generator.Php/PhpModelPropertyGenerator.cs b/TopModel.Generator.Php/PhpModelPropertyGenerator.cs index 6282a62b..eda2ce10 100644 --- a/TopModel.Generator.Php/PhpModelPropertyGenerator.cs +++ b/TopModel.Generator.Php/PhpModelPropertyGenerator.cs @@ -184,7 +184,7 @@ private void WriteRegularProperty(PhpWriter fw, Class classe, IProperty property foreach (var annotation in _config.GetDomainAnnotations(property, tag)) { - fw.WriteLine(1, annotation); + fw.WriteLine(1, annotation.Annotation); } var defaultValue = _config.GetValue(property, _classes); diff --git a/docs/generator/jpa.md b/docs/generator/jpa.md index 109a975d..9921000d 100644 --- a/docs/generator/jpa.md +++ b/docs/generator/jpa.md @@ -98,30 +98,6 @@ Par ailleurs, si la classe possède une association avec une classe qui contient Cette `enum` possède les différents attributs de la classe. Elle définit également une méthode `getEntity`, qui renvoit l'instance de la classe de référence correspondante. -##### EnumShortcutMode - -Il peut être laborieux de toujours passer par la classe de référence lorsqu'on ne manipule le plus souvent que leurs clés primaires. CTopModel - JPA permet de créer des raccoucis pour rendre cette approche possible. Si la configuration `enumShortcutMode` est activée : - -```yaml -enumShortcutMode: true -``` - -Alors les getters et setters des références statiques ne considèreront plus le type de la table de référence, mais uniquement celui de sa clé primaire. - -Exemple : - -```java - private TypeUtilisateur.Values getTypeUtilisateurCode() { - return this.typeUtilisateur.getCode(); - } - - private void setTypeUtilisateurCode(TypeUtilisateur.Values typeUtilisateurCode) { - this.typeUtilisateur = new TypeUtilisateur(typeUtilisateurCode, typeUtilisateurCode.getLibelle()); - } -``` - -En effet, pour les références dont toutes les valeurs sont connues à l'avance et identifiées par un code, celui-ci est beaucoup plus utilisé dans le code java. L'existence de la table correspondante en base de donnée n'est utile que pour la création d'une contrainte de valeur sur les tables qui la référencent. - #### Classes non persistées Les classes non persistées sont générées de la même manière que les classes persistées, mais ne reçoivent pas les annotations JPA. @@ -617,10 +593,6 @@ Le générateur créé un fichier de configuration de job par module. Ce job ord _Variables par tag_: **non** -- `enumShortcutMode` - - Option pour générer des getters et setters vers l'enum des références plutôt que sur la table - - `fieldsEnum` Option pour générer une enum des champs de certaines classes. Les valeurs possibles sont : diff --git a/samples/generators/jpa/src/main/javagen/topmodel/jpa/sample/demo/dtos/securite/profil/ProfilRead.java b/samples/generators/jpa/src/main/javagen/topmodel/jpa/sample/demo/dtos/securite/profil/ProfilRead.java index 84312ad0..7282cf96 100644 --- a/samples/generators/jpa/src/main/javagen/topmodel/jpa/sample/demo/dtos/securite/profil/ProfilRead.java +++ b/samples/generators/jpa/src/main/javagen/topmodel/jpa/sample/demo/dtos/securite/profil/ProfilRead.java @@ -192,9 +192,9 @@ public enum Fields { DATE_MODIFICATION(LocalDateTime.class), // UTILISATEURS(List.class); - private Class type; + private final Class type; - private Fields(Class type) { + Fields(Class type) { this.type = type; } diff --git a/samples/generators/jpa/src/main/javagen/topmodel/jpa/sample/demo/dtos/securite/profil/ProfilWrite.java b/samples/generators/jpa/src/main/javagen/topmodel/jpa/sample/demo/dtos/securite/profil/ProfilWrite.java index fa524c0a..53f62957 100644 --- a/samples/generators/jpa/src/main/javagen/topmodel/jpa/sample/demo/dtos/securite/profil/ProfilWrite.java +++ b/samples/generators/jpa/src/main/javagen/topmodel/jpa/sample/demo/dtos/securite/profil/ProfilWrite.java @@ -86,9 +86,9 @@ public enum Fields { LIBELLE(String.class), // DROITS(List.class); - private Class type; + private final Class type; - private Fields(Class type) { + Fields(Class type) { this.type = type; } diff --git a/samples/generators/jpa/src/main/javagen/topmodel/jpa/sample/demo/dtos/securite/utilisateur/UtilisateurRead.java b/samples/generators/jpa/src/main/javagen/topmodel/jpa/sample/demo/dtos/securite/utilisateur/UtilisateurRead.java index f4a86f6c..99a95c9e 100644 --- a/samples/generators/jpa/src/main/javagen/topmodel/jpa/sample/demo/dtos/securite/utilisateur/UtilisateurRead.java +++ b/samples/generators/jpa/src/main/javagen/topmodel/jpa/sample/demo/dtos/securite/utilisateur/UtilisateurRead.java @@ -49,8 +49,8 @@ public class UtilisateurRead implements Serializable { * Email de l'utilisateur. * Alias of {@link topmodel.jpa.sample.demo.entities.securite.utilisateur.Utilisateur#getEmail() Utilisateur#getEmail()} */ - @NotNull @Email + @NotNull private String email; /** @@ -74,14 +74,14 @@ public class UtilisateurRead implements Serializable { /** * Profil de l'utilisateur. - * Alias of {@link topmodel.jpa.sample.demo.entities.securite.utilisateur.Utilisateur#getProfilId() Utilisateur#getProfilId()} + * Alias of {@link topmodel.jpa.sample.demo.entities.securite.utilisateur.Utilisateur#getProfil() Utilisateur#getProfil()} */ @NotNull private Integer profilId; /** * Type d'utilisateur. - * Alias of {@link topmodel.jpa.sample.demo.entities.securite.utilisateur.Utilisateur#getTypeUtilisateurCode() Utilisateur#getTypeUtilisateurCode()} + * Alias of {@link topmodel.jpa.sample.demo.entities.securite.utilisateur.Utilisateur#getTypeUtilisateur() Utilisateur#getTypeUtilisateur()} */ @NotNull private TypeUtilisateurCode typeUtilisateurCode = TypeUtilisateurCode.GEST; @@ -319,9 +319,9 @@ public enum Fields { DATE_CREATION(LocalDateTime.class), // DATE_MODIFICATION(LocalDateTime.class); - private Class type; + private final Class type; - private Fields(Class type) { + Fields(Class type) { this.type = type; } diff --git a/samples/generators/jpa/src/main/javagen/topmodel/jpa/sample/demo/dtos/securite/utilisateur/UtilisateurWrite.java b/samples/generators/jpa/src/main/javagen/topmodel/jpa/sample/demo/dtos/securite/utilisateur/UtilisateurWrite.java index ff8f04df..e95b78c9 100644 --- a/samples/generators/jpa/src/main/javagen/topmodel/jpa/sample/demo/dtos/securite/utilisateur/UtilisateurWrite.java +++ b/samples/generators/jpa/src/main/javagen/topmodel/jpa/sample/demo/dtos/securite/utilisateur/UtilisateurWrite.java @@ -41,8 +41,8 @@ public class UtilisateurWrite implements Serializable { * Email de l'utilisateur. * Alias of {@link topmodel.jpa.sample.demo.entities.securite.utilisateur.Utilisateur#getEmail() Utilisateur#getEmail()} */ - @NotNull @Email + @NotNull private String email; /** @@ -66,14 +66,14 @@ public class UtilisateurWrite implements Serializable { /** * Profil de l'utilisateur. - * Alias of {@link topmodel.jpa.sample.demo.entities.securite.utilisateur.Utilisateur#getProfilId() Utilisateur#getProfilId()} + * Alias of {@link topmodel.jpa.sample.demo.entities.securite.utilisateur.Utilisateur#getProfil() Utilisateur#getProfil()} */ @NotNull private Integer profilId; /** * Type d'utilisateur. - * Alias of {@link topmodel.jpa.sample.demo.entities.securite.utilisateur.Utilisateur#getTypeUtilisateurCode() Utilisateur#getTypeUtilisateurCode()} + * Alias of {@link topmodel.jpa.sample.demo.entities.securite.utilisateur.Utilisateur#getTypeUtilisateur() Utilisateur#getTypeUtilisateur()} */ @NotNull private TypeUtilisateurCode typeUtilisateurCode = TypeUtilisateurCode.GEST; @@ -237,9 +237,9 @@ public enum Fields { PROFIL_ID(Integer.class), // TYPE_UTILISATEUR_CODE(TypeUtilisateurCode.class); - private Class type; + private final Class type; - private Fields(Class type) { + Fields(Class type) { this.type = type; } diff --git a/samples/generators/jpa/src/main/javagen/topmodel/jpa/sample/demo/entities/securite/profil/Droit.java b/samples/generators/jpa/src/main/javagen/topmodel/jpa/sample/demo/entities/securite/profil/Droit.java index a2f2ce67..539cda59 100644 --- a/samples/generators/jpa/src/main/javagen/topmodel/jpa/sample/demo/entities/securite/profil/Droit.java +++ b/samples/generators/jpa/src/main/javagen/topmodel/jpa/sample/demo/entities/securite/profil/Droit.java @@ -130,9 +130,9 @@ public enum Fields { LIBELLE(String.class), // TYPE_DROIT(TypeDroit.class); - private Class type; + private final Class type; - private Fields(Class type) { + Fields(Class type) { this.type = type; } diff --git a/samples/generators/jpa/src/main/javagen/topmodel/jpa/sample/demo/entities/securite/profil/Profil.java b/samples/generators/jpa/src/main/javagen/topmodel/jpa/sample/demo/entities/securite/profil/Profil.java index b57b1972..c1f39acb 100644 --- a/samples/generators/jpa/src/main/javagen/topmodel/jpa/sample/demo/entities/securite/profil/Profil.java +++ b/samples/generators/jpa/src/main/javagen/topmodel/jpa/sample/demo/entities/securite/profil/Profil.java @@ -34,9 +34,9 @@ * Profil des utilisateurs. */ @Generated("TopModel : https://github.com/klee-contrib/topmodel") +@EntityListeners(AuditingEntityListener.class) @Entity @Table(name = "PROFIL") -@EntityListeners(AuditingEntityListener.class) public class Profil { /** @@ -64,15 +64,15 @@ public class Profil { /** * Date de création de l'utilisateur. */ - @Column(name = "PRO_DATE_CREATION", nullable = false, columnDefinition = "date") @CreatedDate + @Column(name = "PRO_DATE_CREATION", nullable = false, columnDefinition = "date") private LocalDateTime dateCreation = LocalDateTime.now(); /** * Date de modification de l'utilisateur. */ - @Column(name = "PRO_DATE_MODIFICATION", columnDefinition = "date") @LastModifiedDate + @Column(name = "PRO_DATE_MODIFICATION", columnDefinition = "date") private LocalDateTime dateModification = LocalDateTime.now(); /** @@ -207,9 +207,9 @@ public enum Fields { DATE_MODIFICATION(LocalDateTime.class), // UTILISATEURS(Utilisateur.class); - private Class type; + private final Class type; - private Fields(Class type) { + Fields(Class type) { this.type = type; } diff --git a/samples/generators/jpa/src/main/javagen/topmodel/jpa/sample/demo/entities/securite/profil/TypeDroit.java b/samples/generators/jpa/src/main/javagen/topmodel/jpa/sample/demo/entities/securite/profil/TypeDroit.java index 5f11c138..456c2a18 100644 --- a/samples/generators/jpa/src/main/javagen/topmodel/jpa/sample/demo/entities/securite/profil/TypeDroit.java +++ b/samples/generators/jpa/src/main/javagen/topmodel/jpa/sample/demo/entities/securite/profil/TypeDroit.java @@ -101,9 +101,9 @@ public enum Fields { CODE(TypeDroitCode.class), // LIBELLE(String.class); - private Class type; + private final Class type; - private Fields(Class type) { + Fields(Class type) { this.type = type; } diff --git a/samples/generators/jpa/src/main/javagen/topmodel/jpa/sample/demo/entities/securite/utilisateur/TypeUtilisateur.java b/samples/generators/jpa/src/main/javagen/topmodel/jpa/sample/demo/entities/securite/utilisateur/TypeUtilisateur.java index 945d5045..9e6e3807 100644 --- a/samples/generators/jpa/src/main/javagen/topmodel/jpa/sample/demo/entities/securite/utilisateur/TypeUtilisateur.java +++ b/samples/generators/jpa/src/main/javagen/topmodel/jpa/sample/demo/entities/securite/utilisateur/TypeUtilisateur.java @@ -101,9 +101,9 @@ public enum Fields { CODE(TypeUtilisateurCode.class), // LIBELLE(String.class); - private Class type; + private final Class type; - private Fields(Class type) { + Fields(Class type) { this.type = type; } diff --git a/samples/generators/jpa/src/main/javagen/topmodel/jpa/sample/demo/entities/securite/utilisateur/Utilisateur.java b/samples/generators/jpa/src/main/javagen/topmodel/jpa/sample/demo/entities/securite/utilisateur/Utilisateur.java index 0c268563..8c7facaa 100644 --- a/samples/generators/jpa/src/main/javagen/topmodel/jpa/sample/demo/entities/securite/utilisateur/Utilisateur.java +++ b/samples/generators/jpa/src/main/javagen/topmodel/jpa/sample/demo/entities/securite/utilisateur/Utilisateur.java @@ -31,10 +31,10 @@ * Utilisateur de l'application. */ @Generated("TopModel : https://github.com/klee-contrib/topmodel") +@EntityListeners(AuditingEntityListener.class) @Entity @Table(name = "UTILISATEUR", uniqueConstraints = { @UniqueConstraint(columnNames = {"UTI_EMAIL"})}) -@EntityListeners(AuditingEntityListener.class) public class Utilisateur { /** @@ -98,15 +98,15 @@ public class Utilisateur { /** * Date de création de l'utilisateur. */ - @Column(name = "UTI_DATE_CREATION", nullable = false, columnDefinition = "date") @CreatedDate + @Column(name = "UTI_DATE_CREATION", nullable = false, columnDefinition = "date") private LocalDateTime dateCreation = LocalDateTime.now(); /** * Date de modification de l'utilisateur. */ - @Column(name = "UTI_DATE_MODIFICATION", columnDefinition = "date") @LastModifiedDate + @Column(name = "UTI_DATE_MODIFICATION", columnDefinition = "date") private LocalDateTime dateModification = LocalDateTime.now(); /** @@ -312,9 +312,9 @@ public enum Fields { DATE_CREATION(LocalDateTime.class), // DATE_MODIFICATION(LocalDateTime.class); - private Class type; + private final Class type; - private Fields(Class type) { + Fields(Class type) { this.type = type; } diff --git a/samples/generators/jpa/topmodel.config b/samples/generators/jpa/topmodel.config index 6a02b809..50b8cc01 100644 --- a/samples/generators/jpa/topmodel.config +++ b/samples/generators/jpa/topmodel.config @@ -24,7 +24,6 @@ jpa: apiGeneration: "{apiGeneration}" resourcesPath: resources/i18n/model fieldsEnum: Persisted_Dto - enumShortcutMode: false persistenceMode: jakarta daosInterface: topmodel.jpa.sample.demo.daos.repository.CustomCrudRepository daosAbstract: true diff --git a/samples/generators/jpa/topmodel.config.schema.json b/samples/generators/jpa/topmodel.config.schema.json index a98480cc..dac5defb 100644 --- a/samples/generators/jpa/topmodel.config.schema.json +++ b/samples/generators/jpa/topmodel.config.schema.json @@ -285,11 +285,6 @@ "type": "string", "description": "Nom du schéma sur lequel les entités sont sauvegardées" }, - "enumShortcutMode": { - "type": "boolean", - "description": "Option pour générer des getters et setters vers l'enum des références plutôt que sur la table", - "default": "false" - }, "associationAdders": { "type": "boolean", "description": "Option pour générer des méthodes d'ajouts pour les associations oneToMany et manyToMany. Ces méthodes permettent de synchroniser les objets ajoutés", diff --git a/samples/model/jpa.topmodel.lock b/samples/model/jpa.topmodel.lock index a6e99daa..dbfe8c5d 100644 --- a/samples/model/jpa.topmodel.lock +++ b/samples/model/jpa.topmodel.lock @@ -4,7 +4,7 @@ version: 2.1.3 custom: - ../../../TopModel.Generator.Jpa: b7b41bad6aa1f4963dda4549de26efcd + ../../../TopModel.Generator.Jpa: 0335b3f662fbe0264e7b12e38b2f8b3e generatedFiles: - ../generators/jpa/src/main/javagen/topmodel/jpa/sample/demo/api/client/securite/profil/ProfilClient.java - ../generators/jpa/src/main/javagen/topmodel/jpa/sample/demo/api/client/securite/utilisateur/UtilisateurClient.java From 378d5f8e24379ee2946a5e093cb7a01f3448043e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gild=C3=A9ric=20DERUETTE?= Date: Fri, 29 Nov 2024 08:49:01 +0100 Subject: [PATCH 2/5] Refacto GetDomainImports --- TopModel.Generator.Core/GeneratorConfigBase.cs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/TopModel.Generator.Core/GeneratorConfigBase.cs b/TopModel.Generator.Core/GeneratorConfigBase.cs index 3e7ed45b..1326984b 100644 --- a/TopModel.Generator.Core/GeneratorConfigBase.cs +++ b/TopModel.Generator.Core/GeneratorConfigBase.cs @@ -205,10 +205,7 @@ public IEnumerable GetDomainImports(IProperty property, string tag) yield return import; } - foreach (var import in GetImplementation(property.Domain)!.Annotations - .Where(a => FilterAnnotations(a, property, tag)) - .SelectMany(a => a.Imports) - .Select(u => u.ParseTemplate(property, this, tag))) + foreach (var import in GetDomainAnnotations(property, tag).SelectMany(a => a.Imports)) { yield return import; } From 8796f18cf69baa4cb926ba0abf7e5ba95ee38c26 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gild=C3=A9ric=20DERUETTE?= Date: Fri, 29 Nov 2024 11:27:51 +0100 Subject: [PATCH 3/5] Correction lock c# --- TopModel.Generator.Jpa/JpaEntityGenerator.cs | 1 - TopModel.Generator.Jpa/JpaModelPropertyGenerator.cs | 2 +- samples/model/csharp.topmodel.lock | 2 +- samples/model/jpa.topmodel.lock | 2 +- 4 files changed, 3 insertions(+), 4 deletions(-) diff --git a/TopModel.Generator.Jpa/JpaEntityGenerator.cs b/TopModel.Generator.Jpa/JpaEntityGenerator.cs index c58ff9ea..41cc526e 100644 --- a/TopModel.Generator.Jpa/JpaEntityGenerator.cs +++ b/TopModel.Generator.Jpa/JpaEntityGenerator.cs @@ -2,7 +2,6 @@ using TopModel.Core; using TopModel.Core.Model.Implementation; using TopModel.Generator.Core; -using TopModel.Utils; namespace TopModel.Generator.Jpa; diff --git a/TopModel.Generator.Jpa/JpaModelPropertyGenerator.cs b/TopModel.Generator.Jpa/JpaModelPropertyGenerator.cs index fd7fd659..1334435c 100644 --- a/TopModel.Generator.Jpa/JpaModelPropertyGenerator.cs +++ b/TopModel.Generator.Jpa/JpaModelPropertyGenerator.cs @@ -163,7 +163,7 @@ public void WriteProperty(JavaWriter fw, IProperty property, string tag) fw.WriteAnnotations(1, annotations); string defaultValue = GetDefaultValue(property); fw.AddImports(GetDefaultValueImports(property, tag)); - fw.WriteLine(1, $"private {GetPropertyType(property)} {GetPropertyName(property)}{defaultValue};"); ; + fw.WriteLine(1, $"private {GetPropertyType(property)} {GetPropertyName(property)}{defaultValue};"); } public void WriteSetter(JavaWriter fw, string tag, IProperty property, int indentLevel = 1) diff --git a/samples/model/csharp.topmodel.lock b/samples/model/csharp.topmodel.lock index 629796b7..29e41363 100644 --- a/samples/model/csharp.topmodel.lock +++ b/samples/model/csharp.topmodel.lock @@ -4,7 +4,7 @@ version: 2.1.3 custom: - ../../../TopModel.Generator.Csharp: 1f47b333bf3d8c8acce3ee5d40956cc9 + ../../../TopModel.Generator.Csharp: 31ed4ff61fbd77556e82c0834df6afc4 generatedFiles: - ../generators/csharp/src/Clients/CSharp.Clients.Db/generated/CSharpDbContext.comments.cs - ../generators/csharp/src/Clients/CSharp.Clients.Db/generated/CSharpDbContext.cs diff --git a/samples/model/jpa.topmodel.lock b/samples/model/jpa.topmodel.lock index dbfe8c5d..ac950275 100644 --- a/samples/model/jpa.topmodel.lock +++ b/samples/model/jpa.topmodel.lock @@ -4,7 +4,7 @@ version: 2.1.3 custom: - ../../../TopModel.Generator.Jpa: 0335b3f662fbe0264e7b12e38b2f8b3e + ../../../TopModel.Generator.Jpa: 92a0e54adbe0afae0ea6eb16ff619f46 generatedFiles: - ../generators/jpa/src/main/javagen/topmodel/jpa/sample/demo/api/client/securite/profil/ProfilClient.java - ../generators/jpa/src/main/javagen/topmodel/jpa/sample/demo/api/client/securite/utilisateur/UtilisateurClient.java From e0867dd0171fe3d8b079efffa982842421f18004 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gild=C3=A9ric=20DERUETTE?= Date: Fri, 29 Nov 2024 11:34:04 +0100 Subject: [PATCH 4/5] Update actions github --- .github/workflows/check.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml index a9f66967..30a488b7 100644 --- a/.github/workflows/check.yml +++ b/.github/workflows/check.yml @@ -19,13 +19,13 @@ jobs: dotnet-version: 9.0.x - name: build - run: dotnet build -f net8.0 + run: dotnet build -f net9.0 - name: modgen - run: dotnet run --project TopModel.Generator/TopModel.Generator.csproj -f net8.0 -- -c + run: dotnet run --project TopModel.Generator/TopModel.Generator.csproj -f net9.0 -- -c - name: tmdgen - run: dotnet run --project TopModel.ModelGenerator/TopModel.ModelGenerator.csproj -f net8.0 -- -f samples/generators/open-api/tmdgen.config -c + run: dotnet run --project TopModel.ModelGenerator/TopModel.ModelGenerator.csproj -f net9.0 -- -f samples/generators/open-api/tmdgen.config -c - name: Set up JDK 21 uses: actions/setup-java@v4 From 9e803803b3af7c35fe6634a009988efd865e8612 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gild=C3=A9ric=20DERUETTE?= Date: Tue, 3 Dec 2024 15:35:00 +0100 Subject: [PATCH 5/5] Fix Action --- samples/model/php.topmodel.lock | 2 +- samples/modgen.bat | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/samples/model/php.topmodel.lock b/samples/model/php.topmodel.lock index 7b08b827..229a1357 100644 --- a/samples/model/php.topmodel.lock +++ b/samples/model/php.topmodel.lock @@ -4,7 +4,7 @@ version: 2.1.3 custom: - ../../../TopModel.Generator.Php: 8029e36a5806c385b25b725c2e00ecdc + ../../../TopModel.Generator.Php: 3c169097a8296afcf9c40ff520e7a2bf generatedFiles: - ../generators/php/src/Entity/Securite/Profil/Droit.php - ../generators/php/src/Entity/Securite/Profil/Profil.php diff --git a/samples/modgen.bat b/samples/modgen.bat index 60f0ff01..2d8dbb74 100644 --- a/samples/modgen.bat +++ b/samples/modgen.bat @@ -1,2 +1,2 @@ @REM dotnet run --project ../TopModel.ModelGenerator -f net8.0 -dotnet run --project ../TopModel.Generator -f net8.0 \ No newline at end of file +dotnet run --project ../TopModel.Generator -f net9.0 \ No newline at end of file