forked from loafle/openapi-generator-original
Merge branch 'oas3_support2' into php-client
This commit is contained in:
@@ -1436,7 +1436,7 @@ public class DefaultCodegen implements CodegenConfig {
|
||||
m.allowableValues.put("values", schema.getEnum());
|
||||
}
|
||||
if (schema.getAdditionalProperties() != null || schema instanceof MapSchema) {
|
||||
addParentContainer(m, m.name, schema);
|
||||
addAdditionPropertiesToCodeGenModel(m, schema);
|
||||
}
|
||||
addVars(m, schema.getProperties(), schema.getRequired());
|
||||
}
|
||||
@@ -1446,7 +1446,7 @@ public class DefaultCodegen implements CodegenConfig {
|
||||
postProcessModelProperty(m, prop);
|
||||
}
|
||||
}
|
||||
LOGGER.info("debugging fromModel return: " + m);
|
||||
LOGGER.debug("debugging fromModel return: " + m);
|
||||
|
||||
return m;
|
||||
}
|
||||
@@ -1481,6 +1481,10 @@ public class DefaultCodegen implements CodegenConfig {
|
||||
return false;
|
||||
}
|
||||
|
||||
protected void addAdditionPropertiesToCodeGenModel(CodegenModel codegenModel, Schema schema) {
|
||||
addParentContainer(codegenModel, codegenModel.name, schema);
|
||||
}
|
||||
|
||||
protected void addProperties(Map<String, Schema> properties, List<String> required, Schema schema, Map<String, Schema> allSchemas) {
|
||||
if (schema instanceof ComposedSchema) {
|
||||
ComposedSchema composedSchema = (ComposedSchema) schema;
|
||||
@@ -1532,7 +1536,7 @@ public class DefaultCodegen implements CodegenConfig {
|
||||
LOGGER.error("Unexpected missing property for name " + name);
|
||||
return null;
|
||||
}
|
||||
LOGGER.info("debugging fromProperty for " + name + " : " + p);
|
||||
LOGGER.debug("debugging fromProperty for " + name + " : " + p);
|
||||
|
||||
CodegenProperty property = CodegenModelFactory.newInstance(CodegenModelType.PROPERTY);
|
||||
property.name = toVarName(name);
|
||||
@@ -1620,7 +1624,6 @@ public class DefaultCodegen implements CodegenConfig {
|
||||
if (p instanceof BinarySchema || SchemaTypeUtil.BINARY_FORMAT.equals(p.getFormat())) {
|
||||
property.isBinary = true;
|
||||
} else if (p instanceof FileSchema) {
|
||||
LOGGER.info("debugging FileSchema: " + property.baseName);
|
||||
property.isFile = true;
|
||||
} else {
|
||||
property.maxLength = p.getMaxLength();
|
||||
@@ -1777,7 +1780,7 @@ public class DefaultCodegen implements CodegenConfig {
|
||||
setNonArrayMapProperty(property, type);
|
||||
}
|
||||
|
||||
LOGGER.info("debugging from property : " + property);
|
||||
LOGGER.debug("debugging from property return: " + property);
|
||||
return property;
|
||||
}
|
||||
|
||||
@@ -2112,14 +2115,12 @@ public class DefaultCodegen implements CodegenConfig {
|
||||
// add form parameters to the beginning of all parameter list
|
||||
if (prependFormOrBodyParameters) {
|
||||
for (CodegenParameter cp : formParams) {
|
||||
LOGGER.info("Adding " + cp.baseName + " to allParams list");
|
||||
allParams.add(cp.copy());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// process body parameter
|
||||
if (StringUtils.isNotBlank(requestBody.get$ref())) {
|
||||
LOGGER.info("request body name: " + getSimpleRef(requestBody.get$ref()));
|
||||
requestBody = openAPI.getComponents().getRequestBodies().get(getSimpleRef(requestBody.get$ref()));
|
||||
}
|
||||
bodyParam = fromRequestBody(requestBody, schemas, imports);
|
||||
@@ -2138,8 +2139,6 @@ public class DefaultCodegen implements CodegenConfig {
|
||||
|
||||
if (parameters != null) {
|
||||
for (Parameter param : parameters) {
|
||||
LOGGER.info("parameter debugging " + param.getName() + " => " + param);
|
||||
|
||||
if (StringUtils.isNotBlank(param.get$ref())) {
|
||||
param = getParameterFromRef(param.get$ref(), openAPI);
|
||||
}
|
||||
@@ -2456,7 +2455,6 @@ public class DefaultCodegen implements CodegenConfig {
|
||||
}
|
||||
|
||||
CodegenProperty codegenProperty = fromProperty(parameter.getName(), parameterSchema);
|
||||
LOGGER.info("fromProperty debug required: " + parameter.getRequired());
|
||||
// TODO revise below which seems not working
|
||||
//if (parameterSchema.getRequired() != null && !parameterSchema.getRequired().isEmpty() && parameterSchema.getRequired().contains(codegenProperty.baseName)) {
|
||||
codegenProperty.required = Boolean.TRUE.equals(parameter.getRequired()) ? true : false;
|
||||
@@ -2467,9 +2465,15 @@ public class DefaultCodegen implements CodegenConfig {
|
||||
setParameterBooleanFlagWithCodegenProperty(codegenParameter, codegenProperty);
|
||||
|
||||
|
||||
codegenParameter.required = codegenProperty.required;
|
||||
codegenParameter.dataType = codegenProperty.datatype;
|
||||
String parameterDataType = this.getParameterDataType(parameter, parameterSchema);
|
||||
if (parameterDataType != null) {
|
||||
codegenParameter.dataType = parameterDataType;
|
||||
} else {
|
||||
codegenParameter.dataType = codegenProperty.datatype;
|
||||
}
|
||||
codegenParameter.dataFormat = codegenProperty.dataFormat;
|
||||
codegenParameter.required = codegenProperty.required;
|
||||
|
||||
if (codegenProperty.isEnum) {
|
||||
codegenParameter.datatypeWithEnum = codegenProperty.datatypeWithEnum;
|
||||
codegenParameter.enumName = codegenProperty.enumName;
|
||||
@@ -2670,10 +2674,21 @@ public class DefaultCodegen implements CodegenConfig {
|
||||
setParameterExampleValue(codegenParameter);
|
||||
|
||||
postProcessParameter(codegenParameter);
|
||||
LOGGER.info("debugging codegenParameter return: " + codegenParameter);
|
||||
LOGGER.debug("debugging codegenParameter return: " + codegenParameter);
|
||||
return codegenParameter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the data type of a parameter.
|
||||
* Returns null by default to use the CodegenProperty.datatype value
|
||||
* @param parameter
|
||||
* @param property
|
||||
* @return
|
||||
*/
|
||||
protected String getParameterDataType(Parameter parameter, Schema schema) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean isDataTypeBinary(String dataType) {
|
||||
if (dataType != null) {
|
||||
return dataType.toLowerCase().startsWith("byte");
|
||||
@@ -3706,7 +3721,7 @@ public class DefaultCodegen implements CodegenConfig {
|
||||
return mediaType.getSchema();
|
||||
}
|
||||
|
||||
private Schema getSchemaFromResponse(ApiResponse response) {
|
||||
protected Schema getSchemaFromResponse(ApiResponse response) {
|
||||
if (response.getContent() == null || response.getContent().isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
@@ -3745,11 +3760,8 @@ public class DefaultCodegen implements CodegenConfig {
|
||||
|
||||
scopes.add(scope);
|
||||
}
|
||||
//LOGGER.info("setOauth2Info setting scopes properly");
|
||||
codegenSecurity.scopes = scopes;
|
||||
}
|
||||
|
||||
//LOGGER.info("setOauth2Info scope: " + flow.getScopes());
|
||||
}
|
||||
|
||||
private List<Schema> getInterfaces(ComposedSchema composed) {
|
||||
@@ -3855,15 +3867,12 @@ public class DefaultCodegen implements CodegenConfig {
|
||||
|
||||
protected String getParentName(ComposedSchema composedSchema, Map<String, Schema> allSchemas) {
|
||||
if (composedSchema.getAllOf() != null && !composedSchema.getAllOf().isEmpty()) {
|
||||
LOGGER.info("debugging getParentName if: " + composedSchema);
|
||||
Schema schema = composedSchema.getAllOf().get(0);
|
||||
String ref = schema.get$ref();
|
||||
if (StringUtils.isBlank(ref)) {
|
||||
return null;
|
||||
}
|
||||
return getSimpleRef(ref);
|
||||
} else {
|
||||
LOGGER.info("debugging getParentName else: " + composedSchema);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@@ -3916,7 +3925,7 @@ public class DefaultCodegen implements CodegenConfig {
|
||||
|
||||
public List<CodegenParameter> fromRequestBodyToFormParameters(RequestBody body, Map<String, Schema> schemas, Set<String> imports) {
|
||||
List<CodegenParameter> parameters = new ArrayList<CodegenParameter>();
|
||||
LOGGER.info("Request body = " + body);
|
||||
LOGGER.debug("debugging fromRequestBodyToFormParameters= " + body);
|
||||
Schema schema = getSchemaFromBody(body);
|
||||
if (schema.getProperties() != null && !schema.getProperties().isEmpty()) {
|
||||
Map<String, Schema> properties = schema.getProperties();
|
||||
@@ -3930,17 +3939,13 @@ public class DefaultCodegen implements CodegenConfig {
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < parameters.size(); i++) {
|
||||
System.out.println("parmaeter name:" + parameters.get(i).baseName);
|
||||
}
|
||||
|
||||
return parameters;
|
||||
}
|
||||
|
||||
public CodegenParameter fromFormProperty(String name, Schema propertySchema, Set<String> imports) {
|
||||
CodegenParameter codegenParameter = CodegenModelFactory.newInstance(CodegenModelType.PARAMETER);
|
||||
|
||||
LOGGER.info("Debugging fromRequestBodyToFormParameters: " + name);
|
||||
LOGGER.debug("Debugging fromFormProperty: " + name);
|
||||
CodegenProperty codegenProperty = fromProperty(name, propertySchema);
|
||||
|
||||
codegenParameter.isFormParam = Boolean.TRUE;
|
||||
@@ -4043,7 +4048,6 @@ public class DefaultCodegen implements CodegenConfig {
|
||||
codegenParameter.baseType = codegenModel.classname;
|
||||
codegenParameter.dataType = getTypeDeclaration(codegenModel.classname);
|
||||
codegenParameter.description = codegenModel.description;
|
||||
LOGGER.info("debugging fromRequestBody imports model: " + codegenParameter);
|
||||
imports.add(codegenParameter.baseType);
|
||||
} else {
|
||||
CodegenProperty codegenProperty = fromProperty("property", schema);
|
||||
@@ -4051,10 +4055,8 @@ public class DefaultCodegen implements CodegenConfig {
|
||||
codegenParameter.baseType = codegenProperty.baseType;
|
||||
codegenParameter.dataType = codegenProperty.datatype;
|
||||
codegenParameter.description = codegenProperty.description;
|
||||
LOGGER.info("Setting description to body parameter: " + codegenProperty.description);
|
||||
|
||||
if (codegenProperty.complexType != null) {
|
||||
LOGGER.info("debugging fromRequestBody imports: " + codegenProperty.complexType);
|
||||
imports.add(codegenProperty.complexType);
|
||||
}
|
||||
}
|
||||
@@ -4118,4 +4120,22 @@ public class DefaultCodegen implements CodegenConfig {
|
||||
return false;
|
||||
}
|
||||
|
||||
protected void addOption(String key, String description) {
|
||||
addOption(key, description, null);
|
||||
}
|
||||
|
||||
protected void addOption(String key, String description, String defaultValue) {
|
||||
CliOption option = new CliOption(key, description);
|
||||
if (defaultValue != null)
|
||||
option.defaultValue(defaultValue);
|
||||
cliOptions.add(option);
|
||||
}
|
||||
|
||||
protected void addSwitch(String key, String description, Boolean defaultValue) {
|
||||
CliOption option = CliOption.newBoolean(key, description);
|
||||
if (defaultValue != null)
|
||||
option.defaultValue(defaultValue.toString());
|
||||
cliOptions.add(option);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -359,7 +359,7 @@ public class DefaultGenerator extends AbstractGenerator implements Generator {
|
||||
try {
|
||||
//don't generate models that have an import mapping
|
||||
if (config.importMapping().containsKey(name)) {
|
||||
LOGGER.info("Model " + name + " not imported due to import mapping");
|
||||
LOGGER.debug("Model " + name + " not imported due to import mapping");
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,948 @@
|
||||
package org.openapitools.codegen.languages;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.samskivert.mustache.Mustache;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.openapitools.codegen.*;
|
||||
import org.openapitools.codegen.utils.*;
|
||||
import org.openapitools.codegen.mustache.*;
|
||||
import io.swagger.v3.oas.models.security.SecurityScheme;
|
||||
import io.swagger.v3.oas.models.*;
|
||||
import io.swagger.v3.oas.models.media.*;
|
||||
import io.swagger.v3.oas.models.responses.ApiResponse;
|
||||
import io.swagger.v3.oas.models.parameters.*;
|
||||
import io.swagger.v3.core.util.Yaml;
|
||||
import io.swagger.v3.parser.util.SchemaTypeUtil;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.*;
|
||||
|
||||
public abstract class AbstractCSharpCodegen extends DefaultCodegen implements CodegenConfig {
|
||||
|
||||
protected boolean optionalAssemblyInfoFlag = true;
|
||||
protected boolean optionalProjectFileFlag = true;
|
||||
protected boolean optionalEmitDefaultValue = false;
|
||||
protected boolean optionalMethodArgumentFlag = true;
|
||||
protected boolean useDateTimeOffsetFlag = false;
|
||||
protected boolean useCollection = false;
|
||||
protected boolean returnICollection = false;
|
||||
protected boolean netCoreProjectFileFlag = false;
|
||||
|
||||
protected String modelPropertyNaming = CodegenConstants.MODEL_PROPERTY_NAMING_TYPE.PascalCase.name();
|
||||
|
||||
protected String packageVersion = "1.0.0";
|
||||
protected String packageName = "IO.Swagger";
|
||||
protected String packageTitle = "Swagger Library";
|
||||
protected String packageProductName = "SwaggerLibrary";
|
||||
protected String packageDescription = "A library generated from a Swagger doc";
|
||||
protected String packageCompany = "Swagger";
|
||||
protected String packageCopyright = "No Copyright";
|
||||
protected String packageAuthors = "Swagger";
|
||||
|
||||
protected String interfacePrefix = "I";
|
||||
|
||||
protected String sourceFolder = "src";
|
||||
|
||||
// TODO: Add option for test folder output location. Nice to allow e.g. ./test instead of ./src.
|
||||
// This would require updating relative paths (e.g. path to main project file in test project file)
|
||||
protected String testFolder = sourceFolder;
|
||||
|
||||
protected Set<String> collectionTypes;
|
||||
protected Set<String> mapTypes;
|
||||
|
||||
protected Logger LOGGER = LoggerFactory.getLogger(AbstractCSharpCodegen.class);
|
||||
|
||||
public AbstractCSharpCodegen() {
|
||||
super();
|
||||
|
||||
supportsInheritance = true;
|
||||
|
||||
// C# does not use import mapping
|
||||
importMapping.clear();
|
||||
|
||||
outputFolder = "generated-code" + File.separator + this.getName();
|
||||
embeddedTemplateDir = templateDir = this.getName();
|
||||
|
||||
collectionTypes = new HashSet<String>(
|
||||
Arrays.asList(
|
||||
"IList", "List",
|
||||
"ICollection", "Collection",
|
||||
"IEnumerable")
|
||||
);
|
||||
|
||||
mapTypes = new HashSet<String>(
|
||||
Arrays.asList("IDictionary")
|
||||
);
|
||||
|
||||
// NOTE: C# uses camel cased reserved words, while models are title cased. We don't want lowercase comparisons.
|
||||
reservedWords.addAll(
|
||||
Arrays.asList(
|
||||
// set "client" as a reserved word to avoid conflicts with IO.Swagger.Client
|
||||
// this is a workaround and can be removed if c# api client is updated to use
|
||||
// fully qualified name
|
||||
"Client", "client", "parameter",
|
||||
// local variable names in API methods (endpoints)
|
||||
"localVarPath", "localVarPathParams", "localVarQueryParams", "localVarHeaderParams",
|
||||
"localVarFormParams", "localVarFileParams", "localVarStatusCode", "localVarResponse",
|
||||
"localVarPostBody", "localVarHttpHeaderAccepts", "localVarHttpHeaderAccept",
|
||||
"localVarHttpContentTypes", "localVarHttpContentType",
|
||||
"localVarStatusCode",
|
||||
// C# reserved words
|
||||
"abstract", "as", "base", "bool", "break", "byte", "case", "catch", "char", "checked",
|
||||
"class", "const", "continue", "decimal", "default", "delegate", "do", "double", "else",
|
||||
"enum", "event", "explicit", "extern", "false", "finally", "fixed", "float", "for",
|
||||
"foreach", "goto", "if", "implicit", "in", "int", "interface", "internal", "is", "lock",
|
||||
"long", "namespace", "new", "null", "object", "operator", "out", "override", "params",
|
||||
"private", "protected", "public", "readonly", "ref", "return", "sbyte", "sealed",
|
||||
"short", "sizeof", "stackalloc", "static", "string", "struct", "switch", "this", "throw",
|
||||
"true", "try", "typeof", "uint", "ulong", "unchecked", "unsafe", "ushort", "using",
|
||||
"virtual", "void", "volatile", "while")
|
||||
);
|
||||
|
||||
// TODO: Either include fully qualified names here or handle in DefaultCodegen via lastIndexOf(".") search
|
||||
languageSpecificPrimitives = new HashSet<String>(
|
||||
Arrays.asList(
|
||||
"String",
|
||||
"string",
|
||||
"bool?",
|
||||
"double?",
|
||||
"decimal?",
|
||||
"int?",
|
||||
"long?",
|
||||
"float?",
|
||||
"byte[]",
|
||||
"ICollection",
|
||||
"Collection",
|
||||
"List",
|
||||
"Dictionary",
|
||||
"DateTime?",
|
||||
"DateTimeOffset?",
|
||||
"String",
|
||||
"Boolean",
|
||||
"Double",
|
||||
"Int32",
|
||||
"Int64",
|
||||
"Float",
|
||||
"Guid?",
|
||||
"System.IO.Stream", // not really a primitive, we include it to avoid model import
|
||||
"Object")
|
||||
);
|
||||
|
||||
instantiationTypes.put("array", "List");
|
||||
instantiationTypes.put("list", "List");
|
||||
instantiationTypes.put("map", "Dictionary");
|
||||
|
||||
// Nullable types here assume C# 2 support is not part of base
|
||||
typeMapping = new HashMap<String, String>();
|
||||
typeMapping.put("string", "string");
|
||||
typeMapping.put("binary", "byte[]");
|
||||
typeMapping.put("bytearray", "byte[]");
|
||||
typeMapping.put("boolean", "bool?");
|
||||
typeMapping.put("integer", "int?");
|
||||
typeMapping.put("float", "float?");
|
||||
typeMapping.put("long", "long?");
|
||||
typeMapping.put("double", "double?");
|
||||
typeMapping.put("number", "decimal?");
|
||||
typeMapping.put("datetime", "DateTime?");
|
||||
typeMapping.put("date", "DateTime?");
|
||||
typeMapping.put("file", "System.IO.Stream");
|
||||
typeMapping.put("array", "List");
|
||||
typeMapping.put("list", "List");
|
||||
typeMapping.put("map", "Dictionary");
|
||||
typeMapping.put("object", "Object");
|
||||
typeMapping.put("uuid", "Guid?");
|
||||
}
|
||||
|
||||
public void setReturnICollection(boolean returnICollection) {
|
||||
this.returnICollection = returnICollection;
|
||||
}
|
||||
|
||||
public void setOptionalEmitDefaultValue(boolean optionalEmitDefaultValue) {
|
||||
this.optionalEmitDefaultValue = optionalEmitDefaultValue;
|
||||
}
|
||||
|
||||
public void setUseCollection(boolean useCollection) {
|
||||
this.useCollection = useCollection;
|
||||
if (useCollection) {
|
||||
typeMapping.put("array", "Collection");
|
||||
typeMapping.put("list", "Collection");
|
||||
|
||||
instantiationTypes.put("array", "Collection");
|
||||
instantiationTypes.put("list", "Collection");
|
||||
}
|
||||
}
|
||||
|
||||
public void setOptionalMethodArgumentFlag(boolean flag) {
|
||||
this.optionalMethodArgumentFlag = flag;
|
||||
}
|
||||
|
||||
public void setNetCoreProjectFileFlag(boolean flag) {
|
||||
this.netCoreProjectFileFlag = flag;
|
||||
}
|
||||
|
||||
public void useDateTimeOffset(boolean flag) {
|
||||
this.useDateTimeOffsetFlag = flag;
|
||||
if (flag) typeMapping.put("datetime", "DateTimeOffset?");
|
||||
else typeMapping.put("datetime", "DateTime?");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processOpts() {
|
||||
super.processOpts();
|
||||
|
||||
// {{packageVersion}}
|
||||
if (additionalProperties.containsKey(CodegenConstants.PACKAGE_VERSION)) {
|
||||
setPackageVersion((String) additionalProperties.get(CodegenConstants.PACKAGE_VERSION));
|
||||
} else {
|
||||
additionalProperties.put(CodegenConstants.PACKAGE_VERSION, packageVersion);
|
||||
}
|
||||
|
||||
// {{sourceFolder}}
|
||||
if (additionalProperties.containsKey(CodegenConstants.SOURCE_FOLDER)) {
|
||||
setSourceFolder((String) additionalProperties.get(CodegenConstants.SOURCE_FOLDER));
|
||||
} else {
|
||||
additionalProperties.put(CodegenConstants.SOURCE_FOLDER, this.sourceFolder);
|
||||
}
|
||||
|
||||
// {{packageName}}
|
||||
if (additionalProperties.containsKey(CodegenConstants.PACKAGE_NAME)) {
|
||||
setPackageName((String) additionalProperties.get(CodegenConstants.PACKAGE_NAME));
|
||||
} else {
|
||||
additionalProperties.put(CodegenConstants.PACKAGE_NAME, packageName);
|
||||
}
|
||||
|
||||
if (additionalProperties.containsKey(CodegenConstants.INVOKER_PACKAGE)) {
|
||||
LOGGER.warn(String.format("%s is not used by C# generators. Please use %s", CodegenConstants.INVOKER_PACKAGE, CodegenConstants.PACKAGE_NAME));
|
||||
}
|
||||
|
||||
// {{packageTitle}}
|
||||
if (additionalProperties.containsKey(CodegenConstants.PACKAGE_TITLE)) {
|
||||
setPackageTitle((String) additionalProperties.get(CodegenConstants.PACKAGE_TITLE));
|
||||
} else {
|
||||
additionalProperties.put(CodegenConstants.PACKAGE_TITLE, packageTitle);
|
||||
}
|
||||
|
||||
// {{packageProductName}}
|
||||
if (additionalProperties.containsKey(CodegenConstants.PACKAGE_PRODUCTNAME)) {
|
||||
setPackageProductName((String) additionalProperties.get(CodegenConstants.PACKAGE_PRODUCTNAME));
|
||||
} else {
|
||||
additionalProperties.put(CodegenConstants.PACKAGE_PRODUCTNAME, packageProductName);
|
||||
}
|
||||
|
||||
// {{packageDescription}}
|
||||
if (additionalProperties.containsKey(CodegenConstants.PACKAGE_DESCRIPTION)) {
|
||||
setPackageDescription((String) additionalProperties.get(CodegenConstants.PACKAGE_DESCRIPTION));
|
||||
} else {
|
||||
additionalProperties.put(CodegenConstants.PACKAGE_DESCRIPTION, packageDescription);
|
||||
}
|
||||
|
||||
// {{packageCompany}}
|
||||
if (additionalProperties.containsKey(CodegenConstants.PACKAGE_COMPANY)) {
|
||||
setPackageCompany((String) additionalProperties.get(CodegenConstants.PACKAGE_COMPANY));
|
||||
} else {
|
||||
additionalProperties.put(CodegenConstants.PACKAGE_COMPANY, packageCompany);
|
||||
}
|
||||
|
||||
// {{packageCopyright}}
|
||||
if (additionalProperties.containsKey(CodegenConstants.PACKAGE_COPYRIGHT)) {
|
||||
setPackageCopyright((String) additionalProperties.get(CodegenConstants.PACKAGE_COPYRIGHT));
|
||||
} else {
|
||||
additionalProperties.put(CodegenConstants.PACKAGE_COPYRIGHT, packageCopyright);
|
||||
}
|
||||
|
||||
// {{packageAuthors}}
|
||||
if (additionalProperties.containsKey(CodegenConstants.PACKAGE_AUTHORS)) {
|
||||
setPackageAuthors((String) additionalProperties.get(CodegenConstants.PACKAGE_AUTHORS));
|
||||
} else {
|
||||
additionalProperties.put(CodegenConstants.PACKAGE_AUTHORS, packageAuthors);
|
||||
}
|
||||
|
||||
// {{useDateTimeOffset}}
|
||||
if (additionalProperties.containsKey(CodegenConstants.USE_DATETIME_OFFSET)) {
|
||||
useDateTimeOffset(convertPropertyToBooleanAndWriteBack(CodegenConstants.USE_DATETIME_OFFSET));
|
||||
} else {
|
||||
additionalProperties.put(CodegenConstants.USE_DATETIME_OFFSET, useDateTimeOffsetFlag);
|
||||
}
|
||||
|
||||
if (additionalProperties.containsKey(CodegenConstants.USE_COLLECTION)) {
|
||||
setUseCollection(convertPropertyToBooleanAndWriteBack(CodegenConstants.USE_COLLECTION));
|
||||
} else {
|
||||
additionalProperties.put(CodegenConstants.USE_COLLECTION, useCollection);
|
||||
}
|
||||
|
||||
if (additionalProperties.containsKey(CodegenConstants.RETURN_ICOLLECTION)) {
|
||||
setReturnICollection(convertPropertyToBooleanAndWriteBack(CodegenConstants.RETURN_ICOLLECTION));
|
||||
} else {
|
||||
additionalProperties.put(CodegenConstants.RETURN_ICOLLECTION, returnICollection);
|
||||
}
|
||||
|
||||
if (additionalProperties.containsKey(CodegenConstants.OPTIONAL_EMIT_DEFAULT_VALUES)) {
|
||||
setOptionalEmitDefaultValue(convertPropertyToBooleanAndWriteBack(CodegenConstants.OPTIONAL_EMIT_DEFAULT_VALUES));
|
||||
} else {
|
||||
additionalProperties.put(CodegenConstants.OPTIONAL_EMIT_DEFAULT_VALUES, optionalEmitDefaultValue);
|
||||
}
|
||||
|
||||
if (additionalProperties.containsKey(CodegenConstants.NETCORE_PROJECT_FILE)) {
|
||||
setNetCoreProjectFileFlag(convertPropertyToBooleanAndWriteBack(CodegenConstants.NETCORE_PROJECT_FILE));
|
||||
} else {
|
||||
additionalProperties.put(CodegenConstants.NETCORE_PROJECT_FILE, netCoreProjectFileFlag);
|
||||
}
|
||||
|
||||
if (additionalProperties.containsKey(CodegenConstants.INTERFACE_PREFIX)) {
|
||||
String useInterfacePrefix = additionalProperties.get(CodegenConstants.INTERFACE_PREFIX).toString();
|
||||
if("false".equals(useInterfacePrefix.toLowerCase())) {
|
||||
setInterfacePrefix("");
|
||||
} else if(!"true".equals(useInterfacePrefix.toLowerCase())) {
|
||||
// NOTE: if user passes "true" explicitly, we use the default I- prefix. The other supported case here is a custom prefix.
|
||||
setInterfacePrefix(sanitizeName(useInterfacePrefix));
|
||||
}
|
||||
}
|
||||
|
||||
// This either updates additionalProperties with the above fixes, or sets the default if the option was not specified.
|
||||
additionalProperties.put(CodegenConstants.INTERFACE_PREFIX, interfacePrefix);
|
||||
|
||||
addMustacheLambdas(additionalProperties);
|
||||
}
|
||||
|
||||
private void addMustacheLambdas(Map<String, Object> objs) {
|
||||
|
||||
Map<String, Mustache.Lambda> lambdas = new ImmutableMap.Builder<String, Mustache.Lambda>()
|
||||
.put("lowercase", new LowercaseLambda().generator(this))
|
||||
.put("uppercase", new UppercaseLambda())
|
||||
.put("titlecase", new TitlecaseLambda())
|
||||
.put("camelcase", new CamelCaseLambda().generator(this))
|
||||
.put("camelcase_param", new CamelCaseLambda().generator(this).escapeAsParamName(true))
|
||||
.put("indented", new IndentedLambda())
|
||||
.put("indented_8", new IndentedLambda(8, " "))
|
||||
.put("indented_12", new IndentedLambda(12, " "))
|
||||
.put("indented_16", new IndentedLambda(16, " "))
|
||||
.build();
|
||||
|
||||
if (objs.containsKey("lambda")) {
|
||||
LOGGER.warn("An property named 'lambda' already exists. Mustache lambdas renamed from 'lambda' to '_lambda'. " +
|
||||
"You'll likely need to use a custom template, " +
|
||||
"see https://github.com/swagger-api/swagger-codegen#modifying-the-client-library-format. ");
|
||||
objs.put("_lambda", lambdas);
|
||||
} else {
|
||||
objs.put("lambda", lambdas);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postProcessModelProperty(CodegenModel model, CodegenProperty property) {
|
||||
super.postProcessModelProperty(model, property);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> postProcessModels(Map<String, Object> objs) {
|
||||
List<Object> models = (List<Object>) objs.get("models");
|
||||
for (Object _mo : models) {
|
||||
Map<String, Object> mo = (Map<String, Object>) _mo;
|
||||
CodegenModel cm = (CodegenModel) mo.get("model");
|
||||
for (CodegenProperty var : cm.vars) {
|
||||
// check to see if model name is same as the property name
|
||||
// which will result in compilation error
|
||||
// if found, prepend with _ to workaround the limitation
|
||||
if (var.name.equalsIgnoreCase(cm.name)) {
|
||||
var.name = "_" + var.name;
|
||||
}
|
||||
}
|
||||
}
|
||||
// process enum in models
|
||||
return postProcessModelsEnum(objs);
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoked by {@link DefaultGenerator} after all models have been post-processed, allowing for a last pass of codegen-specific model cleanup.
|
||||
*
|
||||
* @param objs Current state of codegen object model.
|
||||
* @return An in-place modified state of the codegen object model.
|
||||
*/
|
||||
@Override
|
||||
public Map<String, Object> postProcessAllModels(Map<String, Object> objs) {
|
||||
final Map<String, Object> processed = super.postProcessAllModels(objs);
|
||||
postProcessEnumRefs(processed);
|
||||
return processed;
|
||||
}
|
||||
|
||||
/**
|
||||
* C# differs from other languages in that Enums are not _true_ objects; enums are compiled to integral types.
|
||||
* So, in C#, an enum is considers more like a user-defined primitive.
|
||||
*
|
||||
* When working with enums, we can't always assume a RefModel is a nullable type (where default(YourType) == null),
|
||||
* so this post processing runs through all models to find RefModel'd enums. Then, it runs through all vars and modifies
|
||||
* those vars referencing RefModel'd enums to work the same as inlined enums rather than as objects.
|
||||
* @param models processed models to be further processed for enum references
|
||||
*/
|
||||
@SuppressWarnings({ "unchecked" })
|
||||
private void postProcessEnumRefs(final Map<String, Object> models) {
|
||||
Map<String, CodegenModel> enumRefs = new HashMap<String, CodegenModel>();
|
||||
for (Map.Entry<String, Object> entry : models.entrySet()) {
|
||||
CodegenModel model = ModelUtils.getModelByName(entry.getKey(), models);
|
||||
if (model.isEnum) {
|
||||
enumRefs.put(entry.getKey(), model);
|
||||
}
|
||||
}
|
||||
|
||||
for (Map.Entry<String, Object> entry : models.entrySet()) {
|
||||
String swaggerName = entry.getKey();
|
||||
CodegenModel model = ModelUtils.getModelByName(swaggerName, models);
|
||||
if (model != null) {
|
||||
for (CodegenProperty var : model.allVars) {
|
||||
if (enumRefs.containsKey(var.datatype)) {
|
||||
// Handle any enum properties referred to by $ref.
|
||||
// This is different in C# than most other generators, because enums in C# are compiled to integral types,
|
||||
// while enums in many other languages are true objects.
|
||||
CodegenModel refModel = enumRefs.get(var.datatype);
|
||||
var.allowableValues = refModel.allowableValues;
|
||||
var.isEnum = true;
|
||||
|
||||
updateCodegenPropertyEnum(var);
|
||||
|
||||
// We do these after updateCodegenPropertyEnum to avoid generalities that don't mesh with C#.
|
||||
var.isPrimitiveType = true;
|
||||
}
|
||||
}
|
||||
|
||||
// We're looping all models here.
|
||||
if (model.isEnum) {
|
||||
// We now need to make allowableValues.enumVars look like the context of CodegenProperty
|
||||
Boolean isString = false;
|
||||
Boolean isInteger = false;
|
||||
Boolean isLong = false;
|
||||
Boolean isByte = false;
|
||||
|
||||
if (model.dataType.startsWith("byte")) {
|
||||
// C# Actually supports byte and short enums, swagger spec only supports byte.
|
||||
isByte = true;
|
||||
model.vendorExtensions.put("x-enum-byte", true);
|
||||
} else if (model.dataType.startsWith("int32")) {
|
||||
isInteger = true;
|
||||
model.vendorExtensions.put("x-enum-integer", true);
|
||||
} else if (model.dataType.startsWith("int64")) {
|
||||
isLong = true;
|
||||
model.vendorExtensions.put("x-enum-long", true);
|
||||
} else {
|
||||
// C# doesn't support non-integral enums, so we need to treat everything else as strings (e.g. to not lose precision or data integrity)
|
||||
isString = true;
|
||||
model.vendorExtensions.put("x-enum-string", true);
|
||||
}
|
||||
|
||||
// Since we iterate enumVars for modelnnerEnum and enumClass templates, and CodegenModel is missing some of CodegenProperty's properties,
|
||||
// we can take advantage of Mustache's contextual lookup to add the same "properties" to the model's enumVars scope rather than CodegenProperty's scope.
|
||||
List<Map<String, String>> enumVars = (ArrayList<Map<String, String>>)model.allowableValues.get("enumVars");
|
||||
List<Map<String, Object>> newEnumVars = new ArrayList<Map<String, Object>>();
|
||||
for (Map<String, String> enumVar : enumVars) {
|
||||
Map<String, Object> mixedVars = new HashMap<String, Object>();
|
||||
mixedVars.putAll(enumVar);
|
||||
|
||||
mixedVars.put("isString", isString);
|
||||
mixedVars.put("isLong", isLong);
|
||||
mixedVars.put("isInteger", isInteger);
|
||||
mixedVars.put("isByte", isByte);
|
||||
|
||||
newEnumVars.add(mixedVars);
|
||||
}
|
||||
|
||||
if (!newEnumVars.isEmpty()) {
|
||||
model.allowableValues.put("enumVars", newEnumVars);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
LOGGER.warn("Expected to retrieve model %s by name, but no model was found. Check your -Dmodels inclusions.", swaggerName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update codegen property's enum by adding "enumVars" (with name and value)
|
||||
*
|
||||
* @param var list of CodegenProperty
|
||||
*/
|
||||
@Override
|
||||
public void updateCodegenPropertyEnum(CodegenProperty var) {
|
||||
if (var.vendorExtensions == null) {
|
||||
var.vendorExtensions = new HashMap<>();
|
||||
}
|
||||
|
||||
super.updateCodegenPropertyEnum(var);
|
||||
|
||||
// Because C# uses nullable primitives for datatype, and datatype is used in DefaultCodegen for determining enum-ness, guard against weirdness here.
|
||||
if (var.isEnum) {
|
||||
if ("byte".equals(var.dataFormat)) {// C# Actually supports byte and short enums.
|
||||
var.vendorExtensions.put("x-enum-byte", true);
|
||||
var.isString = false;
|
||||
var.isLong = false;
|
||||
var.isInteger = false;
|
||||
} else if ("int32".equals(var.dataFormat)) {
|
||||
var.isInteger = true;
|
||||
var.isString = false;
|
||||
var.isLong = false;
|
||||
} else if ("int64".equals(var.dataFormat)) {
|
||||
var.isLong = true;
|
||||
var.isString = false;
|
||||
var.isInteger = false;
|
||||
} else {// C# doesn't support non-integral enums, so we need to treat everything else as strings (e.g. to not lose precision or data integrity)
|
||||
var.isString = true;
|
||||
var.isInteger = false;
|
||||
var.isLong = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> postProcessOperations(Map<String, Object> objs) {
|
||||
super.postProcessOperations(objs);
|
||||
if (objs != null) {
|
||||
Map<String, Object> operations = (Map<String, Object>) objs.get("operations");
|
||||
if (operations != null) {
|
||||
List<CodegenOperation> ops = (List<CodegenOperation>) operations.get("operation");
|
||||
for (CodegenOperation operation : ops) {
|
||||
|
||||
// Check return types for collection
|
||||
if (operation.returnType != null) {
|
||||
String typeMapping;
|
||||
int namespaceEnd = operation.returnType.lastIndexOf(".");
|
||||
if (namespaceEnd > 0) {
|
||||
typeMapping = operation.returnType.substring(namespaceEnd);
|
||||
} else {
|
||||
typeMapping = operation.returnType;
|
||||
}
|
||||
|
||||
if (this.collectionTypes.contains(typeMapping)) {
|
||||
operation.isListContainer = true;
|
||||
operation.returnContainer = operation.returnType;
|
||||
if (this.returnICollection && (
|
||||
typeMapping.startsWith("List") ||
|
||||
typeMapping.startsWith("Collection"))) {
|
||||
// NOTE: ICollection works for both List<T> and Collection<T>
|
||||
int genericStart = typeMapping.indexOf("<");
|
||||
if (genericStart > 0) {
|
||||
operation.returnType = "ICollection" + typeMapping.substring(genericStart);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
operation.returnContainer = operation.returnType;
|
||||
operation.isMapContainer = this.mapTypes.contains(typeMapping);
|
||||
}
|
||||
}
|
||||
|
||||
if (operation.examples != null){
|
||||
for (Map<String, String> example : operation.examples)
|
||||
{
|
||||
for (Map.Entry<String, String> entry : example.entrySet())
|
||||
{
|
||||
// Replace " with \", \r, \n with \\r, \\n
|
||||
String val = entry.getValue().replace("\"", "\\\"")
|
||||
.replace("\r","\\r")
|
||||
.replace("\n","\\n");
|
||||
entry.setValue(val);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
processOperation(operation);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return objs;
|
||||
}
|
||||
|
||||
protected void processOperation(CodegenOperation operation) {
|
||||
// default noop
|
||||
}
|
||||
|
||||
@Override
|
||||
public String apiFileFolder() {
|
||||
return outputFolder + File.separator + sourceFolder + File.separator + packageName + File.separator + apiPackage();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String modelFileFolder() {
|
||||
return outputFolder + File.separator + sourceFolder + File.separator + packageName + File.separator + modelPackage();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toModelFilename(String name) {
|
||||
// should be the same as the model name
|
||||
return toModelName(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toOperationId(String operationId) {
|
||||
// throw exception if method name is empty (should not occur as an auto-generated method name will be used)
|
||||
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)) {
|
||||
LOGGER.warn(operationId + " (reserved word) cannot be used as method name. Renamed to " + camelize(sanitizeName("call_" + operationId)));
|
||||
operationId = "call_" + operationId;
|
||||
}
|
||||
|
||||
return camelize(sanitizeName(operationId));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toVarName(String name) {
|
||||
// sanitize name
|
||||
name = sanitizeName(name);
|
||||
|
||||
// if it's all uppper case, do nothing
|
||||
if (name.matches("^[A-Z_]*$")) {
|
||||
return name;
|
||||
}
|
||||
|
||||
// camelize the variable name
|
||||
// pet_id => PetId
|
||||
name = camelize(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) {
|
||||
// sanitize name
|
||||
name = sanitizeName(name);
|
||||
|
||||
// replace - with _ e.g. created-at => created_at
|
||||
name = name.replaceAll("-", "_");
|
||||
|
||||
// if it's all uppper case, do nothing
|
||||
if (name.matches("^[A-Z_]*$")) {
|
||||
return name;
|
||||
}
|
||||
|
||||
// camelize(lower) the variable name
|
||||
// pet_id => petId
|
||||
name = camelize(name, true);
|
||||
|
||||
// for reserved word or word starting with number, append _
|
||||
if (isReservedWord(name) || name.matches("^\\d.*")) {
|
||||
name = escapeReservedWord(name);
|
||||
}
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String escapeReservedWord(String name) {
|
||||
if(this.reservedWordsMappings().containsKey(name)) {
|
||||
return this.reservedWordsMappings().get(name);
|
||||
}
|
||||
return "_" + name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the example value of the property
|
||||
*
|
||||
* @param p Swagger property object
|
||||
* @return string presentation of the example value of the property
|
||||
*/
|
||||
@Override
|
||||
public String toExampleValue(Schema p) {
|
||||
if (p instanceof StringSchema) {
|
||||
StringSchema dp = (StringSchema) p;
|
||||
if (dp.getExample() != null) {
|
||||
return "\"" + dp.getExample().toString() + "\"";
|
||||
}
|
||||
} else if (p instanceof BooleanSchema) {
|
||||
BooleanSchema dp = (BooleanSchema) p;
|
||||
if (dp.getExample() != null) {
|
||||
return dp.getExample().toString();
|
||||
}
|
||||
} else if (p instanceof DateSchema) {
|
||||
// TODO
|
||||
} else if (p instanceof DateTimeSchema) {
|
||||
// TODO
|
||||
} else if (p instanceof NumberSchema) {
|
||||
NumberSchema dp = (NumberSchema) p;
|
||||
if (dp.getExample() != null) {
|
||||
return dp.getExample().toString();
|
||||
}
|
||||
} else if (p instanceof IntegerSchema) {
|
||||
IntegerSchema dp = (IntegerSchema) p;
|
||||
if (dp.getExample() != null) {
|
||||
return dp.getExample().toString();
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the default value of the property
|
||||
*
|
||||
* @param p Swagger property object
|
||||
* @return string presentation of the default value of the property
|
||||
*/
|
||||
@Override
|
||||
public String toDefaultValue(Schema p) {
|
||||
if (p instanceof StringSchema) {
|
||||
StringSchema dp = (StringSchema) p;
|
||||
if (dp.getDefault() != null) {
|
||||
String _default = dp.getDefault();
|
||||
if (dp.getEnum() == null) {
|
||||
return "\"" + _default + "\"";
|
||||
} else {
|
||||
// convert to enum var name later in postProcessModels
|
||||
return _default;
|
||||
}
|
||||
}
|
||||
} else if (p instanceof BooleanSchema) {
|
||||
BooleanSchema dp = (BooleanSchema) p;
|
||||
if (dp.getDefault() != null) {
|
||||
return dp.getDefault().toString();
|
||||
}
|
||||
} else if (p instanceof DateSchema) {
|
||||
// TODO
|
||||
} else if (p instanceof DateTimeSchema) {
|
||||
// TODO
|
||||
} else if (p instanceof NumberSchema) {
|
||||
NumberSchema dp = (NumberSchema) p;
|
||||
if (dp.getDefault() != null) {
|
||||
return dp.getDefault().toString();
|
||||
}
|
||||
} else if (p instanceof IntegerSchema) {
|
||||
IntegerSchema dp = (IntegerSchema) p;
|
||||
if (dp.getDefault() != null) {
|
||||
return dp.getDefault().toString();
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isReservedWord(String word) {
|
||||
// NOTE: This differs from super's implementation in that C# does _not_ want case insensitive matching.
|
||||
return reservedWords.contains(word);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSchemaType(Schema p) {
|
||||
String openAPIType = super.getSchemaType(p);
|
||||
String type;
|
||||
|
||||
if (openAPIType == null) {
|
||||
openAPIType = ""; // set swagger type to empty string if null
|
||||
}
|
||||
|
||||
// NOTE: typeMapping here supports things like string/String, long/Long, datetime/DateTime as lowercase keys.
|
||||
// Should we require explicit casing here (values are not insensitive).
|
||||
// TODO avoid using toLowerCase as typeMapping should be case-sensitive
|
||||
if (typeMapping.containsKey(openAPIType.toLowerCase())) {
|
||||
type = typeMapping.get(openAPIType.toLowerCase());
|
||||
if (languageSpecificPrimitives.contains(type)) {
|
||||
return type;
|
||||
}
|
||||
} else {
|
||||
type = openAPIType;
|
||||
}
|
||||
return toModelName(type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides C# strongly typed declaration for simple arrays of some type and arrays of arrays of some type.
|
||||
* @param arr The input array property
|
||||
* @return The type declaration when the type is an array of arrays.
|
||||
*/
|
||||
private String getArrayTypeDeclaration(ArraySchema arr) {
|
||||
// TODO: collection type here should be fully qualified namespace to avoid model conflicts
|
||||
// This supports arrays of arrays.
|
||||
String arrayType = typeMapping.get("array");
|
||||
StringBuilder instantiationType = new StringBuilder(arrayType);
|
||||
Schema items = arr.getItems();
|
||||
String nestedType = getTypeDeclaration(items);
|
||||
// TODO: We may want to differentiate here between generics and primitive arrays.
|
||||
instantiationType.append("<").append(nestedType).append(">");
|
||||
return instantiationType.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toInstantiationType(Schema p) {
|
||||
if (p instanceof ArraySchema) {
|
||||
return getArrayTypeDeclaration((ArraySchema) p);
|
||||
}
|
||||
return super.toInstantiationType(p);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTypeDeclaration(Schema p) {
|
||||
if (p instanceof ArraySchema) {
|
||||
return getArrayTypeDeclaration((ArraySchema) p);
|
||||
} else if (p instanceof MapSchema) {
|
||||
// Should we also support maps of maps?
|
||||
MapSchema mp = (MapSchema) p;
|
||||
Schema inner = (Schema) mp.getAdditionalProperties();
|
||||
return getSchemaType(p) + "<string, " + getTypeDeclaration(inner) + ">";
|
||||
}
|
||||
return super.getTypeDeclaration(p);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toModelName(String name) {
|
||||
// We need to check if import-mapping has a different model for this class, so we use it
|
||||
// instead of the auto-generated one.
|
||||
if (importMapping.containsKey(name)) {
|
||||
return importMapping.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(name + " (reserved word) cannot be used as model name. Renamed to " + camelize("model_" + name));
|
||||
name = "model_" + name; // e.g. return => ModelReturn (after camelize)
|
||||
}
|
||||
|
||||
// model name starts with number
|
||||
if (name.matches("^\\d.*")) {
|
||||
LOGGER.warn(name + " (model name starts with number) cannot be used as model name. Renamed to " + camelize("model_" + name));
|
||||
name = "model_" + name; // e.g. 200Response => Model200Response (after camelize)
|
||||
}
|
||||
|
||||
// camelize the model name
|
||||
// phone_number => PhoneNumber
|
||||
return camelize(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String apiTestFileFolder() {
|
||||
return outputFolder + ".Test";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String modelTestFileFolder() {
|
||||
return outputFolder + ".Test";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toApiTestFilename(String name) {
|
||||
return toApiName(name) + "Tests";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toModelTestFilename(String name) {
|
||||
return toModelName(name) + "Tests";
|
||||
}
|
||||
|
||||
public void setPackageName(String packageName) {
|
||||
this.packageName = packageName;
|
||||
}
|
||||
|
||||
public void setPackageVersion(String packageVersion) {
|
||||
this.packageVersion = packageVersion;
|
||||
}
|
||||
|
||||
public void setPackageTitle(String packageTitle) {
|
||||
this.packageTitle = packageTitle;
|
||||
}
|
||||
|
||||
public void setPackageProductName(String packageProductName) {
|
||||
this.packageProductName = packageProductName;
|
||||
}
|
||||
|
||||
public void setPackageDescription(String packageDescription) {
|
||||
this.packageDescription = packageDescription;
|
||||
}
|
||||
|
||||
public void setPackageCompany(String packageCompany) {
|
||||
this.packageCompany = packageCompany;
|
||||
}
|
||||
|
||||
public void setPackageCopyright(String packageCopyright) {
|
||||
this.packageCopyright = packageCopyright;
|
||||
}
|
||||
|
||||
public void setPackageAuthors(String packageAuthors) {
|
||||
this.packageAuthors = packageAuthors;
|
||||
}
|
||||
|
||||
public void setSourceFolder(String sourceFolder) {
|
||||
this.sourceFolder = sourceFolder;
|
||||
}
|
||||
|
||||
public String getInterfacePrefix() {
|
||||
return interfacePrefix;
|
||||
}
|
||||
|
||||
public void setInterfacePrefix(final String interfacePrefix) {
|
||||
this.interfacePrefix = interfacePrefix;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toEnumValue(String value, String datatype) {
|
||||
// C# only supports enums as literals for int, int?, long, long?, byte, and byte?. All else must be treated as strings.
|
||||
// Per: https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/enum
|
||||
// The approved types for an enum are byte, sbyte, short, ushort, int, uint, long, or ulong.
|
||||
// but we're not supporting unsigned integral types or shorts.
|
||||
if(datatype.startsWith("int") || datatype.startsWith("long") || datatype.startsWith("byte")) {
|
||||
return value;
|
||||
}
|
||||
|
||||
return escapeText(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toEnumVarName(String name, String datatype) {
|
||||
if (name.length() == 0) {
|
||||
return "Empty";
|
||||
}
|
||||
|
||||
// for symbol, e.g. $, #
|
||||
if (getSymbolName(name) != null) {
|
||||
return camelize(getSymbolName(name));
|
||||
}
|
||||
|
||||
String enumName = sanitizeName(name);
|
||||
|
||||
enumName = enumName.replaceFirst("^_", "");
|
||||
enumName = enumName.replaceFirst("_$", "");
|
||||
|
||||
enumName = camelize(enumName) + "Enum";
|
||||
|
||||
if (enumName.matches("\\d.*")) { // starts with number
|
||||
return "_" + enumName;
|
||||
} else {
|
||||
return enumName;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toEnumName(CodegenProperty property) {
|
||||
return sanitizeName(camelize(property.name)) + "Enum";
|
||||
}
|
||||
|
||||
public String testPackageName() {
|
||||
return this.packageName + ".Test";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String escapeQuotationMark(String input) {
|
||||
// remove " to avoid code injection
|
||||
return input.replace("\"", "");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String escapeUnsafeCharacters(String input) {
|
||||
return input.replace("*/", "*_/").replace("/*", "/_*").replace("--", "- -");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,182 @@
|
||||
package org.openapitools.codegen.languages;
|
||||
|
||||
import org.openapitools.codegen.CodegenConfig;
|
||||
import org.openapitools.codegen.CodegenProperty;
|
||||
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 java.util.Arrays;
|
||||
|
||||
abstract public class AbstractCppCodegen extends DefaultCodegen implements CodegenConfig {
|
||||
|
||||
public AbstractCppCodegen() {
|
||||
super();
|
||||
|
||||
/*
|
||||
* Reserved words. Override this with reserved words specific to your language
|
||||
*/
|
||||
setReservedWordsLowerCase(
|
||||
Arrays.asList(
|
||||
"alignas",
|
||||
"alignof",
|
||||
"and",
|
||||
"and_eq",
|
||||
"asm",
|
||||
"auto",
|
||||
"bitand",
|
||||
"bitor",
|
||||
"bool",
|
||||
"break",
|
||||
"case",
|
||||
"catch",
|
||||
"char",
|
||||
"char16_t",
|
||||
"char32_t",
|
||||
"class",
|
||||
"compl",
|
||||
"concept",
|
||||
"const",
|
||||
"constexpr",
|
||||
"const_cast",
|
||||
"continue",
|
||||
"decltype",
|
||||
"default",
|
||||
"delete",
|
||||
"do",
|
||||
"double",
|
||||
"dynamic_cast",
|
||||
"else",
|
||||
"enum",
|
||||
"explicit",
|
||||
"export",
|
||||
"extern",
|
||||
"false",
|
||||
"float",
|
||||
"for",
|
||||
"friend",
|
||||
"goto",
|
||||
"if",
|
||||
"inline",
|
||||
"int",
|
||||
"linux",
|
||||
"long",
|
||||
"mutable",
|
||||
"namespace",
|
||||
"new",
|
||||
"noexcept",
|
||||
"not",
|
||||
"not_eq",
|
||||
"nullptr",
|
||||
"operator",
|
||||
"or",
|
||||
"or_eq",
|
||||
"private",
|
||||
"protected",
|
||||
"public",
|
||||
"register",
|
||||
"reinterpret_cast",
|
||||
"requires",
|
||||
"return",
|
||||
"short",
|
||||
"signed",
|
||||
"sizeof",
|
||||
"static",
|
||||
"static_assert",
|
||||
"static_cast",
|
||||
"struct",
|
||||
"switch",
|
||||
"template",
|
||||
"this",
|
||||
"thread_local",
|
||||
"throw",
|
||||
"true",
|
||||
"try",
|
||||
"typedef",
|
||||
"typeid",
|
||||
"typename",
|
||||
"union",
|
||||
"unsigned",
|
||||
"using",
|
||||
"virtual",
|
||||
"void",
|
||||
"volatile",
|
||||
"wchar_t",
|
||||
"while",
|
||||
"xor",
|
||||
"xor_eq")
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toVarName(String name) {
|
||||
if (typeMapping.keySet().contains(name) || typeMapping.values().contains(name)
|
||||
|| importMapping.values().contains(name) || defaultIncludes.contains(name)
|
||||
|| languageSpecificPrimitives.contains(name)) {
|
||||
return sanitizeName(name);
|
||||
}
|
||||
|
||||
if (isReservedWord(name)) {
|
||||
return escapeReservedWord(name);
|
||||
}
|
||||
|
||||
if (name.length() > 1) {
|
||||
return sanitizeName(Character.toUpperCase(name.charAt(0)) + name.substring(1));
|
||||
}
|
||||
|
||||
return sanitizeName(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Escapes a reserved word as defined in the `reservedWords` array. Handle
|
||||
* escaping those terms here. This logic is only called if a variable
|
||||
* matches the reserved words
|
||||
*
|
||||
* @return the escaped term
|
||||
*/
|
||||
@Override
|
||||
public String escapeReservedWord(String name) {
|
||||
if (this.reservedWordsMappings().containsKey(name)) {
|
||||
return this.reservedWordsMappings().get(name);
|
||||
}
|
||||
return sanitizeName("_" + name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toOperationId(String operationId) {
|
||||
if (isReservedWord(operationId)) {
|
||||
LOGGER.warn(operationId + " (reserved word) cannot be used as method name. Renamed to " + escapeReservedWord(operationId));
|
||||
return escapeReservedWord(operationId);
|
||||
}
|
||||
return sanitizeName(super.toOperationId(operationId));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toParamName(String name) {
|
||||
return sanitizeName(super.toParamName(name));
|
||||
}
|
||||
|
||||
@Override
|
||||
public CodegenProperty fromProperty(String name, Schema p) {
|
||||
CodegenProperty property = super.fromProperty(name, p);
|
||||
String nameInCamelCase = property.nameInCamelCase;
|
||||
if (nameInCamelCase.length() > 1) {
|
||||
nameInCamelCase = sanitizeName(Character.toLowerCase(nameInCamelCase.charAt(0)) + nameInCamelCase.substring(1));
|
||||
} else {
|
||||
nameInCamelCase = sanitizeName(nameInCamelCase);
|
||||
}
|
||||
property.nameInCamelCase = nameInCamelCase;
|
||||
return property;
|
||||
}
|
||||
|
||||
/**
|
||||
* Output the Getter name for boolean property, e.g. isActive
|
||||
*
|
||||
* @param name the name of the property
|
||||
* @return getter name based on naming convention
|
||||
*/
|
||||
public String toBooleanGetter(String name) {
|
||||
return "is" + getterAndSetterCapitalize(name);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,477 @@
|
||||
package org.openapitools.codegen.languages;
|
||||
|
||||
import org.openapitools.codegen.*;
|
||||
import io.swagger.v3.oas.models.OpenAPI;
|
||||
import io.swagger.v3.oas.models.Operation;
|
||||
import io.swagger.v3.oas.models.media.*;
|
||||
import io.swagger.v3.core.util.Yaml;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public abstract class AbstractGoCodegen extends DefaultCodegen implements CodegenConfig {
|
||||
|
||||
protected static Logger LOGGER = LoggerFactory.getLogger(AbstractGoCodegen.class);
|
||||
|
||||
protected boolean withXml = false;
|
||||
|
||||
protected String packageName = "swagger";
|
||||
|
||||
public AbstractGoCodegen() {
|
||||
super();
|
||||
|
||||
defaultIncludes = new HashSet<String>(
|
||||
Arrays.asList(
|
||||
"map",
|
||||
"array")
|
||||
);
|
||||
|
||||
languageSpecificPrimitives = new HashSet<String>(
|
||||
Arrays.asList(
|
||||
"string",
|
||||
"bool",
|
||||
"uint",
|
||||
"uint32",
|
||||
"uint64",
|
||||
"int",
|
||||
"int32",
|
||||
"int64",
|
||||
"float32",
|
||||
"float64",
|
||||
"complex64",
|
||||
"complex128",
|
||||
"rune",
|
||||
"byte")
|
||||
);
|
||||
|
||||
instantiationTypes.clear();
|
||||
/*instantiationTypes.put("array", "GoArray");
|
||||
instantiationTypes.put("map", "GoMap");*/
|
||||
|
||||
typeMapping.clear();
|
||||
typeMapping.put("integer", "int32");
|
||||
typeMapping.put("long", "int64");
|
||||
typeMapping.put("number", "float32");
|
||||
typeMapping.put("float", "float32");
|
||||
typeMapping.put("double", "float64");
|
||||
typeMapping.put("boolean", "bool");
|
||||
typeMapping.put("string", "string");
|
||||
typeMapping.put("UUID", "string");
|
||||
typeMapping.put("date", "string");
|
||||
typeMapping.put("DateTime", "time.Time");
|
||||
typeMapping.put("password", "string");
|
||||
typeMapping.put("File", "*os.File");
|
||||
typeMapping.put("file", "*os.File");
|
||||
// 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", "interface{}");
|
||||
typeMapping.put("UUID", "string");
|
||||
|
||||
importMapping = new HashMap<String, String>();
|
||||
importMapping.put("time.Time", "time");
|
||||
importMapping.put("*os.File", "os");
|
||||
|
||||
cliOptions.clear();
|
||||
cliOptions.add(new CliOption(CodegenConstants.PACKAGE_NAME, "Go package name (convention: lowercase).")
|
||||
.defaultValue("swagger"));
|
||||
cliOptions.add(new CliOption(CodegenConstants.HIDE_GENERATION_TIMESTAMP, "hides the timestamp when files were generated")
|
||||
.defaultValue(Boolean.TRUE.toString()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Escapes a reserved word as defined in the `reservedWords` array. Handle escaping
|
||||
* those terms here. This logic is only called if a variable matches the reserved words
|
||||
*
|
||||
* @return the escaped term
|
||||
*/
|
||||
@Override
|
||||
public String escapeReservedWord(String name)
|
||||
{
|
||||
// Can't start with an underscore, as our fields need to start with an
|
||||
// UppercaseLetter so that Go 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 toVarName(String name) {
|
||||
// replace - with _ e.g. created-at => created_at
|
||||
name = sanitizeName(name.replaceAll("-", "_"));
|
||||
|
||||
// if it's all uppper case, do nothing
|
||||
if (name.matches("^[A-Z_]*$"))
|
||||
return name;
|
||||
|
||||
// camelize (lower first character) the variable name
|
||||
// pet_id => PetId
|
||||
name = camelize(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) {
|
||||
// params should be lowerCamelCase. E.g. "person Person", instead of
|
||||
// "Person Person".
|
||||
//
|
||||
// REVISIT: Actually, for idiomatic go, the param name should
|
||||
// really should just be a letter, e.g. "p Person"), but we'll get
|
||||
// around to that some other time... Maybe.
|
||||
return camelize(toVarName(name), true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toModelName(String name) {
|
||||
// camelize the model name
|
||||
// phone_number => PhoneNumber
|
||||
return camelize(toModel(name));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toModelFilename(String name) {
|
||||
return toModel("model_" + name);
|
||||
}
|
||||
|
||||
public String toModel(String 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(name + " (reserved word) cannot be used as model name. Renamed to " + ("model_" + name));
|
||||
name = "model_" + name; // e.g. return => ModelReturn (after camelize)
|
||||
}
|
||||
|
||||
// model name starts with number
|
||||
if (name.matches("^\\d.*")) {
|
||||
LOGGER.warn(name + " (model name starts with number) cannot be used as model name. Renamed to " + ("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.go => pet_api.go
|
||||
return "api_" + underscore(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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){
|
||||
|
||||
// Give the base class a chance to process
|
||||
super.postProcessParameter(parameter);
|
||||
|
||||
char firstChar = parameter.paramName.charAt(0);
|
||||
|
||||
if (Character.isUpperCase(firstChar)) {
|
||||
// First char is already uppercase, just use paramName.
|
||||
parameter.vendorExtensions.put("x-exportParamName", parameter.paramName);
|
||||
|
||||
}
|
||||
|
||||
// It's a lowercase first char, let's convert it to uppercase
|
||||
StringBuilder sb = new StringBuilder(parameter.paramName);
|
||||
sb.setCharAt(0, Character.toUpperCase(firstChar));
|
||||
parameter.vendorExtensions.put("x-exportParamName", sb.toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTypeDeclaration(Schema p) {
|
||||
if(p instanceof ArraySchema) {
|
||||
ArraySchema ap = (ArraySchema) p;
|
||||
Schema inner = ap.getItems();
|
||||
return "[]" + 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);
|
||||
|
||||
// Not using the supertype invocation, because we want to UpperCamelize
|
||||
// the type.
|
||||
String openAPIType = getSchemaType(p);
|
||||
if (typeMapping.containsKey(openAPIType)) {
|
||||
return typeMapping.get(openAPIType);
|
||||
}
|
||||
|
||||
if(typeMapping.containsValue(openAPIType)) {
|
||||
return openAPIType;
|
||||
}
|
||||
|
||||
if(languageSpecificPrimitives.contains(openAPIType)) {
|
||||
return openAPIType;
|
||||
}
|
||||
|
||||
return toModelName(openAPIType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSchemaType(Schema p) {
|
||||
String openAPIType = super.getSchemaType(p);
|
||||
String type = null;
|
||||
if(typeMapping.containsKey(openAPIType)) {
|
||||
type = typeMapping.get(openAPIType);
|
||||
if(languageSpecificPrimitives.contains(type))
|
||||
return (type);
|
||||
}
|
||||
else
|
||||
type = openAPIType;
|
||||
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(operationId + " (reserved word) cannot be used as method name. Renamed to " + camelize("call_" + operationId));
|
||||
sanitizedOperationId = "call_" + sanitizedOperationId;
|
||||
}
|
||||
|
||||
return camelize(sanitizedOperationId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> postProcessOperations(Map<String, Object> objs) {
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, Object> objectMap = (Map<String, Object>) objs.get("operations");
|
||||
@SuppressWarnings("unchecked")
|
||||
List<CodegenOperation> operations = (List<CodegenOperation>) objectMap.get("operation");
|
||||
for (CodegenOperation operation : operations) {
|
||||
// http method verb conversion (e.g. PUT => Put)
|
||||
operation.httpMethod = camelize(operation.httpMethod.toLowerCase());
|
||||
}
|
||||
|
||||
// remove model imports to avoid error
|
||||
List<Map<String, String>> imports = (List<Map<String, String>>) objs.get("imports");
|
||||
if (imports == null)
|
||||
return objs;
|
||||
|
||||
Iterator<Map<String, String>> iterator = imports.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
String _import = iterator.next().get("import");
|
||||
if (_import.startsWith(apiPackage()))
|
||||
iterator.remove();
|
||||
}
|
||||
|
||||
// if their is a return type, import encoding/json and if needed encoding/xml
|
||||
for (CodegenOperation operation : operations) {
|
||||
if(operation.returnBaseType != null ) {
|
||||
imports.add(createMapping("import", "encoding/json"));
|
||||
if (withXml)
|
||||
imports.add(createMapping("import", "encoding/xml"));
|
||||
break; //just need to import once
|
||||
}
|
||||
}
|
||||
|
||||
// this will only import "fmt" if there are items in pathParams
|
||||
for (CodegenOperation operation : operations) {
|
||||
if(operation.pathParams != null && operation.pathParams.size() > 0) {
|
||||
imports.add(createMapping("import", "fmt"));
|
||||
break; //just need to import once
|
||||
}
|
||||
}
|
||||
|
||||
// recursively add import for mapping one type to multiple imports
|
||||
List<Map<String, String>> recursiveImports = (List<Map<String, String>>) objs.get("imports");
|
||||
if (recursiveImports == null)
|
||||
return objs;
|
||||
|
||||
ListIterator<Map<String, String>> 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 objs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> postProcessModels(Map<String, Object> objs) {
|
||||
// remove model imports to avoid error
|
||||
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();
|
||||
}
|
||||
|
||||
// recursively add import for mapping one type to multiple imports
|
||||
List<Map<String, String>> recursiveImports = (List<Map<String, String>>) objs.get("imports");
|
||||
if (recursiveImports == null)
|
||||
return objs;
|
||||
|
||||
ListIterator<Map<String, String>> 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
|
||||
public Map<String, Object> postProcessSupportingFileData(Map<String, Object> objs) {
|
||||
OpenAPI openAPI = (OpenAPI) objs.get("openapi");
|
||||
if (openAPI != null) {
|
||||
try {
|
||||
objs.put("swagger-yaml", Yaml.mapper().writeValueAsString(openAPI));
|
||||
} catch (JsonProcessingException e) {
|
||||
LOGGER.error(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
return super.postProcessSupportingFileData(objs);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean needToImport(String type) {
|
||||
return !defaultIncludes.contains(type)
|
||||
&& !languageSpecificPrimitives.contains(type);
|
||||
}
|
||||
|
||||
public void setPackageName(String packageName) {
|
||||
this.packageName = packageName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String escapeQuotationMark(String input) {
|
||||
// remove " to avoid code injection
|
||||
return input.replace("\"", "");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String escapeUnsafeCharacters(String input) {
|
||||
return input.replace("*/", "*_/").replace("/*", "/_*");
|
||||
}
|
||||
|
||||
public Map<String, String> createMapping(String key, String value){
|
||||
Map<String, String> customImport = new HashMap<String, String>();
|
||||
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();
|
||||
}
|
||||
|
||||
// string
|
||||
String enumName = sanitizeName(underscore(name).toUpperCase());
|
||||
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();
|
||||
|
||||
// remove [] for array or map of enum
|
||||
enumName = enumName.replace("[]", "");
|
||||
|
||||
if (enumName.matches("\\d.*")) { // starts with number
|
||||
return "_" + enumName;
|
||||
} else {
|
||||
return enumName;
|
||||
}
|
||||
}
|
||||
|
||||
public void setWithXml(boolean withXml) {
|
||||
this.withXml = withXml;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,534 @@
|
||||
package org.openapitools.codegen.languages;
|
||||
|
||||
import org.openapitools.codegen.CliOption;
|
||||
import org.openapitools.codegen.CodegenConfig;
|
||||
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 io.swagger.v3.oas.models.responses.ApiResponse;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
|
||||
public abstract class AbstractKotlinCodegen extends DefaultCodegen implements CodegenConfig {
|
||||
static Logger LOGGER = LoggerFactory.getLogger(AbstractKotlinCodegen.class);
|
||||
|
||||
protected String artifactId;
|
||||
protected String artifactVersion = "1.0.0";
|
||||
protected String groupId = "io.swagger";
|
||||
protected String packageName;
|
||||
|
||||
protected String sourceFolder = "src/main/kotlin";
|
||||
|
||||
protected String apiDocPath = "docs/";
|
||||
protected String modelDocPath = "docs/";
|
||||
|
||||
protected CodegenConstants.ENUM_PROPERTY_NAMING_TYPE enumPropertyNaming = CodegenConstants.ENUM_PROPERTY_NAMING_TYPE.camelCase;
|
||||
|
||||
public AbstractKotlinCodegen() {
|
||||
super();
|
||||
supportsInheritance = true;
|
||||
|
||||
languageSpecificPrimitives = new HashSet<String>(Arrays.asList(
|
||||
"kotlin.Byte",
|
||||
"kotlin.Short",
|
||||
"kotlin.Int",
|
||||
"kotlin.Long",
|
||||
"kotlin.Float",
|
||||
"kotlin.Double",
|
||||
"kotlin.Boolean",
|
||||
"kotlin.Char",
|
||||
"kotlin.String",
|
||||
"kotlin.Array",
|
||||
"kotlin.collections.List",
|
||||
"kotlin.collections.Map",
|
||||
"kotlin.collections.Set"
|
||||
));
|
||||
|
||||
// this includes hard reserved words defined by https://github.com/JetBrains/kotlin/blob/master/core/descriptors/src/org/jetbrains/kotlin/renderer/KeywordStringsGenerated.java
|
||||
// as well as keywords from https://kotlinlang.org/docs/reference/keyword-reference.html
|
||||
reservedWords = new HashSet<String>(Arrays.asList(
|
||||
"abstract",
|
||||
"annotation",
|
||||
"as",
|
||||
"break",
|
||||
"case",
|
||||
"catch",
|
||||
"class",
|
||||
"companion",
|
||||
"const",
|
||||
"constructor",
|
||||
"continue",
|
||||
"crossinline",
|
||||
"data",
|
||||
"delegate",
|
||||
"do",
|
||||
"else",
|
||||
"enum",
|
||||
"external",
|
||||
"false",
|
||||
"final",
|
||||
"finally",
|
||||
"for",
|
||||
"fun",
|
||||
"if",
|
||||
"in",
|
||||
"infix",
|
||||
"init",
|
||||
"inline",
|
||||
"inner",
|
||||
"interface",
|
||||
"internal",
|
||||
"is",
|
||||
"it",
|
||||
"lateinit",
|
||||
"lazy",
|
||||
"noinline",
|
||||
"null",
|
||||
"object",
|
||||
"open",
|
||||
"operator",
|
||||
"out",
|
||||
"override",
|
||||
"package",
|
||||
"private",
|
||||
"protected",
|
||||
"public",
|
||||
"reified",
|
||||
"return",
|
||||
"sealed",
|
||||
"super",
|
||||
"suspend",
|
||||
"tailrec",
|
||||
"this",
|
||||
"throw",
|
||||
"true",
|
||||
"try",
|
||||
"typealias",
|
||||
"typeof",
|
||||
"val",
|
||||
"var",
|
||||
"vararg",
|
||||
"when",
|
||||
"while"
|
||||
));
|
||||
|
||||
defaultIncludes = new HashSet<String>(Arrays.asList(
|
||||
"kotlin.Byte",
|
||||
"kotlin.Short",
|
||||
"kotlin.Int",
|
||||
"kotlin.Long",
|
||||
"kotlin.Float",
|
||||
"kotlin.Double",
|
||||
"kotlin.Boolean",
|
||||
"kotlin.Char",
|
||||
"kotlin.Array",
|
||||
"kotlin.collections.List",
|
||||
"kotlin.collections.Set",
|
||||
"kotlin.collections.Map"
|
||||
));
|
||||
|
||||
typeMapping = new HashMap<String, String>();
|
||||
typeMapping.put("string", "kotlin.String");
|
||||
typeMapping.put("boolean", "kotlin.Boolean");
|
||||
typeMapping.put("integer", "kotlin.Int");
|
||||
typeMapping.put("float", "kotlin.Float");
|
||||
typeMapping.put("long", "kotlin.Long");
|
||||
typeMapping.put("double", "kotlin.Double");
|
||||
typeMapping.put("number", "java.math.BigDecimal");
|
||||
typeMapping.put("date-time", "java.time.LocalDateTime");
|
||||
typeMapping.put("date", "java.time.LocalDateTime");
|
||||
typeMapping.put("file", "java.io.File");
|
||||
typeMapping.put("array", "kotlin.Array");
|
||||
typeMapping.put("list", "kotlin.Array");
|
||||
typeMapping.put("map", "kotlin.collections.Map");
|
||||
typeMapping.put("object", "kotlin.Any");
|
||||
typeMapping.put("binary", "kotlin.Array<kotlin.Byte>");
|
||||
typeMapping.put("Date", "java.time.LocalDateTime");
|
||||
typeMapping.put("DateTime", "java.time.LocalDateTime");
|
||||
|
||||
instantiationTypes.put("array", "arrayOf");
|
||||
instantiationTypes.put("list", "arrayOf");
|
||||
instantiationTypes.put("map", "mapOf");
|
||||
|
||||
importMapping = new HashMap<String, String>();
|
||||
importMapping.put("BigDecimal", "java.math.BigDecimal");
|
||||
importMapping.put("UUID", "java.util.UUID");
|
||||
importMapping.put("File", "java.io.File");
|
||||
importMapping.put("Date", "java.util.Date");
|
||||
importMapping.put("Timestamp", "java.sql.Timestamp");
|
||||
importMapping.put("DateTime", "java.time.LocalDateTime");
|
||||
importMapping.put("LocalDateTime", "java.time.LocalDateTime");
|
||||
importMapping.put("LocalDate", "java.time.LocalDate");
|
||||
importMapping.put("LocalTime", "java.time.LocalTime");
|
||||
|
||||
specialCharReplacements.put(";", "Semicolon");
|
||||
|
||||
cliOptions.clear();
|
||||
addOption(CodegenConstants.SOURCE_FOLDER, CodegenConstants.SOURCE_FOLDER_DESC, sourceFolder);
|
||||
addOption(CodegenConstants.PACKAGE_NAME, "Generated artifact package name (e.g. io.swagger).", packageName);
|
||||
addOption(CodegenConstants.GROUP_ID, "Generated artifact package's organization (i.e. maven groupId).", groupId);
|
||||
addOption(CodegenConstants.ARTIFACT_ID, "Generated artifact id (name of jar).", artifactId);
|
||||
addOption(CodegenConstants.ARTIFACT_VERSION, "Generated artifact's package version.", artifactVersion);
|
||||
|
||||
CliOption enumPropertyNamingOpt = new CliOption(CodegenConstants.ENUM_PROPERTY_NAMING, CodegenConstants.ENUM_PROPERTY_NAMING_DESC);
|
||||
cliOptions.add(enumPropertyNamingOpt.defaultValue(enumPropertyNaming.name()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String apiDocFileFolder() {
|
||||
return (outputFolder + "/" + apiDocPath).replace('/', File.separatorChar);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String apiFileFolder() {
|
||||
return outputFolder + File.separator + sourceFolder + File.separator + apiPackage().replace('.', File.separatorChar);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String escapeQuotationMark(String input) {
|
||||
// remove " to avoid code injection
|
||||
return input.replace("\"", "");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String escapeReservedWord(String name) {
|
||||
// TODO: Allow enum escaping as an option (e.g. backticks vs append/prepend underscore vs match model property escaping).
|
||||
return String.format("`%s`", name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String escapeUnsafeCharacters(String input) {
|
||||
return input.replace("*/", "*_/").replace("/*", "/_*");
|
||||
}
|
||||
|
||||
public CodegenConstants.ENUM_PROPERTY_NAMING_TYPE getEnumPropertyNaming() {
|
||||
return this.enumPropertyNaming;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the naming convention for Kotlin enum properties
|
||||
*
|
||||
* @param enumPropertyNamingType The string representation of the naming convention, as defined by {@link CodegenConstants.ENUM_PROPERTY_NAMING_TYPE}
|
||||
*/
|
||||
public void setEnumPropertyNaming(final String enumPropertyNamingType) {
|
||||
try {
|
||||
this.enumPropertyNaming = CodegenConstants.ENUM_PROPERTY_NAMING_TYPE.valueOf(enumPropertyNamingType);
|
||||
} catch (IllegalArgumentException ex) {
|
||||
StringBuilder sb = new StringBuilder(enumPropertyNamingType + " is an invalid enum property naming option. Please choose from:");
|
||||
for (CodegenConstants.ENUM_PROPERTY_NAMING_TYPE t : CodegenConstants.ENUM_PROPERTY_NAMING_TYPE.values()) {
|
||||
sb.append("\n ").append(t.name());
|
||||
}
|
||||
throw new RuntimeException(sb.toString());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* returns the swagger type for the property
|
||||
*
|
||||
* @param p Swagger property object
|
||||
* @return string presentation of the type
|
||||
**/
|
||||
@Override
|
||||
public String getSchemaType(Schema p) {
|
||||
String openAPIType = super.getSchemaType(p);
|
||||
String type;
|
||||
// This maps, for example, long -> kotlin.Long based on hashes in this type's constructor
|
||||
if (typeMapping.containsKey(openAPIType)) {
|
||||
type = typeMapping.get(openAPIType);
|
||||
if (languageSpecificPrimitives.contains(type)) {
|
||||
return toModelName(type);
|
||||
}
|
||||
} else {
|
||||
type = openAPIType;
|
||||
}
|
||||
return toModelName(type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Output the type declaration of the property
|
||||
*
|
||||
* @param p Swagger Property object
|
||||
* @return a string presentation of the property type
|
||||
*/
|
||||
@Override
|
||||
public String getTypeDeclaration(Schema p) {
|
||||
if (p instanceof ArraySchema) {
|
||||
return getArrayTypeDeclaration((ArraySchema) p);
|
||||
} else if (p instanceof MapSchema) {
|
||||
MapSchema mp = (MapSchema) p;
|
||||
Schema inner = (Schema) mp.getAdditionalProperties();
|
||||
|
||||
// Maps will be keyed only by primitive Kotlin string
|
||||
return getSchemaType(p) + "<kotlin.String, " + getTypeDeclaration(inner) + ">";
|
||||
}
|
||||
return super.getTypeDeclaration(p);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String modelDocFileFolder() {
|
||||
return (outputFolder + "/" + modelDocPath).replace('/', File.separatorChar);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String modelFileFolder() {
|
||||
return outputFolder + File.separator + sourceFolder + File.separator + modelPackage().replace('.', File.separatorChar);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> postProcessModels(Map<String, Object> objs) {
|
||||
return postProcessModelsEnum(super.postProcessModels(objs));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processOpts() {
|
||||
super.processOpts();
|
||||
|
||||
if (additionalProperties.containsKey(CodegenConstants.ENUM_PROPERTY_NAMING)) {
|
||||
setEnumPropertyNaming((String) additionalProperties.get(CodegenConstants.ENUM_PROPERTY_NAMING));
|
||||
}
|
||||
|
||||
if (additionalProperties.containsKey(CodegenConstants.SOURCE_FOLDER)) {
|
||||
this.setSourceFolder((String) additionalProperties.get(CodegenConstants.SOURCE_FOLDER));
|
||||
} else {
|
||||
additionalProperties.put(CodegenConstants.SOURCE_FOLDER, sourceFolder);
|
||||
}
|
||||
|
||||
if (additionalProperties.containsKey(CodegenConstants.PACKAGE_NAME)) {
|
||||
this.setPackageName((String) additionalProperties.get(CodegenConstants.PACKAGE_NAME));
|
||||
if (!additionalProperties.containsKey(CodegenConstants.MODEL_PACKAGE))
|
||||
this.setModelPackage(packageName + ".models");
|
||||
if (!additionalProperties.containsKey(CodegenConstants.API_PACKAGE))
|
||||
this.setApiPackage(packageName + ".apis");
|
||||
} else {
|
||||
additionalProperties.put(CodegenConstants.PACKAGE_NAME, packageName);
|
||||
}
|
||||
|
||||
if (additionalProperties.containsKey(CodegenConstants.ARTIFACT_ID)) {
|
||||
this.setArtifactId((String) additionalProperties.get(CodegenConstants.ARTIFACT_ID));
|
||||
} else {
|
||||
additionalProperties.put(CodegenConstants.ARTIFACT_ID, artifactId);
|
||||
}
|
||||
|
||||
if (additionalProperties.containsKey(CodegenConstants.GROUP_ID)) {
|
||||
this.setGroupId((String) additionalProperties.get(CodegenConstants.GROUP_ID));
|
||||
} else {
|
||||
additionalProperties.put(CodegenConstants.GROUP_ID, groupId);
|
||||
}
|
||||
|
||||
if (additionalProperties.containsKey(CodegenConstants.ARTIFACT_VERSION)) {
|
||||
this.setArtifactVersion((String) additionalProperties.get(CodegenConstants.ARTIFACT_VERSION));
|
||||
} else {
|
||||
additionalProperties.put(CodegenConstants.ARTIFACT_VERSION, artifactVersion);
|
||||
}
|
||||
|
||||
if (additionalProperties.containsKey(CodegenConstants.INVOKER_PACKAGE)) {
|
||||
LOGGER.warn(CodegenConstants.INVOKER_PACKAGE + " with " + this.getName() + " generator is ignored. Use " + CodegenConstants.PACKAGE_NAME + ".");
|
||||
}
|
||||
|
||||
additionalProperties.put(CodegenConstants.API_PACKAGE, apiPackage());
|
||||
additionalProperties.put(CodegenConstants.MODEL_PACKAGE, modelPackage());
|
||||
|
||||
additionalProperties.put("apiDocPath", apiDocPath);
|
||||
additionalProperties.put("modelDocPath", modelDocPath);
|
||||
}
|
||||
|
||||
public void setArtifactId(String artifactId) {
|
||||
this.artifactId = artifactId;
|
||||
}
|
||||
|
||||
public void setArtifactVersion(String artifactVersion) {
|
||||
this.artifactVersion = artifactVersion;
|
||||
}
|
||||
|
||||
public void setGroupId(String groupId) {
|
||||
this.groupId = groupId;
|
||||
}
|
||||
|
||||
public void setPackageName(String packageName) {
|
||||
this.packageName = packageName;
|
||||
}
|
||||
|
||||
public void setSourceFolder(String sourceFolder) {
|
||||
this.sourceFolder = sourceFolder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the sanitized variable name for enum
|
||||
*
|
||||
* @param value enum variable name
|
||||
* @param datatype data type
|
||||
* @return the sanitized variable name for enum
|
||||
*/
|
||||
@Override
|
||||
public String toEnumVarName(String value, String datatype) {
|
||||
String modified;
|
||||
if (value.length() == 0) {
|
||||
modified = "EMPTY";
|
||||
} else {
|
||||
modified = value;
|
||||
modified = sanitizeKotlinSpecificNames(modified);
|
||||
}
|
||||
|
||||
switch (getEnumPropertyNaming()) {
|
||||
case original:
|
||||
// NOTE: This is provided as a last-case allowance, but will still result in reserved words being escaped.
|
||||
modified = value;
|
||||
break;
|
||||
case camelCase:
|
||||
// NOTE: Removes hyphens and underscores
|
||||
modified = camelize(modified, true);
|
||||
break;
|
||||
case PascalCase:
|
||||
// NOTE: Removes hyphens and underscores
|
||||
String result = camelize(modified);
|
||||
modified = titleCase(result);
|
||||
break;
|
||||
case snake_case:
|
||||
// NOTE: Removes hyphens
|
||||
modified = underscore(modified);
|
||||
break;
|
||||
case UPPERCASE:
|
||||
modified = modified.toUpperCase();
|
||||
break;
|
||||
}
|
||||
|
||||
if (reservedWords.contains(modified)) {
|
||||
return escapeReservedWord(modified);
|
||||
}
|
||||
|
||||
return modified;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toInstantiationType(Schema p) {
|
||||
if (p instanceof ArraySchema) {
|
||||
return getArrayTypeDeclaration((ArraySchema) p);
|
||||
}
|
||||
return super.toInstantiationType(p);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the fully-qualified "Model" name for import
|
||||
*
|
||||
* @param name the name of the "Model"
|
||||
* @return the fully-qualified "Model" name for import
|
||||
*/
|
||||
@Override
|
||||
public String toModelImport(String name) {
|
||||
// toModelImport is called while processing operations, but DefaultCodegen doesn't
|
||||
// define imports correctly with fully qualified primitives and models as defined in this generator.
|
||||
if (needToImport(name)) {
|
||||
return super.toModelImport(name);
|
||||
}
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Output the proper model name (capitalized).
|
||||
* In case the name belongs to the TypeSystem it won't be renamed.
|
||||
*
|
||||
* @param name the name of the model
|
||||
* @return capitalized model name
|
||||
*/
|
||||
@Override
|
||||
public String toModelName(final String name) {
|
||||
// Allow for explicitly configured kotlin.* and java.* types
|
||||
if (name.startsWith("kotlin.") || name.startsWith("java.")) {
|
||||
return name;
|
||||
}
|
||||
|
||||
// If importMapping contains name, assume this is a legitimate model name.
|
||||
if (importMapping.containsKey(name)) {
|
||||
return importMapping.get(name);
|
||||
}
|
||||
|
||||
String modifiedName = name.replaceAll("\\.", "");
|
||||
modifiedName = sanitizeKotlinSpecificNames(modifiedName);
|
||||
|
||||
if (reservedWords.contains(modifiedName)) {
|
||||
modifiedName = escapeReservedWord(modifiedName);
|
||||
}
|
||||
|
||||
return titleCase(modifiedName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides a strongly typed declaration for simple arrays of some type and arrays of arrays of some type.
|
||||
*
|
||||
* @param arr Array schema
|
||||
* @return type declaration of array
|
||||
*/
|
||||
private String getArrayTypeDeclaration(ArraySchema arr) {
|
||||
// TODO: collection type here should be fully qualified namespace to avoid model conflicts
|
||||
// This supports arrays of arrays.
|
||||
String arrayType = typeMapping.get("array");
|
||||
StringBuilder instantiationType = new StringBuilder(arrayType);
|
||||
Schema items = arr.getItems();
|
||||
String nestedType = getTypeDeclaration(items);
|
||||
// TODO: We may want to differentiate here between generics and primitive arrays.
|
||||
instantiationType.append("<").append(nestedType).append(">");
|
||||
return instantiationType.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sanitize against Kotlin specific naming conventions, which may differ from those required by {@link DefaultCodegen#sanitizeName}.
|
||||
*
|
||||
* @param name string to be sanitize
|
||||
* @return sanitized string
|
||||
*/
|
||||
private String sanitizeKotlinSpecificNames(final String name) {
|
||||
String word = name;
|
||||
for (Map.Entry<String, String> specialCharacters : specialCharReplacements.entrySet()) {
|
||||
// Underscore is the only special character we'll allow
|
||||
if (!specialCharacters.getKey().equals("_")) {
|
||||
word = word.replaceAll("\\Q" + specialCharacters.getKey() + "\\E", specialCharacters.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback, replace unknowns with underscore.
|
||||
word = word.replaceAll("\\W+", "_");
|
||||
if (word.matches("\\d.*")) {
|
||||
word = "_" + word;
|
||||
}
|
||||
|
||||
// _, __, and ___ are reserved in Kotlin. Treat all names with only underscores consistently, regardless of count.
|
||||
if (word.matches("^_*$")) {
|
||||
word = word.replaceAll("\\Q_\\E", "Underscore");
|
||||
}
|
||||
|
||||
return word;
|
||||
}
|
||||
|
||||
private String titleCase(final String input) {
|
||||
return input.substring(0, 1).toUpperCase() + input.substring(1);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isReservedWord(String word) {
|
||||
// We want case-sensitive escaping, to avoid unnecessary backtick-escaping.
|
||||
return reservedWords.contains(word);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the type to see if it needs import the library/module/package
|
||||
*
|
||||
* @param type name of the type
|
||||
* @return true if the library/module/package of the corresponding type needs to be imported
|
||||
*/
|
||||
@Override
|
||||
protected boolean needToImport(String type) {
|
||||
// provides extra protection against improperly trying to import language primitives and java types
|
||||
boolean imports = !type.startsWith("kotlin.") && !type.startsWith("java.") && !defaultIncludes.contains(type) && !languageSpecificPrimitives.contains(type);
|
||||
return imports;
|
||||
}
|
||||
}
|
||||
@@ -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,553 @@
|
||||
package org.openapitools.codegen.languages;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.*;
|
||||
|
||||
import org.openapitools.codegen.CliOption;
|
||||
import org.openapitools.codegen.CodegenConfig;
|
||||
import org.openapitools.codegen.CodegenConstants;
|
||||
import org.openapitools.codegen.CodegenModel;
|
||||
import org.openapitools.codegen.CodegenProperty;
|
||||
import org.openapitools.codegen.CodegenType;
|
||||
import org.openapitools.codegen.DefaultCodegen;
|
||||
import io.swagger.v3.oas.models.media.*;
|
||||
import io.swagger.v3.oas.models.PathItem;
|
||||
import io.swagger.v3.oas.models.PathItem.HttpMethod;
|
||||
import io.swagger.v3.oas.models.*;
|
||||
import io.swagger.v3.oas.models.parameters.*;
|
||||
import io.swagger.v3.oas.models.info.*;
|
||||
import io.swagger.v3.parser.util.SchemaTypeUtil;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
public abstract class AbstractTypeScriptClientCodegen extends DefaultCodegen implements CodegenConfig {
|
||||
private static final String X_DISCRIMINATOR_TYPE = "x-discriminator-value";
|
||||
private static final String UNDEFINED_VALUE = "undefined";
|
||||
|
||||
protected String modelPropertyNaming = "camelCase";
|
||||
protected Boolean supportsES6 = true;
|
||||
protected HashSet<String> languageGenericTypes;
|
||||
|
||||
public AbstractTypeScriptClientCodegen() {
|
||||
super();
|
||||
|
||||
// clear import mapping (from default generator) as TS does not use it
|
||||
// at the moment
|
||||
importMapping.clear();
|
||||
|
||||
supportsInheritance = true;
|
||||
setReservedWordsLowerCase(Arrays.asList(
|
||||
// local variable names used in API methods (endpoints)
|
||||
"varLocalPath", "queryParameters", "headerParams", "formParams", "useFormData", "varLocalDeferred",
|
||||
"requestOptions",
|
||||
// Typescript reserved words
|
||||
"abstract", "await", "boolean", "break", "byte", "case", "catch", "char", "class", "const", "continue", "debugger", "default", "delete", "do", "double", "else", "enum", "export", "extends", "false", "final", "finally", "float", "for", "function", "goto", "if", "implements", "import", "in", "instanceof", "int", "interface", "let", "long", "native", "new", "null", "package", "private", "protected", "public", "return", "short", "static", "super", "switch", "synchronized", "this", "throw", "transient", "true", "try", "typeof", "var", "void", "volatile", "while", "with", "yield"));
|
||||
|
||||
languageSpecificPrimitives = new HashSet<>(Arrays.asList(
|
||||
"string",
|
||||
"String",
|
||||
"boolean",
|
||||
"Boolean",
|
||||
"Double",
|
||||
"Integer",
|
||||
"Long",
|
||||
"Float",
|
||||
"Object",
|
||||
"Array",
|
||||
"Date",
|
||||
"number",
|
||||
"any",
|
||||
"File",
|
||||
"Error",
|
||||
"Map"
|
||||
));
|
||||
|
||||
languageGenericTypes = new HashSet<String>(Arrays.asList(
|
||||
"Array"
|
||||
));
|
||||
|
||||
instantiationTypes.put("array", "Array");
|
||||
|
||||
typeMapping = new HashMap<String, String>();
|
||||
typeMapping.put("Array", "Array");
|
||||
typeMapping.put("array", "Array");
|
||||
typeMapping.put("List", "Array");
|
||||
typeMapping.put("boolean", "boolean");
|
||||
typeMapping.put("string", "string");
|
||||
typeMapping.put("int", "number");
|
||||
typeMapping.put("float", "number");
|
||||
typeMapping.put("number", "number");
|
||||
typeMapping.put("long", "number");
|
||||
typeMapping.put("short", "number");
|
||||
typeMapping.put("char", "string");
|
||||
typeMapping.put("double", "number");
|
||||
typeMapping.put("object", "any");
|
||||
typeMapping.put("integer", "number");
|
||||
typeMapping.put("Map", "any");
|
||||
typeMapping.put("date", "string");
|
||||
typeMapping.put("DateTime", "Date");
|
||||
//TODO binary should be mapped to byte array
|
||||
// mapped to String as a workaround
|
||||
typeMapping.put("binary", "string");
|
||||
typeMapping.put("ByteArray", "string");
|
||||
typeMapping.put("UUID", "string");
|
||||
typeMapping.put("File", "any");
|
||||
typeMapping.put("Error", "Error");
|
||||
|
||||
cliOptions.add(new CliOption(CodegenConstants.MODEL_PROPERTY_NAMING, CodegenConstants.MODEL_PROPERTY_NAMING_DESC).defaultValue("camelCase"));
|
||||
cliOptions.add(new CliOption(CodegenConstants.SUPPORTS_ES6, CodegenConstants.SUPPORTS_ES6_DESC).defaultValue("false"));
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processOpts() {
|
||||
super.processOpts();
|
||||
|
||||
if (additionalProperties.containsKey(CodegenConstants.MODEL_PROPERTY_NAMING)) {
|
||||
setModelPropertyNaming((String) additionalProperties.get(CodegenConstants.MODEL_PROPERTY_NAMING));
|
||||
}
|
||||
|
||||
if (additionalProperties.containsKey(CodegenConstants.SUPPORTS_ES6)) {
|
||||
setSupportsES6(Boolean.valueOf(additionalProperties.get(CodegenConstants.SUPPORTS_ES6).toString()));
|
||||
additionalProperties.put("supportsES6", getSupportsES6());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public CodegenType getTag() {
|
||||
return CodegenType.CLIENT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String escapeReservedWord(String name) {
|
||||
if (this.reservedWordsMappings().containsKey(name)) {
|
||||
return this.reservedWordsMappings().get(name);
|
||||
}
|
||||
return "_" + name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String apiFileFolder() {
|
||||
return outputFolder + "/" + apiPackage().replace('.', File.separatorChar);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String modelFileFolder() {
|
||||
return outputFolder + "/" + modelPackage().replace('.', File.separatorChar);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toParamName(String name) {
|
||||
// should be the same as variable name
|
||||
return toVarName(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toVarName(String name) {
|
||||
// sanitize name
|
||||
name = sanitizeName(name);
|
||||
|
||||
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 toModelName(String name) {
|
||||
name = sanitizeName(name); // FIXME: a parameter should not be assigned. Also declare the methods parameters as 'final'.
|
||||
|
||||
if (!StringUtils.isEmpty(modelNamePrefix)) {
|
||||
name = modelNamePrefix + "_" + name;
|
||||
}
|
||||
|
||||
if (!StringUtils.isEmpty(modelNameSuffix)) {
|
||||
name = name + "_" + modelNameSuffix;
|
||||
}
|
||||
|
||||
// model name cannot use reserved keyword, e.g. return
|
||||
if (isReservedWord(name)) {
|
||||
String modelName = camelize("model_" + name);
|
||||
LOGGER.warn(name + " (reserved word) cannot be used as model name. Renamed to " + modelName);
|
||||
return modelName;
|
||||
}
|
||||
|
||||
// model name starts with number
|
||||
if (name.matches("^\\d.*")) {
|
||||
String modelName = camelize("model_" + name); // 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;
|
||||
}
|
||||
|
||||
if (languageSpecificPrimitives.contains(name)) {
|
||||
String modelName = camelize("model_" + name);
|
||||
LOGGER.warn(name + " (model name matches existing language type) cannot be used as a model name. Renamed to " + modelName);
|
||||
return modelName;
|
||||
}
|
||||
|
||||
// camelize the model name
|
||||
// phone_number => PhoneNumber
|
||||
return camelize(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toModelFilename(String name) {
|
||||
// should be the same as the model name
|
||||
return toModelName(name);
|
||||
}
|
||||
|
||||
@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 "{ [key: string]: " + getTypeDeclaration(inner) + "; }";
|
||||
} else if (p instanceof FileSchema) {
|
||||
return "any";
|
||||
} else if (p instanceof StringSchema && SchemaTypeUtil.BINARY_FORMAT.equals(p.getFormat())) {
|
||||
return "any";
|
||||
}
|
||||
return super.getTypeDeclaration(p);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected String getParameterDataType(Parameter parameter, Schema p) {
|
||||
// handle enums of various data types
|
||||
Schema inner;
|
||||
if (p instanceof ArraySchema) {
|
||||
ArraySchema mp1 = (ArraySchema) p;
|
||||
inner = mp1.getItems();
|
||||
return this.getSchemaType(p) + "<" + this.getParameterDataType(parameter, inner) + ">";
|
||||
} else if (p instanceof MapSchema) {
|
||||
MapSchema mp = (MapSchema) p;
|
||||
inner = (Schema) mp.getAdditionalProperties();
|
||||
return "{ [key: string]: " + this.getParameterDataType(parameter, inner) + "; }";
|
||||
} else if (p instanceof StringSchema) {
|
||||
// Handle string enums
|
||||
StringSchema sp = (StringSchema) p;
|
||||
if (sp.getEnum() != null) {
|
||||
return enumValuesToEnumTypeUnion(sp.getEnum(), "string");
|
||||
}
|
||||
} else if (p instanceof IntegerSchema) {
|
||||
// Handle integer enums
|
||||
IntegerSchema sp = (IntegerSchema) p;
|
||||
if (sp.getEnum() != null) {
|
||||
return numericEnumValuesToEnumTypeUnion(new ArrayList<Number>(sp.getEnum()));
|
||||
}
|
||||
} else if (p instanceof NumberSchema) {
|
||||
// Handle double enums
|
||||
NumberSchema sp = (NumberSchema) p;
|
||||
if (sp.getEnum() != null) {
|
||||
return numericEnumValuesToEnumTypeUnion(new ArrayList<Number>(sp.getEnum()));
|
||||
}
|
||||
}
|
||||
/* TODO revise the logic below
|
||||
else if (p instanceof DateSchema) {
|
||||
// Handle date enums
|
||||
DateSchema sp = (DateSchema) p;
|
||||
if (sp.getEnum() != null) {
|
||||
return enumValuesToEnumTypeUnion(sp.getEnum(), "string");
|
||||
}
|
||||
} else if (p instanceof DateTimeSchema) {
|
||||
// Handle datetime enums
|
||||
DateTimeSchema sp = (DateTimeSchema) p;
|
||||
if (sp.getEnum() != null) {
|
||||
return enumValuesToEnumTypeUnion(sp.getEnum(), "string");
|
||||
}
|
||||
}*/
|
||||
return this.getTypeDeclaration(p);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a list of strings to a literal union for representing enum values as a type.
|
||||
* Example output: 'available' | 'pending' | 'sold'
|
||||
*
|
||||
* @param values list of allowed enum values
|
||||
* @param dataType either "string" or "number"
|
||||
* @return
|
||||
*/
|
||||
protected String enumValuesToEnumTypeUnion(List<String> values, String dataType) {
|
||||
StringBuilder b = new StringBuilder();
|
||||
boolean isFirst = true;
|
||||
for (String value : values) {
|
||||
if (!isFirst) {
|
||||
b.append(" | ");
|
||||
}
|
||||
b.append(toEnumValue(value.toString(), dataType));
|
||||
isFirst = false;
|
||||
}
|
||||
return b.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a list of numbers to a literal union for representing enum values as a type.
|
||||
* Example output: 3 | 9 | 55
|
||||
*
|
||||
* @param values
|
||||
* @return
|
||||
*/
|
||||
protected String numericEnumValuesToEnumTypeUnion(List<Number> values) {
|
||||
List<String> stringValues = new ArrayList<>();
|
||||
for (Number value : values) {
|
||||
stringValues.add(value.toString());
|
||||
}
|
||||
return enumValuesToEnumTypeUnion(stringValues, "number");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toDefaultValue(Schema p) {
|
||||
if (p instanceof StringSchema) {
|
||||
StringSchema sp = (StringSchema) p;
|
||||
if (sp.getDefault() != null) {
|
||||
return "'" + sp.getDefault() + "'";
|
||||
}
|
||||
return UNDEFINED_VALUE;
|
||||
} else if (p instanceof BooleanSchema) {
|
||||
return UNDEFINED_VALUE;
|
||||
} else if (p instanceof DateSchema) {
|
||||
return UNDEFINED_VALUE;
|
||||
} else if (p instanceof DateTimeSchema) {
|
||||
return UNDEFINED_VALUE;
|
||||
} else if (p instanceof NumberSchema) {
|
||||
NumberSchema dp = (NumberSchema) p;
|
||||
if (dp.getDefault() != null) {
|
||||
return dp.getDefault().toString();
|
||||
}
|
||||
return UNDEFINED_VALUE;
|
||||
} else if (p instanceof IntegerSchema) {
|
||||
IntegerSchema ip = (IntegerSchema) p;
|
||||
if (ip.getDefault() != null) {
|
||||
return ip.getDefault().toString();
|
||||
}
|
||||
return UNDEFINED_VALUE;
|
||||
} else {
|
||||
return UNDEFINED_VALUE;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSchemaType(Schema p) {
|
||||
String openAPIType = super.getSchemaType(p);
|
||||
String type = null;
|
||||
if (typeMapping.containsKey(openAPIType)) {
|
||||
type = typeMapping.get(openAPIType);
|
||||
if (languageSpecificPrimitives.contains(type))
|
||||
return type;
|
||||
} else
|
||||
type = openAPIType;
|
||||
return toModelName(type);
|
||||
}
|
||||
|
||||
@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
|
||||
// append _ at the beginning, e.g. _return
|
||||
if (isReservedWord(operationId)) {
|
||||
return escapeReservedWord(camelize(sanitizeName(operationId), true));
|
||||
}
|
||||
|
||||
return camelize(sanitizeName(operationId), true);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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 String toEnumValue(String value, String datatype) {
|
||||
if ("number".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";
|
||||
}
|
||||
|
||||
// for symbol, e.g. $, #
|
||||
if (getSymbolName(name) != null) {
|
||||
return camelize(getSymbolName(name));
|
||||
}
|
||||
|
||||
// number
|
||||
if ("number".equals(datatype)) {
|
||||
String varName = "NUMBER_" + name;
|
||||
|
||||
varName = varName.replaceAll("-", "MINUS_");
|
||||
varName = varName.replaceAll("\\+", "PLUS_");
|
||||
varName = varName.replaceAll("\\.", "_DOT_");
|
||||
return varName;
|
||||
}
|
||||
|
||||
// string
|
||||
String enumName = sanitizeName(name);
|
||||
enumName = enumName.replaceFirst("^_", "");
|
||||
enumName = enumName.replaceFirst("_$", "");
|
||||
|
||||
// camelize the enum variable name
|
||||
// ref: https://basarat.gitbooks.io/typescript/content/docs/enums.html
|
||||
enumName = camelize(enumName);
|
||||
|
||||
if (enumName.matches("\\d.*")) { // starts with number
|
||||
return "_" + enumName;
|
||||
} else {
|
||||
return enumName;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toEnumName(CodegenProperty property) {
|
||||
String enumName = toModelName(property.name) + "Enum";
|
||||
|
||||
if (enumName.matches("\\d.*")) { // starts with number
|
||||
return "_" + enumName;
|
||||
} else {
|
||||
return enumName;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> postProcessModels(Map<String, Object> objs) {
|
||||
// process enum in models
|
||||
List<Object> models = (List<Object>) postProcessModelsEnum(objs).get("models");
|
||||
for (Object _mo : models) {
|
||||
Map<String, Object> mo = (Map<String, Object>) _mo;
|
||||
CodegenModel cm = (CodegenModel) mo.get("model");
|
||||
cm.imports = new TreeSet(cm.imports);
|
||||
// name enum with model name, e.g. StatusEnum => Pet.StatusEnum
|
||||
for (CodegenProperty var : cm.vars) {
|
||||
if (Boolean.TRUE.equals(var.isEnum)) {
|
||||
var.datatypeWithEnum = var.datatypeWithEnum.replace(var.enumName, cm.classname + "." + var.enumName);
|
||||
}
|
||||
}
|
||||
if (cm.parent != null) {
|
||||
for (CodegenProperty var : cm.allVars) {
|
||||
if (Boolean.TRUE.equals(var.isEnum)) {
|
||||
var.datatypeWithEnum = var.datatypeWithEnum
|
||||
.replace(var.enumName, cm.classname + "." + var.enumName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return objs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> postProcessAllModels(Map<String, Object> objs) {
|
||||
Map<String, Object> result = super.postProcessAllModels(objs);
|
||||
|
||||
for (Map.Entry<String, Object> entry : result.entrySet()) {
|
||||
Map<String, Object> inner = (Map<String, Object>) entry.getValue();
|
||||
List<Map<String, Object>> models = (List<Map<String, Object>>) inner.get("models");
|
||||
for (Map<String, Object> mo : models) {
|
||||
CodegenModel cm = (CodegenModel) mo.get("model");
|
||||
if (cm.discriminator != null && cm.children != null) {
|
||||
for (CodegenModel child : cm.children) {
|
||||
this.setDiscriminatorValue(child, cm.discriminator.getPropertyName(), this.getDiscriminatorValue(child));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public void setSupportsES6(Boolean value) {
|
||||
supportsES6 = value;
|
||||
}
|
||||
|
||||
public Boolean getSupportsES6() {
|
||||
return supportsES6;
|
||||
}
|
||||
|
||||
private void setDiscriminatorValue(CodegenModel model, String baseName, String value) {
|
||||
for (CodegenProperty prop : model.allVars) {
|
||||
if (prop.baseName.equals(baseName)) {
|
||||
prop.discriminatorValue = value;
|
||||
}
|
||||
}
|
||||
if (model.children != null) {
|
||||
final boolean newDiscriminator = model.discriminator != null;
|
||||
for (CodegenModel child : model.children) {
|
||||
this.setDiscriminatorValue(child, baseName, newDiscriminator ? value : this.getDiscriminatorValue(child));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private String getDiscriminatorValue(CodegenModel model) {
|
||||
return model.vendorExtensions.containsKey(X_DISCRIMINATOR_TYPE) ?
|
||||
(String) model.vendorExtensions.get(X_DISCRIMINATOR_TYPE) : model.classname;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String escapeQuotationMark(String input) {
|
||||
// remove ', " to avoid code injection
|
||||
return input.replace("\"", "").replace("'", "");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String escapeUnsafeCharacters(String input) {
|
||||
return input.replace("*/", "*_/").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("\"", "");
|
||||
}
|
||||
}
|
||||
@@ -182,17 +182,17 @@ public class AndroidClientCodegen extends DefaultCodegen implements CodegenConfi
|
||||
|
||||
@Override
|
||||
public String getSchemaType(Schema p) {
|
||||
String swaggerType = super.getSchemaType(p);
|
||||
String openAPIType = super.getSchemaType(p);
|
||||
String type = null;
|
||||
if (typeMapping.containsKey(swaggerType)) {
|
||||
type = typeMapping.get(swaggerType);
|
||||
if (typeMapping.containsKey(openAPIType)) {
|
||||
type = typeMapping.get(openAPIType);
|
||||
if (languageSpecificPrimitives.contains(type) || type.indexOf(".") >= 0 ||
|
||||
type.equals("Map") || type.equals("List") ||
|
||||
type.equals("File") || type.equals("Date")) {
|
||||
return type;
|
||||
}
|
||||
} else {
|
||||
type = swaggerType;
|
||||
type = openAPIType;
|
||||
}
|
||||
return toModelName(type);
|
||||
}
|
||||
@@ -435,86 +435,6 @@ public class AndroidClientCodegen extends DefaultCodegen implements CodegenConfi
|
||||
} else {
|
||||
throw new IllegalArgumentException("Invalid 'library' option specified: '" + getLibrary() + "'. Must be 'httpclient' or 'volley' (default)");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void addSupportingFilesForHttpClient() {
|
||||
// documentation files
|
||||
modelDocTemplateFiles.put("model_doc.mustache", ".md");
|
||||
apiDocTemplateFiles.put("api_doc.mustache", ".md");
|
||||
supportingFiles.add(new SupportingFile("README.mustache", "", "README.md"));
|
||||
|
||||
supportingFiles.add(new SupportingFile("pom.mustache", "", "pom.xml"));
|
||||
supportingFiles.add(new SupportingFile("settings.gradle.mustache", "", "settings.gradle"));
|
||||
supportingFiles.add(new SupportingFile("build.mustache", "", "build.gradle"));
|
||||
supportingFiles.add(new SupportingFile("manifest.mustache", projectFolder, "AndroidManifest.xml"));
|
||||
supportingFiles.add(new SupportingFile("apiInvoker.mustache",
|
||||
(sourceFolder + File.separator + invokerPackage).replace(".", File.separator), "ApiInvoker.java"));
|
||||
supportingFiles.add(new SupportingFile("httpPatch.mustache",
|
||||
(sourceFolder + File.separator + invokerPackage).replace(".", File.separator), "HttpPatch.java"));
|
||||
supportingFiles.add(new SupportingFile("jsonUtil.mustache",
|
||||
(sourceFolder + File.separator + invokerPackage).replace(".", File.separator), "JsonUtil.java"));
|
||||
supportingFiles.add(new SupportingFile("apiException.mustache",
|
||||
(sourceFolder + File.separator + invokerPackage).replace(".", File.separator), "ApiException.java"));
|
||||
supportingFiles.add(new SupportingFile("Pair.mustache",
|
||||
(sourceFolder + File.separator + invokerPackage).replace(".", File.separator), "Pair.java"));
|
||||
supportingFiles.add(new SupportingFile("git_push.sh.mustache", "", "git_push.sh"));
|
||||
supportingFiles.add(new SupportingFile("gitignore.mustache", "", ".gitignore"));
|
||||
|
||||
// gradle wrapper 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"));
|
||||
|
||||
}
|
||||
|
||||
private void addSupportingFilesForVolley() {
|
||||
// documentation files
|
||||
modelDocTemplateFiles.put("model_doc.mustache", ".md");
|
||||
apiDocTemplateFiles.put("api_doc.mustache", ".md");
|
||||
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("pom.mustache", "", "pom.xml"));
|
||||
// supportingFiles.add(new SupportingFile("settings.gradle.mustache", "", "settings.gradle"));
|
||||
supportingFiles.add(new SupportingFile("build.mustache", "", "build.gradle"));
|
||||
supportingFiles.add(new SupportingFile("manifest.mustache", projectFolder, "AndroidManifest.xml"));
|
||||
supportingFiles.add(new SupportingFile("apiInvoker.mustache",
|
||||
(sourceFolder + File.separator + invokerPackage).replace(".", File.separator), "ApiInvoker.java"));
|
||||
supportingFiles.add(new SupportingFile("jsonUtil.mustache",
|
||||
(sourceFolder + File.separator + invokerPackage).replace(".", File.separator), "JsonUtil.java"));
|
||||
supportingFiles.add(new SupportingFile("apiException.mustache",
|
||||
(sourceFolder + File.separator + invokerPackage).replace(".", File.separator), "ApiException.java"));
|
||||
supportingFiles.add(new SupportingFile("Pair.mustache",
|
||||
(sourceFolder + File.separator + invokerPackage).replace(".", File.separator), "Pair.java"));
|
||||
supportingFiles.add(new SupportingFile("request/getrequest.mustache",
|
||||
(sourceFolder + File.separator + requestPackage).replace(".", File.separator), "GetRequest.java"));
|
||||
supportingFiles.add(new SupportingFile("request/postrequest.mustache",
|
||||
(sourceFolder + File.separator + requestPackage).replace(".", File.separator), "PostRequest.java"));
|
||||
supportingFiles.add(new SupportingFile("request/putrequest.mustache",
|
||||
(sourceFolder + File.separator + requestPackage).replace(".", File.separator), "PutRequest.java"));
|
||||
supportingFiles.add(new SupportingFile("request/deleterequest.mustache",
|
||||
(sourceFolder + File.separator + requestPackage).replace(".", File.separator), "DeleteRequest.java"));
|
||||
supportingFiles.add(new SupportingFile("request/patchrequest.mustache",
|
||||
(sourceFolder + File.separator + requestPackage).replace(".", File.separator), "PatchRequest.java"));
|
||||
supportingFiles.add(new SupportingFile("auth/apikeyauth.mustache",
|
||||
(sourceFolder + File.separator + authPackage).replace(".", File.separator), "ApiKeyAuth.java"));
|
||||
supportingFiles.add(new SupportingFile("auth/httpbasicauth.mustache",
|
||||
(sourceFolder + File.separator + authPackage).replace(".", File.separator), "HttpBasicAuth.java"));
|
||||
supportingFiles.add(new SupportingFile("auth/authentication.mustache",
|
||||
(sourceFolder + File.separator + authPackage).replace(".", File.separator), "Authentication.java"));
|
||||
|
||||
// gradle wrapper 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"));
|
||||
}
|
||||
|
||||
public Boolean getUseAndroidMavenGradlePlugin() {
|
||||
@@ -592,4 +512,83 @@ public class AndroidClientCodegen extends DefaultCodegen implements CodegenConfi
|
||||
return input.replace("*/", "*_/").replace("/*", "/_*");
|
||||
}
|
||||
|
||||
private void addSupportingFilesForVolley() {
|
||||
// documentation files
|
||||
modelDocTemplateFiles.put("model_doc.mustache", ".md");
|
||||
apiDocTemplateFiles.put("api_doc.mustache", ".md");
|
||||
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("pom.mustache", "", "pom.xml"));
|
||||
// supportingFiles.add(new SupportingFile("settings.gradle.mustache", "", "settings.gradle"));
|
||||
supportingFiles.add(new SupportingFile("build.mustache", "", "build.gradle"));
|
||||
supportingFiles.add(new SupportingFile("manifest.mustache", projectFolder, "AndroidManifest.xml"));
|
||||
supportingFiles.add(new SupportingFile("apiInvoker.mustache",
|
||||
(sourceFolder + File.separator + invokerPackage).replace(".", File.separator), "ApiInvoker.java"));
|
||||
supportingFiles.add(new SupportingFile("jsonUtil.mustache",
|
||||
(sourceFolder + File.separator + invokerPackage).replace(".", File.separator), "JsonUtil.java"));
|
||||
supportingFiles.add(new SupportingFile("apiException.mustache",
|
||||
(sourceFolder + File.separator + invokerPackage).replace(".", File.separator), "ApiException.java"));
|
||||
supportingFiles.add(new SupportingFile("Pair.mustache",
|
||||
(sourceFolder + File.separator + invokerPackage).replace(".", File.separator), "Pair.java"));
|
||||
supportingFiles.add(new SupportingFile("request/getrequest.mustache",
|
||||
(sourceFolder + File.separator + requestPackage).replace(".", File.separator), "GetRequest.java"));
|
||||
supportingFiles.add(new SupportingFile("request/postrequest.mustache",
|
||||
(sourceFolder + File.separator + requestPackage).replace(".", File.separator), "PostRequest.java"));
|
||||
supportingFiles.add(new SupportingFile("request/putrequest.mustache",
|
||||
(sourceFolder + File.separator + requestPackage).replace(".", File.separator), "PutRequest.java"));
|
||||
supportingFiles.add(new SupportingFile("request/deleterequest.mustache",
|
||||
(sourceFolder + File.separator + requestPackage).replace(".", File.separator), "DeleteRequest.java"));
|
||||
supportingFiles.add(new SupportingFile("request/patchrequest.mustache",
|
||||
(sourceFolder + File.separator + requestPackage).replace(".", File.separator), "PatchRequest.java"));
|
||||
supportingFiles.add(new SupportingFile("auth/apikeyauth.mustache",
|
||||
(sourceFolder + File.separator + authPackage).replace(".", File.separator), "ApiKeyAuth.java"));
|
||||
supportingFiles.add(new SupportingFile("auth/httpbasicauth.mustache",
|
||||
(sourceFolder + File.separator + authPackage).replace(".", File.separator), "HttpBasicAuth.java"));
|
||||
supportingFiles.add(new SupportingFile("auth/authentication.mustache",
|
||||
(sourceFolder + File.separator + authPackage).replace(".", File.separator), "Authentication.java"));
|
||||
|
||||
// gradle wrapper 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"));
|
||||
}
|
||||
|
||||
private void addSupportingFilesForHttpClient() {
|
||||
// documentation files
|
||||
modelDocTemplateFiles.put("model_doc.mustache", ".md");
|
||||
apiDocTemplateFiles.put("api_doc.mustache", ".md");
|
||||
supportingFiles.add(new SupportingFile("README.mustache", "", "README.md"));
|
||||
|
||||
supportingFiles.add(new SupportingFile("pom.mustache", "", "pom.xml"));
|
||||
supportingFiles.add(new SupportingFile("settings.gradle.mustache", "", "settings.gradle"));
|
||||
supportingFiles.add(new SupportingFile("build.mustache", "", "build.gradle"));
|
||||
supportingFiles.add(new SupportingFile("manifest.mustache", projectFolder, "AndroidManifest.xml"));
|
||||
supportingFiles.add(new SupportingFile("apiInvoker.mustache",
|
||||
(sourceFolder + File.separator + invokerPackage).replace(".", File.separator), "ApiInvoker.java"));
|
||||
supportingFiles.add(new SupportingFile("httpPatch.mustache",
|
||||
(sourceFolder + File.separator + invokerPackage).replace(".", File.separator), "HttpPatch.java"));
|
||||
supportingFiles.add(new SupportingFile("jsonUtil.mustache",
|
||||
(sourceFolder + File.separator + invokerPackage).replace(".", File.separator), "JsonUtil.java"));
|
||||
supportingFiles.add(new SupportingFile("apiException.mustache",
|
||||
(sourceFolder + File.separator + invokerPackage).replace(".", File.separator), "ApiException.java"));
|
||||
supportingFiles.add(new SupportingFile("Pair.mustache",
|
||||
(sourceFolder + File.separator + invokerPackage).replace(".", File.separator), "Pair.java"));
|
||||
supportingFiles.add(new SupportingFile("git_push.sh.mustache", "", "git_push.sh"));
|
||||
supportingFiles.add(new SupportingFile("gitignore.mustache", "", ".gitignore"));
|
||||
|
||||
// gradle wrapper 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"));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,110 @@
|
||||
package org.openapitools.codegen.languages;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.openapitools.codegen.CliOption;
|
||||
import org.openapitools.codegen.CodegenConfig;
|
||||
import org.openapitools.codegen.CodegenConstants;
|
||||
import org.openapitools.codegen.CodegenOperation;
|
||||
import org.openapitools.codegen.CodegenType;
|
||||
import org.openapitools.codegen.DefaultCodegen;
|
||||
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.*;
|
||||
|
||||
|
||||
public class Apache2ConfigCodegen extends DefaultCodegen implements CodegenConfig {
|
||||
public static final String USER_INFO_PATH = "userInfoPath";
|
||||
protected String userInfoPath = "/var/www/html/";
|
||||
|
||||
@Override
|
||||
public CodegenType getTag() {
|
||||
return CodegenType.CONFIG;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "apache2";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHelp() {
|
||||
return "Generates an Apache2 Config file with the permissions";
|
||||
}
|
||||
|
||||
public Apache2ConfigCodegen() {
|
||||
super();
|
||||
apiTemplateFiles.put("apache-config.mustache", ".conf");
|
||||
|
||||
embeddedTemplateDir = templateDir = "apache2";
|
||||
|
||||
cliOptions.add(new CliOption(USER_INFO_PATH, "Path to the user and group files"));
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void processOpts() {
|
||||
if (additionalProperties.containsKey(USER_INFO_PATH)) {
|
||||
userInfoPath = additionalProperties.get(USER_INFO_PATH).toString();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String escapeQuotationMark(String input) {
|
||||
// remove " to avoid code injection
|
||||
return input.replace("\"", "");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String escapeUnsafeCharacters(String input) {
|
||||
return input.replace("*/", "*_/").replace("/*", "/_*");
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public Map<String, Object> postProcessOperations(Map<String, Object> objs) {
|
||||
Map<String, Object> operations = (Map<String, Object>) objs.get("operations");
|
||||
List<CodegenOperation> operationList = (List<CodegenOperation>) operations.get("operation");
|
||||
List<CodegenOperation> newOpList = new ArrayList<CodegenOperation>();
|
||||
for (CodegenOperation op : operationList) {
|
||||
String path = new String(op.path);
|
||||
|
||||
String[] items = path.split("/", -1);
|
||||
List<String> splitPath = new ArrayList<String>();
|
||||
for (String item : items) {
|
||||
if (item.matches("^\\{(.*)\\}$")) {
|
||||
item = "*";
|
||||
}
|
||||
splitPath.add(item);
|
||||
op.path += item + "/";
|
||||
}
|
||||
op.vendorExtensions.put("x-codegen-userInfoPath", userInfoPath);
|
||||
boolean foundInNewList = false;
|
||||
for (CodegenOperation op1 : newOpList) {
|
||||
if (!foundInNewList) {
|
||||
if (op1.path.equals(op.path)) {
|
||||
foundInNewList = true;
|
||||
List<CodegenOperation> currentOtherMethodList = (List<CodegenOperation>) op1.vendorExtensions.get("x-codegen-otherMethods");
|
||||
if (currentOtherMethodList == null) {
|
||||
currentOtherMethodList = new ArrayList<CodegenOperation>();
|
||||
}
|
||||
op.operationIdCamelCase = op1.operationIdCamelCase;
|
||||
currentOtherMethodList.add(op);
|
||||
op1.vendorExtensions.put("x-codegen-otherMethods", currentOtherMethodList);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!foundInNewList) {
|
||||
newOpList.add(op);
|
||||
}
|
||||
}
|
||||
operations.put("operation", newOpList);
|
||||
return objs;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,228 @@
|
||||
package org.openapitools.codegen.languages;
|
||||
|
||||
import org.openapitools.codegen.CliOption;
|
||||
import org.openapitools.codegen.CodegenConfig;
|
||||
import org.openapitools.codegen.CodegenConstants;
|
||||
import org.openapitools.codegen.CodegenOperation;
|
||||
import org.openapitools.codegen.CodegenType;
|
||||
import org.openapitools.codegen.DefaultCodegen;
|
||||
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 io.swagger.v3.oas.models.info.*;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Map;
|
||||
import java.util.List;
|
||||
|
||||
public class ClojureClientCodegen extends DefaultCodegen implements CodegenConfig {
|
||||
private static final String PROJECT_NAME = "projectName";
|
||||
private static final String PROJECT_DESCRIPTION = "projectDescription";
|
||||
private static final String PROJECT_VERSION = "projectVersion";
|
||||
private static final String PROJECT_URL = "projectUrl";
|
||||
private static final String PROJECT_LICENSE_NAME = "projectLicenseName";
|
||||
private static final String PROJECT_LICENSE_URL = "projectLicenseUrl";
|
||||
private static final String BASE_NAMESPACE = "baseNamespace";
|
||||
|
||||
protected String projectName;
|
||||
protected String projectDescription;
|
||||
protected String projectVersion;
|
||||
protected String baseNamespace;
|
||||
|
||||
protected String sourceFolder = "src";
|
||||
|
||||
public ClojureClientCodegen() {
|
||||
super();
|
||||
outputFolder = "generated-code" + File.separator + "clojure";
|
||||
apiTemplateFiles.put("api.mustache", ".clj");
|
||||
embeddedTemplateDir = templateDir = "clojure";
|
||||
|
||||
cliOptions.add(new CliOption(PROJECT_NAME,
|
||||
"name of the project (Default: generated from info.title or \"swagger-clj-client\")"));
|
||||
cliOptions.add(new CliOption(PROJECT_DESCRIPTION,
|
||||
"description of the project (Default: using info.description or \"Client library of <projectNname>\")"));
|
||||
cliOptions.add(new CliOption(PROJECT_VERSION,
|
||||
"version of the project (Default: using info.version or \"1.0.0\")"));
|
||||
cliOptions.add(new CliOption(PROJECT_URL,
|
||||
"URL of the project (Default: using info.contact.url or not included in project.clj)"));
|
||||
cliOptions.add(new CliOption(PROJECT_LICENSE_NAME,
|
||||
"name of the license the project uses (Default: using info.license.name or not included in project.clj)"));
|
||||
cliOptions.add(new CliOption(PROJECT_LICENSE_URL,
|
||||
"URL of the license the project uses (Default: using info.license.url or not included in project.clj)"));
|
||||
cliOptions.add(new CliOption(BASE_NAMESPACE,
|
||||
"the base/top namespace (Default: generated from projectName)"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public CodegenType getTag() {
|
||||
return CodegenType.CLIENT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "clojure";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHelp() {
|
||||
return "Generates a Clojure client library.";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preprocessOpenAPI(OpenAPI openAPI) {
|
||||
super.preprocessOpenAPI(openAPI);
|
||||
|
||||
if (additionalProperties.containsKey(PROJECT_NAME)) {
|
||||
projectName = ((String) additionalProperties.get(PROJECT_NAME));
|
||||
}
|
||||
if (additionalProperties.containsKey(PROJECT_DESCRIPTION)) {
|
||||
projectDescription = ((String) additionalProperties.get(PROJECT_DESCRIPTION));
|
||||
}
|
||||
if (additionalProperties.containsKey(PROJECT_VERSION)) {
|
||||
projectVersion = ((String) additionalProperties.get(PROJECT_VERSION));
|
||||
}
|
||||
if (additionalProperties.containsKey(BASE_NAMESPACE)) {
|
||||
baseNamespace = ((String) additionalProperties.get(BASE_NAMESPACE));
|
||||
}
|
||||
|
||||
if (openAPI.getInfo() != null) {
|
||||
Info info = openAPI.getInfo();
|
||||
if (projectName == null && info.getTitle() != null) {
|
||||
// when projectName is not specified, generate it from info.title
|
||||
projectName = dashize(info.getTitle());
|
||||
}
|
||||
if (projectVersion == null) {
|
||||
// when projectVersion is not specified, use info.version
|
||||
projectVersion = info.getVersion();
|
||||
}
|
||||
if (projectDescription == null) {
|
||||
// when projectDescription is not specified, use info.description
|
||||
projectDescription = info.getDescription();
|
||||
}
|
||||
|
||||
if (info.getContact() != null) {
|
||||
Contact contact = info.getContact();
|
||||
if (additionalProperties.get(PROJECT_URL) == null) {
|
||||
additionalProperties.put(PROJECT_URL, contact.getUrl());
|
||||
}
|
||||
}
|
||||
if (info.getLicense() != null) {
|
||||
License license = info.getLicense();
|
||||
if (additionalProperties.get(PROJECT_LICENSE_NAME) == null) {
|
||||
additionalProperties.put(PROJECT_LICENSE_NAME, license.getName());
|
||||
}
|
||||
if (additionalProperties.get(PROJECT_LICENSE_URL) == null) {
|
||||
additionalProperties.put(PROJECT_LICENSE_URL, license.getUrl());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// default values
|
||||
if (projectName == null) {
|
||||
projectName = "swagger-clj-client";
|
||||
}
|
||||
if (projectVersion == null) {
|
||||
projectVersion = "1.0.0";
|
||||
}
|
||||
if (projectDescription == null) {
|
||||
projectDescription = "Client library of " + projectName;
|
||||
}
|
||||
if (baseNamespace == null) {
|
||||
baseNamespace = dashize(projectName);
|
||||
}
|
||||
apiPackage = baseNamespace + ".api";
|
||||
|
||||
additionalProperties.put(PROJECT_NAME, projectName);
|
||||
additionalProperties.put(PROJECT_DESCRIPTION, escapeText(projectDescription));
|
||||
additionalProperties.put(PROJECT_VERSION, projectVersion);
|
||||
additionalProperties.put(BASE_NAMESPACE, baseNamespace);
|
||||
additionalProperties.put(CodegenConstants.API_PACKAGE, apiPackage);
|
||||
|
||||
final String baseNamespaceFolder = sourceFolder + File.separator + namespaceToFolder(baseNamespace);
|
||||
supportingFiles.add(new SupportingFile("project.mustache", "", "project.clj"));
|
||||
supportingFiles.add(new SupportingFile("core.mustache", baseNamespaceFolder, "core.clj"));
|
||||
supportingFiles.add(new SupportingFile("git_push.sh.mustache", "", "git_push.sh"));
|
||||
supportingFiles.add(new SupportingFile("gitignore.mustache", "", ".gitignore"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String sanitizeTag(String tag) {
|
||||
return tag.replaceAll("[^a-zA-Z_]+", "_");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String apiFileFolder() {
|
||||
return outputFolder + File.separator + sourceFolder + File.separator + namespaceToFolder(apiPackage);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toOperationId(String operationId) {
|
||||
// throw exception if method name is empty
|
||||
if (StringUtils.isEmpty(operationId)) {
|
||||
throw new RuntimeException("Empty method/operation name (operationId) not allowed");
|
||||
}
|
||||
|
||||
return dashize(sanitizeName(operationId));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toApiFilename(String name) {
|
||||
return underscore(toApiName(name));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toApiName(String name) {
|
||||
return dashize(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toParamName(String name) {
|
||||
return toVarName(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toVarName(String name) {
|
||||
name = name.replaceAll("[^a-zA-Z0-9_-]+", ""); // FIXME: a parameter should not be assigned. Also declare the methods parameters as 'final'.
|
||||
name = dashize(name);
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String escapeText(String input) {
|
||||
if (input == null) {
|
||||
return null;
|
||||
}
|
||||
return input.trim().replace("\\", "\\\\").replace("\"", "\\\"");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> postProcessOperations(Map<String, Object> operations) {
|
||||
Map<String, Object> objs = (Map<String, Object>) operations.get("operations");
|
||||
List<CodegenOperation> ops = (List<CodegenOperation>) objs.get("operation");
|
||||
for (CodegenOperation op : ops) {
|
||||
// Convert httpMethod to lower case, e.g. "get", "post"
|
||||
op.httpMethod = op.httpMethod.toLowerCase();
|
||||
}
|
||||
return operations;
|
||||
}
|
||||
|
||||
@SuppressWarnings("static-method")
|
||||
protected String namespaceToFolder(String ns) {
|
||||
return ns.replace(".", File.separator).replace("-", "_");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String escapeQuotationMark(String input) {
|
||||
// remove " to avoid code injection
|
||||
return input.replace("\"", "");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String escapeUnsafeCharacters(String input) {
|
||||
// ref: https://clojurebridge.github.io/community-docs/docs/clojure/comment/
|
||||
return input.replace("(comment", "(_comment");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
package org.openapitools.codegen.languages;
|
||||
|
||||
import org.openapitools.codegen.*;
|
||||
import io.swagger.v3.oas.models.OpenAPI;
|
||||
import io.swagger.v3.oas.models.Operation;
|
||||
import io.swagger.v3.oas.models.media.*;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class ConfluenceWikiCodegen extends DefaultCodegen implements CodegenConfig {
|
||||
private static final String ALL_OPERATIONS = "";
|
||||
protected String invokerPackage = "io.swagger.client";
|
||||
protected String groupId = "io.swagger";
|
||||
protected String artifactId = "swagger-client";
|
||||
protected String artifactVersion = "1.0.0";
|
||||
|
||||
public ConfluenceWikiCodegen() {
|
||||
super();
|
||||
outputFolder = "docs";
|
||||
embeddedTemplateDir = templateDir = "confluenceWikiDocs";
|
||||
|
||||
defaultIncludes = new HashSet<String>();
|
||||
|
||||
cliOptions.add(new CliOption("appName", "short name of the application"));
|
||||
cliOptions.add(new CliOption("appDescription", "description of the application"));
|
||||
cliOptions.add(new CliOption("infoUrl", "a URL where users can get more information about the application"));
|
||||
cliOptions.add(new CliOption("infoEmail", "an email address to contact for inquiries about the application"));
|
||||
cliOptions.add(new CliOption("licenseInfo", "a short description of the license"));
|
||||
cliOptions.add(new CliOption("licenseUrl", "a URL pointing to the full license"));
|
||||
cliOptions.add(new CliOption(CodegenConstants.INVOKER_PACKAGE, CodegenConstants.INVOKER_PACKAGE_DESC));
|
||||
cliOptions.add(new CliOption(CodegenConstants.GROUP_ID, CodegenConstants.GROUP_ID_DESC));
|
||||
cliOptions.add(new CliOption(CodegenConstants.ARTIFACT_ID, CodegenConstants.ARTIFACT_ID_DESC));
|
||||
cliOptions.add(new CliOption(CodegenConstants.ARTIFACT_VERSION, CodegenConstants.ARTIFACT_VERSION_DESC));
|
||||
|
||||
additionalProperties.put("appName", "Swagger Sample");
|
||||
additionalProperties.put("appDescription", "A sample swagger server");
|
||||
additionalProperties.put("infoUrl", "https://helloreverb.com");
|
||||
additionalProperties.put("infoEmail", "hello@helloreverb.com");
|
||||
additionalProperties.put("licenseInfo", "All rights reserved");
|
||||
additionalProperties.put("licenseUrl", "http://apache.org/licenses/LICENSE-2.0.html");
|
||||
additionalProperties.put(CodegenConstants.INVOKER_PACKAGE, invokerPackage);
|
||||
additionalProperties.put(CodegenConstants.GROUP_ID, groupId);
|
||||
additionalProperties.put(CodegenConstants.ARTIFACT_ID, artifactId);
|
||||
additionalProperties.put(CodegenConstants.ARTIFACT_VERSION, artifactVersion);
|
||||
|
||||
supportingFiles.add(new SupportingFile("index.mustache", "", "confluence-markup.txt"));
|
||||
reservedWords = new HashSet<String>();
|
||||
|
||||
languageSpecificPrimitives = new HashSet<String>();
|
||||
importMapping = new HashMap<String, String>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CodegenType getTag() {
|
||||
return CodegenType.DOCUMENTATION;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "cwiki";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHelp() {
|
||||
return "Generates confluence wiki markup.";
|
||||
}
|
||||
|
||||
@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 Map<String, Object> postProcessOperations(Map<String, Object> objs) {
|
||||
Map<String, Object> operations = (Map<String, Object>) objs.get("operations");
|
||||
List<CodegenOperation> operationList = (List<CodegenOperation>) operations.get("operation");
|
||||
for (CodegenOperation op : operationList) {
|
||||
op.httpMethod = op.httpMethod.toLowerCase();
|
||||
}
|
||||
return objs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String escapeQuotationMark(String input) {
|
||||
// just return the original string
|
||||
return input;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String escapeUnsafeCharacters(String input) {
|
||||
// just return the original string
|
||||
return input;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,399 @@
|
||||
package org.openapitools.codegen.languages;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import io.swagger.v3.parser.util.SchemaTypeUtil;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.openapitools.codegen.*;
|
||||
import io.swagger.v3.oas.models.security.SecurityScheme;
|
||||
import io.swagger.v3.oas.models.*;
|
||||
import io.swagger.v3.oas.models.media.*;
|
||||
import io.swagger.v3.oas.models.responses.ApiResponse;
|
||||
import io.swagger.v3.oas.models.parameters.*;
|
||||
import io.swagger.v3.core.util.Yaml;
|
||||
|
||||
public class CppPistacheServerCodegen extends AbstractCppCodegen {
|
||||
protected String implFolder = "impl";
|
||||
|
||||
@Override
|
||||
public CodegenType getTag() {
|
||||
return CodegenType.SERVER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "pistache-server";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHelp() {
|
||||
return "Generates a C++ API server (based on Pistache)";
|
||||
}
|
||||
|
||||
public CppPistacheServerCodegen() {
|
||||
super();
|
||||
|
||||
apiPackage = "io.swagger.server.api";
|
||||
modelPackage = "io.swagger.server.model";
|
||||
|
||||
modelTemplateFiles.put("model-header.mustache", ".h");
|
||||
modelTemplateFiles.put("model-source.mustache", ".cpp");
|
||||
|
||||
apiTemplateFiles.put("api-header.mustache", ".h");
|
||||
apiTemplateFiles.put("api-source.mustache", ".cpp");
|
||||
apiTemplateFiles.put("api-impl-header.mustache", ".h");
|
||||
apiTemplateFiles.put("api-impl-source.mustache", ".cpp");
|
||||
apiTemplateFiles.put("main-api-server.mustache", ".cpp");
|
||||
|
||||
embeddedTemplateDir = templateDir = "pistache-server";
|
||||
|
||||
cliOptions.clear();
|
||||
|
||||
reservedWords = new HashSet<>();
|
||||
|
||||
supportingFiles.add(new SupportingFile("modelbase-header.mustache", "model", "ModelBase.h"));
|
||||
supportingFiles.add(new SupportingFile("modelbase-source.mustache", "model", "ModelBase.cpp"));
|
||||
supportingFiles.add(new SupportingFile("cmake.mustache", "", "CMakeLists.txt"));
|
||||
supportingFiles.add(new SupportingFile("README.mustache", "", "README.md"));
|
||||
|
||||
languageSpecificPrimitives = new HashSet<String>(
|
||||
Arrays.asList("int", "char", "bool", "long", "float", "double", "int32_t", "int64_t"));
|
||||
|
||||
typeMapping = new HashMap<String, String>();
|
||||
typeMapping.put("date", "std::string");
|
||||
typeMapping.put("DateTime", "std::string");
|
||||
typeMapping.put("string", "std::string");
|
||||
typeMapping.put("integer", "int32_t");
|
||||
typeMapping.put("long", "int64_t");
|
||||
typeMapping.put("boolean", "bool");
|
||||
typeMapping.put("array", "std::vector");
|
||||
typeMapping.put("map", "std::map");
|
||||
typeMapping.put("file", "std::string");
|
||||
typeMapping.put("object", "Object");
|
||||
typeMapping.put("binary", "std::string");
|
||||
typeMapping.put("number", "double");
|
||||
typeMapping.put("UUID", "std::string");
|
||||
|
||||
super.importMapping = new HashMap<String, String>();
|
||||
importMapping.put("std::vector", "#include <vector>");
|
||||
importMapping.put("std::map", "#include <map>");
|
||||
importMapping.put("std::string", "#include <string>");
|
||||
importMapping.put("Object", "#include \"Object.h\"");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processOpts() {
|
||||
super.processOpts();
|
||||
|
||||
additionalProperties.put("modelNamespaceDeclarations", modelPackage.split("\\."));
|
||||
additionalProperties.put("modelNamespace", modelPackage.replaceAll("\\.", "::"));
|
||||
additionalProperties.put("apiNamespaceDeclarations", apiPackage.split("\\."));
|
||||
additionalProperties.put("apiNamespace", apiPackage.replaceAll("\\.", "::"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Escapes a reserved word as defined in the `reservedWords` array. Handle
|
||||
* escaping those terms here. This logic is only called if a variable
|
||||
* matches the reserved words
|
||||
*
|
||||
* @return the escaped term
|
||||
*/
|
||||
@Override
|
||||
public String escapeReservedWord(String name) {
|
||||
return "_" + name; // add an underscore to the name
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toModelImport(String name) {
|
||||
if (importMapping.containsKey(name)) {
|
||||
return importMapping.get(name);
|
||||
} else {
|
||||
return "#include \"" + name + ".h\"";
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public CodegenModel fromModel(String name, Schema model, Map<String, Schema> allDefinitions) {
|
||||
CodegenModel codegenModel = super.fromModel(name, model, allDefinitions);
|
||||
|
||||
Set<String> oldImports = codegenModel.imports;
|
||||
codegenModel.imports = new HashSet<>();
|
||||
for (String imp : oldImports) {
|
||||
String newImp = toModelImport(imp);
|
||||
if (!newImp.isEmpty()) {
|
||||
codegenModel.imports.add(newImp);
|
||||
}
|
||||
}
|
||||
|
||||
return codegenModel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CodegenOperation fromOperation(String path, String httpMethod, Operation operation,
|
||||
Map<String, Schema> definitions, OpenAPI openAPI) {
|
||||
CodegenOperation op = super.fromOperation(path, httpMethod, operation, definitions, openAPI);
|
||||
|
||||
if (operation.getResponses() != null && !operation.getResponses().isEmpty()) {
|
||||
ApiResponse apiResponse = findMethodResponse(operation.getResponses());
|
||||
|
||||
if (apiResponse != null) {
|
||||
Schema response = getSchemaFromResponse(apiResponse);
|
||||
if (response != null) {
|
||||
CodegenProperty cm = fromProperty("response", response);
|
||||
op.vendorExtensions.put("x-codegen-response", cm);
|
||||
if (cm.datatype == "HttpContent") {
|
||||
op.vendorExtensions.put("x-codegen-response-ishttpcontent", true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
String pathForPistache = path.replaceAll("\\{(.*?)}", ":$1");
|
||||
op.vendorExtensions.put("x-codegen-pistache-path", pathForPistache);
|
||||
|
||||
return op;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public Map<String, Object> postProcessOperations(Map<String, Object> objs) {
|
||||
Map<String, Object> operations = (Map<String, Object>) objs.get("operations");
|
||||
String classname = (String) operations.get("classname");
|
||||
operations.put("classnameSnakeUpperCase", DefaultCodegen.underscore(classname).toUpperCase());
|
||||
operations.put("classnameSnakeLowerCase", DefaultCodegen.underscore(classname).toLowerCase());
|
||||
|
||||
List<CodegenOperation> operationList = (List<CodegenOperation>) operations.get("operation");
|
||||
for (CodegenOperation op : operationList) {
|
||||
boolean consumeJson = false;
|
||||
boolean isParsingSupported = true;
|
||||
if (op.bodyParam != null) {
|
||||
if (op.bodyParam.vendorExtensions == null) {
|
||||
op.bodyParam.vendorExtensions = new HashMap<>();
|
||||
}
|
||||
|
||||
op.bodyParam.vendorExtensions.put("x-codegen-pistache-isStringOrDate", op.bodyParam.isString || op.bodyParam.isDate);
|
||||
}
|
||||
if(op.consumes != null) {
|
||||
for (Map<String, String> consume : op.consumes) {
|
||||
if (consume.get("mediaType") != null && consume.get("mediaType").equals("application/json")) {
|
||||
consumeJson = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
op.httpMethod = op.httpMethod.substring(0, 1).toUpperCase() + op.httpMethod.substring(1).toLowerCase();
|
||||
|
||||
for(CodegenParameter param : op.allParams){
|
||||
if (param.isFormParam) isParsingSupported=false;
|
||||
if (param.isFile) isParsingSupported=false;
|
||||
if (param.isCookieParam) isParsingSupported=false;
|
||||
|
||||
//TODO: This changes the info about the real type but it is needed to parse the header params
|
||||
if (param.isHeaderParam) {
|
||||
param.dataType = "Optional<Net::Http::Header::Raw>";
|
||||
param.baseType = "Optional<Net::Http::Header::Raw>";
|
||||
} else if(param.isQueryParam){
|
||||
if(param.isPrimitiveType) {
|
||||
param.dataType = "Optional<" + param.dataType + ">";
|
||||
} else {
|
||||
param.dataType = "Optional<" + param.baseType + ">";
|
||||
param.baseType = "Optional<" + param.baseType + ">";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (op.vendorExtensions == null) {
|
||||
op.vendorExtensions = new HashMap<>();
|
||||
}
|
||||
op.vendorExtensions.put("x-codegen-pistache-consumesJson", consumeJson);
|
||||
op.vendorExtensions.put("x-codegen-pistache-isParsingSupported", isParsingSupported);
|
||||
}
|
||||
|
||||
return objs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toModelFilename(String name) {
|
||||
return initialCaps(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String apiFilename(String templateName, String tag) {
|
||||
String result = super.apiFilename(templateName, tag);
|
||||
|
||||
if ( templateName.endsWith("impl-header.mustache") ) {
|
||||
int ix = result.lastIndexOf('/');
|
||||
result = result.substring(0, ix) + result.substring(ix, result.length() - 2) + "Impl.h";
|
||||
result = result.replace(apiFileFolder(), implFileFolder());
|
||||
} else if ( templateName.endsWith("impl-source.mustache") ) {
|
||||
int ix = result.lastIndexOf('/');
|
||||
result = result.substring(0, ix) + result.substring(ix, result.length() - 4) + "Impl.cpp";
|
||||
result = result.replace(apiFileFolder(), implFileFolder());
|
||||
} else if ( templateName.endsWith("api-server.mustache") ) {
|
||||
int ix = result.lastIndexOf('/');
|
||||
result = result.substring(0, ix) + result.substring(ix, result.length() - 4) + "MainServer.cpp";
|
||||
result = result.replace(apiFileFolder(), outputFolder);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toApiFilename(String name) {
|
||||
return initialCaps(name) + "Api";
|
||||
}
|
||||
|
||||
/**
|
||||
* Optional - type declaration. This is a String which is used by the
|
||||
* templates to instantiate your types. There is typically special handling
|
||||
* for different property types
|
||||
*
|
||||
* @return a string value used as the `dataType` field for model templates,
|
||||
* `returnType` for api templates
|
||||
*/
|
||||
@Override
|
||||
public String getTypeDeclaration(Schema p) {
|
||||
String swaggerType = getSchemaType(p);
|
||||
|
||||
if (p instanceof ArraySchema) {
|
||||
ArraySchema ap = (ArraySchema) p;
|
||||
Schema inner = ap.getItems();
|
||||
return getSchemaType(p) + "<" + getTypeDeclaration(inner) + ">";
|
||||
}
|
||||
if (p instanceof MapSchema) {
|
||||
MapSchema mp = (MapSchema) p;
|
||||
Schema inner = (Schema) mp.getAdditionalProperties();
|
||||
return getSchemaType(p) + "<std::string, " + getTypeDeclaration(inner) + ">";
|
||||
}
|
||||
if (p instanceof StringSchema || p instanceof DateSchema
|
||||
|| p instanceof DateTimeSchema || p instanceof FileSchema
|
||||
|| languageSpecificPrimitives.contains(swaggerType)) {
|
||||
return toModelName(swaggerType);
|
||||
}
|
||||
|
||||
return "std::shared_ptr<" + swaggerType + ">";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toDefaultValue(Schema p) {
|
||||
if (p instanceof StringSchema) {
|
||||
return "\"\"";
|
||||
} else if (p instanceof BooleanSchema) {
|
||||
return "false";
|
||||
} else if (p instanceof DateSchema) {
|
||||
return "\"\"";
|
||||
} else if (p instanceof DateTimeSchema) {
|
||||
return "\"\"";
|
||||
} else if (p instanceof NumberSchema) {
|
||||
if (SchemaTypeUtil.FLOAT_FORMAT.equals(p.getFormat())) {
|
||||
return "0.0f";
|
||||
}
|
||||
return "0.0";
|
||||
} else if (p instanceof IntegerSchema) {
|
||||
if (SchemaTypeUtil.INTEGER64_FORMAT.equals(p.getFormat())) {
|
||||
return "0L";
|
||||
}
|
||||
return "0";
|
||||
} else if (p instanceof MapSchema) {
|
||||
MapSchema ap = (MapSchema) p;
|
||||
String inner = getSchemaType((Schema) ap.getAdditionalProperties());
|
||||
return "std::map<std::string, " + inner + ">()";
|
||||
} else if (p instanceof ArraySchema) {
|
||||
ArraySchema ap = (ArraySchema) p;
|
||||
String inner = getSchemaType(ap.getItems());
|
||||
if (!languageSpecificPrimitives.contains(inner)) {
|
||||
inner = "std::shared_ptr<" + inner + ">";
|
||||
}
|
||||
return "std::vector<" + inner + ">()";
|
||||
} else if (!StringUtils.isEmpty(p.get$ref())) { // model
|
||||
return "new " + toModelName(p.get$ref()) + "()";
|
||||
}
|
||||
return "nullptr";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postProcessParameter(CodegenParameter parameter) {
|
||||
super.postProcessParameter(parameter);
|
||||
|
||||
boolean isPrimitiveType = parameter.isPrimitiveType == Boolean.TRUE;
|
||||
boolean isListContainer = parameter.isListContainer == Boolean.TRUE;
|
||||
boolean isString = parameter.isString == Boolean.TRUE;
|
||||
|
||||
if (!isPrimitiveType && !isListContainer && !isString && !parameter.dataType.startsWith("std::shared_ptr")) {
|
||||
parameter.dataType = "std::shared_ptr<" + parameter.dataType + ">";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Location to write model files. You can use the modelPackage() as defined
|
||||
* when the class is instantiated
|
||||
*/
|
||||
public String modelFileFolder() {
|
||||
return (outputFolder + "/model").replace("/", File.separator);
|
||||
}
|
||||
|
||||
/**
|
||||
* Location to write api files. You can use the apiPackage() as defined when
|
||||
* the class is instantiated
|
||||
*/
|
||||
@Override
|
||||
public String apiFileFolder() {
|
||||
return (outputFolder + "/api").replace("/", File.separator);
|
||||
}
|
||||
|
||||
private String implFileFolder() {
|
||||
return (outputFolder + "/" + implFolder).replace("/", File.separator);
|
||||
}
|
||||
|
||||
/**
|
||||
* Optional - swagger type conversion. This is used to map swagger types in
|
||||
* a `Schema` into either language specific types via `typeMapping` or
|
||||
* into complex models if there is not a mapping.
|
||||
*
|
||||
* @return a string value of the type or complex model for this property
|
||||
*/
|
||||
@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 toModelName(String type) {
|
||||
if (typeMapping.keySet().contains(type) || typeMapping.values().contains(type)
|
||||
|| importMapping.values().contains(type) || defaultIncludes.contains(type)
|
||||
|| languageSpecificPrimitives.contains(type)) {
|
||||
return type;
|
||||
} else {
|
||||
return Character.toUpperCase(type.charAt(0)) + type.substring(1);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toApiName(String type) {
|
||||
return Character.toUpperCase(type.charAt(0)) + type.substring(1) + "Api";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String escapeQuotationMark(String input) {
|
||||
// remove " to avoid code injection
|
||||
return input.replace("\"", "");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String escapeUnsafeCharacters(String input) {
|
||||
return input.replace("*/", "*_/").replace("/*", "/_*");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,425 @@
|
||||
package org.openapitools.codegen.languages;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.openapitools.codegen.*;
|
||||
import io.swagger.v3.oas.models.OpenAPI;
|
||||
import io.swagger.v3.oas.models.Operation;
|
||||
import io.swagger.v3.oas.models.media.*;
|
||||
import io.swagger.v3.oas.models.responses.ApiResponse;
|
||||
import io.swagger.v3.parser.util.SchemaTypeUtil;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
public class CppQt5ClientCodegen extends AbstractCppCodegen implements CodegenConfig {
|
||||
public static final String CPP_NAMESPACE = "cppNamespace";
|
||||
public static final String CPP_NAMESPACE_DESC = "C++ namespace (convention: name::space::for::api).";
|
||||
public static final String OPTIONAL_PROJECT_FILE_DESC = "Generate client.pri.";
|
||||
|
||||
protected final String PREFIX = "SWG";
|
||||
protected Set<String> foundationClasses = new HashSet<String>();
|
||||
// source folder where to write the files
|
||||
protected String sourceFolder = "client";
|
||||
protected String apiVersion = "1.0.0";
|
||||
protected Map<String, String> namespaces = new HashMap<String, String>();
|
||||
protected Set<String> systemIncludes = new HashSet<String>();
|
||||
protected String cppNamespace = "Swagger";
|
||||
protected boolean optionalProjectFileFlag = true;
|
||||
|
||||
public CppQt5ClientCodegen() {
|
||||
super();
|
||||
|
||||
// set the output folder here
|
||||
outputFolder = "generated-code/qt5cpp";
|
||||
|
||||
// set modelNamePrefix as default for QT5CPP
|
||||
if (modelNamePrefix == "") {
|
||||
modelNamePrefix = PREFIX;
|
||||
}
|
||||
|
||||
/*
|
||||
* Models. You can write model files using the modelTemplateFiles map.
|
||||
* if you want to create one template for file, you can do so here.
|
||||
* for multiple files for model, just put another entry in the `modelTemplateFiles` with
|
||||
* a different extension
|
||||
*/
|
||||
modelTemplateFiles.put(
|
||||
"model-header.mustache",
|
||||
".h");
|
||||
|
||||
modelTemplateFiles.put(
|
||||
"model-body.mustache",
|
||||
".cpp");
|
||||
|
||||
/*
|
||||
* Api classes. You can write classes for each Api file with the apiTemplateFiles map.
|
||||
* as with models, add multiple entries with different extensions for multiple files per
|
||||
* class
|
||||
*/
|
||||
apiTemplateFiles.put(
|
||||
"api-header.mustache", // the template to use
|
||||
".h"); // the extension for each file to write
|
||||
|
||||
apiTemplateFiles.put(
|
||||
"api-body.mustache", // the template to use
|
||||
".cpp"); // the extension for each file to write
|
||||
|
||||
/*
|
||||
* Template Location. This is the location which templates will be read from. The generator
|
||||
* will use the resource stream to attempt to read the templates.
|
||||
*/
|
||||
embeddedTemplateDir = templateDir = "qt5cpp";
|
||||
|
||||
// CLI options
|
||||
addOption(CPP_NAMESPACE, CPP_NAMESPACE_DESC, this.cppNamespace);
|
||||
addSwitch(CodegenConstants.OPTIONAL_PROJECT_FILE, OPTIONAL_PROJECT_FILE_DESC, this.optionalProjectFileFlag);
|
||||
|
||||
/*
|
||||
* Additional Properties. These values can be passed to the templates and
|
||||
* are available in models, apis, and supporting files
|
||||
*/
|
||||
additionalProperties.put("apiVersion", apiVersion);
|
||||
additionalProperties().put("prefix", PREFIX);
|
||||
|
||||
// Write defaults namespace in properties so that it can be accessible in templates.
|
||||
// At this point command line has not been parsed so if value is given
|
||||
// in command line it will superseed this content
|
||||
additionalProperties.put("cppNamespace", cppNamespace);
|
||||
|
||||
/*
|
||||
* Language Specific Primitives. These types will not trigger imports by
|
||||
* the client generator
|
||||
*/
|
||||
languageSpecificPrimitives = new HashSet<String>(
|
||||
Arrays.asList(
|
||||
"bool",
|
||||
"qint32",
|
||||
"qint64",
|
||||
"float",
|
||||
"double")
|
||||
);
|
||||
|
||||
supportingFiles.add(new SupportingFile("helpers-header.mustache", sourceFolder, PREFIX + "Helpers.h"));
|
||||
supportingFiles.add(new SupportingFile("helpers-body.mustache", sourceFolder, PREFIX + "Helpers.cpp"));
|
||||
supportingFiles.add(new SupportingFile("HttpRequest.h.mustache", sourceFolder, PREFIX + "HttpRequest.h"));
|
||||
supportingFiles.add(new SupportingFile("HttpRequest.cpp.mustache", sourceFolder, PREFIX + "HttpRequest.cpp"));
|
||||
supportingFiles.add(new SupportingFile("modelFactory.mustache", sourceFolder, PREFIX + "ModelFactory.h"));
|
||||
supportingFiles.add(new SupportingFile("object.mustache", sourceFolder, PREFIX + "Object.h"));
|
||||
supportingFiles.add(new SupportingFile("QObjectWrapper.h.mustache", sourceFolder, PREFIX + "QObjectWrapper.h"));
|
||||
if (optionalProjectFileFlag) {
|
||||
supportingFiles.add(new SupportingFile("Project.mustache", sourceFolder, "client.pri"));
|
||||
}
|
||||
|
||||
super.typeMapping = new HashMap<String, String>();
|
||||
|
||||
typeMapping.put("date", "QDate");
|
||||
typeMapping.put("DateTime", "QDateTime");
|
||||
typeMapping.put("string", "QString");
|
||||
typeMapping.put("integer", "qint32");
|
||||
typeMapping.put("long", "qint64");
|
||||
typeMapping.put("boolean", "bool");
|
||||
typeMapping.put("array", "QList");
|
||||
typeMapping.put("map", "QMap");
|
||||
typeMapping.put("file", "SWGHttpRequestInputFileElement");
|
||||
typeMapping.put("object", PREFIX + "Object");
|
||||
//TODO binary should be mapped to byte array
|
||||
// mapped to String as a workaround
|
||||
typeMapping.put("binary", "QString");
|
||||
typeMapping.put("ByteArray", "QByteArray");
|
||||
// UUID support - possible enhancement : use QUuid instead of QString.
|
||||
// beware though that Serialisation/deserialisation of QUuid does not
|
||||
// come out of the box and will need to be sorted out (at least imply
|
||||
// modifications on multiple templates)
|
||||
typeMapping.put("UUID", "QString");
|
||||
|
||||
importMapping = new HashMap<String, String>();
|
||||
|
||||
importMapping.put("SWGHttpRequestInputFileElement", "#include \"" + PREFIX + "HttpRequest.h\"");
|
||||
|
||||
namespaces = new HashMap<String, String>();
|
||||
|
||||
foundationClasses.add("QString");
|
||||
|
||||
systemIncludes.add("QString");
|
||||
systemIncludes.add("QList");
|
||||
systemIncludes.add("QMap");
|
||||
systemIncludes.add("QDate");
|
||||
systemIncludes.add("QDateTime");
|
||||
systemIncludes.add("QByteArray");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processOpts() {
|
||||
super.processOpts();
|
||||
|
||||
if (additionalProperties.containsKey("cppNamespace")) {
|
||||
cppNamespace = (String) additionalProperties.get("cppNamespace");
|
||||
}
|
||||
|
||||
additionalProperties.put("cppNamespaceDeclarations", cppNamespace.split("\\::"));
|
||||
if (additionalProperties.containsKey("modelNamePrefix")) {
|
||||
supportingFiles.clear();
|
||||
supportingFiles.add(new SupportingFile("helpers-header.mustache", sourceFolder, modelNamePrefix + "Helpers.h"));
|
||||
supportingFiles.add(new SupportingFile("helpers-body.mustache", sourceFolder, modelNamePrefix + "Helpers.cpp"));
|
||||
supportingFiles.add(new SupportingFile("HttpRequest.h.mustache", sourceFolder, modelNamePrefix + "HttpRequest.h"));
|
||||
supportingFiles.add(new SupportingFile("HttpRequest.cpp.mustache", sourceFolder, modelNamePrefix + "HttpRequest.cpp"));
|
||||
supportingFiles.add(new SupportingFile("modelFactory.mustache", sourceFolder, modelNamePrefix + "ModelFactory.h"));
|
||||
supportingFiles.add(new SupportingFile("object.mustache", sourceFolder, modelNamePrefix + "Object.h"));
|
||||
supportingFiles.add(new SupportingFile("QObjectWrapper.h.mustache", sourceFolder, modelNamePrefix + "QObjectWrapper.h"));
|
||||
|
||||
typeMapping.put("object", modelNamePrefix + "Object");
|
||||
typeMapping.put("file", modelNamePrefix + "HttpRequestInputFileElement");
|
||||
importMapping.put("SWGHttpRequestInputFileElement", "#include \"" + modelNamePrefix + "HttpRequest.h\"");
|
||||
additionalProperties().put("prefix", modelNamePrefix);
|
||||
}
|
||||
|
||||
if (additionalProperties.containsKey(CodegenConstants.OPTIONAL_PROJECT_FILE)) {
|
||||
setOptionalProjectFileFlag(convertPropertyToBooleanAndWriteBack(CodegenConstants.OPTIONAL_PROJECT_FILE));
|
||||
} else {
|
||||
additionalProperties.put(CodegenConstants.OPTIONAL_PROJECT_FILE, optionalProjectFileFlag);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the type of generator.
|
||||
*
|
||||
* @return the CodegenType for this generator
|
||||
* @see org.openapitools.codegen.CodegenType
|
||||
*/
|
||||
@Override
|
||||
public CodegenType getTag() {
|
||||
return CodegenType.CLIENT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures a friendly name for the generator. This will be used by the generator
|
||||
* to select the library with the -l flag.
|
||||
*
|
||||
* @return the friendly name for the generator
|
||||
*/
|
||||
@Override
|
||||
public String getName() {
|
||||
return "qt5cpp";
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns human-friendly help for the generator. Provide the consumer with help
|
||||
* tips, parameters here
|
||||
*
|
||||
* @return A string value for the help message
|
||||
*/
|
||||
@Override
|
||||
public String getHelp() {
|
||||
return "Generates a Qt5 C++ client library.";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toModelImport(String name) {
|
||||
if (namespaces.containsKey(name)) {
|
||||
return "using " + namespaces.get(name) + ";";
|
||||
} else if (systemIncludes.contains(name)) {
|
||||
return "#include <" + name + ">";
|
||||
}
|
||||
|
||||
String folder = modelPackage().replace("::", File.separator);
|
||||
if (!folder.isEmpty())
|
||||
folder += File.separator;
|
||||
|
||||
return "#include \"" + folder + name + ".h\"";
|
||||
}
|
||||
|
||||
/**
|
||||
* Escapes a reserved word as defined in the `reservedWords` array. Handle escaping
|
||||
* those terms here. This logic is only called if a variable matches the reserved words
|
||||
*
|
||||
* @return the escaped term
|
||||
*/
|
||||
@Override
|
||||
public String escapeReservedWord(String name) {
|
||||
if (this.reservedWordsMappings().containsKey(name)) {
|
||||
return this.reservedWordsMappings().get(name);
|
||||
}
|
||||
return "_" + name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Location to write model files. You can use the modelPackage() as defined when the class is
|
||||
* instantiated
|
||||
*/
|
||||
@Override
|
||||
public String modelFileFolder() {
|
||||
return outputFolder + "/" + sourceFolder + "/" + modelPackage().replace("::", File.separator);
|
||||
}
|
||||
|
||||
/**
|
||||
* Location to write api files. You can use the apiPackage() as defined when the class is
|
||||
* instantiated
|
||||
*/
|
||||
@Override
|
||||
public String apiFileFolder() {
|
||||
return outputFolder + "/" + sourceFolder + "/" + apiPackage().replace("::", File.separator);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toModelFilename(String name) {
|
||||
return modelNamePrefix + initialCaps(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toApiFilename(String name) {
|
||||
return modelNamePrefix + initialCaps(name) + "Api";
|
||||
}
|
||||
|
||||
/**
|
||||
* Optional - type declaration. This is a String which is used by the templates to instantiate your
|
||||
* types. There is typically special handling for different property types
|
||||
*
|
||||
* @return a string value used as the `dataType` field for model templates, `returnType` for api templates
|
||||
*/
|
||||
@Override
|
||||
public String getTypeDeclaration(Schema p) {
|
||||
String openAPIType = getSchemaType(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) + "<QString, " + getTypeDeclaration(inner) + ">*";
|
||||
}
|
||||
if (foundationClasses.contains(openAPIType)) {
|
||||
return openAPIType + "*";
|
||||
} else if (languageSpecificPrimitives.contains(openAPIType)) {
|
||||
return toModelName(openAPIType);
|
||||
} else {
|
||||
return openAPIType + "*";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toDefaultValue(Schema p) {
|
||||
if (p instanceof StringSchema) {
|
||||
return "new QString(\"\")";
|
||||
} else if (p instanceof BooleanSchema) {
|
||||
return "false";
|
||||
} else if (p instanceof DateSchema) {
|
||||
return "NULL";
|
||||
} else if (p instanceof DateTimeSchema) {
|
||||
return "NULL";
|
||||
} else if (p instanceof NumberSchema) {
|
||||
if (SchemaTypeUtil.FLOAT_FORMAT.equals(p.getFormat())) {
|
||||
return "0.0f";
|
||||
}
|
||||
return "0.0";
|
||||
} else if (p instanceof IntegerSchema) {
|
||||
if (SchemaTypeUtil.INTEGER64_FORMAT.equals(p.getFormat())) {
|
||||
return "0L";
|
||||
}
|
||||
return "0";
|
||||
} else if (p instanceof MapSchema) {
|
||||
MapSchema mp = (MapSchema) p;
|
||||
Schema inner = (Schema) mp.getAdditionalProperties();
|
||||
return "new QMap<QString, " + getTypeDeclaration(inner) + ">()";
|
||||
} else if (p instanceof ArraySchema) {
|
||||
ArraySchema ap = (ArraySchema) p;
|
||||
Schema inner = ap.getItems();
|
||||
return "new QList<" + getTypeDeclaration(inner) + ">()";
|
||||
}
|
||||
// else
|
||||
if (!StringUtils.isEmpty(p.get$ref())) {
|
||||
return "new " + toModelName(p.get$ref()) + "()";
|
||||
}
|
||||
return "NULL";
|
||||
}
|
||||
|
||||
/**
|
||||
* Optional - swagger type conversion. This is used to map swagger types in a `Schema` into
|
||||
* either language specific types via `typeMapping` or into complex models if there is not a mapping.
|
||||
*
|
||||
* @return a string value of the type or complex model for this property
|
||||
*/
|
||||
@Override
|
||||
public String getSchemaType(Schema p) {
|
||||
String openAPIType = super.getSchemaType(p);
|
||||
String type = null;
|
||||
if (typeMapping.containsKey(openAPIType)) {
|
||||
type = typeMapping.get(openAPIType);
|
||||
if (languageSpecificPrimitives.contains(type)) {
|
||||
return toModelName(type);
|
||||
}
|
||||
if (foundationClasses.contains(type)) {
|
||||
return type;
|
||||
}
|
||||
} else {
|
||||
type = openAPIType;
|
||||
}
|
||||
return toModelName(type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toModelName(String type) {
|
||||
if (typeMapping.keySet().contains(type) ||
|
||||
typeMapping.values().contains(type) ||
|
||||
importMapping.values().contains(type) ||
|
||||
defaultIncludes.contains(type) ||
|
||||
languageSpecificPrimitives.contains(type)) {
|
||||
return type;
|
||||
} else {
|
||||
return modelNamePrefix + Character.toUpperCase(type.charAt(0)) + type.substring(1);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toVarName(String name) {
|
||||
// sanitize name
|
||||
name = sanitizeName(name); // FIXME: a parameter should not be assigned. Also declare the methods parameters as 'final'.
|
||||
|
||||
// if it's all uppper case, convert to lower case
|
||||
if (name.matches("^[A-Z_]*$")) {
|
||||
name = name.toLowerCase();
|
||||
}
|
||||
|
||||
// camelize (lower first character) the variable name
|
||||
// petId => pet_id
|
||||
name = underscore(name);
|
||||
|
||||
// for reserved word or word starting with number, append _
|
||||
if (isReservedWord(name) || name.matches("^\\d.*")) {
|
||||
name = escapeReservedWord(name);
|
||||
}
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toParamName(String name) {
|
||||
return toVarName(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toApiName(String type) {
|
||||
return modelNamePrefix + Character.toUpperCase(type.charAt(0)) + type.substring(1) + "Api";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String escapeQuotationMark(String input) {
|
||||
// remove " to avoid code injection
|
||||
return input.replace("\"", "");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String escapeUnsafeCharacters(String input) {
|
||||
return input.replace("*/", "*_/").replace("/*", "/_*");
|
||||
}
|
||||
|
||||
public void setOptionalProjectFileFlag(boolean flag) {
|
||||
this.optionalProjectFileFlag = flag;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,429 @@
|
||||
package org.openapitools.codegen.languages;
|
||||
|
||||
import static com.google.common.base.Strings.isNullOrEmpty;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import com.google.common.collect.ArrayListMultimap;
|
||||
import com.google.common.collect.Multimap;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.openapitools.codegen.CliOption;
|
||||
import org.openapitools.codegen.CodegenConstants;
|
||||
import org.openapitools.codegen.CodegenModel;
|
||||
import org.openapitools.codegen.CodegenOperation;
|
||||
import org.openapitools.codegen.CodegenParameter;
|
||||
import org.openapitools.codegen.CodegenProperty;
|
||||
import org.openapitools.codegen.CodegenType;
|
||||
import org.openapitools.codegen.SupportingFile;
|
||||
import org.openapitools.codegen.utils.ModelUtils;
|
||||
import io.swagger.v3.oas.models.OpenAPI;
|
||||
import io.swagger.v3.oas.models.Operation;
|
||||
import io.swagger.v3.oas.models.media.*;
|
||||
import io.swagger.v3.oas.models.responses.ApiResponse;
|
||||
import io.swagger.v3.parser.util.SchemaTypeUtil;
|
||||
|
||||
|
||||
public class CppRestClientCodegen extends AbstractCppCodegen {
|
||||
|
||||
public static final String DECLSPEC = "declspec";
|
||||
public static final String DEFAULT_INCLUDE = "defaultInclude";
|
||||
|
||||
protected String packageVersion = "1.0.0";
|
||||
protected String declspec = "";
|
||||
protected String defaultInclude = "";
|
||||
|
||||
private final Set<String> parentModels = new HashSet<>();
|
||||
private final Multimap<String, CodegenModel> childrenByParent = ArrayListMultimap.create();
|
||||
|
||||
/**
|
||||
* Configures the type of generator.
|
||||
*
|
||||
* @return the CodegenType for this generator
|
||||
* @see org.openapitools.codegen.CodegenType
|
||||
*/
|
||||
public CodegenType getTag() {
|
||||
return CodegenType.CLIENT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures a friendly name for the generator. This will be used by the
|
||||
* generator to select the library with the -l flag.
|
||||
*
|
||||
* @return the friendly name for the generator
|
||||
*/
|
||||
public String getName() {
|
||||
return "cpprest";
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns human-friendly help for the generator. Provide the consumer with
|
||||
* help tips, parameters here
|
||||
*
|
||||
* @return A string value for the help message
|
||||
*/
|
||||
public String getHelp() {
|
||||
return "Generates a C++ API client with C++ REST SDK (https://github.com/Microsoft/cpprestsdk).";
|
||||
}
|
||||
|
||||
public CppRestClientCodegen() {
|
||||
super();
|
||||
|
||||
apiPackage = "io.swagger.client.api";
|
||||
modelPackage = "io.swagger.client.model";
|
||||
|
||||
modelTemplateFiles.put("model-header.mustache", ".h");
|
||||
modelTemplateFiles.put("model-source.mustache", ".cpp");
|
||||
|
||||
apiTemplateFiles.put("api-header.mustache", ".h");
|
||||
apiTemplateFiles.put("api-source.mustache", ".cpp");
|
||||
|
||||
embeddedTemplateDir = templateDir = "cpprest";
|
||||
|
||||
cliOptions.clear();
|
||||
|
||||
// CLI options
|
||||
addOption(CodegenConstants.MODEL_PACKAGE, "C++ namespace for models (convention: name.space.model).",
|
||||
this.modelPackage);
|
||||
addOption(CodegenConstants.API_PACKAGE, "C++ namespace for apis (convention: name.space.api).",
|
||||
this.apiPackage);
|
||||
addOption(CodegenConstants.PACKAGE_VERSION, "C++ package version.", this.packageVersion);
|
||||
addOption(DECLSPEC, "C++ preprocessor to place before the class name for handling dllexport/dllimport.",
|
||||
this.declspec);
|
||||
addOption(DEFAULT_INCLUDE,
|
||||
"The default include statement that should be placed in all headers for including things like the declspec (convention: #include \"Commons.h\" ",
|
||||
this.defaultInclude);
|
||||
|
||||
supportingFiles.add(new SupportingFile("modelbase-header.mustache", "", "ModelBase.h"));
|
||||
supportingFiles.add(new SupportingFile("modelbase-source.mustache", "", "ModelBase.cpp"));
|
||||
supportingFiles.add(new SupportingFile("object-header.mustache", "", "Object.h"));
|
||||
supportingFiles.add(new SupportingFile("object-source.mustache", "", "Object.cpp"));
|
||||
supportingFiles.add(new SupportingFile("apiclient-header.mustache", "", "ApiClient.h"));
|
||||
supportingFiles.add(new SupportingFile("apiclient-source.mustache", "", "ApiClient.cpp"));
|
||||
supportingFiles.add(new SupportingFile("apiconfiguration-header.mustache", "", "ApiConfiguration.h"));
|
||||
supportingFiles.add(new SupportingFile("apiconfiguration-source.mustache", "", "ApiConfiguration.cpp"));
|
||||
supportingFiles.add(new SupportingFile("apiexception-header.mustache", "", "ApiException.h"));
|
||||
supportingFiles.add(new SupportingFile("apiexception-source.mustache", "", "ApiException.cpp"));
|
||||
supportingFiles.add(new SupportingFile("ihttpbody-header.mustache", "", "IHttpBody.h"));
|
||||
supportingFiles.add(new SupportingFile("jsonbody-header.mustache", "", "JsonBody.h"));
|
||||
supportingFiles.add(new SupportingFile("jsonbody-source.mustache", "", "JsonBody.cpp"));
|
||||
supportingFiles.add(new SupportingFile("httpcontent-header.mustache", "", "HttpContent.h"));
|
||||
supportingFiles.add(new SupportingFile("httpcontent-source.mustache", "", "HttpContent.cpp"));
|
||||
supportingFiles.add(new SupportingFile("multipart-header.mustache", "", "MultipartFormData.h"));
|
||||
supportingFiles.add(new SupportingFile("multipart-source.mustache", "", "MultipartFormData.cpp"));
|
||||
supportingFiles.add(new SupportingFile("gitignore.mustache", "", ".gitignore"));
|
||||
supportingFiles.add(new SupportingFile("git_push.sh.mustache", "", "git_push.sh"));
|
||||
supportingFiles.add(new SupportingFile("cmake-lists.mustache", "", "CMakeLists.txt"));
|
||||
|
||||
languageSpecificPrimitives = new HashSet<String>(
|
||||
Arrays.asList("int", "char", "bool", "long", "float", "double", "int32_t", "int64_t"));
|
||||
|
||||
typeMapping = new HashMap<String, String>();
|
||||
typeMapping.put("date", "utility::datetime");
|
||||
typeMapping.put("DateTime", "utility::datetime");
|
||||
typeMapping.put("string", "utility::string_t");
|
||||
typeMapping.put("integer", "int32_t");
|
||||
typeMapping.put("long", "int64_t");
|
||||
typeMapping.put("boolean", "bool");
|
||||
typeMapping.put("array", "std::vector");
|
||||
typeMapping.put("map", "std::map");
|
||||
typeMapping.put("file", "HttpContent");
|
||||
typeMapping.put("object", "Object");
|
||||
typeMapping.put("binary", "std::string");
|
||||
typeMapping.put("number", "double");
|
||||
typeMapping.put("UUID", "utility::string_t");
|
||||
|
||||
super.importMapping = new HashMap<String, String>();
|
||||
importMapping.put("std::vector", "#include <vector>");
|
||||
importMapping.put("std::map", "#include <map>");
|
||||
importMapping.put("std::string", "#include <string>");
|
||||
importMapping.put("HttpContent", "#include \"HttpContent.h\"");
|
||||
importMapping.put("Object", "#include \"Object.h\"");
|
||||
importMapping.put("utility::string_t", "#include <cpprest/details/basic_types.h>");
|
||||
importMapping.put("utility::datetime", "#include <cpprest/details/basic_types.h>");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processOpts() {
|
||||
super.processOpts();
|
||||
|
||||
if (additionalProperties.containsKey(DECLSPEC)) {
|
||||
declspec = additionalProperties.get(DECLSPEC).toString();
|
||||
}
|
||||
|
||||
if (additionalProperties.containsKey(DEFAULT_INCLUDE)) {
|
||||
defaultInclude = additionalProperties.get(DEFAULT_INCLUDE).toString();
|
||||
}
|
||||
|
||||
additionalProperties.put("modelNamespaceDeclarations", modelPackage.split("\\."));
|
||||
additionalProperties.put("modelNamespace", modelPackage.replaceAll("\\.", "::"));
|
||||
additionalProperties.put("modelHeaderGuardPrefix", modelPackage.replaceAll("\\.", "_").toUpperCase());
|
||||
additionalProperties.put("apiNamespaceDeclarations", apiPackage.split("\\."));
|
||||
additionalProperties.put("apiNamespace", apiPackage.replaceAll("\\.", "::"));
|
||||
additionalProperties.put("apiHeaderGuardPrefix", apiPackage.replaceAll("\\.", "_").toUpperCase());
|
||||
additionalProperties.put("declspec", declspec);
|
||||
additionalProperties.put("defaultInclude", defaultInclude);
|
||||
}
|
||||
|
||||
/**
|
||||
* Location to write model files. You can use the modelPackage() as defined
|
||||
* when the class is instantiated
|
||||
*/
|
||||
public String modelFileFolder() {
|
||||
return outputFolder + "/model";
|
||||
}
|
||||
|
||||
/**
|
||||
* Location to write api files. You can use the apiPackage() as defined when
|
||||
* the class is instantiated
|
||||
*/
|
||||
@Override
|
||||
public String apiFileFolder() {
|
||||
return outputFolder + "/api";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toModelImport(String name) {
|
||||
if (importMapping.containsKey(name)) {
|
||||
return importMapping.get(name);
|
||||
} else {
|
||||
return "#include \"" + name + ".h\"";
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public CodegenModel fromModel(String name, Schema model, Map<String, Schema> allDefinitions) {
|
||||
CodegenModel codegenModel = super.fromModel(name, model, allDefinitions);
|
||||
|
||||
Set<String> oldImports = codegenModel.imports;
|
||||
codegenModel.imports = new HashSet<String>();
|
||||
for (String imp : oldImports) {
|
||||
String newImp = toModelImport(imp);
|
||||
if (!newImp.isEmpty()) {
|
||||
codegenModel.imports.add(newImp);
|
||||
}
|
||||
}
|
||||
|
||||
return codegenModel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CodegenOperation fromOperation(String path, String httpMethod, Operation operation,
|
||||
Map<String, Schema> schema, OpenAPI openAPI) {
|
||||
CodegenOperation op = super.fromOperation(path, httpMethod, operation, schema, openAPI);
|
||||
|
||||
if (operation.getResponses() != null && !operation.getResponses().isEmpty()) {
|
||||
ApiResponse methodResponse = findMethodResponse(operation.getResponses());
|
||||
|
||||
if (methodResponse != null) {
|
||||
Schema response = getSchemaFromResponse(methodResponse);
|
||||
if (response != null) {
|
||||
CodegenProperty cm = fromProperty("response", response);
|
||||
op.vendorExtensions.put("x-codegen-response", cm);
|
||||
if (cm.datatype == "HttpContent") {
|
||||
op.vendorExtensions.put("x-codegen-response-ishttpcontent", true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return op;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postProcessModelProperty(CodegenModel model, CodegenProperty property) {
|
||||
if (isFileSchema(property)) {
|
||||
property.vendorExtensions.put("x-codegen-file", true);
|
||||
}
|
||||
|
||||
if (!isNullOrEmpty(model.parent)) {
|
||||
parentModels.add(model.parent);
|
||||
if (!childrenByParent.containsEntry(model.parent, model)) {
|
||||
childrenByParent.put(model.parent, model);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean isFileSchema(CodegenProperty property) {
|
||||
return property.baseType.equals("HttpContent");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toModelFilename(String name) {
|
||||
return initialCaps(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toApiFilename(String name) {
|
||||
return initialCaps(name) + "Api";
|
||||
}
|
||||
|
||||
/**
|
||||
* Optional - type declaration. This is a String which is used by the
|
||||
* templates to instantiate your types. There is typically special handling
|
||||
* for different property types
|
||||
*
|
||||
* @return a string value used as the `dataType` field for model templates,
|
||||
* `returnType` for api templates
|
||||
*/
|
||||
@Override
|
||||
public String getTypeDeclaration(Schema p) {
|
||||
String openAPIType = getSchemaType(p);
|
||||
|
||||
if (p instanceof ArraySchema) {
|
||||
ArraySchema ap = (ArraySchema) p;
|
||||
Schema inner = ap.getItems();
|
||||
return getSchemaType(p) + "<" + getTypeDeclaration(inner) + ">";
|
||||
}
|
||||
if (p instanceof MapSchema) {
|
||||
MapSchema mp = (MapSchema) p;
|
||||
Schema inner = (Schema) mp.getAdditionalProperties();
|
||||
return getSchemaType(p) + "<utility::string_t, " + getTypeDeclaration(inner) + ">";
|
||||
}
|
||||
if (p instanceof StringSchema || p instanceof DateSchema
|
||||
|| p instanceof DateTimeSchema || p instanceof FileSchema
|
||||
|| languageSpecificPrimitives.contains(openAPIType)) {
|
||||
return toModelName(openAPIType);
|
||||
}
|
||||
|
||||
return "std::shared_ptr<" + openAPIType + ">";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toDefaultValue(Schema p) {
|
||||
if (p instanceof StringSchema) {
|
||||
return "utility::conversions::to_string_t(\"\")";
|
||||
} else if (p instanceof BooleanSchema) {
|
||||
return "false";
|
||||
} else if (p instanceof DateSchema) {
|
||||
return "utility::datetime()";
|
||||
} else if (p instanceof DateTimeSchema) {
|
||||
return "utility::datetime()";
|
||||
} else if (p instanceof NumberSchema) {
|
||||
if (SchemaTypeUtil.FLOAT_FORMAT.equals(p.getFormat())) {
|
||||
return "0.0f";
|
||||
}
|
||||
return "0.0";
|
||||
} else if (p instanceof IntegerSchema) {
|
||||
if (SchemaTypeUtil.INTEGER64_FORMAT.equals(p.getFormat())) {
|
||||
return "0L";
|
||||
}
|
||||
return "0";
|
||||
} else if (p instanceof MapSchema) {
|
||||
MapSchema ap = (MapSchema) p;
|
||||
String inner = getSchemaType((Schema) ap.getAdditionalProperties());
|
||||
return "std::map<utility::string_t, " + inner + ">()";
|
||||
} else if (p instanceof ArraySchema) {
|
||||
ArraySchema ap = (ArraySchema) p;
|
||||
String inner = getSchemaType(ap.getItems());
|
||||
if (!languageSpecificPrimitives.contains(inner)) {
|
||||
inner = "std::shared_ptr<" + inner + ">";
|
||||
}
|
||||
return "std::vector<" + inner + ">()";
|
||||
} else if (!StringUtils.isEmpty(p.get$ref())) {
|
||||
return "new " + toModelName(p.get$ref()) + "()";
|
||||
}
|
||||
return "nullptr";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postProcessParameter(CodegenParameter parameter) {
|
||||
super.postProcessParameter(parameter);
|
||||
|
||||
boolean isPrimitiveType = parameter.isPrimitiveType == Boolean.TRUE;
|
||||
boolean isListContainer = parameter.isListContainer == Boolean.TRUE;
|
||||
boolean isString = parameter.isString == Boolean.TRUE;
|
||||
|
||||
if (!isPrimitiveType && !isListContainer && !isString && !parameter.dataType.startsWith("std::shared_ptr")) {
|
||||
parameter.dataType = "std::shared_ptr<" + parameter.dataType + ">";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Optional - swagger type conversion. This is used to map swagger types in
|
||||
* a `Schema` into either language specific types via `typeMapping` or
|
||||
* into complex models if there is not a mapping.
|
||||
*
|
||||
* @return a string value of the type or complex model for this property
|
||||
* @see io.swagger.models.properties.Schema
|
||||
*/
|
||||
@Override
|
||||
public String getSchemaType(Schema p) {
|
||||
String openAPIType = super.getSchemaType(p);
|
||||
String type = null;
|
||||
if (typeMapping.containsKey(openAPIType)) {
|
||||
type = typeMapping.get(openAPIType);
|
||||
if (languageSpecificPrimitives.contains(type))
|
||||
return toModelName(type);
|
||||
} else
|
||||
type = openAPIType;
|
||||
return toModelName(type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toModelName(String type) {
|
||||
if (typeMapping.keySet().contains(type) || typeMapping.values().contains(type)
|
||||
|| importMapping.values().contains(type) || defaultIncludes.contains(type)
|
||||
|| languageSpecificPrimitives.contains(type)) {
|
||||
return type;
|
||||
} else {
|
||||
return Character.toUpperCase(type.charAt(0)) + type.substring(1);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toApiName(String type) {
|
||||
return Character.toUpperCase(type.charAt(0)) + type.substring(1) + "Api";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String escapeQuotationMark(String input) {
|
||||
// remove " to avoid code injection
|
||||
return input.replace("\"", "");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String escapeUnsafeCharacters(String input) {
|
||||
return input.replace("*/", "*_/").replace("/*", "/_*");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> postProcessAllModels(final Map<String, Object> models) {
|
||||
|
||||
final Map<String, Object> processed = super.postProcessAllModels(models);
|
||||
postProcessParentModels(models);
|
||||
return processed;
|
||||
}
|
||||
|
||||
private void postProcessParentModels(final Map<String, Object> models) {
|
||||
for (final String parent : parentModels) {
|
||||
final CodegenModel parentModel = ModelUtils.getModelByName(parent, models);
|
||||
final Collection<CodegenModel> childrenModels = childrenByParent.get(parent);
|
||||
for (final CodegenModel child : childrenModels) {
|
||||
processParentPropertiesInChildModel(parentModel, child);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the child property's isInherited flag to true if it is an inherited property
|
||||
*/
|
||||
private void processParentPropertiesInChildModel(final CodegenModel parent, final CodegenModel child) {
|
||||
final Map<String, CodegenProperty> childPropertiesByName = new HashMap<>(child.vars.size());
|
||||
for (final CodegenProperty childSchema : child.vars) {
|
||||
childPropertiesByName.put(childSchema.name, childSchema);
|
||||
}
|
||||
for (final CodegenProperty parentSchema : parent.vars) {
|
||||
final CodegenProperty duplicatedByParent = childPropertiesByName.get(parentSchema.name);
|
||||
if (duplicatedByParent != null) {
|
||||
duplicatedByParent.isInherited = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,382 @@
|
||||
package org.openapitools.codegen.languages;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import io.swagger.v3.parser.util.SchemaTypeUtil;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.openapitools.codegen.*;
|
||||
import io.swagger.v3.oas.models.security.SecurityScheme;
|
||||
import io.swagger.v3.oas.models.*;
|
||||
import io.swagger.v3.oas.models.media.*;
|
||||
import io.swagger.v3.oas.models.responses.ApiResponse;
|
||||
import io.swagger.v3.oas.models.parameters.*;
|
||||
import io.swagger.v3.core.util.Yaml;
|
||||
|
||||
public class CppRestbedServerCodegen extends AbstractCppCodegen {
|
||||
|
||||
public static final String DECLSPEC = "declspec";
|
||||
public static final String DEFAULT_INCLUDE = "defaultInclude";
|
||||
|
||||
protected String packageVersion = "1.0.0";
|
||||
protected String declspec = "";
|
||||
protected String defaultInclude = "";
|
||||
|
||||
public CppRestbedServerCodegen() {
|
||||
super();
|
||||
|
||||
apiPackage = "io.swagger.server.api";
|
||||
modelPackage = "io.swagger.server.model";
|
||||
|
||||
modelTemplateFiles.put("model-header.mustache", ".h");
|
||||
modelTemplateFiles.put("model-source.mustache", ".cpp");
|
||||
|
||||
apiTemplateFiles.put("api-header.mustache", ".h");
|
||||
apiTemplateFiles.put("api-source.mustache", ".cpp");
|
||||
|
||||
embeddedTemplateDir = templateDir = "restbed";
|
||||
|
||||
cliOptions.clear();
|
||||
|
||||
// CLI options
|
||||
addOption(CodegenConstants.MODEL_PACKAGE, "C++ namespace for models (convention: name.space.model).",
|
||||
this.modelPackage);
|
||||
addOption(CodegenConstants.API_PACKAGE, "C++ namespace for apis (convention: name.space.api).",
|
||||
this.apiPackage);
|
||||
addOption(CodegenConstants.PACKAGE_VERSION, "C++ package version.", this.packageVersion);
|
||||
addOption(DECLSPEC, "C++ preprocessor to place before the class name for handling dllexport/dllimport.",
|
||||
this.declspec);
|
||||
addOption(DEFAULT_INCLUDE,
|
||||
"The default include statement that should be placed in all headers for including things like the declspec (convention: #include \"Commons.h\" ",
|
||||
this.defaultInclude);
|
||||
|
||||
supportingFiles.add(new SupportingFile("gitignore.mustache", "", ".gitignore"));
|
||||
supportingFiles.add(new SupportingFile("git_push.sh.mustache", "", "git_push.sh"));
|
||||
supportingFiles.add(new SupportingFile("README.mustache", "", "README.md"));
|
||||
|
||||
languageSpecificPrimitives = new HashSet<String>(
|
||||
Arrays.asList("int", "char", "bool", "long", "float", "double", "int32_t", "int64_t"));
|
||||
|
||||
typeMapping = new HashMap<String, String>();
|
||||
typeMapping.put("date", "std::string");
|
||||
typeMapping.put("DateTime", "std::string");
|
||||
typeMapping.put("string", "std::string");
|
||||
typeMapping.put("integer", "int32_t");
|
||||
typeMapping.put("long", "int64_t");
|
||||
typeMapping.put("boolean", "bool");
|
||||
typeMapping.put("array", "std::vector");
|
||||
typeMapping.put("map", "std::map");
|
||||
typeMapping.put("file", "std::string");
|
||||
typeMapping.put("object", "Object");
|
||||
typeMapping.put("binary", "restbed::Bytes");
|
||||
typeMapping.put("number", "double");
|
||||
typeMapping.put("UUID", "std::string");
|
||||
|
||||
super.importMapping = new HashMap<String, String>();
|
||||
importMapping.put("std::vector", "#include <vector>");
|
||||
importMapping.put("std::map", "#include <map>");
|
||||
importMapping.put("std::string", "#include <string>");
|
||||
importMapping.put("Object", "#include \"Object.h\"");
|
||||
importMapping.put("restbed::Bytes", "#include <corvusoft/restbed/byte.hpp>");
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the type of generator.
|
||||
*
|
||||
* @return the CodegenType for this generator
|
||||
*/
|
||||
public CodegenType getTag() {
|
||||
return CodegenType.SERVER;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures a friendly name for the generator. This will be used by the
|
||||
* generator to select the library with the -l flag.
|
||||
*
|
||||
* @return the friendly name for the generator
|
||||
*/
|
||||
public String getName() {
|
||||
return "restbed";
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns human-friendly help for the generator. Provide the consumer with
|
||||
* help tips, parameters here
|
||||
*
|
||||
* @return A string value for the help message
|
||||
*/
|
||||
public String getHelp() {
|
||||
return "Generates a C++ API Server with Restbed (https://github.com/Corvusoft/restbed).";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processOpts() {
|
||||
super.processOpts();
|
||||
|
||||
if (additionalProperties.containsKey(DECLSPEC)) {
|
||||
declspec = additionalProperties.get(DECLSPEC).toString();
|
||||
}
|
||||
|
||||
if (additionalProperties.containsKey(DEFAULT_INCLUDE)) {
|
||||
defaultInclude = additionalProperties.get(DEFAULT_INCLUDE).toString();
|
||||
}
|
||||
|
||||
additionalProperties.put("modelNamespaceDeclarations", modelPackage.split("\\."));
|
||||
additionalProperties.put("modelNamespace", modelPackage.replaceAll("\\.", "::"));
|
||||
additionalProperties.put("apiNamespaceDeclarations", apiPackage.split("\\."));
|
||||
additionalProperties.put("apiNamespace", apiPackage.replaceAll("\\.", "::"));
|
||||
additionalProperties.put("declspec", declspec);
|
||||
additionalProperties.put("defaultInclude", defaultInclude);
|
||||
}
|
||||
|
||||
/**
|
||||
* Escapes a reserved word as defined in the `reservedWords` array. Handle
|
||||
* escaping those terms here. This logic is only called if a variable
|
||||
* matches the reserved words
|
||||
*
|
||||
* @return the escaped term
|
||||
*/
|
||||
@Override
|
||||
public String escapeReservedWord(String name) {
|
||||
return "_" + name; // add an underscore to the name
|
||||
}
|
||||
|
||||
/**
|
||||
* Location to write model files. You can use the modelPackage() as defined
|
||||
* when the class is instantiated
|
||||
*/
|
||||
public String modelFileFolder() {
|
||||
return (outputFolder + "/model").replace("/", File.separator);
|
||||
}
|
||||
|
||||
/**
|
||||
* Location to write api files. You can use the apiPackage() as defined when
|
||||
* the class is instantiated
|
||||
*/
|
||||
@Override
|
||||
public String apiFileFolder() {
|
||||
return (outputFolder + "/api").replace("/", File.separator);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toModelImport(String name) {
|
||||
if (importMapping.containsKey(name)) {
|
||||
return importMapping.get(name);
|
||||
} else {
|
||||
return "#include \"" + name + ".h\"";
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public CodegenModel fromModel(String name, Schema model, Map<String, Schema> allDefinitions) {
|
||||
CodegenModel codegenModel = super.fromModel(name, model, allDefinitions);
|
||||
|
||||
Set<String> oldImports = codegenModel.imports;
|
||||
codegenModel.imports = new HashSet<String>();
|
||||
for (String imp : oldImports) {
|
||||
String newImp = toModelImport(imp);
|
||||
if (!newImp.isEmpty()) {
|
||||
codegenModel.imports.add(newImp);
|
||||
}
|
||||
}
|
||||
|
||||
return codegenModel;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toModelFilename(String name) {
|
||||
return initialCaps(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toApiFilename(String name) {
|
||||
return initialCaps(name) + "Api";
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public Map<String, Object> postProcessOperations(Map<String, Object> objs) {
|
||||
Map<String, Object> operations = (Map<String, Object>) objs.get("operations");
|
||||
List<CodegenOperation> operationList = (List<CodegenOperation>) operations.get("operation");
|
||||
List<CodegenOperation> newOpList = new ArrayList<CodegenOperation>();
|
||||
for (CodegenOperation op : operationList) {
|
||||
String path = new String(op.path);
|
||||
|
||||
String[] items = path.split("/", -1);
|
||||
String resourceNameCamelCase = "";
|
||||
op.path = "";
|
||||
for (String item : items) {
|
||||
if (item.length() > 1) {
|
||||
if (item.matches("^\\{(.*)\\}$")) {
|
||||
String tmpResourceName = item.substring(1, item.length() - 1);
|
||||
resourceNameCamelCase += Character.toUpperCase(tmpResourceName.charAt(0)) + tmpResourceName.substring(1);
|
||||
item = item.substring(0, item.length() - 1);
|
||||
item += ": .*}";
|
||||
} else {
|
||||
resourceNameCamelCase += Character.toUpperCase(item.charAt(0)) + item.substring(1);
|
||||
}
|
||||
} else if (item.length() == 1) {
|
||||
resourceNameCamelCase += Character.toUpperCase(item.charAt(0));
|
||||
}
|
||||
op.path += item + "/";
|
||||
}
|
||||
op.vendorExtensions.put("x-codegen-resourceName", resourceNameCamelCase);
|
||||
boolean foundInNewList = false;
|
||||
for (CodegenOperation op1 : newOpList) {
|
||||
if (!foundInNewList) {
|
||||
if (op1.path.equals(op.path)) {
|
||||
foundInNewList = true;
|
||||
List<CodegenOperation> currentOtherMethodList = (List<CodegenOperation>) op1.vendorExtensions.get("x-codegen-otherMethods");
|
||||
if (currentOtherMethodList == null) {
|
||||
currentOtherMethodList = new ArrayList<CodegenOperation>();
|
||||
}
|
||||
op.operationIdCamelCase = op1.operationIdCamelCase;
|
||||
currentOtherMethodList.add(op);
|
||||
op1.vendorExtensions.put("x-codegen-otherMethods", currentOtherMethodList);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!foundInNewList) {
|
||||
newOpList.add(op);
|
||||
}
|
||||
}
|
||||
operations.put("operation", newOpList);
|
||||
return objs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Optional - type declaration. This is a String which is used by the
|
||||
* templates to instantiate your types. There is typically special handling
|
||||
* for different property types
|
||||
*
|
||||
* @return a string value used as the `dataType` field for model templates,
|
||||
* `returnType` for api templates
|
||||
*/
|
||||
@Override
|
||||
public String getTypeDeclaration(Schema p) {
|
||||
String swaggerType = getSchemaType(p);
|
||||
|
||||
if (p instanceof ArraySchema) {
|
||||
ArraySchema ap = (ArraySchema) p;
|
||||
Schema inner = ap.getItems();
|
||||
return getSchemaType(p) + "<" + getTypeDeclaration(inner) + ">";
|
||||
}
|
||||
if (p instanceof MapSchema) {
|
||||
Schema inner = (Schema) p.getAdditionalProperties();
|
||||
return getSchemaType(p) + "<std::string, " + getTypeDeclaration(inner) + ">";
|
||||
}
|
||||
if (p instanceof StringSchema || p instanceof DateSchema
|
||||
|| p instanceof DateTimeSchema || p instanceof FileSchema
|
||||
|| languageSpecificPrimitives.contains(swaggerType)) {
|
||||
return toModelName(swaggerType);
|
||||
}
|
||||
|
||||
return "std::shared_ptr<" + swaggerType + ">";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toDefaultValue(Schema p) {
|
||||
if (p instanceof StringSchema) {
|
||||
return "\"\"";
|
||||
} else if (p instanceof BooleanSchema) {
|
||||
return "false";
|
||||
} else if (p instanceof DateSchema) {
|
||||
return "\"\"";
|
||||
} else if (p instanceof DateTimeSchema) {
|
||||
return "\"\"";
|
||||
} else if (p instanceof NumberSchema) {
|
||||
if (SchemaTypeUtil.FLOAT_FORMAT.equals(p.getFormat())) {
|
||||
return "0.0f";
|
||||
}
|
||||
return "0.0";
|
||||
} else if (p instanceof IntegerSchema) {
|
||||
if (SchemaTypeUtil.INTEGER64_FORMAT.equals(p.getFormat())) {
|
||||
return "0L";
|
||||
}
|
||||
return "0";
|
||||
} else if (p instanceof MapSchema) {
|
||||
MapSchema ap = (MapSchema) p;
|
||||
String inner = getSchemaType((Schema) ap.getAdditionalProperties());
|
||||
return "std::map<std::string, " + inner + ">()";
|
||||
} else if (p instanceof ArraySchema) {
|
||||
ArraySchema ap = (ArraySchema) p;
|
||||
String inner = getSchemaType(ap.getItems());
|
||||
if (!languageSpecificPrimitives.contains(inner)) {
|
||||
inner = "std::shared_ptr<" + inner + ">";
|
||||
}
|
||||
return "std::vector<" + inner + ">()";
|
||||
} else if (!StringUtils.isEmpty(p.get$ref())) {
|
||||
return "new " + toModelName(p.get$ref()) + "()";
|
||||
}
|
||||
return "nullptr";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postProcessParameter(CodegenParameter parameter) {
|
||||
super.postProcessParameter(parameter);
|
||||
|
||||
boolean isPrimitiveType = parameter.isPrimitiveType == Boolean.TRUE;
|
||||
boolean isListContainer = parameter.isListContainer == Boolean.TRUE;
|
||||
boolean isString = parameter.isString == Boolean.TRUE;
|
||||
|
||||
if (!isPrimitiveType && !isListContainer && !isString && !parameter.dataType.startsWith("std::shared_ptr")) {
|
||||
parameter.dataType = "std::shared_ptr<" + parameter.dataType + ">";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Optional - swagger type conversion. This is used to map swagger types in
|
||||
* a `Schema` into either language specific types via `typeMapping` or
|
||||
* into complex models if there is not a mapping.
|
||||
*
|
||||
* @return a string value of the type or complex model for this property
|
||||
*/
|
||||
@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 toModelName(String type) {
|
||||
if (typeMapping.keySet().contains(type) || typeMapping.values().contains(type)
|
||||
|| importMapping.values().contains(type) || defaultIncludes.contains(type)
|
||||
|| languageSpecificPrimitives.contains(type)) {
|
||||
return type;
|
||||
} else {
|
||||
return Character.toUpperCase(type.charAt(0)) + type.substring(1);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toApiName(String type) {
|
||||
return Character.toUpperCase(type.charAt(0)) + type.substring(1) + "Api";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String escapeQuotationMark(String input) {
|
||||
// remove " to avoid code injection
|
||||
return input.replace("\"", "");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String escapeUnsafeCharacters(String input) {
|
||||
return input.replace("*/", "*_/").replace("/*", "/_*");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,185 @@
|
||||
package org.openapitools.codegen.languages;
|
||||
|
||||
import org.openapitools.codegen.*;
|
||||
import io.swagger.v3.oas.models.OpenAPI;
|
||||
import io.swagger.v3.oas.models.Operation;
|
||||
import io.swagger.v3.oas.models.media.*;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.*;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class GoClientCodegen extends AbstractGoCodegen {
|
||||
|
||||
protected String packageVersion = "1.0.0";
|
||||
protected String apiDocPath = "docs/";
|
||||
protected String modelDocPath = "docs/";
|
||||
public static final String WITH_XML = "withXml";
|
||||
|
||||
public GoClientCodegen() {
|
||||
super();
|
||||
|
||||
outputFolder = "generated-code/go";
|
||||
modelTemplateFiles.put("model.mustache", ".go");
|
||||
apiTemplateFiles.put("api.mustache", ".go");
|
||||
|
||||
modelDocTemplateFiles.put("model_doc.mustache", ".md");
|
||||
apiDocTemplateFiles.put("api_doc.mustache", ".md");
|
||||
|
||||
embeddedTemplateDir = templateDir = "go";
|
||||
|
||||
setReservedWordsLowerCase(
|
||||
Arrays.asList(
|
||||
// data type
|
||||
"string", "bool", "uint", "uint8", "uint16", "uint32", "uint64",
|
||||
"int", "int8", "int16", "int32", "int64", "float32", "float64",
|
||||
"complex64", "complex128", "rune", "byte", "uintptr",
|
||||
|
||||
"break", "default", "func", "interface", "select",
|
||||
"case", "defer", "go", "map", "struct",
|
||||
"chan", "else", "goto", "package", "switch",
|
||||
"const", "fallthrough", "if", "range", "type",
|
||||
"continue", "for", "import", "return", "var", "error", "ApiResponse", "nil")
|
||||
// Added "error" as it's used so frequently that it may as well be a keyword
|
||||
);
|
||||
|
||||
cliOptions.add(new CliOption(CodegenConstants.PACKAGE_VERSION, "Go package version.")
|
||||
.defaultValue("1.0.0"));
|
||||
cliOptions.add(CliOption.newBoolean(WITH_XML, "whether to include support for application/xml content type and include XML annotations in the model (works with libraries that provide support for JSON and XML)"));
|
||||
|
||||
// option to change the order of form/body parameter
|
||||
cliOptions.add(CliOption.newBoolean(
|
||||
CodegenConstants.PREPEND_FORM_OR_BODY_PARAMETERS,
|
||||
CodegenConstants.PREPEND_FORM_OR_BODY_PARAMETERS_DESC)
|
||||
.defaultValue(Boolean.FALSE.toString()));
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processOpts() {
|
||||
super.processOpts();
|
||||
|
||||
// default HIDE_GENERATION_TIMESTAMP to true
|
||||
if (!additionalProperties.containsKey(CodegenConstants.HIDE_GENERATION_TIMESTAMP)) {
|
||||
additionalProperties.put(CodegenConstants.HIDE_GENERATION_TIMESTAMP, Boolean.TRUE.toString());
|
||||
} else {
|
||||
additionalProperties.put(CodegenConstants.HIDE_GENERATION_TIMESTAMP,
|
||||
Boolean.valueOf(additionalProperties().get(CodegenConstants.HIDE_GENERATION_TIMESTAMP).toString()));
|
||||
}
|
||||
|
||||
if (additionalProperties.containsKey(CodegenConstants.PACKAGE_NAME)) {
|
||||
setPackageName((String) additionalProperties.get(CodegenConstants.PACKAGE_NAME));
|
||||
}
|
||||
else {
|
||||
setPackageName("swagger");
|
||||
}
|
||||
|
||||
if (additionalProperties.containsKey(CodegenConstants.PACKAGE_VERSION)) {
|
||||
setPackageVersion((String) additionalProperties.get(CodegenConstants.PACKAGE_VERSION));
|
||||
}
|
||||
else {
|
||||
setPackageVersion("1.0.0");
|
||||
}
|
||||
|
||||
additionalProperties.put(CodegenConstants.PACKAGE_NAME, packageName);
|
||||
additionalProperties.put(CodegenConstants.PACKAGE_VERSION, packageVersion);
|
||||
|
||||
additionalProperties.put("apiDocPath", apiDocPath);
|
||||
additionalProperties.put("modelDocPath", modelDocPath);
|
||||
|
||||
modelPackage = packageName;
|
||||
apiPackage = packageName;
|
||||
|
||||
supportingFiles.add(new SupportingFile("swagger.mustache", "api", "swagger.yaml"));
|
||||
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("configuration.mustache", "", "configuration.go"));
|
||||
supportingFiles.add(new SupportingFile("client.mustache", "", "client.go"));
|
||||
supportingFiles.add(new SupportingFile("response.mustache", "", "response.go"));
|
||||
supportingFiles.add(new SupportingFile(".travis.yml", "", ".travis.yml"));
|
||||
|
||||
if(additionalProperties.containsKey(WITH_XML)) {
|
||||
setWithXml(Boolean.parseBoolean(additionalProperties.get(WITH_XML).toString()));
|
||||
if ( withXml ) {
|
||||
additionalProperties.put(WITH_XML, "true");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the type of generator.
|
||||
*
|
||||
* @return the CodegenType for this generator
|
||||
* @see org.openapitools.codegen.CodegenType
|
||||
*/
|
||||
@Override
|
||||
public CodegenType getTag() {
|
||||
return CodegenType.CLIENT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures a friendly name for the generator. This will be used by the generator
|
||||
* to select the library with the -l flag.
|
||||
*
|
||||
* @return the friendly name for the generator
|
||||
*/
|
||||
@Override
|
||||
public String getName() {
|
||||
return "go";
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns human-friendly help for the generator. Provide the consumer with help
|
||||
* tips, parameters here
|
||||
*
|
||||
* @return A string value for the help message
|
||||
*/
|
||||
@Override
|
||||
public String getHelp() {
|
||||
return "Generates a Go client library (beta).";
|
||||
}
|
||||
|
||||
/**
|
||||
* Location to write api files. You can use the apiPackage() as defined when the class is
|
||||
* instantiated
|
||||
*/
|
||||
@Override
|
||||
public String apiFileFolder() {
|
||||
return outputFolder + File.separator;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String modelFileFolder() {
|
||||
return outputFolder + 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);
|
||||
}
|
||||
|
||||
public void setPackageVersion(String packageVersion) {
|
||||
this.packageVersion = packageVersion;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,161 @@
|
||||
package org.openapitools.codegen.languages;
|
||||
|
||||
import org.openapitools.codegen.*;
|
||||
import io.swagger.v3.oas.models.OpenAPI;
|
||||
import io.swagger.v3.oas.models.Operation;
|
||||
import io.swagger.v3.oas.models.media.*;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.*;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class GoServerCodegen extends AbstractGoCodegen {
|
||||
|
||||
protected String apiVersion = "1.0.0";
|
||||
protected int serverPort = 8080;
|
||||
protected String projectName = "swagger-server";
|
||||
protected String apiPath = "go";
|
||||
|
||||
public GoServerCodegen() {
|
||||
super();
|
||||
|
||||
// set the output folder here
|
||||
outputFolder = "generated-code/go";
|
||||
|
||||
/*
|
||||
* Models. You can write model files using the modelTemplateFiles map.
|
||||
* if you want to create one template for file, you can do so here.
|
||||
* for multiple files for model, just put another entry in the `modelTemplateFiles` with
|
||||
* a different extension
|
||||
*/
|
||||
modelTemplateFiles.put(
|
||||
"model.mustache",
|
||||
".go");
|
||||
|
||||
/*
|
||||
* Api classes. You can write classes for each Api file with the apiTemplateFiles map.
|
||||
* as with models, add multiple entries with different extensions for multiple files per
|
||||
* class
|
||||
*/
|
||||
apiTemplateFiles.put(
|
||||
"controller-api.mustache", // the template to use
|
||||
".go"); // the extension for each file to write
|
||||
|
||||
/*
|
||||
* Template Location. This is the location which templates will be read from. The generator
|
||||
* will use the resource stream to attempt to read the templates.
|
||||
*/
|
||||
embeddedTemplateDir = templateDir = "go-server";
|
||||
|
||||
/*
|
||||
* Reserved words. Override this with reserved words specific to your language
|
||||
*/
|
||||
setReservedWordsLowerCase(
|
||||
Arrays.asList(
|
||||
// data type
|
||||
"string", "bool", "uint", "uint8", "uint16", "uint32", "uint64",
|
||||
"int", "int8", "int16", "int32", "int64", "float32", "float64",
|
||||
"complex64", "complex128", "rune", "byte", "uintptr",
|
||||
|
||||
"break", "default", "func", "interface", "select",
|
||||
"case", "defer", "go", "map", "struct",
|
||||
"chan", "else", "goto", "package", "switch",
|
||||
"const", "fallthrough", "if", "range", "type",
|
||||
"continue", "for", "import", "return", "var", "error", "nil")
|
||||
// Added "error" as it's used so frequently that it may as well be a keyword
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processOpts() {
|
||||
super.processOpts();
|
||||
|
||||
if (additionalProperties.containsKey(CodegenConstants.PACKAGE_NAME)) {
|
||||
setPackageName((String) additionalProperties.get(CodegenConstants.PACKAGE_NAME));
|
||||
}
|
||||
else {
|
||||
setPackageName("swagger");
|
||||
}
|
||||
|
||||
/*
|
||||
* Additional Properties. These values can be passed to the templates and
|
||||
* are available in models, apis, and supporting files
|
||||
*/
|
||||
additionalProperties.put("apiVersion", apiVersion);
|
||||
additionalProperties.put("serverPort", serverPort);
|
||||
additionalProperties.put("apiPath", apiPath);
|
||||
additionalProperties.put(CodegenConstants.PACKAGE_NAME, packageName);
|
||||
|
||||
modelPackage = packageName;
|
||||
apiPackage = packageName;
|
||||
|
||||
/*
|
||||
* Supporting Files. You can write single files for the generator with the
|
||||
* entire object tree available. If the input file has a suffix of `.mustache
|
||||
* it will be processed by the template engine. Otherwise, it will be copied
|
||||
*/
|
||||
supportingFiles.add(new SupportingFile("swagger.mustache", "api", "swagger.yaml"));
|
||||
supportingFiles.add(new SupportingFile("main.mustache", "", "main.go"));
|
||||
supportingFiles.add(new SupportingFile("routers.mustache", apiPath, "routers.go"));
|
||||
supportingFiles.add(new SupportingFile("logger.mustache", apiPath, "logger.go"));
|
||||
writeOptional(outputFolder, new SupportingFile("README.mustache", apiPath, "README.md"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String apiPackage() {
|
||||
return apiPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the type of generator.
|
||||
*
|
||||
* @return the CodegenType for this generator
|
||||
* @see org.openapitools.codegen.CodegenType
|
||||
*/
|
||||
@Override
|
||||
public CodegenType getTag() {
|
||||
return CodegenType.SERVER;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures a friendly name for the generator. This will be used by the generator
|
||||
* to select the library with the -l flag.
|
||||
*
|
||||
* @return the friendly name for the generator
|
||||
*/
|
||||
@Override
|
||||
public String getName() {
|
||||
return "go-server";
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns human-friendly help for the generator. Provide the consumer with help
|
||||
* tips, parameters here
|
||||
*
|
||||
* @return A string value for the help message
|
||||
*/
|
||||
@Override
|
||||
public String getHelp() {
|
||||
return "Generates a Go server library using the swagger-tools project. By default, " +
|
||||
"it will also generate service classes--which you can disable with the `-Dnoservice` environment variable.";
|
||||
}
|
||||
|
||||
/**
|
||||
* Location to write api files. You can use the apiPackage() as defined when the class is
|
||||
* instantiated
|
||||
*/
|
||||
@Override
|
||||
public String apiFileFolder() {
|
||||
return outputFolder + File.separator + apiPackage().replace('.', File.separatorChar);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String modelFileFolder() {
|
||||
return outputFolder + File.separator + apiPackage().replace('.', File.separatorChar);
|
||||
}
|
||||
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,117 @@
|
||||
package org.openapitools.codegen.languages;
|
||||
|
||||
import org.openapitools.codegen.CliOption;
|
||||
import org.openapitools.codegen.CodegenConstants;
|
||||
import org.openapitools.codegen.CodegenType;
|
||||
import org.openapitools.codegen.SupportingFile;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class KotlinClientCodegen extends AbstractKotlinCodegen {
|
||||
|
||||
public static final String DATE_LIBRARY = "dateLibrary";
|
||||
protected CodegenConstants.ENUM_PROPERTY_NAMING_TYPE enumPropertyNaming = CodegenConstants.ENUM_PROPERTY_NAMING_TYPE.camelCase;
|
||||
static Logger LOGGER = LoggerFactory.getLogger(KotlinClientCodegen.class);
|
||||
|
||||
protected String dateLibrary = DateLibrary.JAVA8.value;
|
||||
|
||||
public enum DateLibrary {
|
||||
STRING("string"),
|
||||
THREETENBP("threetenbp"),
|
||||
JAVA8("java8");
|
||||
|
||||
public final String value;
|
||||
|
||||
DateLibrary(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an instance of `KotlinClientCodegen`.
|
||||
*/
|
||||
public KotlinClientCodegen() {
|
||||
super();
|
||||
|
||||
artifactId = "kotlin-client";
|
||||
packageName = "io.swagger.client";
|
||||
|
||||
outputFolder = "generated-code" + File.separator + "kotlin-client";
|
||||
modelTemplateFiles.put("model.mustache", ".kt");
|
||||
apiTemplateFiles.put("api.mustache", ".kt");
|
||||
modelDocTemplateFiles.put("model_doc.mustache", ".md");
|
||||
apiDocTemplateFiles.put("api_doc.mustache", ".md");
|
||||
embeddedTemplateDir = templateDir = "kotlin-client";
|
||||
apiPackage = packageName + ".apis";
|
||||
modelPackage = packageName + ".models";
|
||||
|
||||
CliOption dateLibrary = new CliOption(DATE_LIBRARY, "Option. Date library to use");
|
||||
Map<String, String> dateOptions = new HashMap<>();
|
||||
dateOptions.put(DateLibrary.THREETENBP.value, "Threetenbp");
|
||||
dateOptions.put(DateLibrary.STRING.value, "String");
|
||||
dateOptions.put(DateLibrary.JAVA8.value, "Java 8 native JSR310");
|
||||
dateLibrary.setEnum(dateOptions);
|
||||
cliOptions.add(dateLibrary);
|
||||
}
|
||||
|
||||
public CodegenType getTag() {
|
||||
return CodegenType.CLIENT;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return "kotlin";
|
||||
}
|
||||
|
||||
public String getHelp() {
|
||||
return "Generates a Kotlin client.";
|
||||
}
|
||||
|
||||
public void setDateLibrary(String library) {
|
||||
this.dateLibrary = library;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processOpts() {
|
||||
super.processOpts();
|
||||
|
||||
if (additionalProperties.containsKey(DATE_LIBRARY)) {
|
||||
setDateLibrary(additionalProperties.get(DATE_LIBRARY).toString());
|
||||
}
|
||||
|
||||
if (DateLibrary.THREETENBP.value.equals(dateLibrary)) {
|
||||
additionalProperties.put(DateLibrary.THREETENBP.value, true);
|
||||
typeMapping.put("date", "LocalDate");
|
||||
typeMapping.put("DateTime", "LocalDateTime");
|
||||
importMapping.put("LocalDate", "org.threeten.bp.LocalDate");
|
||||
importMapping.put("LocalDateTime", "org.threeten.bp.LocalDateTime");
|
||||
defaultIncludes.add("org.threeten.bp.LocalDateTime");
|
||||
} else if (DateLibrary.STRING.value.equals(dateLibrary)) {
|
||||
typeMapping.put("date-time", "kotlin.String");
|
||||
typeMapping.put("date", "kotlin.String");
|
||||
typeMapping.put("Date", "kotlin.String");
|
||||
typeMapping.put("DateTime", "kotlin.String");
|
||||
} else if (DateLibrary.JAVA8.value.equals(dateLibrary)) {
|
||||
additionalProperties.put(DateLibrary.JAVA8.value, true);
|
||||
}
|
||||
|
||||
supportingFiles.add(new SupportingFile("README.mustache", "", "README.md"));
|
||||
supportingFiles.add(new SupportingFile("build.gradle.mustache", "", "build.gradle"));
|
||||
supportingFiles.add(new SupportingFile("settings.gradle.mustache", "", "settings.gradle"));
|
||||
|
||||
final String infrastructureFolder = (sourceFolder + File.separator + packageName + File.separator + "infrastructure").replace(".", "/");
|
||||
|
||||
supportingFiles.add(new SupportingFile("infrastructure/ApiClient.kt.mustache", infrastructureFolder, "ApiClient.kt"));
|
||||
supportingFiles.add(new SupportingFile("infrastructure/ApiAbstractions.kt.mustache", infrastructureFolder, "ApiAbstractions.kt"));
|
||||
supportingFiles.add(new SupportingFile("infrastructure/ApiInfrastructureResponse.kt.mustache", infrastructureFolder, "ApiInfrastructureResponse.kt"));
|
||||
supportingFiles.add(new SupportingFile("infrastructure/ApplicationDelegates.kt.mustache", infrastructureFolder, "ApplicationDelegates.kt"));
|
||||
supportingFiles.add(new SupportingFile("infrastructure/RequestConfig.kt.mustache", infrastructureFolder, "RequestConfig.kt"));
|
||||
supportingFiles.add(new SupportingFile("infrastructure/RequestMethod.kt.mustache", infrastructureFolder, "RequestMethod.kt"));
|
||||
supportingFiles.add(new SupportingFile("infrastructure/ResponseExtensions.kt.mustache", infrastructureFolder, "ResponseExtensions.kt"));
|
||||
supportingFiles.add(new SupportingFile("infrastructure/Serializer.kt.mustache", infrastructureFolder, "Serializer.kt"));
|
||||
supportingFiles.add(new SupportingFile("infrastructure/Errors.kt.mustache", infrastructureFolder, "Errors.kt"));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,238 @@
|
||||
package org.openapitools.codegen.languages;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.samskivert.mustache.Mustache;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.openapitools.codegen.CliOption;
|
||||
import org.openapitools.codegen.CodegenConstants;
|
||||
import org.openapitools.codegen.CodegenType;
|
||||
import org.openapitools.codegen.SupportingFile;
|
||||
import org.openapitools.codegen.mustache.*;
|
||||
|
||||
import io.swagger.v3.oas.models.OpenAPI;
|
||||
import io.swagger.v3.oas.models.Operation;
|
||||
import io.swagger.v3.oas.models.media.*;
|
||||
import io.swagger.v3.oas.models.responses.ApiResponse;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class KotlinServerCodegen extends AbstractKotlinCodegen {
|
||||
|
||||
public static final String DEFAULT_LIBRARY = Constants.KTOR;
|
||||
static Logger LOGGER = LoggerFactory.getLogger(KotlinServerCodegen.class);
|
||||
private Boolean autoHeadFeatureEnabled = true;
|
||||
private Boolean conditionalHeadersFeatureEnabled = false;
|
||||
private Boolean hstsFeatureEnabled = true;
|
||||
private Boolean corsFeatureEnabled = false;
|
||||
private Boolean compressionFeatureEnabled = true;
|
||||
|
||||
// This is here to potentially warn the user when an option is not supoprted by the target framework.
|
||||
private Map<String, List<String>> optionsSupportedPerFramework = new ImmutableMap.Builder<String, List<String>>()
|
||||
.put(Constants.KTOR, Arrays.asList(
|
||||
Constants.AUTOMATIC_HEAD_REQUESTS,
|
||||
Constants.CONDITIONAL_HEADERS,
|
||||
Constants.HSTS,
|
||||
Constants.CORS,
|
||||
Constants.COMPRESSION
|
||||
))
|
||||
.build();
|
||||
|
||||
/**
|
||||
* Constructs an instance of `KotlinServerCodegen`.
|
||||
*/
|
||||
public KotlinServerCodegen() {
|
||||
super();
|
||||
|
||||
artifactId = "kotlin-server";
|
||||
packageName = "io.swagger.server";
|
||||
outputFolder = "generated-code" + File.separator + "kotlin-server";
|
||||
modelTemplateFiles.put("model.mustache", ".kt");
|
||||
apiTemplateFiles.put("api.mustache", ".kt");
|
||||
embeddedTemplateDir = templateDir = "kotlin-server";
|
||||
apiPackage = packageName + ".apis";
|
||||
modelPackage = packageName + ".models";
|
||||
|
||||
supportedLibraries.put("ktor", "ktor framework");
|
||||
|
||||
// TODO: Configurable server engine. Defaults to netty in build.gradle.
|
||||
CliOption library = new CliOption(CodegenConstants.LIBRARY, "library template (sub-template) to use");
|
||||
library.setDefault(DEFAULT_LIBRARY);
|
||||
library.setEnum(supportedLibraries);
|
||||
|
||||
cliOptions.add(library);
|
||||
|
||||
addSwitch(Constants.AUTOMATIC_HEAD_REQUESTS, Constants.AUTOMATIC_HEAD_REQUESTS_DESC, getAutoHeadFeatureEnabled());
|
||||
addSwitch(Constants.CONDITIONAL_HEADERS, Constants.CONDITIONAL_HEADERS_DESC, getConditionalHeadersFeatureEnabled());
|
||||
addSwitch(Constants.HSTS, Constants.HSTS_DESC, getHstsFeatureEnabled());
|
||||
addSwitch(Constants.CORS, Constants.CORS_DESC, getCorsFeatureEnabled());
|
||||
addSwitch(Constants.COMPRESSION, Constants.COMPRESSION_DESC, getCompressionFeatureEnabled());
|
||||
}
|
||||
|
||||
public Boolean getAutoHeadFeatureEnabled() {
|
||||
return autoHeadFeatureEnabled;
|
||||
}
|
||||
|
||||
public void setAutoHeadFeatureEnabled(Boolean autoHeadFeatureEnabled) {
|
||||
this.autoHeadFeatureEnabled = autoHeadFeatureEnabled;
|
||||
}
|
||||
|
||||
public Boolean getCompressionFeatureEnabled() {
|
||||
return compressionFeatureEnabled;
|
||||
}
|
||||
|
||||
public void setCompressionFeatureEnabled(Boolean compressionFeatureEnabled) {
|
||||
this.compressionFeatureEnabled = compressionFeatureEnabled;
|
||||
}
|
||||
|
||||
public Boolean getConditionalHeadersFeatureEnabled() {
|
||||
return conditionalHeadersFeatureEnabled;
|
||||
}
|
||||
|
||||
public void setConditionalHeadersFeatureEnabled(Boolean conditionalHeadersFeatureEnabled) {
|
||||
this.conditionalHeadersFeatureEnabled = conditionalHeadersFeatureEnabled;
|
||||
}
|
||||
|
||||
public Boolean getCorsFeatureEnabled() {
|
||||
return corsFeatureEnabled;
|
||||
}
|
||||
|
||||
public void setCorsFeatureEnabled(Boolean corsFeatureEnabled) {
|
||||
this.corsFeatureEnabled = corsFeatureEnabled;
|
||||
}
|
||||
|
||||
public String getHelp() {
|
||||
return "Generates a Kotlin server.";
|
||||
}
|
||||
|
||||
public Boolean getHstsFeatureEnabled() {
|
||||
return hstsFeatureEnabled;
|
||||
}
|
||||
|
||||
public void setHstsFeatureEnabled(Boolean hstsFeatureEnabled) {
|
||||
this.hstsFeatureEnabled = hstsFeatureEnabled;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return "kotlin-server";
|
||||
}
|
||||
|
||||
public CodegenType getTag() {
|
||||
return CodegenType.SERVER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processOpts() {
|
||||
super.processOpts();
|
||||
|
||||
if (additionalProperties.containsKey(CodegenConstants.LIBRARY)) {
|
||||
this.setLibrary((String) additionalProperties.get(CodegenConstants.LIBRARY));
|
||||
}
|
||||
|
||||
// set default library to "ktor"
|
||||
if (StringUtils.isEmpty(library)) {
|
||||
this.setLibrary("ktor");
|
||||
additionalProperties.put(CodegenConstants.LIBRARY, "ktor");
|
||||
LOGGER.info("`library` option is empty. Default to 'ktor'.");
|
||||
}
|
||||
|
||||
if (additionalProperties.containsKey(Constants.AUTOMATIC_HEAD_REQUESTS)) {
|
||||
setAutoHeadFeatureEnabled(convertPropertyToBooleanAndWriteBack(Constants.AUTOMATIC_HEAD_REQUESTS));
|
||||
} else {
|
||||
additionalProperties.put(Constants.AUTOMATIC_HEAD_REQUESTS, getAutoHeadFeatureEnabled());
|
||||
}
|
||||
|
||||
if (additionalProperties.containsKey(Constants.CONDITIONAL_HEADERS)) {
|
||||
setConditionalHeadersFeatureEnabled(convertPropertyToBooleanAndWriteBack(Constants.CONDITIONAL_HEADERS));
|
||||
} else {
|
||||
additionalProperties.put(Constants.CONDITIONAL_HEADERS, getConditionalHeadersFeatureEnabled());
|
||||
}
|
||||
|
||||
if (additionalProperties.containsKey(Constants.HSTS)) {
|
||||
setHstsFeatureEnabled(convertPropertyToBooleanAndWriteBack(Constants.HSTS));
|
||||
} else {
|
||||
additionalProperties.put(Constants.HSTS, getHstsFeatureEnabled());
|
||||
}
|
||||
|
||||
if (additionalProperties.containsKey(Constants.CORS)) {
|
||||
setCorsFeatureEnabled(convertPropertyToBooleanAndWriteBack(Constants.CORS));
|
||||
} else {
|
||||
additionalProperties.put(Constants.CORS, getCorsFeatureEnabled());
|
||||
}
|
||||
|
||||
if (additionalProperties.containsKey(Constants.COMPRESSION)) {
|
||||
setCompressionFeatureEnabled(convertPropertyToBooleanAndWriteBack(Constants.COMPRESSION));
|
||||
} else {
|
||||
additionalProperties.put(Constants.COMPRESSION, getCompressionFeatureEnabled());
|
||||
}
|
||||
|
||||
Boolean generateApis = additionalProperties.containsKey(CodegenConstants.GENERATE_APIS) && (Boolean)additionalProperties.get(CodegenConstants.GENERATE_APIS);
|
||||
String packageFolder = (sourceFolder + File.separator + packageName).replace(".", File.separator);
|
||||
String resourcesFolder = "src/main/resources"; // not sure this can be user configurable.
|
||||
|
||||
supportingFiles.add(new SupportingFile("README.mustache", "", "README.md"));
|
||||
supportingFiles.add(new SupportingFile("Dockerfile.mustache", "", "Dockerfile"));
|
||||
|
||||
supportingFiles.add(new SupportingFile("build.gradle.mustache", "", "build.gradle"));
|
||||
supportingFiles.add(new SupportingFile("settings.gradle.mustache", "", "settings.gradle"));
|
||||
supportingFiles.add(new SupportingFile("gradle.properties", "", "gradle.properties"));
|
||||
|
||||
supportingFiles.add(new SupportingFile("AppMain.kt.mustache", packageFolder, "AppMain.kt"));
|
||||
supportingFiles.add(new SupportingFile("Configuration.kt.mustache", packageFolder, "Configuration.kt"));
|
||||
|
||||
if (generateApis) {
|
||||
supportingFiles.add(new SupportingFile("Paths.kt.mustache", packageFolder, "Paths.kt"));
|
||||
}
|
||||
|
||||
supportingFiles.add(new SupportingFile("application.conf.mustache", resourcesFolder, "application.conf"));
|
||||
supportingFiles.add(new SupportingFile("logback.xml", resourcesFolder, "logback.xml"));
|
||||
|
||||
final String infrastructureFolder = (sourceFolder + File.separator + packageName + File.separator + "infrastructure").replace(".", File.separator);
|
||||
|
||||
supportingFiles.add(new SupportingFile("ApiKeyAuth.kt.mustache", infrastructureFolder, "ApiKeyAuth.kt"));
|
||||
|
||||
addMustacheLambdas(additionalProperties);
|
||||
}
|
||||
|
||||
private void addMustacheLambdas(Map<String, Object> objs) {
|
||||
|
||||
Map<String, Mustache.Lambda> lambdas = new ImmutableMap.Builder<String, Mustache.Lambda>()
|
||||
.put("lowercase", new LowercaseLambda().generator(this))
|
||||
.put("uppercase", new UppercaseLambda())
|
||||
.put("titlecase", new TitlecaseLambda())
|
||||
.put("camelcase", new CamelCaseLambda().generator(this))
|
||||
.put("indented", new IndentedLambda())
|
||||
.put("indented_8", new IndentedLambda(8, " "))
|
||||
.put("indented_12", new IndentedLambda(12, " "))
|
||||
.put("indented_16", new IndentedLambda(16, " "))
|
||||
.build();
|
||||
|
||||
if (objs.containsKey("lambda")) {
|
||||
LOGGER.warn("An property named 'lambda' already exists. Mustache lambdas renamed from 'lambda' to '_lambda'. " +
|
||||
"You'll likely need to use a custom template, " +
|
||||
"see https://github.com/swagger-api/swagger-codegen#modifying-the-client-library-format. ");
|
||||
objs.put("_lambda", lambdas);
|
||||
} else {
|
||||
objs.put("lambda", lambdas);
|
||||
}
|
||||
}
|
||||
|
||||
public static class Constants {
|
||||
public final static String KTOR = "ktor";
|
||||
public final static String AUTOMATIC_HEAD_REQUESTS = "featureAutoHead";
|
||||
public final static String AUTOMATIC_HEAD_REQUESTS_DESC = "Automatically provide responses to HEAD requests for existing routes that have the GET verb defined.";
|
||||
public final static String CONDITIONAL_HEADERS = "featureConditionalHeaders";
|
||||
public final static String CONDITIONAL_HEADERS_DESC = "Avoid sending content if client already has same content, by checking ETag or LastModified properties.";
|
||||
public final static String HSTS = "featureHSTS";
|
||||
public final static String HSTS_DESC = "Avoid sending content if client already has same content, by checking ETag or LastModified properties.";
|
||||
public final static String CORS = "featureCORS";
|
||||
public final static String CORS_DESC = "Ktor by default provides an interceptor for implementing proper support for Cross-Origin Resource Sharing (CORS). See enable-cors.org.";
|
||||
public final static String COMPRESSION = "featureCompression";
|
||||
public final static String COMPRESSION_DESC = "Adds ability to compress outgoing content using gzip, deflate or custom encoder and thus reduce size of the response.";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,542 @@
|
||||
package org.openapitools.codegen.languages;
|
||||
|
||||
import org.openapitools.codegen.*;
|
||||
import io.swagger.v3.oas.models.OpenAPI;
|
||||
import io.swagger.v3.oas.models.Operation;
|
||||
import io.swagger.v3.oas.models.media.*;
|
||||
import io.swagger.v3.oas.models.responses.ApiResponse;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.*;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class LuaClientCodegen extends DefaultCodegen implements CodegenConfig {
|
||||
static Logger LOGGER = LoggerFactory.getLogger(LuaClientCodegen.class);
|
||||
|
||||
protected String specFolder = "spec";
|
||||
protected String packageName = "swagger-client";
|
||||
protected String packageVersion = "1.0.0-1";
|
||||
protected String apiDocPath = "docs/";
|
||||
protected String modelDocPath = "docs/";
|
||||
protected String luaRocksFilename = "swagger-client-1.0.0-1.rockspec";
|
||||
|
||||
public CodegenType getTag() {
|
||||
return CodegenType.CLIENT;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return "lua";
|
||||
}
|
||||
|
||||
public String getHelp() {
|
||||
return "Generates a Lua client library (beta).";
|
||||
}
|
||||
|
||||
public LuaClientCodegen() {
|
||||
super();
|
||||
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";
|
||||
|
||||
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<String>(
|
||||
Arrays.asList(
|
||||
"map",
|
||||
"array")
|
||||
);
|
||||
|
||||
languageSpecificPrimitives = new HashSet<String>(
|
||||
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("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<String, String>();
|
||||
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: lowercase).")
|
||||
.defaultValue("swagger-client"));
|
||||
cliOptions.add(new CliOption(CodegenConstants.PACKAGE_VERSION, "Lua package version.")
|
||||
.defaultValue("1.0.0-1"));
|
||||
cliOptions.add(new CliOption(CodegenConstants.HIDE_GENERATION_TIMESTAMP, "hides the timestamp when files were generated")
|
||||
.defaultValue(Boolean.TRUE.toString()));
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processOpts() {
|
||||
super.processOpts();
|
||||
|
||||
// default HIDE_GENERATION_TIMESTAMP to true
|
||||
if (!additionalProperties.containsKey(CodegenConstants.HIDE_GENERATION_TIMESTAMP)) {
|
||||
additionalProperties.put(CodegenConstants.HIDE_GENERATION_TIMESTAMP, Boolean.TRUE.toString());
|
||||
} else {
|
||||
additionalProperties.put(CodegenConstants.HIDE_GENERATION_TIMESTAMP,
|
||||
Boolean.valueOf(additionalProperties().get(CodegenConstants.HIDE_GENERATION_TIMESTAMP).toString()));
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
public String modelFileFolder() {
|
||||
return outputFolder + File.separator + packageName + File.separator + "model" + File.separator;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toVarName(String name) {
|
||||
// replace - with _ e.g. created-at => created_at
|
||||
name = sanitizeName(name.replaceAll("-", "_"));
|
||||
|
||||
// if it's all uppper 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) {
|
||||
return toVarName(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toModelName(String name) {
|
||||
return toModelFilename(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toModelFilename(String 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(name + " (reserved word) cannot be used as model name. Renamed to " + ("model_" + name));
|
||||
name = "model_" + name; // e.g. return => ModelReturn (after camelize)
|
||||
}
|
||||
|
||||
// model name starts with number
|
||||
if (name.matches("^\\d.*")) {
|
||||
LOGGER.warn(name + " (model name starts with number) cannot be used as model name. Renamed to " + ("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 (p instanceof ArraySchema) {
|
||||
ArraySchema ap = (ArraySchema) p;
|
||||
Schema inner = ap.getItems();
|
||||
return getTypeDeclaration(inner);
|
||||
} else if (p instanceof MapSchema) {
|
||||
MapSchema mp = (MapSchema) p;
|
||||
Schema inner = (Schema) mp.getAdditionalProperties();
|
||||
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(operationId + " (reserved word) cannot be used as method name. Renamed to " + underscore("call_" + operationId));
|
||||
sanitizedOperationId = "call_" + sanitizedOperationId;
|
||||
}
|
||||
|
||||
return underscore(sanitizedOperationId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> postProcessOperations(Map<String, Object> objs) {
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, Object> objectMap = (Map<String, Object>) objs.get("operations");
|
||||
@SuppressWarnings("unchecked")
|
||||
List<CodegenOperation> operations = (List<CodegenOperation>) objectMap.get("operation");
|
||||
for (CodegenOperation op : operations) {
|
||||
|
||||
String[] items = op.path.split("/", -1);
|
||||
String luaPath = "";
|
||||
int pathParamIndex = 0;
|
||||
|
||||
for (int i = 0; i < items.length; ++i) {
|
||||
if (items[i].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();
|
||||
luaPath = luaPath + "/%s";
|
||||
pathParamIndex++;
|
||||
} else if (items[i].length() != 0) {
|
||||
luaPath = luaPath + "/" + items[i];
|
||||
} else {
|
||||
//luaPath = luaPath + "/";
|
||||
}
|
||||
}
|
||||
op.vendorExtensions.put("x-codegen-path", luaPath);
|
||||
}
|
||||
return objs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> postProcessModels(Map<String, Object> objs) {
|
||||
// remove model imports to avoid error
|
||||
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();
|
||||
}
|
||||
|
||||
// recursively add import for mapping one type to multiple imports
|
||||
List<Map<String, String>> recursiveImports = (List<Map<String, String>>) objs.get("imports");
|
||||
if (recursiveImports == null)
|
||||
return objs;
|
||||
|
||||
ListIterator<Map<String, String>> 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);
|
||||
}
|
||||
|
||||
public void setPackageName(String packageName) {
|
||||
this.packageName = packageName;
|
||||
}
|
||||
|
||||
public void setPackageVersion(String packageVersion) {
|
||||
this.packageVersion = packageVersion;
|
||||
}
|
||||
|
||||
public void setLuaRocksFilename(String luaRocksFilename) {
|
||||
this.luaRocksFilename = luaRocksFilename;
|
||||
}
|
||||
|
||||
@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<String, String> createMapping(String key, String value) {
|
||||
Map<String, String> customImport = new HashMap<String, String>();
|
||||
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();
|
||||
}
|
||||
|
||||
// string
|
||||
String enumName = sanitizeName(underscore(name).toUpperCase());
|
||||
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();
|
||||
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,422 @@
|
||||
package org.openapitools.codegen.languages;
|
||||
|
||||
import org.openapitools.codegen.CodegenConfig;
|
||||
import org.openapitools.codegen.CodegenParameter;
|
||||
import org.openapitools.codegen.CodegenType;
|
||||
import org.openapitools.codegen.DefaultCodegen;
|
||||
import org.openapitools.codegen.SupportingFile;
|
||||
import org.openapitools.codegen.CodegenConstants;
|
||||
import org.openapitools.codegen.CliOption;
|
||||
|
||||
import io.swagger.v3.oas.models.OpenAPI;
|
||||
import io.swagger.v3.oas.models.Operation;
|
||||
import io.swagger.v3.oas.models.media.*;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.regex.Matcher;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
public class PerlClientCodegen extends DefaultCodegen implements CodegenConfig {
|
||||
public static final String MODULE_NAME = "moduleName";
|
||||
public static final String MODULE_VERSION = "moduleVersion";
|
||||
protected String moduleName = "WWW::SwaggerClient";
|
||||
protected String modulePathPart = moduleName.replaceAll("::", Matcher.quoteReplacement(File.separator));
|
||||
protected String moduleVersion = "1.0.0";
|
||||
protected String apiDocPath = "docs/";
|
||||
protected String modelDocPath = "docs/";
|
||||
|
||||
protected static int emptyFunctionNameCounter = 0;
|
||||
|
||||
public PerlClientCodegen() {
|
||||
super();
|
||||
|
||||
// clear import mapping (from default generator) as perl does not use it
|
||||
// at the moment
|
||||
importMapping.clear();
|
||||
|
||||
modelPackage = File.separatorChar + "Object";
|
||||
outputFolder = "generated-code" + File.separatorChar + "perl";
|
||||
modelTemplateFiles.put("object.mustache", ".pm");
|
||||
apiTemplateFiles.put("api.mustache", ".pm");
|
||||
modelTestTemplateFiles.put("object_test.mustache", ".t");
|
||||
apiTestTemplateFiles.put("api_test.mustache", ".t");
|
||||
modelDocTemplateFiles.put("object_doc.mustache", ".md");
|
||||
apiDocTemplateFiles.put("api_doc.mustache", ".md");
|
||||
embeddedTemplateDir = templateDir = "perl";
|
||||
|
||||
|
||||
setReservedWordsLowerCase(
|
||||
Arrays.asList(
|
||||
"else", "lock", "qw",
|
||||
"__END__", "elsif", "lt", "qx",
|
||||
"__FILE__", "eq", "m", "s",
|
||||
"__LINE__", "exp", "ne", "sub",
|
||||
"__PACKAGE__", "for", "no", "tr",
|
||||
"and", "foreach", "or", "unless",
|
||||
"cmp", "ge", "package", "until",
|
||||
"continue", "gt", "q", "while",
|
||||
"CORE", "if", "qq", "xor",
|
||||
"do", "le", "qr", "y",
|
||||
"return"
|
||||
)
|
||||
);
|
||||
|
||||
languageSpecificPrimitives.clear();
|
||||
languageSpecificPrimitives.add("int");
|
||||
languageSpecificPrimitives.add("double");
|
||||
languageSpecificPrimitives.add("string");
|
||||
languageSpecificPrimitives.add("boolean");
|
||||
languageSpecificPrimitives.add("DateTime");
|
||||
languageSpecificPrimitives.add("ARRAY");
|
||||
languageSpecificPrimitives.add("HASH");
|
||||
languageSpecificPrimitives.add("object");
|
||||
|
||||
typeMapping.clear();
|
||||
typeMapping.put("integer", "int");
|
||||
typeMapping.put("long", "int");
|
||||
typeMapping.put("float", "double");
|
||||
typeMapping.put("double", "double");
|
||||
typeMapping.put("boolean", "boolean");
|
||||
typeMapping.put("string", "string");
|
||||
typeMapping.put("date", "DateTime");
|
||||
typeMapping.put("DateTime", "DateTime");
|
||||
typeMapping.put("password", "string");
|
||||
typeMapping.put("array", "ARRAY");
|
||||
typeMapping.put("map", "HASH");
|
||||
typeMapping.put("object", "object");
|
||||
//TODO binary should be mapped to byte array
|
||||
// mapped to String as a workaround
|
||||
typeMapping.put("binary", "string");
|
||||
typeMapping.put("ByteArray", "string");
|
||||
|
||||
cliOptions.clear();
|
||||
cliOptions.add(new CliOption(MODULE_NAME, "Perl module name (convention: CamelCase or Long::Module).").defaultValue("SwaggerClient"));
|
||||
cliOptions.add(new CliOption(MODULE_VERSION, "Perl module version.").defaultValue("1.0.0"));
|
||||
cliOptions.add(CliOption.newBoolean(CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG,
|
||||
CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG_DESC).defaultValue(Boolean.TRUE.toString()));
|
||||
cliOptions.add(CliOption.newBoolean(CodegenConstants.ENSURE_UNIQUE_PARAMS, CodegenConstants
|
||||
.ENSURE_UNIQUE_PARAMS_DESC).defaultValue(Boolean.TRUE.toString()));
|
||||
cliOptions.add(new CliOption(CodegenConstants.HIDE_GENERATION_TIMESTAMP, CodegenConstants.HIDE_GENERATION_TIMESTAMP_DESC)
|
||||
.defaultValue(Boolean.TRUE.toString()));
|
||||
|
||||
// option to change the order of form/body parameter
|
||||
cliOptions.add(CliOption.newBoolean(
|
||||
CodegenConstants.PREPEND_FORM_OR_BODY_PARAMETERS,
|
||||
CodegenConstants.PREPEND_FORM_OR_BODY_PARAMETERS_DESC)
|
||||
.defaultValue(Boolean.FALSE.toString()));
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void processOpts() {
|
||||
super.processOpts();
|
||||
|
||||
if (additionalProperties.containsKey(MODULE_VERSION)) {
|
||||
setModuleVersion((String) additionalProperties.get(MODULE_VERSION));
|
||||
} else {
|
||||
additionalProperties.put(MODULE_VERSION, moduleVersion);
|
||||
}
|
||||
|
||||
if (additionalProperties.containsKey(MODULE_NAME)) {
|
||||
setModuleName((String) additionalProperties.get(MODULE_NAME));
|
||||
setModulePathPart(moduleName.replaceAll("::", Matcher.quoteReplacement(File.separator)));
|
||||
} else {
|
||||
additionalProperties.put(MODULE_NAME, moduleName);
|
||||
}
|
||||
|
||||
// make api and model doc path available in mustache template
|
||||
additionalProperties.put("apiDocPath", apiDocPath);
|
||||
additionalProperties.put("modelDocPath", modelDocPath);
|
||||
|
||||
// default HIDE_GENERATION_TIMESTAMP to true
|
||||
if (!additionalProperties.containsKey(CodegenConstants.HIDE_GENERATION_TIMESTAMP)) {
|
||||
additionalProperties.put(CodegenConstants.HIDE_GENERATION_TIMESTAMP, Boolean.TRUE.toString());
|
||||
} else {
|
||||
additionalProperties.put(CodegenConstants.HIDE_GENERATION_TIMESTAMP,
|
||||
Boolean.valueOf(additionalProperties().get(CodegenConstants.HIDE_GENERATION_TIMESTAMP).toString()));
|
||||
}
|
||||
|
||||
supportingFiles.add(new SupportingFile("ApiClient.mustache", ("lib/" + modulePathPart).replace('/', File.separatorChar), "ApiClient.pm"));
|
||||
supportingFiles.add(new SupportingFile("Configuration.mustache", ("lib/" + modulePathPart).replace('/', File.separatorChar), "Configuration.pm"));
|
||||
supportingFiles.add(new SupportingFile("ApiFactory.mustache", ("lib/" + modulePathPart).replace('/', File.separatorChar), "ApiFactory.pm"));
|
||||
supportingFiles.add(new SupportingFile("Role.mustache", ("lib/" + modulePathPart).replace('/', File.separatorChar), "Role.pm"));
|
||||
supportingFiles.add(new SupportingFile("AutoDoc.mustache", ("lib/" + modulePathPart + "/Role").replace('/', File.separatorChar), "AutoDoc.pm"));
|
||||
supportingFiles.add(new SupportingFile("autodoc.script.mustache", "bin", "autodoc"));
|
||||
supportingFiles.add(new SupportingFile("README.mustache", "", "README.md"));
|
||||
supportingFiles.add(new SupportingFile("gitignore.mustache", "", ".gitignore"));
|
||||
supportingFiles.add(new SupportingFile("git_push.sh.mustache", "", "git_push.sh"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public CodegenType getTag() {
|
||||
return CodegenType.CLIENT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "perl";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHelp() {
|
||||
return "Generates a Perl client library.";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String escapeReservedWord(String name) {
|
||||
if (this.reservedWordsMappings().containsKey(name)) {
|
||||
return this.reservedWordsMappings().get(name);
|
||||
}
|
||||
return "_" + name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String apiFileFolder() {
|
||||
return (outputFolder + "/lib/" + modulePathPart + apiPackage()).replace('/', File.separatorChar);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String modelFileFolder() {
|
||||
return (outputFolder + "/lib/" + modulePathPart + modelPackage()).replace('/', File.separatorChar);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String apiTestFileFolder() {
|
||||
return (outputFolder + "/t").replace('/', File.separatorChar);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String modelTestFileFolder() {
|
||||
return (outputFolder + "/t").replace('/', File.separatorChar);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String apiDocFileFolder() {
|
||||
return (outputFolder + "/" + apiDocPath).replace('/', File.separatorChar);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String modelDocFileFolder() {
|
||||
return (outputFolder + "/" + modelDocPath).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 type;
|
||||
}
|
||||
} else {
|
||||
type = swaggerType;
|
||||
}
|
||||
if (type == null) {
|
||||
return null;
|
||||
}
|
||||
return toModelName(type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toDefaultValue(Schema p) {
|
||||
if (p instanceof StringSchema) {
|
||||
StringSchema dp = (StringSchema) p;
|
||||
if (dp.getDefault() != null) {
|
||||
return "'" + dp.getDefault() + "'";
|
||||
}
|
||||
} else if (p instanceof BooleanSchema) {
|
||||
BooleanSchema dp = (BooleanSchema) p;
|
||||
if (dp.getDefault() != null) {
|
||||
return dp.getDefault().toString();
|
||||
}
|
||||
} else if (p instanceof DateSchema) {
|
||||
// TODO
|
||||
} else if (p instanceof DateTimeSchema) {
|
||||
// TODO
|
||||
} else if (p instanceof NumberSchema) {
|
||||
NumberSchema dp = (NumberSchema) p;
|
||||
if (dp.getDefault() != null) {
|
||||
return dp.getDefault().toString();
|
||||
}
|
||||
} else if (p instanceof IntegerSchema) {
|
||||
IntegerSchema dp = (IntegerSchema) p;
|
||||
if (dp.getDefault() != null) {
|
||||
return dp.getDefault().toString();
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toVarName(String name) {
|
||||
// return the name in underscore style
|
||||
// PhoneNumber => phone_number
|
||||
name = underscore(name); // FIXME: a parameter should not be assigned. Also declare the methods parameters as 'final'.
|
||||
|
||||
// parameter name starting with number won't compile
|
||||
// need to escape it by appending _ at the beginning
|
||||
if (name.matches("^\\d.*")) {
|
||||
name = "_" + name;
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toParamName(String name) {
|
||||
// should be the same as variable name
|
||||
return toVarName(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toModelName(String name) {
|
||||
name = sanitizeName(name); // FIXME: a parameter should not be assigned. Also declare the methods parameters as 'final'.
|
||||
|
||||
// model name cannot use reserved keyword
|
||||
if (isReservedWord(name)) {
|
||||
LOGGER.warn(name + " (reserved word) cannot be used as model name. Renamed to " + camelize("model_" + name));
|
||||
name = "model_" + name;
|
||||
}
|
||||
|
||||
// model name starts with number
|
||||
if (name.matches("^\\d.*")) {
|
||||
LOGGER.warn(name + " (model name starts with number) cannot be used as model name. Renamed to " + camelize("model_" + name));
|
||||
name = "model_" + name; // e.g. 200Response => Model200Response (after camelize)
|
||||
}
|
||||
|
||||
// add prefix/suffic to model name
|
||||
if (!StringUtils.isEmpty(modelNamePrefix)) {
|
||||
name = modelNamePrefix + "_" + name;
|
||||
}
|
||||
|
||||
if (!StringUtils.isEmpty(modelNameSuffix)) {
|
||||
name = name + "_" + modelNameSuffix;
|
||||
}
|
||||
|
||||
// camelize the model name
|
||||
// phone_number => PhoneNumber
|
||||
return camelize(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toModelFilename(String name) {
|
||||
// should be the same as the model name
|
||||
return toModelName(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toModelTestFilename(String name) {
|
||||
return toModelFilename(name) + "Test";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toModelDocFilename(String name) {
|
||||
return toModelFilename(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toApiTestFilename(String name) {
|
||||
return toApiFilename(name) + "Test";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toApiDocFilename(String name) {
|
||||
return toApiFilename(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. phone_number_api.rb => PhoneNumberApi.rb
|
||||
return camelize(name) + "Api";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toApiName(String name) {
|
||||
if (name.length() == 0) {
|
||||
return "DefaultApi";
|
||||
}
|
||||
// e.g. phone_number_api => PhoneNumberApi
|
||||
return camelize(name) + "Api";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toOperationId(String operationId) {
|
||||
//rename to empty_function_name_1 (e.g.) if method name is empty
|
||||
if (StringUtils.isEmpty(operationId)) {
|
||||
operationId = underscore("empty_function_name_" + emptyFunctionNameCounter++);
|
||||
LOGGER.warn("Empty method name (operationId) found. Renamed to " + operationId);
|
||||
return operationId;
|
||||
}
|
||||
|
||||
// method name cannot use reserved keyword, e.g. return
|
||||
if (isReservedWord(operationId)) {
|
||||
LOGGER.warn(operationId + " (reserved word) cannot be used as method name. Renamed to " + underscore("call_" + operationId));
|
||||
return underscore("call_" + operationId);
|
||||
}
|
||||
|
||||
//return underscore(operationId).replaceAll("[^A-Za-z0-9_]", "");
|
||||
return underscore(sanitizeName(operationId));
|
||||
}
|
||||
|
||||
public void setModuleName(String moduleName) {
|
||||
this.moduleName = moduleName;
|
||||
}
|
||||
|
||||
public void setModulePathPart(String modulePathPart) {
|
||||
this.modulePathPart = modulePathPart;
|
||||
}
|
||||
|
||||
public void setModuleVersion(String moduleVersion) {
|
||||
this.moduleVersion = moduleVersion;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setParameterExampleValue(CodegenParameter p) {
|
||||
if (Boolean.TRUE.equals(p.isString) || Boolean.TRUE.equals(p.isBinary) ||
|
||||
Boolean.TRUE.equals(p.isByteArray) || Boolean.TRUE.equals(p.isFile)) {
|
||||
p.example = "'" + p.example + "'";
|
||||
} else if (Boolean.TRUE.equals(p.isBoolean)) {
|
||||
if (Boolean.parseBoolean(p.example))
|
||||
p.example = "1";
|
||||
else
|
||||
p.example = "0";
|
||||
} else if (Boolean.TRUE.equals(p.isDateTime) || Boolean.TRUE.equals(p.isDate)) {
|
||||
p.example = "DateTime->from_epoch(epoch => str2time('" + p.example + "'))";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String escapeQuotationMark(String input) {
|
||||
return input.replace("'", "");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String escapeUnsafeCharacters(String input) {
|
||||
// remove =end, =cut to avoid code injection
|
||||
return input.replace("=begin", "=_begin").replace("=end", "=_end").replace("=cut", "=_cut").replace("=pod", "=_pod");
|
||||
}
|
||||
}
|
||||
@@ -10,16 +10,15 @@ import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
|
||||
public class LumenServerCodegen extends AbstractPhpCodegen
|
||||
{
|
||||
@SuppressWarnings("hiding")
|
||||
public class PhpLumenServerCodegen extends AbstractPhpCodegen {
|
||||
@SuppressWarnings("hiding")
|
||||
protected String apiVersion = "1.0.0";
|
||||
|
||||
|
||||
/**
|
||||
* Configures the type of generator.
|
||||
*
|
||||
* @return the CodegenType for this generator
|
||||
* @see org.openapitools.codegen.CodegenType
|
||||
*
|
||||
* @return the CodegenType for this generator
|
||||
* @see org.openapitools.codegen.CodegenType
|
||||
*/
|
||||
public CodegenType getTag() {
|
||||
return CodegenType.SERVER;
|
||||
@@ -28,7 +27,7 @@ public class LumenServerCodegen extends AbstractPhpCodegen
|
||||
/**
|
||||
* Configures a friendly name for the generator. This will be used by the generator
|
||||
* to select the library with the -l flag.
|
||||
*
|
||||
*
|
||||
* @return the friendly name for the generator
|
||||
*/
|
||||
public String getName() {
|
||||
@@ -38,14 +37,14 @@ public class LumenServerCodegen extends AbstractPhpCodegen
|
||||
/**
|
||||
* Returns human-friendly help for the generator. Provide the consumer with help
|
||||
* tips, parameters here
|
||||
*
|
||||
*
|
||||
* @return A string value for the help message
|
||||
*/
|
||||
public String getHelp() {
|
||||
return "Generates a PHP Lumen server library.";
|
||||
}
|
||||
|
||||
public LumenServerCodegen() {
|
||||
public PhpLumenServerCodegen() {
|
||||
super();
|
||||
|
||||
embeddedTemplateDir = templateDir = "lumen";
|
||||
@@ -88,13 +87,13 @@ public class LumenServerCodegen extends AbstractPhpCodegen
|
||||
supportingFiles.add(new SupportingFile("app.php", packagePath + File.separator + srcBasePath + File.separator + "bootstrap", "app.php"));
|
||||
supportingFiles.add(new SupportingFile("index.php", packagePath + File.separator + srcBasePath + File.separator + "public", "index.php"));
|
||||
supportingFiles.add(new SupportingFile("User.php", packagePath + File.separator + srcBasePath + File.separator + "app", "User.php"));
|
||||
supportingFiles.add(new SupportingFile("Kernel.php", packagePath + File.separator + srcBasePath + File.separator + "app" + File.separator + "Console", "Kernel.php"));
|
||||
supportingFiles.add(new SupportingFile("Handler.php", packagePath + File.separator + srcBasePath + File.separator + "app" + File.separator + "Exceptions", "Handler.php"));
|
||||
supportingFiles.add(new SupportingFile("routes.mustache", packagePath + File.separator + srcBasePath + File.separator + "app" + File.separator + "Http", "routes.php"));
|
||||
|
||||
supportingFiles.add(new SupportingFile("Controller.php", packagePath + File.separator + srcBasePath + File.separator + "app" + File.separator + "Http" + File.separator + "Controllers" + File.separator, "Controller.php"));
|
||||
supportingFiles.add(new SupportingFile("Authenticate.php", packagePath + File.separator + srcBasePath + File.separator + "app" + File.separator + "Http" + File.separator + "Middleware" + File.separator, "Authenticate.php"));
|
||||
|
||||
supportingFiles.add(new SupportingFile("Kernel.php", packagePath + File.separator + srcBasePath + File.separator + "app" + File.separator + "Console", "Kernel.php"));
|
||||
supportingFiles.add(new SupportingFile("Handler.php", packagePath + File.separator + srcBasePath + File.separator + "app" + File.separator + "Exceptions", "Handler.php"));
|
||||
supportingFiles.add(new SupportingFile("routes.mustache", packagePath + File.separator + srcBasePath + File.separator + "app" + File.separator + "Http", "routes.php"));
|
||||
|
||||
supportingFiles.add(new SupportingFile("Controller.php", packagePath + File.separator + srcBasePath + File.separator + "app" + File.separator + "Http" + File.separator + "Controllers" + File.separator, "Controller.php"));
|
||||
supportingFiles.add(new SupportingFile("Authenticate.php", packagePath + File.separator + srcBasePath + File.separator + "app" + File.separator + "Http" + File.separator + "Middleware" + File.separator, "Authenticate.php"));
|
||||
|
||||
}
|
||||
|
||||
// override with any special post-processing
|
||||
@@ -113,7 +112,7 @@ public class LumenServerCodegen extends AbstractPhpCodegen
|
||||
throw new IllegalArgumentException("'.' (dot) is not supported by PHP Lumen. Please refer to https://github.com/swagger-api/swagger-codegen/issues/6897 for more info.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// sort the endpoints in ascending to avoid the route priority issure.
|
||||
// https://github.com/swagger-api/swagger-codegen/issues/2643
|
||||
Collections.sort(operations, new Comparator<CodegenOperation>() {
|
||||
@@ -20,13 +20,13 @@ import java.util.Map;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
public class SilexServerCodegen extends DefaultCodegen implements CodegenConfig {
|
||||
public class PhpSilexServerCodegen extends DefaultCodegen implements CodegenConfig {
|
||||
protected String invokerPackage;
|
||||
protected String groupId = "io.swagger";
|
||||
protected String artifactId = "swagger-server";
|
||||
protected String artifactVersion = "1.0.0";
|
||||
|
||||
public SilexServerCodegen() {
|
||||
public PhpSilexServerCodegen() {
|
||||
super();
|
||||
|
||||
invokerPackage = camelize("SwaggerServer");
|
||||
@@ -103,7 +103,9 @@ public class SilexServerCodegen extends DefaultCodegen implements CodegenConfig
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
public String getName()
|
||||
|
||||
{
|
||||
return "php-silex";
|
||||
}
|
||||
|
||||
@@ -113,13 +115,13 @@ public class SilexServerCodegen extends DefaultCodegen implements CodegenConfig
|
||||
}
|
||||
|
||||
@Override
|
||||
public String escapeReservedWord(String name) {
|
||||
if(this.reservedWordsMappings().containsKey(name)) {
|
||||
public String escapeReservedWord(String name) {
|
||||
if (this.reservedWordsMappings().containsKey(name)) {
|
||||
return this.reservedWordsMappings().get(name);
|
||||
}
|
||||
return "_" + name;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String apiFileFolder() {
|
||||
return (outputFolder + "/" + apiPackage()).replace('/', File.separatorChar);
|
||||
@@ -233,7 +235,7 @@ public class SilexServerCodegen extends DefaultCodegen implements CodegenConfig
|
||||
for (int i = 0; i < items.length; ++i) {
|
||||
if (items[i].matches("^\\{(.*)\\}$")) { // wrap in {}
|
||||
// camelize path variable
|
||||
items[i] = "{" + camelize(items[i].substring(1, items[i].length()-1), true) + "}";
|
||||
items[i] = "{" + camelize(items[i].substring(1, items[i].length() - 1), true) + "}";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.regex.Matcher;
|
||||
|
||||
public class SlimFrameworkServerCodegen extends DefaultCodegen implements CodegenConfig {
|
||||
public class PhpSlimServerCodegen extends DefaultCodegen implements CodegenConfig {
|
||||
protected String invokerPackage;
|
||||
protected String srcBasePath = "lib";
|
||||
protected String groupId = "io.swagger";
|
||||
@@ -29,7 +29,7 @@ public class SlimFrameworkServerCodegen extends DefaultCodegen implements Codege
|
||||
|
||||
private String variableNamingConvention = "camelCase";
|
||||
|
||||
public SlimFrameworkServerCodegen() {
|
||||
public PhpSlimServerCodegen() {
|
||||
super();
|
||||
|
||||
// clear import mapping (from default generator) as slim does not use it
|
||||
@@ -120,8 +120,8 @@ public class SlimFrameworkServerCodegen extends DefaultCodegen implements Codege
|
||||
}
|
||||
|
||||
@Override
|
||||
public String escapeReservedWord(String name) {
|
||||
if(this.reservedWordsMappings().containsKey(name)) {
|
||||
public String escapeReservedWord(String name) {
|
||||
if (this.reservedWordsMappings().containsKey(name)) {
|
||||
return this.reservedWordsMappings().get(name);
|
||||
}
|
||||
return "_" + name;
|
||||
@@ -199,11 +199,11 @@ public class SlimFrameworkServerCodegen extends DefaultCodegen implements Codege
|
||||
if ("camelCase".equals(variableNamingConvention)) {
|
||||
// return the name in camelCase style
|
||||
// phone_number => phoneNumber
|
||||
name = camelize(name, true);
|
||||
name = camelize(name, true);
|
||||
} else { // default to snake case
|
||||
// return the name in underscore style
|
||||
// PhoneNumber => phone_number
|
||||
name = underscore(name);
|
||||
name = underscore(name);
|
||||
}
|
||||
|
||||
// parameter name starting with number won't compile
|
||||
@@ -260,12 +260,12 @@ public class SlimFrameworkServerCodegen extends DefaultCodegen implements Codege
|
||||
}
|
||||
|
||||
return (getPackagePath() + File.separatorChar + basePath
|
||||
// Replace period, backslash, forward slash with file separator in package name
|
||||
+ packageName.replaceAll("[\\.\\\\/]", Matcher.quoteReplacement(File.separator))
|
||||
// Trim prefix file separators from package path
|
||||
.replaceAll(regFirstPathSeparator, ""))
|
||||
// Trim trailing file separators from the overall path
|
||||
.replaceAll(regLastPathSeparator+ "$", "");
|
||||
// Replace period, backslash, forward slash with file separator in package name
|
||||
+ packageName.replaceAll("[\\.\\\\/]", Matcher.quoteReplacement(File.separator))
|
||||
// Trim prefix file separators from package path
|
||||
.replaceAll(regFirstPathSeparator, ""))
|
||||
// Trim trailing file separators from the overall path
|
||||
.replaceAll(regLastPathSeparator + "$", "");
|
||||
}
|
||||
|
||||
public String getPackagePath() {
|
||||
@@ -0,0 +1,593 @@
|
||||
package org.openapitools.codegen.languages;
|
||||
|
||||
import org.openapitools.codegen.*;
|
||||
import io.swagger.v3.oas.models.media.*;
|
||||
import io.swagger.v3.oas.models.PathItem;
|
||||
import io.swagger.v3.oas.models.PathItem.HttpMethod;
|
||||
import io.swagger.v3.oas.models.*;
|
||||
import io.swagger.v3.oas.models.parameters.*;
|
||||
import io.swagger.v3.core.util.Yaml;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.*;
|
||||
|
||||
public class PhpSymfonyServerCodegen extends AbstractPhpCodegen implements CodegenConfig {
|
||||
@SuppressWarnings("hiding")
|
||||
static Logger LOGGER = LoggerFactory.getLogger(PhpSymfonyServerCodegen.class);
|
||||
|
||||
public static final String BUNDLE_NAME = "bundleName";
|
||||
public static final String COMPOSER_VENDOR_NAME = "composerVendorName";
|
||||
public static final String COMPOSER_PROJECT_NAME = "composerProjectName";
|
||||
public static final String PHP_LEGACY_SUPPORT = "phpLegacySupport";
|
||||
public static final Map<String, String> SYMFONY_EXCEPTIONS;
|
||||
protected String testsPackage;
|
||||
protected String apiTestsPackage;
|
||||
protected String modelTestsPackage;
|
||||
protected String composerVendorName = "swagger";
|
||||
protected String composerProjectName = "server-bundle";
|
||||
protected String testsDirName = "Tests";
|
||||
protected String bundleName;
|
||||
protected String bundleClassName;
|
||||
protected String bundleExtensionName;
|
||||
protected String bundleAlias;
|
||||
protected String controllerDirName = "Controller";
|
||||
protected String serviceDirName = "Service";
|
||||
protected String controllerPackage;
|
||||
protected String servicePackage;
|
||||
protected Boolean phpLegacySupport = Boolean.TRUE;
|
||||
|
||||
protected HashSet<String> typeHintable;
|
||||
|
||||
static {
|
||||
SYMFONY_EXCEPTIONS = new HashMap<>();
|
||||
SYMFONY_EXCEPTIONS.put("400", "Symfony\\Component\\HttpKernel\\Exception\\BadRequestHttpException");
|
||||
SYMFONY_EXCEPTIONS.put("401", "Symfony\\Component\\HttpKernel\\Exception\\UnauthorizedHttpException");
|
||||
SYMFONY_EXCEPTIONS.put("403", "Symfony\\Component\\HttpKernel\\Exception\\AccessDeniedHttpException");
|
||||
SYMFONY_EXCEPTIONS.put("404", "Symfony\\Component\\HttpKernel\\Exception\\NotFoundHttpException");
|
||||
SYMFONY_EXCEPTIONS.put("405", "Symfony\\Component\\HttpKernel\\Exception\\MethodNotAllowedHttpException");
|
||||
SYMFONY_EXCEPTIONS.put("406", "Symfony\\Component\\HttpKernel\\Exception\\NotAcceptableHttpException");
|
||||
SYMFONY_EXCEPTIONS.put("409", "Symfony\\Component\\HttpKernel\\Exception\\ConflictHttpException");
|
||||
SYMFONY_EXCEPTIONS.put("410", "Symfony\\Component\\HttpKernel\\Exception\\GoneHttpException");
|
||||
SYMFONY_EXCEPTIONS.put("411", "Symfony\\Component\\HttpKernel\\Exception\\LengthRequiredHttpException");
|
||||
SYMFONY_EXCEPTIONS.put("412", "Symfony\\Component\\HttpKernel\\Exception\\PreconditionFailedHttpException");
|
||||
SYMFONY_EXCEPTIONS.put("415", "Symfony\\Component\\HttpKernel\\Exception\\UnsupportedMediaTypeHttpException");
|
||||
SYMFONY_EXCEPTIONS.put("422", "Symfony\\Component\\HttpKernel\\Exception\\UnprocessableEntityHttpException");
|
||||
SYMFONY_EXCEPTIONS.put("428", "Symfony\\Component\\HttpKernel\\Exception\\PreconditionRequiredHttpException");
|
||||
SYMFONY_EXCEPTIONS.put("429", "Symfony\\Component\\HttpKernel\\Exception\\TooManyRequestsHttpException");
|
||||
SYMFONY_EXCEPTIONS.put("503", "Symfony\\Component\\HttpKernel\\Exception\\ServiceUnavailableHttpException");
|
||||
}
|
||||
|
||||
public PhpSymfonyServerCodegen() {
|
||||
super();
|
||||
|
||||
// clear import mapping (from default generator) as php does not use it
|
||||
// at the moment
|
||||
importMapping.clear();
|
||||
|
||||
supportsInheritance = true;
|
||||
srcBasePath = ".";
|
||||
setInvokerPackage("Swagger\\Server");
|
||||
setBundleName("SwaggerServer");
|
||||
packagePath = "SymfonyBundle-php";
|
||||
modelDirName = "Model";
|
||||
docsBasePath = "Resources" + File.separator + "docs";
|
||||
apiDocPath = docsBasePath + File.separator + apiDirName;
|
||||
modelDocPath = docsBasePath + File.separator + modelDirName;
|
||||
outputFolder = "generated-code" + File.separator + "php";
|
||||
apiTemplateFiles.put("api_controller.mustache", ".php");
|
||||
modelTestTemplateFiles.put("testing/model_test.mustache", ".php");
|
||||
apiTestTemplateFiles = new HashMap<String, String>();
|
||||
apiTestTemplateFiles.put("testing/api_test.mustache", ".php");
|
||||
embeddedTemplateDir = templateDir = "php-symfony";
|
||||
|
||||
setReservedWordsLowerCase(
|
||||
Arrays.asList(
|
||||
// local variables used in api methods (endpoints)
|
||||
"resourcePath", "httpBody", "queryParams", "headerParams",
|
||||
"formParams", "_header_accept", "_tempBody",
|
||||
|
||||
// PHP reserved words
|
||||
"__halt_compiler", "abstract", "and", "array", "as", "break", "callable", "case", "catch", "class", "clone", "const", "continue", "declare", "default", "die", "do", "echo", "else", "elseif", "empty", "enddeclare", "endfor", "endforeach", "endif", "endswitch", "endwhile", "eval", "exit", "extends", "final", "for", "foreach", "function", "global", "goto", "if", "implements", "include", "include_once", "instanceof", "insteadof", "interface", "isset", "list", "namespace", "new", "or", "print", "private", "protected", "public", "require", "require_once", "return", "static", "switch", "throw", "trait", "try", "unset", "use", "var", "while", "xor"
|
||||
)
|
||||
);
|
||||
|
||||
// ref: http://php.net/manual/en/language.types.intro.php
|
||||
languageSpecificPrimitives = new HashSet<String>(
|
||||
Arrays.asList(
|
||||
"bool",
|
||||
"int",
|
||||
"double",
|
||||
"float",
|
||||
"string",
|
||||
"object",
|
||||
"mixed",
|
||||
"number",
|
||||
"void",
|
||||
"byte",
|
||||
"array"
|
||||
)
|
||||
);
|
||||
|
||||
defaultIncludes = new HashSet<String>(
|
||||
Arrays.asList(
|
||||
"\\DateTime",
|
||||
"UploadedFile"
|
||||
)
|
||||
);
|
||||
|
||||
variableNamingConvention = "camelCase";
|
||||
|
||||
// provide primitives to mustache template
|
||||
List sortedLanguageSpecificPrimitives = new ArrayList(languageSpecificPrimitives);
|
||||
Collections.sort(sortedLanguageSpecificPrimitives);
|
||||
String primitives = "'" + StringUtils.join(sortedLanguageSpecificPrimitives, "', '") + "'";
|
||||
additionalProperties.put("primitives", primitives);
|
||||
|
||||
// ref: https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#data-types
|
||||
typeMapping = new HashMap<String, String>();
|
||||
typeMapping.put("integer", "int");
|
||||
typeMapping.put("long", "int");
|
||||
typeMapping.put("number", "float");
|
||||
typeMapping.put("float", "float");
|
||||
typeMapping.put("double", "double");
|
||||
typeMapping.put("string", "string");
|
||||
typeMapping.put("byte", "int");
|
||||
typeMapping.put("boolean", "bool");
|
||||
typeMapping.put("Date", "\\DateTime");
|
||||
typeMapping.put("DateTime", "\\DateTime");
|
||||
typeMapping.put("file", "UploadedFile");
|
||||
typeMapping.put("map", "array");
|
||||
typeMapping.put("array", "array");
|
||||
typeMapping.put("list", "array");
|
||||
typeMapping.put("object", "array");
|
||||
typeMapping.put("binary", "string");
|
||||
typeMapping.put("ByteArray", "string");
|
||||
typeMapping.put("UUID", "string");
|
||||
|
||||
cliOptions.add(new CliOption(COMPOSER_VENDOR_NAME, "The vendor name used in the composer package name. The template uses {{composerVendorName}}/{{composerProjectName}} for the composer package name. e.g. yaypets. IMPORTANT NOTE (2016/03): composerVendorName will be deprecated and replaced by gitUserId in the next swagger-codegen release"));
|
||||
cliOptions.add(new CliOption(BUNDLE_NAME, "The name of the Symfony bundle. The template uses {{bundleName}}"));
|
||||
cliOptions.add(new CliOption(COMPOSER_PROJECT_NAME, "The project name used in the composer package name. The template uses {{composerVendorName}}/{{composerProjectName}} for the composer package name. e.g. petstore-client. IMPORTANT NOTE (2016/03): composerProjectName will be deprecated and replaced by gitRepoId in the next swagger-codegen release"));
|
||||
cliOptions.add(new CliOption(CodegenConstants.HIDE_GENERATION_TIMESTAMP, "hides the timestamp when files were generated")
|
||||
.defaultValue(Boolean.TRUE.toString()));
|
||||
cliOptions.add(new CliOption(PHP_LEGACY_SUPPORT, "Should the generated code be compatible with PHP 5.x?").defaultValue(Boolean.TRUE.toString()));
|
||||
}
|
||||
|
||||
public String getBundleName() {
|
||||
return bundleName;
|
||||
}
|
||||
|
||||
public void setBundleName(String bundleName) {
|
||||
this.bundleName = bundleName;
|
||||
this.bundleClassName = bundleName + "Bundle";
|
||||
this.bundleExtensionName = bundleName + "Extension";
|
||||
this.bundleAlias = snakeCase(bundleName).replaceAll("([A-Z]+)", "\\_$1").toLowerCase();
|
||||
}
|
||||
|
||||
public void setPhpLegacySupport(Boolean support) {
|
||||
this.phpLegacySupport = support;
|
||||
}
|
||||
|
||||
public String controllerFileFolder() {
|
||||
return (outputFolder + File.separator + toPackagePath(controllerPackage, srcBasePath));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String escapeText(String input) {
|
||||
if (input != null) {
|
||||
// Trim the string to avoid leading and trailing spaces.
|
||||
return super.escapeText(input).trim();
|
||||
}
|
||||
return input;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CodegenType getTag() {
|
||||
return CodegenType.SERVER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "php-symfony";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHelp() {
|
||||
return "Generates a Symfony server bundle.";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String apiFilename(String templateName, String tag) {
|
||||
String suffix = apiTemplateFiles().get(templateName);
|
||||
if (templateName.equals("api_controller.mustache"))
|
||||
return controllerFileFolder() + '/' + toControllerName(tag) + suffix;
|
||||
|
||||
return apiFileFolder() + '/' + toApiFilename(tag) + suffix;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processOpts() {
|
||||
super.processOpts();
|
||||
|
||||
// default HIDE_GENERATION_TIMESTAMP to true
|
||||
if (!additionalProperties.containsKey(CodegenConstants.HIDE_GENERATION_TIMESTAMP)) {
|
||||
additionalProperties.put(CodegenConstants.HIDE_GENERATION_TIMESTAMP, Boolean.TRUE.toString());
|
||||
} else {
|
||||
additionalProperties.put(CodegenConstants.HIDE_GENERATION_TIMESTAMP,
|
||||
Boolean.valueOf(additionalProperties().get(CodegenConstants.HIDE_GENERATION_TIMESTAMP).toString()));
|
||||
}
|
||||
|
||||
if (additionalProperties.containsKey(BUNDLE_NAME)) {
|
||||
this.setBundleName((String) additionalProperties.get(BUNDLE_NAME));
|
||||
} else {
|
||||
additionalProperties.put(BUNDLE_NAME, bundleName);
|
||||
}
|
||||
|
||||
if (additionalProperties.containsKey(COMPOSER_PROJECT_NAME)) {
|
||||
this.setComposerProjectName((String) additionalProperties.get(COMPOSER_PROJECT_NAME));
|
||||
} else {
|
||||
additionalProperties.put(COMPOSER_PROJECT_NAME, composerProjectName);
|
||||
}
|
||||
|
||||
if (additionalProperties.containsKey(COMPOSER_VENDOR_NAME)) {
|
||||
this.setComposerVendorName((String) additionalProperties.get(COMPOSER_VENDOR_NAME));
|
||||
} else {
|
||||
additionalProperties.put(COMPOSER_VENDOR_NAME, composerVendorName);
|
||||
}
|
||||
|
||||
if (additionalProperties.containsKey(PHP_LEGACY_SUPPORT)) {
|
||||
this.setPhpLegacySupport(Boolean.valueOf((String) additionalProperties.get(PHP_LEGACY_SUPPORT)));
|
||||
} else {
|
||||
additionalProperties.put(PHP_LEGACY_SUPPORT, phpLegacySupport);
|
||||
}
|
||||
|
||||
additionalProperties.put("escapedInvokerPackage", invokerPackage.replace("\\", "\\\\"));
|
||||
additionalProperties.put("controllerPackage", controllerPackage);
|
||||
additionalProperties.put("servicePackage", servicePackage);
|
||||
additionalProperties.put("apiTestsPackage", apiTestsPackage);
|
||||
additionalProperties.put("modelTestsPackage", modelTestsPackage);
|
||||
|
||||
// make Symonfy-specific properties available
|
||||
additionalProperties.put("bundleName", bundleName);
|
||||
additionalProperties.put("bundleClassName", bundleClassName);
|
||||
additionalProperties.put("bundleExtensionName", bundleExtensionName);
|
||||
additionalProperties.put("bundleAlias", bundleAlias);
|
||||
|
||||
// make api and model src path available in mustache template
|
||||
additionalProperties.put("apiSrcPath", "." + File.separator + toSrcPath(apiPackage, srcBasePath));
|
||||
additionalProperties.put("modelSrcPath", "." + File.separator + toSrcPath(modelPackage, srcBasePath));
|
||||
additionalProperties.put("testsSrcPath", "." + File.separator + toSrcPath(testsPackage, srcBasePath));
|
||||
additionalProperties.put("apiTestsSrcPath", "." + File.separator + toSrcPath(apiTestsPackage, srcBasePath));
|
||||
additionalProperties.put("modelTestsSrcPath", "." + File.separator + toSrcPath(modelTestsPackage, srcBasePath));
|
||||
additionalProperties.put("apiTestPath", "." + File.separator + testsDirName + File.separator + apiDirName);
|
||||
additionalProperties.put("modelTestPath", "." + File.separator + testsDirName + File.separator + modelDirName);
|
||||
|
||||
// make api and model doc path available in mustache template
|
||||
additionalProperties.put("apiDocPath", apiDocPath);
|
||||
additionalProperties.put("modelDocPath", modelDocPath);
|
||||
|
||||
// make test path available in mustache template
|
||||
additionalProperties.put("testsDirName", testsDirName);
|
||||
|
||||
final String configDir = getPackagePath() + File.separator + "Resources" + File.separator + "config";
|
||||
final String dependencyInjectionDir = getPackagePath() + File.separator + "DependencyInjection";
|
||||
|
||||
supportingFiles.add(new SupportingFile("Controller.mustache", toPackagePath(controllerPackage, srcBasePath), "Controller.php"));
|
||||
supportingFiles.add(new SupportingFile("Bundle.mustache", getPackagePath(), bundleClassName + ".php"));
|
||||
supportingFiles.add(new SupportingFile("Extension.mustache", dependencyInjectionDir, bundleExtensionName + ".php"));
|
||||
supportingFiles.add(new SupportingFile("ApiPass.mustache", dependencyInjectionDir + File.separator + "Compiler", bundleName + "ApiPass.php"));
|
||||
supportingFiles.add(new SupportingFile("ApiServer.mustache", toPackagePath(apiPackage, srcBasePath), "ApiServer.php"));
|
||||
|
||||
// Serialization components
|
||||
supportingFiles.add(new SupportingFile("serialization/SerializerInterface.mustache", toPackagePath(servicePackage, srcBasePath), "SerializerInterface.php"));
|
||||
supportingFiles.add(new SupportingFile("serialization/JmsSerializer.mustache", toPackagePath(servicePackage, srcBasePath), "JmsSerializer.php"));
|
||||
supportingFiles.add(new SupportingFile("serialization/StrictJsonDeserializationVisitor.mustache", toPackagePath(servicePackage, srcBasePath), "StrictJsonDeserializationVisitor.php"));
|
||||
supportingFiles.add(new SupportingFile("serialization/TypeMismatchException.mustache", toPackagePath(servicePackage, srcBasePath), "TypeMismatchException.php"));
|
||||
// Validation components
|
||||
supportingFiles.add(new SupportingFile("validation/ValidatorInterface.mustache", toPackagePath(servicePackage, srcBasePath), "ValidatorInterface.php"));
|
||||
supportingFiles.add(new SupportingFile("validation/SymfonyValidator.mustache", toPackagePath(servicePackage, srcBasePath), "SymfonyValidator.php"));
|
||||
|
||||
// Testing components
|
||||
supportingFiles.add(new SupportingFile("testing/phpunit.xml.mustache", getPackagePath(), "phpunit.xml.dist"));
|
||||
supportingFiles.add(new SupportingFile("testing/pom.xml", getPackagePath(), "pom.xml"));
|
||||
supportingFiles.add(new SupportingFile("testing/AppKernel.php", toPackagePath(testsPackage, srcBasePath), "AppKernel.php"));
|
||||
supportingFiles.add(new SupportingFile("testing/test_config.yml", toPackagePath(testsPackage, srcBasePath), "test_config.yml"));
|
||||
|
||||
supportingFiles.add(new SupportingFile("routing.mustache", configDir, "routing.yml"));
|
||||
supportingFiles.add(new SupportingFile("services.mustache", configDir, "services.yml"));
|
||||
supportingFiles.add(new SupportingFile("composer.mustache", getPackagePath(), "composer.json"));
|
||||
supportingFiles.add(new SupportingFile("autoload.mustache", getPackagePath(), "autoload.php"));
|
||||
supportingFiles.add(new SupportingFile("README.mustache", getPackagePath(), "README.md"));
|
||||
|
||||
supportingFiles.add(new SupportingFile(".travis.yml", getPackagePath(), ".travis.yml"));
|
||||
supportingFiles.add(new SupportingFile(".php_cs", getPackagePath(), ".php_cs"));
|
||||
supportingFiles.add(new SupportingFile("git_push.sh.mustache", getPackagePath(), "git_push.sh"));
|
||||
|
||||
// Type-hintable primitive types
|
||||
// ref: http://php.net/manual/en/functions.arguments.php#functions.arguments.type-declaration
|
||||
if (phpLegacySupport) {
|
||||
typeHintable = new HashSet<String>(
|
||||
Arrays.asList(
|
||||
"array"
|
||||
)
|
||||
);
|
||||
} else {
|
||||
typeHintable = new HashSet<String>(
|
||||
Arrays.asList(
|
||||
"array",
|
||||
"bool",
|
||||
"float",
|
||||
"int",
|
||||
"string"
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> postProcessOperations(Map<String, Object> objs) {
|
||||
objs = super.postProcessOperations(objs);
|
||||
|
||||
Map<String, Object> operations = (Map<String, Object>) objs.get("operations");
|
||||
operations.put("controllerName", toControllerName((String) operations.get("pathPrefix")));
|
||||
operations.put("symfonyService", toSymfonyService((String) operations.get("pathPrefix")));
|
||||
|
||||
HashSet<CodegenSecurity> authMethods = new HashSet<>();
|
||||
List<CodegenOperation> operationList = (List<CodegenOperation>) operations.get("operation");
|
||||
|
||||
for (CodegenOperation op : operationList) {
|
||||
// Loop through all input parameters to determine, whether we have to import something to
|
||||
// make the input type available.
|
||||
for (CodegenParameter param : op.allParams) {
|
||||
// Determine if the parameter type is supported as a type hint and make it available
|
||||
// to the templating engine
|
||||
String typeHint = getTypeHint(param.dataType);
|
||||
if (!typeHint.isEmpty()) {
|
||||
param.vendorExtensions.put("x-parameterType", typeHint);
|
||||
}
|
||||
|
||||
if (param.isContainer) {
|
||||
param.vendorExtensions.put("x-parameterType", getTypeHint(param.dataType + "[]"));
|
||||
}
|
||||
|
||||
// Create a variable to display the correct data type in comments for interfaces
|
||||
param.vendorExtensions.put("x-commentType", param.dataType);
|
||||
if (param.isContainer) {
|
||||
param.vendorExtensions.put("x-commentType", param.dataType + "[]");
|
||||
}
|
||||
|
||||
// Quote default values for strings
|
||||
// @todo: The default values for headers, forms and query params are handled
|
||||
// in DefaultCodegen fromParameter with no real possibility to override
|
||||
// the functionality. Thus we are handling quoting of string values here
|
||||
if (param.dataType.equals("string") && param.defaultValue != null && !param.defaultValue.isEmpty()) {
|
||||
param.defaultValue = "'" + param.defaultValue + "'";
|
||||
}
|
||||
}
|
||||
|
||||
// Create a variable to display the correct return type in comments for interfaces
|
||||
if (op.returnType != null) {
|
||||
op.vendorExtensions.put("x-commentType", op.returnType);
|
||||
if (!op.returnTypeIsPrimitive) {
|
||||
op.vendorExtensions.put("x-commentType", op.returnType + "[]");
|
||||
}
|
||||
} else {
|
||||
op.vendorExtensions.put("x-commentType", "void");
|
||||
}
|
||||
|
||||
// Add operation's authentication methods to whole interface
|
||||
if (op.authMethods != null) {
|
||||
authMethods.addAll(op.authMethods);
|
||||
}
|
||||
}
|
||||
|
||||
operations.put("authMethods", authMethods);
|
||||
|
||||
return objs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> postProcessModels(Map<String, Object> objs) {
|
||||
objs = super.postProcessModels(objs);
|
||||
|
||||
ArrayList<Object> modelsArray = (ArrayList<Object>) objs.get("models");
|
||||
Map<String, Object> models = (Map<String, Object>) modelsArray.get(0);
|
||||
CodegenModel model = (CodegenModel) models.get("model");
|
||||
|
||||
// Simplify model var type
|
||||
for (CodegenProperty var : model.vars) {
|
||||
if (var.datatype != null) {
|
||||
// Determine if the parameter type is supported as a type hint and make it available
|
||||
// to the templating engine
|
||||
String typeHint = getTypeHint(var.datatype);
|
||||
if (!typeHint.isEmpty()) {
|
||||
var.vendorExtensions.put("x-parameterType", typeHint);
|
||||
}
|
||||
|
||||
// Create a variable to display the correct data type in comments for models
|
||||
var.vendorExtensions.put("x-commentType", var.datatype);
|
||||
if (var.isContainer) {
|
||||
var.vendorExtensions.put("x-commentType", var.datatype + "[]");
|
||||
}
|
||||
|
||||
if (var.isBoolean) {
|
||||
var.getter = var.getter.replaceAll("^get", "is");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return objs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String escapeReservedWord(String name) {
|
||||
if (this.reservedWordsMappings().containsKey(name)) {
|
||||
return this.reservedWordsMappings().get(name);
|
||||
}
|
||||
return "_" + name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String apiTestFileFolder() {
|
||||
return (outputFolder + File.separator + toPackagePath(apiTestsPackage, srcBasePath));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String modelTestFileFolder() {
|
||||
return (outputFolder + File.separator + toPackagePath(modelTestsPackage, srcBasePath));
|
||||
}
|
||||
|
||||
public void setComposerVendorName(String composerVendorName) {
|
||||
this.composerVendorName = composerVendorName;
|
||||
}
|
||||
|
||||
public void setComposerProjectName(String composerProjectName) {
|
||||
this.composerProjectName = composerProjectName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setInvokerPackage(String invokerPackage) {
|
||||
super.setInvokerPackage(invokerPackage);
|
||||
apiPackage = invokerPackage + "\\" + apiDirName;
|
||||
modelPackage = invokerPackage + "\\" + modelDirName;
|
||||
testsPackage = invokerPackage + "\\" + testsDirName;
|
||||
apiTestsPackage = testsPackage + "\\" + apiDirName;
|
||||
modelTestsPackage = testsPackage + "\\" + modelDirName;
|
||||
controllerPackage = invokerPackage + "\\" + controllerDirName;
|
||||
servicePackage = invokerPackage + "\\" + serviceDirName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTypeDeclaration(Schema p) {
|
||||
if (p instanceof ArraySchema) {
|
||||
ArraySchema ap = (ArraySchema) p;
|
||||
Schema inner = ap.getItems();
|
||||
return getTypeDeclaration(inner);
|
||||
}
|
||||
|
||||
if (p instanceof MapSchema) {
|
||||
MapSchema mp = (MapSchema) p;
|
||||
Schema inner = (Schema) mp.getAdditionalProperties();
|
||||
return getTypeDeclaration(inner);
|
||||
}
|
||||
|
||||
if (!StringUtils.isEmpty(p.get$ref())) {
|
||||
return getTypeDeclaration(getPropertyTypeDeclaration(p));
|
||||
}
|
||||
|
||||
return getPropertyTypeDeclaration(p);
|
||||
}
|
||||
|
||||
/**
|
||||
* Output the type declaration of the property
|
||||
*
|
||||
* @param p Swagger Schema object
|
||||
* @return a string presentation of the property type
|
||||
*/
|
||||
public String getPropertyTypeDeclaration(Schema p) {
|
||||
String openAPIType = getSchemaType(p);
|
||||
if (typeMapping.containsKey(openAPIType)) {
|
||||
return typeMapping.get(openAPIType);
|
||||
}
|
||||
return openAPIType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTypeDeclaration(String name) {
|
||||
if (!languageSpecificPrimitives.contains(name)) {
|
||||
return modelPackage + "\\" + name;
|
||||
}
|
||||
return super.getTypeDeclaration(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the fully-qualified "Model" name for import
|
||||
*
|
||||
* @param name the name of the "Model"
|
||||
* @return the fully-qualified "Model" name for import
|
||||
*/
|
||||
@Override
|
||||
public String toModelImport(String name) {
|
||||
if ("".equals(modelPackage())) {
|
||||
return name;
|
||||
} else {
|
||||
return modelPackage() + "\\" + name;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toEnumValue(String value, String datatype) {
|
||||
if ("int".equals(datatype) || "double".equals(datatype) || "float".equals(datatype)) {
|
||||
return value;
|
||||
} else {
|
||||
return "\"" + escapeText(value) + "\"";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the regular expression/JSON schema pattern (http://json-schema.org/latest/json-schema-validation.html#anchor33)
|
||||
*
|
||||
* @param pattern the pattern (regular expression)
|
||||
* @return properly-escaped pattern
|
||||
*/
|
||||
@Override
|
||||
public String toRegularExpression(String pattern) {
|
||||
return escapeText(pattern);
|
||||
}
|
||||
|
||||
public String toApiName(String name) {
|
||||
if (name.isEmpty()) {
|
||||
return "DefaultApiInterface";
|
||||
}
|
||||
return camelize(name, false) + "ApiInterface";
|
||||
}
|
||||
|
||||
protected String toControllerName(String name) {
|
||||
if (name.isEmpty()) {
|
||||
return "DefaultController";
|
||||
}
|
||||
return camelize(name, false) + "Controller";
|
||||
}
|
||||
|
||||
protected String toSymfonyService(String name) {
|
||||
String prefix = composerVendorName + ".api.";
|
||||
if (name.isEmpty()) {
|
||||
return prefix + "default";
|
||||
}
|
||||
|
||||
return prefix + name;
|
||||
}
|
||||
|
||||
protected String getTypeHint(String type) {
|
||||
// Type hint array types
|
||||
if (type.endsWith("[]")) {
|
||||
return "array";
|
||||
}
|
||||
|
||||
// Check if the type is a native type that is type hintable in PHP
|
||||
if (typeHintable.contains(type)) {
|
||||
return type;
|
||||
}
|
||||
|
||||
// Default includes are referenced by their fully-qualified class name (including namespace)
|
||||
if (defaultIncludes.contains(type)) {
|
||||
return type;
|
||||
}
|
||||
|
||||
// Model classes are assumed to be imported and we reference them by their class name
|
||||
if (isModelClass(type)) {
|
||||
// This parameter is an instance of a model
|
||||
return extractSimpleName(type);
|
||||
}
|
||||
|
||||
// PHP does not support type hinting for this parameter data type
|
||||
return "";
|
||||
}
|
||||
|
||||
protected Boolean isModelClass(String type) {
|
||||
return Boolean.valueOf(type.contains(modelPackage()));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,336 @@
|
||||
package org.openapitools.codegen.languages;
|
||||
|
||||
import io.swagger.v3.oas.models.PathItem;
|
||||
import org.openapitools.codegen.*;
|
||||
|
||||
import io.swagger.v3.oas.models.PathItem.HttpMethod;
|
||||
import io.swagger.v3.oas.models.OpenAPI;
|
||||
import io.swagger.v3.oas.models.Operation;
|
||||
import io.swagger.v3.oas.models.media.*;
|
||||
import io.swagger.v3.core.util.Yaml;
|
||||
import io.swagger.v3.oas.models.parameters.*;
|
||||
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class PhpZendExpressivePathHandlerServerCodegen extends AbstractPhpCodegen {
|
||||
|
||||
public static final String VEN_FROM_QUERY = "internal.ze-ph.fromQuery";
|
||||
public static final String VEN_COLLECTION_FORMAT = "internal.ze-ph.collectionFormat";
|
||||
public static final String VEN_QUERY_DATA_TYPE = "internal.ze-ph.queryDataType";
|
||||
public static final String VEN_HAS_QUERY_DATA = "internal.ze-ph.hasQueryData";
|
||||
|
||||
@Override
|
||||
public CodegenType getTag() {
|
||||
return CodegenType.SERVER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "php-ze-ph";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHelp() {
|
||||
return "Generates PHP server stub using Zend Expressive ( https://zendframework.github.io/zend-expressive ) and Path Handler ( https://github.com/Articus/PathHandler ).";
|
||||
}
|
||||
|
||||
public PhpZendExpressivePathHandlerServerCodegen() {
|
||||
super();
|
||||
//no point to use double - http://php.net/manual/en/language.types.float.php , especially because of PHP 7+ float type declaration
|
||||
typeMapping.put("double", "float");
|
||||
|
||||
embeddedTemplateDir = templateDir = "ze-ph";
|
||||
invokerPackage = "App";
|
||||
packagePath = "";
|
||||
srcBasePath = "src" + File.separator + "App";
|
||||
apiDirName = "Handler";
|
||||
modelDirName = "DTO";
|
||||
apiPackage = invokerPackage + "\\" + apiDirName;
|
||||
modelPackage = invokerPackage + "\\" + modelDirName;
|
||||
|
||||
apiTestTemplateFiles.clear();
|
||||
modelTestTemplateFiles.clear();
|
||||
apiDocTemplateFiles.clear();
|
||||
modelDocTemplateFiles.clear();
|
||||
|
||||
supportingFiles.add(new SupportingFile("README.md.mustache", packagePath, "README.md"));
|
||||
supportingFiles.add(new SupportingFile("composer.json.mustache", packagePath, "composer.json"));
|
||||
supportingFiles.add(new SupportingFile("index.php", packagePath + File.separator + "public", "index.php"));
|
||||
supportingFiles.add(new SupportingFile("container.php", packagePath + File.separator + "application", "container.php"));
|
||||
supportingFiles.add(new SupportingFile("config.yml", packagePath + File.separator + "application", "config.yml"));
|
||||
supportingFiles.add(new SupportingFile("app.yml.mustache", packagePath + File.separator + "application" + File.separator + "config", "app.yml"));
|
||||
supportingFiles.add(new SupportingFile("path_handler.yml.mustache", packagePath + File.separator + "application" + File.separator + "config", "path_handler.yml"));
|
||||
supportingFiles.add(new SupportingFile("data_transfer.yml.mustache", packagePath + File.separator + "application" + File.separator + "config", "data_transfer.yml"));
|
||||
supportingFiles.add(new SupportingFile("ErrorMiddleware.php.mustache", packagePath + File.separator + srcBasePath, "ErrorMiddleware.php"));
|
||||
supportingFiles.add(new SupportingFile("Date.php.mustache", packagePath + File.separator + srcBasePath + File.separator + "Strategy", "Date.php"));
|
||||
supportingFiles.add(new SupportingFile("DateTime.php.mustache", packagePath + File.separator + srcBasePath + File.separator + "Strategy", "DateTime.php"));
|
||||
supportingFiles.add(new SupportingFile("QueryParameter.php.mustache", packagePath + File.separator + srcBasePath + File.separator + "Strategy", "QueryParameter.php"));
|
||||
supportingFiles.add(new SupportingFile("QueryParameterArray.php.mustache", packagePath + File.separator + srcBasePath + File.separator + "Strategy", "QueryParameterArray.php"));
|
||||
supportingFiles.add(new SupportingFile("Type.php.mustache", packagePath + File.separator + srcBasePath + File.separator + "Validator", "Type.php"));
|
||||
supportingFiles.add(new SupportingFile("QueryParameterType.php.mustache", packagePath + File.separator + srcBasePath + File.separator + "Validator", "QueryParameterType.php"));
|
||||
supportingFiles.add(new SupportingFile("QueryParameterArrayType.php.mustache", packagePath + File.separator + srcBasePath + File.separator + "Validator", "QueryParameterArrayType.php"));
|
||||
|
||||
additionalProperties.put(CodegenConstants.ARTIFACT_VERSION, "1.0.0");
|
||||
}
|
||||
|
||||
/**
|
||||
* Add operation to group
|
||||
* Override of default grouping - group by resource path, not tag
|
||||
*
|
||||
* @param tag name of the tag
|
||||
* @param resourcePath path of the resource
|
||||
* @param operation Swagger Operation object
|
||||
* @param co Codegen Operation object
|
||||
* @param operations map of Codegen operations
|
||||
*/
|
||||
@Override
|
||||
public void addOperationToGroup(String tag, String resourcePath, Operation operation, CodegenOperation co, Map<String, List<CodegenOperation>> operations) {
|
||||
List<CodegenOperation> opList = operations.get(resourcePath);
|
||||
if (opList == null) {
|
||||
opList = new ArrayList<CodegenOperation>();
|
||||
operations.put(resourcePath, opList);
|
||||
}
|
||||
//ignore duplicate operation ids - that means that operation has several tags
|
||||
int counter = 0;
|
||||
for (CodegenOperation op : opList) {
|
||||
if (co.operationId.equals(op.operationId)) {
|
||||
counter++;
|
||||
}
|
||||
}
|
||||
if (counter == 0) {
|
||||
co.operationIdLowerCase = co.operationId.toLowerCase();
|
||||
opList.add(co);
|
||||
co.baseName = tag;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the file name of the Api Test
|
||||
*
|
||||
* @param name the file name of the Api
|
||||
* @return the file name of the Api
|
||||
*/
|
||||
@Override
|
||||
public String toApiFilename(String name) {
|
||||
return toApiName(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Output the API (class) name (capitalized) ending with "Api"
|
||||
* Return DefaultApi if name is empty
|
||||
*
|
||||
* @param name the name of the Api
|
||||
* @return capitalized Api name ending with "Api"
|
||||
*/
|
||||
@Override
|
||||
public String toApiName(String name) {
|
||||
//Remove }
|
||||
name = name.replaceAll("[\\}]", "");
|
||||
return super.toModelName(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate additional model definitions from query parameters
|
||||
*
|
||||
* @param openAPI OpenAPI object
|
||||
*/
|
||||
@Override
|
||||
public void preprocessOpenAPI(OpenAPI openAPI) {
|
||||
super.preprocessOpenAPI(openAPI);
|
||||
|
||||
Map<String, PathItem> paths = openAPI.getPaths();
|
||||
if (paths != null) {
|
||||
for (String pathname : paths.keySet()) {
|
||||
PathItem path = paths.get(pathname);
|
||||
Map<HttpMethod, Operation> operationMap = path.readOperationsMap();
|
||||
if (operationMap != null) {
|
||||
for (HttpMethod method : operationMap.keySet()) {
|
||||
Operation operation = operationMap.get(method);
|
||||
Map<String, Schema> schemas = new HashMap<>();
|
||||
if (operation == null || operation.getParameters() == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (Parameter parameter : operation.getParameters()) {
|
||||
Schema schema = convertParameterToSchema(parameter);
|
||||
if (schema != null) {
|
||||
schemas.put(schema.getName(), schema);
|
||||
}
|
||||
}
|
||||
|
||||
if (!schemas.isEmpty()) {
|
||||
Schema model = new Schema();
|
||||
String operationId = getOrGenerateOperationId(operation, pathname, method.name());
|
||||
model.setDescription("Query parameters for " + operationId);
|
||||
model.setProperties(schemas);
|
||||
model.getExtensions().put(VEN_FROM_QUERY, Boolean.TRUE);
|
||||
String definitionName = generateUniqueDefinitionName(operationId + "QueryData", openAPI);
|
||||
openAPI.getComponents().addSchemas(definitionName, model);
|
||||
String definitionModel = "\\" + modelPackage + "\\" + toModelName(definitionName);
|
||||
operation.getExtensions().put(VEN_QUERY_DATA_TYPE, definitionModel);
|
||||
operation.getExtensions().put(VEN_HAS_QUERY_DATA, Boolean.TRUE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected Schema convertParameterToSchema(Parameter parameter) {
|
||||
Schema property = null;
|
||||
if (parameter instanceof QueryParameter) {
|
||||
QueryParameter queryParameter = (QueryParameter) parameter;
|
||||
// array
|
||||
if (queryParameter.getSchema() instanceof ArraySchema) {
|
||||
Schema inner = ((ArraySchema) queryParameter.getSchema()).getItems();
|
||||
ArraySchema arraySchema = new ArraySchema();
|
||||
arraySchema.setMinItems(queryParameter.getSchema().getMinItems());
|
||||
arraySchema.setMaxItems(queryParameter.getSchema().getMaxItems());
|
||||
arraySchema.setItems(inner);
|
||||
String collectionFormat = getCollectionFormat(queryParameter);
|
||||
if (collectionFormat == null) {
|
||||
collectionFormat = "csv";
|
||||
}
|
||||
arraySchema.getExtensions().put(VEN_COLLECTION_FORMAT, collectionFormat);
|
||||
property = arraySchema;
|
||||
} else { // non-array e.g. string, integer
|
||||
switch (queryParameter.getSchema().getType()) {
|
||||
case "string":
|
||||
StringSchema stringSchema = new StringSchema();
|
||||
stringSchema.setMinLength(queryParameter.getSchema().getMinLength());
|
||||
stringSchema.setMaxLength(queryParameter.getSchema().getMaxLength());
|
||||
stringSchema.setPattern(queryParameter.getSchema().getPattern());
|
||||
stringSchema.setEnum(queryParameter.getSchema().getEnum());
|
||||
property = stringSchema;
|
||||
break;
|
||||
case "integer":
|
||||
IntegerSchema integerSchema = new IntegerSchema();
|
||||
integerSchema.setMinimum(queryParameter.getSchema().getMinimum());
|
||||
integerSchema.setMaximum(queryParameter.getSchema().getMaximum());
|
||||
property = integerSchema;
|
||||
break;
|
||||
case "number":
|
||||
NumberSchema floatSchema = new NumberSchema();
|
||||
floatSchema.setMinimum(queryParameter.getSchema().getMinimum());
|
||||
floatSchema.setMaximum(queryParameter.getSchema().getMaximum());
|
||||
property = floatSchema;
|
||||
break;
|
||||
case "boolean":
|
||||
property = new BooleanSchema();
|
||||
break;
|
||||
case "date":
|
||||
property = new DateSchema();
|
||||
break;
|
||||
case "date-time":
|
||||
property = new DateTimeSchema();
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (property != null) {
|
||||
property.setName(queryParameter.getName());
|
||||
property.setDescription(queryParameter.getDescription());
|
||||
if (Boolean.TRUE.equals(queryParameter.getRequired())) {
|
||||
List<String> required = new ArrayList<String>();
|
||||
required.add(queryParameter.getName());
|
||||
}
|
||||
|
||||
property.getExtensions().put(VEN_FROM_QUERY, Boolean.TRUE);
|
||||
}
|
||||
}
|
||||
return property;
|
||||
}
|
||||
|
||||
protected String generateUniqueDefinitionName(String name, OpenAPI openAPI) {
|
||||
String result = name;
|
||||
if (openAPI.getComponents().getSchemas() != null) {
|
||||
int count = 1;
|
||||
while (openAPI.getComponents().getSchemas().containsKey(result)) {
|
||||
result = name + "_" + count;
|
||||
count += 1;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> postProcessOperations(Map<String, Object> objs) {
|
||||
objs = super.postProcessOperations(objs);
|
||||
Map<String, Object> operations = (Map<String, Object>) objs.get("operations");
|
||||
List<CodegenOperation> operationList = (List<CodegenOperation>) operations.get("operation");
|
||||
String interfaceToImplement;
|
||||
StringBuilder interfacesToImplement = new StringBuilder();
|
||||
String classMethod;
|
||||
String pathPattern = null;
|
||||
for (CodegenOperation op : operationList) {
|
||||
switch (op.httpMethod) {
|
||||
case "GET":
|
||||
interfaceToImplement = "Operation\\GetInterface";
|
||||
classMethod = "handleGet";
|
||||
break;
|
||||
case "POST":
|
||||
interfaceToImplement = "Operation\\PostInterface";
|
||||
classMethod = "handlePost";
|
||||
break;
|
||||
case "PATCH":
|
||||
interfaceToImplement = "Operation\\PatchInterface";
|
||||
classMethod = "handlePatch";
|
||||
break;
|
||||
case "PUT":
|
||||
interfaceToImplement = "Operation\\PutInterface";
|
||||
classMethod = "handlePut";
|
||||
break;
|
||||
case "DELETE":
|
||||
interfaceToImplement = "Operation\\DeleteInterface";
|
||||
classMethod = "handleDelete";
|
||||
break;
|
||||
default:
|
||||
throw new RuntimeException("Unknown HTTP Method " + op.httpMethod + " not allowed");
|
||||
}
|
||||
if (interfacesToImplement.length() > 0) {
|
||||
interfacesToImplement.append(", ");
|
||||
}
|
||||
interfacesToImplement.append(interfaceToImplement);
|
||||
op.httpMethod = classMethod;
|
||||
//All operations have same path because of custom operation grouping, so path pattern can be calculated only once
|
||||
if (pathPattern == null) {
|
||||
pathPattern = generatePathPattern(op);
|
||||
}
|
||||
}
|
||||
operations.put("interfacesToImplement", interfacesToImplement.toString());
|
||||
operations.put("pathPattern", pathPattern);
|
||||
|
||||
return objs;
|
||||
}
|
||||
|
||||
protected String generatePathPattern(CodegenOperation op) {
|
||||
String result = op.path;
|
||||
for (CodegenParameter pp : op.pathParams) {
|
||||
StringBuilder replacement = new StringBuilder("{" + pp.paramName);
|
||||
if (pp.isEnum) {
|
||||
StringBuilder enumRegExp = new StringBuilder();
|
||||
for (String enumValue : pp._enum) {
|
||||
if (enumRegExp.length() > 0) {
|
||||
enumRegExp.append("|");
|
||||
}
|
||||
enumRegExp.append(enumValue.replaceAll("[\\Q<>()[]{}|^$-=!?*+.\\\\E]", "\\\\$0"));
|
||||
}
|
||||
replacement.append(":");
|
||||
replacement.append(enumRegExp);
|
||||
} else if (pp.isInteger) {
|
||||
replacement.append(":0|(?:-?[1-9][0-9]*)");
|
||||
} else if (pp.isString && (pp.pattern != null) && (!pp.pattern.isEmpty())) {
|
||||
replacement.append(":");
|
||||
replacement.append(pp.pattern);
|
||||
}
|
||||
//TODO add regular expressions for other types if they are actually used for path parameters
|
||||
replacement.append("}");
|
||||
result = result.replace("{" + pp.paramName + "}", replacement);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -9,10 +9,11 @@ import org.openapitools.codegen.CodegenProperty;
|
||||
import org.openapitools.codegen.CodegenType;
|
||||
import org.openapitools.codegen.DefaultCodegen;
|
||||
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 io.swagger.v3.oas.models.responses.ApiResponse;
|
||||
import io.swagger.v3.parser.util.SchemaTypeUtil;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
@@ -101,16 +102,16 @@ public class PythonClientCodegen extends DefaultCodegen implements CodegenConfig
|
||||
// from https://docs.python.org/3/reference/lexical_analysis.html#keywords
|
||||
setReservedWordsLowerCase(
|
||||
Arrays.asList(
|
||||
// local variable name used in API methods (endpoints)
|
||||
"all_params", "resource_path", "path_params", "query_params",
|
||||
"header_params", "form_params", "local_var_files", "body_params", "auth_settings",
|
||||
// @property
|
||||
"property",
|
||||
// python reserved words
|
||||
"and", "del", "from", "not", "while", "as", "elif", "global", "or", "with",
|
||||
"assert", "else", "if", "pass", "yield", "break", "except", "import",
|
||||
"print", "class", "exec", "in", "raise", "continue", "finally", "is",
|
||||
"return", "def", "for", "lambda", "try", "self", "nonlocal", "None", "True", "False"));
|
||||
// local variable name used in API methods (endpoints)
|
||||
"all_params", "resource_path", "path_params", "query_params",
|
||||
"header_params", "form_params", "local_var_files", "body_params", "auth_settings",
|
||||
// @property
|
||||
"property",
|
||||
// python reserved words
|
||||
"and", "del", "from", "not", "while", "as", "elif", "global", "or", "with",
|
||||
"assert", "else", "if", "pass", "yield", "break", "except", "import",
|
||||
"print", "class", "exec", "in", "raise", "continue", "finally", "is",
|
||||
"return", "def", "for", "lambda", "try", "self", "nonlocal", "None", "True", "False"));
|
||||
|
||||
regexModifiers = new HashMap<Character, String>();
|
||||
regexModifiers.put('i', "IGNORECASE");
|
||||
@@ -146,21 +147,19 @@ public class PythonClientCodegen extends DefaultCodegen implements CodegenConfig
|
||||
super.processOpts();
|
||||
Boolean excludeTests = false;
|
||||
|
||||
if(additionalProperties.containsKey(CodegenConstants.EXCLUDE_TESTS)) {
|
||||
if (additionalProperties.containsKey(CodegenConstants.EXCLUDE_TESTS)) {
|
||||
excludeTests = Boolean.valueOf(additionalProperties.get(CodegenConstants.EXCLUDE_TESTS).toString());
|
||||
}
|
||||
|
||||
if (additionalProperties.containsKey(CodegenConstants.PACKAGE_NAME)) {
|
||||
setPackageName((String) additionalProperties.get(CodegenConstants.PACKAGE_NAME));
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
setPackageName("swagger_client");
|
||||
}
|
||||
|
||||
if (additionalProperties.containsKey(CodegenConstants.PROJECT_NAME)) {
|
||||
setProjectName((String) additionalProperties.get(CodegenConstants.PROJECT_NAME));
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
// default: set project based on package name
|
||||
// e.g. petstore_api (package name) => petstore-api (project name)
|
||||
setProjectName(packageName.replaceAll("_", "-"));
|
||||
@@ -168,8 +167,7 @@ public class PythonClientCodegen extends DefaultCodegen implements CodegenConfig
|
||||
|
||||
if (additionalProperties.containsKey(CodegenConstants.PACKAGE_VERSION)) {
|
||||
setPackageVersion((String) additionalProperties.get(CodegenConstants.PACKAGE_VERSION));
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
setPackageVersion("1.0.0");
|
||||
}
|
||||
|
||||
@@ -204,7 +202,7 @@ public class PythonClientCodegen extends DefaultCodegen implements CodegenConfig
|
||||
supportingFiles.add(new SupportingFile("__init__model.mustache", packageName + File.separatorChar + modelPackage, "__init__.py"));
|
||||
supportingFiles.add(new SupportingFile("__init__api.mustache", packageName + File.separatorChar + apiPackage, "__init__.py"));
|
||||
|
||||
if(Boolean.FALSE.equals(excludeTests)) {
|
||||
if (Boolean.FALSE.equals(excludeTests)) {
|
||||
supportingFiles.add(new SupportingFile("__init__test.mustache", testFolder, "__init__.py"));
|
||||
}
|
||||
supportingFiles.add(new SupportingFile("git_push.sh.mustache", "", "git_push.sh"));
|
||||
@@ -235,14 +233,14 @@ public class PythonClientCodegen extends DefaultCodegen implements CodegenConfig
|
||||
@Override
|
||||
public String toModelImport(String name) {
|
||||
String modelImport;
|
||||
if (StringUtils.startsWithAny(name,"import", "from")) {
|
||||
if (StringUtils.startsWithAny(name, "import", "from")) {
|
||||
modelImport = name;
|
||||
} else {
|
||||
modelImport = "from ";
|
||||
if (!"".equals(modelPackage())) {
|
||||
modelImport += modelPackage() + ".";
|
||||
}
|
||||
modelImport += toModelFilename(name)+ " import " + name;
|
||||
modelImport += toModelFilename(name) + " import " + name;
|
||||
}
|
||||
return modelImport;
|
||||
}
|
||||
@@ -254,7 +252,7 @@ public class PythonClientCodegen extends DefaultCodegen implements CodegenConfig
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postProcessParameter(CodegenParameter parameter){
|
||||
public void postProcessParameter(CodegenParameter parameter) {
|
||||
postProcessPattern(parameter.pattern, parameter.vendorExtensions);
|
||||
}
|
||||
|
||||
@@ -268,21 +266,21 @@ public class PythonClientCodegen extends DefaultCodegen implements CodegenConfig
|
||||
* does not support this in as natural a way so it needs to convert it. See
|
||||
* https://docs.python.org/2/howto/regex.html#compilation-flags for details.
|
||||
*/
|
||||
public void postProcessPattern(String pattern, Map<String, Object> vendorExtensions){
|
||||
if(pattern != null) {
|
||||
public void postProcessPattern(String pattern, Map<String, Object> vendorExtensions) {
|
||||
if (pattern != null) {
|
||||
int i = pattern.lastIndexOf('/');
|
||||
|
||||
//Must follow Perl /pattern/modifiers convention
|
||||
if(pattern.charAt(0) != '/' || i < 2) {
|
||||
if (pattern.charAt(0) != '/' || i < 2) {
|
||||
throw new IllegalArgumentException("Pattern must follow the Perl "
|
||||
+ "/pattern/modifiers convention. "+pattern+" is not valid.");
|
||||
+ "/pattern/modifiers convention. " + pattern + " is not valid.");
|
||||
}
|
||||
|
||||
String regex = pattern.substring(1, i).replace("'", "\\'");
|
||||
List<String> modifiers = new ArrayList<String>();
|
||||
|
||||
for(char c : pattern.substring(i).toCharArray()) {
|
||||
if(regexModifiers.containsKey(c)) {
|
||||
for (char c : pattern.substring(i).toCharArray()) {
|
||||
if (regexModifiers.containsKey(c)) {
|
||||
String modifier = regexModifiers.get(c);
|
||||
modifiers.add(modifier);
|
||||
}
|
||||
@@ -310,7 +308,7 @@ public class PythonClientCodegen extends DefaultCodegen implements CodegenConfig
|
||||
|
||||
@Override
|
||||
public String escapeReservedWord(String name) {
|
||||
if(this.reservedWordsMappings().containsKey(name)) {
|
||||
if (this.reservedWordsMappings().containsKey(name)) {
|
||||
return this.reservedWordsMappings().get(name);
|
||||
}
|
||||
return "_" + name;
|
||||
@@ -521,7 +519,7 @@ public class PythonClientCodegen extends DefaultCodegen implements CodegenConfig
|
||||
}
|
||||
|
||||
public void setProjectName(String projectName) {
|
||||
this.projectName= projectName;
|
||||
this.projectName = projectName;
|
||||
}
|
||||
|
||||
public void setPackageVersion(String packageVersion) {
|
||||
@@ -534,7 +532,7 @@ public class PythonClientCodegen extends DefaultCodegen implements CodegenConfig
|
||||
|
||||
/**
|
||||
* Generate Python package name from String `packageName`
|
||||
*
|
||||
* <p>
|
||||
* (PEP 0008) Python packages should also have short, all-lowercase names,
|
||||
* although the use of underscores is discouraged.
|
||||
*
|
||||
|
||||
@@ -0,0 +1,695 @@
|
||||
package org.openapitools.codegen.languages;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.google.common.collect.ArrayListMultimap;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Multimap;
|
||||
|
||||
import org.openapitools.codegen.*;
|
||||
import io.swagger.v3.oas.models.media.*;
|
||||
import io.swagger.v3.oas.models.PathItem;
|
||||
import io.swagger.v3.oas.models.PathItem.HttpMethod;
|
||||
import io.swagger.v3.oas.models.*;
|
||||
import io.swagger.v3.oas.models.parameters.*;
|
||||
import io.swagger.v3.core.util.Yaml;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.*;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class PythonFlaskConnexionServerCodegen extends DefaultCodegen implements CodegenConfig {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(PythonFlaskConnexionServerCodegen.class);
|
||||
|
||||
public static final String CONTROLLER_PACKAGE = "controllerPackage";
|
||||
public static final String DEFAULT_CONTROLLER = "defaultController";
|
||||
public static final String SUPPORT_PYTHON2 = "supportPython2";
|
||||
|
||||
protected int serverPort = 8080;
|
||||
protected String packageName;
|
||||
protected String packageVersion;
|
||||
protected String controllerPackage;
|
||||
protected String defaultController;
|
||||
protected Map<Character, String> regexModifiers;
|
||||
|
||||
public PythonFlaskConnexionServerCodegen() {
|
||||
super();
|
||||
modelPackage = "models";
|
||||
testPackage = "test";
|
||||
|
||||
languageSpecificPrimitives.clear();
|
||||
languageSpecificPrimitives.add("int");
|
||||
languageSpecificPrimitives.add("float");
|
||||
languageSpecificPrimitives.add("List");
|
||||
languageSpecificPrimitives.add("Dict");
|
||||
languageSpecificPrimitives.add("bool");
|
||||
languageSpecificPrimitives.add("str");
|
||||
languageSpecificPrimitives.add("datetime");
|
||||
languageSpecificPrimitives.add("date");
|
||||
languageSpecificPrimitives.add("file");
|
||||
languageSpecificPrimitives.add("object");
|
||||
|
||||
typeMapping.clear();
|
||||
typeMapping.put("integer", "int");
|
||||
typeMapping.put("float", "float");
|
||||
typeMapping.put("number", "float");
|
||||
typeMapping.put("long", "int");
|
||||
typeMapping.put("double", "float");
|
||||
typeMapping.put("array", "List");
|
||||
typeMapping.put("map", "Dict");
|
||||
typeMapping.put("boolean", "bool");
|
||||
typeMapping.put("string", "str");
|
||||
typeMapping.put("date", "date");
|
||||
typeMapping.put("DateTime", "datetime");
|
||||
typeMapping.put("object", "object");
|
||||
typeMapping.put("file", "file");
|
||||
typeMapping.put("UUID", "str");
|
||||
|
||||
// from https://docs.python.org/3/reference/lexical_analysis.html#keywords
|
||||
setReservedWordsLowerCase(
|
||||
Arrays.asList(
|
||||
// @property
|
||||
"property",
|
||||
// python reserved words
|
||||
"and", "del", "from", "not", "while", "as", "elif", "global", "or", "with",
|
||||
"assert", "else", "if", "pass", "yield", "break", "except", "import",
|
||||
"print", "class", "exec", "in", "raise", "continue", "finally", "is",
|
||||
"return", "def", "for", "lambda", "try", "self", "None", "True", "False", "nonlocal"));
|
||||
|
||||
// set the output folder here
|
||||
outputFolder = "generated-code/connexion";
|
||||
|
||||
apiTemplateFiles.put("controller.mustache", ".py");
|
||||
modelTemplateFiles.put("model.mustache", ".py");
|
||||
apiTestTemplateFiles().put("controller_test.mustache", ".py");
|
||||
|
||||
/*
|
||||
* Template Location. This is the location which templates will be read from. The generator
|
||||
* will use the resource stream to attempt to read the templates.
|
||||
*/
|
||||
embeddedTemplateDir = templateDir = "flaskConnexion";
|
||||
|
||||
/*
|
||||
* Additional Properties. These values can be passed to the templates and
|
||||
* are available in models, apis, and supporting files
|
||||
*/
|
||||
additionalProperties.put("serverPort", serverPort);
|
||||
|
||||
/*
|
||||
* Supporting Files. You can write single files for the generator with the
|
||||
* entire object tree available. If the input file has a suffix of `.mustache
|
||||
* it will be processed by the template engine. Otherwise, it will be copied
|
||||
*/
|
||||
supportingFiles.add(new SupportingFile("README.mustache", "", "README.md"));
|
||||
supportingFiles.add(new SupportingFile("setup.mustache", "", "setup.py"));
|
||||
supportingFiles.add(new SupportingFile("tox.mustache", "", "tox.ini"));
|
||||
supportingFiles.add(new SupportingFile("test-requirements.mustache", "", "test-requirements.txt"));
|
||||
supportingFiles.add(new SupportingFile("requirements.mustache", "", "requirements.txt"));
|
||||
supportingFiles.add(new SupportingFile("git_push.sh.mustache", "", "git_push.sh"));
|
||||
supportingFiles.add(new SupportingFile("gitignore.mustache", "", ".gitignore"));
|
||||
supportingFiles.add(new SupportingFile("travis.mustache", "", ".travis.yml"));
|
||||
supportingFiles.add(new SupportingFile("Dockerfile.mustache", "", "Dockerfile"));
|
||||
supportingFiles.add(new SupportingFile("dockerignore.mustache", "", ".dockerignore"));
|
||||
|
||||
regexModifiers = new HashMap<Character, String>();
|
||||
regexModifiers.put('i', "IGNORECASE");
|
||||
regexModifiers.put('l', "LOCALE");
|
||||
regexModifiers.put('m', "MULTILINE");
|
||||
regexModifiers.put('s', "DOTALL");
|
||||
regexModifiers.put('u', "UNICODE");
|
||||
regexModifiers.put('x', "VERBOSE");
|
||||
|
||||
cliOptions.add(new CliOption(CodegenConstants.PACKAGE_NAME, "python package name (convention: snake_case).")
|
||||
.defaultValue("swagger_server"));
|
||||
cliOptions.add(new CliOption(CodegenConstants.PACKAGE_VERSION, "python package version.")
|
||||
.defaultValue("1.0.0"));
|
||||
cliOptions.add(new CliOption(CONTROLLER_PACKAGE, "controller package").
|
||||
defaultValue("controllers"));
|
||||
cliOptions.add(new CliOption(DEFAULT_CONTROLLER, "default controller").
|
||||
defaultValue("default_controller"));
|
||||
cliOptions.add(new CliOption(SUPPORT_PYTHON2, "support python2").
|
||||
defaultValue("false"));
|
||||
cliOptions.add(new CliOption("serverPort", "TCP port to listen to in app.run").
|
||||
defaultValue("8080"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processOpts() {
|
||||
super.processOpts();
|
||||
//apiTemplateFiles.clear();
|
||||
|
||||
if (additionalProperties.containsKey(CodegenConstants.PACKAGE_NAME)) {
|
||||
setPackageName((String) additionalProperties.get(CodegenConstants.PACKAGE_NAME));
|
||||
} else {
|
||||
setPackageName("swagger_server");
|
||||
additionalProperties.put(CodegenConstants.PACKAGE_NAME, this.packageName);
|
||||
}
|
||||
if (additionalProperties.containsKey(CodegenConstants.PACKAGE_VERSION)) {
|
||||
setPackageVersion((String) additionalProperties.get(CodegenConstants.PACKAGE_VERSION));
|
||||
} else {
|
||||
setPackageVersion("1.0.0");
|
||||
additionalProperties.put(CodegenConstants.PACKAGE_VERSION, this.packageVersion);
|
||||
}
|
||||
if (additionalProperties.containsKey(CONTROLLER_PACKAGE)) {
|
||||
this.controllerPackage = additionalProperties.get(CONTROLLER_PACKAGE).toString();
|
||||
} else {
|
||||
this.controllerPackage = "controllers";
|
||||
additionalProperties.put(CONTROLLER_PACKAGE, this.controllerPackage);
|
||||
}
|
||||
if (additionalProperties.containsKey(DEFAULT_CONTROLLER)) {
|
||||
this.defaultController = additionalProperties.get(DEFAULT_CONTROLLER).toString();
|
||||
} else {
|
||||
this.defaultController = "default_controller";
|
||||
additionalProperties.put(DEFAULT_CONTROLLER, this.defaultController);
|
||||
}
|
||||
if (Boolean.TRUE.equals(additionalProperties.get(SUPPORT_PYTHON2))) {
|
||||
additionalProperties.put(SUPPORT_PYTHON2, Boolean.TRUE);
|
||||
typeMapping.put("long", "long");
|
||||
}
|
||||
supportingFiles.add(new SupportingFile("__init__.mustache", packageName, "__init__.py"));
|
||||
supportingFiles.add(new SupportingFile("__main__.mustache", packageName, "__main__.py"));
|
||||
supportingFiles.add(new SupportingFile("encoder.mustache", packageName, "encoder.py"));
|
||||
supportingFiles.add(new SupportingFile("util.mustache", packageName, "util.py"));
|
||||
supportingFiles.add(new SupportingFile("__init__.mustache", packageName + File.separatorChar + controllerPackage, "__init__.py"));
|
||||
supportingFiles.add(new SupportingFile("__init__model.mustache", packageName + File.separatorChar + modelPackage, "__init__.py"));
|
||||
supportingFiles.add(new SupportingFile("base_model_.mustache", packageName + File.separatorChar + modelPackage, "base_model_.py"));
|
||||
supportingFiles.add(new SupportingFile("__init__test.mustache", packageName + File.separatorChar + testPackage, "__init__.py"));
|
||||
supportingFiles.add(new SupportingFile("swagger.mustache", packageName + File.separatorChar + "swagger", "swagger.yaml"));
|
||||
|
||||
modelPackage = packageName + "." + modelPackage;
|
||||
controllerPackage = packageName + "." + controllerPackage;
|
||||
testPackage = packageName + "." + testPackage;
|
||||
}
|
||||
|
||||
private static String dropDots(String str) {
|
||||
return str.replaceAll("\\.", "_");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String apiPackage() {
|
||||
return controllerPackage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the type of generator.
|
||||
*
|
||||
* @return the CodegenType for this generator
|
||||
* @see org.openapitools.codegen.CodegenType
|
||||
*/
|
||||
@Override
|
||||
public CodegenType getTag() {
|
||||
return CodegenType.SERVER;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures a friendly name for the generator. This will be used by the generator
|
||||
* to select the library with the -l flag.
|
||||
*
|
||||
* @return the friendly name for the generator
|
||||
*/
|
||||
@Override
|
||||
public String getName() {
|
||||
return "python-flask";
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns human-friendly help for the generator. Provide the consumer with help
|
||||
* tips, parameters here
|
||||
*
|
||||
* @return A string value for the help message
|
||||
*/
|
||||
@Override
|
||||
public String getHelp() {
|
||||
return "Generates a Python server library using the Connexion project. By default, " +
|
||||
"it will also generate service classes -- which you can disable with the `-Dnoservice` environment variable.";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toApiName(String name) {
|
||||
if (name == null || name.length() == 0) {
|
||||
return "DefaultController";
|
||||
}
|
||||
return camelize(name, false) + "Controller";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toApiFilename(String name) {
|
||||
return underscore(toApiName(name));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toApiTestFilename(String name) {
|
||||
return "test_" + toApiFilename(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Escapes a reserved word as defined in the `reservedWords` array. Handle escaping
|
||||
* those terms here. This logic is only called if a variable matches the reserved words
|
||||
*
|
||||
* @return the escaped term
|
||||
*/
|
||||
@Override
|
||||
public String escapeReservedWord(String name) {
|
||||
if (this.reservedWordsMappings().containsKey(name)) {
|
||||
return this.reservedWordsMappings().get(name);
|
||||
}
|
||||
return "_" + name; // add an underscore to the name
|
||||
}
|
||||
|
||||
/**
|
||||
* Location to write api files. You can use the apiPackage() as defined when the class is
|
||||
* instantiated
|
||||
*/
|
||||
@Override
|
||||
public String apiFileFolder() {
|
||||
return outputFolder + File.separator + apiPackage().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) + "[str, " + 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 type;
|
||||
}
|
||||
} else {
|
||||
type = toModelName(swaggerType);
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preprocessOpenAPI(OpenAPI openAPI) {
|
||||
// need vendor extensions for x-swagger-router-controller
|
||||
Map<String, PathItem> paths = openAPI.getPaths();
|
||||
if (paths != null) {
|
||||
for (String pathname : paths.keySet()) {
|
||||
PathItem path = paths.get(pathname);
|
||||
Map<HttpMethod, Operation> operationMap = path.readOperationsMap();
|
||||
if (operationMap != null) {
|
||||
for (HttpMethod method : operationMap.keySet()) {
|
||||
Operation operation = operationMap.get(method);
|
||||
String tag = "default";
|
||||
if (operation.getTags() != null && operation.getTags().size() > 0) {
|
||||
tag = operation.getTags().get(0);
|
||||
}
|
||||
String operationId = operation.getOperationId();
|
||||
if (operationId == null) {
|
||||
operationId = getOrGenerateOperationId(operation, pathname, method.toString());
|
||||
}
|
||||
operation.setOperationId(toOperationId(operationId));
|
||||
if (operation.getExtensions().get("x-swagger-router-controller") == null) {
|
||||
operation.getExtensions().put(
|
||||
"x-swagger-router-controller",
|
||||
controllerPackage + "." + toApiFilename(tag)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private static List<Map<String, Object>> getOperations(Map<String, Object> objs) {
|
||||
List<Map<String, Object>> result = new ArrayList<Map<String, Object>>();
|
||||
Map<String, Object> apiInfo = (Map<String, Object>) objs.get("apiInfo");
|
||||
List<Map<String, Object>> apis = (List<Map<String, Object>>) apiInfo.get("apis");
|
||||
for (Map<String, Object> api : apis) {
|
||||
result.add((Map<String, Object>) api.get("operations"));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static List<Map<String, Object>> sortOperationsByPath(List<CodegenOperation> ops) {
|
||||
Multimap<String, CodegenOperation> opsByPath = ArrayListMultimap.create();
|
||||
|
||||
for (CodegenOperation op : ops) {
|
||||
opsByPath.put(op.path, op);
|
||||
}
|
||||
|
||||
List<Map<String, Object>> opsByPathList = new ArrayList<Map<String, Object>>();
|
||||
for (Map.Entry<String, Collection<CodegenOperation>> entry : opsByPath.asMap().entrySet()) {
|
||||
Map<String, Object> opsByPathEntry = new HashMap<String, Object>();
|
||||
opsByPathList.add(opsByPathEntry);
|
||||
opsByPathEntry.put("path", entry.getKey());
|
||||
opsByPathEntry.put("operation", entry.getValue());
|
||||
List<CodegenOperation> operationsForThisPath = Lists.newArrayList(entry.getValue());
|
||||
operationsForThisPath.get(operationsForThisPath.size() - 1).hasMore = false;
|
||||
if (opsByPathList.size() < opsByPath.asMap().size()) {
|
||||
opsByPathEntry.put("hasMore", "true");
|
||||
}
|
||||
}
|
||||
|
||||
return opsByPathList;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> postProcessSupportingFileData(Map<String, Object> objs) {
|
||||
OpenAPI swagger = (OpenAPI) objs.get("openapi");
|
||||
if (swagger != null) {
|
||||
try {
|
||||
objs.put("swagger-yaml", Yaml.mapper().writeValueAsString(swagger));
|
||||
} catch (JsonProcessingException e) {
|
||||
LOGGER.error(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
for (Map<String, Object> operations : getOperations(objs)) {
|
||||
@SuppressWarnings("unchecked")
|
||||
List<CodegenOperation> ops = (List<CodegenOperation>) operations.get("operation");
|
||||
|
||||
List<Map<String, Object>> opsByPathList = sortOperationsByPath(ops);
|
||||
operations.put("operationsByPath", opsByPathList);
|
||||
}
|
||||
return super.postProcessSupportingFileData(objs);
|
||||
}
|
||||
|
||||
@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'.
|
||||
|
||||
// remove dollar sign
|
||||
name = name.replaceAll("$", "");
|
||||
|
||||
// if it's all uppper case, convert to lower case
|
||||
if (name.matches("^[A-Z_]*$")) {
|
||||
name = name.toLowerCase();
|
||||
}
|
||||
|
||||
// underscore the variable name
|
||||
// petId => pet_id
|
||||
name = underscore(name);
|
||||
|
||||
// remove leading underscore
|
||||
name = name.replaceAll("^_*", "");
|
||||
|
||||
// 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) {
|
||||
// don't do name =removeNonNameElementToCamelCase(name); // this breaks connexion, which does not modify param names before sending them
|
||||
if (reservedWords.contains(name)) {
|
||||
return escapeReservedWord(name);
|
||||
}
|
||||
|
||||
// sanitize the param name but don't underscore it since it's used for request mapping
|
||||
String paramName = sanitizeName(name);
|
||||
if (!paramName.equals(name)) {
|
||||
LOGGER.warn(name + " (parameter name) cannot be used as parameter name with flask-connexion and was sanitized as " + paramName);
|
||||
}
|
||||
// Param name is already sanitized in swagger spec processing
|
||||
return paramName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toModelFilename(String name) {
|
||||
// underscore the model file name
|
||||
// PhoneNumber => phone_number
|
||||
return underscore(dropDots(toModelName(name)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toModelName(String name) {
|
||||
name = sanitizeName(name); // FIXME: a parameter should not be assigned. Also declare the methods parameters as 'final'.
|
||||
// remove dollar sign
|
||||
name = name.replaceAll("$", "");
|
||||
|
||||
// model name cannot use reserved keyword, e.g. return
|
||||
if (isReservedWord(name)) {
|
||||
LOGGER.warn(name + " (reserved word) cannot be used as model name. Renamed to " + camelize("model_" + name));
|
||||
name = "model_" + name; // e.g. return => ModelReturn (after camelize)
|
||||
}
|
||||
|
||||
// model name starts with number
|
||||
if (name.matches("^\\d.*")) {
|
||||
LOGGER.warn(name + " (model name starts with number) cannot be used as model name. Renamed to " + camelize("model_" + name));
|
||||
name = "model_" + name; // e.g. 200Response => Model200Response (after camelize)
|
||||
}
|
||||
|
||||
if (!StringUtils.isEmpty(modelNamePrefix)) {
|
||||
name = modelNamePrefix + "_" + name;
|
||||
}
|
||||
|
||||
if (!StringUtils.isEmpty(modelNameSuffix)) {
|
||||
name = name + "_" + modelNameSuffix;
|
||||
}
|
||||
|
||||
// camelize the model name
|
||||
// phone_number => PhoneNumber
|
||||
return camelize(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toOperationId(String operationId) {
|
||||
// throw exception if method name is empty (should not occur as an auto-generated method name will be used)
|
||||
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)) {
|
||||
LOGGER.warn(operationId + " (reserved word) cannot be used as method name. Renamed to " + underscore(sanitizeName("call_" + operationId)));
|
||||
operationId = "call_" + operationId;
|
||||
}
|
||||
|
||||
return underscore(sanitizeName(operationId));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the default value of the property
|
||||
*
|
||||
* @param p Swagger property object
|
||||
* @return string presentation of the default value of the property
|
||||
*/
|
||||
@Override
|
||||
public String toDefaultValue(Schema p) {
|
||||
if (p instanceof StringSchema) {
|
||||
StringSchema dp = (StringSchema) p;
|
||||
if (dp.getDefault() != null) {
|
||||
return "'" + dp.getDefault() + "'";
|
||||
}
|
||||
} else if (p instanceof BooleanSchema) {
|
||||
BooleanSchema dp = (BooleanSchema) p;
|
||||
if (dp.getDefault() != null) {
|
||||
if (dp.getDefault().toString().equalsIgnoreCase("false"))
|
||||
return "False";
|
||||
else
|
||||
return "True";
|
||||
}
|
||||
} else if (p instanceof DateSchema) {
|
||||
// TODO
|
||||
} else if (p instanceof DateTimeSchema) {
|
||||
// TODO
|
||||
} else if (p instanceof NumberSchema) {
|
||||
NumberSchema dp = (NumberSchema) p;
|
||||
if (dp.getDefault() != null) {
|
||||
return dp.getDefault().toString();
|
||||
}
|
||||
} else if (p instanceof IntegerSchema) {
|
||||
IntegerSchema dp = (IntegerSchema) p;
|
||||
if (dp.getDefault() != null) {
|
||||
return dp.getDefault().toString();
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setParameterExampleValue(CodegenParameter p) {
|
||||
String example;
|
||||
|
||||
if (p.defaultValue == null) {
|
||||
example = p.example;
|
||||
} else {
|
||||
example = p.defaultValue;
|
||||
}
|
||||
|
||||
String type = p.baseType;
|
||||
if (type == null) {
|
||||
type = p.dataType;
|
||||
}
|
||||
|
||||
if ("String".equalsIgnoreCase(type) || "str".equalsIgnoreCase(type)) {
|
||||
if (example == null) {
|
||||
example = p.paramName + "_example";
|
||||
}
|
||||
example = "'" + escapeText(example) + "'";
|
||||
} else if ("Integer".equals(type) || "int".equals(type)) {
|
||||
if (p.minimum != null) {
|
||||
example = "" + (Integer.valueOf(p.minimum) + 1);
|
||||
}
|
||||
if (p.maximum != null) {
|
||||
example = "" + p.maximum;
|
||||
} else if (example == null) {
|
||||
example = "56";
|
||||
}
|
||||
|
||||
} else if ("Long".equalsIgnoreCase(type)) {
|
||||
if (p.minimum != null) {
|
||||
example = "" + (Long.valueOf(p.minimum) + 1);
|
||||
}
|
||||
if (p.maximum != null) {
|
||||
example = "" + p.maximum;
|
||||
} else if (example == null) {
|
||||
example = "789";
|
||||
}
|
||||
} else if ("Float".equalsIgnoreCase(type) || "Double".equalsIgnoreCase(type)) {
|
||||
if (p.minimum != null) {
|
||||
example = "" + p.minimum;
|
||||
} else if (p.maximum != null) {
|
||||
example = "" + p.maximum;
|
||||
} else if (example == null) {
|
||||
example = "3.4";
|
||||
}
|
||||
} else if ("BOOLEAN".equalsIgnoreCase(type) || "bool".equalsIgnoreCase(type)) {
|
||||
if (example == null) {
|
||||
example = "True";
|
||||
}
|
||||
} else if ("file".equalsIgnoreCase(type)) {
|
||||
example = "(BytesIO(b'some file data'), 'file.txt')";
|
||||
} else if ("Date".equalsIgnoreCase(type)) {
|
||||
if (example == null) {
|
||||
example = "2013-10-20";
|
||||
}
|
||||
example = "'" + escapeText(example) + "'";
|
||||
} else if ("DateTime".equalsIgnoreCase(type)) {
|
||||
if (example == null) {
|
||||
example = "2013-10-20T19:20:30+01:00";
|
||||
}
|
||||
example = "'" + escapeText(example) + "'";
|
||||
} else if (!languageSpecificPrimitives.contains(type)) {
|
||||
// type is a model class, e.g. User
|
||||
example = type + "()";
|
||||
} else {
|
||||
LOGGER.warn("Type " + type + " not handled properly in setParameterExampleValue");
|
||||
}
|
||||
|
||||
if (p.items != null && p.items.defaultValue != null) {
|
||||
example = p.items.defaultValue;
|
||||
}
|
||||
if (example == null) {
|
||||
example = "None";
|
||||
} else if (Boolean.TRUE.equals(p.isListContainer)) {
|
||||
if (Boolean.TRUE.equals(p.isBodyParam)) {
|
||||
example = "[" + example + "]";
|
||||
}
|
||||
} else if (Boolean.TRUE.equals(p.isMapContainer)) {
|
||||
example = "{'key': " + example + "}";
|
||||
}
|
||||
|
||||
p.example = example;
|
||||
}
|
||||
|
||||
public void setPackageName(String packageName) {
|
||||
this.packageName = packageName;
|
||||
}
|
||||
|
||||
public void setPackageVersion(String packageVersion) {
|
||||
this.packageVersion = packageVersion;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String escapeQuotationMark(String input) {
|
||||
// remove ' to avoid code injection
|
||||
return input.replace("'", "");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String escapeUnsafeCharacters(String input) {
|
||||
// remove multiline comment
|
||||
return input.replace("'''", "'_'_'");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toModelImport(String name) {
|
||||
String modelImport;
|
||||
if (StringUtils.startsWithAny(name, "import", "from")) {
|
||||
modelImport = name;
|
||||
} else {
|
||||
modelImport = "from ";
|
||||
if (!"".equals(modelPackage())) {
|
||||
modelImport += modelPackage() + ".";
|
||||
}
|
||||
modelImport += toModelFilename(name) + " import " + name;
|
||||
}
|
||||
return modelImport;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postProcessModelProperty(CodegenModel model, CodegenProperty property) {
|
||||
if (StringUtils.isNotEmpty(property.pattern)) {
|
||||
addImport(model, "import re");
|
||||
}
|
||||
postProcessPattern(property.pattern, property.vendorExtensions);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> postProcessModels(Map<String, Object> objs) {
|
||||
// process enum in models
|
||||
return postProcessModelsEnum(objs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postProcessParameter(CodegenParameter parameter) {
|
||||
postProcessPattern(parameter.pattern, parameter.vendorExtensions);
|
||||
}
|
||||
|
||||
/*
|
||||
* The swagger pattern spec follows the Perl convention and style of modifiers. Python
|
||||
* does not support this in as natural a way so it needs to convert it. See
|
||||
* https://docs.python.org/2/howto/regex.html#compilation-flags for details.
|
||||
*/
|
||||
public void postProcessPattern(String pattern, Map<String, Object> vendorExtensions) {
|
||||
if (pattern != null) {
|
||||
int i = pattern.lastIndexOf('/');
|
||||
|
||||
//Must follow Perl /pattern/modifiers convention
|
||||
if (pattern.charAt(0) != '/' || i < 2) {
|
||||
throw new IllegalArgumentException("Pattern must follow the Perl "
|
||||
+ "/pattern/modifiers convention. " + pattern + " is not valid.");
|
||||
}
|
||||
|
||||
String regex = pattern.substring(1, i).replace("'", "\\'");
|
||||
List<String> modifiers = new ArrayList<String>();
|
||||
|
||||
for (char c : pattern.substring(i).toCharArray()) {
|
||||
if (regexModifiers.containsKey(c)) {
|
||||
String modifier = regexModifiers.get(c);
|
||||
modifiers.add(modifier);
|
||||
}
|
||||
}
|
||||
|
||||
vendorExtensions.put("x-regex", regex);
|
||||
vendorExtensions.put("x-modifiers", modifiers);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -23,9 +23,9 @@ import org.apache.commons.lang3.StringUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class Rails5ServerCodegen extends DefaultCodegen implements CodegenConfig {
|
||||
public class RubyOnRailsServerCodegen extends DefaultCodegen implements CodegenConfig {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(Rails5ServerCodegen.class);
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(RubyOnRailsServerCodegen.class);
|
||||
private static final SimpleDateFormat MIGRATE_FILE_NAME_FORMAT = new SimpleDateFormat("yyyyMMddHHmmss");
|
||||
|
||||
protected String gemName;
|
||||
@@ -58,7 +58,7 @@ public class Rails5ServerCodegen extends DefaultCodegen implements CodegenConfig
|
||||
protected String socketsFolder = tmpFolder + File.separator + "sockets";
|
||||
protected String vendorFolder = "vendor";
|
||||
|
||||
public Rails5ServerCodegen() {
|
||||
public RubyOnRailsServerCodegen() {
|
||||
super();
|
||||
outputFolder = "generated-code" + File.separator + "rails5";
|
||||
apiPackage = "app/controllers";
|
||||
@@ -182,7 +182,7 @@ public class Rails5ServerCodegen extends DefaultCodegen implements CodegenConfig
|
||||
|
||||
@Override
|
||||
public String getHelp() {
|
||||
return "Generates a Rails5 server library.";
|
||||
return "Generates a Ruby on Rails server library.";
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,282 @@
|
||||
package org.openapitools.codegen.languages;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.openapitools.codegen.CodegenConfig;
|
||||
import org.openapitools.codegen.CodegenType;
|
||||
import org.openapitools.codegen.DefaultCodegen;
|
||||
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 io.swagger.v3.oas.models.responses.ApiResponse;
|
||||
import io.swagger.v3.parser.util.SchemaTypeUtil;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
|
||||
public class TizenClientCodegen extends DefaultCodegen implements CodegenConfig {
|
||||
protected static String PREFIX = "ArtikCloud";
|
||||
protected String sourceFolder = "src";
|
||||
protected String documentationFolder = "doc";
|
||||
|
||||
public TizenClientCodegen() {
|
||||
super();
|
||||
outputFolder = "";
|
||||
modelTemplateFiles.put("model-header.mustache", ".h");
|
||||
modelTemplateFiles.put("model-body.mustache", ".cpp");
|
||||
apiTemplateFiles.put("api-header.mustache", ".h");
|
||||
apiTemplateFiles.put("api-body.mustache", ".cpp");
|
||||
embeddedTemplateDir = templateDir = "tizen";
|
||||
modelPackage = "";
|
||||
|
||||
defaultIncludes = new HashSet<String>(
|
||||
Arrays.asList(
|
||||
"bool",
|
||||
"int",
|
||||
"long long",
|
||||
"double",
|
||||
"float")
|
||||
);
|
||||
languageSpecificPrimitives = new HashSet<String>(
|
||||
Arrays.asList(
|
||||
"bool",
|
||||
"int",
|
||||
"long long",
|
||||
"double",
|
||||
"float",
|
||||
"std::string")
|
||||
);
|
||||
|
||||
additionalProperties().put("prefix", PREFIX);
|
||||
|
||||
setReservedWordsLowerCase(
|
||||
Arrays.asList(
|
||||
"alignas", "alignof", "and", "and_eq", "asm", "atomic_cancel", "atomic_commit", "atomic_noexcept",
|
||||
"auto", "bitand", "bitor", "bool", "break", "case", "catch", "char", "char16_t", "char32_t",
|
||||
"class", "compl", "concept", "const", "constexpr", "const_cast", "continue", "decltype", "default",
|
||||
"delete", "do", "double", "dynamic_cast", "else", "enum", "explicit", "export", "extern", "false",
|
||||
"float", "for", "friend", "goto", "if", "inline", "int", "import", "long", "module", "mutable",
|
||||
"namespace", "new", "noexcept", "not", "not_eq", "nullptr", "operator", "or", "or_eq", "private",
|
||||
"protected", "public", "register", "reinterpret_cast", "requires", "return", "short", "signed",
|
||||
"sizeof", "static", "static_assert", "static_cast", "struct", "switch", "synchronized", "template",
|
||||
"this", "thread_local", "throw", "true", "try", "typedef", "typeid", "typename", "union",
|
||||
"unsigned", "using", "virtual", "void", "volatile", "wchar_t", "while", "xor", "xor_eq"
|
||||
));
|
||||
|
||||
super.typeMapping = new HashMap<String, String>();
|
||||
|
||||
//typeMapping.put("Date", "DateTime");
|
||||
//typeMapping.put("DateTime", "DateTime");
|
||||
typeMapping.put("string", "std::string");
|
||||
typeMapping.put("integer", "int");
|
||||
typeMapping.put("float", "float");
|
||||
typeMapping.put("long", "long long");
|
||||
typeMapping.put("boolean", "bool");
|
||||
typeMapping.put("double", "double");
|
||||
typeMapping.put("array", "std::list");
|
||||
typeMapping.put("map", "std::map");
|
||||
typeMapping.put("number", "long long");
|
||||
typeMapping.put("object", "std::string");
|
||||
typeMapping.put("binary", "std::string");
|
||||
typeMapping.put("password", "std::string");
|
||||
//TODO:Maybe use better formats for dateTime?
|
||||
typeMapping.put("file", "std::string");
|
||||
typeMapping.put("DateTime", "std::string");
|
||||
typeMapping.put("Date", "std::string");
|
||||
typeMapping.put("UUID", "std::string");
|
||||
|
||||
importMapping = new HashMap<String, String>();
|
||||
|
||||
supportingFiles.clear();
|
||||
supportingFiles.add(new SupportingFile("helpers-header.mustache", sourceFolder, "Helpers.h"));
|
||||
supportingFiles.add(new SupportingFile("helpers-body.mustache", sourceFolder, "Helpers.cpp"));
|
||||
supportingFiles.add(new SupportingFile("netclient-header.mustache", sourceFolder, "NetClient.h"));
|
||||
supportingFiles.add(new SupportingFile("netclient-body.mustache", sourceFolder, "NetClient.cpp"));
|
||||
supportingFiles.add(new SupportingFile("object.mustache", sourceFolder, "Object.h"));
|
||||
supportingFiles.add(new SupportingFile("requestinfo.mustache", sourceFolder, "RequestInfo.h"));
|
||||
supportingFiles.add(new SupportingFile("error-header.mustache", sourceFolder, "Error.h"));
|
||||
supportingFiles.add(new SupportingFile("error-body.mustache", sourceFolder, "Error.cpp"));
|
||||
supportingFiles.add(new SupportingFile("Doxyfile.mustache", documentationFolder, "Doxyfile"));
|
||||
supportingFiles.add(new SupportingFile("generateDocumentation.mustache", documentationFolder, "generateDocumentation.sh"));
|
||||
supportingFiles.add(new SupportingFile("doc-readme.mustache", documentationFolder, "README.md"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public CodegenType getTag() {
|
||||
return CodegenType.CLIENT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "tizen";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHelp() {
|
||||
return "Generates a Samsung Tizen C++ client library.";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toInstantiationType(Schema p) {
|
||||
if (p instanceof MapSchema) {
|
||||
return instantiationTypes.get("map");
|
||||
} else if (p instanceof ArraySchema) {
|
||||
return instantiationTypes.get("array");
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTypeDeclaration(String name) {
|
||||
if (languageSpecificPrimitives.contains(name)) {
|
||||
return name;
|
||||
} else {
|
||||
return name + "";
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSchemaType(Schema p) {
|
||||
String openAPIType = super.getSchemaType(p);
|
||||
String type = null;
|
||||
if (typeMapping.containsKey(openAPIType)) {
|
||||
type = typeMapping.get(openAPIType);
|
||||
if (languageSpecificPrimitives.contains(type)) {
|
||||
return toModelName(type);
|
||||
}
|
||||
} else {
|
||||
type = openAPIType;
|
||||
}
|
||||
return toModelName(type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTypeDeclaration(Schema p) {
|
||||
String openAPIType = getSchemaType(p);
|
||||
if (languageSpecificPrimitives.contains(openAPIType)) {
|
||||
return toModelName(openAPIType);
|
||||
} else {
|
||||
return openAPIType + "";
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toModelName(String type) {
|
||||
if (typeMapping.keySet().contains(type) ||
|
||||
typeMapping.values().contains(type) ||
|
||||
importMapping.values().contains(type) ||
|
||||
defaultIncludes.contains(type) ||
|
||||
languageSpecificPrimitives.contains(type)) {
|
||||
return type;
|
||||
} else {
|
||||
return Character.toUpperCase(type.charAt(0)) + type.substring(1);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toModelImport(String name) {
|
||||
if (name.equals("std::string")) {
|
||||
return "#include <string>";
|
||||
} else if (name.equals("std::map")) {
|
||||
return "#include <map>";
|
||||
} else if (name.equals("std::list")) {
|
||||
return "#include <list>";
|
||||
}
|
||||
return "#include \"" + name + ".h\"";
|
||||
}
|
||||
|
||||
//Might not be needed
|
||||
@Override
|
||||
public String toDefaultValue(Schema p) {
|
||||
if (p instanceof StringSchema) {
|
||||
return "std::string()";
|
||||
} else if (p instanceof BooleanSchema) {
|
||||
return "bool(false)";
|
||||
} else if (p instanceof NumberSchema) {
|
||||
if (SchemaTypeUtil.FLOAT_FORMAT.equals(p.getFormat())) {
|
||||
return "float(0)";
|
||||
}
|
||||
return "double(0)";
|
||||
|
||||
} else if (p instanceof IntegerSchema) {
|
||||
if (SchemaTypeUtil.INTEGER64_FORMAT.equals(p.getFormat())) {
|
||||
return "long(0)";
|
||||
}
|
||||
return "int(0)";
|
||||
} else if (p instanceof MapSchema) {
|
||||
return "new std::map()";
|
||||
} else if (p instanceof ArraySchema) {
|
||||
return "new std::list()";
|
||||
} else if (!StringUtils.isEmpty(p.get$ref())) {
|
||||
return "new " + toModelName(p.get$ref()) + "()";
|
||||
}
|
||||
return "null";
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String apiFileFolder() {
|
||||
return outputFolder + File.separator + sourceFolder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String modelFileFolder() {
|
||||
return outputFolder + File.separator + sourceFolder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toModelFilename(String name) {
|
||||
return initialCaps(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toApiName(String name) {
|
||||
return initialCaps(name) + "Manager";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toApiFilename(String name) {
|
||||
return initialCaps(name) + "Manager";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toVarName(String name) {
|
||||
String paramName = name.replaceAll("[^a-zA-Z0-9_]", "");
|
||||
paramName = Character.toLowerCase(paramName.charAt(0)) + paramName.substring(1);
|
||||
if (isReservedWord(paramName)) {
|
||||
return escapeReservedWord(paramName);
|
||||
}
|
||||
return "" + paramName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String escapeReservedWord(String name) {
|
||||
if (this.reservedWordsMappings().containsKey(name)) {
|
||||
return this.reservedWordsMappings().get(name);
|
||||
}
|
||||
return "_" + name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toOperationId(String operationId) {
|
||||
// throw exception if method name is empty
|
||||
if (operationId == "") {
|
||||
throw new RuntimeException("Empty method name (operationId) not allowed");
|
||||
}
|
||||
|
||||
// method name cannot use reserved keyword, e.g. return$
|
||||
if (isReservedWord(operationId)) {
|
||||
operationId = escapeReservedWord(operationId);
|
||||
}
|
||||
|
||||
// add_pet_by_id => addPetById
|
||||
return camelize(operationId, true);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,424 @@
|
||||
package org.openapitools.codegen.languages;
|
||||
|
||||
import java.io.File;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import io.swagger.v3.parser.util.SchemaTypeUtil;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.openapitools.codegen.CliOption;
|
||||
import org.openapitools.codegen.CodegenModel;
|
||||
import org.openapitools.codegen.CodegenParameter;
|
||||
import org.openapitools.codegen.CodegenOperation;
|
||||
import org.openapitools.codegen.SupportingFile;
|
||||
import org.openapitools.codegen.utils.SemVer;
|
||||
|
||||
import io.swagger.v3.oas.models.media.*;
|
||||
import io.swagger.v3.oas.models.PathItem;
|
||||
import io.swagger.v3.oas.models.PathItem.HttpMethod;
|
||||
import io.swagger.v3.oas.models.*;
|
||||
import io.swagger.v3.oas.models.parameters.*;
|
||||
import io.swagger.v3.oas.models.info.*;
|
||||
|
||||
public class TypeScriptAngularClientCodegen extends AbstractTypeScriptClientCodegen {
|
||||
private static final SimpleDateFormat SNAPSHOT_SUFFIX_FORMAT = new SimpleDateFormat("yyyyMMddHHmm");
|
||||
private static final String X_DISCRIMINATOR_TYPE = "x-discriminator-value";
|
||||
|
||||
public static final String NPM_NAME = "npmName";
|
||||
public static final String NPM_VERSION = "npmVersion";
|
||||
public static final String NPM_REPOSITORY = "npmRepository";
|
||||
public static final String SNAPSHOT = "snapshot";
|
||||
public static final String WITH_INTERFACES = "withInterfaces";
|
||||
public static final String TAGGED_UNIONS = "taggedUnions";
|
||||
public static final String NG_VERSION = "ngVersion";
|
||||
|
||||
protected String npmName = null;
|
||||
protected String npmVersion = "1.0.0";
|
||||
protected String npmRepository = null;
|
||||
|
||||
private boolean taggedUnions = false;
|
||||
|
||||
public TypeScriptAngularClientCodegen() {
|
||||
super();
|
||||
this.outputFolder = "generated-code/typescript-angular";
|
||||
|
||||
embeddedTemplateDir = templateDir = "typescript-angular";
|
||||
modelTemplateFiles.put("model.mustache", ".ts");
|
||||
apiTemplateFiles.put("api.service.mustache", ".ts");
|
||||
languageSpecificPrimitives.add("Blob");
|
||||
typeMapping.put("file", "Blob");
|
||||
apiPackage = "api";
|
||||
modelPackage = "model";
|
||||
|
||||
this.cliOptions.add(new CliOption(NPM_NAME, "The name under which you want to publish generated npm package"));
|
||||
this.cliOptions.add(new CliOption(NPM_VERSION, "The version of your npm package"));
|
||||
this.cliOptions.add(new CliOption(NPM_REPOSITORY,
|
||||
"Use this property to set an url your private npmRepo in the package.json"));
|
||||
this.cliOptions.add(new CliOption(SNAPSHOT,
|
||||
"When setting this property to true the version will be suffixed with -SNAPSHOT.yyyyMMddHHmm",
|
||||
SchemaTypeUtil.BOOLEAN_TYPE).defaultValue(Boolean.FALSE.toString()));
|
||||
this.cliOptions.add(new CliOption(WITH_INTERFACES,
|
||||
"Setting this property to true will generate interfaces next to the default class implementations.",
|
||||
SchemaTypeUtil.BOOLEAN_TYPE).defaultValue(Boolean.FALSE.toString()));
|
||||
this.cliOptions.add(new CliOption(TAGGED_UNIONS,
|
||||
"Use discriminators to create tagged unions instead of extending interfaces.",
|
||||
SchemaTypeUtil.BOOLEAN_TYPE).defaultValue(Boolean.FALSE.toString()));
|
||||
this.cliOptions.add(new CliOption(NG_VERSION, "The version of Angular. Default is '4.3'"));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void addAdditionPropertiesToCodeGenModel(CodegenModel codegenModel, Schema schema) {
|
||||
codegenModel.additionalPropertiesType = getTypeDeclaration((Schema) schema.getAdditionalProperties());
|
||||
addImport(codegenModel, codegenModel.additionalPropertiesType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "typescript-angular";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHelp() {
|
||||
return "Generates a TypeScript Angular (2.x or 4.x) client library.";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processOpts() {
|
||||
super.processOpts();
|
||||
supportingFiles.add(
|
||||
new SupportingFile("models.mustache", modelPackage().replace('.', File.separatorChar), "models.ts"));
|
||||
supportingFiles
|
||||
.add(new SupportingFile("apis.mustache", apiPackage().replace('.', File.separatorChar), "api.ts"));
|
||||
supportingFiles.add(new SupportingFile("index.mustache", getIndexDirectory(), "index.ts"));
|
||||
supportingFiles.add(new SupportingFile("api.module.mustache", getIndexDirectory(), "api.module.ts"));
|
||||
supportingFiles.add(new SupportingFile("configuration.mustache", getIndexDirectory(), "configuration.ts"));
|
||||
supportingFiles.add(new SupportingFile("variables.mustache", getIndexDirectory(), "variables.ts"));
|
||||
supportingFiles.add(new SupportingFile("encoder.mustache", getIndexDirectory(), "encoder.ts"));
|
||||
supportingFiles.add(new SupportingFile("gitignore", "", ".gitignore"));
|
||||
supportingFiles.add(new SupportingFile("git_push.sh.mustache", "", "git_push.sh"));
|
||||
supportingFiles.add(new SupportingFile("README.mustache", getIndexDirectory(), "README.md"));
|
||||
|
||||
if (additionalProperties.containsKey(NPM_NAME)) {
|
||||
addNpmPackageGeneration();
|
||||
}
|
||||
|
||||
if (additionalProperties.containsKey(WITH_INTERFACES)) {
|
||||
boolean withInterfaces = Boolean.parseBoolean(additionalProperties.get(WITH_INTERFACES).toString());
|
||||
if (withInterfaces) {
|
||||
apiTemplateFiles.put("apiInterface.mustache", "Interface.ts");
|
||||
}
|
||||
}
|
||||
|
||||
if (additionalProperties.containsKey(TAGGED_UNIONS)) {
|
||||
taggedUnions = Boolean.parseBoolean(additionalProperties.get(TAGGED_UNIONS).toString());
|
||||
}
|
||||
|
||||
// determine NG version
|
||||
SemVer ngVersion;
|
||||
if (additionalProperties.containsKey(NG_VERSION)) {
|
||||
ngVersion = new SemVer(additionalProperties.get(NG_VERSION).toString());
|
||||
} else {
|
||||
ngVersion = new SemVer("4.3.0");
|
||||
LOGGER.info("generating code for Angular {} ...", ngVersion);
|
||||
LOGGER.info(" (you can select the angular version by setting the additionalProperty ngVersion)");
|
||||
}
|
||||
additionalProperties.put(NG_VERSION, ngVersion);
|
||||
additionalProperties.put("injectionToken", ngVersion.atLeast("4.0.0") ? "InjectionToken" : "OpaqueToken");
|
||||
additionalProperties.put("injectionTokenTyped", ngVersion.atLeast("4.0.0"));
|
||||
additionalProperties.put("useHttpClient", ngVersion.atLeast("4.3.0"));
|
||||
if (!ngVersion.atLeast("4.3.0")) {
|
||||
supportingFiles.add(new SupportingFile("rxjs-operators.mustache", getIndexDirectory(), "rxjs-operators.ts"));
|
||||
}
|
||||
}
|
||||
|
||||
private void addNpmPackageGeneration() {
|
||||
if (additionalProperties.containsKey(NPM_NAME)) {
|
||||
this.setNpmName(additionalProperties.get(NPM_NAME).toString());
|
||||
}
|
||||
|
||||
if (additionalProperties.containsKey(NPM_VERSION)) {
|
||||
this.setNpmVersion(additionalProperties.get(NPM_VERSION).toString());
|
||||
}
|
||||
|
||||
if (additionalProperties.containsKey(SNAPSHOT)
|
||||
&& Boolean.valueOf(additionalProperties.get(SNAPSHOT).toString())) {
|
||||
this.setNpmVersion(npmVersion + "-SNAPSHOT." + SNAPSHOT_SUFFIX_FORMAT.format(new Date()));
|
||||
}
|
||||
additionalProperties.put(NPM_VERSION, npmVersion);
|
||||
|
||||
if (additionalProperties.containsKey(NPM_REPOSITORY)) {
|
||||
this.setNpmRepository(additionalProperties.get(NPM_REPOSITORY).toString());
|
||||
}
|
||||
|
||||
//Files for building our lib
|
||||
supportingFiles.add(new SupportingFile("package.mustache", getIndexDirectory(), "package.json"));
|
||||
supportingFiles.add(new SupportingFile("typings.mustache", getIndexDirectory(), "typings.json"));
|
||||
supportingFiles.add(new SupportingFile("tsconfig.mustache", getIndexDirectory(), "tsconfig.json"));
|
||||
}
|
||||
|
||||
private String getIndexDirectory() {
|
||||
String indexPackage = modelPackage.substring(0, Math.max(0, modelPackage.lastIndexOf('.')));
|
||||
return indexPackage.replace('.', File.separatorChar);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDataTypeFile(final String dataType) {
|
||||
return dataType != null && dataType.equals("Blob");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTypeDeclaration(Schema p) {
|
||||
if (p instanceof FileSchema) {
|
||||
return "Blob";
|
||||
} else if (!StringUtils.isEmpty(p.get$ref())) {
|
||||
return "any";
|
||||
} else {
|
||||
return super.getTypeDeclaration(p);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getSchemaType(Schema p) {
|
||||
String openAPIType = super.getSchemaType(p);
|
||||
if (isLanguagePrimitive(openAPIType) || isLanguageGenericType(openAPIType)) {
|
||||
return openAPIType;
|
||||
}
|
||||
applyLocalTypeMapping(openAPIType);
|
||||
return openAPIType;
|
||||
}
|
||||
|
||||
private String applyLocalTypeMapping(String type) {
|
||||
if (typeMapping.containsKey(type)) {
|
||||
type = typeMapping.get(type);
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
private boolean isLanguagePrimitive(String type) {
|
||||
return languageSpecificPrimitives.contains(type);
|
||||
}
|
||||
|
||||
private boolean isLanguageGenericType(String type) {
|
||||
for (String genericType : languageGenericTypes) {
|
||||
if (type.startsWith(genericType + "<")) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postProcessParameter(CodegenParameter parameter) {
|
||||
super.postProcessParameter(parameter);
|
||||
parameter.dataType = applyLocalTypeMapping(parameter.dataType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> postProcessOperations(Map<String, Object> operations) {
|
||||
Map<String, Object> objs = (Map<String, Object>) operations.get("operations");
|
||||
|
||||
// Add filename information for api imports
|
||||
objs.put("apiFilename", getApiFilenameFromClassname(objs.get("classname").toString()));
|
||||
|
||||
List<CodegenOperation> ops = (List<CodegenOperation>) objs.get("operation");
|
||||
for (CodegenOperation op : ops) {
|
||||
if ((boolean) additionalProperties.get("useHttpClient")) {
|
||||
op.httpMethod = op.httpMethod.toLowerCase(Locale.ENGLISH);
|
||||
} else {
|
||||
// Convert httpMethod to Angular's RequestMethod enum
|
||||
// https://angular.io/docs/ts/latest/api/http/index/RequestMethod-enum.html
|
||||
switch (op.httpMethod) {
|
||||
case "GET":
|
||||
op.httpMethod = "RequestMethod.Get";
|
||||
break;
|
||||
case "POST":
|
||||
op.httpMethod = "RequestMethod.Post";
|
||||
break;
|
||||
case "PUT":
|
||||
op.httpMethod = "RequestMethod.Put";
|
||||
break;
|
||||
case "DELETE":
|
||||
op.httpMethod = "RequestMethod.Delete";
|
||||
break;
|
||||
case "OPTIONS":
|
||||
op.httpMethod = "RequestMethod.Options";
|
||||
break;
|
||||
case "HEAD":
|
||||
op.httpMethod = "RequestMethod.Head";
|
||||
break;
|
||||
case "PATCH":
|
||||
op.httpMethod = "RequestMethod.Patch";
|
||||
break;
|
||||
default:
|
||||
throw new RuntimeException("Unknown HTTP Method " + op.httpMethod + " not allowed");
|
||||
}
|
||||
}
|
||||
|
||||
// Prep a string buffer where we're going to set up our new version of the string.
|
||||
StringBuilder pathBuffer = new StringBuilder();
|
||||
StringBuilder parameterName = new StringBuilder();
|
||||
int insideCurly = 0;
|
||||
|
||||
// Iterate through existing string, one character at a time.
|
||||
for (int i = 0; i < op.path.length(); i++) {
|
||||
switch (op.path.charAt(i)) {
|
||||
case '{':
|
||||
// We entered curly braces, so track that.
|
||||
insideCurly++;
|
||||
|
||||
// Add the more complicated component instead of just the brace.
|
||||
pathBuffer.append("${encodeURIComponent(String(");
|
||||
break;
|
||||
case '}':
|
||||
// We exited curly braces, so track that.
|
||||
insideCurly--;
|
||||
|
||||
// Add the more complicated component instead of just the brace.
|
||||
pathBuffer.append(toVarName(parameterName.toString()));
|
||||
pathBuffer.append("))}");
|
||||
parameterName.setLength(0);
|
||||
break;
|
||||
default:
|
||||
if (insideCurly > 0) {
|
||||
parameterName.append(op.path.charAt(i));
|
||||
} else {
|
||||
pathBuffer.append(op.path.charAt(i));
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Overwrite path to TypeScript template string, after applying everything we just did.
|
||||
op.path = pathBuffer.toString();
|
||||
}
|
||||
|
||||
// Add additional filename information for model imports in the services
|
||||
List<Map<String, Object>> imports = (List<Map<String, Object>>) operations.get("imports");
|
||||
for (Map<String, Object> im : imports) {
|
||||
im.put("filename", im.get("import"));
|
||||
im.put("classname", getModelnameFromModelFilename(im.get("filename").toString()));
|
||||
}
|
||||
|
||||
return operations;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> postProcessModels(Map<String, Object> objs) {
|
||||
Map<String, Object> result = super.postProcessModels(objs);
|
||||
|
||||
return postProcessModelsEnum(result);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> postProcessAllModels(Map<String, Object> objs) {
|
||||
Map<String, Object> result = super.postProcessAllModels(objs);
|
||||
|
||||
for (Map.Entry<String, Object> entry : result.entrySet()) {
|
||||
Map<String, Object> inner = (Map<String, Object>) entry.getValue();
|
||||
List<Map<String, Object>> models = (List<Map<String, Object>>) inner.get("models");
|
||||
for (Map<String, Object> mo : models) {
|
||||
CodegenModel cm = (CodegenModel) mo.get("model");
|
||||
if (taggedUnions) {
|
||||
mo.put(TAGGED_UNIONS, true);
|
||||
if (cm.discriminator != null && cm.children != null) {
|
||||
for (CodegenModel child : cm.children) {
|
||||
cm.imports.add(child.classname);
|
||||
}
|
||||
}
|
||||
if (cm.parent != null) {
|
||||
cm.imports.remove(cm.parent);
|
||||
}
|
||||
}
|
||||
// Add additional filename information for imports
|
||||
mo.put("tsImports", toTsImports(cm, cm.imports));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private List<Map<String, String>> toTsImports(CodegenModel cm, Set<String> imports) {
|
||||
List<Map<String, String>> tsImports = new ArrayList<>();
|
||||
for (String im : imports) {
|
||||
if (!im.equals(cm.classname)) {
|
||||
HashMap<String, String> tsImport = new HashMap<>();
|
||||
tsImport.put("classname", im);
|
||||
tsImport.put("filename", toModelFilename(im));
|
||||
tsImports.add(tsImport);
|
||||
}
|
||||
}
|
||||
return tsImports;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toApiName(String name) {
|
||||
if (name.length() == 0) {
|
||||
return "DefaultService";
|
||||
}
|
||||
return initialCaps(name) + "Service";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toApiFilename(String name) {
|
||||
if (name.length() == 0) {
|
||||
return "default.service";
|
||||
}
|
||||
return camelize(name, true) + ".service";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toApiImport(String name) {
|
||||
return apiPackage() + "/" + toApiFilename(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toModelFilename(String name) {
|
||||
return camelize(toModelName(name), true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toModelImport(String name) {
|
||||
return modelPackage() + "/" + toModelFilename(name);
|
||||
}
|
||||
|
||||
public String getNpmName() {
|
||||
return npmName;
|
||||
}
|
||||
|
||||
public void setNpmName(String npmName) {
|
||||
this.npmName = npmName;
|
||||
}
|
||||
|
||||
public String getNpmVersion() {
|
||||
return npmVersion;
|
||||
}
|
||||
|
||||
public void setNpmVersion(String npmVersion) {
|
||||
this.npmVersion = npmVersion;
|
||||
}
|
||||
|
||||
public String getNpmRepository() {
|
||||
return npmRepository;
|
||||
}
|
||||
|
||||
public void setNpmRepository(String npmRepository) {
|
||||
this.npmRepository = npmRepository;
|
||||
}
|
||||
|
||||
private String getApiFilenameFromClassname(String classname) {
|
||||
String name = classname.substring(0, classname.length() - "Service".length());
|
||||
return toApiFilename(name);
|
||||
}
|
||||
|
||||
private String getModelnameFromModelFilename(String filename) {
|
||||
String name = filename.substring((modelPackage() + "/").length());
|
||||
return camelize(name);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
package org.openapitools.codegen.languages;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import io.swagger.v3.parser.util.SchemaTypeUtil;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.openapitools.codegen.CliOption;
|
||||
import org.openapitools.codegen.CodegenModel;
|
||||
import org.openapitools.codegen.CodegenParameter;
|
||||
import org.openapitools.codegen.CodegenOperation;
|
||||
import org.openapitools.codegen.SupportingFile;
|
||||
import org.openapitools.codegen.utils.SemVer;
|
||||
|
||||
import io.swagger.v3.oas.models.media.*;
|
||||
import io.swagger.v3.oas.models.PathItem;
|
||||
import io.swagger.v3.oas.models.PathItem.HttpMethod;
|
||||
import io.swagger.v3.oas.models.*;
|
||||
import io.swagger.v3.oas.models.parameters.*;
|
||||
import io.swagger.v3.oas.models.info.*;
|
||||
|
||||
public class TypeScriptAngularJsClientCodegen extends AbstractTypeScriptClientCodegen {
|
||||
|
||||
public TypeScriptAngularJsClientCodegen() {
|
||||
super();
|
||||
outputFolder = "generated-code/typescript-angularjs";
|
||||
modelTemplateFiles.put("model.mustache", ".ts");
|
||||
apiTemplateFiles.put("api.mustache", ".ts");
|
||||
embeddedTemplateDir = templateDir = "typescript-angularjs";
|
||||
apiPackage = "api";
|
||||
modelPackage = "model";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "typescript-angularjs";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHelp() {
|
||||
return "Generates a TypeScript AngularJS client library.";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processOpts() {
|
||||
super.processOpts();
|
||||
supportingFiles.add(new SupportingFile("models.mustache", modelPackage().replace('.', File.separatorChar), "models.ts"));
|
||||
supportingFiles.add(new SupportingFile("apis.mustache", apiPackage().replace('.', File.separatorChar), "api.ts"));
|
||||
supportingFiles.add(new SupportingFile("index.mustache", getIndexDirectory(), "index.ts"));
|
||||
supportingFiles.add(new SupportingFile("api.module.mustache", getIndexDirectory(), "api.module.ts"));
|
||||
supportingFiles.add(new SupportingFile("git_push.sh.mustache", "", "git_push.sh"));
|
||||
supportingFiles.add(new SupportingFile("gitignore", "", ".gitignore"));
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSchemaType(Schema p) {
|
||||
String openAPIType = super.getSchemaType(p);
|
||||
if (isLanguagePrimitive(openAPIType) || isLanguageGenericType(openAPIType)) {
|
||||
return openAPIType;
|
||||
}
|
||||
return addModelPrefix(openAPIType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postProcessParameter(CodegenParameter parameter) {
|
||||
super.postProcessParameter(parameter);
|
||||
parameter.dataType = addModelPrefix(parameter.dataType);
|
||||
}
|
||||
|
||||
private String getIndexDirectory() {
|
||||
String indexPackage = modelPackage.substring(0, Math.max(0, modelPackage.lastIndexOf('.')));
|
||||
return indexPackage.replace('.', File.separatorChar);
|
||||
}
|
||||
|
||||
private String addModelPrefix(String openAPIType) {
|
||||
String type = null;
|
||||
if (typeMapping.containsKey(openAPIType)) {
|
||||
type = typeMapping.get(openAPIType);
|
||||
} else {
|
||||
type = openAPIType;
|
||||
}
|
||||
|
||||
if (!isLanguagePrimitive(type) && !isLanguageGenericType(type)) {
|
||||
type = "models." + openAPIType;
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
private boolean isLanguagePrimitive(String type) {
|
||||
return languageSpecificPrimitives.contains(type);
|
||||
}
|
||||
|
||||
private boolean isLanguageGenericType(String type) {
|
||||
for (String genericType : languageGenericTypes) {
|
||||
if (type.startsWith(genericType + "<")) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,140 @@
|
||||
package org.openapitools.codegen.languages;
|
||||
|
||||
import io.swagger.v3.parser.util.SchemaTypeUtil;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.openapitools.codegen.*;
|
||||
|
||||
import io.swagger.v3.oas.models.media.*;
|
||||
import io.swagger.v3.oas.models.PathItem;
|
||||
import io.swagger.v3.oas.models.PathItem.HttpMethod;
|
||||
import io.swagger.v3.oas.models.*;
|
||||
import io.swagger.v3.oas.models.parameters.*;
|
||||
import io.swagger.v3.oas.models.info.*;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.TreeSet;
|
||||
|
||||
public class TypeScriptAureliaClientCodegen extends AbstractTypeScriptClientCodegen {
|
||||
|
||||
public static final String NPM_NAME = "npmName";
|
||||
public static final String NPM_VERSION = "npmVersion";
|
||||
|
||||
protected String npmName = null;
|
||||
protected String npmVersion = "1.0.0";
|
||||
|
||||
public TypeScriptAureliaClientCodegen() {
|
||||
super();
|
||||
|
||||
apiTemplateFiles.put("api.mustache", ".ts");
|
||||
|
||||
// clear import mapping (from default generator) as TS does not use it
|
||||
// at the moment
|
||||
importMapping.clear();
|
||||
|
||||
outputFolder = "generated-code/typescript-aurelia";
|
||||
embeddedTemplateDir = templateDir = "typescript-aurelia";
|
||||
this.cliOptions.add(new CliOption(NPM_NAME, "The name under which you want to publish generated npm package"));
|
||||
this.cliOptions.add(new CliOption(NPM_VERSION, "The version of your npm package"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "typescript-aurelia";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHelp() {
|
||||
return "Generates a TypeScript client library for the Aurelia framework (beta).";
|
||||
}
|
||||
|
||||
public String getNpmName() {
|
||||
return npmName;
|
||||
}
|
||||
|
||||
public void setNpmName(String npmName) {
|
||||
this.npmName = npmName;
|
||||
}
|
||||
|
||||
public String getNpmVersion() {
|
||||
return npmVersion;
|
||||
}
|
||||
|
||||
public void setNpmVersion(String npmVersion) {
|
||||
this.npmVersion = npmVersion;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processOpts() {
|
||||
super.processOpts();
|
||||
|
||||
if (additionalProperties.containsKey(NPM_NAME)) {
|
||||
this.setNpmName(additionalProperties.get(NPM_NAME).toString());
|
||||
}
|
||||
|
||||
if (additionalProperties.containsKey(NPM_VERSION)) {
|
||||
this.setNpmVersion(additionalProperties.get(NPM_VERSION).toString());
|
||||
}
|
||||
|
||||
// Set supporting files
|
||||
supportingFiles.add(new SupportingFile("models.mustache", "", "models.ts"));
|
||||
supportingFiles.add(new SupportingFile("index.ts.mustache", "", "index.ts"));
|
||||
supportingFiles.add(new SupportingFile("Api.ts.mustache", "", "Api.ts"));
|
||||
supportingFiles.add(new SupportingFile("AuthStorage.ts.mustache", "", "AuthStorage.ts"));
|
||||
supportingFiles.add(new SupportingFile("git_push.sh.mustache", "", "git_push.sh"));
|
||||
supportingFiles.add(new SupportingFile("README.md", "", "README.md"));
|
||||
supportingFiles.add(new SupportingFile("package.json.mustache", "", "package.json"));
|
||||
supportingFiles.add(new SupportingFile("tsconfig.json.mustache", "", "tsconfig.json"));
|
||||
supportingFiles.add(new SupportingFile("tslint.json.mustache", "", "tslint.json"));
|
||||
supportingFiles.add(new SupportingFile("gitignore", "", ".gitignore"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> postProcessOperations(Map<String, Object> objs) {
|
||||
objs = super.postProcessOperations(objs);
|
||||
|
||||
HashSet<String> modelImports = new HashSet<>();
|
||||
Map<String, Object> operations = (Map<String, Object>) objs.get("operations");
|
||||
List<CodegenOperation> operationList = (List<CodegenOperation>) operations.get("operation");
|
||||
for (CodegenOperation op : operationList) {
|
||||
// Aurelia uses "asGet", "asPost", ... methods; change the method format
|
||||
op.httpMethod = initialCaps(op.httpMethod.toLowerCase());
|
||||
|
||||
// Collect models to be imported
|
||||
for (CodegenParameter param : op.allParams) {
|
||||
if (!param.isPrimitiveType && !param.isListContainer && !param.dataType.equals("any")) {
|
||||
modelImports.add(param.dataType);
|
||||
}
|
||||
}
|
||||
if (op.returnBaseType != null && !op.returnTypeIsPrimitive) {
|
||||
modelImports.add(op.returnBaseType);
|
||||
}
|
||||
}
|
||||
|
||||
objs.put("modelImports", modelImports);
|
||||
|
||||
return objs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> postProcessModels(Map<String, Object> objs) {
|
||||
// process enum in models
|
||||
List<Object> models = (List<Object>) postProcessModelsEnum(objs).get("models");
|
||||
for (Object _mo : models) {
|
||||
Map<String, Object> mo = (Map<String, Object>) _mo;
|
||||
CodegenModel cm = (CodegenModel) mo.get("model");
|
||||
cm.imports = new TreeSet(cm.imports);
|
||||
for (CodegenProperty var : cm.vars) {
|
||||
// name enum with model name, e.g. StatuEnum => PetStatusEnum
|
||||
if (Boolean.TRUE.equals(var.isEnum)) {
|
||||
var.datatypeWithEnum = var.datatypeWithEnum.replace(var.enumName, cm.classname + var.enumName);
|
||||
var.enumName = cm.classname + var.enumName;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return objs;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,147 @@
|
||||
package org.openapitools.codegen.languages;
|
||||
|
||||
import io.swagger.v3.parser.util.SchemaTypeUtil;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.openapitools.codegen.*;
|
||||
|
||||
import io.swagger.v3.oas.models.media.*;
|
||||
import io.swagger.v3.oas.models.PathItem;
|
||||
import io.swagger.v3.oas.models.PathItem.HttpMethod;
|
||||
import io.swagger.v3.oas.models.*;
|
||||
import io.swagger.v3.oas.models.parameters.*;
|
||||
import io.swagger.v3.oas.models.info.*;
|
||||
|
||||
import java.io.File;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.*;
|
||||
|
||||
public class TypeScriptFetchClientCodegen extends AbstractTypeScriptClientCodegen {
|
||||
private static final SimpleDateFormat SNAPSHOT_SUFFIX_FORMAT = new SimpleDateFormat("yyyyMMddHHmm");
|
||||
|
||||
public static final String NPM_NAME = "npmName";
|
||||
public static final String NPM_VERSION = "npmVersion";
|
||||
public static final String NPM_REPOSITORY = "npmRepository";
|
||||
public static final String SNAPSHOT = "snapshot";
|
||||
public static final String WITH_INTERFACES = "withInterfaces";
|
||||
|
||||
protected String npmName = null;
|
||||
protected String npmVersion = "1.0.0";
|
||||
protected String npmRepository = null;
|
||||
|
||||
public TypeScriptFetchClientCodegen() {
|
||||
super();
|
||||
|
||||
// clear import mapping (from default generator) as TS does not use it
|
||||
// at the moment
|
||||
importMapping.clear();
|
||||
|
||||
outputFolder = "generated-code/typescript-fetch";
|
||||
embeddedTemplateDir = templateDir = "typescript-fetch";
|
||||
|
||||
this.cliOptions.add(new CliOption(NPM_NAME, "The name under which you want to publish generated npm package"));
|
||||
this.cliOptions.add(new CliOption(NPM_VERSION, "The version of your npm package"));
|
||||
this.cliOptions.add(new CliOption(NPM_REPOSITORY, "Use this property to set an url your private npmRepo in the package.json"));
|
||||
this.cliOptions.add(new CliOption(SNAPSHOT, "When setting this property to true the version will be suffixed with -SNAPSHOT.yyyyMMddHHmm", SchemaTypeUtil.BOOLEAN_TYPE).defaultValue(Boolean.FALSE.toString()));
|
||||
this.cliOptions.add(new CliOption(WITH_INTERFACES, "Setting this property to true will generate interfaces next to the default class implementations.", SchemaTypeUtil.BOOLEAN_TYPE).defaultValue(Boolean.FALSE.toString()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "typescript-fetch";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHelp() {
|
||||
return "Generates a TypeScript client library using Fetch API (beta).";
|
||||
}
|
||||
|
||||
public String getNpmName() {
|
||||
return npmName;
|
||||
}
|
||||
|
||||
public void setNpmName(String npmName) {
|
||||
this.npmName = npmName;
|
||||
}
|
||||
|
||||
public String getNpmVersion() {
|
||||
return npmVersion;
|
||||
}
|
||||
|
||||
public void setNpmVersion(String npmVersion) {
|
||||
this.npmVersion = npmVersion;
|
||||
}
|
||||
|
||||
public String getNpmRepository() {
|
||||
return npmRepository;
|
||||
}
|
||||
|
||||
public void setNpmRepository(String npmRepository) {
|
||||
this.npmRepository = npmRepository;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processOpts() {
|
||||
super.processOpts();
|
||||
supportingFiles.add(new SupportingFile("index.mustache", "", "index.ts"));
|
||||
supportingFiles.add(new SupportingFile("api.mustache", "", "api.ts"));
|
||||
supportingFiles.add(new SupportingFile("configuration.mustache", "", "configuration.ts"));
|
||||
supportingFiles.add(new SupportingFile("custom.d.mustache", "", "custom.d.ts"));
|
||||
supportingFiles.add(new SupportingFile("git_push.sh.mustache", "", "git_push.sh"));
|
||||
supportingFiles.add(new SupportingFile("gitignore", "", ".gitignore"));
|
||||
|
||||
if (additionalProperties.containsKey(NPM_NAME)) {
|
||||
addNpmPackageGeneration();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTypeDeclaration(Schema p) {
|
||||
Schema inner;
|
||||
if (p instanceof ArraySchema) {
|
||||
inner = ((ArraySchema) p).getItems();
|
||||
return this.getSchemaType(p) + "<" + this.getTypeDeclaration(inner) + ">";
|
||||
} else if (p instanceof MapSchema) {
|
||||
inner = (Schema) p.getAdditionalProperties();
|
||||
return "{ [key: string]: " + this.getTypeDeclaration(inner) + "; }";
|
||||
} else if (p instanceof FileSchema) {
|
||||
return "any";
|
||||
} else if (p instanceof BinarySchema) {
|
||||
return "any";
|
||||
} else if (!StringUtils.isEmpty(p.get$ref())) { // model
|
||||
return "any";
|
||||
} else {
|
||||
return super.getTypeDeclaration(p);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void addAdditionPropertiesToCodeGenModel(CodegenModel codegenModel, Schema schema) {
|
||||
codegenModel.additionalPropertiesType = getTypeDeclaration((Schema) schema.getAdditionalProperties());
|
||||
addImport(codegenModel, codegenModel.additionalPropertiesType);
|
||||
}
|
||||
|
||||
private void addNpmPackageGeneration() {
|
||||
if (additionalProperties.containsKey(NPM_NAME)) {
|
||||
this.setNpmName(additionalProperties.get(NPM_NAME).toString());
|
||||
}
|
||||
|
||||
if (additionalProperties.containsKey(NPM_VERSION)) {
|
||||
this.setNpmVersion(additionalProperties.get(NPM_VERSION).toString());
|
||||
}
|
||||
|
||||
if (additionalProperties.containsKey(SNAPSHOT) && Boolean.valueOf(additionalProperties.get(SNAPSHOT).toString())) {
|
||||
this.setNpmVersion(npmVersion + "-SNAPSHOT." + SNAPSHOT_SUFFIX_FORMAT.format(new Date()));
|
||||
}
|
||||
additionalProperties.put(NPM_VERSION, npmVersion);
|
||||
|
||||
if (additionalProperties.containsKey(NPM_REPOSITORY)) {
|
||||
this.setNpmRepository(additionalProperties.get(NPM_REPOSITORY).toString());
|
||||
}
|
||||
|
||||
//Files for building our lib
|
||||
supportingFiles.add(new SupportingFile("README.mustache", "", "README.md"));
|
||||
supportingFiles.add(new SupportingFile("package.mustache", "", "package.json"));
|
||||
supportingFiles.add(new SupportingFile("tsconfig.mustache", "", "tsconfig.json"));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,195 @@
|
||||
package org.openapitools.codegen.languages;
|
||||
|
||||
import io.swagger.v3.parser.util.SchemaTypeUtil;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.openapitools.codegen.*;
|
||||
|
||||
import io.swagger.v3.oas.models.media.*;
|
||||
import io.swagger.v3.oas.models.PathItem;
|
||||
import io.swagger.v3.oas.models.PathItem.HttpMethod;
|
||||
import io.swagger.v3.oas.models.*;
|
||||
import io.swagger.v3.oas.models.parameters.*;
|
||||
import io.swagger.v3.oas.models.info.*;
|
||||
|
||||
import java.io.File;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
|
||||
public class TypeScriptJqueryClientCodegen extends AbstractTypeScriptClientCodegen {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(TypeScriptJqueryClientCodegen.class);
|
||||
private static final SimpleDateFormat SNAPSHOT_SUFFIX_FORMAT = new SimpleDateFormat("yyyyMMddHHmm");
|
||||
|
||||
public static final String NPM_NAME = "npmName";
|
||||
public static final String NPM_VERSION = "npmVersion";
|
||||
public static final String NPM_REPOSITORY = "npmRepository";
|
||||
public static final String SNAPSHOT = "snapshot";
|
||||
public static final String JQUERY_ALREADY_IMPORTED = "jqueryAlreadyImported";
|
||||
|
||||
protected String npmName = null;
|
||||
protected String npmVersion = "1.0.0";
|
||||
protected String npmRepository = null;
|
||||
|
||||
public TypeScriptJqueryClientCodegen() {
|
||||
super();
|
||||
|
||||
modelTemplateFiles.put("model.mustache", ".ts");
|
||||
apiTemplateFiles.put("api.mustache", ".ts");
|
||||
typeMapping.put("Date", "Date");
|
||||
apiPackage = "api";
|
||||
modelPackage = "model";
|
||||
|
||||
outputFolder = "generated-code/typescript-jquery";
|
||||
embeddedTemplateDir = templateDir = "typescript-jquery";
|
||||
|
||||
this.cliOptions.add(new CliOption(NPM_NAME, "The name under which you want to publish generated npm package"));
|
||||
this.cliOptions.add(new CliOption(NPM_VERSION, "The version of your npm package"));
|
||||
this.cliOptions.add(new CliOption(NPM_REPOSITORY, "Use this property to set an url your private npmRepo in the package.json"));
|
||||
this.cliOptions.add(new CliOption(SNAPSHOT,
|
||||
"When setting this property to true the version will be suffixed with -SNAPSHOT.yyyyMMddHHmm",
|
||||
SchemaTypeUtil.BOOLEAN_TYPE).defaultValue(Boolean.FALSE.toString()));
|
||||
this.cliOptions.add(new CliOption(JQUERY_ALREADY_IMPORTED,
|
||||
"When using this in legacy app using mix of typescript and javascript, this will only declare jquery and not import it",
|
||||
SchemaTypeUtil.BOOLEAN_TYPE).defaultValue(Boolean.FALSE.toString()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "typescript-jquery";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHelp() {
|
||||
return "Generates a TypeScript jquery client library.";
|
||||
}
|
||||
|
||||
public void setNpmName(String npmName) {
|
||||
this.npmName = npmName;
|
||||
}
|
||||
|
||||
public void setNpmVersion(String npmVersion) {
|
||||
this.npmVersion = npmVersion;
|
||||
}
|
||||
|
||||
public String getNpmVersion() {
|
||||
return npmVersion;
|
||||
}
|
||||
|
||||
public String getNpmRepository() {
|
||||
return npmRepository;
|
||||
}
|
||||
|
||||
public void setNpmRepository(String npmRepository) {
|
||||
this.npmRepository = npmRepository;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processOpts() {
|
||||
super.processOpts();
|
||||
|
||||
supportingFiles.add(new SupportingFile("git_push.sh.mustache", "", "git_push.sh"));
|
||||
supportingFiles.add(new SupportingFile("models.mustache", modelPackage().replace('.', File.separatorChar), "models.ts"));
|
||||
supportingFiles.add(new SupportingFile("apis.mustache", apiPackage().replace('.', File.separatorChar), "api.ts"));
|
||||
supportingFiles.add(new SupportingFile("configuration.mustache", getIndexDirectory(), "configuration.ts"));
|
||||
supportingFiles.add(new SupportingFile("index.mustache", getIndexDirectory(), "index.ts"));
|
||||
supportingFiles.add(new SupportingFile("variables.mustache", getIndexDirectory(), "variables.ts"));
|
||||
|
||||
//LOGGER.warn("check additionals: " + additionalProperties.get(NPM_NAME));
|
||||
if (additionalProperties.containsKey(NPM_NAME)) {
|
||||
addNpmPackageGeneration();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSchemaType(Schema p) {
|
||||
String openAPIType = super.getSchemaType(p);
|
||||
if (p instanceof StringSchema) {
|
||||
if (p.getEnum() != null) {
|
||||
return openAPIType;
|
||||
}
|
||||
}
|
||||
if (isLanguagePrimitive(openAPIType) || isLanguageGenericType(openAPIType)) {
|
||||
return openAPIType;
|
||||
}
|
||||
return addModelPrefix(openAPIType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postProcessParameter(CodegenParameter parameter) {
|
||||
super.postProcessParameter(parameter);
|
||||
|
||||
if (!parameter.isEnum) {
|
||||
parameter.dataType = addModelPrefix(parameter.dataType);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void addAdditionPropertiesToCodeGenModel(CodegenModel codegenModel, Schema schema) {
|
||||
codegenModel.additionalPropertiesType = getSchemaType((Schema) schema.getAdditionalProperties());
|
||||
addImport(codegenModel, codegenModel.additionalPropertiesType);
|
||||
}
|
||||
|
||||
private String addModelPrefix(String openAPIType) {
|
||||
String type = null;
|
||||
if (typeMapping.containsKey(openAPIType)) {
|
||||
type = typeMapping.get(openAPIType);
|
||||
} else {
|
||||
type = openAPIType;
|
||||
}
|
||||
|
||||
if (!isLanguagePrimitive(type) && !isLanguageGenericType(type)) {
|
||||
type = "models." + openAPIType;
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
private boolean isLanguagePrimitive(String type) {
|
||||
return languageSpecificPrimitives.contains(type);
|
||||
}
|
||||
|
||||
private boolean isLanguageGenericType(String type) {
|
||||
for (String genericType : languageGenericTypes) {
|
||||
if (type.startsWith(genericType + "<")) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private String getPackageRootDirectory() {
|
||||
String indexPackage = modelPackage.substring(0, Math.max(0, modelPackage.lastIndexOf('.')));
|
||||
return indexPackage.replace('.', File.separatorChar);
|
||||
}
|
||||
|
||||
private void addNpmPackageGeneration() {
|
||||
if (additionalProperties.containsKey(NPM_NAME)) {
|
||||
this.setNpmName(additionalProperties.get(NPM_NAME).toString());
|
||||
}
|
||||
|
||||
if (additionalProperties.containsKey(NPM_VERSION)) {
|
||||
this.setNpmVersion(additionalProperties.get(NPM_VERSION).toString());
|
||||
}
|
||||
|
||||
if (additionalProperties.containsKey(SNAPSHOT) && Boolean.valueOf(additionalProperties.get(SNAPSHOT).toString())) {
|
||||
this.setNpmVersion(npmVersion + "-SNAPSHOT." + SNAPSHOT_SUFFIX_FORMAT.format(new Date()));
|
||||
}
|
||||
additionalProperties.put(NPM_VERSION, npmVersion);
|
||||
|
||||
if (additionalProperties.containsKey(NPM_REPOSITORY)) {
|
||||
this.setNpmRepository(additionalProperties.get(NPM_REPOSITORY).toString());
|
||||
}
|
||||
|
||||
//Files for building our lib
|
||||
supportingFiles.add(new SupportingFile("README.mustache", getPackageRootDirectory(), "README.md"));
|
||||
supportingFiles.add(new SupportingFile("package.mustache", getPackageRootDirectory(), "package.json"));
|
||||
supportingFiles.add(new SupportingFile("typings.mustache", getPackageRootDirectory(), "typings.json"));
|
||||
supportingFiles.add(new SupportingFile("tsconfig.mustache", getPackageRootDirectory(), "tsconfig.json"));
|
||||
}
|
||||
|
||||
private String getIndexDirectory() {
|
||||
String indexPackage = modelPackage.substring(0, Math.max(0, modelPackage.lastIndexOf('.')));
|
||||
return indexPackage.replace('.', File.separatorChar);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,137 @@
|
||||
package org.openapitools.codegen.languages;
|
||||
|
||||
import io.swagger.v3.parser.util.SchemaTypeUtil;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.File;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
|
||||
import org.openapitools.codegen.*;
|
||||
|
||||
import io.swagger.v3.oas.models.media.*;
|
||||
import io.swagger.v3.oas.models.PathItem;
|
||||
import io.swagger.v3.oas.models.PathItem.HttpMethod;
|
||||
import io.swagger.v3.oas.models.*;
|
||||
import io.swagger.v3.oas.models.parameters.*;
|
||||
import io.swagger.v3.oas.models.info.*;
|
||||
|
||||
public class TypeScriptNodeClientCodegen extends AbstractTypeScriptClientCodegen {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(TypeScriptNodeClientCodegen.class);
|
||||
private static final SimpleDateFormat SNAPSHOT_SUFFIX_FORMAT = new SimpleDateFormat("yyyyMMddHHmm");
|
||||
|
||||
public static final String NPM_NAME = "npmName";
|
||||
public static final String NPM_VERSION = "npmVersion";
|
||||
public static final String NPM_REPOSITORY = "npmRepository";
|
||||
public static final String SNAPSHOT = "snapshot";
|
||||
|
||||
protected String npmName = null;
|
||||
protected String npmVersion = "1.0.0";
|
||||
protected String npmRepository = null;
|
||||
|
||||
public TypeScriptNodeClientCodegen() {
|
||||
super();
|
||||
|
||||
typeMapping.put("file", "Buffer");
|
||||
|
||||
// clear import mapping (from default generator) as TS does not use it
|
||||
// at the moment
|
||||
importMapping.clear();
|
||||
|
||||
outputFolder = "generated-code/typescript-node";
|
||||
embeddedTemplateDir = templateDir = "typescript-node";
|
||||
|
||||
this.cliOptions.add(new CliOption(NPM_NAME, "The name under which you want to publish generated npm package"));
|
||||
this.cliOptions.add(new CliOption(NPM_VERSION, "The version of your npm package"));
|
||||
this.cliOptions.add(new CliOption(NPM_REPOSITORY, "Use this property to set an url your private npmRepo in the package.json"));
|
||||
this.cliOptions.add(new CliOption(SNAPSHOT,
|
||||
"When setting this property to true the version will be suffixed with -SNAPSHOT.yyyyMMddHHmm",
|
||||
SchemaTypeUtil.BOOLEAN_TYPE).defaultValue(Boolean.FALSE.toString()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "typescript-node";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHelp() {
|
||||
return "Generates a TypeScript NodeJS client library.";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDataTypeFile(final String dataType) {
|
||||
return "Buffer".equals(dataType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTypeDeclaration(Schema p) {
|
||||
if (p instanceof FileSchema) {
|
||||
return "Buffer";
|
||||
} else if (p instanceof BinarySchema) {
|
||||
return "Buffer";
|
||||
}
|
||||
return super.getTypeDeclaration(p);
|
||||
}
|
||||
|
||||
public void setNpmName(String npmName) {
|
||||
this.npmName = npmName;
|
||||
}
|
||||
|
||||
public void setNpmVersion(String npmVersion) {
|
||||
this.npmVersion = npmVersion;
|
||||
}
|
||||
|
||||
public String getNpmVersion() {
|
||||
return npmVersion;
|
||||
}
|
||||
|
||||
public String getNpmRepository() {
|
||||
return npmRepository;
|
||||
}
|
||||
|
||||
public void setNpmRepository(String npmRepository) {
|
||||
this.npmRepository = npmRepository;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processOpts() {
|
||||
super.processOpts();
|
||||
supportingFiles.add(new SupportingFile("api.mustache", null, "api.ts"));
|
||||
supportingFiles.add(new SupportingFile("git_push.sh.mustache", "", "git_push.sh"));
|
||||
supportingFiles.add(new SupportingFile("gitignore", "", ".gitignore"));
|
||||
|
||||
if (additionalProperties.containsKey(NPM_NAME)) {
|
||||
addNpmPackageGeneration();
|
||||
}
|
||||
}
|
||||
|
||||
private void addNpmPackageGeneration() {
|
||||
if (additionalProperties.containsKey(NPM_NAME)) {
|
||||
this.setNpmName(additionalProperties.get(NPM_NAME).toString());
|
||||
}
|
||||
|
||||
if (additionalProperties.containsKey(NPM_VERSION)) {
|
||||
this.setNpmVersion(additionalProperties.get(NPM_VERSION).toString());
|
||||
}
|
||||
|
||||
if (additionalProperties.containsKey(SNAPSHOT) && Boolean.valueOf(additionalProperties.get(SNAPSHOT).toString())) {
|
||||
this.setNpmVersion(npmVersion + "-SNAPSHOT." + SNAPSHOT_SUFFIX_FORMAT.format(new Date()));
|
||||
}
|
||||
additionalProperties.put(NPM_VERSION, npmVersion);
|
||||
|
||||
if (additionalProperties.containsKey(NPM_REPOSITORY)) {
|
||||
this.setNpmRepository(additionalProperties.get(NPM_REPOSITORY).toString());
|
||||
}
|
||||
|
||||
//Files for building our lib
|
||||
supportingFiles.add(new SupportingFile("package.mustache", getPackageRootDirectory(), "package.json"));
|
||||
supportingFiles.add(new SupportingFile("tsconfig.mustache", getPackageRootDirectory(), "tsconfig.json"));
|
||||
}
|
||||
|
||||
private String getPackageRootDirectory() {
|
||||
String indexPackage = modelPackage.substring(0, Math.max(0, modelPackage.lastIndexOf('.')));
|
||||
return indexPackage.replace('.', File.separatorChar);
|
||||
}
|
||||
}
|
||||
@@ -1,16 +1,42 @@
|
||||
org.openapitools.codegen.languages.AndroidClientCodegen
|
||||
org.openapitools.codegen.languages.Apache2ConfigCodegen
|
||||
org.openapitools.codegen.languages.AkkaScalaClientCodegen
|
||||
org.openapitools.codegen.languages.BashClientCodegen
|
||||
org.openapitools.codegen.languages.ClojureClientCodegen
|
||||
org.openapitools.codegen.languages.ConfluenceWikiCodegen
|
||||
org.openapitools.codegen.languages.CppQt5ClientCodegen
|
||||
org.openapitools.codegen.languages.CppRestbedServerCodegen
|
||||
org.openapitools.codegen.languages.CppRestClientCodegen
|
||||
org.openapitools.codegen.languages.CppPistacheServerCodegen
|
||||
org.openapitools.codegen.languages.DartClientCodegen
|
||||
org.openapitools.codegen.languages.ElixirClientCodegen
|
||||
org.openapitools.codegen.languages.KotlinClientCodegen
|
||||
org.openapitools.codegen.languages.KotlinServerCodegen
|
||||
org.openapitools.codegen.languages.HaskellHttpClientCodegen
|
||||
org.openapitools.codegen.languages.HaskellServantCodegen
|
||||
org.openapitools.codegen.languages.LumenServerCodegen
|
||||
org.openapitools.codegen.languages.JavascriptClientCodegen
|
||||
org.openapitools.codegen.languages.LuaClientCodegen
|
||||
org.openapitools.codegen.languages.ObjcClientCodegen
|
||||
org.openapitools.codegen.languages.PerlClientCodegen
|
||||
org.openapitools.codegen.languages.PhpClientCodegen
|
||||
org.openapitools.codegen.languages.PhpLumenServerCodegen
|
||||
org.openapitools.codegen.languages.PhpSlimServerCodegen
|
||||
org.openapitools.codegen.languages.PhpSilexServerCodegen
|
||||
org.openapitools.codegen.languages.PhpSymfonyServerCodegen
|
||||
org.openapitools.codegen.languages.PhpZendExpressivePathHandlerServerCodegen
|
||||
org.openapitools.codegen.languages.PowerShellClientCodegen
|
||||
org.openapitools.codegen.languages.PythonClientCodegen
|
||||
org.openapitools.codegen.languages.PythonFlaskConnexionServerCodegen
|
||||
org.openapitools.codegen.languages.Qt5CPPClientCodegen
|
||||
org.openapitools.codegen.languages.RClientCodegen
|
||||
org.openapitools.codegen.languages.Rails5ServerCodegen
|
||||
org.openapitools.codegen.languages.RubyOnRailsServerCodegen
|
||||
org.openapitools.codegen.languages.RubyClientCodegen
|
||||
org.openapitools.codegen.languages.SlimFrameworkServerCodegen
|
||||
org.openapitools.codegen.languages.SilexServerCodegen
|
||||
org.openapitools.codegen.languages.ScalaClientCodegen
|
||||
org.openapitools.codegen.languages.SinatraServerCodegen
|
||||
org.openapitools.codegen.languages.TizenClientCodegen
|
||||
org.openapitools.codegen.languages.TypeScriptAngularClientCodegen
|
||||
org.openapitools.codegen.languages.TypeScriptAngularJsClientCodegen
|
||||
org.openapitools.codegen.languages.TypeScriptAureliaClientCodegen
|
||||
org.openapitools.codegen.languages.TypeScriptFetchClientCodegen
|
||||
org.openapitools.codegen.languages.TypeScriptJqueryClientCodegen
|
||||
org.openapitools.codegen.languages.TypeScriptNodeClientCodegen
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
QT += network
|
||||
|
||||
HEADERS += \
|
||||
# Models
|
||||
{{#models}}
|
||||
{{#model}}
|
||||
$${PWD}/{{classname}}.h \
|
||||
{{/model}}
|
||||
{{/models}}
|
||||
# APIs
|
||||
{{#apiInfo}}
|
||||
{{#apis}}
|
||||
{{#operations}}
|
||||
$${PWD}/{{classname}}.h \
|
||||
{{/operations}}
|
||||
{{/apis}}
|
||||
{{/apiInfo}}
|
||||
# Others
|
||||
$${PWD}/{{prefix}}Helpers.h \
|
||||
$${PWD}/{{prefix}}HttpRequest.h \
|
||||
$${PWD}/{{prefix}}ModelFactory.h \
|
||||
$${PWD}/{{prefix}}Object.h \
|
||||
$${PWD}/{{prefix}}QObjectWrapper.h
|
||||
|
||||
SOURCES += \
|
||||
# Models
|
||||
{{#models}}
|
||||
{{#model}}
|
||||
$${PWD}/{{classname}}.cpp \
|
||||
{{/model}}
|
||||
{{/models}}
|
||||
# APIs
|
||||
{{#apiInfo}}
|
||||
{{#apis}}
|
||||
{{#operations}}
|
||||
$${PWD}/{{classname}}.cpp \
|
||||
{{/operations}}
|
||||
{{/apis}}
|
||||
{{/apiInfo}}
|
||||
# Others
|
||||
$${PWD}/{{prefix}}Helpers.cpp \
|
||||
$${PWD}/{{prefix}}HttpRequest.cpp
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
{{>licenseInfo}}
|
||||
#ifndef {{prefix}}_QOBJECT_WRAPPER_H
|
||||
#define {{prefix}}_QOBJECT_WRAPPER_H
|
||||
|
||||
#include <QObject>
|
||||
|
||||
{{#cppNamespaceDeclarations}}
|
||||
namespace {{this}} {
|
||||
{{/cppNamespaceDeclarations}}
|
||||
|
||||
template <typename ObjectPtrT>
|
||||
class {{prefix}}QObjectWrapper : public QObject {
|
||||
public:
|
||||
{{prefix}}QObjectWrapper(ObjectPtrT ptr){
|
||||
data = ptr;
|
||||
}
|
||||
~{{prefix}}QObjectWrapper(){
|
||||
delete data;
|
||||
}
|
||||
private :
|
||||
ObjectPtrT data;
|
||||
};
|
||||
|
||||
{{#cppNamespaceDeclarations}}
|
||||
}
|
||||
{{/cppNamespaceDeclarations}}
|
||||
|
||||
#endif // {{prefix}}_QOBJECT_WRAPPER_H
|
||||
@@ -46,7 +46,7 @@ public abstract class AbstractOptionsTest {
|
||||
final Set<String> undocumented = new HashSet<String>(testOptions);
|
||||
undocumented.removeAll(cliOptions);
|
||||
if (!undocumented.isEmpty()) {
|
||||
Assert.fail(String.format("These options weren't documented: %s.", StringUtils.join(undocumented, ", ")));
|
||||
Assert.fail(String.format("These options weren't documented: %s. Are you expecting base options and calling cliOptions.clear()?", StringUtils.join(undocumented, ", ")));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
package org.openapitools.codegen.go;
|
||||
|
||||
import org.openapitools.codegen.AbstractOptionsTest;
|
||||
import org.openapitools.codegen.CodegenConfig;
|
||||
import org.openapitools.codegen.languages.GoClientCodegen;
|
||||
import org.openapitools.codegen.options.GoClientOptionsProvider;
|
||||
|
||||
import mockit.Expectations;
|
||||
import mockit.Tested;
|
||||
|
||||
public class GoClientOptionsTest extends AbstractOptionsTest {
|
||||
|
||||
@Tested
|
||||
private GoClientCodegen clientCodegen;
|
||||
|
||||
public GoClientOptionsTest() {
|
||||
super(new GoClientOptionsProvider());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected CodegenConfig getCodegenConfig() {
|
||||
return clientCodegen;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Override
|
||||
protected void setExpectations() {
|
||||
new Expectations(clientCodegen) {{
|
||||
clientCodegen.setPackageVersion(GoClientOptionsProvider.PACKAGE_VERSION_VALUE);
|
||||
times = 1;
|
||||
clientCodegen.setPackageName(GoClientOptionsProvider.PACKAGE_NAME_VALUE);
|
||||
times = 1;
|
||||
clientCodegen.setWithXml(GoClientOptionsProvider.WITH_XML_VALUE);
|
||||
times = 1;
|
||||
clientCodegen.setPrependFormOrBodyParameters(Boolean.valueOf(GoClientOptionsProvider.PREPEND_FORM_OR_BODY_PARAMETERS_VALUE));
|
||||
times = 1;
|
||||
}};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,262 @@
|
||||
package org.openapitools.codegen.go;
|
||||
|
||||
import org.openapitools.codegen.languages.GoClientCodegen;
|
||||
import org.openapitools.codegen.*;
|
||||
|
||||
import io.swagger.v3.oas.models.OpenAPI;
|
||||
import io.swagger.v3.oas.models.Operation;
|
||||
import io.swagger.v3.oas.models.media.*;
|
||||
import io.swagger.v3.parser.util.SchemaTypeUtil;
|
||||
|
||||
import com.google.common.collect.Sets;
|
||||
import org.testng.Assert;
|
||||
import org.testng.annotations.DataProvider;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
@SuppressWarnings("static-method")
|
||||
public class GoModelTest {
|
||||
|
||||
@Test(description = "convert a simple Go model")
|
||||
public void simpleModelTest() {
|
||||
final Schema model = new Schema()
|
||||
.description("a sample model")
|
||||
.addProperties("id", new IntegerSchema().format(SchemaTypeUtil.INTEGER64_FORMAT))
|
||||
.addProperties("name", new StringSchema())
|
||||
.addProperties("createdAt", new DateTimeSchema())
|
||||
.addRequiredItem("id")
|
||||
.addRequiredItem("name");
|
||||
final DefaultCodegen codegen = new GoClientCodegen();
|
||||
final CodegenModel cm = codegen.fromModel("sample", model);
|
||||
|
||||
Assert.assertEquals(cm.name, "sample");
|
||||
Assert.assertEquals(cm.classname, "Sample");
|
||||
Assert.assertEquals(cm.description, "a sample model");
|
||||
Assert.assertEquals(cm.vars.size(), 3);
|
||||
Assert.assertEquals(cm.imports.size(), 1);
|
||||
|
||||
final CodegenProperty property1 = cm.vars.get(0);
|
||||
Assert.assertEquals(property1.baseName, "id");
|
||||
Assert.assertEquals(property1.datatype, "int64");
|
||||
Assert.assertEquals(property1.name, "Id");
|
||||
Assert.assertEquals(property1.defaultValue, "null");
|
||||
Assert.assertEquals(property1.baseType, "int64");
|
||||
Assert.assertTrue(property1.hasMore);
|
||||
Assert.assertTrue(property1.required);
|
||||
Assert.assertTrue(property1.isPrimitiveType);
|
||||
Assert.assertTrue(property1.isNotContainer);
|
||||
|
||||
final CodegenProperty property2 = cm.vars.get(1);
|
||||
Assert.assertEquals(property2.baseName, "name");
|
||||
Assert.assertEquals(property2.datatype, "string");
|
||||
Assert.assertEquals(property2.name, "Name");
|
||||
Assert.assertEquals(property2.defaultValue, "null");
|
||||
Assert.assertEquals(property2.baseType, "string");
|
||||
Assert.assertTrue(property2.hasMore);
|
||||
Assert.assertTrue(property2.required);
|
||||
Assert.assertTrue(property2.isPrimitiveType);
|
||||
Assert.assertTrue(property2.isNotContainer);
|
||||
|
||||
final CodegenProperty property3 = cm.vars.get(2);
|
||||
Assert.assertEquals(property3.baseName, "createdAt");
|
||||
Assert.assertEquals(property3.complexType, "time.Time");
|
||||
Assert.assertEquals(property3.datatype, "time.Time");
|
||||
Assert.assertEquals(property3.name, "CreatedAt");
|
||||
Assert.assertEquals(property3.defaultValue, "null");
|
||||
Assert.assertEquals(property3.baseType, "time.Time");
|
||||
Assert.assertFalse(property3.hasMore);
|
||||
Assert.assertFalse(property3.required);
|
||||
Assert.assertTrue(property3.isNotContainer);
|
||||
}
|
||||
|
||||
@Test(description = "convert a model with list property")
|
||||
public void listPropertyTest() {
|
||||
final Schema model = new Schema()
|
||||
.description("a sample model")
|
||||
.addProperties("id", new IntegerSchema().format(SchemaTypeUtil.INTEGER64_FORMAT))
|
||||
.addProperties("urls", new ArraySchema()
|
||||
.items(new StringSchema()))
|
||||
.addRequiredItem("id");
|
||||
final DefaultCodegen codegen = new GoClientCodegen();
|
||||
final CodegenModel cm = codegen.fromModel("sample", model);
|
||||
|
||||
Assert.assertEquals(cm.name, "sample");
|
||||
Assert.assertEquals(cm.classname, "Sample");
|
||||
Assert.assertEquals(cm.description, "a sample model");
|
||||
Assert.assertEquals(cm.vars.size(), 2);
|
||||
|
||||
final CodegenProperty property1 = cm.vars.get(0);
|
||||
Assert.assertEquals(property1.baseName, "id");
|
||||
Assert.assertEquals(property1.datatype, "int64");
|
||||
Assert.assertEquals(property1.name, "Id");
|
||||
Assert.assertEquals(property1.defaultValue, "null");
|
||||
Assert.assertEquals(property1.baseType, "int64");
|
||||
Assert.assertTrue(property1.hasMore);
|
||||
Assert.assertTrue(property1.required);
|
||||
Assert.assertTrue(property1.isPrimitiveType);
|
||||
Assert.assertTrue(property1.isNotContainer);
|
||||
|
||||
final CodegenProperty property2 = cm.vars.get(1);
|
||||
Assert.assertEquals(property2.baseName, "urls");
|
||||
Assert.assertEquals(property2.datatype, "[]string");
|
||||
Assert.assertEquals(property2.name, "Urls");
|
||||
Assert.assertEquals(property2.baseType, "array");
|
||||
Assert.assertFalse(property2.hasMore);
|
||||
Assert.assertEquals(property2.containerType, "array");
|
||||
Assert.assertFalse(property2.required);
|
||||
Assert.assertTrue(property2.isPrimitiveType);
|
||||
Assert.assertTrue(property2.isContainer);
|
||||
}
|
||||
|
||||
@Test(description = "convert a model with a map property")
|
||||
public void mapPropertyTest() {
|
||||
final Schema model = new Schema()
|
||||
.description("a sample model")
|
||||
.addProperties("translations", new MapSchema()
|
||||
.additionalProperties(new StringSchema()))
|
||||
.addRequiredItem("id");
|
||||
final DefaultCodegen codegen = new GoClientCodegen();
|
||||
final CodegenModel cm = codegen.fromModel("sample", model);
|
||||
|
||||
Assert.assertEquals(cm.name, "sample");
|
||||
Assert.assertEquals(cm.classname, "Sample");
|
||||
Assert.assertEquals(cm.description, "a sample model");
|
||||
Assert.assertEquals(cm.vars.size(), 1);
|
||||
|
||||
final CodegenProperty property1 = cm.vars.get(0);
|
||||
Assert.assertEquals(property1.baseName, "translations");
|
||||
Assert.assertEquals(property1.datatype, "map[string]string");
|
||||
Assert.assertEquals(property1.name, "Translations");
|
||||
Assert.assertEquals(property1.baseType, "map");
|
||||
Assert.assertEquals(property1.containerType, "map");
|
||||
Assert.assertFalse(property1.required);
|
||||
Assert.assertTrue(property1.isContainer);
|
||||
Assert.assertTrue(property1.isPrimitiveType);
|
||||
}
|
||||
|
||||
@Test(description = "convert a model with complex property")
|
||||
public void complexPropertyTest() {
|
||||
final Schema model = new Schema()
|
||||
.description("a sample model")
|
||||
.addProperties("children", new Schema().$ref("#/definitions/Children"));
|
||||
final DefaultCodegen codegen = new GoClientCodegen();
|
||||
final CodegenModel cm = codegen.fromModel("sample", model);
|
||||
|
||||
Assert.assertEquals(cm.name, "sample");
|
||||
Assert.assertEquals(cm.classname, "Sample");
|
||||
Assert.assertEquals(cm.description, "a sample model");
|
||||
Assert.assertEquals(cm.vars.size(), 1);
|
||||
|
||||
final CodegenProperty property1 = cm.vars.get(0);
|
||||
Assert.assertEquals(property1.baseName, "children");
|
||||
Assert.assertEquals(property1.datatype, "Children");
|
||||
Assert.assertEquals(property1.name, "Children");
|
||||
Assert.assertEquals(property1.baseType, "Children");
|
||||
Assert.assertFalse(property1.required);
|
||||
Assert.assertTrue(property1.isNotContainer);
|
||||
}
|
||||
|
||||
@Test(description = "convert a model with complex list property")
|
||||
public void complexListProperty() {
|
||||
final Schema model = new Schema()
|
||||
.description("a sample model")
|
||||
.addProperties("children", new ArraySchema()
|
||||
.items(new Schema().$ref("#/definitions/Children")));
|
||||
final DefaultCodegen codegen = new GoClientCodegen();
|
||||
final CodegenModel cm = codegen.fromModel("sample", model);
|
||||
|
||||
Assert.assertEquals(cm.name, "sample");
|
||||
Assert.assertEquals(cm.classname, "Sample");
|
||||
Assert.assertEquals(cm.description, "a sample model");
|
||||
Assert.assertEquals(cm.vars.size(), 1);
|
||||
|
||||
final CodegenProperty property1 = cm.vars.get(0);
|
||||
Assert.assertEquals(property1.baseName, "children");
|
||||
Assert.assertEquals(property1.datatype, "[]Children");
|
||||
Assert.assertEquals(property1.name, "Children");
|
||||
Assert.assertEquals(property1.baseType, "array");
|
||||
Assert.assertEquals(property1.containerType, "array");
|
||||
Assert.assertFalse(property1.required);
|
||||
Assert.assertTrue(property1.isContainer);
|
||||
}
|
||||
|
||||
@Test(description = "convert a model with complex map property")
|
||||
public void complexMapProperty() {
|
||||
final Schema model = new Schema()
|
||||
.description("a sample model")
|
||||
.addProperties("children", new MapSchema()
|
||||
.additionalProperties(new Schema().$ref("#/definitions/Children")));
|
||||
final DefaultCodegen codegen = new GoClientCodegen();
|
||||
final CodegenModel cm = codegen.fromModel("sample", model);
|
||||
|
||||
Assert.assertEquals(cm.name, "sample");
|
||||
Assert.assertEquals(cm.classname, "Sample");
|
||||
Assert.assertEquals(cm.description, "a sample model");
|
||||
Assert.assertEquals(cm.vars.size(), 1);
|
||||
Assert.assertEquals(Sets.intersection(cm.imports, Sets.newHashSet("Children")).size(), 1);
|
||||
|
||||
final CodegenProperty property1 = cm.vars.get(0);
|
||||
Assert.assertEquals(property1.baseName, "children");
|
||||
Assert.assertEquals(property1.complexType, "Children");
|
||||
Assert.assertEquals(property1.datatype, "map[string]Children");
|
||||
Assert.assertEquals(property1.name, "Children");
|
||||
Assert.assertEquals(property1.baseType, "map");
|
||||
Assert.assertEquals(property1.containerType, "map");
|
||||
Assert.assertFalse(property1.required);
|
||||
Assert.assertTrue(property1.isContainer);
|
||||
Assert.assertFalse(property1.isNotContainer);
|
||||
}
|
||||
|
||||
@Test(description = "convert an array model")
|
||||
public void arrayModelTest() {
|
||||
final Schema model = new ArraySchema()
|
||||
.items(new Schema().$ref("#/definitions/Children"))
|
||||
.description("an array model");
|
||||
final DefaultCodegen codegen = new GoClientCodegen();
|
||||
final CodegenModel cm = codegen.fromModel("sample", model);
|
||||
|
||||
Assert.assertEquals(cm.name, "sample");
|
||||
Assert.assertEquals(cm.classname, "Sample");
|
||||
Assert.assertEquals(cm.description, "an array model");
|
||||
Assert.assertEquals(cm.vars.size(), 0);
|
||||
Assert.assertEquals(cm.imports.size(), 1);
|
||||
}
|
||||
|
||||
@Test(description = "convert an map model")
|
||||
public void mapModelTest() {
|
||||
final Schema model = new Schema()
|
||||
.additionalProperties(new Schema().$ref("#/definitions/Children"))
|
||||
.description("a map model");
|
||||
final DefaultCodegen codegen = new GoClientCodegen();
|
||||
final CodegenModel cm = codegen.fromModel("sample", model);
|
||||
|
||||
Assert.assertEquals(cm.name, "sample");
|
||||
Assert.assertEquals(cm.classname, "Sample");
|
||||
Assert.assertEquals(cm.description, "a map model");
|
||||
Assert.assertEquals(cm.vars.size(), 0);
|
||||
Assert.assertEquals(cm.imports.size(), 1);
|
||||
Assert.assertEquals(Sets.intersection(cm.imports, Sets.newHashSet("Children")).size(), 1);
|
||||
}
|
||||
|
||||
@DataProvider(name = "modelNames")
|
||||
public static Object[][] primeNumbers() {
|
||||
return new Object[][] {
|
||||
{"sample", "Sample"},
|
||||
{"sample_name", "SampleName"},
|
||||
{"sample__name", "SampleName"},
|
||||
{"/sample", "Sample"},
|
||||
{"\\sample", "Sample"},
|
||||
{"sample.name", "SampleName"},
|
||||
{"_sample", "Sample"},
|
||||
};
|
||||
}
|
||||
|
||||
@Test(dataProvider = "modelNames", description = "avoid inner class")
|
||||
public void modelNameTest(String name, String expectedName) {
|
||||
final Schema model = new Schema();
|
||||
final DefaultCodegen codegen = new GoClientCodegen();
|
||||
final CodegenModel cm = codegen.fromModel(name, model);
|
||||
|
||||
Assert.assertEquals(cm.name, name);
|
||||
Assert.assertEquals(cm.classname, expectedName);
|
||||
}
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
package org.openapitools.codegen.lumen;
|
||||
|
||||
import org.openapitools.codegen.AbstractOptionsTest;
|
||||
import org.openapitools.codegen.CodegenConfig;
|
||||
import org.openapitools.codegen.languages.LumenServerCodegen;
|
||||
import org.openapitools.codegen.options.LumenServerOptionsProvider;
|
||||
|
||||
import mockit.Expectations;
|
||||
import mockit.Tested;
|
||||
|
||||
public class LumenServerOptionsTest extends AbstractOptionsTest {
|
||||
|
||||
@Tested
|
||||
private LumenServerCodegen clientCodegen;
|
||||
|
||||
public LumenServerOptionsTest() {
|
||||
super(new LumenServerOptionsProvider());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected CodegenConfig getCodegenConfig() {
|
||||
return clientCodegen;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Override
|
||||
protected void setExpectations() {
|
||||
new Expectations(clientCodegen) {{
|
||||
clientCodegen.setSortParamsByRequiredFlag(Boolean.valueOf(LumenServerOptionsProvider.SORT_PARAMS_VALUE));
|
||||
times = 1;
|
||||
clientCodegen.setParameterNamingConvention(LumenServerOptionsProvider.VARIABLE_NAMING_CONVENTION_VALUE);
|
||||
clientCodegen.setModelPackage(LumenServerOptionsProvider.MODEL_PACKAGE_VALUE);
|
||||
times = 1;
|
||||
clientCodegen.setApiPackage(LumenServerOptionsProvider.API_PACKAGE_VALUE);
|
||||
times = 1;
|
||||
times = 1;
|
||||
clientCodegen.setInvokerPackage(LumenServerOptionsProvider.INVOKER_PACKAGE_VALUE);
|
||||
times = 1;
|
||||
clientCodegen.setPackagePath(LumenServerOptionsProvider.PACKAGE_PATH_VALUE);
|
||||
times = 1;
|
||||
clientCodegen.setSrcBasePath(LumenServerOptionsProvider.SRC_BASE_PATH_VALUE);
|
||||
times = 1;
|
||||
clientCodegen.setGitUserId(LumenServerOptionsProvider.GIT_USER_ID_VALUE);
|
||||
times = 1;
|
||||
clientCodegen.setGitRepoId(LumenServerOptionsProvider.GIT_REPO_ID_VALUE);
|
||||
times = 1;
|
||||
clientCodegen.setArtifactVersion(LumenServerOptionsProvider.ARTIFACT_VERSION_VALUE);
|
||||
times = 1;
|
||||
}};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package org.openapitools.codegen.lumen;
|
||||
|
||||
import org.openapitools.codegen.AbstractOptionsTest;
|
||||
import org.openapitools.codegen.CodegenConfig;
|
||||
import org.openapitools.codegen.languages.PhpLumenServerCodegen;
|
||||
import org.openapitools.codegen.options.PhpLumenServerOptionsProvider;
|
||||
|
||||
import mockit.Expectations;
|
||||
import mockit.Tested;
|
||||
|
||||
public class PhpLumenServerOptionsTest extends AbstractOptionsTest {
|
||||
|
||||
@Tested
|
||||
private PhpLumenServerCodegen clientCodegen;
|
||||
|
||||
public PhpLumenServerOptionsTest() {
|
||||
super(new PhpLumenServerOptionsProvider());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected CodegenConfig getCodegenConfig() {
|
||||
return clientCodegen;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Override
|
||||
protected void setExpectations() {
|
||||
new Expectations(clientCodegen) {{
|
||||
clientCodegen.setSortParamsByRequiredFlag(Boolean.valueOf(PhpLumenServerOptionsProvider.SORT_PARAMS_VALUE));
|
||||
times = 1;
|
||||
clientCodegen.setParameterNamingConvention(PhpLumenServerOptionsProvider.VARIABLE_NAMING_CONVENTION_VALUE);
|
||||
clientCodegen.setModelPackage(PhpLumenServerOptionsProvider.MODEL_PACKAGE_VALUE);
|
||||
times = 1;
|
||||
clientCodegen.setApiPackage(PhpLumenServerOptionsProvider.API_PACKAGE_VALUE);
|
||||
times = 1;
|
||||
times = 1;
|
||||
clientCodegen.setInvokerPackage(PhpLumenServerOptionsProvider.INVOKER_PACKAGE_VALUE);
|
||||
times = 1;
|
||||
clientCodegen.setPackagePath(PhpLumenServerOptionsProvider.PACKAGE_PATH_VALUE);
|
||||
times = 1;
|
||||
clientCodegen.setSrcBasePath(PhpLumenServerOptionsProvider.SRC_BASE_PATH_VALUE);
|
||||
times = 1;
|
||||
clientCodegen.setGitUserId(PhpLumenServerOptionsProvider.GIT_USER_ID_VALUE);
|
||||
times = 1;
|
||||
clientCodegen.setGitRepoId(PhpLumenServerOptionsProvider.GIT_REPO_ID_VALUE);
|
||||
times = 1;
|
||||
clientCodegen.setArtifactVersion(PhpLumenServerOptionsProvider.ARTIFACT_VERSION_VALUE);
|
||||
times = 1;
|
||||
}};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package org.openapitools.codegen.perl;
|
||||
|
||||
import org.openapitools.codegen.AbstractOptionsTest;
|
||||
import org.openapitools.codegen.CodegenConfig;
|
||||
import org.openapitools.codegen.languages.PerlClientCodegen;
|
||||
import org.openapitools.codegen.options.PerlClientOptionsProvider;
|
||||
|
||||
import mockit.Expectations;
|
||||
import mockit.Tested;
|
||||
|
||||
public class PerlClientOptionsTest extends AbstractOptionsTest {
|
||||
|
||||
@Tested
|
||||
private PerlClientCodegen clientCodegen;
|
||||
|
||||
public PerlClientOptionsTest() {
|
||||
super(new PerlClientOptionsProvider());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected CodegenConfig getCodegenConfig() {
|
||||
return clientCodegen;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Override
|
||||
protected void setExpectations() {
|
||||
new Expectations(clientCodegen) {{
|
||||
clientCodegen.setModuleName(PerlClientOptionsProvider.MODULE_NAME_VALUE);
|
||||
times = 1;
|
||||
clientCodegen.setModuleVersion(PerlClientOptionsProvider.MODULE_VERSION_VALUE);
|
||||
times = 1;
|
||||
clientCodegen.setPrependFormOrBodyParameters(Boolean.valueOf(PerlClientOptionsProvider.PREPEND_FORM_OR_BODY_PARAMETERS_VALUE));
|
||||
times = 1;
|
||||
}};
|
||||
}
|
||||
}
|
||||
@@ -2,19 +2,19 @@ package org.openapitools.codegen.silex;
|
||||
|
||||
import org.openapitools.codegen.AbstractOptionsTest;
|
||||
import org.openapitools.codegen.CodegenConfig;
|
||||
import org.openapitools.codegen.languages.SilexServerCodegen;
|
||||
import org.openapitools.codegen.options.SilexServerOptionsProvider;
|
||||
import org.openapitools.codegen.languages.PhpSilexServerCodegen;
|
||||
import org.openapitools.codegen.options.PhpSilexServerOptionsProvider;
|
||||
|
||||
import mockit.Expectations;
|
||||
import mockit.Tested;
|
||||
|
||||
public class SilexServerOptionsTest extends AbstractOptionsTest {
|
||||
public class PhpSilexServerOptionsTest extends AbstractOptionsTest {
|
||||
|
||||
@Tested
|
||||
private SilexServerCodegen clientCodegen;
|
||||
private PhpSilexServerCodegen clientCodegen;
|
||||
|
||||
public SilexServerOptionsTest() {
|
||||
super(new SilexServerOptionsProvider());
|
||||
public PhpSilexServerOptionsTest() {
|
||||
super(new PhpSilexServerOptionsProvider());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -26,7 +26,7 @@ public class SilexServerOptionsTest extends AbstractOptionsTest {
|
||||
@Override
|
||||
protected void setExpectations() {
|
||||
new Expectations(clientCodegen) {{
|
||||
clientCodegen.setSortParamsByRequiredFlag(Boolean.valueOf(SilexServerOptionsProvider.SORT_PARAMS_VALUE));
|
||||
clientCodegen.setSortParamsByRequiredFlag(Boolean.valueOf(PhpSilexServerOptionsProvider.SORT_PARAMS_VALUE));
|
||||
times = 1;
|
||||
}};
|
||||
}
|
||||
@@ -2,19 +2,19 @@ package org.openapitools.codegen.slim;
|
||||
|
||||
import org.openapitools.codegen.AbstractOptionsTest;
|
||||
import org.openapitools.codegen.CodegenConfig;
|
||||
import org.openapitools.codegen.languages.SlimFrameworkServerCodegen;
|
||||
import org.openapitools.codegen.options.SlimFrameworkServerOptionsProvider;
|
||||
import org.openapitools.codegen.languages.PhpSlimServerCodegen;
|
||||
import org.openapitools.codegen.options.PhpSlimServerOptionsProvider;
|
||||
|
||||
import mockit.Expectations;
|
||||
import mockit.Tested;
|
||||
|
||||
public class SlimFrameworkServerOptionsTest extends AbstractOptionsTest {
|
||||
public class PhpSlimServerOptionsTest extends AbstractOptionsTest {
|
||||
|
||||
@Tested
|
||||
private SlimFrameworkServerCodegen clientCodegen;
|
||||
private PhpSlimServerCodegen clientCodegen;
|
||||
|
||||
public SlimFrameworkServerOptionsTest() {
|
||||
super(new SlimFrameworkServerOptionsProvider());
|
||||
public PhpSlimServerOptionsTest() {
|
||||
super(new PhpSlimServerOptionsProvider());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -26,7 +26,7 @@ public class SlimFrameworkServerOptionsTest extends AbstractOptionsTest {
|
||||
@Override
|
||||
protected void setExpectations() {
|
||||
new Expectations(clientCodegen) {{
|
||||
clientCodegen.setSortParamsByRequiredFlag(Boolean.valueOf(SlimFrameworkServerOptionsProvider.SORT_PARAMS_VALUE));
|
||||
clientCodegen.setSortParamsByRequiredFlag(Boolean.valueOf(PhpSlimServerOptionsProvider.SORT_PARAMS_VALUE));
|
||||
times = 1;
|
||||
}};
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package org.openapitools.codegen.options;
|
||||
|
||||
import org.openapitools.codegen.CodegenConstants;
|
||||
import org.openapitools.codegen.languages.GoClientCodegen;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class GoClientOptionsProvider implements OptionsProvider {
|
||||
|
||||
public static final String PACKAGE_VERSION_VALUE = "1.0.0";
|
||||
public static final String PACKAGE_NAME_VALUE = "Go";
|
||||
public static final boolean WITH_XML_VALUE = true;
|
||||
public static final Boolean PREPEND_FORM_OR_BODY_PARAMETERS_VALUE = true;
|
||||
|
||||
@Override
|
||||
public String getLanguage() {
|
||||
return "go";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, String> createOptions() {
|
||||
ImmutableMap.Builder<String, String> builder = new ImmutableMap.Builder<String, String>();
|
||||
return builder
|
||||
.put(CodegenConstants.PACKAGE_VERSION, PACKAGE_VERSION_VALUE)
|
||||
.put(CodegenConstants.PACKAGE_NAME, PACKAGE_NAME_VALUE)
|
||||
.put(CodegenConstants.HIDE_GENERATION_TIMESTAMP, "true")
|
||||
.put(CodegenConstants.WITH_XML, "true")
|
||||
.put(CodegenConstants.PREPEND_FORM_OR_BODY_PARAMETERS, "true")
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isServer() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package org.openapitools.codegen.options;
|
||||
|
||||
import org.openapitools.codegen.CodegenConstants;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class GoServerOptionsProvider implements OptionsProvider {
|
||||
public static final String SORT_PARAMS_VALUE = "false";
|
||||
public static final String ENSURE_UNIQUE_PARAMS_VALUE = "true";
|
||||
public static final String ALLOW_UNICODE_IDENTIFIERS_VALUE = "false";
|
||||
public static final String PREPEND_FORM_OR_BODY_PARAMETERS_VALUE = "true";
|
||||
|
||||
@Override
|
||||
public String getLanguage() {
|
||||
return "go-server";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, String> createOptions() {
|
||||
ImmutableMap.Builder<String, String> builder = new ImmutableMap.Builder<String, String>();
|
||||
return builder.put(CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG, SORT_PARAMS_VALUE)
|
||||
.put(CodegenConstants.ENSURE_UNIQUE_PARAMS, ENSURE_UNIQUE_PARAMS_VALUE)
|
||||
.put(CodegenConstants.ALLOW_UNICODE_IDENTIFIERS, ALLOW_UNICODE_IDENTIFIERS_VALUE)
|
||||
.put(CodegenConstants.PREPEND_FORM_OR_BODY_PARAMETERS, "true")
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isServer() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package org.openapitools.codegen.options;
|
||||
|
||||
import org.openapitools.codegen.CodegenConstants;
|
||||
import org.openapitools.codegen.languages.PerlClientCodegen;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class PerlClientOptionsProvider implements OptionsProvider {
|
||||
public static final String MODULE_NAME_VALUE = "";
|
||||
public static final String MODULE_VERSION_VALUE = "";
|
||||
public static final String PREPEND_FORM_OR_BODY_PARAMETERS_VALUE = "true";
|
||||
|
||||
@Override
|
||||
public String getLanguage() {
|
||||
return "perl";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, String> createOptions() {
|
||||
ImmutableMap.Builder<String, String> builder = new ImmutableMap.Builder<String, String>();
|
||||
return builder.put(PerlClientCodegen.MODULE_NAME, MODULE_NAME_VALUE)
|
||||
.put(PerlClientCodegen.MODULE_VERSION, MODULE_VERSION_VALUE)
|
||||
.put(CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG, "true")
|
||||
.put(CodegenConstants.ENSURE_UNIQUE_PARAMS, "true")
|
||||
.put("hideGenerationTimestamp", "true")
|
||||
.put(CodegenConstants.PREPEND_FORM_OR_BODY_PARAMETERS, PREPEND_FORM_OR_BODY_PARAMETERS_VALUE)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isServer() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -7,7 +7,7 @@ import com.google.common.collect.ImmutableMap;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class LumenServerOptionsProvider implements OptionsProvider {
|
||||
public class PhpLumenServerOptionsProvider implements OptionsProvider {
|
||||
public static final String MODEL_PACKAGE_VALUE = "package";
|
||||
public static final String API_PACKAGE_VALUE = "apiPackage";
|
||||
public static final String SORT_PARAMS_VALUE = "false";
|
||||
@@ -6,7 +6,7 @@ import com.google.common.collect.ImmutableMap;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class SilexServerOptionsProvider implements OptionsProvider {
|
||||
public class PhpSilexServerOptionsProvider implements OptionsProvider {
|
||||
public static final String SORT_PARAMS_VALUE = "false";
|
||||
public static final String ENSURE_UNIQUE_PARAMS_VALUE = "true";
|
||||
public static final String ALLOW_UNICODE_IDENTIFIERS_VALUE = "false";
|
||||
@@ -6,7 +6,7 @@ import com.google.common.collect.ImmutableMap;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class SlimFrameworkServerOptionsProvider implements OptionsProvider {
|
||||
public class PhpSlimServerOptionsProvider implements OptionsProvider {
|
||||
public static final String SORT_PARAMS_VALUE = "false";
|
||||
public static final String ENSURE_UNIQUE_PARAMS_VALUE = "true";
|
||||
public static final String ALLOW_UNICODE_IDENTIFIERS_VALUE = "false";
|
||||
Reference in New Issue
Block a user