Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.openapitools.codegen.languages.LuaClientCodegen Maven / Gradle / Ivy
/*
* 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
*
* https://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.Schema;
import lombok.Setter;
import org.apache.commons.lang3.StringUtils;
import org.openapitools.codegen.*;
import org.openapitools.codegen.meta.GeneratorMetadata;
import org.openapitools.codegen.meta.Stability;
import org.openapitools.codegen.meta.features.*;
import org.openapitools.codegen.model.ModelMap;
import org.openapitools.codegen.model.ModelsMap;
import org.openapitools.codegen.model.OperationMap;
import org.openapitools.codegen.model.OperationsMap;
import org.openapitools.codegen.utils.ModelUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.util.*;
import static org.openapitools.codegen.utils.StringUtils.camelize;
import static org.openapitools.codegen.utils.StringUtils.underscore;
public class LuaClientCodegen extends DefaultCodegen implements CodegenConfig {
private final Logger LOGGER = LoggerFactory.getLogger(LuaClientCodegen.class);
protected String specFolder = "spec";
@Setter protected String packageName = "openapiclient";
@Setter protected String packageVersion = "1.0.0-1";
protected String apiDocPath = "docs/";
protected String modelDocPath = "docs/";
@Setter protected String luaRocksFilename = "openapiclient-1.0.0-1.rockspec";
@Override
public CodegenType getTag() {
return CodegenType.CLIENT;
}
@Override
public String getName() {
return "lua";
}
@Override
public String getHelp() {
return "Generates a Lua client library (beta).";
}
public LuaClientCodegen() {
super();
modifyFeatureSet(features -> features
.includeDocumentationFeatures(DocumentationFeature.Readme)
.wireFormatFeatures(EnumSet.of(WireFormatFeature.JSON, WireFormatFeature.XML))
.securityFeatures(EnumSet.of(
SecurityFeature.BasicAuth,
SecurityFeature.ApiKey,
SecurityFeature.OAuth2_Implicit
))
.excludeGlobalFeatures(
GlobalFeature.XMLStructureDefinitions,
GlobalFeature.Callbacks,
GlobalFeature.LinkObjects,
GlobalFeature.ParameterStyling
)
.includeSchemaSupportFeatures(
SchemaSupportFeature.Polymorphism
)
.includeParameterFeatures(
ParameterFeature.Cookie
)
);
generatorMetadata = GeneratorMetadata.newBuilder(generatorMetadata)
.stability(Stability.BETA)
.build();
outputFolder = "generated-code/lua";
modelTemplateFiles.put("model.mustache", ".lua");
apiTemplateFiles.put("api.mustache", ".lua");
modelDocTemplateFiles.put("model_doc.mustache", ".md");
apiDocTemplateFiles.put("api_doc.mustache", ".md");
embeddedTemplateDir = templateDir = "lua";
// default HIDE_GENERATION_TIMESTAMP to true
hideGenerationTimestamp = Boolean.TRUE;
setReservedWordsLowerCase(
Arrays.asList(
// data type
"nil", "string", "boolean", "number", "userdata", "thread",
"table",
// reserved words: http://www.lua.org/manual/5.1/manual.html#2.1
"and", "break", "do", "else", "elseif",
"end", "false", "for", "function", "if",
"in", "local", "nil", "not", "or",
"repeat", "return", "then", "true", "until", "while"
)
);
defaultIncludes = new HashSet<>(
Arrays.asList(
"map",
"array")
);
languageSpecificPrimitives = new HashSet<>(
Arrays.asList(
"nil",
"string",
"boolean",
"number")
);
instantiationTypes.clear();
/*instantiationTypes.put("array", "LuaArray");
instantiationTypes.put("map", "LuaMap");*/
typeMapping.clear();
typeMapping.put("integer", "number");
typeMapping.put("long", "number");
typeMapping.put("number", "number");
typeMapping.put("float", "number");
typeMapping.put("double", "number");
typeMapping.put("boolean", "boolean");
typeMapping.put("string", "string");
typeMapping.put("UUID", "string");
typeMapping.put("URI", "string");
typeMapping.put("date", "string");
typeMapping.put("DateTime", "string");
typeMapping.put("password", "string");
// TODO fix file mapping
typeMapping.put("file", "string");
// map binary to string as a workaround
// the correct solution is to use []byte
typeMapping.put("binary", "string");
typeMapping.put("ByteArray", "string");
typeMapping.put("object", "TODO_OBJECT_MAPPING");
importMapping = new HashMap<>();
importMapping.put("time.Time", "time");
importMapping.put("*os.File", "os");
importMapping.put("os", "io/ioutil");
cliOptions.clear();
cliOptions.add(new CliOption(CodegenConstants.PACKAGE_NAME, "Lua package name (convention: single word).")
.defaultValue("openapiclient"));
cliOptions.add(new CliOption(CodegenConstants.PACKAGE_VERSION, "Lua package version.")
.defaultValue("1.0.0-1"));
cliOptions.add(new CliOption(CodegenConstants.HIDE_GENERATION_TIMESTAMP, CodegenConstants.HIDE_GENERATION_TIMESTAMP_DESC)
.defaultValue(Boolean.TRUE.toString()));
}
@Override
public void processOpts() {
super.processOpts();
if (additionalProperties.containsKey(CodegenConstants.PACKAGE_NAME)) {
setPackageName((String) additionalProperties.get(CodegenConstants.PACKAGE_NAME));
}
if (additionalProperties.containsKey(CodegenConstants.PACKAGE_VERSION)) {
setPackageVersion((String) additionalProperties.get(CodegenConstants.PACKAGE_VERSION));
}
additionalProperties.put(CodegenConstants.PACKAGE_NAME, packageName);
additionalProperties.put(CodegenConstants.PACKAGE_VERSION, packageVersion);
// set rockspec based on package name, version
setLuaRocksFilename(packageName + "-" + packageVersion + ".rockspec");
additionalProperties.put("apiDocPath", apiDocPath);
additionalProperties.put("modelDocPath", modelDocPath);
apiTestTemplateFiles.put("api_test.mustache", ".lua");
modelTestTemplateFiles.put("model_test.mustache", ".lua");
apiDocTemplateFiles.clear(); // TODO: add api doc template
modelDocTemplateFiles.clear(); // TODO: add model doc template
modelPackage = packageName;
apiPackage = packageName;
//supportingFiles.add(new SupportingFile("README.mustache", "", "README.md"));
supportingFiles.add(new SupportingFile("git_push.sh.mustache", "", "git_push.sh"));
supportingFiles.add(new SupportingFile("gitignore.mustache", "", ".gitignore"));
supportingFiles.add(new SupportingFile("luarocks.mustache", "", luaRocksFilename));
//supportingFiles.add(new SupportingFile("configuration.mustache", "", "configuration.lua"));
//supportingFiles.add(new SupportingFile("api_client.mustache", "", "api_client.lua"));
//supportingFiles.add(new SupportingFile("api_response.mustache", "", "api_response.lua"));
//supportingFiles.add(new SupportingFile(".travis.yml", "", ".travis.yml"));
}
@Override
public String escapeReservedWord(String name) {
// Can't start with an underscore, as our fields need to start with an
// UppercaseLetter so that Lua treats them as public/visible.
// Options?
// - MyName
// - AName
// - TheName
// - XName
// - X_Name
// ... or maybe a suffix?
// - Name_ ... think this will work.
if (this.reservedWordsMappings().containsKey(name)) {
return this.reservedWordsMappings().get(name);
}
return camelize(name) + '_';
}
@Override
public String apiFileFolder() {
return outputFolder + File.separator + packageName + File.separator + "api" + File.separator;
}
@Override
public String modelFileFolder() {
return outputFolder + File.separator + packageName + File.separator + "model" + File.separator;
}
@Override
public String toVarName(String name) {
// obtain the name from nameMapping directly if provided
if (nameMapping.containsKey(name)) {
return nameMapping.get(name);
}
// replace - with _ e.g. created-at => created_at
name = sanitizeName(name.replaceAll("-", "_"));
// if it's all upper case, do nothing
if (name.matches("^[A-Z_]*$"))
return name;
// convert variable name to snake case
// PetId => pet_id
name = underscore(name);
// for reserved word or word starting with number, append _
if (isReservedWord(name))
name = escapeReservedWord(name);
// for reserved word or word starting with number, append _
if (name.matches("^\\d.*"))
name = "Var" + name;
return name;
}
@Override
public String toParamName(String name) {
// obtain the name from parameterNameMapping directly if provided
if (parameterNameMapping.containsKey(name)) {
return parameterNameMapping.get(name);
}
return toVarName(name);
}
@Override
public String toModelName(String name) {
return toModelFilename(name);
}
@Override
public String toModelFilename(String name) {
// obtain the name from modelNameMapping directly if provided
if (modelNameMapping.containsKey(name)) {
return modelNameMapping.get(name);
}
if (!StringUtils.isEmpty(modelNamePrefix)) {
name = modelNamePrefix + "_" + name;
}
if (!StringUtils.isEmpty(modelNameSuffix)) {
name = name + "_" + modelNameSuffix;
}
name = sanitizeName(name);
// model name cannot use reserved keyword, e.g. return
if (isReservedWord(name)) {
LOGGER.warn("{} (reserved word) cannot be used as model name. Renamed to {}", name, "model_" + name);
name = "model_" + name; // e.g. return => ModelReturn (after camelize)
}
// model name starts with number
if (name.matches("^\\d.*")) {
LOGGER.warn("{} (model name starts with number) cannot be used as model name. Renamed to {}", name,
"model_" + name);
name = "model_" + name; // e.g. 200Response => Model200Response (after camelize)
}
return underscore(name);
}
@Override
public String toApiFilename(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'.
// e.g. PetApi.lua => pet_api.lua
return underscore(name) + "_api";
}
@Override
public String toApiTestFilename(String name) {
return toApiFilename(name) + "_spec";
}
@Override
public String toModelTestFilename(String name) {
return toModelFilename(name) + "_spec";
}
/**
* Overrides postProcessParameter to add a vendor extension "x-exportParamName".
* This is useful when paramName starts with a lowercase letter, but we need that
* param to be exportable (starts with an Uppercase letter).
*
* @param parameter CodegenParameter object to be processed.
*/
@Override
public void postProcessParameter(CodegenParameter parameter) {
}
@Override
public String apiTestFileFolder() {
return outputFolder + File.separator + specFolder.replace("/", File.separator);
}
@Override
public String modelTestFileFolder() {
return outputFolder + File.separator + specFolder.replace("/", File.separator);
}
@Override
public String apiDocFileFolder() {
return (outputFolder + "/" + apiDocPath).replace('/', File.separatorChar);
}
@Override
public String modelDocFileFolder() {
return (outputFolder + "/" + modelDocPath).replace('/', File.separatorChar);
}
@Override
public String toModelDocFilename(String name) {
return toModelName(name);
}
@Override
public String toApiDocFilename(String name) {
return toApiName(name);
}
@Override
public String toApiName(String name) {
return underscore(super.toApiName(name));
}
@Override
public String getTypeDeclaration(Schema p) {
if (ModelUtils.isArraySchema(p)) {
Schema inner = ModelUtils.getSchemaItems(p);
return getTypeDeclaration(inner);
} else if (ModelUtils.isMapSchema(p)) {
Schema inner = ModelUtils.getAdditionalProperties(p);
return getTypeDeclaration(inner);
}
// Not using the supertype invocation, because we want to UpperCamelize
// the type.
String schemaType = getSchemaType(p);
if (typeMapping.containsKey(schemaType)) {
return typeMapping.get(schemaType);
}
if (typeMapping.containsValue(schemaType)) {
return schemaType;
}
if (languageSpecificPrimitives.contains(schemaType)) {
return schemaType;
}
return toModelName(schemaType);
}
@Override
public String getSchemaType(Schema p) {
String schemaType = super.getSchemaType(p);
String type = null;
if (typeMapping.containsKey(schemaType)) {
type = typeMapping.get(schemaType);
if (languageSpecificPrimitives.contains(type))
return (type);
} else {
type = schemaType;
}
return type;
}
@Override
public String toOperationId(String operationId) {
String sanitizedOperationId = sanitizeName(operationId);
// method name cannot use reserved keyword, e.g. return
if (isReservedWord(sanitizedOperationId)) {
LOGGER.warn("{} (reserved word) cannot be used as method name. Renamed to {}", operationId, underscore("call_" + operationId));
sanitizedOperationId = "call_" + sanitizedOperationId;
}
return underscore(sanitizedOperationId);
}
@Override
public OperationsMap postProcessOperationsWithModels(OperationsMap objs, List allModels) {
OperationMap objectMap = objs.getOperations();
List operations = objectMap.getOperation();
for (CodegenOperation op : operations) {
String[] items = op.path.split("/", -1);
String luaPath = "";
int pathParamIndex = 0;
for (String item : items) {
if (item.matches("^\\{(.*)\\}$")) { // wrap in {}
// find the datatype of the parameter
//final CodegenParameter cp = op.pathParams.get(pathParamIndex);
// TODO: Handle non-primitives…
//luaPath = luaPath + cp.dataType.toLowerCase(Locale.ROOT);
luaPath = luaPath + "/%s";
pathParamIndex++;
} else if (item.length() != 0) {
luaPath = luaPath + "/" + item;
} else {
//luaPath = luaPath + "/";
}
}
op.vendorExtensions.put("x-codegen-path", luaPath);
}
return objs;
}
@Override
public ModelsMap postProcessModels(ModelsMap objs) {
// remove model imports to avoid error
List> imports = objs.getImports();
final String prefix = modelPackage();
Iterator> iterator = imports.iterator();
while (iterator.hasNext()) {
String _import = iterator.next().get("import");
if (_import.startsWith(prefix))
iterator.remove();
}
// recursively add import for mapping one type to multiple imports
List> recursiveImports = objs.getImports();
if (recursiveImports == null)
return objs;
ListIterator> listIterator = imports.listIterator();
while (listIterator.hasNext()) {
String _import = listIterator.next().get("import");
// if the import package happens to be found in the importMapping (key)
// add the corresponding import package to the list
if (importMapping.containsKey(_import)) {
listIterator.add(createMapping("import", importMapping.get(_import)));
}
}
return postProcessModelsEnum(objs);
}
@Override
protected boolean needToImport(String type) {
return !defaultIncludes.contains(type)
&& !languageSpecificPrimitives.contains(type);
}
@Override
public String escapeQuotationMark(String input) {
// remove " to avoid code injection
return input.replace("\"", "");
}
@Override
public String escapeUnsafeCharacters(String input) {
return input.replace("]]", "] ]");
}
public Map createMapping(String key, String value) {
Map customImport = new HashMap<>();
customImport.put(key, value);
return customImport;
}
@Override
public String toEnumValue(String value, String datatype) {
if ("int".equals(datatype) || "double".equals(datatype) || "float".equals(datatype)) {
return value;
} else {
return escapeText(value);
}
}
@Override
public String toEnumDefaultValue(String value, String datatype) {
return datatype + "_" + value;
}
@Override
public String toEnumVarName(String name, String datatype) {
if (name.length() == 0) {
return "EMPTY";
}
// number
if ("int".equals(datatype) || "double".equals(datatype) || "float".equals(datatype)) {
String varName = name;
varName = varName.replaceAll("-", "MINUS_");
varName = varName.replaceAll("\\+", "PLUS_");
varName = varName.replaceAll("\\.", "_DOT_");
return varName;
}
// for symbol, e.g. $, #
if (getSymbolName(name) != null) {
return getSymbolName(name).toUpperCase(Locale.ROOT);
}
// string
String enumName = sanitizeName(underscore(name).toUpperCase(Locale.ROOT));
enumName = enumName.replaceFirst("^_", "");
enumName = enumName.replaceFirst("_$", "");
if (isReservedWord(enumName) || enumName.matches("\\d.*")) { // reserved word or starts with number
return escapeReservedWord(enumName);
} else {
return enumName;
}
}
@Override
public String toEnumName(CodegenProperty property) {
String enumName = underscore(toModelName(property.name)).toUpperCase(Locale.ROOT);
// remove [] for array or map of enum
enumName = enumName.replace("[]", "");
if (enumName.matches("\\d.*")) { // starts with number
return "_" + enumName;
} else {
return enumName;
}
}
@Override
public String toModelImport(String name) {
if (needToImport(toModelName(name))) {
return toModelName(name);
}
return name;
}
@Override
public void postProcess() {
System.out.println("################################################################################");
System.out.println("# Thanks for using OpenAPI Generator. #");
System.out.println("# Please consider donation to help us maintain this project \uD83D\uDE4F #");
System.out.println("# https://opencollective.com/openapi_generator/donate #");
System.out.println("# #");
System.out.println("# This generator is contributed by daurnimator (https://github.com/daurnimator)#");
System.out.println("# Pls support his work directly via https://github.com/sponsors/daurnimator \uD83D\uDE4F #");
System.out.println("################################################################################");
}
@Override
public GeneratorLanguage generatorLanguage() { return GeneratorLanguage.LUA; }
}