diff --git a/Btms.Backend.Cli/Features/GenerateModels/CSharpFileBuilder.cs b/Btms.Backend.Cli/Features/GenerateModels/CSharpFileBuilder.cs index f6d1f630..719cb54f 100644 --- a/Btms.Backend.Cli/Features/GenerateModels/CSharpFileBuilder.cs +++ b/Btms.Backend.Cli/Features/GenerateModels/CSharpFileBuilder.cs @@ -1,5 +1,6 @@ using Btms.Backend.Cli.Features.GenerateModels.ClassMaps; using Btms.Backend.Cli.Features.GenerateModels.DescriptorModel; +using Btms.Common.Extensions; using RazorLight; namespace Btms.Backend.Cli.Features.GenerateModels; @@ -102,16 +103,18 @@ private static void ApplySourceClassMapOverrides(ClassDescriptor @class) { if (propertyMap.NoAttributes) { - propertyDescriptor.SourceAttributes.Clear(); + propertyDescriptor.NoAttributes = true; propertyDescriptor.InternalAttributes.Clear(); } else { - propertyDescriptor.SourceAttributes.AddRange(propertyMap.SourceAttributes); + propertyDescriptor.SourceAttributes = propertyMap.SourceAttributes; propertyDescriptor.InternalAttributes.AddRange(propertyMap.InternalAttributes); } } + propertyDescriptor.SourceJsonPropertyName = propertyMap.SourceJsonPropertyName; + propertyDescriptor.InternalJsonPropertyName = propertyMap.InternalJsonPropertyName; propertyDescriptor.ExcludedFromSource = propertyMap.ExcludedFromSource; propertyDescriptor.ExcludedFromInternal = propertyMap.ExcludedFromInternal; diff --git a/Btms.Backend.Cli/Features/GenerateModels/ClassMaps/Bootstrap.cs b/Btms.Backend.Cli/Features/GenerateModels/ClassMaps/Bootstrap.cs index e681256e..ce272d6d 100644 --- a/Btms.Backend.Cli/Features/GenerateModels/ClassMaps/Bootstrap.cs +++ b/Btms.Backend.Cli/Features/GenerateModels/ClassMaps/Bootstrap.cs @@ -20,17 +20,31 @@ public static void RegisterAlvsClassMaps() { map.MapProperty("ArrivalDateTime") .IsDateTime(DatetimeType.Epoch) - .SetInternalName("ArrivesAt"); - - map.MapProperty("MasterUCR").SetName("MasterUcr"); - map.MapProperty("SubmitterTURN").SetName("SubmitterTurn"); - map.MapProperty("DeclarationUCR").SetName("DeclarationUcr"); + .SetInternalName("arrivesAt"); + + map.MapProperty("MasterUCR") + .SetName("masterUcr") + .SetSourceJsonPropertyName("masterUCR"); + + map.MapProperty("SubmitterTURN") + .SetName("submitterTurn") + .SetSourceJsonPropertyName("submitterTURN"); + + map.MapProperty("DeclarationUCR") + .SetName("declarationUcr") + .SetSourceJsonPropertyName("declarationUCR"); + }); GeneratorClassMap.RegisterClassMap("Items", map => { - map.MapProperty("Documents"); - map.MapProperty("Checks"); + map.MapProperty("Document") + .SetSourceJsonPropertyName("documents") + .SetInternalJsonPropertyName("documents"); + + map.MapProperty("Check") + .SetSourceJsonPropertyName("checks") + .SetInternalJsonPropertyName("checks"); }); GeneratorClassMap.RegisterClassMap("Check", map => @@ -48,13 +62,21 @@ public static void RegisterAlvsClassMaps() IpaffsDescriptorBuilder.ClassNamePrefix)); - map.MapProperty("MasterUCR").SetName("MasterUcr"); - map.MapProperty("SubmitterTURN").SetName("SubmitterTurn"); - map.MapProperty("DeclarationUCR").SetName("DeclarationUcr"); + map.MapProperty("MasterUCR") + .SetName("masterUcr") + .SetSourceJsonPropertyName("masterUCR"); + + map.MapProperty("SubmitterTURN") + .SetName("submitterTurn") + .SetSourceJsonPropertyName("submitterTURN"); + + map.MapProperty("DeclarationUCR") + .SetName("declarationUcr") + .SetSourceJsonPropertyName("declarationUCR"); }); GeneratorClassMap.RegisterClassMap("ServiceHeader", - map => { map.MapProperty("ServiceCallTimestamp").IsDateTime(DatetimeType.Epoch).SetInternalName("ServiceCalled"); }); + map => { map.MapProperty("ServiceCallTimestamp").IsDateTime(DatetimeType.Epoch).SetInternalName("serviceCalled"); }); GeneratorClassMap.RegisterClassMap("AlvsClearanceRequest", map => { map.SetClassName("AlvsClearanceRequest", "CdsClearanceRequest"); }); @@ -63,14 +85,14 @@ public static void RegisterAlvsClassMaps() { map.SetClassName("AlvsClearanceRequestPost", "CdsClearanceRequestPost"); map.MapProperty("AlvsClearanceRequest").SetType("AlvsClearanceRequest", "CdsClearanceRequest"); - map.MapProperty("sendingDate").SetInternalName("SentOn").IsDateTime(); + map.MapProperty("sendingDate").SetInternalName("sentOn").IsDateTime(); }); GeneratorClassMap.RegisterClassMap("AlvsClearanceRequestPostResult", map => { map.SetClassName("AlvsClearanceRequestPostResult", "CdsClearanceRequestPostResult") .NoInternalClass(); - map.MapProperty("sendingDate").SetInternalName("SentOn").IsDateTime(); + map.MapProperty("sendingDate").SetInternalName("sentOn").IsDateTime(); }); } @@ -187,16 +209,16 @@ public static void RegisterIpaffsClassMaps() GeneratorClassMap.RegisterClassMap("Decision", map => { - map.MapProperty("decision").SetName("DecisionEnum"); + map.MapProperty("decision").SetName("decisionEnum"); map.MapProperty("notAcceptableActionByDate").IsDate(); }); GeneratorClassMap.RegisterClassMap("ImportNotification", map => { - map.MapProperty("Id").SetName("IpaffsId"); - map.MapProperty("Type").SetName("ImportNotificationType"); - map.MapProperty("LastUpdated").SetName("LastUpdated", "UpdatedSource").IsDateTime(); - map.MapProperty("RiskDecisionLockingTime").SetName("RiskDecisionLockedOn").IsDateTime(); + map.MapProperty("Id").SetName("ipaffsId"); + map.MapProperty("Type").SetName("importNotificationType"); + map.MapProperty("LastUpdated").SetName("lastUpdated", "UpdatedSource").IsDateTime(); + map.MapProperty("RiskDecisionLockingTime").SetName("riskDecisionLockedOn").IsDateTime(); }); GeneratorClassMap.RegisterClassMap("Purpose", map => @@ -206,8 +228,8 @@ public static void RegisterIpaffsClassMaps() map.MapProperty("exitDate").IsDate(); - map.MapProperty("FinalBIP").SetName("FinalBip"); - map.MapProperty("ExitBIP").SetName("ExitBip"); + map.MapProperty("FinalBIP").SetName("finalBip"); + map.MapProperty("ExitBIP").SetName("exitBip"); }); GeneratorClassMap.RegisterClassMap("VeterinaryInformation", @@ -243,7 +265,7 @@ public static void RegisterIpaffsClassMaps() map => { map.MapProperty("dateOfIssue").IsDateTime().SetInternalName("issuedOn"); }); GeneratorClassMap.RegisterClassMap("JourneyRiskCategorisationResult", - map => { map.MapProperty("riskLevelDateTime").SetName("RiskLevelSetFor").IsDateTime(); }); + map => { map.MapProperty("riskLevelDateTime").SetName("riskLevelSetFor").IsDateTime(); }); GeneratorClassMap.RegisterClassMap("RiskAssessmentResult", @@ -295,9 +317,9 @@ public static void RegisterIpaffsClassMaps() map.MapProperty("importerLocalReferenceNumber").IsSensitive(); map.MapProperty("commodities").ExcludeFromInternal(); map.MapProperty("originalEstimatedDateTime").SetName("originalEstimatedOn").IsDateTime(); - map.MapProperty("submissionDate").SetName("SubmittedOn").IsDateTime(); + map.MapProperty("submissionDate").SetName("submittedOn").IsDateTime(); map.MapProperty("isGVMSRoute").SetName("isGvmsRoute"); - map.MapProperty("portOfExitDate").IsDateTime().SetInternalName("ExitedPortOfOn"); + map.MapProperty("portOfExitDate").IsDateTime().SetInternalName("exitedPortOfOn"); map.MapDateOnlyAndTimeOnlyToDateTimeProperty("arrivalDate", "arrivalTime", "arrivesAt"); map.MapDateOnlyAndTimeOnlyToDateTimeProperty("departureDate", "departureTime", "departedOn"); diff --git a/Btms.Backend.Cli/Features/GenerateModels/ClassMaps/PropertyMap.cs b/Btms.Backend.Cli/Features/GenerateModels/ClassMaps/PropertyMap.cs index 770807de..292abb7f 100644 --- a/Btms.Backend.Cli/Features/GenerateModels/ClassMaps/PropertyMap.cs +++ b/Btms.Backend.Cli/Features/GenerateModels/ClassMaps/PropertyMap.cs @@ -20,6 +20,10 @@ internal class PropertyMap(string name) { public string Name { get; set; } = name; + public string? SourceJsonPropertyName { get; set; } + + public string? InternalJsonPropertyName { get; set; } + public string Type { get; set; } = null!; public string InternalType { get; set; } = null!; @@ -28,9 +32,9 @@ internal class PropertyMap(string name) public bool TypeOverwritten { get; set; } - public List SourceAttributes { get; set; } = new(); + public List SourceAttributes { get; set; } = []; - public List InternalAttributes { get; set; } = new(); + public List InternalAttributes { get; set; } = []; public bool AttributesOverwritten { get; set; } @@ -59,14 +63,14 @@ public class MapperMap public PropertyMap SetInternalType(string type) { - InternalType = type ?? throw new ArgumentNullException("type"); + InternalType = type ?? throw new ArgumentNullException(nameof(type)); InternalTypeOverwritten = true; return this; } public PropertyMap SetType(string type, string? internalType = null) { - Type = type ?? throw new ArgumentNullException("type"); + Type = type ?? throw new ArgumentNullException(nameof(type)); InternalType = internalType ?? type; InternalTypeOverwritten = internalType.HasValue(); TypeOverwritten = true; @@ -97,6 +101,18 @@ public PropertyMap IsTime() public PropertyMap SetName(string name, string? internalName = null) { + if (!name.StartsWithLowercase()) + { + throw new InvalidOperationException( + "Name must start with lowercase letter"); + } + + if (!internalName.StartsWithLowercase()) + { + throw new InvalidOperationException( + "Internal name must start with lowercase letter"); + } + SetSourceName(name); SetInternalName(internalName ?? name); return this; @@ -104,18 +120,53 @@ public PropertyMap SetName(string name, string? internalName = null) public PropertyMap SetSourceName(string name) { - OverriddenSourceName = name ?? throw new ArgumentNullException("name"); + if (!name.StartsWithLowercase()) + { + throw new InvalidOperationException( + "Name must start with lowercase letter"); + } + + OverriddenSourceName = name ?? throw new ArgumentNullException(nameof(name)); SourceNameOverwritten = true; return this; } public PropertyMap SetInternalName(string name) { - OverriddenInternalName = name ?? throw new ArgumentNullException("name"); + if (!name.StartsWithLowercase()) + { + throw new InvalidOperationException( + "Name must start with lowercase letter"); + } + OverriddenInternalName = name ?? throw new ArgumentNullException(nameof(name)); InternalNameOverwritten = true; return this; } + public PropertyMap SetSourceJsonPropertyName(string name) + { + if (!name.StartsWithLowercase()) + { + throw new InvalidOperationException( + "Name must start with lowercase letter"); + } + + SourceJsonPropertyName = name; + return this; + } + + public PropertyMap SetInternalJsonPropertyName(string name) + { + if (!name.StartsWithLowercase()) + { + throw new InvalidOperationException( + "Name must start with lowercase letter"); + } + + InternalJsonPropertyName = name; + return this; + } + public PropertyMap IsSensitive() { AddAttribute("[Btms.SensitiveData.SensitiveData]", Model.Source); @@ -150,7 +201,7 @@ public PropertyMap AddAttribute(string attribute, Model model) { if (string.IsNullOrEmpty(attribute)) { - throw new ArgumentNullException("attribute"); + throw new ArgumentNullException(nameof(attribute)); } switch (model) diff --git a/Btms.Backend.Cli/Features/GenerateModels/DescriptorModel/PropertyDescriptor.cs b/Btms.Backend.Cli/Features/GenerateModels/DescriptorModel/PropertyDescriptor.cs index 02b2d75f..5fb39951 100644 --- a/Btms.Backend.Cli/Features/GenerateModels/DescriptorModel/PropertyDescriptor.cs +++ b/Btms.Backend.Cli/Features/GenerateModels/DescriptorModel/PropertyDescriptor.cs @@ -1,4 +1,5 @@ using System.Diagnostics; +using Btms.Common.Extensions; using Humanizer; namespace Btms.Backend.Cli.Features.GenerateModels.DescriptorModel; @@ -34,8 +35,8 @@ public PropertyDescriptor(string sourceName, string internalName, string type, s Description = description?.Replace("\n", " "); IsReferenceType = isReferenceType; IsArray = isArray; - SourceAttributes = [$"[JsonPropertyName(\"{sourceName}\")]"]; - InternalAttributes = ["[Attr]", $"[System.ComponentModel.Description(\"{Description}\")]", $"[JsonPropertyName(\"{sourceName}\")]"]; + // SourceAttributes = []; // [$"[JsonPropertyName(\"{sourceName}\")]"]; + // InternalAttributes = ["[Attr]", $"[System.ComponentModel.Description(\"{Description}\")]", $"[JsonPropertyName(\"{sourceName}\")]"]; if (type.EndsWith("Enum")) { @@ -43,8 +44,15 @@ public PropertyDescriptor(string sourceName, string internalName, string type, s "[MongoDB.Bson.Serialization.Attributes.BsonRepresentation(MongoDB.Bson.BsonType.String)]"); } } + + public bool NoAttributes { get; set; } = default; + public string SourceName { get; set; } + public string? SourceJsonPropertyName { get; set; } + + public string? InternalJsonPropertyName { get; set; } + public string InternalName { get; set; } public string Type { get; set; } @@ -53,9 +61,9 @@ public PropertyDescriptor(string sourceName, string internalName, string type, s public string? Description { get; set; } - public List SourceAttributes { get; set; } + public List SourceAttributes { get; set; } = []; - public List InternalAttributes { get; set; } + public List InternalAttributes { get; set; } = []; public bool IsReferenceType { get; set; } @@ -132,6 +140,32 @@ public string GetInternalPropertyName() return n; } + public string[] GetSourceAttributes() + { + if (NoAttributes) return []; + + var defaultParams = new List() { $"[JsonPropertyName(\"{SourceJsonPropertyName ?? SourceName}\")]" }; + defaultParams.AddRange(SourceAttributes); + + return defaultParams.ToArray(); + } + + public string[] GetInternalAttributes() + { + if (NoAttributes) return []; + + var defaultParams = new List() { "[Attr]", $"[JsonPropertyName(\"{InternalJsonPropertyName ?? InternalName}\")]" }; + + if (!string.IsNullOrEmpty(Description)) + { + defaultParams.Add($"[System.ComponentModel.Description(\"{Description}\")]"); + } + + defaultParams.AddRange(InternalAttributes); + + return defaultParams.ToArray(); + } + public string GetInternalPropertyType() { return GetPropertyType(InternalType ?? Type); diff --git a/Btms.Backend.Cli/Features/GenerateModels/Templates/ClassTemplate.cshtml b/Btms.Backend.Cli/Features/GenerateModels/Templates/ClassTemplate.cshtml index 5bec4d3b..4e6895a7 100644 --- a/Btms.Backend.Cli/Features/GenerateModels/Templates/ClassTemplate.cshtml +++ b/Btms.Backend.Cli/Features/GenerateModels/Templates/ClassTemplate.cshtml @@ -17,9 +17,14 @@ using System.Dynamic; namespace @Model.SourceNamespace; +@if (!String.IsNullOrEmpty(Model.Description)) +{ + /// /// @Model.Description /// + +} public partial class @Model.GetClassName() //@if (Model.IsResource) { : CustomStringMongoIdentifiable } { @@ -27,12 +32,16 @@ public partial class @Model.GetClassName() //@if (Model.IsResource) { : C @foreach (var property in Model.Properties.Where(x => !x.ExcludedFromSource)) { var t = new HtmlString(property.GetSourcePropertyType()); - -/// + +@if (!String.IsNullOrEmpty(property.Description)) +{ + +/// /// @property.Description /// - - @foreach (var attr in property.SourceAttributes) + +} + @foreach (var attr in property.GetSourceAttributes()) { var htmlString = new HtmlString(attr); @htmlString diff --git a/Btms.Backend.Cli/Features/GenerateModels/Templates/InternalClassTemplate.cshtml b/Btms.Backend.Cli/Features/GenerateModels/Templates/InternalClassTemplate.cshtml index 40a8c214..572ed254 100644 --- a/Btms.Backend.Cli/Features/GenerateModels/Templates/InternalClassTemplate.cshtml +++ b/Btms.Backend.Cli/Features/GenerateModels/Templates/InternalClassTemplate.cshtml @@ -17,30 +17,30 @@ using System.Dynamic; namespace @Model.InternalNamespace; - +@if (!String.IsNullOrEmpty(Model.Description)) +{ + /// /// @Model.Description /// + +} public partial class @Model.GetInternalClassName() //@if (Model.IsResource) { : CustomStringMongoIdentifiable } { -@* @if (Model.IsResource) -{ - - // This field is used by the jsonapi-consumer to control the correct casing in the type field - public string Type { get; set; } = "@Model.Name"; - -} *@ @foreach(var property in Model.Properties.Where(x => !x.ExcludedFromInternal)) { var t = new HtmlString(property.GetInternalPropertyType()); + @if (!String.IsNullOrEmpty(property.Description)) + { /// /// @property.Description /// - @foreach (var attr in property.InternalAttributes) + } + @foreach (var attr in property.GetInternalAttributes()) { var htmlString = new HtmlString(attr); @htmlString diff --git a/Btms.Common/Extensions/StringExtensions.cs b/Btms.Common/Extensions/StringExtensions.cs index ca9e062e..b321d989 100644 --- a/Btms.Common/Extensions/StringExtensions.cs +++ b/Btms.Common/Extensions/StringExtensions.cs @@ -17,4 +17,9 @@ public static class StringExtensions { return JsonNode.Parse(value) as IDictionary; } + + public static bool StartsWithLowercase(this string? s) + { + return true; + } } \ No newline at end of file