add scala client generators

This commit is contained in:
wing328 2018-03-27 22:45:21 +08:00
parent e7743da0e9
commit aa5a7ad540
4 changed files with 855 additions and 0 deletions

View File

@ -0,0 +1,277 @@
package org.openapitools.codegen.languages;
import java.io.File;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import com.samskivert.mustache.Escapers;
import com.samskivert.mustache.Mustache;
import org.openapitools.codegen.CliOption;
import org.openapitools.codegen.CodegenConstants;
import org.openapitools.codegen.DefaultCodegen;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.Operation;
import io.swagger.v3.oas.models.media.*;
import org.apache.commons.lang3.StringUtils;
public abstract class AbstractScalaCodegen extends DefaultCodegen {
protected String modelPropertyNaming = "camelCase";
protected String invokerPackage = "io.swagger.client";
protected String sourceFolder = "src/main/scala";
protected boolean stripPackageName = true;
public AbstractScalaCodegen() {
super();
languageSpecificPrimitives.addAll(Arrays.asList(
"String",
"boolean",
"Boolean",
"Double",
"Int",
"Long",
"Float",
"Object",
"Any",
"List",
"Seq",
"Map",
"Array"));
reservedWords.addAll(Arrays.asList(
"abstract",
"case",
"catch",
"class",
"def",
"do",
"else",
"extends",
"false",
"final",
"finally",
"for",
"forSome",
"if",
"implicit",
"import",
"lazy",
"match",
"new",
"null",
"object",
"override",
"package",
"private",
"protected",
"return",
"sealed",
"super",
"this",
"throw",
"trait",
"try",
"true",
"type",
"val",
"var",
"while",
"with",
"yield"
));
cliOptions.add(new CliOption(CodegenConstants.MODEL_PACKAGE, CodegenConstants.MODEL_PACKAGE_DESC));
cliOptions.add(new CliOption(CodegenConstants.API_PACKAGE, CodegenConstants.API_PACKAGE_DESC));
cliOptions.add(new CliOption(CodegenConstants.SOURCE_FOLDER, CodegenConstants.SOURCE_FOLDER_DESC));
}
@Override
public void processOpts() {
super.processOpts();
if (additionalProperties.containsKey(CodegenConstants.SOURCE_FOLDER)) {
this.setSourceFolder((String) additionalProperties.get(CodegenConstants.SOURCE_FOLDER));
}
if (additionalProperties.containsKey(CodegenConstants.STRIP_PACKAGE_NAME) &&
"false".equalsIgnoreCase(additionalProperties.get(CodegenConstants.STRIP_PACKAGE_NAME).toString())) {
this.stripPackageName = false;
additionalProperties.put(CodegenConstants.STRIP_PACKAGE_NAME, false);
LOGGER.warn("stripPackageName=false. Compilation errors may occur if API type names clash with types " +
"in the default imports");
}
}
public void setSourceFolder(String sourceFolder) {
this.sourceFolder = sourceFolder;
}
public String getSourceFolder() {
return sourceFolder;
}
@Override
public String escapeReservedWord(String name) {
if (this.reservedWordsMappings().containsKey(name)) {
return this.reservedWordsMappings().get(name);
}
// Reserved words will be further escaped at the mustache compiler level.
// Scala escaping done here (via `, without compiler escaping) would otherwise be HTML encoded.
return "`" + name + "`";
}
@Override
public Mustache.Compiler processCompiler(Mustache.Compiler compiler) {
Mustache.Escaper SCALA = new Mustache.Escaper() {
@Override public String escape (String text) {
// Fix included as suggested by akkie in #6393
// The given text is a reserved word which is escaped by enclosing it with grave accents. If we would
// escape that with the default Mustache `HTML` escaper, then the escaper would also escape our grave
// accents. So we remove the grave accents before the escaping and add it back after the escaping.
if (text.startsWith("`") && text.endsWith("`")) {
String unescaped = text.substring(1, text.length() - 1);
return "`" + Escapers.HTML.escape(unescaped) + "`";
}
// All none reserved words will be escaped with the default Mustache `HTML` escaper
return Escapers.HTML.escape(text);
}
};
return compiler.withEscaper(SCALA);
}
@Override
public String apiFileFolder() {
return outputFolder + "/" + sourceFolder + "/" + apiPackage().replace('.', File.separatorChar);
}
@Override
public String modelFileFolder() {
return outputFolder + "/" + sourceFolder + "/" + modelPackage().replace('.', File.separatorChar);
}
@Override
public String getTypeDeclaration(Schema p) {
if (p instanceof ArraySchema) {
ArraySchema ap = (ArraySchema) p;
Schema inner = ap.getItems();
return getSchemaType(p) + "[" + getTypeDeclaration(inner) + "]";
} else if (p instanceof MapSchema) {
MapSchema mp = (MapSchema) p;
Schema inner = (Schema) mp.getAdditionalProperties();
return getSchemaType(p) + "[String, " + getTypeDeclaration(inner) + "]";
}
return super.getTypeDeclaration(p);
}
@Override
public String getSchemaType(Schema p) {
String swaggerType = super.getSchemaType(p);
String type = null;
if (typeMapping.containsKey(swaggerType)) {
type = typeMapping.get(swaggerType);
if (languageSpecificPrimitives.contains(type)) {
return toModelName(type);
}
} else {
type = swaggerType;
}
return toModelName(type);
}
@Override
public String toInstantiationType(Schema p) {
if (p instanceof MapSchema) {
MapSchema ap = (MapSchema) p;
String inner = getSchemaType((Schema)ap.getAdditionalProperties());
return instantiationTypes.get("map") + "[String, " + inner + "]";
} else if (p instanceof ArraySchema) {
ArraySchema ap = (ArraySchema) p;
String inner = getSchemaType(ap.getItems());
return instantiationTypes.get("array") + "[" + inner + "]";
} else {
return null;
}
}
@Override
public String toDefaultValue(Schema p) {
if (p instanceof StringSchema) {
return "null";
} else if (p instanceof BooleanSchema) {
return "null";
} else if (p instanceof DateSchema) {
return "null";
} else if (p instanceof DateTimeSchema) {
return "null";
} else if (p instanceof NumberSchema) {
return "null";
} else if (p instanceof IntegerSchema) {
return "null";
} else if (p instanceof MapSchema) {
MapSchema ap = (MapSchema) p;
String inner = getSchemaType((Schema) ap.getAdditionalProperties());
return "new HashMap[String, " + inner + "]() ";
} else if (p instanceof ArraySchema) {
ArraySchema ap = (ArraySchema) p;
String inner = getSchemaType(ap.getItems());
return "new ListBuffer[" + inner + "]() ";
} else {
return "null";
}
}
@Override
public Map<String, Object> postProcessModels(Map<String, Object> objs) {
// remove model imports to avoid warnings for importing class in the same package in Scala
List<Map<String, String>> imports = (List<Map<String, String>>) objs.get("imports");
final String prefix = modelPackage() + ".";
Iterator<Map<String, String>> iterator = imports.iterator();
while (iterator.hasNext()) {
String _import = iterator.next().get("import");
if (_import.startsWith(prefix)) iterator.remove();
}
return objs;
}
@Override
public String toModelFilename(String name) {
// should be the same as the model name
return toModelName(name);
}
@Override
public String escapeUnsafeCharacters(String input) {
return input.replace("*/", "*_/").replace("/*", "/_*");
}
protected String formatIdentifier(String name, boolean capitalized) {
String identifier = camelize(sanitizeName(name), true);
if (capitalized) {
identifier = StringUtils.capitalize(identifier);
}
if (identifier.matches("[a-zA-Z_$][\\w_$]+") && !isReservedWord(identifier)) {
return identifier;
}
return escapeReservedWord(identifier);
}
protected String stripPackageName(String input) {
if (!stripPackageName || StringUtils.isEmpty(input) || input.lastIndexOf(".") < 0)
return input;
int lastIndexOfDot = input.lastIndexOf(".");
return input.substring(lastIndexOfDot + 1);
}
@Override
public String escapeQuotationMark(String input) {
// remove " to avoid code injection
return input.replace("\"", "");
}
}

View File

@ -0,0 +1,336 @@
package org.openapitools.codegen.languages;
import com.google.common.base.CaseFormat;
import com.samskivert.mustache.Mustache;
import com.samskivert.mustache.Template;
import io.swagger.v3.oas.models.security.SecurityScheme;
import org.openapitools.codegen.CliOption;
import org.openapitools.codegen.CodegenConfig;
import org.openapitools.codegen.CodegenConstants;
import org.openapitools.codegen.CodegenOperation;
import org.openapitools.codegen.CodegenProperty;
import org.openapitools.codegen.CodegenResponse;
import org.openapitools.codegen.CodegenSecurity;
import org.openapitools.codegen.CodegenType;
import org.openapitools.codegen.SupportingFile;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.Operation;
import io.swagger.v3.oas.models.media.*;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.io.IOException;
import java.io.StringWriter;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
public class AkkaScalaClientCodegen extends AbstractScalaCodegen implements CodegenConfig {
protected String mainPackage = "io.swagger.client";
protected String groupId = "io.swagger";
protected String artifactId = "swagger-client";
protected String artifactVersion = "1.0.0";
protected String resourcesFolder = "src/main/resources";
protected String configKey = "apiRequest";
protected int defaultTimeoutInMs = 5000;
protected String configKeyPath = mainPackage;
protected boolean registerNonStandardStatusCodes = true;
protected boolean renderJavadoc = true;
protected boolean removeOAuthSecurities = true;
/**
* If set to true, only the default response (the one with le lowest 2XX code) will be considered as a success, and all
* others as ApiErrors.
* If set to false, all responses defined in the model will be considered as a success upon reception. Only http errors,
* unmarshalling problems and any other RuntimeException will be considered as ApiErrors.
*/
protected boolean onlyOneSuccess = true;
@SuppressWarnings("hiding")
protected Logger LOGGER = LoggerFactory.getLogger(AkkaScalaClientCodegen.class);
public AkkaScalaClientCodegen() {
super();
outputFolder = "generated-code/scala";
modelTemplateFiles.put("model.mustache", ".scala");
apiTemplateFiles.put("api.mustache", ".scala");
embeddedTemplateDir = templateDir = "akka-scala";
apiPackage = mainPackage + ".api";
modelPackage = mainPackage + ".model";
invokerPackage = mainPackage + ".core";
setReservedWordsLowerCase(
Arrays.asList(
"abstract", "case", "catch", "class", "def", "do", "else", "extends",
"false", "final", "finally", "for", "forSome", "if", "implicit",
"import", "lazy", "match", "new", "null", "object", "override", "package",
"private", "protected", "return", "sealed", "super", "this", "throw",
"trait", "try", "true", "type", "val", "var", "while", "with", "yield")
);
additionalProperties.put(CodegenConstants.INVOKER_PACKAGE, invokerPackage);
additionalProperties.put(CodegenConstants.GROUP_ID, groupId);
additionalProperties.put(CodegenConstants.ARTIFACT_ID, artifactId);
additionalProperties.put(CodegenConstants.ARTIFACT_VERSION, artifactVersion);
additionalProperties.put("configKey", configKey);
additionalProperties.put("configKeyPath", configKeyPath);
additionalProperties.put("defaultTimeout", defaultTimeoutInMs);
if (renderJavadoc) {
additionalProperties.put("javadocRenderer", new JavadocLambda());
}
additionalProperties.put("fnCapitalize", new CapitalizeLambda());
additionalProperties.put("fnCamelize", new CamelizeLambda(false));
additionalProperties.put("fnEnumEntry", new EnumEntryLambda());
additionalProperties.put("onlyOneSuccess", onlyOneSuccess);
supportingFiles.add(new SupportingFile("README.mustache", "", "README.md"));
supportingFiles.add(new SupportingFile("pom.mustache", "", "pom.xml"));
supportingFiles.add(new SupportingFile("build.sbt.mustache", "", "build.sbt"));
supportingFiles.add(new SupportingFile("reference.mustache", resourcesFolder, "reference.conf"));
final String invokerFolder = (sourceFolder + File.separator + invokerPackage).replace(".", File.separator);
supportingFiles.add(new SupportingFile("apiRequest.mustache", invokerFolder, "ApiRequest.scala"));
supportingFiles.add(new SupportingFile("apiInvoker.mustache", invokerFolder, "ApiInvoker.scala"));
supportingFiles.add(new SupportingFile("requests.mustache", invokerFolder, "requests.scala"));
supportingFiles.add(new SupportingFile("apiSettings.mustache", invokerFolder, "ApiSettings.scala"));
final String apiFolder = (sourceFolder + File.separator + apiPackage).replace(".", File.separator);
supportingFiles.add(new SupportingFile("enumsSerializers.mustache", apiFolder, "EnumsSerializers.scala"));
importMapping.remove("Seq");
importMapping.remove("List");
importMapping.remove("Set");
importMapping.remove("Map");
importMapping.put("DateTime", "org.joda.time.DateTime");
typeMapping = new HashMap<String, String>();
typeMapping.put("array", "Seq");
typeMapping.put("set", "Set");
typeMapping.put("boolean", "Boolean");
typeMapping.put("string", "String");
typeMapping.put("int", "Int");
typeMapping.put("integer", "Int");
typeMapping.put("long", "Long");
typeMapping.put("float", "Float");
typeMapping.put("byte", "Byte");
typeMapping.put("short", "Short");
typeMapping.put("char", "Char");
typeMapping.put("long", "Long");
typeMapping.put("double", "Double");
typeMapping.put("object", "Any");
typeMapping.put("file", "File");
typeMapping.put("number", "Double");
instantiationTypes.put("array", "ListBuffer");
instantiationTypes.put("map", "Map");
}
@Override
public CodegenType getTag() {
return CodegenType.CLIENT;
}
@Override
public String getName() {
return "akka-scala";
}
@Override
public String getHelp() {
return "Generates a Scala client library (beta) base on Akka/Spray.";
}
@Override
public String escapeReservedWord(String name) {
if(this.reservedWordsMappings().containsKey(name)) {
return this.reservedWordsMappings().get(name);
}
return "`" + name + "`";
}
@Override
public Map<String, Object> postProcessOperations(Map<String, Object> objs) {
if (registerNonStandardStatusCodes) {
try {
@SuppressWarnings("unchecked")
Map<String, ArrayList<CodegenOperation>> opsMap = (Map<String, ArrayList<CodegenOperation>>) objs.get("operations");
HashSet<Integer> unknownCodes = new HashSet<Integer>();
for (CodegenOperation operation : opsMap.get("operation")) {
for (CodegenResponse response : operation.responses) {
if ("default".equals(response.code)) {
continue;
}
try {
int code = Integer.parseInt(response.code);
if (code >= 600) {
unknownCodes.add(code);
}
} catch (NumberFormatException e) {
LOGGER.error("Status code is not an integer : response.code", e);
}
}
}
if (!unknownCodes.isEmpty()) {
additionalProperties.put("unknownStatusCodes", unknownCodes);
}
} catch (Exception e) {
LOGGER.error("Unable to find operations List", e);
}
}
return super.postProcessOperations(objs);
}
@Override
public List<CodegenSecurity> fromSecurity(Map<String, SecurityScheme> schemes) {
final List<CodegenSecurity> codegenSecurities = super.fromSecurity(schemes);
if (!removeOAuthSecurities) {
return codegenSecurities;
}
// Remove OAuth securities
Iterator<CodegenSecurity> it = codegenSecurities.iterator();
while (it.hasNext()) {
final CodegenSecurity security = it.next();
if (security.isOAuth) {
it.remove();
}
}
// Adapt 'hasMore'
it = codegenSecurities.iterator();
while (it.hasNext()) {
final CodegenSecurity security = it.next();
security.hasMore = it.hasNext();
}
if (codegenSecurities.isEmpty()) {
return null;
}
return codegenSecurities;
}
@Override
public String toOperationId(String operationId) {
// throw exception if method name is empty
if (StringUtils.isEmpty(operationId)) {
throw new RuntimeException("Empty method name (operationId) not allowed");
}
return super.toOperationId(CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_CAMEL, operationId));
}
@Override
public String toParamName(String name) {
return formatIdentifier(name, false);
}
@Override
public String toVarName(String name) {
return formatIdentifier(name, false);
}
@Override
public String toEnumName(CodegenProperty property) {
return formatIdentifier(property.baseName, true);
}
@Override
public String toDefaultValue(Schema p) {
if (p.getRequired() != null && p.getRequired().contains(p.getName())) {
return "None";
}
if (p instanceof StringSchema) {
return "null";
} else if (p instanceof BooleanSchema) {
return "null";
} else if (p instanceof DateSchema) {
return "null";
} else if (p instanceof DateTimeSchema) {
return "null";
} else if (p instanceof NumberSchema) {
return "null";
} else if (p instanceof IntegerSchema) {
return "null";
} else if (p instanceof MapSchema) {
MapSchema ap = (MapSchema) p;
String inner = getSchemaType((Schema) ap.getAdditionalProperties());
return "Map[String, " + inner + "].empty ";
} else if (p instanceof ArraySchema) {
ArraySchema ap = (ArraySchema) p;
String inner = getSchemaType(ap.getItems());
return "Seq[" + inner + "].empty ";
} else {
return "null";
}
}
@Override
public String toModelName(final String name) {
return formatIdentifier(name, true);
}
private static abstract class CustomLambda implements Mustache.Lambda {
@Override
public void execute(Template.Fragment frag, Writer out) throws IOException {
final StringWriter tempWriter = new StringWriter();
frag.execute(tempWriter);
out.write(formatFragment(tempWriter.toString()));
}
public abstract String formatFragment(String fragment);
}
private static class JavadocLambda extends CustomLambda {
@Override
public String formatFragment(String fragment) {
final String[] lines = fragment.split("\\r?\\n");
final StringBuilder sb = new StringBuilder();
sb.append(" /**\n");
for (String line : lines) {
sb.append(" * ").append(line).append("\n");
}
sb.append(" */\n");
return sb.toString();
}
}
private static class CapitalizeLambda extends CustomLambda {
@Override
public String formatFragment(String fragment) {
return StringUtils.capitalize(fragment);
}
}
private static class CamelizeLambda extends CustomLambda {
private final boolean capitalizeFirst;
public CamelizeLambda(boolean capitalizeFirst) {
this.capitalizeFirst = capitalizeFirst;
}
@Override
public String formatFragment(String fragment) {
return camelize(fragment, !capitalizeFirst);
}
}
private class EnumEntryLambda extends CustomLambda {
@Override
public String formatFragment(String fragment) {
return formatIdentifier(fragment, true);
}
}
@Override
public String escapeQuotationMark(String input) {
// remove " to avoid code injection
return input.replace("\"", "");
}
}

View File

@ -0,0 +1,240 @@
package org.openapitools.codegen.languages;
import org.openapitools.codegen.*;
import java.io.File;
import java.util.Arrays;
import java.util.HashMap;
import org.apache.commons.lang3.StringUtils;
public class ScalaClientCodegen extends AbstractScalaCodegen implements CodegenConfig {
protected String authScheme = "";
protected String gradleWrapperPackage = "gradle.wrapper";
protected boolean authPreemptive;
protected boolean asyncHttpClient = !authScheme.isEmpty();
protected String groupId = "io.swagger";
protected String artifactId = "swagger-scala-client";
protected String artifactVersion = "1.0.0";
protected String clientName = "AsyncClient";
public ScalaClientCodegen() {
super();
outputFolder = "generated-code/scala";
modelTemplateFiles.put("model.mustache", ".scala");
apiTemplateFiles.put("api.mustache", ".scala");
embeddedTemplateDir = templateDir = "scala";
apiPackage = "io.swagger.client.api";
modelPackage = "io.swagger.client.model";
setReservedWordsLowerCase(
Arrays.asList(
// local variable names used in API methods (endpoints)
"path", "contentTypes", "contentType", "queryParams", "headerParams",
"formParams", "postBody", "mp", "basePath", "apiInvoker",
// scala reserved words
"abstract", "case", "catch", "class", "def", "do", "else", "extends",
"false", "final", "finally", "for", "forSome", "if", "implicit",
"import", "lazy", "match", "new", "null", "object", "override", "package",
"private", "protected", "return", "sealed", "super", "this", "throw",
"trait", "try", "true", "type", "val", "var", "while", "with", "yield")
);
additionalProperties.put(CodegenConstants.INVOKER_PACKAGE, invokerPackage);
additionalProperties.put(CodegenConstants.GROUP_ID, groupId);
additionalProperties.put(CodegenConstants.ARTIFACT_ID, artifactId);
additionalProperties.put(CodegenConstants.ARTIFACT_VERSION, artifactVersion);
additionalProperties.put("asyncHttpClient", asyncHttpClient);
additionalProperties.put("authScheme", authScheme);
additionalProperties.put("authPreemptive", authPreemptive);
additionalProperties.put("clientName", clientName);
additionalProperties.put(CodegenConstants.STRIP_PACKAGE_NAME, stripPackageName);
supportingFiles.add(new SupportingFile("pom.mustache", "", "pom.xml"));
supportingFiles.add(new SupportingFile("apiInvoker.mustache",
(sourceFolder + File.separator + invokerPackage).replace(".", java.io.File.separator), "ApiInvoker.scala"));
supportingFiles.add(new SupportingFile("client.mustache",
(sourceFolder + File.separator + invokerPackage).replace(".", java.io.File.separator), clientName + ".scala"));
supportingFiles.add(new SupportingFile("git_push.sh.mustache", "", "git_push.sh"));
supportingFiles.add(new SupportingFile("gitignore.mustache", "", ".gitignore"));
// gradle settings
supportingFiles.add(new SupportingFile("build.gradle.mustache", "", "build.gradle"));
supportingFiles.add(new SupportingFile("settings.gradle.mustache", "", "settings.gradle"));
supportingFiles.add(new SupportingFile("gradle.properties.mustache", "", "gradle.properties"));
// gradleWrapper files
supportingFiles.add(new SupportingFile("gradlew.mustache", "", "gradlew"));
supportingFiles.add(new SupportingFile("gradlew.bat.mustache", "", "gradlew.bat"));
supportingFiles.add(new SupportingFile("gradle-wrapper.properties.mustache",
gradleWrapperPackage.replace(".", File.separator), "gradle-wrapper.properties"));
supportingFiles.add(new SupportingFile("gradle-wrapper.jar",
gradleWrapperPackage.replace(".", File.separator), "gradle-wrapper.jar"));
supportingFiles.add(new SupportingFile("build.sbt.mustache", "", "build.sbt"));
importMapping.remove("List");
importMapping.remove("Set");
importMapping.remove("Map");
importMapping.put("Date", "java.util.Date");
importMapping.put("ListBuffer", "scala.collection.mutable.ListBuffer");
typeMapping = new HashMap<String, String>();
typeMapping.put("enum", "NSString");
typeMapping.put("array", "List");
typeMapping.put("set", "Set");
typeMapping.put("boolean", "Boolean");
typeMapping.put("string", "String");
typeMapping.put("int", "Int");
typeMapping.put("long", "Long");
typeMapping.put("float", "Float");
typeMapping.put("byte", "Byte");
typeMapping.put("short", "Short");
typeMapping.put("char", "Char");
typeMapping.put("double", "Double");
typeMapping.put("object", "Any");
typeMapping.put("file", "File");
typeMapping.put("binary", "Array[Byte]");
typeMapping.put("ByteArray", "Array[Byte]");
typeMapping.put("ArrayByte", "Array[Byte]");
typeMapping.put("date-time", "Date");
typeMapping.put("DateTime", "Date");
instantiationTypes.put("array", "ListBuffer");
instantiationTypes.put("map", "HashMap");
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.MODEL_PROPERTY_NAMING)) {
setModelPropertyNaming((String) additionalProperties.get(CodegenConstants.MODEL_PROPERTY_NAMING));
}
}
public void setModelPropertyNaming(String naming) {
if ("original".equals(naming) || "camelCase".equals(naming) ||
"PascalCase".equals(naming) || "snake_case".equals(naming)) {
this.modelPropertyNaming = naming;
} else {
throw new IllegalArgumentException("Invalid model property naming '" +
naming + "'. Must be 'original', 'camelCase', " +
"'PascalCase' or 'snake_case'");
}
}
public String getModelPropertyNaming() {
return this.modelPropertyNaming;
}
@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 ("_".equals(name)) {
name = "_u";
}
// if it's all uppper case, do nothing
if (name.matches("^[A-Z_]*$")) {
return name;
}
name = getNameUsingModelPropertyNaming(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);
}
public String getNameUsingModelPropertyNaming(String name) {
switch (CodegenConstants.MODEL_PROPERTY_NAMING_TYPE.valueOf(getModelPropertyNaming())) {
case original:
return name;
case camelCase:
return camelize(name, true);
case PascalCase:
return camelize(name);
case snake_case:
return underscore(name);
default:
throw new IllegalArgumentException("Invalid model property naming '" +
name + "'. Must be 'original', 'camelCase', " +
"'PascalCase' or 'snake_case'");
}
}
@Override
public CodegenType getTag() {
return CodegenType.CLIENT;
}
@Override
public String getName() {
return "scala";
}
@Override
public String getHelp() {
return "Generates a Scala client library (beta).";
}
@Override
public String toOperationId(String operationId) {
// throw exception if method name is empty
if (StringUtils.isEmpty(operationId)) {
throw new RuntimeException("Empty method name (operationId) not allowed");
}
// method name cannot use reserved keyword, e.g. return
if (isReservedWord(operationId)) {
throw new RuntimeException(operationId + " (reserved word) cannot be used as method name");
}
return camelize(operationId, true);
}
@Override
public String toModelName(final String name) {
final String sanitizedName = sanitizeName(modelNamePrefix + this.stripPackageName(name) + modelNameSuffix);
// camelize the model name
// phone_number => PhoneNumber
final String camelizedName = camelize(sanitizedName);
// model name cannot use reserved keyword, e.g. return
if (isReservedWord(camelizedName)) {
final String modelName = "Model" + camelizedName;
LOGGER.warn(camelizedName + " (reserved word) cannot be used as model name. Renamed to " + modelName);
return modelName;
}
// model name starts with number
if (name.matches("^\\d.*")) {
final String modelName = "Model" + camelizedName; // e.g. 200Response => Model200Response (after camelize)
LOGGER.warn(name + " (model name starts with number) cannot be used as model name. Renamed to " + modelName);
return modelName;
}
return camelizedName;
}
@Override
public String toEnumName(CodegenProperty property) {
return formatIdentifier(stripPackageName(property.baseName), true);
}
}

View File

@ -1,4 +1,5 @@
org.openapitools.codegen.languages.AndroidClientCodegen
org.openapitools.codegen.languages.AkkaScalaClientCodegen
org.openapitools.codegen.languages.BashClientCodegen
org.openapitools.codegen.languages.DartClientCodegen
org.openapitools.codegen.languages.ElixirClientCodegen
@ -11,6 +12,7 @@ org.openapitools.codegen.languages.PythonClientCodegen
org.openapitools.codegen.languages.RClientCodegen
org.openapitools.codegen.languages.Rails5ServerCodegen
org.openapitools.codegen.languages.RubyClientCodegen
org.openapitools.codegen.languages.ScalaClientCodegen
org.openapitools.codegen.languages.SlimFrameworkServerCodegen
org.openapitools.codegen.languages.SilexServerCodegen
org.openapitools.codegen.languages.SinatraServerCodegen