diff --git a/README.md b/README.md index f6c1488d84d..38976542e93 100644 --- a/README.md +++ b/README.md @@ -756,6 +756,7 @@ Here is a list of template creators: * Configuration * Apache2: @stkrwork * Schema + * Avro: @sgadouar * GraphQL: @wing328 [:heart:](https://www.patreon.com/wing328) * MySQL: @ybelenko diff --git a/bin/openapi3/avro-petstore.sh b/bin/openapi3/avro-petstore.sh old mode 100644 new mode 100755 index f1296f2c122..0098368e067 --- a/bin/openapi3/avro-petstore.sh +++ b/bin/openapi3/avro-petstore.sh @@ -27,6 +27,6 @@ fi # if you've executed sbt assembly previously it will use that instead. export JAVA_OPTS="${JAVA_OPTS} -Xmx1024M -DloggerPath=conf/log4j.properties" -ags="generate -i modules/openapi-generator/src/test/resources/3_0/petstore.yaml -g avro -o samples/openapi3/schema/petstore/avro $@" +ags="generate -t modules/openapi-generator/src/main/resources/avro-schema -i modules/openapi-generator/src/test/resources/3_0/petstore.yaml -g avro-schema -o samples/openapi3/schema/petstore/avro-schema $@" java $JAVA_OPTS -jar $executable $ags diff --git a/docs/generators.md b/docs/generators.md index ede28ac0d6a..7f26d8eb219 100644 --- a/docs/generators.md +++ b/docs/generators.md @@ -125,6 +125,7 @@ The following generators are available: ## SCHEMA generators +* [avro-schema (beta)](generators/avro-schema) * [mysql-schema](generators/mysql-schema) diff --git a/docs/generators/avro-schema.md b/docs/generators/avro-schema.md new file mode 100644 index 00000000000..9b06b1c6d4d --- /dev/null +++ b/docs/generators/avro-schema.md @@ -0,0 +1,14 @@ + +--- +id: generator-opts-schema-avro-schema +title: Config Options for avro-schema +sidebar_label: avro-schema +--- + +| Option | Description | Values | Default | +| ------ | ----------- | ------ | ------- | +|sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| +|ensureUniqueParams|Whether to ensure parameter names are unique in an operation (rename parameters that are not).| |true| +|allowUnicodeIdentifiers|boolean, toggles whether unicode identifiers are allowed in names or not, default is false| |false| +|prependFormOrBodyParameters|Add form or body parameters to the beginning of the parameter list.| |false| +|packageName|package for generated classes (where supported)| |null| diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AvroCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AvroSchemaCodegen.java similarity index 65% rename from modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AvroCodegen.java rename to modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AvroSchemaCodegen.java index a4875549df7..0da3aa03787 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AvroCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AvroSchemaCodegen.java @@ -17,24 +17,36 @@ package org.openapitools.codegen.languages; import org.openapitools.codegen.*; +import org.openapitools.codegen.meta.GeneratorMetadata; +import org.openapitools.codegen.meta.Stability; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.io.File; import java.util.Arrays; import java.util.HashSet; import java.util.Map; import static org.openapitools.codegen.utils.StringUtils.camelize; -public class AvroCodegen extends DefaultCodegen implements CodegenConfig { - private static final String AVRO = "avro"; +public class AvroSchemaCodegen extends DefaultCodegen implements CodegenConfig { + private static final String AVRO = "avro-schema"; + protected String packageName = "model"; - public AvroCodegen() { - outputFolder = "generated-code/avro"; + public AvroSchemaCodegen() { + super(); + + generatorMetadata = GeneratorMetadata.newBuilder(generatorMetadata) + .stability(Stability.BETA) + .build(); + + outputFolder = "generated-code/avro-schema"; modelTemplateFiles.put("model.mustache", ".avsc"); apiPackage = "api"; modelPackage = "model"; - + importMapping.clear(); + embeddedTemplateDir = templateDir = AVRO; // default HIDE_GENERATION_TIMESTAMP to true hideGenerationTimestamp = Boolean.TRUE; @@ -61,18 +73,18 @@ public class AvroCodegen extends DefaultCodegen implements CodegenConfig { typeMapping.put("UUID", "string"); typeMapping.put("BigDecimal", "string"); - importMapping.clear(); + cliOptions.add(new CliOption(CodegenConstants.PACKAGE_NAME, CodegenConstants.PACKAGE_NAME_DESC)); + } - cliOptions.add(new CliOption(CodegenConstants.SOURCE_FOLDER, CodegenConstants.SOURCE_FOLDER_DESC).defaultValue("src")); - cliOptions.add(new CliOption(CodegenConstants.INVOKER_PACKAGE, CodegenConstants.INVOKER_PACKAGE_DESC)); - cliOptions.add(new CliOption(CodegenConstants.API_PACKAGE, CodegenConstants.API_PACKAGE_DESC)); - cliOptions.add(new CliOption(CodegenConstants.MODEL_PACKAGE, CodegenConstants.MODEL_PACKAGE_DESC)); - cliOptions.add(new CliOption(CodegenConstants.LICENSE_NAME, "name of the license the project uses (Default: using info.license.name)")); - cliOptions.add(new CliOption(CodegenConstants.HIDE_GENERATION_TIMESTAMP, CodegenConstants.HIDE_GENERATION_TIMESTAMP_DESC).defaultValue(Boolean.TRUE.toString())); - cliOptions.add(new CliOption(CodegenConstants.MODEL_PROPERTY_NAMING, CodegenConstants.MODEL_PROPERTY_NAMING_DESC).defaultValue("camelCase")); + @Override + public void processOpts() { + super.processOpts(); + if (additionalProperties.containsKey(CodegenConstants.PACKAGE_NAME)) { + packageName = (String) additionalProperties.get(CodegenConstants.PACKAGE_NAME); + } + + additionalProperties.put("packageName", packageName); - embeddedTemplateDir = AVRO; - templateDir = AVRO; } @Override @@ -82,17 +94,17 @@ public class AvroCodegen extends DefaultCodegen implements CodegenConfig { @Override public String getName() { - return "avro"; + return "avro-schema"; } @Override public String getHelp() { - return "Generates a Avro model."; + return "Generates a Avro model (beta)."; } @Override public String modelFileFolder() { - return outputFolder + "/" ; + return outputFolder + File.separator; } @Override @@ -104,8 +116,20 @@ public class AvroCodegen extends DefaultCodegen implements CodegenConfig { protected void setNonArrayMapProperty(CodegenProperty property, String type) { super.setNonArrayMapProperty(property, type); if (property.isModel) { - property.dataType = camelize(modelNamePrefix + property.dataType + modelNameSuffix ); + property.dataType = camelize(modelNamePrefix + property.dataType + modelNameSuffix); } } + @Override + public String escapeUnsafeCharacters(String input) { + // do nothing as it's a schema conversion + return input; + } + + @Override + public String escapeQuotationMark(String input) { + // do nothing as it's a schema conversion + return input; + } + } diff --git a/modules/openapi-generator/src/main/resources/META-INF/services/org.openapitools.codegen.CodegenConfig b/modules/openapi-generator/src/main/resources/META-INF/services/org.openapitools.codegen.CodegenConfig index 865f3b24c89..f6ca902864d 100644 --- a/modules/openapi-generator/src/main/resources/META-INF/services/org.openapitools.codegen.CodegenConfig +++ b/modules/openapi-generator/src/main/resources/META-INF/services/org.openapitools.codegen.CodegenConfig @@ -4,7 +4,7 @@ org.openapitools.codegen.languages.AndroidClientCodegen org.openapitools.codegen.languages.Apache2ConfigCodegen org.openapitools.codegen.languages.ApexClientCodegen org.openapitools.codegen.languages.AspNetCoreServerCodegen -org.openapitools.codegen.languages.AvroCodegen +org.openapitools.codegen.languages.AvroSchemaCodegen org.openapitools.codegen.languages.BashClientCodegen org.openapitools.codegen.languages.CLibcurlClientCodegen org.openapitools.codegen.languages.ClojureClientCodegen diff --git a/modules/openapi-generator/src/main/resources/avro/model.mustache b/modules/openapi-generator/src/main/resources/avro-schema/model.mustache similarity index 70% rename from modules/openapi-generator/src/main/resources/avro/model.mustache rename to modules/openapi-generator/src/main/resources/avro-schema/model.mustache index 59e7558333f..55232ea9a97 100644 --- a/modules/openapi-generator/src/main/resources/avro/model.mustache +++ b/modules/openapi-generator/src/main/resources/avro-schema/model.mustache @@ -1,8 +1,11 @@ -{{#models}}{{#model}}{ - "namespace": "{{package}}", +{{#models}} +{{#model}} +{ + "namespace": "{{packageName}}", "type": "{{#isEnum}}enum{{/isEnum}}{{^isEnum}}record{{/isEnum}}", "doc": "{{{description}}}", "name": "{{{classname}}}", {{#isEnum}}{{>modelEnum}}{{/isEnum}}{{^isEnum}}{{>pojo}}{{/isEnum}} } -{{/model}}{{/models}} \ No newline at end of file +{{/model}} +{{/models}} diff --git a/modules/openapi-generator/src/main/resources/avro/modelEnum.mustache b/modules/openapi-generator/src/main/resources/avro-schema/modelEnum.mustache similarity index 100% rename from modules/openapi-generator/src/main/resources/avro/modelEnum.mustache rename to modules/openapi-generator/src/main/resources/avro-schema/modelEnum.mustache diff --git a/modules/openapi-generator/src/main/resources/avro/pojo.mustache b/modules/openapi-generator/src/main/resources/avro-schema/pojo.mustache similarity index 71% rename from modules/openapi-generator/src/main/resources/avro/pojo.mustache rename to modules/openapi-generator/src/main/resources/avro-schema/pojo.mustache index 83795fb88d5..0472804f293 100644 --- a/modules/openapi-generator/src/main/resources/avro/pojo.mustache +++ b/modules/openapi-generator/src/main/resources/avro-schema/pojo.mustache @@ -1,7 +1,9 @@ - "fields": [{{#vars}}{{^-first}},{{/-first}} + "fields": [ + {{#vars}} { "name": "{{baseName}}", "type": {{^required}}["null", {{/required}}{{>typeProperty}}{{^required}}]{{/required}}, "doc": "{{{description}}}" - }{{/vars}} + }{{^-last}},{{/-last}} + {{/vars}} ] \ No newline at end of file diff --git a/modules/openapi-generator/src/main/resources/avro/typeArray.mustache b/modules/openapi-generator/src/main/resources/avro-schema/typeArray.mustache similarity index 100% rename from modules/openapi-generator/src/main/resources/avro/typeArray.mustache rename to modules/openapi-generator/src/main/resources/avro-schema/typeArray.mustache diff --git a/modules/openapi-generator/src/main/resources/avro/typeEnum.mustache b/modules/openapi-generator/src/main/resources/avro-schema/typeEnum.mustache similarity index 100% rename from modules/openapi-generator/src/main/resources/avro/typeEnum.mustache rename to modules/openapi-generator/src/main/resources/avro-schema/typeEnum.mustache diff --git a/modules/openapi-generator/src/main/resources/avro/typeProperty.mustache b/modules/openapi-generator/src/main/resources/avro-schema/typeProperty.mustache similarity index 100% rename from modules/openapi-generator/src/main/resources/avro/typeProperty.mustache rename to modules/openapi-generator/src/main/resources/avro-schema/typeProperty.mustache diff --git a/samples/openapi3/schema/petstore/avro-schema/.openapi-generator-ignore b/samples/openapi3/schema/petstore/avro-schema/.openapi-generator-ignore new file mode 100644 index 00000000000..7484ee590a3 --- /dev/null +++ b/samples/openapi3/schema/petstore/avro-schema/.openapi-generator-ignore @@ -0,0 +1,23 @@ +# OpenAPI Generator Ignore +# Generated by openapi-generator https://github.com/openapitools/openapi-generator + +# Use this file to prevent files from being overwritten by the generator. +# The patterns follow closely to .gitignore or .dockerignore. + +# As an example, the C# client generator defines ApiClient.cs. +# You can make changes and tell OpenAPI Generator to ignore just this file by uncommenting the following line: +#ApiClient.cs + +# You can match any string of characters against a directory, file or extension with a single asterisk (*): +#foo/*/qux +# The above matches foo/bar/qux and foo/baz/qux, but not foo/bar/baz/qux + +# You can recursively match patterns against a directory, file or extension with a double asterisk (**): +#foo/**/qux +# This matches foo/bar/qux, foo/baz/qux, and foo/bar/baz/qux + +# You can also negate patterns with an exclamation (!). +# For example, you can ignore all files in a docs folder with the file extension .md: +#docs/*.md +# Then explicitly reverse the ignore rule for a single file: +#!docs/README.md diff --git a/samples/openapi3/schema/petstore/avro-schema/.openapi-generator/VERSION b/samples/openapi3/schema/petstore/avro-schema/.openapi-generator/VERSION new file mode 100644 index 00000000000..2f81801b794 --- /dev/null +++ b/samples/openapi3/schema/petstore/avro-schema/.openapi-generator/VERSION @@ -0,0 +1 @@ +4.1.1-SNAPSHOT \ No newline at end of file diff --git a/samples/openapi3/schema/petstore/avro-schema/ApiResponse.avsc b/samples/openapi3/schema/petstore/avro-schema/ApiResponse.avsc new file mode 100644 index 00000000000..d3ce5cc6aea --- /dev/null +++ b/samples/openapi3/schema/petstore/avro-schema/ApiResponse.avsc @@ -0,0 +1,23 @@ +{ + "namespace": "model", + "type": "record", + "doc": "Describes the result of uploading an image resource", + "name": "ApiResponse", + "fields": [ + { + "name": "code", + "type": ["null", "int"], + "doc": "" + }, + { + "name": "type", + "type": ["null", "string"], + "doc": "" + }, + { + "name": "message", + "type": ["null", "string"], + "doc": "" + } + ] +} diff --git a/samples/openapi3/schema/petstore/avro-schema/Category.avsc b/samples/openapi3/schema/petstore/avro-schema/Category.avsc new file mode 100644 index 00000000000..527f2d389cd --- /dev/null +++ b/samples/openapi3/schema/petstore/avro-schema/Category.avsc @@ -0,0 +1,18 @@ +{ + "namespace": "model", + "type": "record", + "doc": "A category for a pet", + "name": "Category", + "fields": [ + { + "name": "id", + "type": ["null", "long"], + "doc": "" + }, + { + "name": "name", + "type": ["null", "string"], + "doc": "" + } + ] +} diff --git a/samples/openapi3/schema/petstore/avro-schema/InlineObject.avsc b/samples/openapi3/schema/petstore/avro-schema/InlineObject.avsc new file mode 100644 index 00000000000..70af82014c9 --- /dev/null +++ b/samples/openapi3/schema/petstore/avro-schema/InlineObject.avsc @@ -0,0 +1,18 @@ +{ + "namespace": "model", + "type": "record", + "doc": "", + "name": "InlineObject", + "fields": [ + { + "name": "name", + "type": ["null", "string"], + "doc": "Updated name of the pet" + }, + { + "name": "status", + "type": ["null", "string"], + "doc": "Updated status of the pet" + } + ] +} diff --git a/samples/openapi3/schema/petstore/avro-schema/InlineObject1.avsc b/samples/openapi3/schema/petstore/avro-schema/InlineObject1.avsc new file mode 100644 index 00000000000..322dae3751e --- /dev/null +++ b/samples/openapi3/schema/petstore/avro-schema/InlineObject1.avsc @@ -0,0 +1,18 @@ +{ + "namespace": "model", + "type": "record", + "doc": "", + "name": "InlineObject1", + "fields": [ + { + "name": "additionalMetadata", + "type": ["null", "string"], + "doc": "Additional data to pass to server" + }, + { + "name": "file", + "type": ["null", "model.File"], + "doc": "file to upload" + } + ] +} diff --git a/samples/openapi3/schema/petstore/avro-schema/Order.avsc b/samples/openapi3/schema/petstore/avro-schema/Order.avsc new file mode 100644 index 00000000000..945f42d579e --- /dev/null +++ b/samples/openapi3/schema/petstore/avro-schema/Order.avsc @@ -0,0 +1,46 @@ +{ + "namespace": "model", + "type": "record", + "doc": "An order for a pets from the pet store", + "name": "Order", + "fields": [ + { + "name": "id", + "type": ["null", "long"], + "doc": "" + }, + { + "name": "petId", + "type": ["null", "long"], + "doc": "" + }, + { + "name": "quantity", + "type": ["null", "int"], + "doc": "" + }, + { + "name": "shipDate", + "type": ["null", "string"], + "doc": "" + }, + { + "name": "status", + "type": ["null", { + "type": "enum", + "name": "Order_status", + "symbols": [ + "placed", + "approved", + "delivered" + ] + }], + "doc": "Order Status" + }, + { + "name": "complete", + "type": ["null", "boolean"], + "doc": "" + } + ] +} diff --git a/samples/openapi3/schema/petstore/avro-schema/Pet.avsc b/samples/openapi3/schema/petstore/avro-schema/Pet.avsc new file mode 100644 index 00000000000..46ccf5f3d66 --- /dev/null +++ b/samples/openapi3/schema/petstore/avro-schema/Pet.avsc @@ -0,0 +1,52 @@ +{ + "namespace": "model", + "type": "record", + "doc": "A pet for sale in the pet store", + "name": "Pet", + "fields": [ + { + "name": "id", + "type": ["null", "long"], + "doc": "" + }, + { + "name": "category", + "type": ["null", "model.Category"], + "doc": "" + }, + { + "name": "name", + "type": "string", + "doc": "" + }, + { + "name": "photoUrls", + "type": { + "type": "array", + "items": "string" + }, + "doc": "" + }, + { + "name": "tags", + "type": ["null", { + "type": "array", + "items": "model.Tag" + }], + "doc": "" + }, + { + "name": "status", + "type": ["null", { + "type": "enum", + "name": "Pet_status", + "symbols": [ + "available", + "pending", + "sold" + ] + }], + "doc": "pet status in the store" + } + ] +} diff --git a/samples/openapi3/schema/petstore/avro-schema/Tag.avsc b/samples/openapi3/schema/petstore/avro-schema/Tag.avsc new file mode 100644 index 00000000000..ec31d8fb17a --- /dev/null +++ b/samples/openapi3/schema/petstore/avro-schema/Tag.avsc @@ -0,0 +1,18 @@ +{ + "namespace": "model", + "type": "record", + "doc": "A tag for a pet", + "name": "Tag", + "fields": [ + { + "name": "id", + "type": ["null", "long"], + "doc": "" + }, + { + "name": "name", + "type": ["null", "string"], + "doc": "" + } + ] +} diff --git a/samples/openapi3/schema/petstore/avro-schema/User.avsc b/samples/openapi3/schema/petstore/avro-schema/User.avsc new file mode 100644 index 00000000000..2654a817946 --- /dev/null +++ b/samples/openapi3/schema/petstore/avro-schema/User.avsc @@ -0,0 +1,48 @@ +{ + "namespace": "model", + "type": "record", + "doc": "A User who is purchasing from the pet store", + "name": "User", + "fields": [ + { + "name": "id", + "type": ["null", "long"], + "doc": "" + }, + { + "name": "username", + "type": ["null", "string"], + "doc": "" + }, + { + "name": "firstName", + "type": ["null", "string"], + "doc": "" + }, + { + "name": "lastName", + "type": ["null", "string"], + "doc": "" + }, + { + "name": "email", + "type": ["null", "string"], + "doc": "" + }, + { + "name": "password", + "type": ["null", "string"], + "doc": "" + }, + { + "name": "phone", + "type": ["null", "string"], + "doc": "" + }, + { + "name": "userStatus", + "type": ["null", "int"], + "doc": "User Status" + } + ] +}