internal static string TryGetFacilityResultOfType(this SwaggerService swaggerService, KeyValuePair <string, SwaggerSchema> swaggerSchema, NamedTextPosition position) { const string nameSuffix = "Result"; if (!swaggerSchema.Key.EndsWith(nameSuffix, StringComparison.Ordinal)) { return(null); } var properties = swaggerSchema.Value.Properties.EmptyIfNull(); if (!properties.Any(x => x.Key == "error" && x.Value.Ref == "#/definitions/Error")) { return(null); } var valueSchema = properties.Where(x => x.Key == "value").Select(x => x.Value).FirstOrDefault(); if (valueSchema == null) { return(null); } return(swaggerService.TryGetFacilityTypeName(valueSchema, position)); }
public static SwaggerConversion Create(SwaggerService swaggerService, string?serviceName, SwaggerParserContext context) { var conversion = new SwaggerConversion(swaggerService, serviceName); conversion.Convert(context); return(conversion); }
internal static string TryGetFacilityTypeName(this SwaggerService swaggerService, ISwaggerSchema swaggerSchema, NamedTextPosition position) { switch (swaggerSchema.Type ?? SwaggerSchemaType.Object) { case SwaggerSchemaType.String: return(swaggerSchema.Format == SwaggerSchemaTypeFormat.Byte ? "bytes" : "string"); case SwaggerSchemaType.Number: return(swaggerSchema.Format == SwaggerSchemaTypeFormat.Decimal ? "decimal" : "double"); case SwaggerSchemaType.Integer: return(swaggerSchema.Format == SwaggerSchemaTypeFormat.Int64 ? "int64" : "int32"); case SwaggerSchemaType.Boolean: return("boolean"); case SwaggerSchemaType.Array: return(swaggerSchema.Items?.Type == SwaggerSchemaType.Array ? null : $"{swaggerService.TryGetFacilityTypeName(swaggerSchema.Items, position)}[]"); case SwaggerSchemaType.Object: var fullSchema = swaggerSchema as SwaggerSchema; if (fullSchema != null) { if (fullSchema.Ref != null) { var resolvedSchema = swaggerService.ResolveDefinition(fullSchema, position); if (swaggerService.IsFacilityError(resolvedSchema)) { return("error"); } string resultOfType = swaggerService.TryGetFacilityResultOfType(resolvedSchema, position); if (resultOfType != null) { return($"result<{resultOfType}>"); } return(resolvedSchema.Key); } if (fullSchema.AdditionalProperties != null) { return($"map<{swaggerService.TryGetFacilityTypeName(fullSchema.AdditionalProperties, position)}>"); } } return("object"); } return(null); }
internal static KeyValuePair <string, SwaggerSchema> ResolveDefinition(this SwaggerService swaggerService, SwaggerSchema swaggerDefinition, NamedTextPosition position) { string name = null; if (swaggerDefinition.Ref != null) { name = GetDefinitionNameFromRef(swaggerDefinition.Ref, position); if (!swaggerService.Definitions.TryGetValue(name, out swaggerDefinition)) { throw new ServiceDefinitionException($"Missing definition named '{name}'.", position); } } return(new KeyValuePair <string, SwaggerSchema>(name, swaggerDefinition)); }
internal static void ResolveOperations(this SwaggerService swaggerService, ref SwaggerOperations swaggerOperations, ref SwaggerParserContext context) { if (swaggerOperations.Ref != null) { const string refPrefix = "#/paths/"; if (!swaggerOperations.Ref.StartsWith(refPrefix, StringComparison.Ordinal)) { throw new ServiceDefinitionException("Operations $ref must start with '#/paths/'.", context.CreatePosition()); } string name = UnescapeRefPart(swaggerOperations.Ref.Substring(refPrefix.Length)); if (!swaggerService.Paths.TryGetValue(name, out swaggerOperations)) { throw new ServiceDefinitionException($"Missing path named '{name}'.", context.CreatePosition()); } context = context.Root.CreateContext("paths/" + name); } }
internal static SwaggerResponse ResolveResponse(this SwaggerService swaggerService, SwaggerResponse swaggerResponse, NamedTextPosition position) { if (swaggerResponse.Ref != null) { const string refPrefix = "#/responses/"; if (!swaggerResponse.Ref.StartsWith(refPrefix, StringComparison.Ordinal)) { throw new ServiceDefinitionException("Response $ref must start with '#/responses/'.", position); } string name = UnescapeRefPart(swaggerResponse.Ref.Substring(refPrefix.Length)); if (!swaggerService.Responses.TryGetValue(name, out swaggerResponse)) { throw new ServiceDefinitionException($"Missing response named '{name}'.", position); } } return(swaggerResponse); }
private void AddResponseFields(IList <ServiceFieldInfo> responseFields, string statusCode, SwaggerResponse swaggerResponse, string serviceMethodName, IList <ServiceAttributeParameterInfo> httpAttributeValues, bool isOnlyResponse, SwaggerService swaggerService, NamedTextPosition position) { var bodySchema = default(KeyValuePair <string, SwaggerSchema>); if (swaggerResponse.Schema != null) { bodySchema = swaggerService.ResolveDefinition(swaggerResponse.Schema, position); } if (bodySchema.Value != null && (bodySchema.Value.Type ?? SwaggerSchemaType.Object) == SwaggerSchemaType.Object && (bodySchema.Key == null || bodySchema.Key.Equals(serviceMethodName + "Response", StringComparison.OrdinalIgnoreCase))) { httpAttributeValues.Add(new ServiceAttributeParameterInfo("code", statusCode, position)); AddFieldsFromSchema(responseFields, swaggerService, position, bodySchema); } else if (swaggerResponse.Identifier == null && isOnlyResponse && swaggerResponse.Schema == null) { httpAttributeValues.Add(new ServiceAttributeParameterInfo("code", statusCode, position)); } else { responseFields.Add(new ServiceFieldInfo( swaggerResponse.Identifier ?? CodeGenUtility.ToCamelCase(bodySchema.Key) ?? GetBodyFieldNameForStatusCode(statusCode), typeName: bodySchema.Key ?? (bodySchema.Value != null ? SwaggerUtility.FilterBodyTypeName(swaggerService.TryGetFacilityTypeName(bodySchema.Value, position)) : null) ?? "boolean", attributes: new[] { new ServiceAttributeInfo("http", new[] { new ServiceAttributeParameterInfo("from", "body", position), new ServiceAttributeParameterInfo("code", statusCode, position), }) }, summary: PrepareSummary(swaggerResponse.Description), position: position)); } }
private void AddRequestFields(IList <ServiceFieldInfo> requestFields, SwaggerParameter swaggerParameter, string serviceMethodName, string httpMethod, SwaggerService swaggerService, NamedTextPosition position) { string kind = swaggerParameter.In; if (kind == SwaggerParameterKind.Path || kind == SwaggerParameterKind.Query || kind == SwaggerParameterKind.Header) { string typeName = swaggerService.TryGetFacilityTypeName(swaggerParameter, position); if (typeName != null) { if (typeName.EndsWith("[]", StringComparison.Ordinal)) { typeName = "string"; } var attributes = new List <ServiceAttributeInfo>(); if (swaggerParameter.Obsolete.GetValueOrDefault()) { attributes.Add(new ServiceAttributeInfo("obsolete")); } string fieldName = swaggerParameter.Identifier ?? swaggerParameter.Name; if (!ServiceDefinitionUtility.IsValidName(fieldName)) { fieldName = CodeGenUtility.ToCamelCase(fieldName); } if (kind == SwaggerParameterKind.Query) { var parameters = new List <ServiceAttributeParameterInfo>(); if (httpMethod != "GET") { parameters.Add(new ServiceAttributeParameterInfo("from", "query")); } if (fieldName != swaggerParameter.Name) { parameters.Add(new ServiceAttributeParameterInfo("name", swaggerParameter.Name)); } if (parameters.Count != 0) { attributes.Add(new ServiceAttributeInfo("http", parameters)); } } else if (kind == SwaggerParameterKind.Header) { attributes.Add(new ServiceAttributeInfo("http", new[] { new ServiceAttributeParameterInfo("from", "header"), new ServiceAttributeParameterInfo("name", swaggerParameter.Name), })); } requestFields.Add(new ServiceFieldInfo( fieldName, typeName: typeName, attributes: attributes, summary: PrepareSummary(swaggerParameter.Description), position: position)); } } else if (kind == SwaggerParameterKind.Body) { var bodySchema = swaggerService.ResolveDefinition(swaggerParameter.Schema, position); if ((bodySchema.Value.Type ?? SwaggerSchemaType.Object) == SwaggerSchemaType.Object && (bodySchema.Key == null || bodySchema.Key.Equals(serviceMethodName + "Request", StringComparison.OrdinalIgnoreCase))) { AddFieldsFromSchema(requestFields, swaggerService, position, bodySchema); } else { string typeName = bodySchema.Key ?? SwaggerUtility.FilterBodyTypeName(swaggerService.TryGetFacilityTypeName(bodySchema.Value, position)); if (typeName != null) { requestFields.Add(new ServiceFieldInfo( bodySchema.Value.Identifier ?? "body", typeName: typeName, attributes: new[] { new ServiceAttributeInfo("http", new[] { new ServiceAttributeParameterInfo("from", "body", position) }) }, summary: PrepareSummary(swaggerParameter.Description), position: position)); } } } }
private void AddServiceMethod(IList <IServiceMemberInfo> members, string method, string path, SwaggerOperation swaggerOperation, IList <SwaggerParameter> swaggerOperationsParameters, SwaggerService swaggerService, SwaggerParserContext context) { if (swaggerOperation == null) { return; } var position = context.CreatePosition(); path = s_pathParameter.Replace(path, match => { string paramName = match.ToString().Substring(1, match.Length - 2); if (!ServiceDefinitionUtility.IsValidName(paramName)) { paramName = CodeGenUtility.ToCamelCase(paramName); } return($"{{{paramName}}}"); }); string name = CodeGenUtility.ToCamelCase(swaggerOperation.OperationId); if (!ServiceDefinitionUtility.IsValidName(name)) { name = CodeGenUtility.ToCamelCase($"{method} {path}"); } var httpAttributeValues = new List <ServiceAttributeParameterInfo> { new ServiceAttributeParameterInfo("method", method), new ServiceAttributeParameterInfo("path", path), }; var requestFields = new List <ServiceFieldInfo>(); foreach (var swaggerParameter in swaggerOperationsParameters.EmptyIfNull().Concat(swaggerOperation.Parameters.EmptyIfNull())) { AddRequestFields(requestFields, swaggerService.ResolveParameter(swaggerParameter, position), name, method, swaggerService, position); } var responseFields = new List <ServiceFieldInfo>(); var swaggerResponsePairs = swaggerOperation.Responses.EmptyIfNull() .Where(x => x.Key[0] == '2' || x.Key[0] == '3' || !string.IsNullOrEmpty(x.Value.Identifier)).ToList(); foreach (var swaggerResponsePair in swaggerResponsePairs) { AddResponseFields(responseFields, swaggerResponsePair.Key, swaggerService.ResolveResponse(swaggerResponsePair.Value, position), name, httpAttributeValues, swaggerOperation.Responses.Count == 1, swaggerService, position); } var attributes = new List <ServiceAttributeInfo> { new ServiceAttributeInfo("http", httpAttributeValues) }; if (swaggerOperation.Deprecated.GetValueOrDefault()) { attributes.Add(new ServiceAttributeInfo("obsolete")); } members.Add(new ServiceMethodInfo( name: name, requestFields: requestFields, responseFields: responseFields, attributes: attributes, summary: PrepareSummary(swaggerOperation.Summary), remarks: SplitRemarks(swaggerOperation.Description), position: position)); }
private void AddServiceDto(List <IServiceMemberInfo> members, string name, SwaggerSchema schema, SwaggerService swaggerService, NamedTextPosition position) { var attributes = new List <ServiceAttributeInfo>(); if (schema.Obsolete.GetValueOrDefault()) { attributes.Add(new ServiceAttributeInfo("obsolete")); } var fields = new List <ServiceFieldInfo>(); foreach (var property in schema.Properties.EmptyIfNull()) { var fieldAttributes = new List <ServiceAttributeInfo>(); if (property.Value.Obsolete.GetValueOrDefault()) { fieldAttributes.Add(new ServiceAttributeInfo("obsolete")); } string typeName = swaggerService.TryGetFacilityTypeName(property.Value, position); if (typeName != null) { fields.Add(new ServiceFieldInfo( property.Key, typeName: typeName, attributes: fieldAttributes, summary: PrepareSummary(property.Value.Description), position: position)); } } members.Add(new ServiceDtoInfo( name: name, fields: fields, attributes: attributes, summary: PrepareSummary(schema.Description), remarks: SplitRemarks(schema.Remarks), position: position)); }
private ServiceInfo ConvertSwaggerService(SwaggerService swaggerService, SwaggerParserContext context) { if (swaggerService.Swagger == null) { throw context.CreateException("swagger field is missing."); } if (swaggerService.Swagger != SwaggerUtility.SwaggerVersion) { throw context.CreateException($"swagger should be '{SwaggerUtility.SwaggerVersion}'.", "swagger"); } if (swaggerService.Info == null) { throw context.CreateException("info is missing."); } string name = ServiceName; if (name != null && !ServiceDefinitionUtility.IsValidName(name)) { throw context.CreateException("ServiceName generator option is not a valid service name."); } if (name == null) { name = swaggerService.Info?.Identifier; } if (name != null && !ServiceDefinitionUtility.IsValidName(name)) { throw context.CreateException("info/x-identifier is not a valid service name.", "info/x-identifier"); } if (name == null) { name = CodeGenUtility.ToPascalCase(swaggerService.Info?.Title); } if (name == null) { throw context.CreateException("info/title is missing.", "info"); } if (name != null && !ServiceDefinitionUtility.IsValidName(name)) { throw context.CreateException("info/title is not a valid service name.", "info/title"); } var attributes = new List <ServiceAttributeInfo>(); string version = swaggerService.Info?.Version; if (!string.IsNullOrWhiteSpace(version)) { attributes.Add(new ServiceAttributeInfo("info", new[] { new ServiceAttributeParameterInfo("version", version, context.CreatePosition("info/version")) }, context.CreatePosition("info"))); } string scheme = GetBestScheme(swaggerService.Schemes); string host = swaggerService.Host; string basePath = swaggerService.BasePath ?? ""; if (!string.IsNullOrWhiteSpace(host) && !string.IsNullOrWhiteSpace(scheme)) { string url = new UriBuilder(scheme, host) { Path = basePath }.Uri.AbsoluteUri; attributes.Add(new ServiceAttributeInfo("http", new[] { new ServiceAttributeParameterInfo("url", url, context.CreatePosition()) }, context.CreatePosition())); } var position = context.CreatePosition(); var members = new List <IServiceMemberInfo>(); foreach (var swaggerPath in swaggerService.Paths.EmptyIfNull()) { var swaggerOperations = swaggerPath.Value; var operationsContext = context.CreateContext("paths/swaggerPath"); swaggerService.ResolveOperations(ref swaggerOperations, ref operationsContext); AddServiceMethod(members, "GET", swaggerPath.Key, swaggerOperations.Get, swaggerOperations.Parameters, swaggerService, operationsContext.CreateContext("get")); AddServiceMethod(members, "POST", swaggerPath.Key, swaggerOperations.Post, swaggerOperations.Parameters, swaggerService, operationsContext.CreateContext("post")); AddServiceMethod(members, "PUT", swaggerPath.Key, swaggerOperations.Put, swaggerOperations.Parameters, swaggerService, operationsContext.CreateContext("put")); AddServiceMethod(members, "DELETE", swaggerPath.Key, swaggerOperations.Delete, swaggerOperations.Parameters, swaggerService, operationsContext.CreateContext("delete")); AddServiceMethod(members, "OPTIONS", swaggerPath.Key, swaggerOperations.Options, swaggerOperations.Parameters, swaggerService, operationsContext.CreateContext("options")); AddServiceMethod(members, "HEAD", swaggerPath.Key, swaggerOperations.Head, swaggerOperations.Parameters, swaggerService, operationsContext.CreateContext("head")); AddServiceMethod(members, "PATCH", swaggerPath.Key, swaggerOperations.Patch, swaggerOperations.Parameters, swaggerService, operationsContext.CreateContext("patch")); } foreach (var swaggerDefinition in swaggerService.Definitions.EmptyIfNull()) { if ((swaggerDefinition.Value.Type ?? SwaggerSchemaType.Object) == SwaggerSchemaType.Object && !members.OfType <ServiceMethodInfo>().Any(x => swaggerDefinition.Key.Equals(x.Name + "Request", StringComparison.OrdinalIgnoreCase)) && !members.OfType <ServiceMethodInfo>().Any(x => swaggerDefinition.Key.Equals(x.Name + "Response", StringComparison.OrdinalIgnoreCase)) && !swaggerService.IsFacilityError(swaggerDefinition) && swaggerService.TryGetFacilityResultOfType(swaggerDefinition, position) == null) { AddServiceDto(members, swaggerDefinition.Key, swaggerDefinition.Value, swaggerService, context.CreatePosition("definitions/" + swaggerDefinition.Key)); } } return(new ServiceInfo(name, members: members, attributes: attributes, summary: PrepareSummary(swaggerService.Info?.Title), remarks: SplitRemarks(swaggerService.Info?.Description), position: context.CreatePosition())); }
/// <summary> /// Generates Swagger (OpenAPI 2.0) for a service definition. /// </summary> public SwaggerService GenerateSwaggerService(ServiceInfo service) { var httpServiceInfo = HttpServiceInfo.Create(service); var swaggerService = new SwaggerService { Swagger = SwaggerUtility.SwaggerVersion, Info = new SwaggerInfo { Identifier = service.Name, Title = GetSummaryOrNull(service) ?? service.Name, Description = GetRemarksOrNull(service), Version = service.TryGetAttribute("info")?.TryGetParameterValue("version") ?? "0.0.0", CodeGen = CodeGenUtility.GetCodeGenComment(GeneratorName ?? ""), }, }; var defaultBaseUri = httpServiceInfo.Url; if (defaultBaseUri != null) { var baseUri = new Uri(defaultBaseUri); swaggerService.Host = baseUri.Host; swaggerService.Schemes = new[] { baseUri.Scheme }; string basePath = baseUri.PathAndQuery; if (!string.IsNullOrEmpty(basePath) && basePath != "/") { swaggerService.BasePath = baseUri.PathAndQuery; } } var paths = new OurDictionary <string, SwaggerOperations>(); foreach (var httpMethodInfo in httpServiceInfo.Methods) { AddMethodToPaths(paths, service, httpMethodInfo); } swaggerService.Paths = paths; var dtoInfos = new OurDictionary <string, ServiceDtoInfo>(); foreach (var httpMethodInfo in httpServiceInfo.Methods) { if (httpMethodInfo.RequestBodyField != null) { AddDtos(dtoInfos, GetDtosForType(service.GetFieldType(httpMethodInfo.RequestBodyField.ServiceField) !)); } AddDto(dtoInfos, TryCreateMethodRequestBodyType(httpMethodInfo)?.Dto); foreach (var httpResponseInfo in httpMethodInfo.ValidResponses) { if (httpResponseInfo.BodyField != null) { AddDtos(dtoInfos, GetDtosForType(service.GetFieldType(httpResponseInfo.BodyField.ServiceField) !)); } AddDto(dtoInfos, TryCreateMethodResponseBodyType(httpMethodInfo, httpResponseInfo)?.Dto); } } while (true) { var dtoCount = dtoInfos.Count; foreach (var field in dtoInfos.Values.SelectMany(x => x.Fields).ToList()) { AddDtos(dtoInfos, GetDtosForType(service.GetFieldType(field) !)); } if (dtoCount == dtoInfos.Count) { break; } } var definitions = new OurDictionary <string, SwaggerSchema>(); foreach (var dtoInfo in dtoInfos.Values) { definitions[dtoInfo.Name] = GetDtoSchema(service, dtoInfo); } swaggerService.Definitions = definitions.Count == 0 ? null : definitions; return(swaggerService); }
internal static bool IsFacilityError(this SwaggerService swaggerService, KeyValuePair <string, SwaggerSchema> swaggerSchema) { return(swaggerSchema.Key == "Error" && swaggerSchema.Value.Properties.EmptyIfNull().Any(x => x.Key == "code" && x.Value.Type == SwaggerSchemaType.String) && swaggerSchema.Value.Properties.EmptyIfNull().Any(x => x.Key == "message" && x.Value.Type == SwaggerSchemaType.String)); }
private SwaggerConversion(SwaggerService swaggerService, string?serviceName) { m_swaggerService = swaggerService; m_serviceName = serviceName; m_errors = new List <ServiceDefinitionError>(); }
private static void AddFieldsFromSchema(IList <ServiceFieldInfo> requestFields, SwaggerService swaggerService, NamedTextPosition position, KeyValuePair <string, SwaggerSchema> bodySchema) { if ((bodySchema.Value.Type ?? SwaggerSchemaType.Object) != SwaggerSchemaType.Object) { throw new NotImplementedException(); } foreach (var property in bodySchema.Value.Properties.EmptyIfNull()) { var attributes = new List <ServiceAttributeInfo>(); if (property.Value.Obsolete.GetValueOrDefault()) { attributes.Add(new ServiceAttributeInfo("obsolete")); } string typeName = swaggerService.TryGetFacilityTypeName(property.Value, position); if (typeName != null) { requestFields.Add(new ServiceFieldInfo( property.Key, typeName: typeName, attributes: attributes, summary: PrepareSummary(property.Value.Description), position: position)); } } }
/// <summary> /// Converts Swagger (OpenAPI) 2.0 into a service definition. /// </summary> public ServiceInfo ConvertSwaggerService(SwaggerService swaggerService) { return(ConvertSwaggerService(swaggerService, SwaggerParserContext.None)); }
/// <summary> /// Converts Swagger (OpenAPI) 2.0 into a service definition. /// </summary> /// <exception cref="ServiceDefinitionException">Thrown if the service would be invalid.</exception> public ServiceInfo ConvertSwaggerService(SwaggerService swaggerService) { if (TryConvertSwaggerService(swaggerService, out var service, out var errors)) { return(service !); }