private void MapPath(RestEaseInterface @interface, string path, OpenApiPathItem pathItem) { foreach (var restEaseInterfaceMethodDetails in pathItem.Operations.Select(o => MapOperationToMappingModel(@interface, path, o.Key.ToString(), o.Value))) { @interface.Methods.Add(restEaseInterfaceMethodDetails); } }
public RestEaseInterface Map(OpenApiDocument openApiDocument) { string name = CSharpUtils.CreateValidIdentifier(Settings.ApiName, CasingType.Pascal); string interfaceName = $"I{name}Api"; var @interface = new RestEaseInterface { Name = interfaceName, Namespace = Settings.Namespace, Summary = openApiDocument.Info?.Description ?? name }; foreach (var path in openApiDocument.Paths) { MapPath(@interface, path.Key, path.Value); } //var methods = paths.Select(p => MapPath(interfaceName, p.Key, p.Value)).SelectMany(x => x).ToList(); //var counts = methods // .GroupBy(method => method.RestEaseMethod.Name + method.RestEaseMethod.Parameters) // .Where(grouping => grouping.Count() > 1) // .ToDictionary(grouping => grouping.Key, p => p.Count()); //// modify the list, going backwards so we can take advantage of our counts. //for (int i = methods.Count - 1; i >= 0; i--) //{ // string key = methods[i].RestEaseMethod.Name + methods[i].RestEaseMethod.Parameters; // if (counts.ContainsKey(key)) // { // // add the suffix and decrement the number of duplicates left to tag. // methods[i].RestEaseMethod.Name += $"{counts[key]--}"; // } //} return @interface; }
private RestEaseInterfaceMethodDetails MapOperationToMappingModel(RestEaseInterface @interface, string path, string httpMethod, OpenApiOperation operation) { string methodRestEaseForAnnotation = httpMethod.ToPascalCase(); string methodRestEaseMethodName = GeneratedRestEaseMethodName(path, operation, methodRestEaseForAnnotation); var headerParameterList = operation.Parameters .Where(p => p.In == ParameterLocation.Header && p.Schema.GetSchemaType() != SchemaType.Object) .Select(p => BuildValidParameter(p.Name, p.Schema, p.Required, p.Description, p.In)) .ToList(); var pathParameterList = operation.Parameters .Where(p => p.In == ParameterLocation.Path && p.Schema.GetSchemaType() != SchemaType.Object) .Select(p => BuildValidParameter(p.Name, p.Schema, p.Required, p.Description, p.In)) .ToList(); var queryParameterList = operation.Parameters .Where(p => p.In == ParameterLocation.Query && p.Schema.GetSchemaType() != SchemaType.Object) .Select(p => BuildValidParameter(p.Name, p.Schema, p.Required, p.Description, p.In)) .ToList(); var extensionMethodParameterList = new List<RestEaseParameter>(); var bodyParameterList = new List<RestEaseParameter>(); var requestDetails = operation.RequestBody != null ? MapRequest(operation, bodyParameterList, extensionMethodParameterList) : null; var headers = new List<string>(); if (requestDetails != null) { if (requestDetails.DetectedContentType != null) { headers.Add($"[Header(\"{HttpKnownHeaderNames.ContentType}\", \"{requestDetails.DetectedContentType.GetDescription()}\")]"); } else if (requestDetails.ContentTypes.Count > 1) { headerParameterList.Add(new RestEaseParameter { Required = true, Summary = "The Content-Type", Identifier = "contentType", IdentifierWithRestEase = $"[Header(\"{HttpKnownHeaderNames.ContentType}\")] string contentType", IdentifierWithType = "string contentType", IsSpecial = false, SchemaFormat = SchemaFormat.Undefined, SchemaType = SchemaType.String }); } } var methodParameterList = headerParameterList .Union(pathParameterList) .Union(bodyParameterList) .Union(queryParameterList) .OrderByDescending(p => p.Required) .ToList(); var response = operation.Responses.First(); object returnType = null; if (response.Value != null && TryGetOpenApiMediaType(response.Value.Content, SupportedContentType.ApplicationJson, out OpenApiMediaType responseJson, out var _)) { switch (responseJson.Schema?.GetSchemaType()) { case SchemaType.Array: string arrayType = responseJson.Schema.Items.Reference != null ? MakeValidModelName(responseJson.Schema.Items.Reference.Id) : MapSchema(responseJson.Schema.Items, null, false, true, null).ToString(); returnType = MapArrayType(arrayType); break; case SchemaType.Object: if (responseJson.Schema.Reference != null) { // Existing defined object returnType = MakeValidModelName(responseJson.Schema.Reference.Id); } else if (responseJson.Schema.AdditionalProperties != null) { // Use AdditionalProperties returnType = MapSchema(responseJson.Schema.AdditionalProperties, null, responseJson.Schema.AdditionalProperties.Nullable, false, null); } else { // Object is defined `inline`, create a new Model and use that one. string className = !string.IsNullOrEmpty(responseJson.Schema.Title) ? CSharpUtils.CreateValidIdentifier(responseJson.Schema.Title, CasingType.Pascal) : $"{methodRestEaseMethodName.ToPascalCase()}Result"; var existingModel = @interface.InlineModels.FirstOrDefault(m => m.ClassName == className); if (existingModel == null) { var newModel = new RestEaseModel { Namespace = Settings.Namespace, ClassName = className, Properties = MapSchema(responseJson.Schema, null, false, true, null) as ICollection<string> }; @interface.InlineModels.Add(newModel); } returnType = className; } break; default: if (Settings.ReturnObjectFromMethodWhenResponseIsDefinedButNoModelIsSpecified) { returnType = "object"; } break; } } var method = new RestEaseInterfaceMethodDetails { Headers = headers, Summary = operation.Summary ?? $"{methodRestEaseMethodName} ({path})", SummaryParameters = methodParameterList.Select(mp => $"<param name=\"{mp.Identifier}\">{mp.Summary.StripHtml()}</param>").ToList(), RestEaseAttribute = $"[{methodRestEaseForAnnotation}(\"{path}\")]", RestEaseMethod = new RestEaseInterfaceMethod { ReturnType = MapReturnType(returnType), Name = methodRestEaseMethodName, ParametersAsString = string.Join(", ", methodParameterList.Select(mp => mp.IdentifierWithRestEase)), Parameters = methodParameterList } }; if (requestDetails?.IsExtension == true) { var combinedMethodParameterList = new List<RestEaseParameter> { new RestEaseParameter { Identifier = "api", IdentifierWithType = $"this {@interface.Name} api", IdentifierWithRestEase = $"this {@interface.Name} api", Summary = "The Api" } }; combinedMethodParameterList.AddRange(methodParameterList.Where(p => !p.IsSpecial)); combinedMethodParameterList.AddRange(extensionMethodParameterList); method.ExtensionMethodDetails = new RestEaseInterfaceMethodDetails { Summary = operation.Summary ?? $"{methodRestEaseMethodName} ({path})", SummaryParameters = combinedMethodParameterList.Select(mp => $"<param name=\"{mp.Identifier}\">{mp.Summary.StripHtml()}</param>").ToList(), RestEaseMethod = new RestEaseInterfaceMethod { ReturnType = method.RestEaseMethod.ReturnType, Name = method.RestEaseMethod.Name, ParametersAsString = string.Join(", ", combinedMethodParameterList.Select(mp => mp.IdentifierWithType)), Parameters = combinedMethodParameterList } }; method.ExtensionMethodParameters = extensionMethodParameterList; method.ExtensionMethodContentType = requestDetails.DetectedContentType; } return method; }
public string Build(RestEaseInterface @interface, string apiName) { var methods = @interface.Methods .Where(m => m.ExtensionMethodDetails != null) .ToList(); if (!methods.Any()) { return(null); } var builder = new StringBuilder(); if (!Settings.SingleFile) { builder.AppendLine("using System;"); builder.AppendLine("using System.Collections.Generic;"); builder.AppendLine("using System.Net.Http;"); builder.AppendLine("using System.Threading.Tasks;"); builder.AppendLine("using RestEase;"); builder.AppendLine($"using {AppendModelsNamespace(@interface.Namespace)};"); } builder.AppendLine(); builder.AppendLine($"namespace {AppendApiNamespace(@interface.Namespace)}"); builder.AppendLine("{"); builder.AppendLine($" public static class {new string(apiName.Skip(1).ToArray())}Extensions"); builder.AppendLine(" {"); foreach (var method in methods) { string asyncPostfix = Settings.AppendAsync ? "Async" : string.Empty; builder.AppendLine(" /// <summary>"); builder.AppendLine($" /// {method.ExtensionMethodDetails.Summary.StripHtml()}"); builder.AppendLine(" /// </summary>"); foreach (var p in method.ExtensionMethodDetails.SummaryParameters) { builder.AppendLine($" /// {p}"); } builder.AppendLine($" public static {method.ExtensionMethodDetails.RestEaseMethod.ReturnType} {method.ExtensionMethodDetails.RestEaseMethod.Name}{asyncPostfix}({method.ExtensionMethodDetails.RestEaseMethod.ParametersAsString})"); builder.AppendLine(" {"); switch (method.ExtensionMethodContentType) { case SupportedContentType.MultipartFormData: BuildMultipartFormDataExtensionMethodBody(Settings, builder, method); break; case SupportedContentType.ApplicationOctetStream: BuildApplicationOctetStreamExtensionMethodBody(Settings, builder, method); break; case SupportedContentType.ApplicationFormUrlEncoded: BuildApplicationFormUrlEncodedExtensionMethodBody(Settings, builder, method); break; } builder.AppendLine($" return api.{method.ExtensionMethodDetails.RestEaseMethod.Name}{asyncPostfix}({string.Join(", ", method.RestEaseMethod.Parameters.Select(p => p.Identifier))});"); builder.AppendLine(" }"); if (method != methods.Last()) { builder.AppendLine(); } } builder.AppendLine(" }"); builder.AppendLine("}"); return(builder.ToString()); }
public string Build(RestEaseInterface @interface, RestEaseSecurity security, bool hasModels) { var builder = new StringBuilder(); builder.AppendLine("using System;"); builder.AppendLine("using System.Collections.Generic;"); builder.AppendLine("using System.Net.Http;"); builder.AppendLine("using System.Net.Http.Headers;"); builder.AppendLine("using System.Threading.Tasks;"); builder.AppendLine("using RestEase;"); if (hasModels || @interface.InlineModels.Any()) { builder.AppendLine($"using {AppendModelsNamespace(@interface.Namespace)};"); } builder.AppendLine(); builder.AppendLine($"namespace {AppendApiNamespace(@interface.Namespace)}"); builder.AppendLine("{"); builder.AppendLine(" /// <summary>"); builder.AppendLine($" /// {@interface.Summary.StripHtml()}"); builder.AppendLine(" /// </summary>"); builder.AppendLine($" public interface {@interface.Name}"); builder.AppendLine(" {"); if (security != null && Settings.PreferredSecurityDefinitionType != SecurityDefinitionType.None) { var header = security.Definitions.FirstOrDefault(sd => sd.Type == SecurityDefinitionType.Header); // var query = security.Definitions.FirstOrDefault(sd => sd.Type == SecurityDefinitionType.Query); if (header != null && (Settings.PreferredSecurityDefinitionType == SecurityDefinitionType.Automatic || Settings.PreferredSecurityDefinitionType == SecurityDefinitionType.Header)) { builder.AppendLine($" [Header(\"{header.Name}\")]"); builder.AppendLine($" string {header.IdentifierName} {{ get; set; }}"); builder.AppendLine(); } } foreach (var method in @interface.Methods) { string asyncPostfix = Settings.AppendAsync ? "Async" : string.Empty; builder.AppendLine(" /// <summary>"); builder.AppendLine($" /// {method.Summary.StripHtml()}"); builder.AppendLine(" /// </summary>"); foreach (var p in method.SummaryParameters) { builder.AppendLine($" /// {p}"); } builder.AppendLine($" {method.RestEaseAttribute}"); foreach (var header in method.Headers) { builder.AppendLine($" {header}"); } builder.AppendLine($" {method.RestEaseMethod.ReturnType} {method.RestEaseMethod.Name}{asyncPostfix}({method.RestEaseMethod.ParametersAsString});"); if (method != @interface.Methods.Last()) { builder.AppendLine(); } } builder.AppendLine(" }"); builder.AppendLine("}"); return(builder.ToString()); }