diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractApexCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractApexCodegen.java new file mode 100644 index 00000000000..20f5c7b0a47 --- /dev/null +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractApexCodegen.java @@ -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) + ""; + } + 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 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 allDefinitions) { + CodegenModel cm = super.fromModel(name, model, allDefinitions); + + // TODO Check enum model handling + if (cm.interfaces == null) { + cm.interfaces = new ArrayList(); + } + + Boolean hasDefaultValues = false; + + // for (de)serializing properties renamed for Apex (e.g. reserved words) + List> propertyMappings = new ArrayList<>(); + for (CodegenProperty p : cm.allVars) { + hasDefaultValues |= p.defaultValue != null; + if (!p.baseName.equals(p.name)) { + Map 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 postProcessModels(Map 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 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 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 parentModelCodegenProperties = parentCodegenModel.vars; + List 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 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"; + } + +} diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/ApexClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/ApexClientCodegen.java index d1242c95831..80a240cc3cb 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/ApexClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/ApexClientCodegen.java @@ -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 primitiveDefaults = new HashMap(); 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()", 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 allDefinitions) { - CodegenModel cm = super.fromModel(name, model, allDefinitions); - if (cm.interfaces == null) { - cm.interfaces = new ArrayList(); - } - - Boolean hasDefaultValues = false; - - // for (de)serializing properties renamed for Apex (e.g. reserved words) - List> propertyMappings = new ArrayList<>(); - for (CodegenProperty p : cm.allVars) { - hasDefaultValues |= p.defaultValue != null; - if (!p.baseName.equals(p.name)) { - Map 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 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 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 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")); + } + } diff --git a/modules/openapi-generator/src/main/resources/apex/README_sfdx.mustache b/modules/openapi-generator/src/main/resources/apex/README_sfdx.mustache index 50f428b5128..c65a0d10b77 100644 --- a/modules/openapi-generator/src/main/resources/apex/README_sfdx.mustache +++ b/modules/openapi-generator/src/main/resources/apex/README_sfdx.mustache @@ -100,7 +100,7 @@ Class | Method | HTTP request | Description {{/isBasic}} {{#isOAuth}}- **Type**: OAuth - **Flow**: {{flow}} -- **Authorizatoin URL**: {{authorizationUrl}} +- **Authorization URL**: {{authorizationUrl}} - **Scopes**: {{^scopes}}N/A{{/scopes}} {{#scopes}} - {{scope}}: {{description}} {{/scopes}} diff --git a/modules/openapi-generator/src/main/resources/apex/Swagger.cls b/modules/openapi-generator/src/main/resources/apex/Swagger.cls index 172c3038111..bb4e44f7971 100644 --- a/modules/openapi-generator/src/main/resources/apex/Swagger.cls +++ b/modules/openapi-generator/src/main/resources/apex/Swagger.cls @@ -271,9 +271,7 @@ public class Swagger { @TestVisible protected virtual void applyAuthentication(List names, Map headers, List query) { - for (Authentication auth : getAuthMethods(names)) { - auth.apply(headers, query); - } + // TODO Check auth methods } @TestVisible @@ -298,7 +296,7 @@ public class Swagger { protected virtual String toEndpoint(String path, Map params, List queryParams) { String query = '?' + paramsToString(queryParams); - return '"callout:' + calloutName + toPath(path, params) + query.removeEnd('?') + '""'; + return 'callout:' + calloutName + toPath(path, params) + query.removeEnd('?'); } @TestVisible diff --git a/modules/openapi-generator/src/main/resources/apex/SwaggerTest.cls b/modules/openapi-generator/src/main/resources/apex/SwaggerTest.cls index e3cec8831c6..d95e9b60aa8 100644 --- a/modules/openapi-generator/src/main/resources/apex/SwaggerTest.cls +++ b/modules/openapi-generator/src/main/resources/apex/SwaggerTest.cls @@ -292,7 +292,7 @@ private class SwaggerTest { new Swagger.Param('foo', 'bar'), new Swagger.Param('bat', '123') }; - String expected = 'https://www.mccombs.utexas.edu/departments/finance?foo=bar&bat=123'; + String expected = 'callout:Winkelmeyer/departments/finance?foo=bar&bat=123'; String actual = client.toEndpoint(path, params, queryParams); System.assertEquals(expected, actual); } @@ -360,7 +360,8 @@ private class SwaggerTest { private class MockApiClient extends Swagger.ApiClient { public MockApiClient() { - basePath = 'https://www.mccombs.utexas.edu'; + basePath = 'https://blog.winkelmeyer.com'; + calloutName = 'Winkelmeyer'; } } } \ No newline at end of file diff --git a/modules/openapi-generator/src/main/resources/apex/api.mustache b/modules/openapi-generator/src/main/resources/apex/api.mustache index ebbef7283f6..700c66eb15c 100644 --- a/modules/openapi-generator/src/main/resources/apex/api.mustache +++ b/modules/openapi-generator/src/main/resources/apex/api.mustache @@ -88,13 +88,13 @@ public class {{classname}} { {{/headerParams}} }{{/hasHeaderParams}}{{^hasHeaderParams}}(){{/hasHeaderParams}}, {{#hasProduces}} - new List{ {{#produces}}'{{{mediaType}}}'{{#hasMore}}, {{/hasMore}}{{/produces}} }, + new List{ {{#produces}}'{{mediaType}}'{{#hasMore}}, {{/hasMore}}{{/produces}} }, {{/hasProduces}} {{^hasProduces}} new List(), {{/hasProduces}} {{#hasConsumes}} - new List{ {{#consumes}}'{{{mediaType}}}'{{#hasMore}}, {{/hasMore}}{{/consumes}} }, + new List{ {{#consumes}}'{{mediaType}}'{{#hasMore}}, {{/hasMore}}{{/consumes}} }, {{/hasConsumes}} {{^hasConsumes}} new List(), diff --git a/modules/openapi-generator/src/main/resources/apex/api_test.mustache b/modules/openapi-generator/src/main/resources/apex/api_test.mustache index f7a3cf0a63f..c5db4898998 100644 --- a/modules/openapi-generator/src/main/resources/apex/api_test.mustache +++ b/modules/openapi-generator/src/main/resources/apex/api_test.mustache @@ -34,18 +34,19 @@ private class {{classname}}Test { {{{returnType}}} response; {{{returnType}}} expectedResponse; {{/returnType}} + String js = ''; {{#authMethods}} client = new {{classPrefix}}Client(); api = new {{classname}}(client);{{#isApiKey}} - ((Swagger.ApiKeyAuth){{/isApiKey}} client.getAuthentication('{{name}}'); - {{#isApiKey}} - client.setApiKey('foo-bar-api-key'); + ((Swagger.ApiKeyAuth)client.getAuthentication('{{name}}')).setApiKey('foo-bar-api-key'); {{/isApiKey}} {{#examples}} + + js = JSON.serialize({{{deserializedExample}}}); res.setHeader('Content-Type', '{{contentType}}'); - res.setBody('{{{example}}}'); + res.setBody(js); expectedResponse = {{{deserializedExample}}}; response = ({{{returnType}}}) api.{{operationId}}({{#hasParams}}params{{/hasParams}}); System.assertEquals(expectedResponse, response); @@ -59,8 +60,9 @@ private class {{classname}}Test { api = new {{classname}}(new {{classPrefix}}Client()); {{#examples}} + js = JSON.serialize({{{deserializedExample}}}); res.setHeader('Content-Type', '{{contentType}}'); - res.setBody('{{{example}}}'); + res.setBody(js); expectedResponse = {{{deserializedExample}}}; response = ({{{returnType}}}) api.{{operationId}}({{#hasParams}}params{{/hasParams}}); System.assertEquals(expectedResponse, response); diff --git a/modules/openapi-generator/src/main/resources/apex/git_push.sh.mustache b/modules/openapi-generator/src/main/resources/apex/git_push.sh.mustache index 8a32e53995d..e153ce23ecf 100644 --- a/modules/openapi-generator/src/main/resources/apex/git_push.sh.mustache +++ b/modules/openapi-generator/src/main/resources/apex/git_push.sh.mustache @@ -1,7 +1,7 @@ #!/bin/sh # ref: https://help.github.com/articles/adding-an-existing-project-to-github-using-the-command-line/ # -# Usage example: /bin/sh ./git_push.sh wing328 openapi-pestore-perl "minor update" +# Usage example: /bin/sh ./git_push.sh wing328 swagger-petstore-perl "minor update" git_user_id=$1 git_repo_id=$2 @@ -36,7 +36,7 @@ git_remote=`git remote` if [ "$git_remote" = "" ]; then # git remote not defined if [ "$GIT_TOKEN" = "" ]; then - echo "[INFO] \$GIT_TOKEN (environment variable) is not set. Using the git credential in your environment." + echo "[INFO] \$GIT_TOKEN (environment variable) is not set. Using the git crediential in your environment." git remote add origin https://github.com/${git_user_id}/${git_repo_id}.git else git remote add origin https://${git_user_id}:${GIT_TOKEN}@github.com/${git_user_id}/${git_repo_id}.git diff --git a/modules/openapi-generator/src/main/resources/apex/licenseInfo.mustache b/modules/openapi-generator/src/main/resources/apex/licenseInfo.mustache index 335db1c5938..94c36dda3af 100644 --- a/modules/openapi-generator/src/main/resources/apex/licenseInfo.mustache +++ b/modules/openapi-generator/src/main/resources/apex/licenseInfo.mustache @@ -5,7 +5,7 @@ * {{#version}}OpenAPI spec version: {{{version}}}{{/version}} * {{#infoEmail}}Contact: {{{infoEmail}}}{{/infoEmail}} * - * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - * https://openapi-generator.tech + * NOTE: This class is auto generated by the swagger code generator program. + * https://github.com/swagger-api/swagger-codegen.git * Do not edit the class manually. */ diff --git a/modules/openapi-generator/src/main/resources/apex/model_test.mustache b/modules/openapi-generator/src/main/resources/apex/model_test.mustache index 7b22a41e557..3aef0d65572 100644 --- a/modules/openapi-generator/src/main/resources/apex/model_test.mustache +++ b/modules/openapi-generator/src/main/resources/apex/model_test.mustache @@ -45,15 +45,6 @@ private class {{classname}}Test { System.assert({{classVarName}}4.equals({{classVarName}}3)); } - @isTest - private static void notEqualsUnlikeInstance() { - {{classname}} {{classVarName}}1 = {{classname}}.getExample(); - {{classname}} {{classVarName}}2 = new {{classname}}(); - - System.assertEquals(false, {{classVarName}}1.equals({{classVarName}}2)); - System.assertEquals(false, {{classVarName}}2.equals({{classVarName}}1)); - } - @isTest private static void notEqualsDifferentType() { {{classname}} {{classVarName}}1 = {{classname}}.getExample(); diff --git a/modules/openapi-generator/src/main/resources/apex/package.mustache b/modules/openapi-generator/src/main/resources/apex/package.mustache index e05b18ab7e3..e13680359ba 100644 --- a/modules/openapi-generator/src/main/resources/apex/package.mustache +++ b/modules/openapi-generator/src/main/resources/apex/package.mustache @@ -3,7 +3,7 @@ {{appName}} API Client Client library for calling the {{appName}} API.{{#appDescription}} {{{appDescription}}}{{/appDescription}} -Generated with OpenAPI Generator (https://openapi-generator.tech) +Generated with Swagger Codegen (github.com/swagger-api/swagger-codegen) {{#apiInfo}} {{#apis}} diff --git a/modules/openapi-generator/src/main/resources/apex/pojo.mustache b/modules/openapi-generator/src/main/resources/apex/pojo.mustache index c26649e959d..320b90922d8 100644 --- a/modules/openapi-generator/src/main/resources/apex/pojo.mustache +++ b/modules/openapi-generator/src/main/resources/apex/pojo.mustache @@ -6,13 +6,15 @@ public class {{classname}}{{#parent}} extends {{{parent}}}{{/parent}}{{#interfac {{#isEnum}} {{^isContainer}} {{>modelInnerEnum}} - {{/isContainer}} - {{#isContainer}} - {{#mostInnerItems}} -{{>modelInnerEnum}} - {{/mostInnerItems}} {{/isContainer}} {{/isEnum}} + {{#items.isEnum}} + {{#items}} + {{^isContainer}} +{{>modelInnerEnum}} + {{/isContainer}} + {{/items}} + {{/items.isEnum}} /** {{#description}} * {{{description}}} @@ -58,16 +60,17 @@ public class {{classname}}{{#parent}} extends {{{parent}}}{{/parent}}{{#interfac public static {{classname}} getExample() { {{classname}} {{classVarName}} = new {{classname}}(); {{#vars}} - {{classVarName}}.{{name}} = {{{example}}}; + {{#example}}{{classVarName}}.{{name}} = {{{example}}};{{/example}} {{/vars}} return {{classVarName}}; } public Boolean equals(Object obj) { - if (obj instanceof {{classname}}) { + if (obj instanceof {{classname}}) { {{#hasVars}} {{classname}} {{classVarName}} = ({{classname}}) obj; return {{#vars}}this.{{name}} == {{classVarName}}.{{name}}{{#hasMore}} - && {{/hasMore}}{{/vars}}; + && {{/hasMore}}{{/vars}};{{/hasVars}}{{^hasVars}} + return true;{{/hasVars}} } return false; } diff --git a/modules/openapi-generator/src/main/resources/apex/pojo_doc.mustache b/modules/openapi-generator/src/main/resources/apex/pojo_doc.mustache index 07b73cc6f5f..0e4c0749866 100644 --- a/modules/openapi-generator/src/main/resources/apex/pojo_doc.mustache +++ b/modules/openapi-generator/src/main/resources/apex/pojo_doc.mustache @@ -3,7 +3,7 @@ ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- -{{#vars}}**{{name}}** | {{#isEnum}}[**{{datatypeWithEnum}}**](#{{datatypeWithEnum}}){{/isEnum}}{{^isEnum}}{{#isPrimitiveType}}**{{dataType}}**{{/isPrimitiveType}}{{^isPrimitiveType}}[**{{dataType}}**]({{complexType}}.md){{/isPrimitiveType}}{{/isEnum}} | {{description}} | {{^required}} [optional]{{/required}}{{#readOnly}} [readonly]{{/readOnly}} +{{#vars}}**{{name}}** | {{#isEnum}}[**{{datatypeWithEnum}}**](#{{datatypeWithEnum}}){{/isEnum}}{{^isEnum}}{{#isPrimitiveType}}**{{datatype}}**{{/isPrimitiveType}}{{^isPrimitiveType}}[**{{datatype}}**]({{complexType}}.md){{/isPrimitiveType}}{{/isEnum}} | {{description}} | {{^required}} [optional]{{/required}}{{#readOnly}} [readonly]{{/readOnly}} {{/vars}} {{#vars}}{{#isEnum}} diff --git a/modules/openapi-generator/src/main/resources/apex/sfdx-project-scratch-def.json b/modules/openapi-generator/src/main/resources/apex/sfdx-project-scratch-def.json new file mode 100644 index 00000000000..36aace55266 --- /dev/null +++ b/modules/openapi-generator/src/main/resources/apex/sfdx-project-scratch-def.json @@ -0,0 +1,8 @@ +{ + "orgName": "muenzpraeger - René Winkelmeyer", + "edition": "Developer", + "orgPreferences": { + "enabled": ["S1DesktopEnabled"], + "disabled": ["S1EncryptedStoragePref2"] + } +} diff --git a/modules/openapi-generator/src/main/resources/apex/sfdx-project.json.mustache b/modules/openapi-generator/src/main/resources/apex/sfdx-project.json.mustache new file mode 100644 index 00000000000..08ac49c0cea --- /dev/null +++ b/modules/openapi-generator/src/main/resources/apex/sfdx-project.json.mustache @@ -0,0 +1,11 @@ +{ + "packageDirectories": [ + { + "path": "force-app", + "default": true + } + ], + "namespace": "", + "sfdcLoginUrl": "https://login.salesforce.com", + "sourceApiVersion": "{{apiVersion}}" +} \ No newline at end of file diff --git a/modules/openapi-generator/src/main/resources/apex/sfdx.mustache b/modules/openapi-generator/src/main/resources/apex/sfdx.mustache deleted file mode 100644 index f63e2e36114..00000000000 --- a/modules/openapi-generator/src/main/resources/apex/sfdx.mustache +++ /dev/null @@ -1,10 +0,0 @@ -{ - "sfdxSource": true, - "version": "1.0.0", - "sourceFolder": "src/", - "folders": [ - "src/classes" - ], - "files": [ - ] -} \ No newline at end of file diff --git a/samples/client/petstore/apex/.openapi-generator-ignore b/samples/client/petstore/apex/.openapi-generator-ignore index 7484ee590a3..c5fa491b4c5 100644 --- a/samples/client/petstore/apex/.openapi-generator-ignore +++ b/samples/client/petstore/apex/.openapi-generator-ignore @@ -1,11 +1,11 @@ -# OpenAPI Generator Ignore -# Generated by openapi-generator https://github.com/openapitools/openapi-generator +# Swagger Codegen Ignore +# Generated by swagger-codegen https://github.com/swagger-api/swagger-codegen # Use this file to prevent files from being overwritten by the generator. # The patterns follow closely to .gitignore or .dockerignore. # As an example, the C# client generator defines ApiClient.cs. -# You can make changes and tell OpenAPI Generator to ignore just this file by uncommenting the following line: +# You can make changes and tell Swagger Codgen to ignore just this file by uncommenting the following line: #ApiClient.cs # You can match any string of characters against a directory, file or extension with a single asterisk (*): diff --git a/samples/client/petstore/apex/.openapi-generator/VERSION b/samples/client/petstore/apex/.openapi-generator/VERSION index 096bf47efe3..4395ff59232 100644 --- a/samples/client/petstore/apex/.openapi-generator/VERSION +++ b/samples/client/petstore/apex/.openapi-generator/VERSION @@ -1 +1 @@ -3.0.0-SNAPSHOT \ No newline at end of file +3.2.0-SNAPSHOT \ No newline at end of file diff --git a/samples/client/petstore/apex/.swagger-codegen/VERSION b/samples/client/petstore/apex/.swagger-codegen/VERSION new file mode 100644 index 00000000000..855ff9501eb --- /dev/null +++ b/samples/client/petstore/apex/.swagger-codegen/VERSION @@ -0,0 +1 @@ +2.4.0-SNAPSHOT \ No newline at end of file diff --git a/samples/client/petstore/apex/docs/SwagPetApi.md b/samples/client/petstore/apex/docs/SwagPetApi.md index ad5843ea638..0911fbd0fa8 100644 --- a/samples/client/petstore/apex/docs/SwagPetApi.md +++ b/samples/client/petstore/apex/docs/SwagPetApi.md @@ -16,10 +16,12 @@ Method | HTTP request | Description # **addPet** -> addPet(swagPet) +> addPet(body) Add a new pet to the store + + ### Example ```java SwagPetApi api = new SwagPetApi(); @@ -30,7 +32,7 @@ Swagger.OAuth petstore_auth = (Swagger.OAuth) client.getAuthentication('petstore petstore_auth.setAccessToken('YOUR ACCESS TOKEN'); Map params = new Map{ - 'swagPet' => SwagPet.getExample() + 'body' => SwagPet.getExample() }; try { @@ -45,7 +47,7 @@ try { Name | Type | Description | Notes ------------- | ------------- | ------------- | ------------- - **swagPet** | [**SwagPet**](SwagPet.md)| Pet object that needs to be added to the store | + **body** | [**SwagPet**](Pet.md)| Pet object that needs to be added to the store | ### Return type @@ -57,8 +59,8 @@ null (empty response body) ### HTTP request headers - - **Content-Type**: application/json, application/xml - - **Accept**: Not defined + - **Content-Type**: application/json + - **Accept**: application/json # **deletePet** @@ -66,6 +68,8 @@ null (empty response body) Deletes a pet + + ### Example ```java SwagPetApi api = new SwagPetApi(); @@ -105,8 +109,8 @@ null (empty response body) ### HTTP request headers - - **Content-Type**: Not defined - - **Accept**: Not defined + - **Content-Type**: application/json + - **Accept**: application/json # **findPetsByStatus** @@ -154,8 +158,8 @@ Name | Type | Description | Notes ### HTTP request headers - - **Content-Type**: Not defined - - **Accept**: application/xml, application/json + - **Content-Type**: application/json + - **Accept**: application/json # **findPetsByTags** @@ -175,7 +179,7 @@ Swagger.OAuth petstore_auth = (Swagger.OAuth) client.getAuthentication('petstore petstore_auth.setAccessToken('YOUR ACCESS TOKEN'); Map params = new Map{ - 'tags' => new List{'\'aeiou\''} + 'tags' => new List{'aeiou'} }; try { @@ -203,8 +207,8 @@ Name | Type | Description | Notes ### HTTP request headers - - **Content-Type**: Not defined - - **Accept**: application/xml, application/json + - **Content-Type**: application/json + - **Accept**: application/json # **getPetById** @@ -252,15 +256,17 @@ Name | Type | Description | Notes ### HTTP request headers - - **Content-Type**: Not defined - - **Accept**: application/xml, application/json + - **Content-Type**: application/json + - **Accept**: application/json # **updatePet** -> updatePet(swagPet) +> updatePet(body) Update an existing pet + + ### Example ```java SwagPetApi api = new SwagPetApi(); @@ -271,7 +277,7 @@ Swagger.OAuth petstore_auth = (Swagger.OAuth) client.getAuthentication('petstore petstore_auth.setAccessToken('YOUR ACCESS TOKEN'); Map params = new Map{ - 'swagPet' => SwagPet.getExample() + 'body' => SwagPet.getExample() }; try { @@ -286,7 +292,7 @@ try { Name | Type | Description | Notes ------------- | ------------- | ------------- | ------------- - **swagPet** | [**SwagPet**](SwagPet.md)| Pet object that needs to be added to the store | + **body** | [**SwagPet**](Pet.md)| Pet object that needs to be added to the store | ### Return type @@ -298,8 +304,8 @@ null (empty response body) ### HTTP request headers - - **Content-Type**: application/json, application/xml - - **Accept**: Not defined + - **Content-Type**: application/json + - **Accept**: application/json # **updatePetWithForm** @@ -307,6 +313,8 @@ null (empty response body) Updates a pet in the store with form data + + ### Example ```java SwagPetApi api = new SwagPetApi(); @@ -349,7 +357,7 @@ null (empty response body) ### HTTP request headers - **Content-Type**: application/x-www-form-urlencoded - - **Accept**: Not defined + - **Accept**: application/json # **uploadFile** @@ -357,6 +365,8 @@ null (empty response body) uploads an image + + ### Example ```java SwagPetApi api = new SwagPetApi(); @@ -399,6 +409,6 @@ Name | Type | Description | Notes ### HTTP request headers - - **Content-Type**: multipart/form-data + - **Content-Type**: application/x-www-form-urlencoded - **Accept**: application/json diff --git a/samples/client/petstore/apex/docs/SwagStoreApi.md b/samples/client/petstore/apex/docs/SwagStoreApi.md index de0b614f3d4..c0212e0300f 100644 --- a/samples/client/petstore/apex/docs/SwagStoreApi.md +++ b/samples/client/petstore/apex/docs/SwagStoreApi.md @@ -50,8 +50,8 @@ No authorization required ### HTTP request headers - - **Content-Type**: Not defined - - **Accept**: Not defined + - **Content-Type**: application/json + - **Accept**: application/json # **getInventory** @@ -84,7 +84,7 @@ This endpoint does not need any parameter. ### Return type -**Map<String, Integer>** +[**Map<String, Integer>**](Map.md) ### Authorization @@ -92,7 +92,7 @@ This endpoint does not need any parameter. ### HTTP request headers - - **Content-Type**: Not defined + - **Content-Type**: application/json - **Accept**: application/json @@ -136,21 +136,23 @@ No authorization required ### HTTP request headers - - **Content-Type**: Not defined - - **Accept**: application/xml, application/json + - **Content-Type**: application/json + - **Accept**: application/json # **placeOrder** -> SwagOrder placeOrder(swagOrder) +> SwagOrder placeOrder(body) Place an order for a pet + + ### Example ```java SwagStoreApi api = new SwagStoreApi(); Map params = new Map{ - 'swagOrder' => SwagOrder.getExample() + 'body' => SwagOrder.getExample() }; try { @@ -166,7 +168,7 @@ try { Name | Type | Description | Notes ------------- | ------------- | ------------- | ------------- - **swagOrder** | [**SwagOrder**](SwagOrder.md)| order placed for purchasing the pet | + **body** | [**SwagOrder**](Order.md)| order placed for purchasing the pet | ### Return type @@ -178,6 +180,6 @@ No authorization required ### HTTP request headers - - **Content-Type**: Not defined - - **Accept**: application/xml, application/json + - **Content-Type**: application/json + - **Accept**: application/json diff --git a/samples/client/petstore/apex/docs/SwagUserApi.md b/samples/client/petstore/apex/docs/SwagUserApi.md index 622607d65d2..aa559ddeac2 100644 --- a/samples/client/petstore/apex/docs/SwagUserApi.md +++ b/samples/client/petstore/apex/docs/SwagUserApi.md @@ -16,7 +16,7 @@ Method | HTTP request | Description # **createUser** -> createUser(swagUser) +> createUser(body) Create user @@ -27,7 +27,7 @@ This can only be done by the logged in user. SwagUserApi api = new SwagUserApi(); Map params = new Map{ - 'swagUser' => SwagUser.getExample() + 'body' => SwagUser.getExample() }; try { @@ -42,7 +42,7 @@ try { Name | Type | Description | Notes ------------- | ------------- | ------------- | ------------- - **swagUser** | [**SwagUser**](SwagUser.md)| Created user object | + **body** | [**SwagUser**](User.md)| Created user object | ### Return type @@ -54,21 +54,23 @@ No authorization required ### HTTP request headers - - **Content-Type**: Not defined - - **Accept**: Not defined + - **Content-Type**: application/json + - **Accept**: application/json # **createUsersWithArrayInput** -> createUsersWithArrayInput(swagUser) +> createUsersWithArrayInput(body) Creates list of users with given input array + + ### Example ```java SwagUserApi api = new SwagUserApi(); Map params = new Map{ - 'swagUser' => new List{SwagUser.getExample()} + 'body' => new List{SwagUser.getExample()} }; try { @@ -83,7 +85,7 @@ try { Name | Type | Description | Notes ------------- | ------------- | ------------- | ------------- - **swagUser** | [**List<SwagUser>**](List.md)| List of user object | + **body** | [**List<SwagUser>**](SwagUser.md)| List of user object | ### Return type @@ -95,21 +97,23 @@ No authorization required ### HTTP request headers - - **Content-Type**: Not defined - - **Accept**: Not defined + - **Content-Type**: application/json + - **Accept**: application/json # **createUsersWithListInput** -> createUsersWithListInput(swagUser) +> createUsersWithListInput(body) Creates list of users with given input array + + ### Example ```java SwagUserApi api = new SwagUserApi(); Map params = new Map{ - 'swagUser' => new List{SwagUser.getExample()} + 'body' => new List{SwagUser.getExample()} }; try { @@ -124,7 +128,7 @@ try { Name | Type | Description | Notes ------------- | ------------- | ------------- | ------------- - **swagUser** | [**List<SwagUser>**](List.md)| List of user object | + **body** | [**List<SwagUser>**](SwagUser.md)| List of user object | ### Return type @@ -136,8 +140,8 @@ No authorization required ### HTTP request headers - - **Content-Type**: Not defined - - **Accept**: Not defined + - **Content-Type**: application/json + - **Accept**: application/json # **deleteUser** @@ -179,8 +183,8 @@ No authorization required ### HTTP request headers - - **Content-Type**: Not defined - - **Accept**: Not defined + - **Content-Type**: application/json + - **Accept**: application/json # **getUserByName** @@ -188,6 +192,8 @@ No authorization required Get user by user name + + ### Example ```java SwagUserApi api = new SwagUserApi(); @@ -209,7 +215,7 @@ try { Name | Type | Description | Notes ------------- | ------------- | ------------- | ------------- - **username** | **String**| The name that needs to be fetched. Use user1 for testing. | + **username** | **String**| The name that needs to be fetched. Use user1 for testing. | ### Return type @@ -221,8 +227,8 @@ No authorization required ### HTTP request headers - - **Content-Type**: Not defined - - **Accept**: application/xml, application/json + - **Content-Type**: application/json + - **Accept**: application/json # **loginUser** @@ -230,6 +236,8 @@ No authorization required Logs user into the system + + ### Example ```java SwagUserApi api = new SwagUserApi(); @@ -265,8 +273,8 @@ No authorization required ### HTTP request headers - - **Content-Type**: Not defined - - **Accept**: application/xml, application/json + - **Content-Type**: application/json + - **Accept**: application/json # **logoutUser** @@ -274,6 +282,8 @@ No authorization required Logs out current logged in user session + + ### Example ```java SwagUserApi api = new SwagUserApi(); @@ -299,12 +309,12 @@ No authorization required ### HTTP request headers - - **Content-Type**: Not defined - - **Accept**: Not defined + - **Content-Type**: application/json + - **Accept**: application/json # **updateUser** -> updateUser(username, swagUser) +> updateUser(username, body) Updated user @@ -316,7 +326,7 @@ SwagUserApi api = new SwagUserApi(); Map params = new Map{ 'username' => 'username_example', - 'swagUser' => SwagUser.getExample() + 'body' => SwagUser.getExample() }; try { @@ -332,7 +342,7 @@ try { Name | Type | Description | Notes ------------- | ------------- | ------------- | ------------- **username** | **String**| name that need to be deleted | - **swagUser** | [**SwagUser**](SwagUser.md)| Updated user object | + **body** | [**SwagUser**](User.md)| Updated user object | ### Return type @@ -344,6 +354,6 @@ No authorization required ### HTTP request headers - - **Content-Type**: Not defined - - **Accept**: Not defined + - **Content-Type**: application/json + - **Accept**: application/json diff --git a/samples/client/petstore/apex/force-app/main/default/classes/SwagApiResponse.cls b/samples/client/petstore/apex/force-app/main/default/classes/SwagApiResponse.cls index c5d38079650..d7d088cfcef 100644 --- a/samples/client/petstore/apex/force-app/main/default/classes/SwagApiResponse.cls +++ b/samples/client/petstore/apex/force-app/main/default/classes/SwagApiResponse.cls @@ -5,8 +5,8 @@ * OpenAPI spec version: 1.0.0 * * - * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - * https://openapi-generator.tech + * NOTE: This class is auto generated by the swagger code generator program. + * https://github.com/swagger-api/swagger-codegen.git * Do not edit the class manually. */ @@ -42,14 +42,14 @@ public class SwagApiResponse implements Swagger.MappedProperties { public static SwagApiResponse getExample() { SwagApiResponse apiResponse = new SwagApiResponse(); - apiResponse.code = ; - apiResponse.r_type = 'aeiou'; - apiResponse.message = 'aeiou'; + apiResponse.code = 0; + apiResponse.r_type = ''; + apiResponse.message = ''; return apiResponse; } public Boolean equals(Object obj) { - if (obj instanceof SwagApiResponse) { + if (obj instanceof SwagApiResponse) { SwagApiResponse apiResponse = (SwagApiResponse) obj; return this.code == apiResponse.code && this.r_type == apiResponse.r_type diff --git a/samples/client/petstore/apex/force-app/main/default/classes/SwagApiResponse.cls-meta.xml b/samples/client/petstore/apex/force-app/main/default/classes/SwagApiResponse.cls-meta.xml index 8b061c82b6f..fec71a26693 100644 --- a/samples/client/petstore/apex/force-app/main/default/classes/SwagApiResponse.cls-meta.xml +++ b/samples/client/petstore/apex/force-app/main/default/classes/SwagApiResponse.cls-meta.xml @@ -1,5 +1,5 @@ - 39.0 + 42.0 Active diff --git a/samples/client/petstore/apex/force-app/main/default/classes/SwagCategory.cls b/samples/client/petstore/apex/force-app/main/default/classes/SwagCategory.cls index 985aa5b1ecd..018d73ec7d4 100644 --- a/samples/client/petstore/apex/force-app/main/default/classes/SwagCategory.cls +++ b/samples/client/petstore/apex/force-app/main/default/classes/SwagCategory.cls @@ -5,8 +5,8 @@ * OpenAPI spec version: 1.0.0 * * - * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - * https://openapi-generator.tech + * NOTE: This class is auto generated by the swagger code generator program. + * https://github.com/swagger-api/swagger-codegen.git * Do not edit the class manually. */ @@ -28,13 +28,13 @@ public class SwagCategory { public static SwagCategory getExample() { SwagCategory category = new SwagCategory(); - category.id = 123456789L; - category.name = 'aeiou'; + category.id = 123456789L; + category.name = ''; return category; } public Boolean equals(Object obj) { - if (obj instanceof SwagCategory) { + if (obj instanceof SwagCategory) { SwagCategory category = (SwagCategory) obj; return this.id == category.id && this.name == category.name; diff --git a/samples/client/petstore/apex/force-app/main/default/classes/SwagCategory.cls-meta.xml b/samples/client/petstore/apex/force-app/main/default/classes/SwagCategory.cls-meta.xml index 8b061c82b6f..fec71a26693 100644 --- a/samples/client/petstore/apex/force-app/main/default/classes/SwagCategory.cls-meta.xml +++ b/samples/client/petstore/apex/force-app/main/default/classes/SwagCategory.cls-meta.xml @@ -1,5 +1,5 @@ - 39.0 + 42.0 Active diff --git a/samples/client/petstore/apex/force-app/main/default/classes/SwagClient.cls-meta.xml b/samples/client/petstore/apex/force-app/main/default/classes/SwagClient.cls-meta.xml index 8b061c82b6f..fec71a26693 100644 --- a/samples/client/petstore/apex/force-app/main/default/classes/SwagClient.cls-meta.xml +++ b/samples/client/petstore/apex/force-app/main/default/classes/SwagClient.cls-meta.xml @@ -1,5 +1,5 @@ - 39.0 + 42.0 Active diff --git a/samples/client/petstore/apex/force-app/main/default/classes/SwagOrder.cls b/samples/client/petstore/apex/force-app/main/default/classes/SwagOrder.cls index 0937a675e9b..47bd1aa549b 100644 --- a/samples/client/petstore/apex/force-app/main/default/classes/SwagOrder.cls +++ b/samples/client/petstore/apex/force-app/main/default/classes/SwagOrder.cls @@ -5,8 +5,8 @@ * OpenAPI spec version: 1.0.0 * * - * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - * https://openapi-generator.tech + * NOTE: This class is auto generated by the swagger code generator program. + * https://github.com/swagger-api/swagger-codegen.git * Do not edit the class manually. */ @@ -65,17 +65,17 @@ public class SwagOrder { public static SwagOrder getExample() { SwagOrder order = new SwagOrder(); - order.id = 123456789L; - order.petId = 123456789L; - order.quantity = ; - order.shipDate = Datetime.newInstanceGmt(2000, 1, 23, 4, 56, 7); - order.status = StatusEnum.PLACED; - order.complete = true; + order.id = 123456789L; + order.petId = 123456789L; + order.quantity = 0; + order.shipDate = Datetime.newInstanceGmt(2000, 1, 23, 4, 56, 7); + order.status = StatusEnum.PLACED; + order.complete = true; return order; } public Boolean equals(Object obj) { - if (obj instanceof SwagOrder) { + if (obj instanceof SwagOrder) { SwagOrder order = (SwagOrder) obj; return this.id == order.id && this.petId == order.petId diff --git a/samples/client/petstore/apex/force-app/main/default/classes/SwagOrder.cls-meta.xml b/samples/client/petstore/apex/force-app/main/default/classes/SwagOrder.cls-meta.xml index 8b061c82b6f..fec71a26693 100644 --- a/samples/client/petstore/apex/force-app/main/default/classes/SwagOrder.cls-meta.xml +++ b/samples/client/petstore/apex/force-app/main/default/classes/SwagOrder.cls-meta.xml @@ -1,5 +1,5 @@ - 39.0 + 42.0 Active diff --git a/samples/client/petstore/apex/force-app/main/default/classes/SwagPet.cls b/samples/client/petstore/apex/force-app/main/default/classes/SwagPet.cls index b04b5a621b1..7cd6f3a85fd 100644 --- a/samples/client/petstore/apex/force-app/main/default/classes/SwagPet.cls +++ b/samples/client/petstore/apex/force-app/main/default/classes/SwagPet.cls @@ -5,8 +5,8 @@ * OpenAPI spec version: 1.0.0 * * - * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - * https://openapi-generator.tech + * NOTE: This class is auto generated by the swagger code generator program. + * https://github.com/swagger-api/swagger-codegen.git * Do not edit the class manually. */ @@ -66,17 +66,17 @@ public class SwagPet { public static SwagPet getExample() { SwagPet pet = new SwagPet(); - pet.id = 123456789L; - pet.category = SwagCategory.getExample(); - pet.name = 'doggie'; - pet.photoUrls = new List{'aeiou'}; - pet.tags = new List{SwagTag.getExample()}; - pet.status = StatusEnum.AVAILABLE; + pet.id = 123456789L; + + pet.name = 'doggie'; + pet.photoUrls = new List{''}; + pet.tags = new List{null}; + pet.status = StatusEnum.AVAILABLE; return pet; } public Boolean equals(Object obj) { - if (obj instanceof SwagPet) { + if (obj instanceof SwagPet) { SwagPet pet = (SwagPet) obj; return this.id == pet.id && this.category == pet.category diff --git a/samples/client/petstore/apex/force-app/main/default/classes/SwagPet.cls-meta.xml b/samples/client/petstore/apex/force-app/main/default/classes/SwagPet.cls-meta.xml index 8b061c82b6f..fec71a26693 100644 --- a/samples/client/petstore/apex/force-app/main/default/classes/SwagPet.cls-meta.xml +++ b/samples/client/petstore/apex/force-app/main/default/classes/SwagPet.cls-meta.xml @@ -1,5 +1,5 @@ - 39.0 + 42.0 Active diff --git a/samples/client/petstore/apex/force-app/main/default/classes/SwagPetApi.cls b/samples/client/petstore/apex/force-app/main/default/classes/SwagPetApi.cls index 747fd271122..8c680e2b193 100644 --- a/samples/client/petstore/apex/force-app/main/default/classes/SwagPetApi.cls +++ b/samples/client/petstore/apex/force-app/main/default/classes/SwagPetApi.cls @@ -5,8 +5,8 @@ * OpenAPI spec version: 1.0.0 * * - * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - * https://openapi-generator.tech + * NOTE: This class is auto generated by the swagger code generator program. + * https://github.com/swagger-api/swagger-codegen.git * Do not edit the class manually. */ diff --git a/samples/client/petstore/apex/force-app/main/default/classes/SwagPetApi.cls-meta.xml b/samples/client/petstore/apex/force-app/main/default/classes/SwagPetApi.cls-meta.xml index 8b061c82b6f..fec71a26693 100644 --- a/samples/client/petstore/apex/force-app/main/default/classes/SwagPetApi.cls-meta.xml +++ b/samples/client/petstore/apex/force-app/main/default/classes/SwagPetApi.cls-meta.xml @@ -1,5 +1,5 @@ - 39.0 + 42.0 Active diff --git a/samples/client/petstore/apex/force-app/main/default/classes/SwagStoreApi.cls b/samples/client/petstore/apex/force-app/main/default/classes/SwagStoreApi.cls index a9f948232f2..36acaad1504 100644 --- a/samples/client/petstore/apex/force-app/main/default/classes/SwagStoreApi.cls +++ b/samples/client/petstore/apex/force-app/main/default/classes/SwagStoreApi.cls @@ -5,8 +5,8 @@ * OpenAPI spec version: 1.0.0 * * - * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - * https://openapi-generator.tech + * NOTE: This class is auto generated by the swagger code generator program. + * https://github.com/swagger-api/swagger-codegen.git * Do not edit the class manually. */ diff --git a/samples/client/petstore/apex/force-app/main/default/classes/SwagStoreApi.cls-meta.xml b/samples/client/petstore/apex/force-app/main/default/classes/SwagStoreApi.cls-meta.xml index 8b061c82b6f..fec71a26693 100644 --- a/samples/client/petstore/apex/force-app/main/default/classes/SwagStoreApi.cls-meta.xml +++ b/samples/client/petstore/apex/force-app/main/default/classes/SwagStoreApi.cls-meta.xml @@ -1,5 +1,5 @@ - 39.0 + 42.0 Active diff --git a/samples/client/petstore/apex/force-app/main/default/classes/SwagTag.cls b/samples/client/petstore/apex/force-app/main/default/classes/SwagTag.cls index 8f90699f773..b6414b68597 100644 --- a/samples/client/petstore/apex/force-app/main/default/classes/SwagTag.cls +++ b/samples/client/petstore/apex/force-app/main/default/classes/SwagTag.cls @@ -5,8 +5,8 @@ * OpenAPI spec version: 1.0.0 * * - * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - * https://openapi-generator.tech + * NOTE: This class is auto generated by the swagger code generator program. + * https://github.com/swagger-api/swagger-codegen.git * Do not edit the class manually. */ @@ -28,13 +28,13 @@ public class SwagTag { public static SwagTag getExample() { SwagTag tag = new SwagTag(); - tag.id = 123456789L; - tag.name = 'aeiou'; + tag.id = 123456789L; + tag.name = ''; return tag; } public Boolean equals(Object obj) { - if (obj instanceof SwagTag) { + if (obj instanceof SwagTag) { SwagTag tag = (SwagTag) obj; return this.id == tag.id && this.name == tag.name; diff --git a/samples/client/petstore/apex/force-app/main/default/classes/SwagTag.cls-meta.xml b/samples/client/petstore/apex/force-app/main/default/classes/SwagTag.cls-meta.xml index 8b061c82b6f..fec71a26693 100644 --- a/samples/client/petstore/apex/force-app/main/default/classes/SwagTag.cls-meta.xml +++ b/samples/client/petstore/apex/force-app/main/default/classes/SwagTag.cls-meta.xml @@ -1,5 +1,5 @@ - 39.0 + 42.0 Active diff --git a/samples/client/petstore/apex/force-app/main/default/classes/SwagUser.cls b/samples/client/petstore/apex/force-app/main/default/classes/SwagUser.cls index 63e4c8423eb..28ffe86d542 100644 --- a/samples/client/petstore/apex/force-app/main/default/classes/SwagUser.cls +++ b/samples/client/petstore/apex/force-app/main/default/classes/SwagUser.cls @@ -5,8 +5,8 @@ * OpenAPI spec version: 1.0.0 * * - * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - * https://openapi-generator.tech + * NOTE: This class is auto generated by the swagger code generator program. + * https://github.com/swagger-api/swagger-codegen.git * Do not edit the class manually. */ @@ -64,19 +64,19 @@ public class SwagUser { public static SwagUser getExample() { SwagUser user = new SwagUser(); - user.id = 123456789L; - user.username = 'aeiou'; - user.firstName = 'aeiou'; - user.lastName = 'aeiou'; - user.email = 'aeiou'; - user.password = 'aeiou'; - user.phone = 'aeiou'; - user.userStatus = ; + user.id = 123456789L; + user.username = ''; + user.firstName = ''; + user.lastName = ''; + user.email = ''; + user.password = ''; + user.phone = ''; + user.userStatus = 0; return user; } public Boolean equals(Object obj) { - if (obj instanceof SwagUser) { + if (obj instanceof SwagUser) { SwagUser user = (SwagUser) obj; return this.id == user.id && this.username == user.username diff --git a/samples/client/petstore/apex/force-app/main/default/classes/SwagUser.cls-meta.xml b/samples/client/petstore/apex/force-app/main/default/classes/SwagUser.cls-meta.xml index 8b061c82b6f..fec71a26693 100644 --- a/samples/client/petstore/apex/force-app/main/default/classes/SwagUser.cls-meta.xml +++ b/samples/client/petstore/apex/force-app/main/default/classes/SwagUser.cls-meta.xml @@ -1,5 +1,5 @@ - 39.0 + 42.0 Active diff --git a/samples/client/petstore/apex/force-app/main/default/classes/SwagUserApi.cls b/samples/client/petstore/apex/force-app/main/default/classes/SwagUserApi.cls index ae296e8d3ba..b37fc799e44 100644 --- a/samples/client/petstore/apex/force-app/main/default/classes/SwagUserApi.cls +++ b/samples/client/petstore/apex/force-app/main/default/classes/SwagUserApi.cls @@ -5,8 +5,8 @@ * OpenAPI spec version: 1.0.0 * * - * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - * https://openapi-generator.tech + * NOTE: This class is auto generated by the swagger code generator program. + * https://github.com/swagger-api/swagger-codegen.git * Do not edit the class manually. */ diff --git a/samples/client/petstore/apex/force-app/main/default/classes/SwagUserApi.cls-meta.xml b/samples/client/petstore/apex/force-app/main/default/classes/SwagUserApi.cls-meta.xml index 8b061c82b6f..fec71a26693 100644 --- a/samples/client/petstore/apex/force-app/main/default/classes/SwagUserApi.cls-meta.xml +++ b/samples/client/petstore/apex/force-app/main/default/classes/SwagUserApi.cls-meta.xml @@ -1,5 +1,5 @@ - 39.0 + 42.0 Active diff --git a/samples/client/petstore/apex/force-app/main/default/classes/Swagger.cls b/samples/client/petstore/apex/force-app/main/default/classes/Swagger.cls index 172c3038111..bb4e44f7971 100644 --- a/samples/client/petstore/apex/force-app/main/default/classes/Swagger.cls +++ b/samples/client/petstore/apex/force-app/main/default/classes/Swagger.cls @@ -271,9 +271,7 @@ public class Swagger { @TestVisible protected virtual void applyAuthentication(List names, Map headers, List query) { - for (Authentication auth : getAuthMethods(names)) { - auth.apply(headers, query); - } + // TODO Check auth methods } @TestVisible @@ -298,7 +296,7 @@ public class Swagger { protected virtual String toEndpoint(String path, Map params, List queryParams) { String query = '?' + paramsToString(queryParams); - return '"callout:' + calloutName + toPath(path, params) + query.removeEnd('?') + '""'; + return 'callout:' + calloutName + toPath(path, params) + query.removeEnd('?'); } @TestVisible diff --git a/samples/client/petstore/apex/force-app/main/default/classes/Swagger.cls-meta.xml b/samples/client/petstore/apex/force-app/main/default/classes/Swagger.cls-meta.xml index 8b061c82b6f..fec71a26693 100644 --- a/samples/client/petstore/apex/force-app/main/default/classes/Swagger.cls-meta.xml +++ b/samples/client/petstore/apex/force-app/main/default/classes/Swagger.cls-meta.xml @@ -1,5 +1,5 @@ - 39.0 + 42.0 Active diff --git a/samples/client/petstore/apex/force-app/main/default/classes/SwaggerResponseMock.cls-meta.xml b/samples/client/petstore/apex/force-app/main/default/classes/SwaggerResponseMock.cls-meta.xml index 8b061c82b6f..fec71a26693 100644 --- a/samples/client/petstore/apex/force-app/main/default/classes/SwaggerResponseMock.cls-meta.xml +++ b/samples/client/petstore/apex/force-app/main/default/classes/SwaggerResponseMock.cls-meta.xml @@ -1,5 +1,5 @@ - 39.0 + 42.0 Active diff --git a/samples/client/petstore/apex/force-app/main/default/classes/SwaggerTest.cls b/samples/client/petstore/apex/force-app/main/default/classes/SwaggerTest.cls index e3cec8831c6..d95e9b60aa8 100644 --- a/samples/client/petstore/apex/force-app/main/default/classes/SwaggerTest.cls +++ b/samples/client/petstore/apex/force-app/main/default/classes/SwaggerTest.cls @@ -292,7 +292,7 @@ private class SwaggerTest { new Swagger.Param('foo', 'bar'), new Swagger.Param('bat', '123') }; - String expected = 'https://www.mccombs.utexas.edu/departments/finance?foo=bar&bat=123'; + String expected = 'callout:Winkelmeyer/departments/finance?foo=bar&bat=123'; String actual = client.toEndpoint(path, params, queryParams); System.assertEquals(expected, actual); } @@ -360,7 +360,8 @@ private class SwaggerTest { private class MockApiClient extends Swagger.ApiClient { public MockApiClient() { - basePath = 'https://www.mccombs.utexas.edu'; + basePath = 'https://blog.winkelmeyer.com'; + calloutName = 'Winkelmeyer'; } } } \ No newline at end of file diff --git a/samples/client/petstore/apex/force-app/main/default/classes/SwaggerTest.cls-meta.xml b/samples/client/petstore/apex/force-app/main/default/classes/SwaggerTest.cls-meta.xml index 8b061c82b6f..fec71a26693 100644 --- a/samples/client/petstore/apex/force-app/main/default/classes/SwaggerTest.cls-meta.xml +++ b/samples/client/petstore/apex/force-app/main/default/classes/SwaggerTest.cls-meta.xml @@ -1,5 +1,5 @@ - 39.0 + 42.0 Active diff --git a/samples/client/petstore/apex/force-app/main/default/namedCredentials/OpenAPI_Petstore.namedCredential b/samples/client/petstore/apex/force-app/main/default/namedCredentials/OpenAPI_Petstore.namedCredential-meta.xml similarity index 100% rename from samples/client/petstore/apex/force-app/main/default/namedCredentials/OpenAPI_Petstore.namedCredential rename to samples/client/petstore/apex/force-app/main/default/namedCredentials/OpenAPI_Petstore.namedCredential-meta.xml diff --git a/samples/client/petstore/apex/force-app/main/default/namedCredentials/Swagger_Petstore.namedCredential-meta.xml b/samples/client/petstore/apex/force-app/main/default/namedCredentials/Swagger_Petstore.namedCredential-meta.xml new file mode 100644 index 00000000000..e7d8d71ac1c --- /dev/null +++ b/samples/client/petstore/apex/force-app/main/default/namedCredentials/Swagger_Petstore.namedCredential-meta.xml @@ -0,0 +1,7 @@ + + + http://petstore.swagger.io/v2 + Anonymous + NoAuthentication + + \ No newline at end of file diff --git a/samples/client/petstore/apex/sfdx-project.json b/samples/client/petstore/apex/sfdx-project.json new file mode 100644 index 00000000000..e0fe2f7ab16 --- /dev/null +++ b/samples/client/petstore/apex/sfdx-project.json @@ -0,0 +1,11 @@ +{ + "packageDirectories": [ + { + "path": "force-app", + "default": true + } + ], + "namespace": "", + "sfdcLoginUrl": "https://login.salesforce.com", + "sourceApiVersion": "42.0" +} \ No newline at end of file