From 90010da61db4c05d6fca6fdbda3bcd3474ae26b3 Mon Sep 17 00:00:00 2001 From: Stephane Carrez Date: Wed, 4 Oct 2017 05:51:04 +0200 Subject: [PATCH] [Ada] Adding Ada support for client code generator (#6602) * Ada language support (generic generator) Implement the AbstractAdaCodegen class with the Ada keywords and global behavior for Ada language * Ada language support (main generator) Implement the AdaCodegen class for the Ada client and server code generator Initial implementation based on a mix from CppRestClientCodegen, NodeJSServerCodegen * Ada language support: register the AdaCodegen generator class * Ada language license template * Ada language model templates (spec and body) * Ada language client spec and body templates * Ada language server spec and body templates * Fix escaping Ada keywords for parameter name * Generate GNAT project and update type mappings - Use 'p_' as escape prefix for parameter names because identifiers are not allowed to start with '_' - Add GNAT project file generation - Update the type mappings to use the Swagger package types * Fix generation of operations with no parameters * Fix instantiation of Ada.Containers.Vectors package in generated model files * New template for the GNAT project file generation * Fix datatype generation for Ada language - Override the getTypeDeclaration function to specify the datatype - Fix definition of language predefined types * Add a Serialize procedure declaration for the Ada model generation * Add a Serialize procedure for the Ada template model generation * Fix operation name and parameter name for Ada - Declare and implement toAdaIdentifier function to verify and turn some identifier to Ada identifier following Ada style - Override toOperationId and use toAdaIdentifier for generation of operation name - Update toParamName to use toAdaIdentifier * Media type support for Ada code generator - Implement postProcessMediaTypes function to add a 'adaMediaType' member to each media type and map it to some Ada enumeration - Post process the 'produces' and 'consumes' media type of an operation * Use x-has-notes extension to avoid emitting notes when they are empty * First generation for Ada client operation body * Add a x-has-uniq-produces and x-has-uniq-consumes to media types to indicate that the list contains only one item, this is necessary for Ada generator for generation of arrays with one item only * Add a postProcessParameter for Ada code generator to emit a x-is-model-type attribute * Update Ada client body template for the serialization of data * Fix postProcessParameter in Ada code generator to take into account file parameters * Update the Ada client body to support form parameters * Fix type name used for mapped types in the Ada generator * Declare a Deserialize procedure for the Ada generated model * Override the fromOperation for Ada client code generator - Emit a x-codegen-response extension with the response description type - Emit a x-id-model-type extension for each type property * Update the Ada client package spec template to declare the result type * Add support to extract response and return result in Ada client code * Fix Ada postProcessModels to handle container properties and emit a correct x-is-model-type attribute * Add support for Deserialize procedure in the Ada model generator * Fix indentation of generated Ada client body package * Add projectName option to configure the GNAT project name * Update the GNAT project name for the Ada code generator * Cleanup implementation and remove unused code * Cleanup implementation and remove unused code * Fix javadoc errors * Use 'ada' for the language name to follow swagger-codegen convention Add (beta) to the help description Fix a NPE that occurs with incomplete yaml descriptions --- .../codegen/languages/AbstractAdaCodegen.java | 163 ++++++++ .../swagger/codegen/languages/AdaCodegen.java | 362 ++++++++++++++++++ .../main/resources/Ada/client-body.mustache | 50 +++ .../main/resources/Ada/client-spec.mustache | 25 ++ .../main/resources/Ada/gnat-project.mustache | 23 ++ .../main/resources/Ada/licenseInfo.mustache | 9 + .../main/resources/Ada/model-body.mustache | 62 +++ .../main/resources/Ada/model-spec.mustache | 43 +++ .../main/resources/Ada/server-body.mustache | 19 + .../main/resources/Ada/server-spec.mustache | 20 + .../services/io.swagger.codegen.CodegenConfig | 1 + 11 files changed, 777 insertions(+) create mode 100644 modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/AbstractAdaCodegen.java create mode 100644 modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/AdaCodegen.java create mode 100644 modules/swagger-codegen/src/main/resources/Ada/client-body.mustache create mode 100644 modules/swagger-codegen/src/main/resources/Ada/client-spec.mustache create mode 100644 modules/swagger-codegen/src/main/resources/Ada/gnat-project.mustache create mode 100644 modules/swagger-codegen/src/main/resources/Ada/licenseInfo.mustache create mode 100644 modules/swagger-codegen/src/main/resources/Ada/model-body.mustache create mode 100644 modules/swagger-codegen/src/main/resources/Ada/model-spec.mustache create mode 100644 modules/swagger-codegen/src/main/resources/Ada/server-body.mustache create mode 100644 modules/swagger-codegen/src/main/resources/Ada/server-spec.mustache diff --git a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/AbstractAdaCodegen.java b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/AbstractAdaCodegen.java new file mode 100644 index 00000000000..eb6e0263ac9 --- /dev/null +++ b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/AbstractAdaCodegen.java @@ -0,0 +1,163 @@ +package io.swagger.codegen.languages; + +import io.swagger.codegen.CodegenConfig; +import io.swagger.codegen.CodegenProperty; +import io.swagger.codegen.DefaultCodegen; +import io.swagger.models.properties.Property; + +import java.util.Arrays; + +abstract public class AbstractAdaCodegen extends DefaultCodegen implements CodegenConfig { + + public AbstractAdaCodegen() { + super(); + + /* + * Reserved words. Override this with reserved words specific to your language + */ + setReservedWordsLowerCase( + Arrays.asList( + "abort", + "abs", + "abstract", + "accept", + "access", + "aliased", + "all", + "and", + "array", + "at", + "begin", + "body", + "case", + "constant", + "declare", + "delay", + "digits", + "do", + "else", + "elsif", + "end", + "entry", + "exception", + "exit", + "for", + "function", + "generic", + "goto", + "if", + "in", + "interface", + "is", + "limited", + "loop", + "mod", + "new", + "not", + "null", + "of", + "or", + "others", + "out", + "overriding", + "package", + "pragma", + "private", + "procedure", + "protected", + "raise", + "range", + "record", + "rem", + "renames", + "requeue", + "return", + "reverse", + "select", + "separate", + "some", + "subtype", + "synchronized", + "tagged", + "task", + "terminate", + "then", + "type", + "until", + "use", + "when", + "while", + "with", + "xor") + ); + } + + /** + * Turn a parameter name, operation name into an Ada identifier. + * + * Ada programming standard avoid the camelcase syntax and prefer the underscore + * notation. We also have to make sure the identifier is not a reserved keyword. + * When this happens, we add the configurable prefix. The function translates: + * + * body - P_Body + * petId - Pet_Id + * updatePetWithForm - Update_Pet_With_Form + * + * @param name the parameter name. + * @param prefix the optional prefix in case the parameter name is a reserved keyword. + * @return the Ada identifier to be used. + */ + protected String toAdaIdentifier(String name, String prefix) { + // We cannot use reserved keywords for identifiers + if (isReservedWord(name)) { + LOGGER.warn("Identifier '" + name + "' is a reserved word, renamed to " + prefix + name); + name = prefix + name; + } + StringBuilder result = new StringBuilder(); + boolean needUpperCase = true; + for (int i = 0; i < name.length(); i++) { + char c = name.charAt(i); + if (needUpperCase) { + needUpperCase = false; + result.append(Character.toUpperCase(c)); + + } else if (Character.isUpperCase((c))) { + if (!needUpperCase) { + result.append('_'); + } + result.append(c); + needUpperCase = false; + } else { + result.append(c); + if (c == '_') { + needUpperCase = true; + } + } + } + return result.toString(); + } + + @Override + public String toOperationId(String operationId) { + return toAdaIdentifier(sanitizeName(operationId), "Call_"); + } + + @Override + public String toVarName(String name) { + return toAdaIdentifier(sanitizeName(name), "P_"); + } + + @Override + public String toParamName(String name) { + return toAdaIdentifier(super.toParamName(name), "P_"); + } + + @Override + public CodegenProperty fromProperty(String name, Property p) { + CodegenProperty property = super.fromProperty(name, p); + String nameInCamelCase = property.nameInCamelCase; + nameInCamelCase = sanitizeName(nameInCamelCase); + property.nameInCamelCase = nameInCamelCase; + return property; + } +} diff --git a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/AdaCodegen.java b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/AdaCodegen.java new file mode 100644 index 00000000000..309f9a2bada --- /dev/null +++ b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/AdaCodegen.java @@ -0,0 +1,362 @@ +package io.swagger.codegen.languages; + +import java.io.File; +import java.util.*; + +import io.swagger.codegen.*; +import io.swagger.models.Model; +import io.swagger.models.Operation; +import io.swagger.models.Response; +import io.swagger.models.Swagger; +import io.swagger.models.properties.*; + +public class AdaCodegen extends AbstractAdaCodegen implements CodegenConfig { + protected String packageName = "swagger"; + protected String projectName = "Swagger"; + protected List> orderedModels; + protected Map> modelDepends; + + public AdaCodegen() { + super(); + + modelNameSuffix = "_Type"; + orderedModels = new ArrayList>(); + modelDepends = new HashMap>(); + embeddedTemplateDir = templateDir = "Ada"; + + // CLI options + addOption(CodegenConstants.PROJECT_NAME, "GNAT project name", + this.projectName); + addOption(CodegenConstants.PACKAGE_NAME, "Ada package name (convention: name.space.model).", + this.modelPackage); + addOption(CodegenConstants.MODEL_PACKAGE, "Ada package for models (convention: name.space.model).", + this.modelPackage); + addOption(CodegenConstants.API_PACKAGE, "Ada package for apis (convention: name.space.api).", + this.apiPackage); + + languageSpecificPrimitives = new HashSet( + Arrays.asList("integer", "boolean", "Integer", "Character", "Boolean", "long", "float", "double", "int32_t", "int64_t")); + + typeMapping = new HashMap(); + typeMapping.put("date", "Swagger.Date"); + typeMapping.put("DateTime", "Swagger.Datetime"); + typeMapping.put("string", "Swagger.UString"); + typeMapping.put("integer", "Integer"); + typeMapping.put("long", "Swagger.Long"); + typeMapping.put("boolean", "Boolean"); + typeMapping.put("array", "Swagger.Vector"); + typeMapping.put("map", "Swagger.Map"); + typeMapping.put("object", "Swagger.Object"); + typeMapping.put("number", "Swagger.Number"); + typeMapping.put("UUID", "Swagger.UString"); + typeMapping.put("file", "Swagger.Http_Content_Type"); + typeMapping.put("binary", "Swagger.Binary"); + + super.importMapping = new HashMap(); + } + + @Override + public CodegenType getTag() { + return CodegenType.CLIENT; + } + + @Override + public String getName() { + return "ada"; + } + + @Override + public String getHelp() { + return "Generates an Ada client implementation (beta)."; + } + + protected void addOption(String key, String description, String defaultValue) { + CliOption option = new CliOption(key, description); + if (defaultValue != null) + option.defaultValue(defaultValue); + cliOptions.add(option); + } + + public String toFilename(String name) { + return name.replace(".", "-").toLowerCase(); + } + + @Override + public void processOpts() { + super.processOpts(); + if (additionalProperties.containsKey(CodegenConstants.PACKAGE_NAME)) { + packageName = (String) additionalProperties.get(CodegenConstants.PACKAGE_NAME); + } + String serverPrefix = "src" + File.separator + "server" + File.separator + toFilename(modelPackage); + String clientPrefix = "src" + File.separator + "client" + File.separator + toFilename(modelPackage); + supportingFiles.add(new SupportingFile("model-spec.mustache", null, clientPrefix + "-models.ads")); + supportingFiles.add(new SupportingFile("model-body.mustache", null, clientPrefix + "-models.adb")); + supportingFiles.add(new SupportingFile("model-spec.mustache", null, serverPrefix + "-models.ads")); + supportingFiles.add(new SupportingFile("model-body.mustache", null, serverPrefix + "-models.adb")); + supportingFiles.add(new SupportingFile("client-spec.mustache", null, clientPrefix + "-clients.ads")); + supportingFiles.add(new SupportingFile("client-body.mustache", null, clientPrefix + "-clients.adb")); + supportingFiles.add(new SupportingFile("server-spec.mustache", null, serverPrefix + "-servers.ads")); + supportingFiles.add(new SupportingFile("server-body.mustache", null, serverPrefix + "-servers.adb")); + + // String title = swagger.getInfo().getTitle(); + supportingFiles.add(new SupportingFile("gnat-project.mustache", "", "project.gpr")); + + if (additionalProperties.containsKey(CodegenConstants.PROJECT_NAME)) { + projectName = (String) additionalProperties.get(CodegenConstants.PROJECT_NAME); + } else { + // default: set project based on package name + // e.g. petstore.api (package name) => petstore_api (project name) + projectName = packageName.replaceAll("\\.", "_"); + } + + /* + * Additional Properties. These values can be passed to the templates and + * are available in models, apis, and supporting files + */ + additionalProperties.put("package", this.modelPackage); + additionalProperties.put(CodegenConstants.PROJECT_NAME, projectName); + } + + @Override + public String apiFileFolder() { + return outputFolder + "/" + apiPackage().replace('.', File.separatorChar); + } + + @Override + public String modelFileFolder() { + return outputFolder + "/model/" + modelPackage().replace('.', File.separatorChar); + } + + /** + * Escapes a reserved word as defined in the `reservedWords` array. Handle + * escaping those terms here. This logic is only called if a variable + * matches the reserved words + * + * @return the escaped term + */ + @Override + public String escapeReservedWord(String name) { + return "p_" + name; // add an underscore to the name + } + + @Override + public String escapeQuotationMark(String input) { + // remove " to avoid code injection + return input.replace("\"", ""); + } + + @Override + public String escapeUnsafeCharacters(String input) { + return input.replace("*/", "*_/").replace("/*", "/_*"); + } + + /** + * Optional - type declaration. This is a String which is used by the + * templates to instantiate your types. There is typically special handling + * for different property types + * + * @return a string value used as the `dataType` field for model templates, + * `returnType` for api templates + */ + @Override + public String getTypeDeclaration(Property p) { + String swaggerType = getSwaggerType(p); + + if (p instanceof ArrayProperty) { + ArrayProperty ap = (ArrayProperty) p; + Property inner = ap.getItems(); + return getTypeDeclaration(inner) + "_Vectors.Vector"; + } + if (p instanceof MapProperty) { + MapProperty mp = (MapProperty) p; + Property inner = mp.getAdditionalProperties(); + return "Swagger." + getTypeDeclaration(inner) + "_Map"; + } + if (typeMapping.containsKey(swaggerType)) { + return typeMapping.get(swaggerType); + } + // LOGGER.info("Swagger type " + swaggerType); + if (languageSpecificPrimitives.contains(swaggerType)) { + return swaggerType; + } + String modelType = toModelName(swaggerType); + if (p instanceof StringProperty || p instanceof DateProperty + || p instanceof DateTimeProperty || p instanceof FileProperty + || languageSpecificPrimitives.contains(modelType)) { + return modelType; + } + + return modelPackage + ".Models." + modelType; + } + + /** + * Overrides postProcessParameter to add a vendor extension "x-is-model-type". + * This boolean indicates that the parameter comes from the model package. + * + * @param parameter CodegenParameter object to be processed. + */ + @Override + public void postProcessParameter(CodegenParameter parameter){ + // Give the base class a chance to process + super.postProcessParameter(parameter); + + boolean isModel = parameter.dataType.startsWith(modelPackage); + if (!isModel && !parameter.isPrimitiveType && !parameter.isDate + && !parameter.isString && !parameter.isContainer && !parameter.isFile) { + isModel = true; + } + parameter.vendorExtensions.put("x-is-model-type", isModel); + } + + /** + * Post process the media types (produces and consumes) for Ada code generator. + * + * For each media type, add a adaMediaType member that gives the Ada enum constant + * for the corresponding type. + * + * @param types the list of media types. + * @return the number of media types. + */ + protected int postProcessMediaTypes(List> types) { + int count = 0; + if (types != null) { + for (Map media : types) { + String mt = media.get("mediaType"); + if (mt != null) { + mt = mt.replace('/', '_'); + media.put("adaMediaType", mt.toUpperCase()); + count++; + } + } + } + return count; + } + + @Override + public CodegenOperation fromOperation(String path, String httpMethod, Operation operation, + Map definitions, Swagger swagger) { + CodegenOperation op = super.fromOperation(path, httpMethod, operation, definitions, swagger); + + if (operation.getResponses() != null && !operation.getResponses().isEmpty()) { + Response methodResponse = findMethodResponse(operation.getResponses()); + + if (methodResponse != null) { + if (methodResponse.getSchema() != null) { + CodegenProperty cm = fromProperty("response", methodResponse.getSchema()); + op.vendorExtensions.put("x-codegen-response", cm); + if(cm.datatype == "HttpContent") { + op.vendorExtensions.put("x-codegen-response-ishttpcontent", true); + } + } + } + } + return op; + } + + @SuppressWarnings("unchecked") + @Override + public Map postProcessOperations(Map objs) { + Map operations = (Map) objs.get("operations"); + List operationList = (List) operations.get("operation"); + + for (CodegenOperation op1 : operationList) { + op1.vendorExtensions.put("x-has-uniq-produces", postProcessMediaTypes(op1.produces) == 1); + op1.vendorExtensions.put("x-has-uniq-consumes", postProcessMediaTypes(op1.consumes) == 1); + op1.vendorExtensions.put("x-has-notes", op1.notes.length() > 0); + } + return objs; + } + + @Override + public Map postProcessModels(Map objs) { + // Collect the model dependencies. + List> models = (List>) objs.get("models"); + for (Map model : models) { + Object v = model.get("model"); + if (v instanceof CodegenModel) { + CodegenModel m = (CodegenModel) v; + List d = new ArrayList(); + for (CodegenProperty p : m.allVars) { + boolean isModel = false; + CodegenProperty item = p; + if (p.isContainer) { + item = p.items; + } + if (item != null && !item.isString && !item.isPrimitiveType && !item.isContainer && !item.isInteger) { + if (!d.contains(item.datatype)) { + // LOGGER.info("Model " + m.name + " uses " + p.datatype); + d.add(item.datatype); + isModel = true; + } + } + p.vendorExtensions.put("x-is-model-type", isModel); + } + modelDepends.put(m.name, d); + orderedModels.add(model); + } + } + + // Sort the models according to dependencies so that model that depend + // on others appear at end of the list. + final Map> deps = modelDepends; + Collections.sort(orderedModels, new Comparator>() { + @Override + public int compare(Map lhs, Map rhs) { + Object v = lhs.get("model"); + String lhsName = ((CodegenModel) v).name; + v = rhs.get("model"); + String rhsName = ((CodegenModel) v).name; + List lhsList = deps.get(lhsName); + List rhsList = deps.get(rhsName); + if (lhsList == rhsList) { + // LOGGER.info("First compare " + lhsName + "<" + rhsName); + return lhsName.compareTo(rhsName); + } + // Put models without dependencies first. + if (lhsList == null) { + // LOGGER.info(" Empty " + lhsName + ", no check " + rhsName); + return -1; + } + if (rhsList == null) { + // LOGGER.info(" No check " + lhsName + ", empty " + rhsName); + return 1; + } + // Put models that depend on another after. + if (lhsList.contains(rhsName)) { + // LOGGER.info(" LSH " + lhsName + " uses " + rhsName); + return 1; + } + if (rhsList.contains(lhsName)) { + // LOGGER.info(" RHS " + rhsName + " uses " + lhsName); + return -1; + } + // Put models with less dependencies first. + if (lhsList.size() < rhsList.size()) { + // LOGGER.info(" LSH size " + lhsName + " < RHS size " + rhsName); + return -1; + } + if (lhsList.size() > rhsList.size()) { + // LOGGER.info(" LSH size " + lhsName + " > RHS size " + rhsName); + return 1; + } + // Sort models on their name. + // LOGGER.info("Compare " + lhsName + "<" + rhsName); + return lhsName.compareTo(rhsName); + } + }); + /* for (Map model : orderedModels) { + Object v = model.get("model"); + if (v instanceof CodegenModel) { + CodegenModel m = (CodegenModel) v; + LOGGER.info("Order: " + m.name); + } + }*/ + return postProcessModelsEnum(objs); + } + + @Override + public Map postProcessSupportingFileData(Map objs) { + objs.put("orderedModels", orderedModels); + return super.postProcessSupportingFileData(objs); + } +} diff --git a/modules/swagger-codegen/src/main/resources/Ada/client-body.mustache b/modules/swagger-codegen/src/main/resources/Ada/client-body.mustache new file mode 100644 index 00000000000..0aa184749af --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/Ada/client-body.mustache @@ -0,0 +1,50 @@ +{{>licenseInfo}} +with Swagger.Streams; +package body {{package}}.Clients is +{{#apiInfo}} +{{#apis}} +{{#operations}} +{{#operation}} + + -- {{summary}}{{#vendorExtensions.x-has-notes}} + -- {{unescapedNotes}}{{/vendorExtensions.x-has-notes}} + procedure {{operationId}} + (Client : in out Client_Type{{#hasParams}};{{/hasParams}}{{#allParams}} + {{paramName}} : in {{^isFile}}{{^isString}}{{^isPrimitiveType}}{{^isContainer}}{{package}}.Models.{{/isContainer}}{{/isPrimitiveType}}{{/isString}}{{/isFile}}{{dataType}}{{#hasMore}};{{/hasMore}}{{/allParams}}{{#returnType}}; + Result : out {{returnType}}{{/returnType}}) is + URI : Swagger.Clients.URI_Type;{{#hasBodyParam}} + Req : Swagger.Clients.Request_Type;{{/hasBodyParam}}{{#hasFormParams}} + Req : Swagger.Clients.Request_Type;{{/hasFormParams}} + {{#returnType}} + Reply : Swagger.Value_Type; + {{/returnType}} + begin + Client.Set_Accept (({{#hasProduces}}{{#produces}}{{#vendorExtensions.x-has-uniq-produces}}1 => {{/vendorExtensions.x-has-uniq-produces}}Swagger.Clients.{{adaMediaType}}{{#hasMore}}, + {{/hasMore}}{{/produces}}{{/hasProduces}}));{{#hasBodyParam}} + Client.Initialize (Req, ({{#hasConsumes}}{{#consumes}}{{#vendorExtensions.x-has-uniq-consumes}}1 -> {{/vendorExtensions.x-has-uniq-consumes}}Swagger.Clients.{{adaMediaType}}{{#hasMore}}, + {{/hasMore}}{{/consumes}}{{/hasConsumes}}{{^hasConsumes}}1 => Swagger.Clients.APPLICATION_JSON{{/hasConsumes}}));{{#bodyParams}}{{#vendorExtensions.x-is-model-type}} + {{package}}.Models.Serialize (Req.Stream, "{{baseName}}", {{paramName}});{{/vendorExtensions.x-is-model-type}}{{^vendorExtensions.x-is-model-type}}{{#isFile}} + -- TODO: Serialize (Req.Stream, "{{basename}}", {{paramName}});{{/isFile}}{{^isFile}}{{^isLong}} + Req.Stream.Write_Entity ("{{baseName}}", {{paramName}});{{/isLong}}{{#isLong}} + Serialize (Req.Stream, "{{baseName}}", {{paramName}});{{/isLong}}{{/isFile}}{{/vendorExtensions.x-is-model-type}}{{/bodyParams}}{{/hasBodyParam}}{{#hasFormParams}} + Client.Initialize (Req, (1 => Swagger.Clients.APPLICATION_FORM));{{#formParams}}{{#vendorExtensions.x-is-model-type}} + {{package}}.Models.Serialize (Req.Stream, "{{baseName}}", {{paramName}});{{/vendorExtensions.x-is-model-type}}{{^vendorExtensions.x-is-model-type}} + Req.Stream.Write_Entity ("{{baseName}}", {{paramName}});{{/vendorExtensions.x-is-model-type}}{{/formParams}}{{/hasFormParams}} +{{#queryParams}}{{#isQueryParam}}{{^isPrimitiveType}}{{^isString}}{{^isContainer}}{{^isDateTime}} + URI.Add_Param ("{{baseName}}", {{paramName}});{{/isDateTime}}{{/isContainer}}{{/isString}}{{/isPrimitiveType}}{{#isPrimitiveType}}{{^isLong}} + URI.Add_Param ("{{baseName}}", {{paramName}});{{/isLong}}{{/isPrimitiveType}}{{#isLong}} + URI.Add_Param ("{{baseName}}", {{paramName}});{{/isLong}}{{#isContainer}} + URI.Add_Param ("{{baseName}}", {{paramName}});{{/isContainer}}{{#isDateTime}} + URI.Add_Param ("{{baseName}}", {{paramName}});{{/isDateTime}}{{/isQueryParam}}{{/queryParams}} + URI.Set_Path ("{{path}}");{{#pathParams}} + URI.Set_Path_Param ("{{baseName}}", {{^isString}}Swagger.To_String ({{/isString}}{{paramName}}{{^isString}}){{/isString}});{{/pathParams}} + Client.Call (Swagger.Clients.{{httpMethod}}, URI{{#hasBodyParam}}, Req{{/hasBodyParam}}{{#returnType}}, Reply{{/returnType}});{{#returnType}}{{#vendorExtensions.x-codegen-response.isString}} + Swagger.Streams.Deserialize (Reply, "", Result);{{/vendorExtensions.x-codegen-response.isString}}{{^vendorExtensions.x-codegen-response.isString}}{{#returnTypeIsPrimitive}} + Swagger.Streams.Deserialize (Reply, "", Result);{{/returnTypeIsPrimitive}}{{^returnTypeIsPrimitive}} + {{package}}.Models.Deserialize (Reply, "", Result);{{/returnTypeIsPrimitive}}{{/vendorExtensions.x-codegen-response.isString}}{{/returnType}} + end {{operationId}}; +{{/operation}} +{{/operations}} +{{/apis}} +{{/apiInfo}} +end {{package}}.Clients; diff --git a/modules/swagger-codegen/src/main/resources/Ada/client-spec.mustache b/modules/swagger-codegen/src/main/resources/Ada/client-spec.mustache new file mode 100644 index 00000000000..67ca7d08c22 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/Ada/client-spec.mustache @@ -0,0 +1,25 @@ +{{>licenseInfo}} +{{#imports}}with {{import}}; +{{/imports}} +with {{package}}.Models; +with Swagger.Clients; +package {{package}}.Clients is + + type Client_Type is new Swagger.Clients.Client_Type with null record; + +{{#apiInfo}} +{{#apis}} +{{#operations}} +{{#operation}} + -- {{summary}}{{#vendorExtensions.x-has-notes}} + -- {{unescapedNotes}}{{/vendorExtensions.x-has-notes}} + procedure {{operationId}} + (Client : in out Client_Type{{#hasParams}};{{/hasParams}}{{#allParams}} + {{paramName}} : in {{^isFile}}{{^isString}}{{^isPrimitiveType}}{{^isContainer}}{{package}}.Models.{{/isContainer}}{{/isPrimitiveType}}{{/isString}}{{/isFile}}{{dataType}}{{#hasMore}};{{/hasMore}}{{/allParams}}{{#returnType}}; + Result : out {{returnType}}{{/returnType}}); + +{{/operation}} +{{/operations}} +{{/apis}} +{{/apiInfo}} +end {{package}}.Clients; diff --git a/modules/swagger-codegen/src/main/resources/Ada/gnat-project.mustache b/modules/swagger-codegen/src/main/resources/Ada/gnat-project.mustache new file mode 100644 index 00000000000..f07f3006cc8 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/Ada/gnat-project.mustache @@ -0,0 +1,23 @@ +-- {{{appName}}} +-- {{{appDescription}}} +-- OpenAPI spec version: 1.0.0 +-- +-- https://github.com/swagger-api/swagger-codegen.git +-- + -- NOTE: Auto generated by the swagger code generator program. +with "config"; +with "util"; +with "asf"; +project {{{projectName}}} is + + Mains := ("{{{appName}}}-server.adb"); + for Main use Mains; + for Source_Dirs use ("src", "src/client", "src/server"); + for Object_Dir use "./" & Config'Exec_Dir & "/bin"; + + package Binder renames Config.Binder; + package Builder renames Config.Builder; + package Compiler renames Config.Compiler; + package Linker renames Config.Linker; + +end {{{projectName}}}; diff --git a/modules/swagger-codegen/src/main/resources/Ada/licenseInfo.mustache b/modules/swagger-codegen/src/main/resources/Ada/licenseInfo.mustache new file mode 100644 index 00000000000..6c6c4b246e5 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/Ada/licenseInfo.mustache @@ -0,0 +1,9 @@ +-- {{{appName}}} +-- {{{appDescription}}} +-- +-- {{#version}}OpenAPI spec version: {{{version}}}{{/version}} +-- {{#infoEmail}}Contact: {{{infoEmail}}}{{/infoEmail}} +-- +-- NOTE: This package is auto generated by the swagger code generator {{{generatorVersion}}}. +-- https://github.com/swagger-api/swagger-codegen.git +-- Do not edit the class manually. \ No newline at end of file diff --git a/modules/swagger-codegen/src/main/resources/Ada/model-body.mustache b/modules/swagger-codegen/src/main/resources/Ada/model-body.mustache new file mode 100644 index 00000000000..120de7b25cd --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/Ada/model-body.mustache @@ -0,0 +1,62 @@ +{{>licenseInfo}} + +package body {{package}}.Models is + + use Swagger.Streams; + +{{#orderedModels}} +{{#model}} + + procedure Serialize (Into : in out Swagger.Streams.Output_Stream'Class; + Name : in String; + Value : in {{classname}}) is + begin + Into.Start_Entity (Name);{{#vars}}{{^isPrimitiveType}}{{^isString}}{{^isContainer}}{{^isDateTime}} + Serialize (Into, "{{baseName}}", Value.{{name}});{{/isDateTime}}{{/isContainer}}{{/isString}}{{/isPrimitiveType}}{{#isPrimitiveType}}{{^isLong}} + Into.Write_Entity ("{{baseName}}", Value.{{name}});{{/isLong}}{{/isPrimitiveType}}{{#isLong}} + Serialize (Into, "{{baseName}}", Value.{{name}});{{/isLong}}{{#isString}} + Into.Write_Entity ("{{baseName}}", Value.{{name}});{{/isString}}{{#isContainer}} + Serialize (Into, "{{baseName}}", Value.{{name}});{{/isContainer}}{{#isDateTime}} + Into.Write_Entity ("{{baseName}}", Value.{{name}});{{/isDateTime}}{{/vars}} + Into.End_Entity (Name); + end Serialize; + + procedure Serialize (Into : in out Swagger.Streams.Output_Stream'Class; + Name : in String; + Value : in {{classname}}_Vectors.Vector) is + begin + Into.Start_Array (Name); + for Item of Value loop + Serialize (Into, "", Item); + end loop; + Into.End_Array (Name); + end Serialize; + + procedure Deserialize (From : in Swagger.Value_Type; + Name : in String; + Value : out {{classname}}) is + Object : Swagger.Value_Type; + begin + Swagger.Streams.Deserialize (From, Name, Object);{{#vars}}{{#vendorExtensions.x-is-model-type}} + Deserialize (Object, "{{baseName}}", Value.{{name}});{{/vendorExtensions.x-is-model-type}}{{^vendorExtensions.x-is-model-type}} + Swagger.Streams.Deserialize (Object, "{{baseName}}", Value.{{name}});{{/vendorExtensions.x-is-model-type}}{{/vars}} + end Deserialize; + + procedure Deserialize (From : in Swagger.Value_Type; + Name : in String; + Value : out {{classname}}_Vectors.Vector) is + List : Swagger.Value_Array_Type; + Item : {{classname}}; + begin + Value.Clear; + Swagger.Streams.Deserialize (From, Name, List); + for Data of List loop + Deserialize (Data, "", Item); + Value.Append (Item); + end loop; + end Deserialize; + +{{/model}} +{{/orderedModels}} + +end {{package}}.Models; diff --git a/modules/swagger-codegen/src/main/resources/Ada/model-spec.mustache b/modules/swagger-codegen/src/main/resources/Ada/model-spec.mustache new file mode 100644 index 00000000000..bed1aa4207d --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/Ada/model-spec.mustache @@ -0,0 +1,43 @@ +{{>licenseInfo}} +{{#imports}}with {{import}}; +{{/imports}} +with Swagger.Streams; +with Ada.Containers.Vectors; +package {{package}}.Models is + +{{#orderedModels}}{{#model}} + -- ------------------------------ + -- {{title}} + -- {{description}} + -- ------------------------------ + type {{classname}} is + record + {{#vars}} + {{name}} : {{datatype}}; + {{/vars}} + end record; + + package {{classname}}_Vectors is + new Ada.Containers.Vectors (Index_Type => Positive, + Element_Type => {{classname}}); + + procedure Serialize (Into : in out Swagger.Streams.Output_Stream'Class; + Name : in String; + Value : in {{classname}}); + + procedure Serialize (Into : in out Swagger.Streams.Output_Stream'Class; + Name : in String; + Value : in {{classname}}_Vectors.Vector); + + procedure Deserialize (From : in Swagger.Value_Type; + Name : in String; + Value : out {{classname}}); + + procedure Deserialize (From : in Swagger.Value_Type; + Name : in String; + Value : out {{classname}}_Vectors.Vector); + +{{/model}} +{{/orderedModels}} + +end {{package}}.Models; diff --git a/modules/swagger-codegen/src/main/resources/Ada/server-body.mustache b/modules/swagger-codegen/src/main/resources/Ada/server-body.mustache new file mode 100644 index 00000000000..dc1ac8c7528 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/Ada/server-body.mustache @@ -0,0 +1,19 @@ +{{>licenseInfo}} +package body {{package}}.Servers is +{{#apiInfo}} +{{#apis}} +{{#operations}} +{{#operation}} + + -- {{summary}} + -- {{notes}} + procedure {{operationId}} ({{#allParams}}{{paramName}} : in {{dataType}}{{#hasMore}}; + {{/hasMore}}{{/allParams}}) is + begin + null; + end {{operationId}}; +{{/operation}} +{{/operations}} +{{/apis}} +{{/apiInfo}} +end {{package}}.Servers; diff --git a/modules/swagger-codegen/src/main/resources/Ada/server-spec.mustache b/modules/swagger-codegen/src/main/resources/Ada/server-spec.mustache new file mode 100644 index 00000000000..0d887b15d36 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/Ada/server-spec.mustache @@ -0,0 +1,20 @@ +{{>licenseInfo}} +{{#imports}}with {{import}}; +{{/imports}} +with {{package}}.Models; +package {{package}}.Servers is +{{#apiInfo}} +{{#apis}} +{{#operations}} +{{#operation}} + + -- {{summary}} + -- {{notes}} + procedure {{operationId}} ({{#allParams}}{{paramName}} : in {{dataType}}{{#hasMore}}; + {{/hasMore}}{{/allParams}}); + +{{/operation}} +{{/operations}} +{{/apis}} +{{/apiInfo}} +end {{package}}.Servers; diff --git a/modules/swagger-codegen/src/main/resources/META-INF/services/io.swagger.codegen.CodegenConfig b/modules/swagger-codegen/src/main/resources/META-INF/services/io.swagger.codegen.CodegenConfig index 6a3706d3d5a..a584a5cd5b3 100644 --- a/modules/swagger-codegen/src/main/resources/META-INF/services/io.swagger.codegen.CodegenConfig +++ b/modules/swagger-codegen/src/main/resources/META-INF/services/io.swagger.codegen.CodegenConfig @@ -1,3 +1,4 @@ +io.swagger.codegen.languages.AdaCodegen io.swagger.codegen.languages.AkkaScalaClientCodegen io.swagger.codegen.languages.AndroidClientCodegen io.swagger.codegen.languages.Apache2ConfigCodegen