mirror of
https://github.com/OpenAPITools/openapi-generator.git
synced 2025-12-11 18:52:44 +00:00
Add C++ UE4 client generator (#6399)
* Added new language: UE4 C++ client * rename generator * add copyright * update doc * fix with Locale.ROOT * add new file * minor improvements * remove postProcessModels Co-authored-by: Samuel Kahn <samuel@kahncode.com>
This commit is contained in:
@@ -0,0 +1,544 @@
|
||||
/*
|
||||
* Copyright 2018 OpenAPI-Generator Contributors (https://openapi-generator.tech)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.openapitools.codegen.languages;
|
||||
|
||||
import io.swagger.v3.oas.models.media.ArraySchema;
|
||||
import io.swagger.v3.oas.models.media.Schema;
|
||||
import org.openapitools.codegen.CodegenConstants;
|
||||
import org.openapitools.codegen.CodegenType;
|
||||
import org.openapitools.codegen.SupportingFile;
|
||||
import org.openapitools.codegen.meta.GeneratorMetadata;
|
||||
import org.openapitools.codegen.meta.Stability;
|
||||
import org.openapitools.codegen.utils.ModelUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.*;
|
||||
|
||||
import static org.openapitools.codegen.utils.StringUtils.camelize;
|
||||
|
||||
public class CppUE4ClientCodegen extends AbstractCppCodegen {
|
||||
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 UNREAL_MODULE_NAME = "unrealModuleName";
|
||||
public static final String UNREAL_MODULE_NAME_DESC = "Name of the generated unreal module (optional)";
|
||||
public static final String OPTIONAL_PROJECT_FILE_DESC = "Generate Build.cs";
|
||||
|
||||
protected String unrealModuleName = "OpenAPI";
|
||||
// Will be treated as pointer
|
||||
protected Set<String> pointerClasses = new HashSet<String>();
|
||||
// source folder where to write the files
|
||||
protected String privateFolder = "Private";
|
||||
protected String publicFolder = "Public";
|
||||
protected String apiVersion = "1.0.0";
|
||||
protected Map<String, String> namespaces = new HashMap<String, String>();
|
||||
// Will be included using the <> syntax, not used in Unreal's coding convention
|
||||
protected Set<String> systemIncludes = new HashSet<String>();
|
||||
protected String cppNamespace = unrealModuleName;
|
||||
protected boolean optionalProjectFileFlag = true;
|
||||
|
||||
public CppUE4ClientCodegen() {
|
||||
super();
|
||||
|
||||
generatorMetadata = GeneratorMetadata.newBuilder(generatorMetadata)
|
||||
.stability(Stability.BETA)
|
||||
.build();
|
||||
|
||||
// set the output folder here
|
||||
outputFolder = "generated-code/cpp-ue4";
|
||||
|
||||
// set modelNamePrefix as default for cpp-ue4
|
||||
if ("".equals(modelNamePrefix)) {
|
||||
modelNamePrefix = unrealModuleName;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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-source.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-source.mustache", // the template to use
|
||||
".cpp"); // the extension for each file to write
|
||||
|
||||
apiTemplateFiles.put(
|
||||
"api-operations-header.mustache", // the template to use
|
||||
".h"); // the extension for each file to write
|
||||
|
||||
apiTemplateFiles.put(
|
||||
"api-operations-source.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 = "cpp-ue4";
|
||||
|
||||
// CLI options
|
||||
addOption(CPP_NAMESPACE, CPP_NAMESPACE_DESC, this.cppNamespace);
|
||||
addOption(UNREAL_MODULE_NAME, UNREAL_MODULE_NAME_DESC, this.unrealModuleName);
|
||||
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("modelNamePrefix", modelNamePrefix);
|
||||
additionalProperties().put("modelPackage", modelPackage);
|
||||
additionalProperties().put("apiPackage", apiPackage);
|
||||
additionalProperties().put("dllapi", unrealModuleName.toUpperCase(Locale.ROOT) + "_API");
|
||||
additionalProperties().put("unrealModuleName", unrealModuleName);
|
||||
|
||||
// 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);
|
||||
additionalProperties.put("unrealModuleName", unrealModuleName);
|
||||
|
||||
/*
|
||||
* Language Specific Primitives. These types will not trigger imports by
|
||||
* the client generator
|
||||
*/
|
||||
languageSpecificPrimitives = new HashSet<String>(
|
||||
Arrays.asList(
|
||||
"bool",
|
||||
"int32",
|
||||
"int64",
|
||||
"float",
|
||||
"double",
|
||||
"FString",
|
||||
"FDateTime",
|
||||
"FGuid",
|
||||
"TArray",
|
||||
"TArray<uint8>", // For byte arrays
|
||||
"TMap",
|
||||
"TSharedPtr<FJsonObject>")
|
||||
);
|
||||
|
||||
supportingFiles.add(new SupportingFile("model-base-header.mustache", publicFolder, modelNamePrefix + "BaseModel.h"));
|
||||
supportingFiles.add(new SupportingFile("model-base-source.mustache", privateFolder, modelNamePrefix + "BaseModel.cpp"));
|
||||
supportingFiles.add(new SupportingFile("helpers-header.mustache", publicFolder, modelNamePrefix + "Helpers.h"));
|
||||
supportingFiles.add(new SupportingFile("helpers-source.mustache", privateFolder, modelNamePrefix + "Helpers.cpp"));
|
||||
if (optionalProjectFileFlag) {
|
||||
supportingFiles.add(new SupportingFile("Build.cs.mustache", unrealModuleName + ".Build.cs"));
|
||||
supportingFiles.add(new SupportingFile("module-header.mustache", privateFolder, unrealModuleName + "Module.h"));
|
||||
supportingFiles.add(new SupportingFile("module-source.mustache", privateFolder, unrealModuleName + "Module.cpp"));
|
||||
}
|
||||
|
||||
super.typeMapping = new HashMap<String, String>();
|
||||
|
||||
// Maps C++ types during call to getSchemaType, see DefaultCodegen.getSchemaType and not the types/formats
|
||||
// defined in openapi specification "array" is also used explicitly in the generator for containers
|
||||
typeMapping.clear();
|
||||
typeMapping.put("integer", "int32");
|
||||
typeMapping.put("long", "int64");
|
||||
typeMapping.put("float", "float");
|
||||
typeMapping.put("number", "double");
|
||||
typeMapping.put("double", "double");
|
||||
typeMapping.put("string", "FString");
|
||||
typeMapping.put("byte", "uint8");
|
||||
typeMapping.put("binary", "TArray<uint8>");
|
||||
typeMapping.put("ByteArray", "TArray<uint8>");
|
||||
typeMapping.put("password", "FString");
|
||||
typeMapping.put("boolean", "bool");
|
||||
typeMapping.put("date", "FDateTime");
|
||||
typeMapping.put("Date", "FDateTime");
|
||||
typeMapping.put("date-time", "FDateTime");
|
||||
typeMapping.put("DateTime", "FDateTime");
|
||||
typeMapping.put("array", "TArray");
|
||||
typeMapping.put("list", "TArray");
|
||||
typeMapping.put("map", "TMap");
|
||||
typeMapping.put("object", "TSharedPtr<FJsonObject>");
|
||||
typeMapping.put("Object", "TSharedPtr<FJsonObject>");
|
||||
typeMapping.put("file", "HttpFileInput");
|
||||
typeMapping.put("UUID", "FGuid");
|
||||
|
||||
importMapping = new HashMap<String, String>();
|
||||
importMapping.put("HttpFileInput", "#include \"" + modelNamePrefix + "Helpers.h\"");
|
||||
|
||||
namespaces = new HashMap<String, String>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processOpts() {
|
||||
super.processOpts();
|
||||
|
||||
if (additionalProperties.containsKey("cppNamespace")) {
|
||||
cppNamespace = (String) additionalProperties.get("cppNamespace");
|
||||
}
|
||||
|
||||
additionalProperties.put("cppNamespaceDeclarations", cppNamespace.split("\\::"));
|
||||
|
||||
boolean updateSupportingFiles = false;
|
||||
if (additionalProperties.containsKey("unrealModuleName")) {
|
||||
unrealModuleName = (String) additionalProperties.get("unrealModuleName");
|
||||
additionalProperties().put("dllapi", unrealModuleName.toUpperCase(Locale.ROOT) + "_API");
|
||||
modelNamePrefix = unrealModuleName;
|
||||
updateSupportingFiles = true;
|
||||
}
|
||||
|
||||
if (additionalProperties.containsKey("modelNamePrefix")) {
|
||||
modelNamePrefix = (String) additionalProperties.get("modelNamePrefix");
|
||||
updateSupportingFiles = true;
|
||||
}
|
||||
|
||||
if (additionalProperties.containsKey(CodegenConstants.OPTIONAL_PROJECT_FILE)) {
|
||||
setOptionalProjectFileFlag(convertPropertyToBooleanAndWriteBack(CodegenConstants.OPTIONAL_PROJECT_FILE));
|
||||
} else {
|
||||
additionalProperties.put(CodegenConstants.OPTIONAL_PROJECT_FILE, optionalProjectFileFlag);
|
||||
}
|
||||
|
||||
if (updateSupportingFiles) {
|
||||
supportingFiles.clear();
|
||||
|
||||
supportingFiles.add(new SupportingFile("model-base-header.mustache", publicFolder, modelNamePrefix + "BaseModel.h"));
|
||||
supportingFiles.add(new SupportingFile("model-base-source.mustache", privateFolder, modelNamePrefix + "BaseModel.cpp"));
|
||||
supportingFiles.add(new SupportingFile("helpers-header.mustache", publicFolder, modelNamePrefix + "Helpers.h"));
|
||||
supportingFiles.add(new SupportingFile("helpers-source.mustache", privateFolder, modelNamePrefix + "Helpers.cpp"));
|
||||
if (optionalProjectFileFlag) {
|
||||
supportingFiles.add(new SupportingFile("Build.cs.mustache", unrealModuleName + ".Build.cs"));
|
||||
supportingFiles.add(new SupportingFile("module-header.mustache", privateFolder, unrealModuleName + "Module.h"));
|
||||
supportingFiles.add(new SupportingFile("module-source.mustache", privateFolder, unrealModuleName + "Module.cpp"));
|
||||
}
|
||||
|
||||
importMapping.put("HttpFileInput", "#include \"" + modelNamePrefix + "Helpers.h\"");
|
||||
}
|
||||
}
|
||||
|
||||
public void setOptionalProjectFileFlag(boolean flag) {
|
||||
this.optionalProjectFileFlag = flag;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 "cpp-ue4";
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 Unreal Engine 4 C++ Module (beta).";
|
||||
}
|
||||
|
||||
@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\"";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean needToImport(String type) {
|
||||
boolean shouldImport = super.needToImport(type);
|
||||
if (shouldImport)
|
||||
return !languageSpecificPrimitives.contains(type);
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 + File.separator + 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 + File.separator + apiPackage().replace("::", File.separator);
|
||||
}
|
||||
|
||||
/*
|
||||
@Override
|
||||
public String modelFilename(String templateName, String tag) {
|
||||
String suffix = modelTemplateFiles().get(templateName);
|
||||
String folder = privateFolder;
|
||||
if (suffix == ".h") {
|
||||
folder = publicFolder;
|
||||
}
|
||||
|
||||
return modelFileFolder() + File.separator + folder + File.separator + toModelFilename(tag) + suffix;
|
||||
}
|
||||
*/
|
||||
|
||||
@Override
|
||||
public String toModelFilename(String name) {
|
||||
name = sanitizeName(name);
|
||||
return modelNamePrefix + camelize(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String apiFilename(String templateName, String tag) {
|
||||
String suffix = apiTemplateFiles().get(templateName);
|
||||
String folder = privateFolder;
|
||||
if (".h".equals(suffix)) {
|
||||
folder = publicFolder;
|
||||
}
|
||||
|
||||
if (templateName.startsWith("api-operations")) {
|
||||
return apiFileFolder() + File.separator + folder + File.separator + toApiFilename(tag) + "Operations" + suffix;
|
||||
} else {
|
||||
return apiFileFolder() + File.separator + folder + File.separator + toApiFilename(tag) + suffix;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toApiFilename(String name) {
|
||||
name = sanitizeName(name);
|
||||
return modelNamePrefix + camelize(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 (ModelUtils.isArraySchema(p)) {
|
||||
ArraySchema ap = (ArraySchema) p;
|
||||
String inner = getSchemaType(ap.getItems());
|
||||
return getSchemaType(p) + "<" + getTypeDeclaration(inner) + ">";
|
||||
} else if (ModelUtils.isMapSchema(p)) {
|
||||
String inner = getSchemaType(ModelUtils.getAdditionalProperties(p));
|
||||
return getSchemaType(p) + "<FString, " + getTypeDeclaration(inner) + ">";
|
||||
}
|
||||
|
||||
if (pointerClasses.contains(openAPIType)) {
|
||||
return openAPIType + "*";
|
||||
} else if (languageSpecificPrimitives.contains(openAPIType)) {
|
||||
return toModelName(openAPIType);
|
||||
} else {
|
||||
return openAPIType;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toDefaultValue(Schema p) {
|
||||
if (ModelUtils.isStringSchema(p)) {
|
||||
if (p.getDefault() != null) {
|
||||
return "TEXT(\"" + p.getDefault().toString() + "\")";
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
} else if (ModelUtils.isBooleanSchema(p)) {
|
||||
if (p.getDefault() != null) {
|
||||
return p.getDefault().toString();
|
||||
} else {
|
||||
return "false";
|
||||
}
|
||||
} else if (ModelUtils.isDateSchema(p)) {
|
||||
return "FDateTime(0)";
|
||||
} else if (ModelUtils.isDateTimeSchema(p)) {
|
||||
return "FDateTime(0)";
|
||||
} else if (ModelUtils.isDoubleSchema(p)) {
|
||||
if (p.getDefault() != null) {
|
||||
return p.getDefault().toString();
|
||||
} else {
|
||||
return "0.0";
|
||||
}
|
||||
} else if (ModelUtils.isFloatSchema(p)) {
|
||||
if (p.getDefault() != null) {
|
||||
return p.getDefault().toString();
|
||||
} else {
|
||||
return "0.0f";
|
||||
}
|
||||
} else if (ModelUtils.isIntegerSchema(p)) {
|
||||
if (p.getDefault() != null) {
|
||||
return p.getDefault().toString();
|
||||
} else {
|
||||
return "0";
|
||||
}
|
||||
} else if (ModelUtils.isLongSchema(p)) {
|
||||
if (p.getDefault() != null) {
|
||||
return p.getDefault().toString();
|
||||
} else {
|
||||
return "0";
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Optional - OpenAPI type conversion. This is used to map OpenAPI types in a `Property` 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.v3.oas.models.media.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);
|
||||
}
|
||||
if (pointerClasses.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 + camelize(sanitizeName(type), false);
|
||||
}
|
||||
}
|
||||
|
||||
@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(Locale.ROOT);
|
||||
}
|
||||
|
||||
// for reserved word or word starting with number, append _
|
||||
if (isReservedWord(name) || name.matches("^\\d.*")) {
|
||||
name = escapeReservedWord(name);
|
||||
}
|
||||
|
||||
//Unreal variable names are CamelCase
|
||||
return camelize(name, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toEnumVarName(String name, String datatype) {
|
||||
return toVarName(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toParamName(String name) {
|
||||
return toVarName(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toApiName(String type) {
|
||||
return modelNamePrefix + camelize(type, false) + "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 String toBooleanGetter(String name) {
|
||||
return "Is" + getterAndSetterCapitalize(name);
|
||||
}
|
||||
|
||||
public String toGetter(String name) {
|
||||
return "Get" + getterAndSetterCapitalize(name);
|
||||
}
|
||||
|
||||
public String toSetter(String name) {
|
||||
return "Set" + getterAndSetterCapitalize(name);
|
||||
}
|
||||
}
|
||||
@@ -16,6 +16,7 @@ org.openapitools.codegen.languages.CppPistacheServerCodegen
|
||||
org.openapitools.codegen.languages.CppRestbedServerCodegen
|
||||
org.openapitools.codegen.languages.CppRestSdkClientCodegen
|
||||
org.openapitools.codegen.languages.CppTizenClientCodegen
|
||||
org.openapitools.codegen.languages.CppUE4ClientCodegen
|
||||
org.openapitools.codegen.languages.CSharpClientCodegen
|
||||
org.openapitools.codegen.languages.CSharpNetCoreClientCodegen
|
||||
org.openapitools.codegen.languages.CSharpDotNet2ClientCodegen
|
||||
@@ -124,4 +125,4 @@ org.openapitools.codegen.languages.TypeScriptInversifyClientCodegen
|
||||
org.openapitools.codegen.languages.TypeScriptJqueryClientCodegen
|
||||
org.openapitools.codegen.languages.TypeScriptNodeClientCodegen
|
||||
org.openapitools.codegen.languages.TypeScriptReduxQueryClientCodegen
|
||||
org.openapitools.codegen.languages.TypeScriptRxjsClientCodegen
|
||||
org.openapitools.codegen.languages.TypeScriptRxjsClientCodegen
|
||||
19
modules/openapi-generator/src/main/resources/cpp-ue4/Build.cs.mustache
vendored
Normal file
19
modules/openapi-generator/src/main/resources/cpp-ue4/Build.cs.mustache
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
{{>licenseInfo}}
|
||||
using System;
|
||||
using System.IO;
|
||||
using UnrealBuildTool;
|
||||
|
||||
public class {{unrealModuleName}} : ModuleRules
|
||||
{
|
||||
public {{unrealModuleName}}(ReadOnlyTargetRules Target) : base(Target)
|
||||
{
|
||||
PublicDependencyModuleNames.AddRange(
|
||||
new string[]
|
||||
{
|
||||
"Core",
|
||||
"Http",
|
||||
"Json",
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
42
modules/openapi-generator/src/main/resources/cpp-ue4/api-header.mustache
vendored
Normal file
42
modules/openapi-generator/src/main/resources/cpp-ue4/api-header.mustache
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
{{>licenseInfo}}
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "{{modelNamePrefix}}BaseModel.h"
|
||||
|
||||
{{#cppNamespaceDeclarations}}
|
||||
namespace {{this}}
|
||||
{
|
||||
{{/cppNamespaceDeclarations}}
|
||||
|
||||
class {{dllapi}} {{classname}}
|
||||
{
|
||||
public:
|
||||
{{classname}}();
|
||||
~{{classname}}();
|
||||
|
||||
void SetURL(const FString& Url);
|
||||
void AddHeaderParam(const FString& Key, const FString& Value);
|
||||
void ClearHeaderParams();
|
||||
|
||||
{{#operations}}{{#operation}}class {{operationIdCamelCase}}Request;
|
||||
class {{operationIdCamelCase}}Response;
|
||||
{{/operation}}{{/operations}}
|
||||
{{#operations}}{{#operation}}DECLARE_DELEGATE_OneParam(F{{operationIdCamelCase}}Delegate, const {{operationIdCamelCase}}Response&);
|
||||
{{/operation}}{{/operations}}
|
||||
{{#operations}}{{#operation}}{{#description}}/* {{{description}}} */
|
||||
{{/description}}bool {{operationIdCamelCase}}(const {{operationIdCamelCase}}Request& Request, const F{{operationIdCamelCase}}Delegate& Delegate = F{{operationIdCamelCase}}Delegate()) const;
|
||||
{{/operation}}{{/operations}}
|
||||
private:
|
||||
{{#operations}}{{#operation}}void On{{operationIdCamelCase}}Response(FHttpRequestPtr HttpRequest, FHttpResponsePtr HttpResponse, bool bSucceeded, F{{operationIdCamelCase}}Delegate Delegate) const;
|
||||
{{/operation}}{{/operations}}
|
||||
bool IsValid() const;
|
||||
void HandleResponse(FHttpResponsePtr HttpResponse, bool bSucceeded, Response& InOutResponse) const;
|
||||
|
||||
FString Url;
|
||||
TMap<FString,FString> AdditionalHeaderParams;
|
||||
};
|
||||
|
||||
{{#cppNamespaceDeclarations}}
|
||||
}
|
||||
{{/cppNamespaceDeclarations}}
|
||||
64
modules/openapi-generator/src/main/resources/cpp-ue4/api-operations-header.mustache
vendored
Normal file
64
modules/openapi-generator/src/main/resources/cpp-ue4/api-operations-header.mustache
vendored
Normal file
@@ -0,0 +1,64 @@
|
||||
{{>licenseInfo}}
|
||||
#pragma once
|
||||
|
||||
#include "{{modelNamePrefix}}BaseModel.h"
|
||||
#include "{{classname}}.h"
|
||||
|
||||
{{#imports}}{{{import}}}
|
||||
{{/imports}}
|
||||
|
||||
{{#cppNamespaceDeclarations}}
|
||||
namespace {{this}}
|
||||
{
|
||||
{{/cppNamespaceDeclarations}}
|
||||
|
||||
{{#operations}}
|
||||
{{#operation}}
|
||||
/* {{summary}}
|
||||
{{#notes}} *
|
||||
* {{notes}}{{/notes}}
|
||||
*/
|
||||
class {{dllapi}} {{classname}}::{{operationIdCamelCase}}Request : public Request
|
||||
{
|
||||
public:
|
||||
virtual ~{{operationIdCamelCase}}Request() {}
|
||||
void SetupHttpRequest(const TSharedRef<IHttpRequest>& HttpRequest) const final;
|
||||
FString ComputePath() const final;
|
||||
|
||||
{{#allParams}}
|
||||
{{#isEnum}}
|
||||
{{#allowableValues}}
|
||||
enum class {{{enumName}}}
|
||||
{
|
||||
{{#enumVars}}
|
||||
{{name}},
|
||||
{{/enumVars}}
|
||||
};
|
||||
{{/allowableValues}}
|
||||
{{#description}}/* {{{description}}} */
|
||||
{{/description}}{{^required}}TOptional<{{/required}}{{{datatypeWithEnum}}}{{^required}}>{{/required}} {{paramName}}{{#required}}{{#defaultValue}} = {{{defaultValue}}}{{/defaultValue}}{{/required}};
|
||||
{{/isEnum}}
|
||||
{{^isEnum}}
|
||||
{{#description}}/* {{{description}}} */
|
||||
{{/description}}{{^required}}TOptional<{{/required}}{{{dataType}}}{{^required}}>{{/required}} {{paramName}}{{#required}}{{#defaultValue}} = {{{defaultValue}}}{{/defaultValue}}{{/required}};
|
||||
{{/isEnum}}
|
||||
{{/allParams}}
|
||||
};
|
||||
|
||||
class {{dllapi}} {{classname}}::{{operationIdCamelCase}}Response : public Response
|
||||
{
|
||||
public:
|
||||
virtual ~{{operationIdCamelCase}}Response() {}
|
||||
{{#responses.0}}
|
||||
void SetHttpResponseCode(EHttpResponseCodes::Type InHttpResponseCode) final;
|
||||
{{/responses.0}}
|
||||
bool FromJson(const TSharedPtr<FJsonValue>& JsonObject) final;
|
||||
|
||||
{{#returnType}}{{{returnType}}} Content;{{/returnType}}
|
||||
};
|
||||
|
||||
{{/operation}}
|
||||
{{/operations}}
|
||||
{{#cppNamespaceDeclarations}}
|
||||
}
|
||||
{{/cppNamespaceDeclarations}}
|
||||
286
modules/openapi-generator/src/main/resources/cpp-ue4/api-operations-source.mustache
vendored
Normal file
286
modules/openapi-generator/src/main/resources/cpp-ue4/api-operations-source.mustache
vendored
Normal file
@@ -0,0 +1,286 @@
|
||||
{{>licenseInfo}}
|
||||
#include "{{classname}}Operations.h"
|
||||
|
||||
#include "{{unrealModuleName}}Module.h"
|
||||
#include "{{modelNamePrefix}}Helpers.h"
|
||||
|
||||
#include "Dom/JsonObject.h"
|
||||
#include "Templates/SharedPointer.h"
|
||||
#include "HttpModule.h"
|
||||
#include "PlatformHttp.h"
|
||||
|
||||
{{#cppNamespaceDeclarations}}
|
||||
namespace {{this}}
|
||||
{
|
||||
{{/cppNamespaceDeclarations}}
|
||||
{{#operations}}{{#operation}}
|
||||
{{#allParams}}
|
||||
{{#isEnum}}
|
||||
inline FString ToString(const {{classname}}::{{operationIdCamelCase}}Request::{{{enumName}}}& Value)
|
||||
{
|
||||
{{#allowableValues}}
|
||||
switch (Value)
|
||||
{
|
||||
{{#enumVars}}
|
||||
case {{classname}}::{{operationIdCamelCase}}Request::{{{enumName}}}::{{name}}:
|
||||
return TEXT({{{value}}});
|
||||
{{/enumVars}}
|
||||
}
|
||||
{{/allowableValues}}
|
||||
|
||||
UE_LOG(Log{{unrealModuleName}}, Error, TEXT("Invalid {{classname}}::{{operationIdCamelCase}}Request::{{{enumName}}} Value (%d)"), (int)Value);
|
||||
return TEXT("");
|
||||
}
|
||||
|
||||
inline FStringFormatArg ToStringFormatArg(const {{classname}}::{{operationIdCamelCase}}Request::{{{enumName}}}& Value)
|
||||
{
|
||||
return FStringFormatArg(ToString(Value));
|
||||
}
|
||||
|
||||
inline void WriteJsonValue(JsonWriter& Writer, const {{classname}}::{{operationIdCamelCase}}Request::{{{enumName}}}& Value)
|
||||
{
|
||||
WriteJsonValue(Writer, ToString(Value));
|
||||
}
|
||||
|
||||
inline bool TryGetJsonValue(const TSharedPtr<FJsonValue>& JsonValue, {{classname}}::{{operationIdCamelCase}}Request::{{{enumName}}}& Value)
|
||||
{
|
||||
{{#allowableValues}}
|
||||
FString TmpValue;
|
||||
if (JsonValue->TryGetString(TmpValue))
|
||||
{
|
||||
static TMap<FString, {{classname}}::{{operationIdCamelCase}}Request::{{{enumName}}}> StringToEnum = { {{#enumVars}}
|
||||
{ TEXT({{{value}}}), {{classname}}::{{operationIdCamelCase}}Request::{{{enumName}}}::{{name}} },{{/enumVars}} };
|
||||
|
||||
const auto Found = StringToEnum.Find(TmpValue);
|
||||
if(Found)
|
||||
{
|
||||
Value = *Found;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
{{/allowableValues}}
|
||||
return false;
|
||||
}
|
||||
|
||||
{{/isEnum}}
|
||||
{{/allParams}}
|
||||
FString {{classname}}::{{operationIdCamelCase}}Request::ComputePath() const
|
||||
{
|
||||
{{^pathParams.0}}
|
||||
FString Path(TEXT("{{{path}}}"));
|
||||
{{/pathParams.0}}
|
||||
{{#pathParams.0}}
|
||||
TMap<FString, FStringFormatArg> PathParams = { {{#pathParams}}
|
||||
{ TEXT("{{baseName}}"), ToStringFormatArg({{paramName}}) }{{#hasMore}},{{/hasMore}}{{/pathParams}} };
|
||||
|
||||
FString Path = FString::Format(TEXT("{{{path}}}"), PathParams);
|
||||
|
||||
{{/pathParams.0}}
|
||||
{{#queryParams.0}}
|
||||
TArray<FString> QueryParams;
|
||||
{{#queryParams}}
|
||||
{{#required}}
|
||||
{{^collectionFormat}}
|
||||
QueryParams.Add(FString(TEXT("{{baseName}}=")) + ToUrlString({{paramName}}));
|
||||
{{/collectionFormat}}
|
||||
{{#collectionFormat}}
|
||||
QueryParams.Add(FString(TEXT("{{baseName}}=")) + CollectionToUrlString_{{collectionFormat}}({{paramName}}, TEXT("{{baseName}}")));
|
||||
{{/collectionFormat}}
|
||||
{{/required}}
|
||||
{{^required}}
|
||||
{{^collectionFormat}}
|
||||
if({{paramName}}.IsSet())
|
||||
{
|
||||
QueryParams.Add(FString(TEXT("{{baseName}}=")) + ToUrlString({{paramName}}.GetValue()));
|
||||
}
|
||||
{{/collectionFormat}}
|
||||
{{#collectionFormat}}
|
||||
if({{paramName}}.IsSet())
|
||||
{
|
||||
QueryParams.Add(FString(TEXT("{{baseName}}=")) + CollectionToUrlString_{{collectionFormat}}({{paramName}}.GetValue(), TEXT("{{baseName}}")));
|
||||
}
|
||||
{{/collectionFormat}}
|
||||
{{/required}}
|
||||
{{/queryParams}}
|
||||
Path += TCHAR('?');
|
||||
Path += FString::Join(QueryParams, TEXT("&"));
|
||||
|
||||
{{/queryParams.0}}
|
||||
return Path;
|
||||
}
|
||||
|
||||
void {{classname}}::{{operationIdCamelCase}}Request::SetupHttpRequest(const TSharedRef<IHttpRequest>& HttpRequest) const
|
||||
{
|
||||
static const TArray<FString> Consumes = { {{#consumes}}TEXT("{{{mediaType}}}"){{#hasMore}}, {{/hasMore}}{{/consumes}} };
|
||||
//static const TArray<FString> Produces = { {{#produces}}TEXT("{{{mediaType}}}"){{#hasMore}}, {{/hasMore}}{{/produces}} };
|
||||
|
||||
HttpRequest->SetVerb(TEXT("{{httpMethod}}"));
|
||||
{{#headerParams.0}}
|
||||
|
||||
// Header parameters
|
||||
{{#headerParams}}
|
||||
{{#required}}
|
||||
HttpRequest->SetHeader(TEXT("{{baseName}}"), {{paramName}});
|
||||
{{/required}}
|
||||
{{^required}}
|
||||
if ({{paramName}}.IsSet())
|
||||
{
|
||||
HttpRequest->SetHeader(TEXT("{{baseName}}"), {{paramName}}.GetValue());
|
||||
}
|
||||
{{/required}}
|
||||
{{/headerParams}}
|
||||
{{/headerParams.0}}
|
||||
|
||||
// Default to Json Body request
|
||||
if (Consumes.Num() == 0 || Consumes.Contains(TEXT("application/json")))
|
||||
{
|
||||
{{#bodyParams.0}}
|
||||
// Body parameters
|
||||
FString JsonBody;
|
||||
JsonWriter Writer = TJsonWriterFactory<>::Create(&JsonBody);
|
||||
|
||||
Writer->WriteObjectStart();
|
||||
{{#bodyParams}}
|
||||
{{#required}}
|
||||
Writer->WriteIdentifierPrefix(TEXT("{{baseName}}")); WriteJsonValue(Writer, {{paramName}});
|
||||
{{/required}}
|
||||
{{^required}}
|
||||
if ({{paramName}}.IsSet())
|
||||
{
|
||||
Writer->WriteIdentifierPrefix(TEXT("{{baseName}}")); WriteJsonValue(Writer, {{paramName}}.GetValue());
|
||||
}
|
||||
{{/required}}
|
||||
{{/bodyParams}}
|
||||
Writer->WriteObjectEnd();
|
||||
Writer->Close();
|
||||
|
||||
HttpRequest->SetHeader(TEXT("Content-Type"), TEXT("application/json; charset=utf-8"));
|
||||
HttpRequest->SetContentAsString(JsonBody);
|
||||
{{/bodyParams.0}}
|
||||
{{#formParams.0}}
|
||||
{{#formParams}}
|
||||
UE_LOG(Log{{unrealModuleName}}, Error, TEXT("Form parameter ({{baseName}}) was ignored, cannot be used in JsonBody"));
|
||||
{{/formParams}}
|
||||
{{/formParams.0}}
|
||||
}
|
||||
else if (Consumes.Contains(TEXT("multipart/form-data")))
|
||||
{
|
||||
{{#formParams.0}}
|
||||
HttpMultipartFormData FormData;
|
||||
{{#formParams}}
|
||||
{{#isContainer}}
|
||||
UE_LOG(Log{{unrealModuleName}}, Error, TEXT("Form parameter ({{baseName}}) was ignored, Collections are not supported in multipart form"));
|
||||
{{/isContainer}}
|
||||
{{^isContainer}}
|
||||
{{#required}}
|
||||
{{#isFile}}
|
||||
FormData.AddFilePart(TEXT("{{baseName}}"), {{paramName}});
|
||||
{{/isFile}}
|
||||
{{#isBinary}}
|
||||
FormData.AddBinaryPart(TEXT("{{baseName}}"), {{paramName}});
|
||||
{{/isBinary}}
|
||||
{{#isBinary}}
|
||||
{{^isFile}}
|
||||
FormData.AddStringPart(TEXT("{{baseName}}"), *ToUrlString({{paramName}}));
|
||||
{{/isFile}}
|
||||
{{/isBinary}}
|
||||
{{/required}}
|
||||
{{^required}}
|
||||
if({{paramName}}.IsSet())
|
||||
{
|
||||
{{#isFile}}
|
||||
FormData.AddFilePart(TEXT("{{baseName}}"), {{paramName}}.GetValue());
|
||||
{{/isFile}}
|
||||
{{#isBinary}}
|
||||
FormData.AddBinaryPart(TEXT("{{baseName}}"), {{paramName}}.GetValue());
|
||||
{{/isBinary}}
|
||||
{{^isBinary}}
|
||||
{{^isFile}}
|
||||
FormData.AddStringPart(TEXT("{{baseName}}"), *ToUrlString({{paramName}}.GetValue()));
|
||||
{{/isFile}}
|
||||
{{/isBinary}}
|
||||
}
|
||||
{{/required}}
|
||||
{{/isContainer}}
|
||||
{{/formParams}}
|
||||
|
||||
FormData.SetupHttpRequest(HttpRequest);
|
||||
{{/formParams.0}}
|
||||
{{#bodyParams.0}}
|
||||
{{#bodyParams}}
|
||||
UE_LOG(Log{{unrealModuleName}}, Error, TEXT("Body parameter ({{baseName}}) was ignored, not supported in multipart form"));
|
||||
{{/bodyParams}}
|
||||
{{/bodyParams.0}}
|
||||
}
|
||||
else if (Consumes.Contains(TEXT("application/x-www-form-urlencoded")))
|
||||
{
|
||||
{{#formParams.0}}
|
||||
TArray<FString> FormParams;
|
||||
{{#formParams}}
|
||||
{{#isContainer}}
|
||||
UE_LOG(Log{{unrealModuleName}}, Error, TEXT("Form parameter ({{baseName}}) was ignored, Collections are not supported in urlencoded requests"));
|
||||
{{/isContainer}}
|
||||
{{#isFile}}
|
||||
UE_LOG(Log{{unrealModuleName}}, Error, TEXT("Form parameter ({{baseName}}) was ignored, Files are not supported in urlencoded requests"));
|
||||
{{/isFile}}
|
||||
{{^isFile}}
|
||||
{{^isContainer}}
|
||||
{{#required}}
|
||||
FormParams.Add(FString(TEXT("{{baseName}}=")) + ToUrlString({{paramName}}));
|
||||
{{/required}}
|
||||
{{^required}}
|
||||
if({{paramName}}.IsSet())
|
||||
{
|
||||
FormParams.Add(FString(TEXT("{{baseName}}=")) + ToUrlString({{paramName}}.GetValue()));
|
||||
}
|
||||
{{/required}}
|
||||
{{/isContainer}}
|
||||
{{/isFile}}
|
||||
{{/formParams}}
|
||||
|
||||
HttpRequest->SetHeader(TEXT("Content-Type"), TEXT("application/x-www-form-urlencoded; charset=utf-8"));
|
||||
HttpRequest->SetContentAsString(FString::Join(FormParams, TEXT("&")));
|
||||
{{/formParams.0}}
|
||||
{{#bodyParams.0}}
|
||||
{{#bodyParams}}
|
||||
UE_LOG(Log{{unrealModuleName}}, Error, TEXT("Body parameter ({{baseName}}) was ignored, not supported in urlencoded requests"));
|
||||
{{/bodyParams}}
|
||||
{{/bodyParams.0}}
|
||||
}
|
||||
else
|
||||
{
|
||||
UE_LOG(Log{{unrealModuleName}}, Error, TEXT("Request ContentType not supported (%s)"), *FString::Join(Consumes, TEXT(",")));
|
||||
}
|
||||
}
|
||||
|
||||
{{#responses.0}}
|
||||
void {{classname}}::{{operationIdCamelCase}}Response::SetHttpResponseCode(EHttpResponseCodes::Type InHttpResponseCode)
|
||||
{
|
||||
Response::SetHttpResponseCode(InHttpResponseCode);
|
||||
switch ((int)InHttpResponseCode)
|
||||
{
|
||||
{{#responses}}
|
||||
case {{code}}:
|
||||
{{#isDefault}}
|
||||
default:
|
||||
{{/isDefault}}
|
||||
SetResponseString(TEXT("{{message}}"));
|
||||
break;
|
||||
{{/responses}}
|
||||
}
|
||||
}
|
||||
{{/responses.0}}
|
||||
|
||||
bool {{classname}}::{{operationIdCamelCase}}Response::FromJson(const TSharedPtr<FJsonValue>& JsonValue)
|
||||
{
|
||||
{{#returnType}}
|
||||
return TryGetJsonValue(JsonValue, Content);
|
||||
{{/returnType}}
|
||||
{{^returnType}}
|
||||
return true;
|
||||
{{/returnType}}
|
||||
}
|
||||
{{/operation}}{{/operations}}
|
||||
{{#cppNamespaceDeclarations}}
|
||||
}
|
||||
{{/cppNamespaceDeclarations}}
|
||||
120
modules/openapi-generator/src/main/resources/cpp-ue4/api-source.mustache
vendored
Normal file
120
modules/openapi-generator/src/main/resources/cpp-ue4/api-source.mustache
vendored
Normal file
@@ -0,0 +1,120 @@
|
||||
{{>licenseInfo}}
|
||||
#include "{{classname}}.h"
|
||||
|
||||
#include "{{classname}}Operations.h"
|
||||
#include "{{unrealModuleName}}Module.h"
|
||||
|
||||
#include "HttpModule.h"
|
||||
#include "Serialization/JsonSerializer.h"
|
||||
|
||||
{{#cppNamespaceDeclarations}}
|
||||
namespace {{this}}
|
||||
{
|
||||
{{/cppNamespaceDeclarations}}
|
||||
|
||||
{{classname}}::{{classname}}()
|
||||
: Url(TEXT("{{basePath}}"))
|
||||
{
|
||||
}
|
||||
|
||||
{{classname}}::~{{classname}}() {}
|
||||
|
||||
void {{classname}}::SetURL(const FString& InUrl)
|
||||
{
|
||||
Url = InUrl;
|
||||
}
|
||||
|
||||
void {{classname}}::AddHeaderParam(const FString& Key, const FString& Value)
|
||||
{
|
||||
AdditionalHeaderParams.Add(Key, Value);
|
||||
}
|
||||
|
||||
void {{classname}}::ClearHeaderParams()
|
||||
{
|
||||
AdditionalHeaderParams.Reset();
|
||||
}
|
||||
|
||||
bool {{classname}}::IsValid() const
|
||||
{
|
||||
if (Url.IsEmpty())
|
||||
{
|
||||
UE_LOG(Log{{unrealModuleName}}, Error, TEXT("{{classname}}: Endpoint Url is not set, request cannot be performed"));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void {{classname}}::HandleResponse(FHttpResponsePtr HttpResponse, bool bSucceeded, Response& InOutResponse) const
|
||||
{
|
||||
InOutResponse.SetHttpResponse(HttpResponse);
|
||||
InOutResponse.SetSuccessful(bSucceeded);
|
||||
|
||||
if (bSucceeded && HttpResponse.IsValid())
|
||||
{
|
||||
InOutResponse.SetHttpResponseCode((EHttpResponseCodes::Type)HttpResponse->GetResponseCode());
|
||||
FString ContentType = HttpResponse->GetContentType();
|
||||
FString Content;
|
||||
|
||||
if (ContentType == TEXT("application/json"))
|
||||
{
|
||||
Content = HttpResponse->GetContentAsString();
|
||||
|
||||
TSharedPtr<FJsonValue> JsonValue;
|
||||
auto Reader = TJsonReaderFactory<>::Create(Content);
|
||||
|
||||
if (FJsonSerializer::Deserialize(Reader, JsonValue) && JsonValue.IsValid())
|
||||
{
|
||||
if (InOutResponse.FromJson(JsonValue))
|
||||
return; // Successfully parsed
|
||||
}
|
||||
}
|
||||
else if(ContentType == TEXT("text/plain"))
|
||||
{
|
||||
Content = HttpResponse->GetContentAsString();
|
||||
InOutResponse.SetResponseString(Content);
|
||||
return; // Successfully parsed
|
||||
}
|
||||
|
||||
// Report the parse error but do not mark the request as unsuccessful. Data could be partial or malformed, but the request succeeded.
|
||||
UE_LOG(Log{{unrealModuleName}}, Error, TEXT("Failed to deserialize Http response content (type:%s):\n%s"), *ContentType , *Content);
|
||||
return;
|
||||
}
|
||||
|
||||
// By default, assume we failed to establish connection
|
||||
InOutResponse.SetHttpResponseCode(EHttpResponseCodes::RequestTimeout);
|
||||
}
|
||||
|
||||
{{#operations}}
|
||||
{{#operation}}
|
||||
bool {{classname}}::{{operationIdCamelCase}}(const {{operationIdCamelCase}}Request& Request, const F{{operationIdCamelCase}}Delegate& Delegate /*= F{{operationIdCamelCase}}Delegate()*/) const
|
||||
{
|
||||
if (!IsValid())
|
||||
return false;
|
||||
|
||||
TSharedRef<IHttpRequest> HttpRequest = FHttpModule::Get().CreateRequest();
|
||||
HttpRequest->SetURL(*(Url + Request.ComputePath()));
|
||||
|
||||
for(const auto& It : AdditionalHeaderParams)
|
||||
{
|
||||
HttpRequest->SetHeader(It.Key, It.Value);
|
||||
}
|
||||
|
||||
Request.SetupHttpRequest(HttpRequest);
|
||||
|
||||
HttpRequest->OnProcessRequestComplete().BindRaw(this, &{{classname}}::On{{operationIdCamelCase}}Response, Delegate);
|
||||
return HttpRequest->ProcessRequest();
|
||||
}
|
||||
|
||||
void {{classname}}::On{{operationIdCamelCase}}Response(FHttpRequestPtr HttpRequest, FHttpResponsePtr HttpResponse, bool bSucceeded, F{{operationIdCamelCase}}Delegate Delegate) const
|
||||
{
|
||||
{{operationIdCamelCase}}Response Response;
|
||||
HandleResponse(HttpResponse, bSucceeded, Response);
|
||||
Delegate.ExecuteIfBound(Response);
|
||||
}
|
||||
|
||||
{{/operation}}
|
||||
{{/operations}}
|
||||
{{#cppNamespaceDeclarations}}
|
||||
}
|
||||
{{/cppNamespaceDeclarations}}
|
||||
405
modules/openapi-generator/src/main/resources/cpp-ue4/helpers-header.mustache
vendored
Normal file
405
modules/openapi-generator/src/main/resources/cpp-ue4/helpers-header.mustache
vendored
Normal file
@@ -0,0 +1,405 @@
|
||||
{{>licenseInfo}}
|
||||
#pragma once
|
||||
|
||||
#include "{{modelNamePrefix}}BaseModel.h"
|
||||
|
||||
#include "Serialization/JsonSerializer.h"
|
||||
#include "Dom/JsonObject.h"
|
||||
#include "Misc/Base64.h"
|
||||
|
||||
class IHttpRequest;
|
||||
|
||||
{{#cppNamespaceDeclarations}}
|
||||
namespace {{this}}
|
||||
{
|
||||
{{/cppNamespaceDeclarations}}
|
||||
|
||||
typedef TSharedRef<TJsonWriter<>> JsonWriter;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class {{dllapi}} HttpFileInput
|
||||
{
|
||||
public:
|
||||
HttpFileInput(const TCHAR* InFilePath);
|
||||
HttpFileInput(const FString& InFilePath);
|
||||
|
||||
// This will automatically set the content type if not already set
|
||||
void SetFilePath(const TCHAR* InFilePath);
|
||||
void SetFilePath(const FString& InFilePath);
|
||||
|
||||
// Optional if it can be deduced from the FilePath
|
||||
void SetContentType(const TCHAR* ContentType);
|
||||
|
||||
HttpFileInput& operator=(const HttpFileInput& Other) = default;
|
||||
HttpFileInput& operator=(const FString& InFilePath) { SetFilePath(*InFilePath); return*this; }
|
||||
HttpFileInput& operator=(const TCHAR* InFilePath) { SetFilePath(InFilePath); return*this; }
|
||||
|
||||
const FString& GetFilePath() const { return FilePath; }
|
||||
const FString& GetContentType() const { return ContentType; }
|
||||
|
||||
// Returns the filename with extension
|
||||
FString GetFilename() const;
|
||||
|
||||
private:
|
||||
FString FilePath;
|
||||
FString ContentType;
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class HttpMultipartFormData
|
||||
{
|
||||
public:
|
||||
void SetBoundary(const TCHAR* InBoundary);
|
||||
void SetupHttpRequest(const TSharedRef<IHttpRequest>& HttpRequest);
|
||||
|
||||
void AddStringPart(const TCHAR* Name, const TCHAR* Data);
|
||||
void AddJsonPart(const TCHAR* Name, const FString& JsonString);
|
||||
void AddBinaryPart(const TCHAR* Name, const TArray<uint8>& ByteArray);
|
||||
void AddFilePart(const TCHAR* Name, const HttpFileInput& File);
|
||||
|
||||
private:
|
||||
void AppendString(const TCHAR* Str);
|
||||
const FString& GetBoundary() const;
|
||||
|
||||
mutable FString Boundary;
|
||||
TArray<uint8> FormData;
|
||||
|
||||
static const TCHAR* Delimiter;
|
||||
static const TCHAR* Newline;
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Decodes Base64Url encoded strings, see https://en.wikipedia.org/wiki/Base64#Variants_summary_table
|
||||
template<typename T>
|
||||
bool Base64UrlDecode(const FString& Base64String, T& Value)
|
||||
{
|
||||
FString TmpCopy(Base64String);
|
||||
TmpCopy.ReplaceInline(TEXT("-"), TEXT("+"));
|
||||
TmpCopy.ReplaceInline(TEXT("_"), TEXT("/"));
|
||||
|
||||
return FBase64::Decode(TmpCopy, Value);
|
||||
}
|
||||
|
||||
// Encodes strings in Base64Url, see https://en.wikipedia.org/wiki/Base64#Variants_summary_table
|
||||
template<typename T>
|
||||
FString Base64UrlEncode(const T& Value)
|
||||
{
|
||||
FString Base64String = FBase64::Encode(Value);
|
||||
Base64String.ReplaceInline(TEXT("+"), TEXT("-"));
|
||||
Base64String.ReplaceInline(TEXT("/"), TEXT("_"));
|
||||
return Base64String;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline FStringFormatArg ToStringFormatArg(const T& Value)
|
||||
{
|
||||
return FStringFormatArg(Value);
|
||||
}
|
||||
|
||||
inline FStringFormatArg ToStringFormatArg(const FDateTime& Value)
|
||||
{
|
||||
return FStringFormatArg(Value.ToIso8601());
|
||||
}
|
||||
|
||||
inline FStringFormatArg ToStringFormatArg(const TArray<uint8>& Value)
|
||||
{
|
||||
return FStringFormatArg(Base64UrlEncode(Value));
|
||||
}
|
||||
|
||||
template<typename T, typename std::enable_if<!std::is_base_of<Model, T>::value, int>::type = 0>
|
||||
inline FString ToString(const T& Value)
|
||||
{
|
||||
return FString::Format(TEXT("{0}"), { ToStringFormatArg(Value) });
|
||||
}
|
||||
|
||||
inline FString ToString(const FString& Value)
|
||||
{
|
||||
return Value;
|
||||
}
|
||||
|
||||
inline FString ToString(const TArray<uint8>& Value)
|
||||
{
|
||||
return Base64UrlEncode(Value);
|
||||
}
|
||||
|
||||
inline FString ToString(const Model& Value)
|
||||
{
|
||||
FString String;
|
||||
JsonWriter Writer = TJsonWriterFactory<>::Create(&String);
|
||||
Value.WriteJson(Writer);
|
||||
Writer->Close();
|
||||
return String;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline FString ToUrlString(const T& Value)
|
||||
{
|
||||
return FPlatformHttp::UrlEncode(ToString(Value));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline FString CollectionToUrlString(const TArray<T>& Collection, const TCHAR* Separator)
|
||||
{
|
||||
FString Output;
|
||||
if(Collection.Num() == 0)
|
||||
return Output;
|
||||
|
||||
Output += ToUrlString(Collection[0]);
|
||||
for(int i = 1; i < Collection.Num(); i++)
|
||||
{
|
||||
Output += FString::Format(TEXT("{0}{1}"), { Separator, *ToUrlString(Collection[i]) });
|
||||
}
|
||||
return Output;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline FString CollectionToUrlString_csv(const TArray<T>& Collection, const TCHAR* BaseName)
|
||||
{
|
||||
return CollectionToUrlString(Collection, TEXT(","));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline FString CollectionToUrlString_ssv(const TArray<T>& Collection, const TCHAR* BaseName)
|
||||
{
|
||||
return CollectionToUrlString(Collection, TEXT(" "));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline FString CollectionToUrlString_tsv(const TArray<T>& Collection, const TCHAR* BaseName)
|
||||
{
|
||||
return CollectionToUrlString(Collection, TEXT("\t"));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline FString CollectionToUrlString_pipes(const TArray<T>& Collection, const TCHAR* BaseName)
|
||||
{
|
||||
return CollectionToUrlString(Collection, TEXT("|"));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline FString CollectionToUrlString_multi(const TArray<T>& Collection, const TCHAR* BaseName)
|
||||
{
|
||||
FString Output;
|
||||
if(Collection.Num() == 0)
|
||||
return Output;
|
||||
|
||||
Output += FString::Format(TEXT("{0}={1}"), { FStringFormatArg(BaseName), ToUrlString(Collection[0]) });
|
||||
for(int i = 1; i < Collection.Num(); i++)
|
||||
{
|
||||
Output += FString::Format(TEXT("&{0}={1}"), { FStringFormatArg(BaseName), ToUrlString(Collection[i]) });
|
||||
}
|
||||
return Output;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<typename T, typename std::enable_if<!std::is_base_of<Model, T>::value, int>::type = 0>
|
||||
inline void WriteJsonValue(JsonWriter& Writer, const T& Value)
|
||||
{
|
||||
Writer->WriteValue(Value);
|
||||
}
|
||||
|
||||
inline void WriteJsonValue(JsonWriter& Writer, const FDateTime& Value)
|
||||
{
|
||||
Writer->WriteValue(Value.ToIso8601());
|
||||
}
|
||||
|
||||
inline void WriteJsonValue(JsonWriter& Writer, const Model& Value)
|
||||
{
|
||||
Value.WriteJson(Writer);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline void WriteJsonValue(JsonWriter& Writer, const TArray<T>& Value)
|
||||
{
|
||||
Writer->WriteArrayStart();
|
||||
for (const auto& Element : Value)
|
||||
{
|
||||
WriteJsonValue(Writer, Element);
|
||||
}
|
||||
Writer->WriteArrayEnd();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline void WriteJsonValue(JsonWriter& Writer, const TMap<FString, T>& Value)
|
||||
{
|
||||
Writer->WriteObjectStart();
|
||||
for (const auto& It : Value)
|
||||
{
|
||||
Writer->WriteIdentifierPrefix(It.Key);
|
||||
WriteJsonValue(Writer, It.Value);
|
||||
}
|
||||
Writer->WriteObjectEnd();
|
||||
}
|
||||
|
||||
inline void WriteJsonValue(JsonWriter& Writer, const TSharedPtr<FJsonObject>& Value)
|
||||
{
|
||||
if (Value.IsValid())
|
||||
{
|
||||
FJsonSerializer::Serialize(Value.ToSharedRef(), Writer, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
Writer->WriteObjectStart();
|
||||
Writer->WriteObjectEnd();
|
||||
}
|
||||
}
|
||||
|
||||
inline void WriteJsonValue(JsonWriter& Writer, const TArray<uint8>& Value)
|
||||
{
|
||||
Writer->WriteValue(ToString(Value));
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<typename T>
|
||||
inline bool TryGetJsonValue(const TSharedPtr<FJsonObject>& JsonObject, const FString& Key, T& Value)
|
||||
{
|
||||
const TSharedPtr<FJsonValue> JsonValue = JsonObject->TryGetField(Key);
|
||||
if (JsonValue.IsValid() && !JsonValue->IsNull())
|
||||
{
|
||||
return TryGetJsonValue(JsonValue, Value);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline bool TryGetJsonValue(const TSharedPtr<FJsonObject>& JsonObject, const FString& Key, TOptional<T>& OptionalValue)
|
||||
{
|
||||
if(JsonObject->HasField(Key))
|
||||
{
|
||||
T Value;
|
||||
if (TryGetJsonValue(JsonObject, Key, Value))
|
||||
{
|
||||
OptionalValue = Value;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
return true; // Absence of optional value is not a parsing error
|
||||
}
|
||||
|
||||
inline bool TryGetJsonValue(const TSharedPtr<FJsonValue>& JsonValue, FString& Value)
|
||||
{
|
||||
FString TmpValue;
|
||||
if (JsonValue->TryGetString(TmpValue))
|
||||
{
|
||||
Value = TmpValue;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool TryGetJsonValue(const TSharedPtr<FJsonValue>& JsonValue, FDateTime& Value)
|
||||
{
|
||||
FString TmpValue;
|
||||
if (JsonValue->TryGetString(TmpValue))
|
||||
return FDateTime::Parse(TmpValue, Value);
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool TryGetJsonValue(const TSharedPtr<FJsonValue>& JsonValue, bool& Value)
|
||||
{
|
||||
bool TmpValue;
|
||||
if (JsonValue->TryGetBool(TmpValue))
|
||||
{
|
||||
Value = TmpValue;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
template<typename T, typename std::enable_if<!std::is_base_of<Model, T>::value, int>::type = 0>
|
||||
inline bool TryGetJsonValue(const TSharedPtr<FJsonValue>& JsonValue, T& Value)
|
||||
{
|
||||
T TmpValue;
|
||||
if (JsonValue->TryGetNumber(TmpValue))
|
||||
{
|
||||
Value = TmpValue;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool TryGetJsonValue(const TSharedPtr<FJsonValue>& JsonValue, Model& Value)
|
||||
{
|
||||
const TSharedPtr<FJsonObject>* Object;
|
||||
if (JsonValue->TryGetObject(Object))
|
||||
return Value.FromJson(*Object);
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline bool TryGetJsonValue(const TSharedPtr<FJsonValue>& JsonValue, TArray<T>& ArrayValue)
|
||||
{
|
||||
const TArray<TSharedPtr<FJsonValue>>* JsonArray;
|
||||
if (JsonValue->TryGetArray(JsonArray))
|
||||
{
|
||||
bool ParseSuccess = true;
|
||||
const int32 Count = JsonArray->Num();
|
||||
ArrayValue.Reset(Count);
|
||||
for (int i = 0; i < Count; i++)
|
||||
{
|
||||
T TmpValue;
|
||||
ParseSuccess &= TryGetJsonValue((*JsonArray)[i], TmpValue);
|
||||
ArrayValue.Emplace(MoveTemp(TmpValue));
|
||||
}
|
||||
return ParseSuccess;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline bool TryGetJsonValue(const TSharedPtr<FJsonValue>& JsonValue, TMap<FString, T>& MapValue)
|
||||
{
|
||||
const TSharedPtr<FJsonObject>* Object;
|
||||
if (JsonValue->TryGetObject(Object))
|
||||
{
|
||||
MapValue.Reset();
|
||||
bool ParseSuccess = true;
|
||||
for (const auto& It : (*Object)->Values)
|
||||
{
|
||||
T TmpValue;
|
||||
ParseSuccess &= TryGetJsonValue(It.Value, TmpValue);
|
||||
MapValue.Emplace(It.Key, MoveTemp(TmpValue));
|
||||
}
|
||||
return ParseSuccess;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool TryGetJsonValue(const TSharedPtr<FJsonValue>& JsonValue, TSharedPtr<FJsonObject>& JsonObjectValue)
|
||||
{
|
||||
const TSharedPtr<FJsonObject>* Object;
|
||||
if (JsonValue->TryGetObject(Object))
|
||||
{
|
||||
JsonObjectValue = *Object;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool TryGetJsonValue(const TSharedPtr<FJsonValue>& JsonValue, TArray<uint8>& Value)
|
||||
{
|
||||
FString TmpValue;
|
||||
if (JsonValue->TryGetString(TmpValue))
|
||||
{
|
||||
Base64UrlDecode(TmpValue, Value);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
{{#cppNamespaceDeclarations}}
|
||||
}
|
||||
{{/cppNamespaceDeclarations}}
|
||||
187
modules/openapi-generator/src/main/resources/cpp-ue4/helpers-source.mustache
vendored
Normal file
187
modules/openapi-generator/src/main/resources/cpp-ue4/helpers-source.mustache
vendored
Normal file
@@ -0,0 +1,187 @@
|
||||
{{>licenseInfo}}
|
||||
#include "{{modelNamePrefix}}Helpers.h"
|
||||
|
||||
#include "{{unrealModuleName}}Module.h"
|
||||
|
||||
#include "Interfaces/IHttpRequest.h"
|
||||
#include "PlatformHttp.h"
|
||||
#include "Misc/FileHelper.h"
|
||||
|
||||
{{#cppNamespaceDeclarations}}
|
||||
namespace {{this}}
|
||||
{
|
||||
{{/cppNamespaceDeclarations}}
|
||||
|
||||
HttpFileInput::HttpFileInput(const TCHAR* InFilePath)
|
||||
{
|
||||
SetFilePath(InFilePath);
|
||||
}
|
||||
|
||||
HttpFileInput::HttpFileInput(const FString& InFilePath)
|
||||
{
|
||||
SetFilePath(InFilePath);
|
||||
}
|
||||
|
||||
void HttpFileInput::SetFilePath(const TCHAR* InFilePath)
|
||||
{
|
||||
FilePath = InFilePath;
|
||||
if(ContentType.IsEmpty())
|
||||
{
|
||||
ContentType = FPlatformHttp::GetMimeType(InFilePath);
|
||||
}
|
||||
}
|
||||
|
||||
void HttpFileInput::SetFilePath(const FString& InFilePath)
|
||||
{
|
||||
SetFilePath(*InFilePath);
|
||||
}
|
||||
|
||||
void HttpFileInput::SetContentType(const TCHAR* InContentType)
|
||||
{
|
||||
ContentType = InContentType;
|
||||
}
|
||||
|
||||
FString HttpFileInput::GetFilename() const
|
||||
{
|
||||
return FPaths::GetCleanFilename(FilePath);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
const TCHAR* HttpMultipartFormData::Delimiter = TEXT("--");
|
||||
const TCHAR* HttpMultipartFormData::Newline = TEXT("\r\n");
|
||||
|
||||
void HttpMultipartFormData::SetBoundary(const TCHAR* InBoundary)
|
||||
{
|
||||
checkf(Boundary.IsEmpty(), TEXT("Boundary must be set before usage"));
|
||||
Boundary = InBoundary;
|
||||
}
|
||||
|
||||
const FString& HttpMultipartFormData::GetBoundary() const
|
||||
{
|
||||
if (Boundary.IsEmpty())
|
||||
{
|
||||
// Generate a random boundary with enough entropy, should avoid occurences of the boundary in the data.
|
||||
// Since the boundary is generated at every request, in case of failure, retries should succeed.
|
||||
Boundary = FGuid::NewGuid().ToString(EGuidFormats::Short);
|
||||
}
|
||||
|
||||
return Boundary;
|
||||
}
|
||||
|
||||
void HttpMultipartFormData::SetupHttpRequest(const TSharedRef<IHttpRequest>& HttpRequest)
|
||||
{
|
||||
if(HttpRequest->GetVerb() != TEXT("POST"))
|
||||
{
|
||||
UE_LOG(Log{{unrealModuleName}}, Error, TEXT("Expected POST verb when using multipart form data"));
|
||||
}
|
||||
|
||||
// Append final boundary
|
||||
AppendString(Delimiter);
|
||||
AppendString(*GetBoundary());
|
||||
AppendString(Delimiter);
|
||||
|
||||
HttpRequest->SetHeader("Content-Type", FString::Printf(TEXT("multipart/form-data; boundary=%s"), *GetBoundary()));
|
||||
HttpRequest->SetContent(FormData);
|
||||
}
|
||||
|
||||
void HttpMultipartFormData::AddStringPart(const TCHAR* Name, const TCHAR* Data)
|
||||
{
|
||||
// Add boundary
|
||||
AppendString(Delimiter);
|
||||
AppendString(*GetBoundary());
|
||||
AppendString(Newline);
|
||||
|
||||
// Add header
|
||||
AppendString(*FString::Printf(TEXT("Content-Disposition: form-data; name = \"%s\""), Name));
|
||||
AppendString(Newline);
|
||||
AppendString(*FString::Printf(TEXT("Content-Type: text/plain; charset=utf-8")));
|
||||
AppendString(Newline);
|
||||
|
||||
// Add header to body splitter
|
||||
AppendString(Newline);
|
||||
|
||||
// Add Data
|
||||
AppendString(Data);
|
||||
AppendString(Newline);
|
||||
}
|
||||
|
||||
void HttpMultipartFormData::AddJsonPart(const TCHAR* Name, const FString& JsonString)
|
||||
{
|
||||
// Add boundary
|
||||
AppendString(Delimiter);
|
||||
AppendString(*GetBoundary());
|
||||
AppendString(Newline);
|
||||
|
||||
// Add header
|
||||
AppendString(*FString::Printf(TEXT("Content-Disposition: form-data; name=\"%s\""), Name));
|
||||
AppendString(Newline);
|
||||
AppendString(*FString::Printf(TEXT("Content-Type: application/json; charset=utf-8")));
|
||||
AppendString(Newline);
|
||||
|
||||
// Add header to body splitter
|
||||
AppendString(Newline);
|
||||
|
||||
// Add Data
|
||||
AppendString(*JsonString);
|
||||
AppendString(Newline);
|
||||
}
|
||||
|
||||
void HttpMultipartFormData::AddBinaryPart(const TCHAR* Name, const TArray<uint8>& ByteArray)
|
||||
{
|
||||
// Add boundary
|
||||
AppendString(Delimiter);
|
||||
AppendString(*GetBoundary());
|
||||
AppendString(Newline);
|
||||
|
||||
// Add header
|
||||
AppendString(*FString::Printf(TEXT("Content-Disposition: form-data; name=\"%s\""), Name));
|
||||
AppendString(Newline);
|
||||
AppendString(*FString::Printf(TEXT("Content-Type: application/octet-stream")));
|
||||
AppendString(Newline);
|
||||
|
||||
// Add header to body splitter
|
||||
AppendString(Newline);
|
||||
|
||||
// Add Data
|
||||
FormData.Append(ByteArray);
|
||||
AppendString(Newline);
|
||||
}
|
||||
|
||||
void HttpMultipartFormData::AddFilePart(const TCHAR* Name, const HttpFileInput& File)
|
||||
{
|
||||
TArray<uint8> FileContents;
|
||||
if (!FFileHelper::LoadFileToArray(FileContents, *File.GetFilePath()))
|
||||
{
|
||||
UE_LOG(Log{{unrealModuleName}}, Error, TEXT("Failed to load file (%s)"), *File.GetFilePath());
|
||||
return;
|
||||
}
|
||||
|
||||
// Add boundary
|
||||
AppendString(Delimiter);
|
||||
AppendString(*GetBoundary());
|
||||
AppendString(Newline);
|
||||
|
||||
// Add header
|
||||
AppendString(*FString::Printf(TEXT("Content-Disposition: form-data; name=\"%s\"; filename=\"%s\""), Name, *File.GetFilename()));
|
||||
AppendString(Newline);
|
||||
AppendString(*FString::Printf(TEXT("Content-Type: %s"), *File.GetContentType()));
|
||||
AppendString(Newline);
|
||||
|
||||
// Add header to body splitter
|
||||
AppendString(Newline);
|
||||
|
||||
// Add Data
|
||||
FormData.Append(FileContents);
|
||||
AppendString(Newline);
|
||||
}
|
||||
|
||||
void HttpMultipartFormData::AppendString(const TCHAR* Str)
|
||||
{
|
||||
FTCHARToUTF8 utf8Str(Str);
|
||||
FormData.Append((uint8*)utf8Str.Get(), utf8Str.Length());
|
||||
}
|
||||
|
||||
{{#cppNamespaceDeclarations}}
|
||||
}
|
||||
{{/cppNamespaceDeclarations}}
|
||||
11
modules/openapi-generator/src/main/resources/cpp-ue4/licenseInfo.mustache
vendored
Normal file
11
modules/openapi-generator/src/main/resources/cpp-ue4/licenseInfo.mustache
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
/**
|
||||
* {{{appName}}}
|
||||
* {{{appDescription}}}
|
||||
*
|
||||
* {{#version}}OpenAPI spec version: {{{version}}}{{/version}}
|
||||
* {{#infoEmail}}Contact: {{{infoEmail}}}{{/infoEmail}}
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator
|
||||
* https://github.com/OpenAPITools/openapi-generator
|
||||
* Do not edit the class manually.
|
||||
*/
|
||||
59
modules/openapi-generator/src/main/resources/cpp-ue4/model-base-header.mustache
vendored
Normal file
59
modules/openapi-generator/src/main/resources/cpp-ue4/model-base-header.mustache
vendored
Normal file
@@ -0,0 +1,59 @@
|
||||
{{>licenseInfo}}
|
||||
#pragma once
|
||||
|
||||
#include "Interfaces/IHttpRequest.h"
|
||||
#include "Interfaces/IHttpResponse.h"
|
||||
#include "Serialization/JsonWriter.h"
|
||||
#include "Dom/JsonObject.h"
|
||||
|
||||
{{#cppNamespaceDeclarations}}
|
||||
namespace {{this}}
|
||||
{
|
||||
{{/cppNamespaceDeclarations}}
|
||||
|
||||
typedef TSharedRef<TJsonWriter<>> JsonWriter;
|
||||
|
||||
class {{dllapi}} Model
|
||||
{
|
||||
public:
|
||||
virtual ~Model() {}
|
||||
virtual void WriteJson(JsonWriter& Writer) const = 0;
|
||||
virtual bool FromJson(const TSharedPtr<FJsonObject>& JsonObject) = 0;
|
||||
};
|
||||
|
||||
class {{dllapi}} Request
|
||||
{
|
||||
public:
|
||||
virtual ~Request() {}
|
||||
virtual void SetupHttpRequest(const TSharedRef<IHttpRequest>& HttpRequest) const = 0;
|
||||
virtual FString ComputePath() const = 0;
|
||||
};
|
||||
|
||||
class {{dllapi}} Response
|
||||
{
|
||||
public:
|
||||
virtual ~Response() {}
|
||||
virtual bool FromJson(const TSharedPtr<FJsonValue>& JsonObject) = 0;
|
||||
|
||||
void SetSuccessful(bool InSuccessful) { Successful = InSuccessful; }
|
||||
bool IsSuccessful() const { return Successful; }
|
||||
|
||||
virtual void SetHttpResponseCode(EHttpResponseCodes::Type InHttpResponseCode);
|
||||
EHttpResponseCodes::Type GetHttpResponseCode() const { return ResponseCode; }
|
||||
|
||||
void SetResponseString(const FString& InResponseString) { ResponseString = InResponseString; }
|
||||
const FString& GetResponseString() const { return ResponseString; }
|
||||
|
||||
void SetHttpResponse(const FHttpResponsePtr& InHttpResponse) { HttpResponse = InHttpResponse; }
|
||||
const FHttpResponsePtr& GetHttpResponse() const { return HttpResponse; }
|
||||
|
||||
private:
|
||||
bool Successful;
|
||||
EHttpResponseCodes::Type ResponseCode;
|
||||
FString ResponseString;
|
||||
FHttpResponsePtr HttpResponse;
|
||||
};
|
||||
|
||||
{{#cppNamespaceDeclarations}}
|
||||
}
|
||||
{{/cppNamespaceDeclarations}}
|
||||
21
modules/openapi-generator/src/main/resources/cpp-ue4/model-base-source.mustache
vendored
Normal file
21
modules/openapi-generator/src/main/resources/cpp-ue4/model-base-source.mustache
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
{{>licenseInfo}}
|
||||
#include "{{modelNamePrefix}}BaseModel.h"
|
||||
|
||||
{{#cppNamespaceDeclarations}}
|
||||
namespace {{this}}
|
||||
{
|
||||
{{/cppNamespaceDeclarations}}
|
||||
|
||||
void Response::SetHttpResponseCode(EHttpResponseCodes::Type InHttpResponseCode)
|
||||
{
|
||||
ResponseCode = InHttpResponseCode;
|
||||
SetSuccessful(EHttpResponseCodes::IsOk(InHttpResponseCode));
|
||||
if(InHttpResponseCode == EHttpResponseCodes::RequestTimeout)
|
||||
{
|
||||
SetResponseString(TEXT("Request Timeout"));
|
||||
}
|
||||
}
|
||||
|
||||
{{#cppNamespaceDeclarations}}
|
||||
}
|
||||
{{/cppNamespaceDeclarations}}
|
||||
51
modules/openapi-generator/src/main/resources/cpp-ue4/model-header.mustache
vendored
Normal file
51
modules/openapi-generator/src/main/resources/cpp-ue4/model-header.mustache
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
{{>licenseInfo}}
|
||||
#pragma once
|
||||
|
||||
#include "{{modelNamePrefix}}BaseModel.h"
|
||||
{{#imports}}{{{import}}}
|
||||
{{/imports}}
|
||||
|
||||
{{#cppNamespaceDeclarations}}
|
||||
namespace {{this}}
|
||||
{
|
||||
{{/cppNamespaceDeclarations}}
|
||||
{{#models}}
|
||||
{{#model}}
|
||||
|
||||
/*
|
||||
* {{classname}}
|
||||
*
|
||||
* {{description}}
|
||||
*/
|
||||
class {{dllapi}} {{classname}} : public Model
|
||||
{
|
||||
public:
|
||||
virtual ~{{classname}}() {}
|
||||
bool FromJson(const TSharedPtr<FJsonObject>& JsonObject) final;
|
||||
void WriteJson(JsonWriter& Writer) const final;
|
||||
|
||||
{{#vars}}
|
||||
{{#isEnum}}
|
||||
{{#allowableValues}}
|
||||
enum class {{{enumName}}}
|
||||
{
|
||||
{{#enumVars}}
|
||||
{{name}},
|
||||
{{/enumVars}}
|
||||
};
|
||||
{{/allowableValues}}
|
||||
{{#description}}/* {{{description}}} */
|
||||
{{/description}}{{^required}}TOptional<{{/required}}{{{datatypeWithEnum}}}{{^required}}>{{/required}} {{name}}{{#required}}{{#defaultValue}} = {{{defaultValue}}}{{/defaultValue}}{{/required}};
|
||||
{{/isEnum}}
|
||||
{{^isEnum}}
|
||||
{{#description}}/* {{{description}}} */
|
||||
{{/description}}{{^required}}TOptional<{{/required}}{{{datatype}}}{{^required}}>{{/required}} {{name}}{{#required}}{{#defaultValue}} = {{{defaultValue}}}{{/defaultValue}}{{/required}};
|
||||
{{/isEnum}}
|
||||
{{/vars}}
|
||||
};
|
||||
|
||||
{{/model}}
|
||||
{{/models}}
|
||||
{{#cppNamespaceDeclarations}}
|
||||
}
|
||||
{{/cppNamespaceDeclarations}}
|
||||
98
modules/openapi-generator/src/main/resources/cpp-ue4/model-source.mustache
vendored
Normal file
98
modules/openapi-generator/src/main/resources/cpp-ue4/model-source.mustache
vendored
Normal file
@@ -0,0 +1,98 @@
|
||||
{{>licenseInfo}}
|
||||
#include "{{classname}}.h"
|
||||
|
||||
#include "{{unrealModuleName}}Module.h"
|
||||
#include "{{modelNamePrefix}}Helpers.h"
|
||||
|
||||
#include "Templates/SharedPointer.h"
|
||||
|
||||
{{#cppNamespaceDeclarations}}
|
||||
namespace {{this}}
|
||||
{
|
||||
{{/cppNamespaceDeclarations}}
|
||||
{{#models}}{{#model}}
|
||||
{{#hasEnums}}
|
||||
{{#vars}}
|
||||
{{#isEnum}}
|
||||
inline FString ToString(const {{classname}}::{{{enumName}}}& Value)
|
||||
{
|
||||
{{#allowableValues}}
|
||||
switch (Value)
|
||||
{
|
||||
{{#enumVars}}
|
||||
case {{classname}}::{{{enumName}}}::{{name}}:
|
||||
return TEXT({{{value}}});
|
||||
{{/enumVars}}
|
||||
}
|
||||
{{/allowableValues}}
|
||||
|
||||
UE_LOG(Log{{unrealModuleName}}, Error, TEXT("Invalid {{classname}}::{{{enumName}}} Value (%d)"), (int)Value);
|
||||
return TEXT("");
|
||||
}
|
||||
|
||||
inline FStringFormatArg ToStringFormatArg(const {{classname}}::{{{enumName}}}& Value)
|
||||
{
|
||||
return FStringFormatArg(ToString(Value));
|
||||
}
|
||||
|
||||
inline void WriteJsonValue(JsonWriter& Writer, const {{classname}}::{{{enumName}}}& Value)
|
||||
{
|
||||
WriteJsonValue(Writer, ToString(Value));
|
||||
}
|
||||
|
||||
inline bool TryGetJsonValue(const TSharedPtr<FJsonValue>& JsonValue, {{classname}}::{{{enumName}}}& Value)
|
||||
{
|
||||
FString TmpValue;
|
||||
if (JsonValue->TryGetString(TmpValue))
|
||||
{
|
||||
static TMap<FString, {{classname}}::{{{enumName}}}> StringToEnum = { {{#enumVars}}
|
||||
{ TEXT({{{value}}}), {{classname}}::{{{enumName}}}::{{name}} },{{/enumVars}} };
|
||||
|
||||
const auto Found = StringToEnum.Find(TmpValue);
|
||||
if(Found)
|
||||
{
|
||||
Value = *Found;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
{{/isEnum}}
|
||||
{{/vars}}
|
||||
{{/hasEnums}}
|
||||
void {{classname}}::WriteJson(JsonWriter& Writer) const
|
||||
{
|
||||
{{#parent}}
|
||||
#error inheritance not handled right now
|
||||
{{/parent}}
|
||||
Writer->WriteObjectStart();
|
||||
{{#vars}}
|
||||
{{#required}}
|
||||
Writer->WriteIdentifierPrefix(TEXT("{{baseName}}")); WriteJsonValue(Writer, {{name}});
|
||||
{{/required}}
|
||||
{{^required}}
|
||||
if ({{name}}.IsSet())
|
||||
{
|
||||
Writer->WriteIdentifierPrefix(TEXT("{{baseName}}")); WriteJsonValue(Writer, {{name}}.GetValue());
|
||||
}
|
||||
{{/required}}
|
||||
{{/vars}}
|
||||
Writer->WriteObjectEnd();
|
||||
}
|
||||
|
||||
bool {{classname}}::FromJson(const TSharedPtr<FJsonObject>& JsonObject)
|
||||
{
|
||||
bool ParseSuccess = true;
|
||||
|
||||
{{#vars}}
|
||||
ParseSuccess &= TryGetJsonValue(JsonObject, TEXT("{{baseName}}"), {{name}});
|
||||
{{/vars}}
|
||||
|
||||
return ParseSuccess;
|
||||
}
|
||||
{{/model}}
|
||||
{{/models}}
|
||||
{{#cppNamespaceDeclarations}}
|
||||
}
|
||||
{{/cppNamespaceDeclarations}}
|
||||
15
modules/openapi-generator/src/main/resources/cpp-ue4/module-header.mustache
vendored
Normal file
15
modules/openapi-generator/src/main/resources/cpp-ue4/module-header.mustache
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
{{>licenseInfo}}
|
||||
#pragma once
|
||||
|
||||
#include "Modules/ModuleInterface.h"
|
||||
#include "Modules/ModuleManager.h"
|
||||
#include "Logging/LogMacros.h"
|
||||
|
||||
DECLARE_LOG_CATEGORY_EXTERN(Log{{unrealModuleName}}, Log, All);
|
||||
|
||||
class {{dllapi}} {{unrealModuleName}}Module : public IModuleInterface
|
||||
{
|
||||
public:
|
||||
void StartupModule() final;
|
||||
void ShutdownModule() final;
|
||||
};
|
||||
14
modules/openapi-generator/src/main/resources/cpp-ue4/module-source.mustache
vendored
Normal file
14
modules/openapi-generator/src/main/resources/cpp-ue4/module-source.mustache
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
{{>licenseInfo}}
|
||||
#include "{{unrealModuleName}}Module.h"
|
||||
|
||||
IMPLEMENT_MODULE({{unrealModuleName}}Module, {{unrealModuleName}});
|
||||
DEFINE_LOG_CATEGORY(Log{{unrealModuleName}});
|
||||
|
||||
void {{unrealModuleName}}Module::StartupModule()
|
||||
{
|
||||
}
|
||||
|
||||
void {{unrealModuleName}}Module::ShutdownModule()
|
||||
{
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user