From afb238814dec4547cdfed3fa9335e6c0b8feae80 Mon Sep 17 00:00:00 2001 From: Akihito Nakano Date: Tue, 17 Jul 2018 10:08:42 +0900 Subject: [PATCH] [Ruby] Abstract Ruby Codegen (#562) * Add AbstractRubyCodegen * Refactor constructor * Move escapeReservedWord() to AbstractRubyCodegen * Move getTypeDeclaration() to AbstractRubyCodegen * Move toDefaultValue() to AbstractRubyCodegen * Move toVarName() to AbstractRubyCodegen * Move toParamName() to AbstractRubyCodegen * Move toOperationId() to AbstractRubyCodegen * Move escapeQuotationMark() to AbstractRubyCodegen * Move escapeUnsafeCharacters() to AbstractRubyCodegen * Use super.escapeReservedWord() * RubyClientCodegen extends AbstractRubyCodegen * Add the differences with AbstractRubyCodegen to "reservedWords" * cliOptions.clear() is not a language specific matter - Rails, Sinatra requires cliOptions.clear() - Ruby client doesn't requires that * Remove duplicated statements with AbstractRubyCodegen * Remove duplicated methods with AbstractRubyCodegen * Merge toVarName() into AbstractRubyCodegen * Merge getTypeDeclaration() into AbstractRubyCodegen * Merge toDefaultValue() into AbstractRubyCodegen * Update Ruby related samples - bin/ruby-client-petstore.sh - bin/ruby-on-rails-server-petstore.sh - bin/ruby-sinatra-server-petstore.sh * Remove unnecessary 'import' * Avoid unnecessary HTML escaping --- .../languages/AbstractRubyCodegen.java | 162 ++++++++++++++++++ .../codegen/languages/RubyClientCodegen.java | 129 +------------- .../languages/RubyOnRailsServerCodegen.java | 111 +----------- .../languages/RubySinatraServerCodegen.java | 119 +------------ .../ruby-sinatra-server/api.mustache | 10 +- .../petstore/ruby-sinatra/api/pet_api.rb | 30 ++-- .../petstore/ruby-sinatra/api/store_api.rb | 12 +- .../petstore/ruby-sinatra/api/user_api.rb | 30 ++-- 8 files changed, 213 insertions(+), 390 deletions(-) create mode 100644 modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractRubyCodegen.java diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractRubyCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractRubyCodegen.java new file mode 100644 index 000000000000..5848febe0b27 --- /dev/null +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractRubyCodegen.java @@ -0,0 +1,162 @@ +/* + * Copyright 2018 OpenAPI-Generator Contributors (https://openapi-generator.tech) + * Copyright 2018 SmartBear Software + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.openapitools.codegen.languages; + +import io.swagger.v3.oas.models.media.ArraySchema; +import io.swagger.v3.oas.models.media.Schema; +import org.openapitools.codegen.*; +import org.openapitools.codegen.utils.ModelUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Arrays; + +abstract class AbstractRubyCodegen extends DefaultCodegen implements CodegenConfig { + private static final Logger LOGGER = LoggerFactory.getLogger(AbstractRubyCodegen.class); + + AbstractRubyCodegen() { + super(); + + setReservedWordsLowerCase( + Arrays.asList( + "__FILE__", "and", "def", "end", "in", "or", "self", "unless", "__LINE__", + "begin", "defined?", "ensure", "module", "redo", "super", "until", "BEGIN", + "break", "do", "false", "next", "rescue", "then", "when", "END", "case", + "else", "for", "nil", "retry", "true", "while", "alias", "class", "elsif", + "if", "not", "return", "undef", "yield") + ); + + languageSpecificPrimitives.clear(); + languageSpecificPrimitives.add("String"); + languageSpecificPrimitives.add("Integer"); + languageSpecificPrimitives.add("Float"); + languageSpecificPrimitives.add("Date"); + languageSpecificPrimitives.add("DateTime"); + languageSpecificPrimitives.add("Array"); + languageSpecificPrimitives.add("Hash"); + languageSpecificPrimitives.add("File"); + languageSpecificPrimitives.add("Object"); + + typeMapping.clear(); + typeMapping.put("string", "String"); + typeMapping.put("char", "String"); + typeMapping.put("int", "Integer"); + typeMapping.put("integer", "Integer"); + typeMapping.put("long", "Integer"); + typeMapping.put("short", "Integer"); + typeMapping.put("float", "Float"); + typeMapping.put("double", "Float"); + typeMapping.put("number", "Float"); + typeMapping.put("date", "Date"); + typeMapping.put("DateTime", "DateTime"); + typeMapping.put("array", "Array"); + typeMapping.put("List", "Array"); + typeMapping.put("map", "Hash"); + typeMapping.put("object", "Object"); + typeMapping.put("file", "File"); + typeMapping.put("binary", "String"); + typeMapping.put("ByteArray", "String"); + typeMapping.put("UUID", "String"); + } + + @Override + public String escapeReservedWord(String name) { + if (this.reservedWordsMappings().containsKey(name)) { + return this.reservedWordsMappings().get(name); + } + return "_" + name; + } + + @Override + public String getTypeDeclaration(Schema schema) { + if (ModelUtils.isArraySchema(schema)) { + Schema inner = ((ArraySchema) schema).getItems(); + return getSchemaType(schema) + "<" + getTypeDeclaration(inner) + ">"; + } else if (ModelUtils.isMapSchema(schema)) { + Schema inner = (Schema) schema.getAdditionalProperties(); + return getSchemaType(schema) + ""; + } + + return super.getTypeDeclaration(schema); + } + + @Override + public String toDefaultValue(Schema p) { + if (ModelUtils.isIntegerSchema(p) || ModelUtils.isNumberSchema(p) || ModelUtils.isBooleanSchema(p)) { + if (p.getDefault() != null) { + return p.getDefault().toString(); + } + } else if (ModelUtils.isStringSchema(p)) { + if (p.getDefault() != null) { + return "'" + escapeText((String) p.getDefault()) + "'"; + } + } + + return null; + } + + @Override + public String toVarName(String name) { + // sanitize name + name = sanitizeName(name); // FIXME: a parameter should not be assigned. Also declare the methods parameters as 'final'. + // if it's all uppper case, convert to lower case + if (name.matches("^[A-Z_]*$")) { + name = name.toLowerCase(); + } + + // camelize (lower first character) the variable name + // petId => pet_id + name = underscore(name); + + // for reserved word or word starting with number, append _ + if (isReservedWord(name) || name.matches("^\\d.*")) { + name = escapeReservedWord(name); + } + + return name; + } + + @Override + public String toParamName(String name) { + // should be the same as variable name + return toVarName(name); + } + + @Override + public String toOperationId(String operationId) { + // method name cannot use reserved keyword, e.g. return + if (isReservedWord(operationId)) { + String newOperationId = underscore("call_" + operationId); + LOGGER.warn(operationId + " (reserved word) cannot be used as method name. Renamed to " + newOperationId); + return newOperationId; + } + + return underscore(operationId); + } + + @Override + public String escapeQuotationMark(String input) { + // remove ' to avoid code injection + return input.replace("'", ""); + } + + @Override + public String escapeUnsafeCharacters(String input) { + return input.replace("=end", "=_end").replace("=begin", "=_begin"); + } +} diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/RubyClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/RubyClientCodegen.java index e53f064098bd..74558b990b12 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/RubyClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/RubyClientCodegen.java @@ -18,14 +18,11 @@ package org.openapitools.codegen.languages; import org.openapitools.codegen.CliOption; -import org.openapitools.codegen.CodegenConfig; import org.openapitools.codegen.CodegenConstants; import org.openapitools.codegen.CodegenParameter; import org.openapitools.codegen.CodegenProperty; import org.openapitools.codegen.CodegenType; -import org.openapitools.codegen.DefaultCodegen; import org.openapitools.codegen.SupportingFile; -import org.openapitools.codegen.utils.ModelUtils; import java.io.File; import java.util.Arrays; @@ -37,7 +34,7 @@ import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public class RubyClientCodegen extends DefaultCodegen implements CodegenConfig { +public class RubyClientCodegen extends AbstractRubyCodegen { private static final Logger LOGGER = LoggerFactory.getLogger(RubyClientCodegen.class); public static final String GEM_NAME = "gemName"; public static final String MODULE_NAME = "moduleName"; @@ -89,21 +86,13 @@ public class RubyClientCodegen extends DefaultCodegen implements CodegenConfig { // default HIDE_GENERATION_TIMESTAMP to true hideGenerationTimestamp = Boolean.TRUE; - setReservedWordsLowerCase( - Arrays.asList( - // local variable names used in API methods (endpoints) - "local_var_path", "query_params", "header_params", "_header_accept", "_header_accept_result", - "_header_content_type", "form_params", "post_body", "auth_names", - // ruby reserved keywords - "__FILE__", "and", "def", "end", "in", "or", "self", "unless", "__LINE__", - "begin", "defined?", "ensure", "module", "redo", "super", "until", "BEGIN", - "break", "do", "false", "next", "rescue", "then", "when", "END", "case", - "else", "for", "nil", "retry", "true", "while", "alias", "class", "elsif", - "if", "not", "return", "undef", "yield") - ); + // local variable names used in API methods (endpoints) + for (String word : Arrays.asList( + "local_var_path", "query_params", "header_params", "_header_accept", "_header_accept_result", + "_header_content_type", "form_params", "post_body", "auth_names")) { + reservedWords.add(word.toLowerCase()); + } - typeMapping.clear(); - languageSpecificPrimitives.clear(); // primitives in ruby lang languageSpecificPrimitives.add("int"); @@ -111,37 +100,8 @@ public class RubyClientCodegen extends DefaultCodegen implements CodegenConfig { languageSpecificPrimitives.add("map"); languageSpecificPrimitives.add("string"); // primitives in the typeMapping - languageSpecificPrimitives.add("String"); - languageSpecificPrimitives.add("Integer"); - languageSpecificPrimitives.add("Float"); - languageSpecificPrimitives.add("Date"); - languageSpecificPrimitives.add("DateTime"); languageSpecificPrimitives.add("BOOLEAN"); - languageSpecificPrimitives.add("Array"); - languageSpecificPrimitives.add("Hash"); - languageSpecificPrimitives.add("File"); - languageSpecificPrimitives.add("Object"); - - typeMapping.put("string", "String"); - typeMapping.put("char", "String"); - typeMapping.put("int", "Integer"); - typeMapping.put("integer", "Integer"); - typeMapping.put("long", "Integer"); - typeMapping.put("short", "Integer"); - typeMapping.put("float", "Float"); - typeMapping.put("double", "Float"); - typeMapping.put("number", "Float"); - typeMapping.put("date", "Date"); - typeMapping.put("DateTime", "DateTime"); typeMapping.put("boolean", "BOOLEAN"); - typeMapping.put("array", "Array"); - typeMapping.put("List", "Array"); - typeMapping.put("map", "Hash"); - typeMapping.put("object", "Object"); - typeMapping.put("file", "File"); - typeMapping.put("binary", "String"); - typeMapping.put("ByteArray", "String"); - typeMapping.put("UUID", "String"); // remove modelPackage and apiPackage added by default Iterator itr = cliOptions.iterator(); @@ -308,14 +268,6 @@ public class RubyClientCodegen extends DefaultCodegen implements CodegenConfig { return underscore(moduleName.replaceAll("[^\\w]+", "")); } - @Override - public String escapeReservedWord(String name) { - if (this.reservedWordsMappings().containsKey(name)) { - return this.reservedWordsMappings().get(name); - } - return "_" + name; - } - @Override public String apiFileFolder() { return outputFolder + File.separator + libFolder + File.separator + gemName + File.separator + apiPackage.replace("/", File.separator); @@ -346,34 +298,6 @@ public class RubyClientCodegen extends DefaultCodegen implements CodegenConfig { return (outputFolder + "/" + modelDocPath).replace('/', File.separatorChar); } - @Override - public String getTypeDeclaration(Schema schema) { - if (ModelUtils.isArraySchema(schema)) { - Schema inner = ((ArraySchema) schema).getItems(); - return getSchemaType(schema) + "<" + getTypeDeclaration(inner) + ">"; - } else if (ModelUtils.isMapSchema(schema)) { - Schema inner = (Schema) schema.getAdditionalProperties(); - return getSchemaType(schema) + ""; - } - - return super.getTypeDeclaration(schema); - } - - @Override - public String toDefaultValue(Schema p) { - if (ModelUtils.isIntegerSchema(p) || ModelUtils.isNumberSchema(p) || ModelUtils.isBooleanSchema(p)) { - if (p.getDefault() != null) { - return p.getDefault().toString(); - } - } else if (ModelUtils.isStringSchema(p)) { - if (p.getDefault() != null) { - return "'" + escapeText((String) p.getDefault()) + "'"; - } - } - - return null; - } - @Override public String getSchemaType(Schema schema) { String openAPIType = super.getSchemaType(schema); @@ -394,33 +318,6 @@ public class RubyClientCodegen extends DefaultCodegen implements CodegenConfig { return toModelName(type); } - @Override - public String toVarName(String name) { - // sanitize name - name = sanitizeName(name); // FIXME: a parameter should not be assigned. Also declare the methods parameters as 'final'. - // if it's all uppper case, convert to lower case - if (name.matches("^[A-Z_]*$")) { - name = name.toLowerCase(); - } - - // camelize (lower first character) the variable name - // petId => pet_id - name = underscore(name); - - // for reserved word or word starting with number, append _ - if (isReservedWord(name) || name.matches("^\\d.*")) { - name = escapeReservedWord(name); - } - - return name; - } - - @Override - public String toParamName(String name) { - // should be the same as variable name - return toVarName(name); - } - @Override public String toModelName(String name) { name = sanitizeName(name); // FIXME: a parameter should not be assigned. Also declare the methods parameters as 'final'. @@ -684,16 +581,4 @@ public class RubyClientCodegen extends DefaultCodegen implements CodegenConfig { // //return super.shouldOverwrite(filename) && !filename.endsWith("_spec.rb"); } - - @Override - public String escapeQuotationMark(String input) { - // remove ' to avoid code injection - return input.replace("'", ""); - } - - @Override - public String escapeUnsafeCharacters(String input) { - return input.replace("=end", "=_end").replace("=begin", "=_begin"); - } - } diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/RubyOnRailsServerCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/RubyOnRailsServerCodegen.java index d6d62f516d8c..3a8752df73f8 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/RubyOnRailsServerCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/RubyOnRailsServerCodegen.java @@ -18,30 +18,19 @@ package org.openapitools.codegen.languages; import java.text.SimpleDateFormat; -import java.util.Date; -import com.fasterxml.jackson.core.JsonProcessingException; -import org.openapitools.codegen.CodegenConfig; import org.openapitools.codegen.CodegenType; -import org.openapitools.codegen.DefaultCodegen; import org.openapitools.codegen.SupportingFile; -import org.openapitools.codegen.utils.ModelUtils; -import io.swagger.v3.oas.models.OpenAPI; -import io.swagger.v3.oas.models.Operation; import io.swagger.v3.oas.models.media.*; -import io.swagger.v3.core.util.Yaml; import java.io.File; -import java.util.Arrays; -import java.util.HashSet; import java.util.Map; -import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public class RubyOnRailsServerCodegen extends DefaultCodegen implements CodegenConfig { +public class RubyOnRailsServerCodegen extends AbstractRubyCodegen { private static final Logger LOGGER = LoggerFactory.getLogger(RubyOnRailsServerCodegen.class); private static final SimpleDateFormat MIGRATE_FILE_NAME_FORMAT = new SimpleDateFormat("yyyyMMddHHmmss"); @@ -87,33 +76,14 @@ public class RubyOnRailsServerCodegen extends DefaultCodegen implements CodegenC embeddedTemplateDir = templateDir = "ruby-on-rails-server"; - typeMapping.clear(); - languageSpecificPrimitives.clear(); - - setReservedWordsLowerCase( - Arrays.asList( - "__FILE__", "and", "def", "end", "in", "or", "self", "unless", "__LINE__", - "begin", "defined?", "ensure", "module", "redo", "super", "until", "BEGIN", - "break", "do", "false", "next", "rescue", "then", "when", "END", "case", - "else", "for", "nil", "retry", "true", "while", "alias", "class", "elsif", - "if", "not", "return", "undef", "yield") - ); - + // In order to adapt to DB migrate script, overwrite typeMapping typeMapping.put("string", "string"); - typeMapping.put("char", "string"); typeMapping.put("int", "integer"); typeMapping.put("integer", "integer"); typeMapping.put("long", "integer"); typeMapping.put("short", "integer"); - typeMapping.put("float", "float"); - typeMapping.put("double", "decimal"); - typeMapping.put("number", "float"); - typeMapping.put("date", "date"); typeMapping.put("DateTime", "datetime"); typeMapping.put("boolean", "boolean"); - typeMapping.put("binary", "string"); - typeMapping.put("ByteArray", "string"); - typeMapping.put("UUID", "string"); // remove modelPackage and apiPackage added by default cliOptions.clear(); @@ -203,59 +173,11 @@ public class RubyOnRailsServerCodegen extends DefaultCodegen implements CodegenC return "Generates a Ruby on Rails (v5) server library."; } - @Override - public String escapeReservedWord(String name) { - if(this.reservedWordsMappings().containsKey(name)) { - return this.reservedWordsMappings().get(name); - } - return "_" + name; - } - @Override public String apiFileFolder() { return outputFolder + File.separator + apiPackage.replace("/", File.separator); } - @Override - public String getTypeDeclaration(Schema p) { - if (ModelUtils.isArraySchema(p)) { - ArraySchema ap = (ArraySchema) p; - Schema inner = ap.getItems(); - return getSchemaType(p) + "[" + getTypeDeclaration(inner) + "]"; - } else if (ModelUtils.isMapSchema(p)) { - Schema inner = (Schema) p.getAdditionalProperties(); - return getSchemaType(p) + "[string," + getTypeDeclaration(inner) + "]"; - } - return super.getTypeDeclaration(p); - } - - @Override - public String toDefaultValue(Schema p) { - return "null"; - } - - @Override - public String toVarName(String name) { - // replace - with _ e.g. created-at => created_at - name = name.replaceAll("-", "_"); // FIXME: a parameter should not be assigned. Also declare the methods parameters as 'final'. - - // if it's all uppper case, convert to lower case - if (name.matches("^[A-Z_]*$")) { - name = name.toLowerCase(); - } - - // camelize (lower first character) the variable name - // petId => pet_id - name = underscore(name); - - // for reserved word or word starting with number, append _ - if (isReservedWord(name) || name.matches("^\\d.*")) { - name = escapeReservedWord(name); - } - - return name; - } - @Override public String getSchemaType(Schema p) { String openAPIType = super.getSchemaType(p); @@ -266,12 +188,6 @@ public class RubyOnRailsServerCodegen extends DefaultCodegen implements CodegenC return "string"; } - @Override - public String toParamName(String name) { - // should be the same as variable name - return toVarName(name); - } - @Override public String toModelName(String name) { // model name cannot use reserved keyword, e.g. return @@ -318,32 +234,9 @@ public class RubyOnRailsServerCodegen extends DefaultCodegen implements CodegenC return camelize(name) + "Controller"; } - @Override - public String toOperationId(String operationId) { - // method name cannot use reserved keyword, e.g. return - if (isReservedWord(operationId)) { - String newOperationId = underscore("call_" + operationId); - LOGGER.warn(operationId + " (reserved word) cannot be used as method name. Renamed to " + newOperationId); - return newOperationId; - } - - return underscore(operationId); - } - @Override public Map postProcessSupportingFileData(Map objs) { generateYAMLSpecFile(objs); return super.postProcessSupportingFileData(objs); } - - @Override - public String escapeQuotationMark(String input) { - // remove ' to avoid code injection - return input.replace("'", ""); - } - - @Override - public String escapeUnsafeCharacters(String input) { - return input.replace("=end", "=_end").replace("=begin", "=_begin"); - } } diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/RubySinatraServerCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/RubySinatraServerCodegen.java index 9f8ecfbde49f..cfedccee5539 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/RubySinatraServerCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/RubySinatraServerCodegen.java @@ -17,29 +17,18 @@ package org.openapitools.codegen.languages; -import com.fasterxml.jackson.core.JsonProcessingException; - -import org.openapitools.codegen.CodegenConfig; import org.openapitools.codegen.CodegenType; -import org.openapitools.codegen.DefaultCodegen; import org.openapitools.codegen.SupportingFile; -import org.openapitools.codegen.utils.ModelUtils; -import io.swagger.v3.oas.models.OpenAPI; -import io.swagger.v3.oas.models.Operation; import io.swagger.v3.oas.models.media.*; -import io.swagger.v3.core.util.Yaml; import java.io.File; -import java.util.Arrays; -import java.util.HashSet; import java.util.Map; -import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public class RubySinatraServerCodegen extends DefaultCodegen implements CodegenConfig { +public class RubySinatraServerCodegen extends AbstractRubyCodegen { private static final Logger LOGGER = LoggerFactory.getLogger(RubySinatraServerCodegen.class); @@ -58,35 +47,6 @@ public class RubySinatraServerCodegen extends DefaultCodegen implements CodegenC apiTemplateFiles.put("api.mustache", ".rb"); embeddedTemplateDir = templateDir = "ruby-sinatra-server"; - typeMapping.clear(); - languageSpecificPrimitives.clear(); - - setReservedWordsLowerCase( - Arrays.asList( - "__FILE__", "and", "def", "end", "in", "or", "self", "unless", "__LINE__", - "begin", "defined?", "ensure", "module", "redo", "super", "until", "BEGIN", - "break", "do", "false", "next", "rescue", "then", "when", "END", "case", - "else", "for", "nil", "retry", "true", "while", "alias", "class", "elsif", - "if", "not", "return", "undef", "yield") - ); - - languageSpecificPrimitives.add("int"); - languageSpecificPrimitives.add("array"); - languageSpecificPrimitives.add("map"); - languageSpecificPrimitives.add("string"); - languageSpecificPrimitives.add("DateTime"); - - typeMapping.put("long", "int"); - typeMapping.put("integer", "int"); - typeMapping.put("Array", "array"); - typeMapping.put("String", "string"); - typeMapping.put("List", "array"); - typeMapping.put("map", "map"); - //TODO binary should be mapped to byte array - // mapped to String as a workaround - typeMapping.put("binary", "string"); - typeMapping.put("UUID", "string"); - // remove modelPackage and apiPackage added by default cliOptions.clear(); } @@ -122,32 +82,11 @@ public class RubySinatraServerCodegen extends DefaultCodegen implements CodegenC return "Generates a Ruby Sinatra server library."; } - @Override - public String escapeReservedWord(String name) { - if (this.reservedWordsMappings().containsKey(name)) { - return this.reservedWordsMappings().get(name); - } - return "_" + name; - } - @Override public String apiFileFolder() { return outputFolder + File.separator + apiPackage.replace("/", File.separator); } - @Override - public String getTypeDeclaration(Schema p) { - if (ModelUtils.isArraySchema(p)) { - ArraySchema ap = (ArraySchema) p; - Schema inner = ap.getItems(); - return getSchemaType(p) + "[" + getTypeDeclaration(inner) + "]"; - } else if (ModelUtils.isMapSchema(p)) { - Schema inner = (Schema) p.getAdditionalProperties(); - return getSchemaType(p) + "[string," + getTypeDeclaration(inner) + "]"; - } - return super.getTypeDeclaration(p); - } - @Override public String getSchemaType(Schema p) { String openAPIType = super.getSchemaType(p); @@ -166,39 +105,6 @@ public class RubySinatraServerCodegen extends DefaultCodegen implements CodegenC return type; } - @Override - public String toDefaultValue(Schema p) { - return "null"; - } - - @Override - public String toVarName(String name) { - // replace - with _ e.g. created-at => created_at - name = name.replaceAll("-", "_"); // FIXME: a parameter should not be assigned. Also declare the methods parameters as 'final'. - - // if it's all uppper case, convert to lower case - if (name.matches("^[A-Z_]*$")) { - name = name.toLowerCase(); - } - - // camelize (lower first character) the variable name - // petId => pet_id - name = underscore(name); - - // for reserved word or word starting with number, append _ - if (isReservedWord(name) || name.matches("^\\d.*")) { - name = escapeReservedWord(name); - } - - return name; - } - - @Override - public String toParamName(String name) { - // should be the same as variable name - return toVarName(name); - } - @Override public String toModelName(String name) { // model name cannot use reserved keyword, e.g. return @@ -243,32 +149,9 @@ public class RubySinatraServerCodegen extends DefaultCodegen implements CodegenC return camelize(name) + "Api"; } - @Override - public String toOperationId(String operationId) { - // method name cannot use reserved keyword, e.g. return - if (isReservedWord(operationId)) { - String newOperationId = underscore("call_" + operationId); - LOGGER.warn(operationId + " (reserved word) cannot be used as method name. Renamed to " + newOperationId); - return newOperationId; - } - - return underscore(operationId); - } - @Override public Map postProcessSupportingFileData(Map objs) { generateYAMLSpecFile(objs); return super.postProcessSupportingFileData(objs); } - - @Override - public String escapeQuotationMark(String input) { - // remove ' to avoid code injection - return input.replace("'", ""); - } - - @Override - public String escapeUnsafeCharacters(String input) { - return input.replace("=end", "=_end").replace("=begin", "=_begin"); - } } diff --git a/modules/openapi-generator/src/main/resources/ruby-sinatra-server/api.mustache b/modules/openapi-generator/src/main/resources/ruby-sinatra-server/api.mustache index 5587837fbdf6..3eeaf93e93da 100644 --- a/modules/openapi-generator/src/main/resources/ruby-sinatra-server/api.mustache +++ b/modules/openapi-generator/src/main/resources/ruby-sinatra-server/api.mustache @@ -7,7 +7,7 @@ MyApp.add_route('{{httpMethod}}', '{{{basePathWithoutHost}}}{{{path}}}', { "resourcePath" => "/{{{baseName}}}", "summary" => "{{{summary}}}", "nickname" => "{{nickname}}", - "responseClass" => "{{#returnType}}{{returnType}}{{/returnType}}{{^returnType}}void{{/returnType}}", + "responseClass" => "{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}void{{/returnType}}", "endpoint" => "{{{path}}}", "notes" => "{{{notes}}}", "parameters" => [ @@ -15,7 +15,7 @@ MyApp.add_route('{{httpMethod}}', '{{{basePathWithoutHost}}}{{{path}}}', { { "name" => "{{paramName}}", "description" => "{{description}}", - "dataType" => "{{dataType}}", + "dataType" => "{{{dataType}}}", {{#collectionFormat}} "collectionFormat" => "{{collectionFormat}}", {{/collectionFormat}} @@ -32,7 +32,7 @@ MyApp.add_route('{{httpMethod}}', '{{{basePathWithoutHost}}}{{{path}}}', { { "name" => "{{paramName}}", "description" => "{{description}}", - "dataType" => "{{dataType}}", + "dataType" => "{{{dataType}}}", "paramType" => "path", }, {{/pathParams}} @@ -40,7 +40,7 @@ MyApp.add_route('{{httpMethod}}', '{{{basePathWithoutHost}}}{{{path}}}', { { "name" => "{{paramName}}", "description" => "{{description}}", - "dataType" => "{{dataType}}", + "dataType" => "{{{dataType}}}", "paramType" => "header", }, {{/headerParams}} @@ -48,7 +48,7 @@ MyApp.add_route('{{httpMethod}}', '{{{basePathWithoutHost}}}{{{path}}}', { { "name" => "body", "description" => "{{description}}", - "dataType" => "{{dataType}}", + "dataType" => "{{{dataType}}}", "paramType" => "body", } {{/bodyParams}} diff --git a/samples/server/petstore/ruby-sinatra/api/pet_api.rb b/samples/server/petstore/ruby-sinatra/api/pet_api.rb index 39fa701c8111..f17047e217b8 100644 --- a/samples/server/petstore/ruby-sinatra/api/pet_api.rb +++ b/samples/server/petstore/ruby-sinatra/api/pet_api.rb @@ -5,7 +5,7 @@ MyApp.add_route('POST', '/v2/pet', { "resourcePath" => "/Pet", "summary" => "Add a new pet to the store", "nickname" => "add_pet", - "responseClass" => "void", + "responseClass" => "void", "endpoint" => "/pet", "notes" => "", "parameters" => [ @@ -27,20 +27,20 @@ MyApp.add_route('DELETE', '/v2/pet/{petId}', { "resourcePath" => "/Pet", "summary" => "Deletes a pet", "nickname" => "delete_pet", - "responseClass" => "void", + "responseClass" => "void", "endpoint" => "/pet/{petId}", "notes" => "", "parameters" => [ { "name" => "pet_id", "description" => "Pet id to delete", - "dataType" => "int", + "dataType" => "Integer", "paramType" => "path", }, { "name" => "api_key", "description" => "", - "dataType" => "string", + "dataType" => "String", "paramType" => "header", }, ]}) do @@ -55,14 +55,14 @@ MyApp.add_route('GET', '/v2/pet/findByStatus', { "resourcePath" => "/Pet", "summary" => "Finds Pets by status", "nickname" => "find_pets_by_status", - "responseClass" => "array[Pet]", + "responseClass" => "Array", "endpoint" => "/pet/findByStatus", "notes" => "Multiple status values can be provided with comma separated strings", "parameters" => [ { "name" => "status", "description" => "Status values that need to be considered for filter", - "dataType" => "array[string]", + "dataType" => "Array", "collectionFormat" => "csv", "paramType" => "query", }, @@ -78,14 +78,14 @@ MyApp.add_route('GET', '/v2/pet/findByTags', { "resourcePath" => "/Pet", "summary" => "Finds Pets by tags", "nickname" => "find_pets_by_tags", - "responseClass" => "array[Pet]", + "responseClass" => "Array", "endpoint" => "/pet/findByTags", "notes" => "Multiple tags can be provided with comma separated strings. Use tag1, tag2, tag3 for testing.", "parameters" => [ { "name" => "tags", "description" => "Tags to filter by", - "dataType" => "array[string]", + "dataType" => "Array", "collectionFormat" => "csv", "paramType" => "query", }, @@ -101,14 +101,14 @@ MyApp.add_route('GET', '/v2/pet/{petId}', { "resourcePath" => "/Pet", "summary" => "Find pet by ID", "nickname" => "get_pet_by_id", - "responseClass" => "Pet", + "responseClass" => "Pet", "endpoint" => "/pet/{petId}", "notes" => "Returns a single pet", "parameters" => [ { "name" => "pet_id", "description" => "ID of pet to return", - "dataType" => "int", + "dataType" => "Integer", "paramType" => "path", }, ]}) do @@ -123,7 +123,7 @@ MyApp.add_route('PUT', '/v2/pet', { "resourcePath" => "/Pet", "summary" => "Update an existing pet", "nickname" => "update_pet", - "responseClass" => "void", + "responseClass" => "void", "endpoint" => "/pet", "notes" => "", "parameters" => [ @@ -145,14 +145,14 @@ MyApp.add_route('POST', '/v2/pet/{petId}', { "resourcePath" => "/Pet", "summary" => "Updates a pet in the store with form data", "nickname" => "update_pet_with_form", - "responseClass" => "void", + "responseClass" => "void", "endpoint" => "/pet/{petId}", "notes" => "", "parameters" => [ { "name" => "pet_id", "description" => "ID of pet that needs to be updated", - "dataType" => "int", + "dataType" => "Integer", "paramType" => "path", }, ]}) do @@ -167,14 +167,14 @@ MyApp.add_route('POST', '/v2/pet/{petId}/uploadImage', { "resourcePath" => "/Pet", "summary" => "uploads an image", "nickname" => "upload_file", - "responseClass" => "ApiResponse", + "responseClass" => "ApiResponse", "endpoint" => "/pet/{petId}/uploadImage", "notes" => "", "parameters" => [ { "name" => "pet_id", "description" => "ID of pet to update", - "dataType" => "int", + "dataType" => "Integer", "paramType" => "path", }, ]}) do diff --git a/samples/server/petstore/ruby-sinatra/api/store_api.rb b/samples/server/petstore/ruby-sinatra/api/store_api.rb index e6fa2551e3aa..7d1b54b2b79f 100644 --- a/samples/server/petstore/ruby-sinatra/api/store_api.rb +++ b/samples/server/petstore/ruby-sinatra/api/store_api.rb @@ -5,14 +5,14 @@ MyApp.add_route('DELETE', '/v2/store/order/{orderId}', { "resourcePath" => "/Store", "summary" => "Delete purchase order by ID", "nickname" => "delete_order", - "responseClass" => "void", + "responseClass" => "void", "endpoint" => "/store/order/{orderId}", "notes" => "For valid response try integer IDs with value < 1000. Anything above 1000 or nonintegers will generate API errors", "parameters" => [ { "name" => "order_id", "description" => "ID of the order that needs to be deleted", - "dataType" => "string", + "dataType" => "String", "paramType" => "path", }, ]}) do @@ -27,7 +27,7 @@ MyApp.add_route('GET', '/v2/store/inventory', { "resourcePath" => "/Store", "summary" => "Returns pet inventories by status", "nickname" => "get_inventory", - "responseClass" => "map[string,int]", + "responseClass" => "Hash", "endpoint" => "/store/inventory", "notes" => "Returns a map of status codes to quantities", "parameters" => [ @@ -43,14 +43,14 @@ MyApp.add_route('GET', '/v2/store/order/{orderId}', { "resourcePath" => "/Store", "summary" => "Find purchase order by ID", "nickname" => "get_order_by_id", - "responseClass" => "Order", + "responseClass" => "Order", "endpoint" => "/store/order/{orderId}", "notes" => "For valid response try integer IDs with value <= 5 or > 10. Other values will generated exceptions", "parameters" => [ { "name" => "order_id", "description" => "ID of pet that needs to be fetched", - "dataType" => "int", + "dataType" => "Integer", "paramType" => "path", }, ]}) do @@ -65,7 +65,7 @@ MyApp.add_route('POST', '/v2/store/order', { "resourcePath" => "/Store", "summary" => "Place an order for a pet", "nickname" => "place_order", - "responseClass" => "Order", + "responseClass" => "Order", "endpoint" => "/store/order", "notes" => "", "parameters" => [ diff --git a/samples/server/petstore/ruby-sinatra/api/user_api.rb b/samples/server/petstore/ruby-sinatra/api/user_api.rb index f2f159ead6d4..e180ccb70e6b 100644 --- a/samples/server/petstore/ruby-sinatra/api/user_api.rb +++ b/samples/server/petstore/ruby-sinatra/api/user_api.rb @@ -5,7 +5,7 @@ MyApp.add_route('POST', '/v2/user', { "resourcePath" => "/User", "summary" => "Create user", "nickname" => "create_user", - "responseClass" => "void", + "responseClass" => "void", "endpoint" => "/user", "notes" => "This can only be done by the logged in user.", "parameters" => [ @@ -27,14 +27,14 @@ MyApp.add_route('POST', '/v2/user/createWithArray', { "resourcePath" => "/User", "summary" => "Creates list of users with given input array", "nickname" => "create_users_with_array_input", - "responseClass" => "void", + "responseClass" => "void", "endpoint" => "/user/createWithArray", "notes" => "", "parameters" => [ { "name" => "body", "description" => "List of user object", - "dataType" => "array[User]", + "dataType" => "Array", "paramType" => "body", } ]}) do @@ -49,14 +49,14 @@ MyApp.add_route('POST', '/v2/user/createWithList', { "resourcePath" => "/User", "summary" => "Creates list of users with given input array", "nickname" => "create_users_with_list_input", - "responseClass" => "void", + "responseClass" => "void", "endpoint" => "/user/createWithList", "notes" => "", "parameters" => [ { "name" => "body", "description" => "List of user object", - "dataType" => "array[User]", + "dataType" => "Array", "paramType" => "body", } ]}) do @@ -71,14 +71,14 @@ MyApp.add_route('DELETE', '/v2/user/{username}', { "resourcePath" => "/User", "summary" => "Delete user", "nickname" => "delete_user", - "responseClass" => "void", + "responseClass" => "void", "endpoint" => "/user/{username}", "notes" => "This can only be done by the logged in user.", "parameters" => [ { "name" => "username", "description" => "The name that needs to be deleted", - "dataType" => "string", + "dataType" => "String", "paramType" => "path", }, ]}) do @@ -93,14 +93,14 @@ MyApp.add_route('GET', '/v2/user/{username}', { "resourcePath" => "/User", "summary" => "Get user by user name", "nickname" => "get_user_by_name", - "responseClass" => "User", + "responseClass" => "User", "endpoint" => "/user/{username}", "notes" => "", "parameters" => [ { "name" => "username", "description" => "The name that needs to be fetched. Use user1 for testing.", - "dataType" => "string", + "dataType" => "String", "paramType" => "path", }, ]}) do @@ -115,21 +115,21 @@ MyApp.add_route('GET', '/v2/user/login', { "resourcePath" => "/User", "summary" => "Logs user into the system", "nickname" => "login_user", - "responseClass" => "string", + "responseClass" => "String", "endpoint" => "/user/login", "notes" => "", "parameters" => [ { "name" => "username", "description" => "The user name for login", - "dataType" => "string", + "dataType" => "String", "allowableValues" => "", "paramType" => "query", }, { "name" => "password", "description" => "The password for login in clear text", - "dataType" => "string", + "dataType" => "String", "allowableValues" => "", "paramType" => "query", }, @@ -145,7 +145,7 @@ MyApp.add_route('GET', '/v2/user/logout', { "resourcePath" => "/User", "summary" => "Logs out current logged in user session", "nickname" => "logout_user", - "responseClass" => "void", + "responseClass" => "void", "endpoint" => "/user/logout", "notes" => "", "parameters" => [ @@ -161,14 +161,14 @@ MyApp.add_route('PUT', '/v2/user/{username}', { "resourcePath" => "/User", "summary" => "Updated user", "nickname" => "update_user", - "responseClass" => "void", + "responseClass" => "void", "endpoint" => "/user/{username}", "notes" => "This can only be done by the logged in user.", "parameters" => [ { "name" => "username", "description" => "name that need to be deleted", - "dataType" => "string", + "dataType" => "String", "paramType" => "path", }, {