From 35e043e4dfcafa4196d1e6568609843ac2683f88 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gild=C3=A9ric=20Deruette?= Date: Thu, 16 Nov 2023 16:11:37 +0100 Subject: [PATCH] =?UTF-8?q?[tmdgen]=20Refonte=20du=20OpenApiGenerator=20su?= =?UTF-8?q?r=20le=20mod=C3=A8le=20du=20DatabaseGenerator=20Cr=C3=A9ation?= =?UTF-8?q?=20d'alias=20dans=20plus=20de=20cas=20Fixes=20#304?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../SpringClientApiGenerator.cs | 2 +- .../Database/DatabaseTmdGenerator.cs | 17 +- .../OpenApi/OpenApiTmdGenerator.cs | 403 +++++++++++++----- .../OpenApi/OpenApiUtils.cs | 5 +- TopModel.ModelGenerator/TmdAliasProperty.cs | 13 + .../TmdAssociationProperty.cs | 8 +- TopModel.ModelGenerator/TmdClass.cs | 8 +- .../TmdCompositionProperty.cs | 10 + TopModel.ModelGenerator/TmdEndpoint.cs | 29 ++ TopModel.ModelGenerator/TmdFile.cs | 4 +- TopModel.ModelGenerator/TmdProperty.cs | 10 +- TopModel.ModelGenerator/TmdRegularProperty.cs | 11 + TopModel.ModelGenerator/TmdWriter.cs | 236 +++++++--- .../generators/open-api/Petstore/Model.tmd | 105 ++--- samples/generators/open-api/Petstore/Pet.tmd | 57 ++- .../generators/open-api/Petstore/Store.tmd | 27 +- samples/generators/open-api/Petstore/User.tmd | 42 +- .../php/topmodel.config.schema.json | 12 +- 18 files changed, 708 insertions(+), 291 deletions(-) create mode 100644 TopModel.ModelGenerator/TmdAliasProperty.cs create mode 100644 TopModel.ModelGenerator/TmdCompositionProperty.cs create mode 100644 TopModel.ModelGenerator/TmdEndpoint.cs create mode 100644 TopModel.ModelGenerator/TmdRegularProperty.cs diff --git a/TopModel.Generator.Jpa/SpringClientApiGenerator.cs b/TopModel.Generator.Jpa/SpringClientApiGenerator.cs index 92c50fd9..f232a3b7 100644 --- a/TopModel.Generator.Jpa/SpringClientApiGenerator.cs +++ b/TopModel.Generator.Jpa/SpringClientApiGenerator.cs @@ -232,7 +232,7 @@ private void WriteUriBuilderMethod(JavaWriter fw, Endpoint endpoint) if (endpoint.GetRouteParams().Any()) { - fullRoute = $@"""{fullRoute}"".formatted({string.Join(", ", endpoint.GetRouteParams().Select(p => p.GetParamName()))});"; + fullRoute = $@"""{fullRoute}"".formatted({string.Join(", ", endpoint.GetRouteParams().Select(p => p.GetParamName()))})"; } else { diff --git a/TopModel.ModelGenerator/Database/DatabaseTmdGenerator.cs b/TopModel.ModelGenerator/Database/DatabaseTmdGenerator.cs index 90332c75..d42d7ae4 100644 --- a/TopModel.ModelGenerator/Database/DatabaseTmdGenerator.cs +++ b/TopModel.ModelGenerator/Database/DatabaseTmdGenerator.cs @@ -97,13 +97,13 @@ private static void AddUniqConstraints(TmdClass classe, IEnumerable g.Name); classe.Unique - .AddRange(uniqConstraints.Select(u => u.Where(c => classe.Properties.Any(p => p.SqlName == c.ColumnName)).Select(c => + .AddRange(uniqConstraints.Select(u => u.Where(c => classe.Properties.OfType().Any(p => p.SqlName == c.ColumnName)).Select(c => { - var property = classe.Properties.First(p => p.SqlName == c.ColumnName); + var property = classe.Properties.OfType().First(p => p.SqlName == c.ColumnName); string name = string.Empty; if (property is TmdAssociationProperty ap) { - name = ap.ForeignClass.Name + ap.ForeignProperty!.Name + ap.Role; + name = ap.Association.Name + ap.ForeignProperty!.Name + ap.Role; } else { @@ -144,16 +144,16 @@ private TmdProperty ColumnToProperty(TmdClass classe, DbColumn column, string tr var columnName = column.ColumnName; - TmdProperty tmdProperty; + TmdRegularProperty tmdProperty; if (foreignConstraint != null && _classes.ContainsKey(foreignConstraint.ForeignTableName)) { tmdProperty = new TmdAssociationProperty(); var foreignClass = _classes[foreignConstraint.ForeignTableName]; - ((TmdAssociationProperty)tmdProperty).ForeignClass = foreignClass; + ((TmdAssociationProperty)tmdProperty).Association = foreignClass; } else { - tmdProperty = new TmdProperty(); + tmdProperty = new TmdRegularProperty(); if (!string.IsNullOrEmpty(trigram)) { var regex = new Regex(Regex.Escape(trigram)); @@ -479,7 +479,7 @@ private async Task ReadValues() var d = new Dictionary(); foreach (var kv in r) { - d.Add(classe.Value.Properties.First(p => p.SqlName == kv.Key).Name, kv.Value?.ToString()); + d.Add(classe.Value.Properties.OfType().First(p => p.SqlName == kv.Key).Name, kv.Value?.ToString()); } return d; @@ -509,7 +509,7 @@ private void ResolveForeignProperties(IGrouping group, IGroupi foreach (var fk in classe.Properties.OfType()) { var foreignColumnName = foreignKeys.First(p => p.ColumnName == fk.SqlName).ForeignColumnName; - fk.ForeignProperty = fk.ForeignClass!.Properties.First(p => p.SqlName == foreignColumnName); + fk.ForeignProperty = fk.Association!.Properties.OfType().First(p => p.SqlName == foreignColumnName); } } } @@ -523,7 +523,6 @@ private IEnumerable WriteFiles() yield return fileName; using var tmdFileWriter = new TmdWriter(rootPath, file!, _logger, ModelRoot); - tmdFileWriter.Write(); } } } \ No newline at end of file diff --git a/TopModel.ModelGenerator/OpenApi/OpenApiTmdGenerator.cs b/TopModel.ModelGenerator/OpenApi/OpenApiTmdGenerator.cs index 9d41c0df..640e0775 100644 --- a/TopModel.ModelGenerator/OpenApi/OpenApiTmdGenerator.cs +++ b/TopModel.ModelGenerator/OpenApi/OpenApiTmdGenerator.cs @@ -60,171 +60,224 @@ protected override async IAsyncEnumerable GenerateCore() var modelFileName = $"{Path.Combine(ModelRoot, _config.OutputDirectory, _config.ModelFileName)}.tmd"; yield return modelFileName; - using var fw = new FileWriter(modelFileName, _logger, false) { StartCommentToken = "####" }; - fw.WriteLine("---"); - fw.WriteLine($"module: {_config.Module}"); - fw.WriteLine("tags:"); - foreach (var tag in _config.ModelTags) + var tmdFile = new TmdFile() { - fw.WriteLine($" - {tag}"); - } - - fw.WriteLine(); + Module = _config.Module, + Name = _config.ModelFileName, + Tags = _config.ModelTags.ToList() + }; + var rootPath = Path.Combine(ModelRoot, _config.OutputDirectory); + var fileName = Path.Combine(rootPath, tmdFile.Module!, tmdFile.Name + ".tmd"); + using var tmdFileWriter = new TmdWriter(ModelRoot, tmdFile, _logger, ModelRoot); var references = new HashSet(referenceMap.SelectMany(r => r.Value).Select(r => r.Id).Distinct()); foreach (var schema in _model.GetSchemas(references).OrderBy(r => r.Key)) { - fw.WriteLine("---"); - fw.WriteLine("class:"); - - var className = schema.Value.Type == "array" ? schema.Key.Unplurialize() : schema.Key; - - fw.WriteLine($" name: {_config.ClassPrefix}{className}"); - - if (_config.PreservePropertyCasing) + if (schema.Value.Type == "string" && schema.Value.Enum.Any()) { - fw.WriteLine($" preservePropertyCasing: true"); - } + var classes = tmdFile.Classes.Select(c => c.Name); + if (classes.Contains($"{_config.ClassPrefix}{schema.Key.ToPascalCase()}")) + { + continue; + } - if (schema.Value.Description != null) - { - fw.WriteLine($" comment: {(schema.Value.Description ?? className).Format()}"); + var enumClass = new TmdClass() + { + File = tmdFile, + Name = $"{_config.ClassPrefix}{schema.Key.ToPascalCase()}", + Comment = $"enum pour les valeurs de {schema.Key.ToPascalCase()}", + PreservePropertyCasing = _config.PreservePropertyCasing + }; + + tmdFile.Classes.Add(enumClass); + + var p = WriteProperty(_config, new(schema.Key.ToPascalCase(), schema.Value), tmdFile); + p.Class = enumClass; + enumClass.Properties.Add(p); + AddValues(enumClass, schema.Value); } else { - fw.WriteLine($" comment: no description provided"); - } - - fw.WriteLine(); - fw.WriteLine($" properties:"); - - var properties = schema.Value.GetProperties().ToList(); - - foreach (var property in properties) - { - if (!property.Value.Enum.Any()) + var classe = new TmdClass() { - WriteProperty(_config, fw, property); - } - else + File = tmdFile, + PreservePropertyCasing = _config.PreservePropertyCasing + }; + + var className = schema.Value.Type == "array" ? schema.Key.Unplurialize() : schema.Key; + classe.Name = $"{_config.ClassPrefix}{className.ToPascalCase()}"; + var classes = tmdFile.Classes.Select(c => c.Name); + if (classes.Contains(classe.Name)) { - fw.WriteLine(" - alias:"); - fw.WriteLine($@" class: {_config.ClassPrefix}{schema.Key.ToPascalCase()}{property.Key.ToPascalCase()}"); - fw.WriteLine($" name: {property.Key.ToPascalCase()}"); + continue; } - if (properties.Last().Key != property.Key) + var parents = _model.GetSchemas().Where(s => s.Value.AnyOf.Contains(schema.Value) || s.Value.OneOf.Contains(schema.Value)); + if (parents.Count() == 1) { - fw.WriteLine(); + classe.Extends = parents.Single().Key.ToPascalCase(); } - } - foreach (var property in properties.Where(p => (p.Value.Enum?.Any() ?? false))) - { - fw.WriteLine("---"); - fw.WriteLine("class:"); - fw.WriteLine($" name: {_config.ClassPrefix}{schema.Key.ToPascalCase()}{property.Key.ToPascalCase()}"); + tmdFile.Classes.Add(classe); - if (_config.PreservePropertyCasing) + if (!string.IsNullOrEmpty(schema.Value.Description?.Trim(' '))) { - fw.WriteLine($" preservePropertyCasing: true"); + classe.Comment = $"{schema.Value.Description.Format()}"; } - fw.WriteLine($" comment: enum pour les valeurs de {property.Key.ToPascalCase()}"); + var classeProperties = classe.Properties; + var properties = schema.Value.GetProperties().ToList(); - fw.WriteLine(); - fw.WriteLine($" properties:"); - - WriteProperty(_config, fw, new("value", property.Value)); - fw.WriteLine(); - fw.WriteLine($" values:"); - var u = 0; - - foreach (var val in property.Value.Enum.OfType()) + foreach (var property in properties) { - fw.WriteLine($@" value{u++}: {{ value: {val.Value} }}"); - } + if (!property.Value.Enum.Any()) + { + var p = WriteProperty(_config, property, tmdFile); + p.Class = classe; + classeProperties.Add(p); + } + else + { + var enumClass = tmdFile.Classes.Where(c => c.Name == $"{classe.Name}{property.Key.ToPascalCase()}").SingleOrDefault(); + if (enumClass == null) + { + enumClass = new TmdClass() + { + File = tmdFile, + Name = $"{classe.Name}{property.Key.ToPascalCase()}", + Comment = $"enum pour les valeurs de {property.Key.ToPascalCase()}", + PreservePropertyCasing = _config.PreservePropertyCasing + }; + + tmdFile.Classes.Add(enumClass); + var p = WriteProperty(_config, new(property.Key.ToPascalCase(), property.Value), tmdFile); + p.Class = enumClass; + enumClass.Properties.Add(p); + AddValues(enumClass, property.Value); + } - foreach (var val in property.Value.Enum.OfType()) - { - fw.WriteLine($@" value{u++}: {{ value: {val.Value} }}"); + classeProperties.Add(new TmdAliasProperty() + { + Alias = enumClass.Properties[0], + Name = $"{property.Key.ToPascalCase()}", + Comment = property.Value.Description.Format(), + Class = classe + }); + } } } } + foreach (var cp in tmdFile.Classes.SelectMany(c => c.Properties.OfType())) + { + var composition = tmdFile.Classes.Where(c => c.Name == cp.CompositionReference).FirstOrDefault(); + cp.Composition = composition; + } + foreach (var module in modules) { var endpointFileName = $"{Path.Combine(ModelRoot, _config.OutputDirectory, module.Key)}.tmd"; yield return endpointFileName; - using var sw = new FileWriter(endpointFileName, _logger, false) { StartCommentToken = "####" }; - sw.WriteLine("---"); - sw.WriteLine($"module: {_config.Module}"); - sw.WriteLine("tags:"); - foreach (var tag in _config.EndpointTags) + var tmdFileEnpoint = new TmdFile() { - sw.WriteLine($" - {tag}"); - } + Module = _config.Module, + Name = module.Key, + Tags = _config.EndpointTags.ToList() + }; + + using var tmdEndpointFileWriter = new TmdWriter(ModelRoot, tmdFileEnpoint, _logger, ModelRoot); if (referenceMap[module.Key].Any()) { - sw.WriteLine("uses:"); var use = $"{_config.OutputDirectory.Replace("\\", "/")}/{_config.ModelFileName}".Replace("//", "/"); if (use.StartsWith("./")) { use = use.Replace("./", string.Empty); } - - sw.WriteLine($" - {use}"); } - sw.WriteLine(); - foreach (var operation in module.OrderBy(o => GetEndpointName(o))) { var path = GetOperationPath(operation.Value); - - sw.WriteLine("---"); - sw.WriteLine("endpoint:"); - sw.WriteLine($" name: {GetEndpointName(operation)}"); - sw.WriteLine($" method: {operation.Key.ToString().ToUpper()}"); - sw.WriteLine($" route: {path}"); - if (operation.Value.Summary != null) + var endPoint = new TmdEndpoint() { - sw.WriteLine($" description: {operation.Value.Summary.Format()}"); - } - else + Name = GetEndpointName(operation), + Method = operation.Key.ToString().ToUpper(), + Route = path, + File = tmdFileEnpoint + }; + tmdFileEnpoint.Endpoints.Add(endPoint); + if (!string.IsNullOrEmpty(operation.Value.Summary)) { - sw.WriteLine($" description: no description provided"); + endPoint.Comment = operation.Value.Summary; } - if (_config.PreservePropertyCasing) + endPoint.PreservePropertyCasing = _config.PreservePropertyCasing; + + if (string.IsNullOrEmpty(operation.Value.Summary)) { - sw.WriteLine($" preservePropertyCasing: true"); + endPoint.Comment = operation.Value.Summary; } if (operation.Value.Parameters.Any(p => p.In == ParameterLocation.Query || p.In == ParameterLocation.Path) || operation.Value.RequestBody != null) { - sw.WriteLine(" params:"); - var bodySchema = operation.Value.GetRequestBodySchema(); if (bodySchema != null) { - WriteProperty(_config, sw, new("body", bodySchema)); + var p = WriteProperty(_config, new("body", bodySchema), tmdFile); + if (p is TmdCompositionProperty cp) + { + cp.Composition = tmdFile.Classes.Where(c => c.Name == cp.CompositionReference).SingleOrDefault(); + } + + endPoint.Params.Add(p); } foreach (var param in operation.Value.Parameters.Where(p => p.In == ParameterLocation.Query || p.In == ParameterLocation.Path).OrderBy(p => path.Contains($@"{{{p.Name}}}") ? 0 + p.Name : 1 + p.Name)) { - sw.WriteLine($" - name: {param.Name}"); - sw.WriteLine($" domain: {_config.GetDomain(param.Name, param.Schema)}"); - if (param.Description != null) + TmdProperty property; + if (param.Schema.Enum.Any()) { - sw.WriteLine($" comment: {param.Description.Format()}"); + var enumClass = tmdFile.Classes.Where(c => c.Name == $"{endPoint.Name.ToPascalCase()}{param.Name.ToPascalCase()}").SingleOrDefault(); + if (enumClass == null) + { + enumClass = new TmdClass() + { + File = tmdFile, + Name = $"{endPoint.Name.ToPascalCase()}{param.Name.ToPascalCase()}", + Comment = $"enum pour les valeurs de {param.Name}", + PreservePropertyCasing = _config.PreservePropertyCasing + }; + + tmdFile.Classes.Add(enumClass); + var p = WriteProperty(_config, new(param.Name.ToPascalCase(), param.Schema), tmdFile); + p.Class = enumClass; + enumClass.Properties.Add(p); + AddValues(enumClass, param.Schema); + } + + property = new TmdAliasProperty() + { + Alias = enumClass.Properties[0], + Name = $"{param.Name.ToPascalCase()}", + Class = enumClass + }; } else { - sw.WriteLine($" comment: no description provided"); + property = new TmdRegularProperty() + { + Name = param.Name, + Domain = _config.GetDomain(param.Name, param.Schema) + }; + } + + endPoint.Params.Add(property); + if (!string.IsNullOrEmpty(param.Description?.Trim(' '))) + { + property.Comment = param.Description.Format(); } } } @@ -232,15 +285,73 @@ protected override async IAsyncEnumerable GenerateCore() var responseSchema = GetResponseSchema(operation.Value).Value; if (responseSchema != null) { - sw.WriteLine(" returns:"); - WriteProperty(_config, sw, new("Result", responseSchema), noList: true); + var returns = WriteProperty(_config, new("Result", responseSchema), tmdFile); + if (returns is TmdCompositionProperty cp) + { + cp.Composition = tmdFile.Classes.Where(c => c.Name == cp.CompositionReference).SingleOrDefault(); + } + + endPoint.Returns = returns; } } } } + private static void AddValues(TmdClass classe, OpenApiSchema schema) + { + foreach (var val in schema.Enum.OfType()) + { + Dictionary value = new() + { + { classe.Properties.First().Name, val.Value } + }; + classe.Values.Add(value); + } + + foreach (var val in schema.Enum.OfType()) + { + Dictionary value = new() + { + { classe.Properties.First().Name, $"{val.Value}" } + }; + classe.Values.Add(value); + } + + foreach (var val in schema.Enum.OfType()) + { + Dictionary value = new() + { + { classe.Properties.First().Name, $"{val.Value}" } + }; + classe.Values.Add(value); + } + + foreach (var val in schema.Enum.OfType()) + { + Dictionary value = new() + { + { classe.Properties.First().Name, $"{val.Value}" } + }; + classe.Values.Add(value); + } + + foreach (var val in schema.Enum.OfType()) + { + Dictionary value = new() + { + { classe.Properties.First().Name, $"{val.Value}" } + }; + classe.Values.Add(value); + } + } + private (string? Kind, string? Name) GetComposition(OpenApiSchema schema) { + if (schema.AnyOf.Any() || schema.OneOf.Any()) + { + return (null, null); + } + return schema.Items?.Reference != null ? ("list", schema.Items.Reference.Id) : schema.Reference != null && _model.GetSchemas().Any(s => s.Value.Reference == schema.Reference) @@ -405,29 +516,101 @@ private IEnumerable GetSchemaReferences(OpenApiSchema schema, yield return reference; } } + + foreach (var oneOff in schema.OneOf) + { + foreach (var reference in GetSchemaReferences(oneOff, visited)) + { + yield return reference; + } + } + + foreach (var anyOff in schema.AnyOf) + { + foreach (var reference in GetSchemaReferences(anyOff, visited)) + { + yield return reference; + } + } } - private void WriteProperty(OpenApiConfig config, FileWriter sw, KeyValuePair property, bool noList = false) + private TmdProperty WriteProperty(OpenApiConfig config, KeyValuePair property, TmdFile tmdFile) { var (kind, name) = GetComposition(property.Value); + if (property.Value.Type == "array" && property.Value.Items.Enum.Any() && property.Value.Items.Type == "string" && property.Value.Items.Reference != null) + { + var aliasClass = tmdFile.Classes.Where(c => c.Name == property.Value.Items.Reference.Id.ToPascalCase()).SingleOrDefault(); + if (aliasClass == null) + { + aliasClass = new TmdClass() + { + File = tmdFile, + Name = $"{_config.ClassPrefix}{property.Value.Items.Reference.Id.ToPascalCase()}", + Comment = $"enum pour les valeurs de {property.Value.Items.Reference.Id.ToPascalCase()}", + PreservePropertyCasing = _config.PreservePropertyCasing + }; + + tmdFile.Classes.Add(aliasClass); + + var p = WriteProperty(_config, new(property.Key, property.Value.Items), tmdFile); + p.Class = aliasClass; + aliasClass.Properties.Add(p); + AddValues(aliasClass, property.Value.Items); + } + + var aliasProperty = new TmdAliasProperty() + { + Name = $"{property.Key}", + Required = !property.Value.Nullable, + Domain = $"{config.GetDomain(property.Key, property.Value)}", + Alias = aliasClass.Properties.First(), + As = "list" + }; + + if (!string.IsNullOrEmpty(property.Value.Description?.Trim(' '))) + { + aliasProperty.Comment = $"{property.Value.Description.Format()}"; + } - if (kind != null && name != null) + return aliasProperty; + } + else if (!(property.Value.Type == "string" && property.Value.Enum.Any()) + && kind != null && name != null) { + var compositionProperty = new TmdCompositionProperty() + { + Name = $"{property.Key}" + }; var domainKind = TmdGenUtils.GetDomainString(config.Domains, type: kind); - sw.WriteLine($" {(noList ? string.Empty : "- ")}composition: {_config.ClassPrefix}{name}"); - sw.WriteLine($" {(noList ? string.Empty : " ")}name: {property.Key}"); if (kind != "object") { - sw.WriteLine($" {(noList ? string.Empty : " ")}domain: {domainKind ?? kind}"); + compositionProperty.Domain = $"{domainKind ?? kind}"; } + + if (!string.IsNullOrEmpty(property.Value.Description?.Trim(' '))) + { + compositionProperty.Comment = $"{property.Value.Description.Format()}"; + } + + compositionProperty.CompositionReference = $"{_config.ClassPrefix}{name.ToPascalCase()}"; + + return compositionProperty; } else { - sw.WriteLine($" {(noList ? string.Empty : "- ")}name: {property.Key}"); - sw.WriteLine($" {(noList ? string.Empty : " ")}domain: {config.GetDomain(property.Key, property.Value)}"); - sw.WriteLine($" {(noList ? string.Empty : " ")}required: {(!property.Value.Nullable).ToString().ToLower()}"); - } + var regularProperty = new TmdRegularProperty() + { + Name = $"{property.Key}", + Required = !property.Value.Nullable, + Domain = $"{config.GetDomain(property.Key, property.Value)}" + }; + + if (!string.IsNullOrEmpty(property.Value.Description?.Trim(' '))) + { + regularProperty.Comment = $"{property.Value.Description.Format()}"; + } - sw.WriteLine($" {(noList ? string.Empty : " ")}comment: {(property.Value.Description ?? property.Key).Format()}"); + return regularProperty; + } } -} \ No newline at end of file +} diff --git a/TopModel.ModelGenerator/OpenApi/OpenApiUtils.cs b/TopModel.ModelGenerator/OpenApi/OpenApiUtils.cs index 1a7ec46e..5a4ab6a2 100644 --- a/TopModel.ModelGenerator/OpenApi/OpenApiUtils.cs +++ b/TopModel.ModelGenerator/OpenApi/OpenApiUtils.cs @@ -61,7 +61,10 @@ public static IDictionary GetSchemas(this OpenApiDocument .Where(s => s.Value.Type == "object" || s.Value.AllOf.Any() && s.Value.AllOf.All(a => a.Type == "object" || a.Reference != null) - || s.Value.Type == "array" && s.Value.Items.Type == "object") + || s.Value.Type == "array" && s.Value.Items.Type == "object" + || s.Value.AnyOf.Any() + || s.Value.OneOf.Any() + || s.Value.Type == "string" && s.Value.Enum.Any()) .Where(s => references == null || references.Contains(s.Key)) .ToDictionary(a => a.Key, a => a.Value); } diff --git a/TopModel.ModelGenerator/TmdAliasProperty.cs b/TopModel.ModelGenerator/TmdAliasProperty.cs new file mode 100644 index 00000000..a888e851 --- /dev/null +++ b/TopModel.ModelGenerator/TmdAliasProperty.cs @@ -0,0 +1,13 @@ +namespace TopModel.ModelGenerator; + +public class TmdAliasProperty : TmdProperty +{ +#nullable disable + public bool Required { get; set; } + + public TmdProperty Alias { get; set; } + + public string Property { get; set; } + + public string As { get; set; } +} \ No newline at end of file diff --git a/TopModel.ModelGenerator/TmdAssociationProperty.cs b/TopModel.ModelGenerator/TmdAssociationProperty.cs index bd48e386..630ab590 100644 --- a/TopModel.ModelGenerator/TmdAssociationProperty.cs +++ b/TopModel.ModelGenerator/TmdAssociationProperty.cs @@ -2,14 +2,14 @@ namespace TopModel.ModelGenerator; -public class TmdAssociationProperty : TmdProperty +public class TmdAssociationProperty : TmdRegularProperty { #nullable disable - public TmdClass ForeignClass { get; set; } + public TmdClass Association { get; set; } #nullable enable - public TmdProperty? ForeignProperty { get; set; } + public TmdRegularProperty? ForeignProperty { get; set; } - public string Role => ForeignClass != Class ? Name.Replace(ForeignClass!.Trigram.ToPascalCase() + ForeignProperty!.Name, string.Empty) : string.Empty; + public string Role => Association != Class ? Name.Replace(Association!.Trigram.ToPascalCase() + ForeignProperty!.Name, string.Empty) : string.Empty; } \ No newline at end of file diff --git a/TopModel.ModelGenerator/TmdClass.cs b/TopModel.ModelGenerator/TmdClass.cs index 97a29375..3736959d 100644 --- a/TopModel.ModelGenerator/TmdClass.cs +++ b/TopModel.ModelGenerator/TmdClass.cs @@ -5,17 +5,23 @@ public class TmdClass #nullable disable public string Name { get; set; } + public string Comment { get; set; } = "Non documenté"; + public string SqlName { get; set; } public List Properties { get; set; } = new(); - public List Dependencies => Properties.OfType().Select(p => p.ForeignClass!).ToList(); + public List Dependencies => Properties.OfType().Select(p => p.Association!).Concat(Properties.OfType().Select(a => a.Class)).ToList(); public string Trigram { get; set; } = string.Empty; public List> Unique { get; set; } = new(); + public bool PreservePropertyCasing { get; set; } = false; + #nullable enable + + public string? Extends { get; set; } public List> Values { get; set; } = new(); public TmdFile? File { get; set; } diff --git a/TopModel.ModelGenerator/TmdCompositionProperty.cs b/TopModel.ModelGenerator/TmdCompositionProperty.cs new file mode 100644 index 00000000..c079acee --- /dev/null +++ b/TopModel.ModelGenerator/TmdCompositionProperty.cs @@ -0,0 +1,10 @@ +using TopModel.Utils; + +namespace TopModel.ModelGenerator; + +public class TmdCompositionProperty : TmdProperty +{ +#nullable disable + + public TmdClass Composition { get; set; } +} \ No newline at end of file diff --git a/TopModel.ModelGenerator/TmdEndpoint.cs b/TopModel.ModelGenerator/TmdEndpoint.cs new file mode 100644 index 00000000..83cb5dfc --- /dev/null +++ b/TopModel.ModelGenerator/TmdEndpoint.cs @@ -0,0 +1,29 @@ +namespace TopModel.ModelGenerator; + +public class TmdEndpoint +{ +#nullable disable + public string Name { get; set; } + + public string Method { get; set; } + + public string Route { get; set; } + + public string Comment { get; set; } = "Non documenté"; + + public List Params { get; set; } = new(); + + public List Properties => Returns != null ? Params.Concat(new List() { Returns }).ToList() : Params; + + public List Dependencies => Properties.OfType().Select(p => p.Association!).Concat( + Properties.OfType().Select(a => a.Class)).Concat( + Properties.OfType().Where(c => c.Composition != null).Select(c => c.Composition)) + .ToList(); + + public bool PreservePropertyCasing { get; set; } = false; + +#nullable enable + public TmdProperty? Returns { get; set; } + + public TmdFile? File { get; set; } +} \ No newline at end of file diff --git a/TopModel.ModelGenerator/TmdFile.cs b/TopModel.ModelGenerator/TmdFile.cs index 25e4d77e..69b66c6d 100644 --- a/TopModel.ModelGenerator/TmdFile.cs +++ b/TopModel.ModelGenerator/TmdFile.cs @@ -9,8 +9,10 @@ public class TmdFile public List Classes { get; set; } = new(); + public List Endpoints { get; set; } = new(); + #nullable enable public string? Module { get; set; } - public List Uses => Classes.SelectMany(c => c.Dependencies).Where(c => c.File != null).Select(f => f!.File!).Distinct().OrderBy(u => u.Name).ToList(); + public List Uses => Classes.SelectMany(c => c.Dependencies).Concat(Endpoints.SelectMany(e => e.Dependencies)).Where(c => c.File != null).Select(f => f!.File!).Distinct().OrderBy(u => u.Name).ToList(); } \ No newline at end of file diff --git a/TopModel.ModelGenerator/TmdProperty.cs b/TopModel.ModelGenerator/TmdProperty.cs index bebe6f8d..fddfcf6d 100644 --- a/TopModel.ModelGenerator/TmdProperty.cs +++ b/TopModel.ModelGenerator/TmdProperty.cs @@ -5,13 +5,11 @@ public class TmdProperty #nullable disable public string Name { get; set; } + public string CompositionReference { get; set; } + public TmdClass Class { get; set; } - public string SqlName { get; set; } + public string Comment { get; set; } = "Non documenté"; public string Domain { get; set; } - - public bool Required { get; set; } - - public bool PrimaryKey { get; set; } -} \ No newline at end of file +} diff --git a/TopModel.ModelGenerator/TmdRegularProperty.cs b/TopModel.ModelGenerator/TmdRegularProperty.cs new file mode 100644 index 00000000..51532a29 --- /dev/null +++ b/TopModel.ModelGenerator/TmdRegularProperty.cs @@ -0,0 +1,11 @@ +namespace TopModel.ModelGenerator; + +public class TmdRegularProperty : TmdProperty +{ +#nullable disable + public string SqlName { get; set; } = string.Empty; + + public bool Required { get; set; } + + public bool PrimaryKey { get; set; } +} \ No newline at end of file diff --git a/TopModel.ModelGenerator/TmdWriter.cs b/TopModel.ModelGenerator/TmdWriter.cs index bfca808d..711b2a1b 100644 --- a/TopModel.ModelGenerator/TmdWriter.cs +++ b/TopModel.ModelGenerator/TmdWriter.cs @@ -30,20 +30,22 @@ public TmdWriter(string path, TmdFile file, ILogger logger, string modelRoot) /// public void Dispose() { + Write(); _writer.Dispose(); } public void Write() { _writer.WriteLine($"---"); - _writer.WriteLine($"module: {_file.Module!.Split('_')[1]}"); + var module = _file.Module?.Contains('_') ?? false ? _file.Module!.Split('_')[1] : _file.Module; + _writer.WriteLine($"module: {module}"); _writer.WriteLine($"tags:"); foreach (var tag in _file.Tags) { _writer.WriteLine($" - {tag}"); } - if (_file.Uses.Any()) + if (_file.Uses.Where(u => u.Name != _file.Name).Any()) { _writer.WriteLine($"uses: "); foreach (var u in _file.Uses.OrderBy(u => u.Name).Where(u => u.Name != _file.Name)) @@ -54,66 +56,186 @@ public void Write() foreach (var classe in _file.Classes.Distinct().OrderBy(c => c.Name)) { - _writer.WriteLine($"---"); - _writer.WriteLine($"class:"); - _writer.WriteLine($" name: {classe.Name}"); + WriteClass(classe); + } + + foreach (var endpoint in _file.Endpoints.Distinct().OrderBy(c => c.Name)) + { + WriteEndpoint(endpoint); + } + } + + private void WriteClass(TmdClass classe) + { + _writer.WriteLine($"---"); + _writer.WriteLine($"class:"); + _writer.WriteLine($" name: {classe.Name}"); + if (!string.IsNullOrEmpty(classe.Extends)) + { + _writer.WriteLine($" extends: {classe.Extends}"); + } + + if (!string.IsNullOrEmpty(classe.SqlName)) + { _writer.WriteLine($" sqlName: {classe.SqlName}"); - _writer.WriteLine($" comment: {classe.Name}"); - if (!string.IsNullOrEmpty(classe.Trigram)) - { - _writer.WriteLine($" trigram: {classe.Trigram.ToUpper()}"); - } + } + + _writer.WriteLine($" comment: {classe.Comment}"); + if (!string.IsNullOrEmpty(classe.Trigram)) + { + _writer.WriteLine($" trigram: {classe.Trigram.ToUpper()}"); + } + if (classe.PreservePropertyCasing) + { + _writer.WriteLine($" preservePropertyCasing: {classe.PreservePropertyCasing.ToString().ToLower()}"); + } + + if (!classe.Properties.Where(p => !(p is TmdCompositionProperty cp && cp.Composition == null)).Any()) + { + _writer.WriteLine($" properties: []"); + } + else + { _writer.WriteLine($" properties:"); foreach (var property in classe.Properties) { - _writer.WriteLine(); - if (property is TmdAssociationProperty ap) - { - _writer.WriteLine($" - association: {ap.ForeignClass.Name}"); - _writer.WriteLine($" comment: {property.Name}"); - if (!string.IsNullOrEmpty(ap.Role)) - { - _writer.WriteLine($" role: {ap.Role}"); - } - } - else - { - _writer.WriteLine($" - name: {property.Name}"); - _writer.WriteLine($" comment: {property.Name}"); - _writer.WriteLine($" domain: {property.Domain}"); - } - - if (property.Required) - { - _writer.WriteLine($" required: true"); - } - - if (property.PrimaryKey) - { - _writer.WriteLine($" primaryKey: true"); - } - } - - if (classe.Unique.Any()) - { - _writer.WriteLine(); - _writer.WriteLine($" unique:"); - foreach (var uniq in classe.Unique) - { - _writer.WriteLine($" - [{string.Join(", ", uniq)}]"); - } - } - - if (classe.Values.Any()) - { - _writer.WriteLine($" values:"); - var i = 0; - foreach (var row in classe.Values) - { - _writer.WriteLine(@$" Value{i++}: {{{string.Join(", ", row.Where(v => v.Value != null).Select(v => $@"{v.Key}: ""{v.Value}"""))}}}"); - } + WriteProperty(property); + } + } + + if (classe.Unique.Any()) + { + _writer.WriteLine(); + _writer.WriteLine($" unique:"); + foreach (var uniq in classe.Unique) + { + _writer.WriteLine($" - [{string.Join(", ", uniq)}]"); + } + } + + if (classe.Values.Any()) + { + _writer.WriteLine(); + _writer.WriteLine($" values:"); + var i = 0; + foreach (var row in classe.Values) + { + _writer.WriteLine(@$" Value{i++}: {{{string.Join(", ", row.Where(v => v.Value != null).Select(v => $@"{v.Key}: ""{v.Value}"""))}}}"); + } + } + } + + private void WriteEndpoint(TmdEndpoint endpoint) + { + _writer.WriteLine($"---"); + _writer.WriteLine($"endpoint:"); + _writer.WriteLine($" name: {endpoint.Name}"); + _writer.WriteLine($" method: {endpoint.Method}"); + _writer.WriteLine($" route: {endpoint.Route}"); + _writer.WriteLine($" description: {endpoint.Comment}"); + if (endpoint.PreservePropertyCasing) + { + _writer.WriteLine($" preservePropertyCasing: {endpoint.PreservePropertyCasing}"); + } + + if (endpoint.Params.Any()) + { + _writer.WriteLine($" params:"); + + foreach (var property in endpoint.Params) + { + WriteProperty(property); + } + } + + if (endpoint.Returns != null) + { + _writer.WriteLine($" returns:"); + WriteProperty(endpoint.Returns, true); + } + } + + private void WriteProperty(TmdProperty property, bool noList = false) + { + _writer.WriteLine(); + var listPrefix = noList ? string.Empty : " "; + if (property is TmdAssociationProperty ap) + { + _writer.WriteLine($" {(noList ? string.Empty : "- ")}association: {ap.Association.Name}"); + _writer.WriteLine($" {listPrefix}comment: {property.Comment}"); + if (!string.IsNullOrEmpty(ap.Role)) + { + _writer.WriteLine($" {listPrefix}role: {ap.Role}"); + } + + if (ap.Required) + { + _writer.WriteLine($" {listPrefix}required: true"); + } + + if (ap.PrimaryKey) + { + _writer.WriteLine($" {listPrefix}primaryKey: true"); + } + } + else if (property is TmdRegularProperty rp) + { + _writer.WriteLine($" {(noList ? string.Empty : "- ")}name: {property.Name}"); + _writer.WriteLine($" {listPrefix}domain: {rp.Domain}"); + if (rp.Required) + { + _writer.WriteLine($" {listPrefix}required: true"); + } + + if (rp.PrimaryKey) + { + _writer.WriteLine($" {listPrefix}primaryKey: true"); + } + + _writer.WriteLine($" {listPrefix}comment: {property.Comment}"); + } + else if (property is TmdCompositionProperty cp) + { + if (cp.Composition == null) + { + return; + } + + _writer.WriteLine($" {(noList ? string.Empty : "- ")}composition: {cp.Composition.Name}"); + _writer.WriteLine($" {listPrefix}name: {property.Name}"); + if (!string.IsNullOrEmpty(property.Domain)) + { + _writer.WriteLine($" {listPrefix}domain: {property.Domain}"); + } + + _writer.WriteLine($" {listPrefix}comment: {property.Comment}"); + } + else if (property is TmdAliasProperty sp) + { + _writer.WriteLine($" {(noList ? string.Empty : "- ")}alias:"); + _writer.WriteLine($" {listPrefix} class: {sp.Alias.Class.Name}"); + _writer.WriteLine($" {listPrefix} property: {sp.Alias.Name}"); + + if (!string.IsNullOrEmpty(property.Name) && property.Name != sp.Alias.Name) + { + _writer.WriteLine($" {listPrefix}name: {property.Name}"); + } + + if (sp.Required) + { + _writer.WriteLine($" {listPrefix}required: true"); + } + + if (!string.IsNullOrEmpty(sp.As)) + { + _writer.WriteLine($" {listPrefix}as: {sp.As}"); + } + + if (!string.IsNullOrEmpty(property.Comment)) + { + _writer.WriteLine($" {listPrefix}comment: {property.Comment}"); } } } -} \ No newline at end of file +} diff --git a/samples/generators/open-api/Petstore/Model.tmd b/samples/generators/open-api/Petstore/Model.tmd index bc497f81..af5166ae 100644 --- a/samples/generators/open-api/Petstore/Model.tmd +++ b/samples/generators/open-api/Petstore/Model.tmd @@ -1,4 +1,4 @@ -#### +#### #### ATTENTION CE FICHIER EST GENERE AUTOMATIQUEMENT ! #### @@ -6,202 +6,203 @@ module: Petstore tags: - petstore - --- class: name: ApiResponse + comment: Non documenté preservePropertyCasing: true - comment: no description provided - properties: + - name: code domain: DO_ENTIER required: true - comment: code + comment: Non documenté - name: type domain: DO_LIBELLE required: true - comment: type + comment: Non documenté - name: message domain: DO_LIBELLE required: true - comment: message + comment: Non documenté --- class: name: Category + comment: Non documenté preservePropertyCasing: true - comment: no description provided - properties: + - name: id domain: DO_ID required: true - comment: id + comment: Non documenté - name: name domain: DO_LIBELLE required: true - comment: name + comment: Non documenté --- class: name: Order + comment: Non documenté preservePropertyCasing: true - comment: no description provided - properties: + - name: id domain: DO_ID required: true - comment: id + comment: Non documenté - name: petId domain: DO_ID required: true - comment: petId + comment: Non documenté - name: quantity domain: DO_ENTIER required: true - comment: quantity + comment: Non documenté - name: shipDate domain: DO_DATE_TIME required: true - comment: shipDate + comment: Non documenté - alias: class: OrderStatus - name: Status + property: Status + comment: Order Status - name: complete domain: DO_BOOLEAN required: true - comment: complete + comment: Non documenté --- class: name: OrderStatus - preservePropertyCasing: true comment: enum pour les valeurs de Status - + preservePropertyCasing: true properties: - - name: value + + - name: Status domain: DO_LIBELLE required: true comment: Order Status values: - value0: { value: placed } - value1: { value: approved } - value2: { value: delivered } + Value0: {Status: "placed"} + Value1: {Status: "approved"} + Value2: {Status: "delivered"} --- class: name: Pet + comment: Non documenté preservePropertyCasing: true - comment: no description provided - properties: + - name: id domain: DO_ID required: true - comment: id + comment: Non documenté - name: name domain: DO_LIBELLE required: true - comment: name + comment: Non documenté - composition: Category name: category - comment: category + comment: Non documenté - name: photoUrls domain: DO_LIBELLE required: true - comment: photoUrls + comment: Non documenté - composition: Tag name: tags domain: DO_LIST - comment: tags + comment: Non documenté - alias: class: PetStatus - name: Status + property: Status + comment: pet status in the store --- class: name: PetStatus - preservePropertyCasing: true comment: enum pour les valeurs de Status - + preservePropertyCasing: true properties: - - name: value + + - name: Status domain: DO_LIBELLE required: true comment: pet status in the store values: - value0: { value: available } - value1: { value: pending } - value2: { value: sold } + Value0: {Status: "available"} + Value1: {Status: "pending"} + Value2: {Status: "sold"} --- class: name: Tag + comment: Non documenté preservePropertyCasing: true - comment: no description provided - properties: + - name: id domain: DO_ID required: true - comment: id + comment: Non documenté - name: name domain: DO_LIBELLE required: true - comment: name + comment: Non documenté --- class: name: User + comment: Non documenté preservePropertyCasing: true - comment: no description provided - properties: + - name: id domain: DO_ID required: true - comment: id + comment: Non documenté - name: username domain: DO_LIBELLE required: true - comment: username + comment: Non documenté - name: firstName domain: DO_LIBELLE required: true - comment: firstName + comment: Non documenté - name: lastName domain: DO_LIBELLE required: true - comment: lastName + comment: Non documenté - name: email domain: DO_LIBELLE required: true - comment: email + comment: Non documenté - name: password domain: DO_LIBELLE required: true - comment: password + comment: Non documenté - name: phone domain: DO_LIBELLE required: true - comment: phone + comment: Non documenté - name: userStatus domain: DO_ENTIER diff --git a/samples/generators/open-api/Petstore/Pet.tmd b/samples/generators/open-api/Petstore/Pet.tmd index a1c4e611..346d76fc 100644 --- a/samples/generators/open-api/Petstore/Pet.tmd +++ b/samples/generators/open-api/Petstore/Pet.tmd @@ -1,4 +1,4 @@ -#### +#### #### ATTENTION CE FICHIER EST GENERE AUTOMATIQUEMENT ! #### @@ -6,32 +6,34 @@ module: Petstore tags: - petstore -uses: +uses: - Petstore/Model - --- endpoint: name: addPet method: POST route: pet description: Add a new pet to the store - preservePropertyCasing: true + preservePropertyCasing: True params: + - composition: Pet name: body - comment: body + comment: Non documenté returns: + composition: Pet name: Result - comment: Result + comment: Non documenté --- endpoint: name: deletePet method: DELETE route: pet/{petId} description: Deletes a pet - preservePropertyCasing: true + preservePropertyCasing: True params: + - name: petId domain: DO_ID comment: Pet id to delete @@ -41,76 +43,87 @@ endpoint: method: GET route: pet/findByStatus description: Finds Pets by status - preservePropertyCasing: true + preservePropertyCasing: True params: + - name: status domain: DO_LIBELLE comment: Status values that need to be considered for filter returns: + composition: Pet name: Result domain: DO_LIST - comment: Result + comment: Non documenté --- endpoint: name: findPetsByTags method: GET route: pet/findByTags description: Finds Pets by tags - preservePropertyCasing: true + preservePropertyCasing: True params: + - name: tags domain: DO_LIBELLE comment: Tags to filter by returns: + composition: Pet name: Result domain: DO_LIST - comment: Result + comment: Non documenté --- endpoint: name: getPetById method: GET route: pet/{petId} description: Find pet by ID - preservePropertyCasing: true + preservePropertyCasing: True params: + - name: petId domain: DO_ID comment: ID of pet to return returns: + composition: Pet name: Result - comment: Result + comment: Non documenté --- endpoint: name: updatePet method: PUT route: pet description: Update an existing pet - preservePropertyCasing: true + preservePropertyCasing: True params: + - composition: Pet name: body - comment: body + comment: Non documenté returns: + composition: Pet name: Result - comment: Result + comment: Non documenté --- endpoint: name: updatePetWithForm method: POST route: pet/{petId} description: Updates a pet in the store with form data - preservePropertyCasing: true + preservePropertyCasing: True params: + - name: petId domain: DO_ID comment: ID of pet that needs to be updated + - name: name domain: DO_LIBELLE comment: Name of pet that needs to be updated + - name: status domain: DO_LIBELLE comment: Status of pet that needs to be updated @@ -120,19 +133,23 @@ endpoint: method: POST route: pet/{petId}/uploadImage description: uploads an image - preservePropertyCasing: true + preservePropertyCasing: True params: + - name: body domain: DO_FILE required: true - comment: body + comment: Non documenté + - name: petId domain: DO_ID comment: ID of pet to update + - name: additionalMetadata domain: DO_LIBELLE comment: Additional Metadata returns: + composition: ApiResponse name: Result - comment: Result + comment: Non documenté diff --git a/samples/generators/open-api/Petstore/Store.tmd b/samples/generators/open-api/Petstore/Store.tmd index f035f7d7..61eb02dd 100644 --- a/samples/generators/open-api/Petstore/Store.tmd +++ b/samples/generators/open-api/Petstore/Store.tmd @@ -1,4 +1,4 @@ -#### +#### #### ATTENTION CE FICHIER EST GENERE AUTOMATIQUEMENT ! #### @@ -6,17 +6,17 @@ module: Petstore tags: - petstore -uses: +uses: - Petstore/Model - --- endpoint: name: deleteOrder method: DELETE route: store/order/{orderId} description: Delete purchase order by ID - preservePropertyCasing: true + preservePropertyCasing: True params: + - name: orderId domain: DO_ID comment: ID of the order that needs to be deleted @@ -26,39 +26,44 @@ endpoint: method: GET route: store/inventory description: Returns pet inventories by status - preservePropertyCasing: true + preservePropertyCasing: True returns: + name: Result domain: DO_ENTIER_MAP required: true - comment: Result + comment: Non documenté --- endpoint: name: getOrderById method: GET route: store/order/{orderId} description: Find purchase order by ID - preservePropertyCasing: true + preservePropertyCasing: True params: + - name: orderId domain: DO_ID comment: ID of order that needs to be fetched returns: + composition: Order name: Result - comment: Result + comment: Non documenté --- endpoint: name: placeOrder method: POST route: store/order description: Place an order for a pet - preservePropertyCasing: true + preservePropertyCasing: True params: + - composition: Order name: body - comment: body + comment: Non documenté returns: + composition: Order name: Result - comment: Result + comment: Non documenté diff --git a/samples/generators/open-api/Petstore/User.tmd b/samples/generators/open-api/Petstore/User.tmd index fb770171..3a6fe5b3 100644 --- a/samples/generators/open-api/Petstore/User.tmd +++ b/samples/generators/open-api/Petstore/User.tmd @@ -1,4 +1,4 @@ -#### +#### #### ATTENTION CE FICHIER EST GENERE AUTOMATIQUEMENT ! #### @@ -6,44 +6,47 @@ module: Petstore tags: - petstore -uses: +uses: - Petstore/Model - --- endpoint: name: createUser method: POST route: user description: Create user - preservePropertyCasing: true + preservePropertyCasing: True params: + - composition: User name: body - comment: body + comment: Non documenté --- endpoint: name: createUsersWithListInput method: POST route: user/createWithList description: Creates list of users with given input array - preservePropertyCasing: true + preservePropertyCasing: True params: + - composition: User name: body domain: DO_LIST - comment: body + comment: Non documenté returns: + composition: User name: Result - comment: Result + comment: Non documenté --- endpoint: name: deleteUser method: DELETE route: user/{username} description: Delete user - preservePropertyCasing: true + preservePropertyCasing: True params: + - name: username domain: DO_LIBELLE comment: The name that needs to be deleted @@ -53,52 +56,59 @@ endpoint: method: GET route: user/{username} description: Get user by user name - preservePropertyCasing: true + preservePropertyCasing: True params: + - name: username domain: DO_LIBELLE comment: The name that needs to be fetched. Use user1 for testing. returns: + composition: User name: Result - comment: Result + comment: Non documenté --- endpoint: name: loginUser method: GET route: user/login description: Logs user into the system - preservePropertyCasing: true + preservePropertyCasing: True params: + - name: password domain: DO_LIBELLE comment: The password for login in clear text + - name: username domain: DO_LIBELLE comment: The user name for login returns: + name: Result domain: DO_LIBELLE required: true - comment: Result + comment: Non documenté --- endpoint: name: logoutUser method: GET route: user/logout description: Logs out current logged in user session - preservePropertyCasing: true + preservePropertyCasing: True --- endpoint: name: updateUser method: PUT route: user/{username} description: Update user - preservePropertyCasing: true + preservePropertyCasing: True params: + - composition: User name: body - comment: body + comment: Non documenté + - name: username domain: DO_LIBELLE comment: name that need to be deleted diff --git a/samples/generators/php/topmodel.config.schema.json b/samples/generators/php/topmodel.config.schema.json index 64983a18..9172a9ea 100644 --- a/samples/generators/php/topmodel.config.schema.json +++ b/samples/generators/php/topmodel.config.schema.json @@ -575,6 +575,14 @@ "type": "number", "description": "Taille des chunks à extraire et insérer" }, + "dataFlowsListeners": { + "type": "array", + "description": "Listeners à ajouter à tous les dataflows", + "items": { + "type": "string", + "description": "Listener à ajouter à tous les dataflows" + } + }, "dbSchema": { "type": "string", "description": "Nom du schéma sur lequel les entités sont sauvegardées" @@ -613,8 +621,8 @@ "type": "string", "description": "Mode de génération de la persistence ('Javax' ou 'Jakarta')", "enum": [ - "Javax", - "Jakarta" + "javax", + "jakarta" ] }, "identity": {