forked from loafle/openapi-generator-original
add scala client generators
This commit is contained in:
parent
e7743da0e9
commit
aa5a7ad540
@ -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("\"", "");
|
||||||
|
}
|
||||||
|
}
|
@ -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("\"", "");
|
||||||
|
}
|
||||||
|
}
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,4 +1,5 @@
|
|||||||
org.openapitools.codegen.languages.AndroidClientCodegen
|
org.openapitools.codegen.languages.AndroidClientCodegen
|
||||||
|
org.openapitools.codegen.languages.AkkaScalaClientCodegen
|
||||||
org.openapitools.codegen.languages.BashClientCodegen
|
org.openapitools.codegen.languages.BashClientCodegen
|
||||||
org.openapitools.codegen.languages.DartClientCodegen
|
org.openapitools.codegen.languages.DartClientCodegen
|
||||||
org.openapitools.codegen.languages.ElixirClientCodegen
|
org.openapitools.codegen.languages.ElixirClientCodegen
|
||||||
@ -11,6 +12,7 @@ org.openapitools.codegen.languages.PythonClientCodegen
|
|||||||
org.openapitools.codegen.languages.RClientCodegen
|
org.openapitools.codegen.languages.RClientCodegen
|
||||||
org.openapitools.codegen.languages.Rails5ServerCodegen
|
org.openapitools.codegen.languages.Rails5ServerCodegen
|
||||||
org.openapitools.codegen.languages.RubyClientCodegen
|
org.openapitools.codegen.languages.RubyClientCodegen
|
||||||
|
org.openapitools.codegen.languages.ScalaClientCodegen
|
||||||
org.openapitools.codegen.languages.SlimFrameworkServerCodegen
|
org.openapitools.codegen.languages.SlimFrameworkServerCodegen
|
||||||
org.openapitools.codegen.languages.SilexServerCodegen
|
org.openapitools.codegen.languages.SilexServerCodegen
|
||||||
org.openapitools.codegen.languages.SinatraServerCodegen
|
org.openapitools.codegen.languages.SinatraServerCodegen
|
||||||
|
Loading…
x
Reference in New Issue
Block a user