mirror of
https://github.com/OpenAPITools/openapi-generator.git
synced 2026-03-18 19:59:11 +00:00
[Apex] migrating to OpenAPI Generator project (#692)
* [apex] migrating to OpenAPITools * migrate apex to openapi-generator
This commit is contained in:
@@ -0,0 +1,698 @@
|
||||
/*
|
||||
* Copyright 2018 OpenAPI-Generator Contributors (https://openapi-generator.tech)
|
||||
* Copyright 2018 SmartBear Software
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://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 java.util.*;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import com.google.common.base.Strings;
|
||||
import org.openapitools.codegen.CodegenOperation;
|
||||
import org.openapitools.codegen.CodegenParameter;
|
||||
import org.openapitools.codegen.CodegenModel;
|
||||
import org.openapitools.codegen.CodegenConfig;
|
||||
import org.openapitools.codegen.CodegenProperty;
|
||||
import org.openapitools.codegen.CodegenType;
|
||||
import org.openapitools.codegen.DefaultCodegen;
|
||||
import org.openapitools.codegen.utils.ModelUtils;
|
||||
import io.swagger.v3.oas.models.media.*;
|
||||
import io.swagger.v3.oas.models.OpenAPI;
|
||||
import io.swagger.v3.oas.models.Operation;
|
||||
import io.swagger.v3.oas.models.responses.ApiResponse;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
|
||||
public abstract class AbstractApexCodegen extends DefaultCodegen implements CodegenConfig {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(AbstractApexCodegen.class);
|
||||
|
||||
protected Boolean serializableModel = false;
|
||||
|
||||
public AbstractApexCodegen() {
|
||||
super();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CodegenType getTag() {
|
||||
return CodegenType.CLIENT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "apex";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHelp() {
|
||||
return "Generates an Apex API client library.";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processOpts() {
|
||||
super.processOpts();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String escapeReservedWord(String name) {
|
||||
if (this.reservedWordsMappings().containsKey(name)) {
|
||||
return this.reservedWordsMappings().get(name);
|
||||
}
|
||||
return "_" + name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String sanitizeName(String name) {
|
||||
name = super.sanitizeName(name);
|
||||
if (name.contains("__")) { // Preventing namespacing
|
||||
name.replaceAll("__", "_");
|
||||
}
|
||||
if (name.matches("^\\d.*")) { // Prevent named credentials with leading number
|
||||
name.replaceAll("^\\d.*", "");
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
@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 (name.toLowerCase().matches("^_*class$")) {
|
||||
return "propertyClass";
|
||||
}
|
||||
|
||||
if ("_".equals(name)) {
|
||||
name = "_u";
|
||||
}
|
||||
|
||||
// if it's all uppper case, do nothing
|
||||
if (name.matches("^[A-Z_]*$")) {
|
||||
if (isReservedWord(name)) {
|
||||
name = escapeReservedWord(name);
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
if (startsWithTwoUppercaseLetters(name)) {
|
||||
name = name.substring(0, 2).toLowerCase() + name.substring(2);
|
||||
}
|
||||
|
||||
// camelize (lower first character) 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;
|
||||
}
|
||||
|
||||
private boolean startsWithTwoUppercaseLetters(String name) {
|
||||
boolean startsWithTwoUppercaseLetters = false;
|
||||
if (name.length() > 1) {
|
||||
startsWithTwoUppercaseLetters = name.substring(0, 2).equals(name.substring(0, 2).toUpperCase());
|
||||
}
|
||||
return startsWithTwoUppercaseLetters;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toParamName(String name) {
|
||||
// to avoid conflicts with 'callback' parameter for async call
|
||||
if ("callback".equals(name)) {
|
||||
return "paramCallback";
|
||||
}
|
||||
|
||||
// should be the same as variable name
|
||||
return toVarName(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toModelName(final String name) {
|
||||
|
||||
final String sanitizedName = sanitizeName(name);
|
||||
|
||||
String nameWithPrefixSuffix = sanitizedName;
|
||||
if (!StringUtils.isEmpty(modelNamePrefix)) {
|
||||
// add '_' so that model name can be camelized correctly
|
||||
nameWithPrefixSuffix = modelNamePrefix + "_" + nameWithPrefixSuffix;
|
||||
}
|
||||
|
||||
if (!StringUtils.isEmpty(modelNameSuffix)) {
|
||||
// add '_' so that model name can be camelized correctly
|
||||
nameWithPrefixSuffix = nameWithPrefixSuffix + "_" + modelNameSuffix;
|
||||
}
|
||||
|
||||
// camelize the model name
|
||||
// phone_number => PhoneNumber
|
||||
final String camelizedName = camelize(nameWithPrefixSuffix);
|
||||
|
||||
// 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 (camelizedName.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 toModelFilename(String name) {
|
||||
// should be the same as the model name
|
||||
return toModelName(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTypeDeclaration(Schema p) {
|
||||
if (ModelUtils.isArraySchema(p)) {
|
||||
ArraySchema ap = (ArraySchema) p;
|
||||
Schema inner = ap.getItems();
|
||||
if (inner == null) {
|
||||
LOGGER.warn(ap.getName() + "(array property) does not have a proper inner type defined");
|
||||
// TODO maybe better defaulting to StringProperty than returning null
|
||||
return null;
|
||||
}
|
||||
return getSchemaType(p) + "<" + getTypeDeclaration(inner) + ">";
|
||||
} else if (ModelUtils.isMapSchema(p)) {
|
||||
Schema inner = (Schema) p.getAdditionalProperties();
|
||||
|
||||
if (inner == null) {
|
||||
LOGGER.warn(p.getName() + "(map property) does not have a proper inner type defined");
|
||||
// TODO maybe better defaulting to StringProperty than returning null
|
||||
return null;
|
||||
}
|
||||
return getSchemaType(p) + "<String, " + getTypeDeclaration(inner) + ">";
|
||||
}
|
||||
return super.getTypeDeclaration(p);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAlias(String name) {
|
||||
if (typeAliases != null && typeAliases.containsKey(name)) {
|
||||
return typeAliases.get(name);
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toDefaultValue(Schema p) {
|
||||
if (ModelUtils.isArraySchema(p)) {
|
||||
final ArraySchema ap = (ArraySchema) p;
|
||||
final String pattern = "new ArrayList<%s>()";
|
||||
if (ap.getItems() == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return String.format(pattern, getTypeDeclaration(ap.getItems()));
|
||||
} else if (ModelUtils.isMapSchema(p)) {
|
||||
final MapSchema ap = (MapSchema) p;
|
||||
final String pattern = "new HashMap<%s>()";
|
||||
if (ap.getAdditionalProperties() == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return String.format(pattern, String.format("String, %s", getTypeDeclaration((Schema) ap.getAdditionalProperties())));
|
||||
} else if (ModelUtils.isLongSchema(p)) {
|
||||
if (p.getDefault() != null) {
|
||||
return p.getDefault().toString() + "l";
|
||||
}
|
||||
return "null";
|
||||
} else if (ModelUtils.isIntegerSchema(p)) {
|
||||
if (p.getDefault() != null) {
|
||||
return p.getDefault().toString();
|
||||
}
|
||||
return "null";
|
||||
} else if (ModelUtils.isFloatSchema(p)) {
|
||||
if (p.getDefault() != null) {
|
||||
return p.getDefault().toString() + "f";
|
||||
}
|
||||
return "null";
|
||||
} else if (ModelUtils.isDoubleSchema(p)) {
|
||||
if (p.getDefault() != null) {
|
||||
return p.getDefault().toString() + "d";
|
||||
}
|
||||
return "null";
|
||||
} else if (ModelUtils.isBooleanSchema(p)) {
|
||||
if (p.getDefault() != null) {
|
||||
return p.getDefault().toString();
|
||||
}
|
||||
return "null";
|
||||
} else if (ModelUtils.isStringSchema(p)) {
|
||||
if (p.getDefault() != null) {
|
||||
String _default = (String) p.getDefault();
|
||||
if (p.getEnum() == null) {
|
||||
return "\"" + escapeText(_default) + "\"";
|
||||
} else {
|
||||
// convert to enum var name later in postProcessModels
|
||||
return _default;
|
||||
}
|
||||
}
|
||||
return "null";
|
||||
}
|
||||
return super.toDefaultValue(p);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setParameterExampleValue(CodegenParameter p) {
|
||||
|
||||
if (Boolean.TRUE.equals(p.isLong)) {
|
||||
p.example = "2147483648L";
|
||||
} else if (Boolean.TRUE.equals(p.isFile)) {
|
||||
p.example = "Blob.valueOf('Sample text file\\nContents')";
|
||||
} else if (Boolean.TRUE.equals(p.isDate)) {
|
||||
p.example = "Date.newInstance(1960, 2, 17)";
|
||||
} else if (Boolean.TRUE.equals(p.isDateTime)) {
|
||||
p.example = "Datetime.newInstanceGmt(2013, 11, 12, 3, 3, 3)";
|
||||
} else if (Boolean.TRUE.equals(p.isListContainer)) {
|
||||
if (p.items != null && p.items.example != null) {
|
||||
p.example = "new " + p.dataType + "{" + p.items.example + "}";
|
||||
}
|
||||
} else if (Boolean.TRUE.equals(p.isMapContainer)) {
|
||||
if (p.items != null && p.items.example != null) {
|
||||
p.example = "new " + p.dataType + "{" + p.items.example + "}";
|
||||
}
|
||||
} else if (Boolean.TRUE.equals(p.isString)) {
|
||||
p.example = "'" + p.example + "'";
|
||||
} else if ("".equals(p.example) || p.example == null && p.dataType != "Object") {
|
||||
// Get an example object from the generated model
|
||||
if (!isReservedWord(p.dataType.toLowerCase())) {
|
||||
p.example = p.dataType + ".getExample()";
|
||||
}
|
||||
} else {
|
||||
p.example = "''";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toExampleValue(Schema p) {
|
||||
if (p == null) {
|
||||
return "";
|
||||
}
|
||||
|
||||
Object obj = p.getExample();
|
||||
String example = obj == null ? "" : obj.toString();
|
||||
|
||||
if (ModelUtils.isArraySchema(p)) {
|
||||
example = "new " + getTypeDeclaration(p) + "{" + toExampleValue(
|
||||
((ArraySchema) p).getItems()) + "}";
|
||||
} else if (ModelUtils.isBooleanSchema(p)) {
|
||||
example = String.valueOf(!"false".equals(example));
|
||||
} else if (ModelUtils.isByteArraySchema(p)) {
|
||||
if (example.isEmpty()) {
|
||||
example = "VGhlIHF1aWNrIGJyb3duIGZveCBqdW1wZWQgb3ZlciB0aGUgbGF6eSBkb2cu";
|
||||
}
|
||||
((ByteArraySchema) p).setExample(example);
|
||||
example = "EncodingUtil.base64Decode('" + example + "')";
|
||||
} else if (ModelUtils.isDateSchema(p)) {
|
||||
if (example.matches("^\\d{4}(-\\d{2}){2}")) {
|
||||
example = example.substring(0, 10).replaceAll("-0?", ", ");
|
||||
} else if (example.isEmpty()) {
|
||||
example = "2000, 1, 23";
|
||||
} else {
|
||||
LOGGER.warn(String.format("The example provided for property '%s' is not a valid RFC3339 date. Defaulting to '2000-01-23'. [%s]", p
|
||||
.getName(), example));
|
||||
example = "2000, 1, 23";
|
||||
}
|
||||
example = "Date.newInstance(" + example + ")";
|
||||
} else if (ModelUtils.isDateTimeSchema(p)) {
|
||||
if (example.matches("^\\d{4}([-T:]\\d{2}){5}.+")) {
|
||||
example = example.substring(0, 19).replaceAll("[-T:]0?", ", ");
|
||||
} else if (example.isEmpty()) {
|
||||
example = "2000, 1, 23, 4, 56, 7";
|
||||
} else {
|
||||
LOGGER.warn(String.format("The example provided for property '%s' is not a valid RFC3339 datetime. Defaulting to '2000-01-23T04-56-07Z'. [%s]", p
|
||||
.getName(), example));
|
||||
example = "2000, 1, 23, 4, 56, 7";
|
||||
}
|
||||
example = "Datetime.newInstanceGmt(" + example + ")";
|
||||
} else if (ModelUtils.isNumberSchema(p)) {
|
||||
example = example.replaceAll("[^-0-9.]", "");
|
||||
example = example.isEmpty() ? "1.3579" : example;
|
||||
} else if (ModelUtils.isFileSchema(p)) {
|
||||
if (example.isEmpty()) {
|
||||
example = "VGhlIHF1aWNrIGJyb3duIGZveCBqdW1wZWQgb3ZlciB0aGUgbGF6eSBkb2cu";
|
||||
p.setExample(example);
|
||||
}
|
||||
example = "EncodingUtil.base64Decode(" + example + ")";
|
||||
} else if (ModelUtils.isEmailSchema(p)) {
|
||||
if (example.isEmpty()) {
|
||||
example = "example@example.com";
|
||||
p.setExample(example);
|
||||
}
|
||||
example = "'" + example + "'";
|
||||
} else if (ModelUtils.isLongSchema(p)) {
|
||||
example = example.isEmpty() ? "123456789L" : example + "L";
|
||||
} else if (ModelUtils.isMapSchema(p)) {
|
||||
example = "new " + getTypeDeclaration(p) + "{'key'=>" + toExampleValue((Schema) p.getAdditionalProperties()) + "}";
|
||||
|
||||
} else if (ModelUtils.isPasswordSchema(p)) {
|
||||
example = example.isEmpty() ? "password123" : escapeText(example);
|
||||
p.setExample(example);
|
||||
example = "'" + example + "'";
|
||||
} else if (ModelUtils.isStringSchema(p)) {
|
||||
List<String> enums = p.getEnum();
|
||||
if (enums != null && example.isEmpty()) {
|
||||
example = enums.get(0);
|
||||
p.setExample(example);
|
||||
} else if (example.isEmpty()) {
|
||||
example = "";
|
||||
} else {
|
||||
example = escapeText(example);
|
||||
p.setExample(example);
|
||||
}
|
||||
example = "'" + example + "'";
|
||||
} else if (ModelUtils.isUUIDSchema(p)) {
|
||||
example = example.isEmpty()
|
||||
? "'046b6c7f-0b8a-43b9-b35d-6489e6daee91'"
|
||||
: "'" + escapeText(example) + "'";
|
||||
} else if (ModelUtils.isIntegerSchema(p)) {
|
||||
example = example.matches("^-?\\d+$") ? example : "0";
|
||||
} else if (ModelUtils.isObjectSchema(p)) {
|
||||
example = example.isEmpty() ? "null" : example;
|
||||
} else {
|
||||
example = super.toExampleValue(p);
|
||||
}
|
||||
return example;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSchemaType(Schema p) {
|
||||
String schemaType = super.getSchemaType(p);
|
||||
|
||||
schemaType = getAlias(schemaType);
|
||||
|
||||
// don't apply renaming on types from the typeMapping
|
||||
if (typeMapping.containsKey(schemaType)) {
|
||||
return typeMapping.get(schemaType);
|
||||
}
|
||||
|
||||
if (null == schemaType) {
|
||||
LOGGER.error("No Type defined for Property " + p);
|
||||
}
|
||||
return toModelName(schemaType);
|
||||
}
|
||||
|
||||
@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");
|
||||
}
|
||||
|
||||
operationId = camelize(sanitizeName(operationId), true);
|
||||
|
||||
// method name cannot use reserved keyword, e.g. return
|
||||
if (isReservedWord(operationId)) {
|
||||
String newOperationId = camelize("call_" + operationId, true);
|
||||
LOGGER.warn(operationId + " (reserved word) cannot be used as method name. Renamed to " + newOperationId);
|
||||
return newOperationId;
|
||||
}
|
||||
|
||||
return operationId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CodegenModel fromModel(String name, Schema model, Map<String, Schema> allDefinitions) {
|
||||
CodegenModel cm = super.fromModel(name, model, allDefinitions);
|
||||
|
||||
// TODO Check enum model handling
|
||||
if (cm.interfaces == null) {
|
||||
cm.interfaces = new ArrayList<String>();
|
||||
}
|
||||
|
||||
Boolean hasDefaultValues = false;
|
||||
|
||||
// for (de)serializing properties renamed for Apex (e.g. reserved words)
|
||||
List<Map<String, String>> propertyMappings = new ArrayList<>();
|
||||
for (CodegenProperty p : cm.allVars) {
|
||||
hasDefaultValues |= p.defaultValue != null;
|
||||
if (!p.baseName.equals(p.name)) {
|
||||
Map<String, String> mapping = new HashMap<>();
|
||||
mapping.put("externalName", p.baseName);
|
||||
mapping.put("internalName", p.name);
|
||||
propertyMappings.add(mapping);
|
||||
}
|
||||
}
|
||||
|
||||
cm.vendorExtensions.put("hasPropertyMappings", !propertyMappings.isEmpty());
|
||||
cm.vendorExtensions.put("hasDefaultValues", hasDefaultValues);
|
||||
cm.vendorExtensions.put("propertyMappings", propertyMappings);
|
||||
|
||||
if (!propertyMappings.isEmpty()) {
|
||||
cm.interfaces.add("Swagger.MappedProperties");
|
||||
}
|
||||
return cm;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postProcessParameter(CodegenParameter parameter) {
|
||||
if (parameter.isBodyParam && parameter.isListContainer) {
|
||||
// items of array bodyParams are being nested an extra level too deep for some reason
|
||||
parameter.items = parameter.items.items;
|
||||
setParameterExampleValue(parameter);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> postProcessModels(Map<String, Object> objs) {
|
||||
return postProcessModelsEnum(objs);
|
||||
}
|
||||
|
||||
/* the following function is not used anywhere in this class so we'll remove it later
|
||||
private static String getAccept(Operation operation) {
|
||||
String accepts = null;
|
||||
String defaultContentType = "application/json";
|
||||
if (operation.getProduces() != null && !operation.getProduces().isEmpty()) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (String produces : operation.getProduces()) {
|
||||
if (defaultContentType.equalsIgnoreCase(produces)) {
|
||||
accepts = defaultContentType;
|
||||
break;
|
||||
} else {
|
||||
if (sb.length() > 0) {
|
||||
sb.append(",");
|
||||
}
|
||||
sb.append(produces);
|
||||
}
|
||||
}
|
||||
if (accepts == null) {
|
||||
accepts = sb.toString();
|
||||
}
|
||||
} else {
|
||||
accepts = defaultContentType;
|
||||
}
|
||||
|
||||
return accepts;
|
||||
}*/
|
||||
|
||||
@Override
|
||||
protected boolean needToImport(String type) {
|
||||
return super.needToImport(type) && type.indexOf(".") < 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toEnumName(CodegenProperty property) {
|
||||
return sanitizeName(camelize(property.name)) + "Enum";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toEnumVarName(String value, String datatype) {
|
||||
if (value.length() == 0) {
|
||||
return "EMPTY";
|
||||
}
|
||||
|
||||
// for symbol, e.g. $, #
|
||||
if (getSymbolName(value) != null) {
|
||||
return getSymbolName(value).toUpperCase();
|
||||
}
|
||||
|
||||
// number
|
||||
if ("Integer".equals(datatype) || "Long".equals(datatype) ||
|
||||
"Float".equals(datatype) || "Double".equals(datatype)) {
|
||||
String varName = "NUMBER_" + value;
|
||||
varName = varName.replaceAll("-", "MINUS_");
|
||||
varName = varName.replaceAll("\\+", "PLUS_");
|
||||
varName = varName.replaceAll("\\.", "_DOT_");
|
||||
return varName;
|
||||
}
|
||||
|
||||
// string
|
||||
String var = value.replaceAll("\\W+", "_").toUpperCase();
|
||||
if (var.matches("\\d.*")) {
|
||||
return "_" + var;
|
||||
} else {
|
||||
return var;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toEnumValue(String value, String datatype) {
|
||||
if ("Integer".equals(datatype) || "Double".equals(datatype)) {
|
||||
return value;
|
||||
} else if ("Long".equals(datatype)) {
|
||||
// add l to number, e.g. 2048 => 2048l
|
||||
return value + "l";
|
||||
} else if ("Float".equals(datatype)) {
|
||||
// add f to number, e.g. 3.14 => 3.14f
|
||||
return value + "f";
|
||||
} else {
|
||||
return "\"" + escapeText(value) + "\"";
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public CodegenOperation fromOperation(String path, String httpMethod, Operation operation, Map<String, Schema> definitions, OpenAPI openAPI) {
|
||||
/* TODO the following logic revised. Maybe we should simply use the consumes, produces provided by the spec
|
||||
Boolean hasFormParams = false;
|
||||
for (Parameter p : operation.getParameters()) {
|
||||
if ("formData".equals(p.getIn())) {
|
||||
hasFormParams = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// only support serialization into JSON and urlencoded forms for now
|
||||
operation.setConsumes(
|
||||
Collections.singletonList(hasFormParams
|
||||
? "application/x-www-form-urlencoded"
|
||||
: "application/json"));
|
||||
|
||||
// only support deserialization from JSON for now
|
||||
operation.setProduces(Collections.singletonList("application/json"));
|
||||
*/
|
||||
|
||||
CodegenOperation op = super.fromOperation(
|
||||
path, httpMethod, operation, definitions, openAPI);
|
||||
|
||||
if (op.getHasExamples()) {
|
||||
// prepare examples for Apex test classes
|
||||
ApiResponse apiResponse = findMethodResponse(operation.getResponses());
|
||||
final Schema responseSchema = ModelUtils.getSchemaFromResponse(apiResponse);
|
||||
String deserializedExample = toExampleValue(responseSchema);
|
||||
for (Map<String, String> example : op.examples) {
|
||||
example.put("example", escapeText(example.get("example")));
|
||||
example.put("deserializedExample", deserializedExample);
|
||||
}
|
||||
}
|
||||
|
||||
return op;
|
||||
}
|
||||
|
||||
private static CodegenModel reconcileInlineEnums(CodegenModel codegenModel, CodegenModel parentCodegenModel) {
|
||||
// This generator uses inline classes to define enums, which breaks when
|
||||
// dealing with models that have subTypes. To clean this up, we will analyze
|
||||
// the parent and child models, look for enums that match, and remove
|
||||
// them from the child models and leave them in the parent.
|
||||
// Because the child models extend the parents, the enums will be available via the parent.
|
||||
|
||||
// Only bother with reconciliation if the parent model has enums.
|
||||
if (!parentCodegenModel.hasEnums) {
|
||||
return codegenModel;
|
||||
}
|
||||
|
||||
// Get the properties for the parent and child models
|
||||
final List<CodegenProperty> parentModelCodegenProperties = parentCodegenModel.vars;
|
||||
List<CodegenProperty> codegenProperties = codegenModel.vars;
|
||||
|
||||
// Iterate over all of the parent model properties
|
||||
boolean removedChildEnum = false;
|
||||
for (CodegenProperty parentModelCodegenPropery : parentModelCodegenProperties) {
|
||||
// Look for enums
|
||||
if (parentModelCodegenPropery.isEnum) {
|
||||
// Now that we have found an enum in the parent class,
|
||||
// and search the child class for the same enum.
|
||||
Iterator<CodegenProperty> iterator = codegenProperties.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
CodegenProperty codegenProperty = iterator.next();
|
||||
if (codegenProperty.isEnum && codegenProperty.equals(parentModelCodegenPropery)) {
|
||||
// We found an enum in the child class that is
|
||||
// a duplicate of the one in the parent, so remove it.
|
||||
iterator.remove();
|
||||
removedChildEnum = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (removedChildEnum) {
|
||||
// If we removed an entry from this model's vars, we need to ensure hasMore is updated
|
||||
int count = 0, numVars = codegenProperties.size();
|
||||
for (CodegenProperty codegenProperty : codegenProperties) {
|
||||
count += 1;
|
||||
codegenProperty.hasMore = (count < numVars) ? true : false;
|
||||
}
|
||||
codegenModel.vars = codegenProperties;
|
||||
}
|
||||
return codegenModel;
|
||||
}
|
||||
|
||||
private static String sanitizePackageName(String packageName) {
|
||||
packageName = packageName.trim(); // FIXME: a parameter should not be assigned. Also declare the methods parameters as 'final'.
|
||||
packageName = packageName.replaceAll("[^a-zA-Z0-9_\\.]", "_");
|
||||
if (Strings.isNullOrEmpty(packageName)) {
|
||||
return "invalidPackageName";
|
||||
}
|
||||
return packageName;
|
||||
}
|
||||
|
||||
|
||||
public void setSerializableModel(Boolean serializableModel) {
|
||||
this.serializableModel = serializableModel;
|
||||
}
|
||||
|
||||
private String sanitizePath(String p) {
|
||||
//prefer replace a ", instead of a fuLL URL encode for readability
|
||||
return p.replaceAll("\"", "%22");
|
||||
}
|
||||
|
||||
public String toRegularExpression(String pattern) {
|
||||
return escapeText(pattern);
|
||||
}
|
||||
|
||||
public boolean convertPropertyToBoolean(String propertyKey) {
|
||||
boolean booleanValue = false;
|
||||
if (additionalProperties.containsKey(propertyKey)) {
|
||||
booleanValue = Boolean.valueOf(additionalProperties.get(propertyKey).toString());
|
||||
}
|
||||
|
||||
return booleanValue;
|
||||
}
|
||||
|
||||
public void writePropertyBack(String propertyKey, boolean value) {
|
||||
additionalProperties.put(propertyKey, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String sanitizeTag(String tag) {
|
||||
return camelize(sanitizeName(tag));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toModelTestFilename(String name) {
|
||||
return toModelName(name) + "Test";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -17,39 +17,19 @@
|
||||
|
||||
package org.openapitools.codegen.languages;
|
||||
|
||||
import io.swagger.v3.oas.models.OpenAPI;
|
||||
import io.swagger.v3.oas.models.Operation;
|
||||
import io.swagger.v3.oas.models.info.Info;
|
||||
import io.swagger.v3.oas.models.media.ArraySchema;
|
||||
import io.swagger.v3.oas.models.media.BooleanSchema;
|
||||
import io.swagger.v3.oas.models.media.ByteArraySchema;
|
||||
import io.swagger.v3.oas.models.media.EmailSchema;
|
||||
import io.swagger.v3.oas.models.media.FileSchema;
|
||||
import io.swagger.v3.oas.models.media.PasswordSchema;
|
||||
import io.swagger.v3.oas.models.media.Schema;
|
||||
import io.swagger.v3.oas.models.responses.ApiResponse;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.openapitools.codegen.CliOption;
|
||||
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.media.*;
|
||||
import io.swagger.v3.oas.models.info.*;
|
||||
import io.swagger.v3.oas.models.OpenAPI;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
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.*;
|
||||
|
||||
public class ApexClientCodegen extends AbstractJavaCodegen {
|
||||
public class ApexClientCodegen extends AbstractApexCodegen {
|
||||
|
||||
private static final String CLASS_PREFIX = "classPrefix";
|
||||
private static final String API_VERSION = "apiVersion";
|
||||
@@ -57,25 +37,23 @@ public class ApexClientCodegen extends AbstractJavaCodegen {
|
||||
private static final String NAMED_CREDENTIAL = "namedCredential";
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(ApexClientCodegen.class);
|
||||
private String classPrefix = "Swag";
|
||||
private String apiVersion = "39.0";
|
||||
private String apiVersion = "42.0";
|
||||
private String buildMethod = "sfdx";
|
||||
private String namedCredential = classPrefix;
|
||||
private String srcPath = "force-app/main/default/";
|
||||
private String sfdxConfigPath = "config/";
|
||||
private HashMap<String, Object> primitiveDefaults = new HashMap<String, Object>();
|
||||
|
||||
public ApexClientCodegen() {
|
||||
super();
|
||||
|
||||
importMapping.clear();
|
||||
|
||||
testFolder = sourceFolder = srcPath;
|
||||
|
||||
embeddedTemplateDir = templateDir = "apex";
|
||||
outputFolder = "generated-code" + File.separator + "apex";
|
||||
apiPackage = "classes";
|
||||
modelPackage = "classes";
|
||||
modelPackage = apiPackage = srcPath + "classes";
|
||||
testPackage = "force-app.main.default.classes";
|
||||
modelNamePrefix = classPrefix;
|
||||
dateLibrary = "";
|
||||
|
||||
apiTemplateFiles.put("api.mustache", ".cls");
|
||||
apiTemplateFiles.put("cls-meta.mustache", ".cls-meta.xml");
|
||||
@@ -109,14 +87,15 @@ public class ApexClientCodegen extends AbstractJavaCodegen {
|
||||
typeMapping.put("short", "Integer");
|
||||
typeMapping.put("UUID", "String");
|
||||
|
||||
// https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_reserved_words.htm
|
||||
setReservedWordsLowerCase(
|
||||
Arrays.asList("abstract", "activate", "and", "any", "array", "as", "asc", "autonomous",
|
||||
"begin", "bigdecimal", "blob", "break", "bulk", "by", "byte", "case", "cast",
|
||||
"catch", "char", "class", "collect", "commit", "const", "continue",
|
||||
"convertcurrency", "date", "decimal", "default", "delete", "desc", "do", "else",
|
||||
"convertcurrency", "currency", "date", "datetime", "decimal", "default", "delete", "desc", "do", "else",
|
||||
"end", "enum", "exception", "exit", "export", "extends", "false", "final",
|
||||
"finally", "float", "for", "from", "future", "global", "goto", "group", "having",
|
||||
"hint", "if", "implements", "import", "inner", "insert", "instanceof", "int",
|
||||
"hint", "if", "implements", "import", "in", "inner", "insert", "instanceof", "int",
|
||||
"interface", "into", "join", "last_90_days", "last_month", "last_n_days",
|
||||
"last_week", "like", "limit", "list", "long", "loop", "map", "merge", "new",
|
||||
"next_90_days", "next_month", "next_n_days", "next_week", "not", "null", "nulls",
|
||||
@@ -124,7 +103,7 @@ public class ApexClientCodegen extends AbstractJavaCodegen {
|
||||
"pragma", "private", "protected", "public", "retrieve", "return", "returning",
|
||||
"rollback", "savepoint", "search", "select", "set", "short", "sort", "stat",
|
||||
"static", "super", "switch", "synchronized", "system", "testmethod", "then", "this",
|
||||
"this_month", "this_week", "throw", "today", "tolabel", "tomorrow", "transaction",
|
||||
"this_month", "this_week", "throw", "time", "today", "tolabel", "tomorrow", "transaction",
|
||||
"trigger", "true", "try", "type", "undelete", "update", "upsert", "using",
|
||||
"virtual", "webservice", "when", "where", "while", "yesterday"
|
||||
));
|
||||
@@ -133,6 +112,17 @@ public class ApexClientCodegen extends AbstractJavaCodegen {
|
||||
Arrays.asList("Blob", "Boolean", "Date", "Datetime", "Decimal", "Double", "ID",
|
||||
"Integer", "Long", "Object", "String", "Time"
|
||||
));
|
||||
|
||||
primitiveDefaults.put("Boolean", true);
|
||||
primitiveDefaults.put("Decimal", 1);
|
||||
primitiveDefaults.put("Double", 1);
|
||||
primitiveDefaults.put("Integer", 1);
|
||||
primitiveDefaults.put("Long", 1);
|
||||
primitiveDefaults.put("String", "");
|
||||
|
||||
instantiationTypes.put("array", "List");
|
||||
instantiationTypes.put("map", "Map");
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -162,6 +152,48 @@ public class ApexClientCodegen extends AbstractJavaCodegen {
|
||||
postProcessOpts();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preprocessOpenAPI(OpenAPI openAPI) {
|
||||
Info info = openAPI.getInfo();
|
||||
String calloutLabel = info.getTitle();
|
||||
additionalProperties.put("calloutLabel", calloutLabel);
|
||||
String sanitized = sanitizeName(calloutLabel);
|
||||
additionalProperties.put("calloutName", sanitized);
|
||||
supportingFiles.add(new SupportingFile("namedCredential.mustache", srcPath + "/namedCredentials",
|
||||
sanitized + ".namedCredential-meta.xml"
|
||||
));
|
||||
|
||||
if (additionalProperties.get(BUILD_METHOD).equals("sfdx")) {
|
||||
generateSfdxSupportingFiles();
|
||||
} else if (additionalProperties.get(BUILD_METHOD).equals("ant")) {
|
||||
generateAntSupportingFiles();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String escapeQuotationMark(String input) {
|
||||
return input.replace("'", "\\'");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String escapeUnsafeCharacters(String input) {
|
||||
return input.replace("*/", "*_/").replace("/*", "/_*");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String escapeText(String input) {
|
||||
if (input == null) {
|
||||
return input;
|
||||
}
|
||||
|
||||
return input.replace("'", "\\'").replace("\n", "\\n").replace("\r", "\\r").replace("*/", "*_/").replace("/*", "/_*");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toApiName(String name) {
|
||||
return camelize(classPrefix + super.toApiName(name));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String escapeReservedWord(String name) {
|
||||
// Identifiers must start with a letter
|
||||
@@ -191,16 +223,19 @@ public class ApexClientCodegen extends AbstractJavaCodegen {
|
||||
} else if (ModelUtils.isBooleanSchema(p)) {
|
||||
// true => "true", false => "false", null => "null"
|
||||
out = String.valueOf(((BooleanSchema) p).getDefault());
|
||||
} else if (ModelUtils.isLongSchema(p)) { // long
|
||||
out = p.getDefault() == null ? out : p.getDefault().toString() + "L";
|
||||
} else if (ModelUtils.isLongSchema(p)) {
|
||||
Long def = (Long) p.getDefault();
|
||||
out = def == null ? out : def.toString() + "L";
|
||||
} else if (ModelUtils.isMapSchema(p)) {
|
||||
Schema inner = (Schema) p.getAdditionalProperties();
|
||||
String s = inner == null ? "Object" : getTypeDeclaration(inner);
|
||||
out = String.format("new Map<String, %s>()", s);
|
||||
} else if (ModelUtils.isStringSchema(p)) {
|
||||
String def = (String) p.getDefault();
|
||||
if (def != null) {
|
||||
out = p.getEnum() == null ? String.format("'%s'", escapeText(def)) : def;
|
||||
if (p.getDefault() != null) {
|
||||
String def = p.getDefault().toString();
|
||||
if (def != null) {
|
||||
out = p.getEnum() == null ? String.format("'%s'", escapeText(def)) : def;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
out = super.toDefaultValue(p);
|
||||
@@ -210,256 +245,12 @@ public class ApexClientCodegen extends AbstractJavaCodegen {
|
||||
return "null".equals(out) ? null : out;
|
||||
}
|
||||
|
||||
@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 (Boolean.TRUE.equals(p.isInteger)) {
|
||||
if (example == null) {
|
||||
example = "56";
|
||||
}
|
||||
} else if (Boolean.TRUE.equals(p.isLong)) {
|
||||
if (example == null) {
|
||||
example = "2147483648L";
|
||||
}
|
||||
} else if (Boolean.TRUE.equals(p.isDouble)
|
||||
|| Boolean.TRUE.equals(p.isFloat)
|
||||
|| Boolean.TRUE.equals(p.isNumber)) {
|
||||
if (example == null) {
|
||||
example = "3.4";
|
||||
}
|
||||
} 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.isFile) || Boolean.TRUE.equals(p.isBinary)) {
|
||||
example = "Blob.valueOf('Sample text file\\nContents')";
|
||||
} else if (Boolean.TRUE.equals(p.isByteArray)) {
|
||||
if (example == null) {
|
||||
example = "YmFzZSA2NCBkYXRh";
|
||||
}
|
||||
example = "\"" + escapeText(example) + "\"";
|
||||
} else if (Boolean.TRUE.equals(p.isDate)) {
|
||||
if (example == null) {
|
||||
example = "1960, 2, 17";
|
||||
}
|
||||
example = "Date.newInstance(" + escapeText(p.example) + ")";
|
||||
} else if (Boolean.TRUE.equals(p.isDateTime)) {
|
||||
if (example == null) {
|
||||
example = "2013, 11, 12, 3, 3, 3";
|
||||
}
|
||||
example = "Datetime.newInstanceGmt(" + escapeText(p.example) + ")";
|
||||
} else if (Boolean.TRUE.equals(p.isString)) {
|
||||
if (example == null) {
|
||||
example = p.paramName + "_example";
|
||||
}
|
||||
example = "\'" + escapeText(example) + "\'";
|
||||
|
||||
} else if (!languageSpecificPrimitives.contains(type)) {
|
||||
// type is a model class, e.g. User
|
||||
example = type + ".getExample()";
|
||||
}
|
||||
|
||||
// container
|
||||
if (Boolean.TRUE.equals(p.isListContainer)) {
|
||||
example = setPropertyExampleValue(p.items);
|
||||
example = "new " + p.dataType + "{" + example + "}";
|
||||
} else if (Boolean.TRUE.equals(p.isMapContainer)) {
|
||||
example = setPropertyExampleValue(p.items);
|
||||
example = "new " + p.dataType + "{" + example + "}";
|
||||
} else if (example == null) {
|
||||
example = "null";
|
||||
}
|
||||
|
||||
p.example = example;
|
||||
}
|
||||
|
||||
protected String setPropertyExampleValue(CodegenProperty p) {
|
||||
String example;
|
||||
|
||||
if (p == null) {
|
||||
return "null";
|
||||
}
|
||||
|
||||
if (p.defaultValue == null) {
|
||||
example = p.example;
|
||||
} else {
|
||||
example = p.defaultValue;
|
||||
}
|
||||
|
||||
String type = p.baseType;
|
||||
if (type == null) {
|
||||
type = p.dataType;
|
||||
}
|
||||
|
||||
if (Boolean.TRUE.equals(p.isInteger)) {
|
||||
if (example == null) {
|
||||
example = "56";
|
||||
}
|
||||
} else if (Boolean.TRUE.equals(p.isLong)) {
|
||||
if (example == null) {
|
||||
example = "2147483648L";
|
||||
}
|
||||
} else if (Boolean.TRUE.equals(p.isDouble)
|
||||
|| Boolean.TRUE.equals(p.isFloat)
|
||||
|| Boolean.TRUE.equals(p.isNumber)) {
|
||||
if (example == null) {
|
||||
example = "3.4";
|
||||
}
|
||||
} else if (Boolean.TRUE.equals(p.isBoolean)) {
|
||||
if (example == null) {
|
||||
example = "true";
|
||||
}
|
||||
} else if (Boolean.TRUE.equals(p.isFile) || Boolean.TRUE.equals(p.isBinary)) {
|
||||
if (example == null) {
|
||||
example = "Blob.valueOf('Sample text file\\nContents')";
|
||||
}
|
||||
example = escapeText(example);
|
||||
} else if (Boolean.TRUE.equals(p.isDate)) {
|
||||
if (example == null) {
|
||||
example = "1960, 2, 17";
|
||||
}
|
||||
example = "Date.newInstance(" + escapeText(p.example) + ")";
|
||||
} else if (Boolean.TRUE.equals(p.isDateTime)) {
|
||||
if (example == null) {
|
||||
example = "2013, 11, 12, 3, 3, 3";
|
||||
}
|
||||
example = "Datetime.newInstanceGmt(" + escapeText(p.example) + ")";
|
||||
} else if (Boolean.TRUE.equals(p.isString)) {
|
||||
if (example == null) {
|
||||
example = p.name + "_example";
|
||||
}
|
||||
example = "\'" + escapeText(example) + "\'";
|
||||
|
||||
} else if (!languageSpecificPrimitives.contains(type)) {
|
||||
// type is a model class, e.g. User
|
||||
example = type + ".getExample()";
|
||||
}
|
||||
|
||||
return example;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CodegenModel fromModel(String name, Schema model, Map<String, Schema> allDefinitions) {
|
||||
CodegenModel cm = super.fromModel(name, model, allDefinitions);
|
||||
if (cm.interfaces == null) {
|
||||
cm.interfaces = new ArrayList<String>();
|
||||
}
|
||||
|
||||
Boolean hasDefaultValues = false;
|
||||
|
||||
// for (de)serializing properties renamed for Apex (e.g. reserved words)
|
||||
List<Map<String, String>> propertyMappings = new ArrayList<>();
|
||||
for (CodegenProperty p : cm.allVars) {
|
||||
hasDefaultValues |= p.defaultValue != null;
|
||||
if (!p.baseName.equals(p.name)) {
|
||||
Map<String, String> mapping = new HashMap<>();
|
||||
mapping.put("externalName", p.baseName);
|
||||
mapping.put("internalName", p.name);
|
||||
propertyMappings.add(mapping);
|
||||
}
|
||||
}
|
||||
|
||||
cm.vendorExtensions.put("hasPropertyMappings", !propertyMappings.isEmpty());
|
||||
cm.vendorExtensions.put("hasDefaultValues", hasDefaultValues);
|
||||
cm.vendorExtensions.put("propertyMappings", propertyMappings);
|
||||
|
||||
if (!propertyMappings.isEmpty()) {
|
||||
cm.interfaces.add("Swagger.MappedProperties");
|
||||
}
|
||||
return cm;
|
||||
}
|
||||
|
||||
/* the following workaround is no longer needed
|
||||
@Override
|
||||
public void postProcessParameter(CodegenParameter parameter) {
|
||||
if (parameter.isBodyParam && parameter.isListContainer) {
|
||||
// items of array bodyParams are being nested an extra level too deep for some reason
|
||||
parameter.items = parameter.items.items;
|
||||
setParameterExampleValue(parameter);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
@Override
|
||||
public void preprocessOpenAPI(OpenAPI openAPI) {
|
||||
Info info = openAPI.getInfo();
|
||||
String calloutLabel = info.getTitle();
|
||||
additionalProperties.put("calloutLabel", calloutLabel);
|
||||
String sanitized = sanitizeName(calloutLabel);
|
||||
additionalProperties.put("calloutName", sanitized);
|
||||
supportingFiles.add(new SupportingFile("namedCredential.mustache", srcPath + "/namedCredentials",
|
||||
sanitized + ".namedCredential"
|
||||
));
|
||||
|
||||
if (additionalProperties.get(BUILD_METHOD).equals("sfdx")) {
|
||||
generateSfdxSupportingFiles();
|
||||
} else if (additionalProperties.get(BUILD_METHOD).equals("ant")) {
|
||||
generateAntSupportingFiles();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public CodegenOperation fromOperation(String path,
|
||||
String httpMethod,
|
||||
Operation operation,
|
||||
Map<String, Schema> definitions,
|
||||
OpenAPI openAPI) {
|
||||
Boolean hasFormParams = false;
|
||||
// comment out the following as there's no consume/produce in OAS3.0
|
||||
// we can move the logic below to postProcessOperations if needed
|
||||
/*
|
||||
// only support serialization into JSON and urlencoded forms for now
|
||||
operation.setConsumes(
|
||||
Collections.singletonList(hasFormParameter(operation)
|
||||
? "application/x-www-form-urlencoded"
|
||||
: "application/json"));
|
||||
|
||||
// only support deserialization from JSON for now
|
||||
operation.setProduces(Collections.singletonList("application/json"));
|
||||
*/
|
||||
|
||||
CodegenOperation op = super.fromOperation(path, httpMethod, operation, definitions, openAPI);
|
||||
|
||||
if (op.getHasExamples()) {
|
||||
// prepare examples for Apex test classes
|
||||
ApiResponse responseProperty = findMethodResponse(operation.getResponses());
|
||||
String deserializedExample = toExampleValue(ModelUtils.getSchemaFromResponse(responseProperty));
|
||||
for (Map<String, String> example : op.examples) {
|
||||
example.put("example", escapeText(example.get("example")));
|
||||
example.put("deserializedExample", deserializedExample);
|
||||
}
|
||||
}
|
||||
|
||||
return op;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String escapeQuotationMark(String input) {
|
||||
return input.replace("'", "\\'");
|
||||
}
|
||||
|
||||
public void setBuildMethod(String buildMethod) {
|
||||
if (buildMethod.equals("ant")) {
|
||||
this.srcPath = "deploy/";
|
||||
} else {
|
||||
this.srcPath = "src/";
|
||||
}
|
||||
testFolder = sourceFolder = srcPath;
|
||||
this.buildMethod = buildMethod;
|
||||
}
|
||||
|
||||
@@ -494,114 +285,6 @@ public class ApexClientCodegen extends AbstractJavaCodegen {
|
||||
));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String escapeText(String input) {
|
||||
if (input == null) {
|
||||
return input;
|
||||
}
|
||||
|
||||
return input.replace("'", "\\'").replace("\n", "\\n").replace("\r", "\\r");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toModelTestFilename(String name) {
|
||||
return toModelName(name) + "Test";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toExampleValue(Schema p) {
|
||||
if (p == null) {
|
||||
return "";
|
||||
}
|
||||
Object obj = p.getExample();
|
||||
String example = obj == null ? "" : obj.toString();
|
||||
if (ModelUtils.isArraySchema(p)) { // array
|
||||
example = "new " + getTypeDeclaration(p) + "{" + toExampleValue(
|
||||
((ArraySchema) p).getItems()) + "}";
|
||||
} else if (ModelUtils.isBooleanSchema(p)) {
|
||||
example = String.valueOf(!"false".equals(example));
|
||||
} else if (ModelUtils.isByteArraySchema(p)) { // byte array
|
||||
if (example.isEmpty()) {
|
||||
example = "VGhlIHF1aWNrIGJyb3duIGZveCBqdW1wZWQgb3ZlciB0aGUgbGF6eSBkb2cu";
|
||||
}
|
||||
((ByteArraySchema) p).setExample(example);
|
||||
example = "EncodingUtil.base64Decode('" + example + "')";
|
||||
} else if (ModelUtils.isDateSchema(p)) { // date
|
||||
if (example.matches("^\\d{4}(-\\d{2}){2}")) {
|
||||
example = example.substring(0, 10).replaceAll("-0?", ", ");
|
||||
} else if (example.isEmpty()) {
|
||||
example = "2000, 1, 23";
|
||||
} else {
|
||||
LOGGER.warn(String.format("The example provided for property '%s' is not a valid RFC3339 date. Defaulting to '2000-01-23'. [%s]", p
|
||||
.getName(), example));
|
||||
example = "2000, 1, 23";
|
||||
}
|
||||
example = "Date.newInstance(" + example + ")";
|
||||
} else if (ModelUtils.isDateTimeSchema(p)) { // datetime
|
||||
if (example.matches("^\\d{4}([-T:]\\d{2}){5}.+")) {
|
||||
example = example.substring(0, 19).replaceAll("[-T:]0?", ", ");
|
||||
} else if (example.isEmpty()) {
|
||||
example = "2000, 1, 23, 4, 56, 7";
|
||||
} else {
|
||||
LOGGER.warn(String.format("The example provided for property '%s' is not a valid RFC3339 datetime. Defaulting to '2000-01-23T04-56-07Z'. [%s]", p
|
||||
.getName(), example));
|
||||
example = "2000, 1, 23, 4, 56, 7";
|
||||
}
|
||||
example = "Datetime.newInstanceGmt(" + example + ")";
|
||||
} else if (ModelUtils.isNumberSchema(p)) { // number
|
||||
example = example.replaceAll("[^-0-9.]", "");
|
||||
example = example.isEmpty() ? "1.3579" : example;
|
||||
} else if (ModelUtils.isFileSchema(p)) { // file
|
||||
if (example.isEmpty()) {
|
||||
example = "VGhlIHF1aWNrIGJyb3duIGZveCBqdW1wZWQgb3ZlciB0aGUgbGF6eSBkb2cu";
|
||||
((FileSchema) p).setExample(example);
|
||||
}
|
||||
example = "EncodingUtil.base64Decode(" + example + ")";
|
||||
} else if (ModelUtils.isEmailSchema(p)) { // email
|
||||
if (example.isEmpty()) {
|
||||
example = "example@example.com";
|
||||
((EmailSchema) p).setExample(example);
|
||||
}
|
||||
example = "'" + example + "'";
|
||||
} else if (ModelUtils.isLongSchema(p)) { // long
|
||||
example = example.isEmpty() ? "123456789L" : example + "L";
|
||||
} else if (ModelUtils.isMapSchema(p)) { // map
|
||||
example = "new " + getTypeDeclaration(p) + "{'key'=>" + toExampleValue(
|
||||
(Schema) p.getAdditionalProperties()) + "}";
|
||||
} else if (ModelUtils.isObjectSchema(p)) { // object
|
||||
example = example.isEmpty() ? "null" : example;
|
||||
} else if (ModelUtils.isPasswordSchema(p)) { // password
|
||||
example = example.isEmpty() ? "password123" : escapeText(example);
|
||||
((PasswordSchema) p).setExample(example);
|
||||
example = "'" + example + "'";
|
||||
} else if (!StringUtils.isEmpty(p.get$ref())) {
|
||||
example = getTypeDeclaration(p) + ".getExample()";
|
||||
} else if (ModelUtils.isUUIDSchema(p)) {
|
||||
example = example.isEmpty()
|
||||
? "'046b6c7f-0b8a-43b9-b35d-6489e6daee91'"
|
||||
: "'" + escapeText(example) + "'";
|
||||
} else if (ModelUtils.isStringSchema(p)) { // string
|
||||
List<String> enums = p.getEnum();
|
||||
if (enums != null && example.isEmpty()) {
|
||||
example = enums.get(0);
|
||||
p.setExample(example);
|
||||
} else if (example.isEmpty()) {
|
||||
example = "aeiou";
|
||||
} else {
|
||||
example = escapeText(example);
|
||||
p.setExample(example);
|
||||
}
|
||||
example = "'" + example + "'";
|
||||
}
|
||||
|
||||
return example;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toApiName(String name) {
|
||||
return camelize(classPrefix + super.toApiName(name));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateCodegenPropertyEnum(CodegenProperty var) {
|
||||
super.updateCodegenPropertyEnum(var);
|
||||
@@ -612,21 +295,6 @@ public class ApexClientCodegen extends AbstractJavaCodegen {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public CodegenType getTag() {
|
||||
return CodegenType.CLIENT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "apex";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHelp() {
|
||||
return "Generates an Apex API client library (beta).";
|
||||
}
|
||||
|
||||
private void generateAntSupportingFiles() {
|
||||
|
||||
supportingFiles.add(new SupportingFile("package.mustache", "deploy", "package.xml"));
|
||||
@@ -638,11 +306,17 @@ public class ApexClientCodegen extends AbstractJavaCodegen {
|
||||
supportingFiles.add(new SupportingFile("gitignore.mustache", "", ".gitignore"));
|
||||
|
||||
writeOptional(outputFolder, new SupportingFile("README_ant.mustache", "README.md"));
|
||||
|
||||
}
|
||||
|
||||
private void generateSfdxSupportingFiles() {
|
||||
supportingFiles.add(new SupportingFile("sfdx.mustache", "", "sfdx-oss-manifest.json"));
|
||||
|
||||
supportingFiles.add(new SupportingFile("sfdx-project-scratch-def.json", sfdxConfigPath, "project-scratch-def.json"));
|
||||
supportingFiles.add(new SupportingFile("sfdx-project.json.mustache", "sfdx-project.json"));
|
||||
|
||||
writeOptional(outputFolder, new SupportingFile("README_sfdx.mustache", "README.md"));
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user