Feature/api name suffix (#3918)

* added apiNameSuffix parameter to control the suffixes of API class/file/doc names

* added --api-name-suffix in readme
This commit is contained in:
bgong-mdsol 2019-10-02 21:51:07 -04:00 committed by William Cheng
parent 7c7fa68737
commit ebc9e291c3
12 changed files with 97 additions and 22 deletions

View File

@ -455,6 +455,7 @@ NAME
SYNOPSIS SYNOPSIS
openapi-generator-cli generate openapi-generator-cli generate
[(-a <authorization> | --auth <authorization>)] [(-a <authorization> | --auth <authorization>)]
[--api-name-suffix <api name suffix>]
[--api-package <api package>] [--artifact-id <artifact id>] [--api-package <api package>] [--artifact-id <artifact id>]
[--artifact-version <artifact version>] [--artifact-version <artifact version>]
[(-c <configuration file> | --config <configuration file>)] [(-c <configuration file> | --config <configuration file>)]

View File

@ -109,6 +109,10 @@ public class Generate implements Runnable {
description = CodegenConstants.MODEL_PACKAGE_DESC) description = CodegenConstants.MODEL_PACKAGE_DESC)
private String modelPackage; private String modelPackage;
@Option(name = {"--api-name-suffix"}, title = "api name suffix",
description = CodegenConstants.API_NAME_SUFFIX_DESC)
private String apiNameSuffix;
@Option(name = {"--model-name-prefix"}, title = "model name prefix", @Option(name = {"--model-name-prefix"}, title = "model name prefix",
description = CodegenConstants.MODEL_NAME_PREFIX_DESC) description = CodegenConstants.MODEL_NAME_PREFIX_DESC)
private String modelNamePrefix; private String modelNamePrefix;
@ -319,6 +323,10 @@ public class Generate implements Runnable {
configurator.setModelPackage(modelPackage); configurator.setModelPackage(modelPackage);
} }
if (isNotEmpty(apiNameSuffix)) {
configurator.setApiNameSuffix(apiNameSuffix);
}
if (isNotEmpty(modelNamePrefix)) { if (isNotEmpty(modelNamePrefix)) {
configurator.setModelNamePrefix(modelNamePrefix); configurator.setModelNamePrefix(modelNamePrefix);
} }

View File

@ -40,6 +40,7 @@ public final class GeneratorSettings implements Serializable {
private String modelPackage; private String modelPackage;
private String invokerPackage; private String invokerPackage;
private String packageName; private String packageName;
private String apiNameSuffix;
private String modelNamePrefix; private String modelNamePrefix;
private String modelNameSuffix; private String modelNameSuffix;
private String groupId; private String groupId;
@ -106,6 +107,21 @@ public final class GeneratorSettings implements Serializable {
return packageName; return packageName;
} }
/**
* Gets a api name suffix for generated models. This name will be appended to a api name.
* <p>
* This option is often used to circumvent compilation issues where models match keywords.
* <p>
* Example:
* <p>
* Suffix <code>Gen</code> applied to <code>Object</code> results in a generated class named <code>ObjectGen</code>.
*
* @return the model name suffix
*/
public String getApiNameSuffix() {
return apiNameSuffix;
}
/** /**
* Gets a model name prefix for generated models. This name will be prefixed to a model name. * Gets a model name prefix for generated models. This name will be prefixed to a model name.
* <p> * <p>
@ -325,6 +341,7 @@ public final class GeneratorSettings implements Serializable {
modelPackage = builder.modelPackage; modelPackage = builder.modelPackage;
invokerPackage = builder.invokerPackage; invokerPackage = builder.invokerPackage;
packageName = builder.packageName; packageName = builder.packageName;
apiNameSuffix = builder.apiNameSuffix;
modelNamePrefix = builder.modelNamePrefix; modelNamePrefix = builder.modelNamePrefix;
modelNameSuffix = builder.modelNameSuffix; modelNameSuffix = builder.modelNameSuffix;
groupId = builder.groupId; groupId = builder.groupId;
@ -366,6 +383,9 @@ public final class GeneratorSettings implements Serializable {
if (isNotEmpty(artifactVersion)) { if (isNotEmpty(artifactVersion)) {
additional.put("artifactVersion", artifactVersion); additional.put("artifactVersion", artifactVersion);
} }
if (isNotEmpty(apiNameSuffix)) {
additional.put("apiNameSuffix", apiNameSuffix);
}
if (isNotEmpty(modelNamePrefix)) { if (isNotEmpty(modelNamePrefix)) {
additional.put("modelNamePrefix", modelNamePrefix); additional.put("modelNamePrefix", modelNamePrefix);
} }
@ -433,6 +453,7 @@ public final class GeneratorSettings implements Serializable {
builder.modelPackage = copy.getModelPackage(); builder.modelPackage = copy.getModelPackage();
builder.invokerPackage = copy.getInvokerPackage(); builder.invokerPackage = copy.getInvokerPackage();
builder.packageName = copy.getPackageName(); builder.packageName = copy.getPackageName();
builder.apiNameSuffix = copy.getApiNameSuffix();
builder.modelNamePrefix = copy.getModelNamePrefix(); builder.modelNamePrefix = copy.getModelNamePrefix();
builder.modelNameSuffix = copy.getModelNameSuffix(); builder.modelNameSuffix = copy.getModelNameSuffix();
builder.groupId = copy.getGroupId(); builder.groupId = copy.getGroupId();
@ -479,6 +500,7 @@ public final class GeneratorSettings implements Serializable {
private String modelPackage; private String modelPackage;
private String invokerPackage; private String invokerPackage;
private String packageName; private String packageName;
private String apiNameSuffix;
private String modelNamePrefix; private String modelNamePrefix;
private String modelNameSuffix; private String modelNameSuffix;
private String groupId; private String groupId;
@ -571,6 +593,17 @@ public final class GeneratorSettings implements Serializable {
return this; return this;
} }
/**
* Sets the {@code apiNameSuffix} and returns a reference to this Builder so that the methods can be chained together.
*
* @param apiNameSuffix the {@code apiNameSuffix} to set
* @return a reference to this Builder
*/
public Builder withApiNameSuffix(String apiNameSuffix) {
this.apiNameSuffix = apiNameSuffix;
return this;
}
/** /**
* Sets the {@code modelNamePrefix} and returns a reference to this Builder so that the methods can be chained together. * Sets the {@code modelNamePrefix} and returns a reference to this Builder so that the methods can be chained together.
* *
@ -880,6 +913,7 @@ public final class GeneratorSettings implements Serializable {
", modelPackage='" + modelPackage + '\'' + ", modelPackage='" + modelPackage + '\'' +
", invokerPackage='" + invokerPackage + '\'' + ", invokerPackage='" + invokerPackage + '\'' +
", packageName='" + packageName + '\'' + ", packageName='" + packageName + '\'' +
", apiNameSuffix='" + apiNameSuffix + '\'' +
", modelNamePrefix='" + modelNamePrefix + '\'' + ", modelNamePrefix='" + modelNamePrefix + '\'' +
", modelNameSuffix='" + modelNameSuffix + '\'' + ", modelNameSuffix='" + modelNameSuffix + '\'' +
", groupId='" + groupId + '\'' + ", groupId='" + groupId + '\'' +
@ -910,6 +944,7 @@ public final class GeneratorSettings implements Serializable {
Objects.equals(getModelPackage(), that.getModelPackage()) && Objects.equals(getModelPackage(), that.getModelPackage()) &&
Objects.equals(getInvokerPackage(), that.getInvokerPackage()) && Objects.equals(getInvokerPackage(), that.getInvokerPackage()) &&
Objects.equals(getPackageName(), that.getPackageName()) && Objects.equals(getPackageName(), that.getPackageName()) &&
Objects.equals(getApiNameSuffix(), that.getApiNameSuffix()) &&
Objects.equals(getModelNamePrefix(), that.getModelNamePrefix()) && Objects.equals(getModelNamePrefix(), that.getModelNamePrefix()) &&
Objects.equals(getModelNameSuffix(), that.getModelNameSuffix()) && Objects.equals(getModelNameSuffix(), that.getModelNameSuffix()) &&
Objects.equals(getGroupId(), that.getGroupId()) && Objects.equals(getGroupId(), that.getGroupId()) &&
@ -937,6 +972,7 @@ public final class GeneratorSettings implements Serializable {
getModelPackage(), getModelPackage(),
getInvokerPackage(), getInvokerPackage(),
getPackageName(), getPackageName(),
getApiNameSuffix(),
getModelNamePrefix(), getModelNamePrefix(),
getModelNameSuffix(), getModelNameSuffix(),
getGroupId(), getGroupId(),

View File

@ -206,6 +206,9 @@ public class CodegenConstants {
// Codegen constants should define a description and provide proper input validation for the value of serializationLibrary // Codegen constants should define a description and provide proper input validation for the value of serializationLibrary
public static final String SERIALIZATION_LIBRARY = "serializationLibrary"; public static final String SERIALIZATION_LIBRARY = "serializationLibrary";
public static final String API_NAME_SUFFIX = "apiNameSuffix";
public static final String API_NAME_SUFFIX_DESC = "Suffix that will be appended to all api names.";
public static final String MODEL_NAME_PREFIX = "modelNamePrefix"; public static final String MODEL_NAME_PREFIX = "modelNamePrefix";
public static final String MODEL_NAME_PREFIX_DESC = "Prefix that will be prepended to all model names."; public static final String MODEL_NAME_PREFIX_DESC = "Prefix that will be prepended to all model names.";

View File

@ -85,6 +85,7 @@ public class DefaultCodegen implements CodegenConfig {
protected Map<String, String> importMapping = new HashMap<String, String>(); protected Map<String, String> importMapping = new HashMap<String, String>();
protected String modelPackage = "", apiPackage = "", fileSuffix; protected String modelPackage = "", apiPackage = "", fileSuffix;
protected String modelNamePrefix = "", modelNameSuffix = ""; protected String modelNamePrefix = "", modelNameSuffix = "";
protected String apiNameSuffix = "Api";
protected String testPackage = ""; protected String testPackage = "";
protected Map<String, String> apiTemplateFiles = new HashMap<String, String>(); protected Map<String, String> apiTemplateFiles = new HashMap<String, String>();
protected Map<String, String> modelTemplateFiles = new HashMap<String, String>(); protected Map<String, String> modelTemplateFiles = new HashMap<String, String>();
@ -180,6 +181,10 @@ public class DefaultCodegen implements CodegenConfig {
.get(CodegenConstants.ALLOW_UNICODE_IDENTIFIERS).toString())); .get(CodegenConstants.ALLOW_UNICODE_IDENTIFIERS).toString()));
} }
if (additionalProperties.containsKey(CodegenConstants.API_NAME_SUFFIX)) {
this.setApiNameSuffix((String) additionalProperties.get(CodegenConstants.API_NAME_SUFFIX));
}
if (additionalProperties.containsKey(CodegenConstants.MODEL_NAME_PREFIX)) { if (additionalProperties.containsKey(CodegenConstants.MODEL_NAME_PREFIX)) {
this.setModelNamePrefix((String) additionalProperties.get(CodegenConstants.MODEL_NAME_PREFIX)); this.setModelNamePrefix((String) additionalProperties.get(CodegenConstants.MODEL_NAME_PREFIX));
} }
@ -779,6 +784,14 @@ public class DefaultCodegen implements CodegenConfig {
this.modelNameSuffix = modelNameSuffix; this.modelNameSuffix = modelNameSuffix;
} }
public String getApiNameSuffix() {
return apiNameSuffix;
}
public void setApiNameSuffix(String apiNameSuffix) {
this.apiNameSuffix = apiNameSuffix;
}
public void setApiPackage(String apiPackage) { public void setApiPackage(String apiPackage) {
this.apiPackage = apiPackage; this.apiPackage = apiPackage;
} }
@ -1692,17 +1705,17 @@ public class DefaultCodegen implements CodegenConfig {
} }
/** /**
* Output the API (class) name (capitalized) ending with "Api" * Output the API (class) name (capitalized) ending with the specified or default suffix
* Return DefaultApi if name is empty * Return DefaultApi if name is empty
* *
* @param name the name of the Api * @param name the name of the Api
* @return capitalized Api name ending with "Api" * @return capitalized Api name
*/ */
public String toApiName(String name) { public String toApiName(String name) {
if (name.length() == 0) { if (name.length() == 0) {
return "DefaultApi"; return "DefaultApi";
} }
return camelize(name) + "Api"; return camelize(name + "_" + apiNameSuffix);
} }
/** /**

View File

@ -287,6 +287,11 @@ public class CodegenConfigurator {
return this; return this;
} }
public CodegenConfigurator setApiNameSuffix(String suffix) {
generatorSettingsBuilder.withApiNameSuffix(suffix);
return this;
}
public CodegenConfigurator setModelNamePrefix(String prefix) { public CodegenConfigurator setModelNamePrefix(String prefix) {
generatorSettingsBuilder.withModelNamePrefix(prefix); generatorSettingsBuilder.withModelNamePrefix(prefix);
return this; return this;

View File

@ -151,7 +151,7 @@ abstract public class AbstractCppCodegen extends DefaultCodegen implements Codeg
@Override @Override
public String toApiName(String type) { public String toApiName(String type) {
return sanitizeName(modelNamePrefix + Character.toUpperCase(type.charAt(0)) + type.substring(1) + "Api"); return sanitizeName(modelNamePrefix + super.toApiName(type));
} }
@Override @Override

View File

@ -244,11 +244,10 @@ public abstract class AbstractJavaJAXRSServerCodegen extends AbstractJavaCodegen
@Override @Override
public String toApiName(final String name) { public String toApiName(final String name) {
String computed = name; String computed = name;
if (computed.length() == 0) { if (computed.length() > 0) {
return "DefaultApi";
}
computed = sanitizeName(computed); computed = sanitizeName(computed);
return camelize(computed) + "Api"; }
return super.toApiName(computed);
} }
@Override @Override

View File

@ -531,7 +531,7 @@ public class PythonClientCodegen extends DefaultCodegen implements CodegenConfig
name = name.replaceAll("-", "_"); name = name.replaceAll("-", "_");
// e.g. PhoneNumberApi.py => phone_number_api.py // e.g. PhoneNumberApi.py => phone_number_api.py
return underscore(name) + "_api"; return underscore(name+ "_" + apiNameSuffix);
} }
@Override @Override
@ -541,11 +541,7 @@ public class PythonClientCodegen extends DefaultCodegen implements CodegenConfig
@Override @Override
public String toApiName(String name) { public String toApiName(String name) {
if (name.length() == 0) { return super.toApiName(name);
return "DefaultApi";
}
// e.g. phone_number_api => PhoneNumberApi
return camelize(name) + "Api";
} }
@Override @Override
@ -553,7 +549,7 @@ public class PythonClientCodegen extends DefaultCodegen implements CodegenConfig
if (name.length() == 0) { if (name.length() == 0) {
return "default_api"; return "default_api";
} }
return underscore(name) + "_api"; return underscore(name+ "_" + apiNameSuffix);
} }
@Override @Override

View File

@ -387,7 +387,7 @@ public class RubyClientCodegen extends AbstractRubyCodegen {
name = name.replaceAll("-", "_"); // FIXME: a parameter should not be assigned. Also declare the methods parameters as 'final'. name = name.replaceAll("-", "_"); // FIXME: a parameter should not be assigned. Also declare the methods parameters as 'final'.
// e.g. PhoneNumberApi.rb => phone_number_api.rb // e.g. PhoneNumberApi.rb => phone_number_api.rb
return underscore(name) + "_api"; return underscore(name + "_" + apiNameSuffix);
} }
@Override @Override
@ -407,11 +407,7 @@ public class RubyClientCodegen extends AbstractRubyCodegen {
@Override @Override
public String toApiName(String name) { public String toApiName(String name) {
if (name.length() == 0) { return super.toApiName(name);
return "DefaultApi";
}
// e.g. phone_number_api => PhoneNumberApi
return camelize(name) + "Api";
} }
@Override @Override

View File

@ -43,6 +43,7 @@ import org.openapitools.codegen.utils.ModelUtils;
import org.testng.Assert; import org.testng.Assert;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull; import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertTrue; import static org.testng.Assert.assertTrue;
@ -968,4 +969,19 @@ public class DefaultCodegenTest {
assertTrue(lambdas.get("indented_16") instanceof IndentedLambda, "Expecting IndentedLambda class"); assertTrue(lambdas.get("indented_16") instanceof IndentedLambda, "Expecting IndentedLambda class");
} }
@Test
public void convertApiNameWithEmptySuffix() {
DefaultCodegen codegen = new DefaultCodegen();
assertEquals(codegen.toApiName("Fake"), "FakeApi");
assertEquals(codegen.toApiName(""), "DefaultApi");
}
@Test
public void convertApiNameWithSuffix() {
DefaultCodegen codegen = new DefaultCodegen();
codegen.setApiNameSuffix("Test");
assertEquals(codegen.toApiName("Fake"), "FakeTest");
assertEquals(codegen.toApiName(""), "DefaultApi");
}
} }

View File

@ -77,6 +77,7 @@ public class CodegenConfiguratorTest {
.setGitHost("test.com") .setGitHost("test.com")
.setGroupId("group") .setGroupId("group")
.setHttpUserAgent("agent") .setHttpUserAgent("agent")
.setApiNameSuffix("api-suffix")
.setModelNamePrefix("model-prefix") .setModelNamePrefix("model-prefix")
.setModelNameSuffix("model-suffix") .setModelNameSuffix("model-suffix")
.setModelPackage("model-package") .setModelPackage("model-package")
@ -100,6 +101,7 @@ public class CodegenConfiguratorTest {
want(props, CodegenConstants.PREPEND_FORM_OR_BODY_PARAMETERS, false); want(props, CodegenConstants.PREPEND_FORM_OR_BODY_PARAMETERS, false);
want(props, CodegenConstants.ENSURE_UNIQUE_PARAMS, true); want(props, CodegenConstants.ENSURE_UNIQUE_PARAMS, true);
want(props, CodegenConstants.ALLOW_UNICODE_IDENTIFIERS, true); want(props, CodegenConstants.ALLOW_UNICODE_IDENTIFIERS, true);
want(props, CodegenConstants.API_NAME_SUFFIX, "api-suffix");
want(props, CodegenConstants.MODEL_NAME_PREFIX, "model-prefix"); want(props, CodegenConstants.MODEL_NAME_PREFIX, "model-prefix");
want(props, CodegenConstants.MODEL_NAME_SUFFIX, "model-suffix"); want(props, CodegenConstants.MODEL_NAME_SUFFIX, "model-suffix");
want(props, CodegenConstants.REMOVE_OPERATION_ID_PREFIX, false); want(props, CodegenConstants.REMOVE_OPERATION_ID_PREFIX, false);