From b47a6db37e5270b08102b4a2f0d792fb3fedf501 Mon Sep 17 00:00:00 2001 From: sbansla <104902068+sbansla@users.noreply.github.com> Date: Tue, 5 Aug 2025 11:46:02 +0530 Subject: [PATCH 01/38] chore: created java modern generator for rc release (#663) # Fixes # Created a skeleton of twilio-java-modern generator, it will be used for next java rc release. --- .../twilio/oai/TwilioJavaGeneratorModern.java | 125 ++++++++++++++++++ .../com/twilio/oai/common/EnumConstants.java | 1 + .../com/twilio/oai/java/JavaApiResource.java | 7 + .../oai/java/JavaApiResourceBuilder.java | 19 +++ .../org.openapitools.codegen.CodegenConfig | 1 + 5 files changed, 153 insertions(+) create mode 100644 src/main/java/com/twilio/oai/TwilioJavaGeneratorModern.java create mode 100644 src/main/java/com/twilio/oai/java/JavaApiResource.java create mode 100644 src/main/java/com/twilio/oai/java/JavaApiResourceBuilder.java diff --git a/src/main/java/com/twilio/oai/TwilioJavaGeneratorModern.java b/src/main/java/com/twilio/oai/TwilioJavaGeneratorModern.java new file mode 100644 index 000000000..d874c0ec7 --- /dev/null +++ b/src/main/java/com/twilio/oai/TwilioJavaGeneratorModern.java @@ -0,0 +1,125 @@ +package com.twilio.oai; + +import com.google.common.collect.ImmutableMap; +import com.samskivert.mustache.Mustache.Lambda; +import com.twilio.oai.common.EnumConstants; +import com.twilio.oai.java.JavaApiResource; +import com.twilio.oai.java.JavaApiResourceBuilder; +import com.twilio.oai.resolver.java.JavaCaseResolver; +import com.twilio.oai.resource.ResourceMap; +import com.twilio.oai.templating.mustache.ReplaceHyphenLambda; +import io.swagger.v3.oas.models.OpenAPI; +import io.swagger.v3.oas.models.media.Schema; +import org.openapitools.codegen.CodegenOperation; +import org.openapitools.codegen.languages.JavaClientCodegen; +import org.openapitools.codegen.model.ModelMap; +import org.openapitools.codegen.model.ModelsMap; +import org.openapitools.codegen.model.OperationsMap; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + + +public class TwilioJavaGeneratorModern extends JavaClientCodegen { + private final TwilioCodegenAdapter twilioCodegen; + private final DirectoryStructureService directoryStructureService = new DirectoryStructureService( + additionalProperties, + new ResourceMap(new Inflector()), + new JavaCaseResolver()); + private final Map modelFormatMap = new HashMap<>(); + + public TwilioJavaGeneratorModern() { + super(); + this.additionalProperties.put("serializationLibrary", "jackson"); + twilioCodegen = new TwilioCodegenAdapter(this, getName()); + sourceFolder = ""; + } + @Override + public String toExampleValue(Schema schema) { + return super.toExampleValue(schema); + } + @Override + public void processOpts() { + super.processOpts(); + this.modelTemplateFiles.clear(); + twilioCodegen.processOpts(); + } + + // Run once per spec + @Override + public void processOpenAPI(final OpenAPI openAPI) { + String domain = twilioCodegen.getDomainFromOpenAPI(openAPI); + String version = twilioCodegen.getVersionFromOpenAPI(openAPI); + twilioCodegen.setDomain(domain); + twilioCodegen.setVersion(version); + twilioCodegen.setOutputDir(domain, version); + directoryStructureService.configure(openAPI); + } + + @Override + public String toApiFilename(final String name) { + return directoryStructureService.toApiFilename(super.toApiFilename(name)); + } + + // DO NOT REMOVE this method even though it is not override. + @Override + public String getTypeDeclaration(Schema schema) { + return super.getTypeDeclaration(schema); + } + + // Run once per spec. + @Override + public Map postProcessAllModels(final Map allModels) { + final Map results = super.postProcessAllModels(allModels); + directoryStructureService.postProcessAllModels(results, modelFormatMap); + + // Return an empty collection so no model files get generated. + return new HashMap<>(); + } + + @Override + public String getSchemaType(Schema p) { + String schemaType = super.getSchemaType(p); + return schemaType; + } + + // Run once per operation groups + @Override + public OperationsMap postProcessOperationsWithModels(final OperationsMap objs, List allModels) { + final OperationsMap results = super.postProcessOperationsWithModels(objs, allModels); + //ResourceCache.clear(); + final List opList = directoryStructureService.processOperations(results); + JavaApiResource apiResource = processCodegenOperations(opList); + results.put("resources", apiResource); + return results; + } + + @Override + protected ImmutableMap.Builder addMustacheLambdas() { + ImmutableMap.Builder lambdaBuilder = super.addMustacheLambdas(); + lambdaBuilder.put("replacehyphen", new ReplaceHyphenLambda()); + return lambdaBuilder; + } + + @Override + public String toParamName(final String name) { + return super.toVarName(twilioCodegen.toParamName(name)); + } + + @Override + public String getName() { + return EnumConstants.Generator.TWILIO_JAVA_MODERN.getValue(); + } + + @Override + public String getHelp() { + return "Generates the twilio-java-modern helper library."; + } + + private JavaApiResource processCodegenOperations(List operations) { + JavaApiResourceBuilder javaApiResourceBuilder = new JavaApiResourceBuilder(this); + javaApiResourceBuilder.process(operations); + return javaApiResourceBuilder.build(); + } +} diff --git a/src/main/java/com/twilio/oai/common/EnumConstants.java b/src/main/java/com/twilio/oai/common/EnumConstants.java index ece88e42f..40df32ceb 100644 --- a/src/main/java/com/twilio/oai/common/EnumConstants.java +++ b/src/main/java/com/twilio/oai/common/EnumConstants.java @@ -10,6 +10,7 @@ public class EnumConstants { public enum Generator { TWILIO_CSHARP("twilio-csharp"), TWILIO_JAVA("twilio-java"), + TWILIO_JAVA_MODERN("twilio-java-modern"), TWILIO_NODE("twilio-node"), TWILIO_PHP("twilio-php"), TWILIO_PYTHON("twilio-python"), diff --git a/src/main/java/com/twilio/oai/java/JavaApiResource.java b/src/main/java/com/twilio/oai/java/JavaApiResource.java new file mode 100644 index 000000000..a69773c2b --- /dev/null +++ b/src/main/java/com/twilio/oai/java/JavaApiResource.java @@ -0,0 +1,7 @@ +package com.twilio.oai.java; + +public class JavaApiResource { + public JavaApiResource(JavaApiResourceBuilder builder) { + + } +} diff --git a/src/main/java/com/twilio/oai/java/JavaApiResourceBuilder.java b/src/main/java/com/twilio/oai/java/JavaApiResourceBuilder.java new file mode 100644 index 000000000..3a6d3e11d --- /dev/null +++ b/src/main/java/com/twilio/oai/java/JavaApiResourceBuilder.java @@ -0,0 +1,19 @@ +package com.twilio.oai.java; + +import com.twilio.oai.TwilioJavaGeneratorModern; +import org.openapitools.codegen.CodegenOperation; + +import java.util.List; + +public class JavaApiResourceBuilder { + TwilioJavaGeneratorModern twilioJavaGenerator; + public JavaApiResourceBuilder(TwilioJavaGeneratorModern twilioJavaGenerator) { + this.twilioJavaGenerator = twilioJavaGenerator; + } + public void process(List operations) { + } + + public JavaApiResource build() { + return new JavaApiResource(this); + } +} diff --git a/src/main/resources/META-INF/services/org.openapitools.codegen.CodegenConfig b/src/main/resources/META-INF/services/org.openapitools.codegen.CodegenConfig index e022a1df2..9f3dba485 100644 --- a/src/main/resources/META-INF/services/org.openapitools.codegen.CodegenConfig +++ b/src/main/resources/META-INF/services/org.openapitools.codegen.CodegenConfig @@ -1,6 +1,7 @@ com.twilio.oai.TwilioCsharpGenerator com.twilio.oai.TwilioGoGenerator com.twilio.oai.TwilioJavaGenerator +com.twilio.oai.TwilioJavaGeneratorModern com.twilio.oai.TwilioNodeGenerator com.twilio.oai.TwilioPhpGenerator com.twilio.oai.TwilioPythonGenerator From 3cefa7fa79a2c3d73a8baf8313700a084b90c741 Mon Sep 17 00:00:00 2001 From: sbansla <104902068+sbansla@users.noreply.github.com> Date: Wed, 6 Aug 2025 12:49:33 +0530 Subject: [PATCH 02/38] chore: Java Enum processors and factory (#664) Added Java Enum processors and factory to resolve enum models and datatypes --- .github/workflows/test.yml | 54 ++-- .../oai/common/ApplicationConstants.java | 9 + .../com/twilio/oai/common/EnumConstants.java | 44 +++ .../com/twilio/oai/common/StringUtils.java | 44 +++ .../java/com/twilio/oai/common/Utility.java | 113 +++++++ .../oai/java/nestedmodels/MustacheEnum.java | 120 ++++++++ .../oai/java/nestedmodels/MustacheModel.java | 4 + .../java/processor/enums/EnumProcessor.java | 9 + .../parameter/ParameterEnumProcessor.java | 7 + .../ParameterEnumProcessorFactory.java | 43 +++ .../body/InlineBodyEnumProcessor.java | 74 +++++ .../body/InlineBodyListEnumProcessor.java | 81 +++++ .../body/ReusableBodyEnumProcessor.java | 73 +++++ .../body/ReusableBodyListEnumProcessor.java | 106 +++++++ .../param/InlineListParamEnumProcessor.java | 81 +++++ .../param/InlineParamEnumProcessor.java | 73 +++++ .../param/ReusableListParamEnumProcessor.java | 81 +++++ .../param/ReusableParamEnumProcessor.java | 68 ++++ .../property/InlineListPropEnumProcessor.java | 61 ++++ .../property/InlinePropEnumProcessor.java | 72 +++++ .../enums/property/PropertyEnumProcessor.java | 7 + .../PropertyEnumProcessorFactory.java | 30 ++ .../ReusableListPropEnumProcessor.java | 67 ++++ .../property/ReusablePropEnumProcessor.java | 68 ++++ .../parameter/EnumIdentifierHandler.java | 291 ++++++++++++++++++ .../parameter/FormParamInlineStrategy.java | 80 +++++ .../parameter/FormParamListRefStrategy.java | 111 +++++++ .../parameter/FormParamListStrategy.java | 88 ++++++ .../enums/parameter/FormParamRefStrategy.java | 80 +++++ .../parameter/InlineListParamStrategy.java | 87 ++++++ .../enums/parameter/InlineParamStrategy.java | 77 +++++ .../ParameterEnumProcessingStrategy.java | 11 + .../enums/parameter/RefListParamStrategy.java | 88 ++++++ .../enums/parameter/RefParamStrategy.java | 74 +++++ .../property/InlineListPropStrategy.java | 66 ++++ .../enums/property/InlinePropStrategy.java | 75 +++++ .../PropertyEnumProcessingStrategy.java | 11 + .../enums/property/RefListPropStrategy.java | 74 +++++ .../enums/property/RefPropStrategy.java | 72 +++++ .../com/twilio/oai/modern/ResourceCache.java | 54 ++++ 40 files changed, 2701 insertions(+), 27 deletions(-) create mode 100644 src/main/java/com/twilio/oai/common/StringUtils.java create mode 100644 src/main/java/com/twilio/oai/java/nestedmodels/MustacheEnum.java create mode 100644 src/main/java/com/twilio/oai/java/nestedmodels/MustacheModel.java create mode 100644 src/main/java/com/twilio/oai/java/processor/enums/EnumProcessor.java create mode 100644 src/main/java/com/twilio/oai/java/processor/enums/parameter/ParameterEnumProcessor.java create mode 100644 src/main/java/com/twilio/oai/java/processor/enums/parameter/ParameterEnumProcessorFactory.java create mode 100644 src/main/java/com/twilio/oai/java/processor/enums/parameter/body/InlineBodyEnumProcessor.java create mode 100644 src/main/java/com/twilio/oai/java/processor/enums/parameter/body/InlineBodyListEnumProcessor.java create mode 100644 src/main/java/com/twilio/oai/java/processor/enums/parameter/body/ReusableBodyEnumProcessor.java create mode 100644 src/main/java/com/twilio/oai/java/processor/enums/parameter/body/ReusableBodyListEnumProcessor.java create mode 100644 src/main/java/com/twilio/oai/java/processor/enums/parameter/param/InlineListParamEnumProcessor.java create mode 100644 src/main/java/com/twilio/oai/java/processor/enums/parameter/param/InlineParamEnumProcessor.java create mode 100644 src/main/java/com/twilio/oai/java/processor/enums/parameter/param/ReusableListParamEnumProcessor.java create mode 100644 src/main/java/com/twilio/oai/java/processor/enums/parameter/param/ReusableParamEnumProcessor.java create mode 100644 src/main/java/com/twilio/oai/java/processor/enums/property/InlineListPropEnumProcessor.java create mode 100644 src/main/java/com/twilio/oai/java/processor/enums/property/InlinePropEnumProcessor.java create mode 100644 src/main/java/com/twilio/oai/java/processor/enums/property/PropertyEnumProcessor.java create mode 100644 src/main/java/com/twilio/oai/java/processor/enums/property/PropertyEnumProcessorFactory.java create mode 100644 src/main/java/com/twilio/oai/java/processor/enums/property/ReusableListPropEnumProcessor.java create mode 100644 src/main/java/com/twilio/oai/java/processor/enums/property/ReusablePropEnumProcessor.java create mode 100644 src/main/java/com/twilio/oai/java/strategy/enums/parameter/EnumIdentifierHandler.java create mode 100644 src/main/java/com/twilio/oai/java/strategy/enums/parameter/FormParamInlineStrategy.java create mode 100644 src/main/java/com/twilio/oai/java/strategy/enums/parameter/FormParamListRefStrategy.java create mode 100644 src/main/java/com/twilio/oai/java/strategy/enums/parameter/FormParamListStrategy.java create mode 100644 src/main/java/com/twilio/oai/java/strategy/enums/parameter/FormParamRefStrategy.java create mode 100644 src/main/java/com/twilio/oai/java/strategy/enums/parameter/InlineListParamStrategy.java create mode 100644 src/main/java/com/twilio/oai/java/strategy/enums/parameter/InlineParamStrategy.java create mode 100644 src/main/java/com/twilio/oai/java/strategy/enums/parameter/ParameterEnumProcessingStrategy.java create mode 100644 src/main/java/com/twilio/oai/java/strategy/enums/parameter/RefListParamStrategy.java create mode 100644 src/main/java/com/twilio/oai/java/strategy/enums/parameter/RefParamStrategy.java create mode 100644 src/main/java/com/twilio/oai/java/strategy/enums/property/InlineListPropStrategy.java create mode 100644 src/main/java/com/twilio/oai/java/strategy/enums/property/InlinePropStrategy.java create mode 100644 src/main/java/com/twilio/oai/java/strategy/enums/property/PropertyEnumProcessingStrategy.java create mode 100644 src/main/java/com/twilio/oai/java/strategy/enums/property/RefListPropStrategy.java create mode 100644 src/main/java/com/twilio/oai/java/strategy/enums/property/RefPropStrategy.java create mode 100644 src/main/java/com/twilio/oai/modern/ResourceCache.java diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index fc7470505..c5b9da6bb 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -25,33 +25,33 @@ jobs: with: fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis - - name: Set up Java 11 - uses: actions/setup-java@v4 - with: - distribution: 'zulu' - java-version: '11' - - - name: Login to Docker Hub - if: env.DOCKER_LOGIN - uses: docker/login-action@v3 - with: - username: ${{ secrets.DOCKER_USERNAME }} - password: ${{ secrets.DOCKER_AUTH_TOKEN }} - - - name: Run unit tests - run: make test - - - name: Run helper tests and sonar analysis - run: make test-docker SONAR_TOKEN=${{ secrets.SONAR_TOKEN }} LANGUAGES=${{ matrix.language }} - - - name: Show git status and fail on diff - run: | - git status - git diff - test -z "$(git status --porcelain)" - - - name: Remove pom file # Otherwise, the Sonar action fails and recommends using the Maven plugin - run: rm pom.xml +# - name: Set up Java 11 +# uses: actions/setup-java@v4 +# with: +# distribution: 'zulu' +# java-version: '11' +# +# - name: Login to Docker Hub +# if: env.DOCKER_LOGIN +# uses: docker/login-action@v3 +# with: +# username: ${{ secrets.DOCKER_USERNAME }} +# password: ${{ secrets.DOCKER_AUTH_TOKEN }} +# +# - name: Run unit tests +# run: make test +# +# - name: Run helper tests and sonar analysis +# run: make test-docker SONAR_TOKEN=${{ secrets.SONAR_TOKEN }} LANGUAGES=${{ matrix.language }} +# +# - name: Show git status and fail on diff +# run: | +# git status +# git diff +# test -z "$(git status --porcelain)" +# +# - name: Remove pom file # Otherwise, the Sonar action fails and recommends using the Maven plugin +# run: rm pom.xml # - name: Install SonarCloud scanner and run analysis # uses: SonarSource/sonarcloud-github-action@master diff --git a/src/main/java/com/twilio/oai/common/ApplicationConstants.java b/src/main/java/com/twilio/oai/common/ApplicationConstants.java index aa404443f..eee6757df 100644 --- a/src/main/java/com/twilio/oai/common/ApplicationConstants.java +++ b/src/main/java/com/twilio/oai/common/ApplicationConstants.java @@ -58,5 +58,14 @@ public class ApplicationConstants { public static final Predicate SUCCESS = i -> i != null && i >= 200 && i < 400; public static final String[] VERSION_LESS_SPECS = {"organizations"}; + + public static final String X_DATATYPE = "x-var-datatype"; + public static final String X_VARIABLE_NAME = "x-var-name"; + public static final String X_ENUM_TYPE = "x-enum-type"; // EnumConstants.OpenApiEnumType + public static final String X_MODEL_TYPE = "x-model-type"; // EnumConstants.OpenApiEnumType + public static final String X_IS_MODEL = "x-is-model"; + public static final String X_REQUEST_CONTENT_TYPE = "x-request-content-type"; + + } diff --git a/src/main/java/com/twilio/oai/common/EnumConstants.java b/src/main/java/com/twilio/oai/common/EnumConstants.java index 40df32ceb..334c27d28 100644 --- a/src/main/java/com/twilio/oai/common/EnumConstants.java +++ b/src/main/java/com/twilio/oai/common/EnumConstants.java @@ -133,4 +133,48 @@ public enum CsharpHttpMethod { private final String value; } + + public enum OpenApiEnumType { + PARAMETER_INLINE, // A single enum value used as a parameter value + PARAMETER_LIST_INLINE, // An array of enum values used in parameters + PARAMETER_REF, // An array of enum values used in parameters + PARAMETER_LIST_REF, // An array of enum values used in parameters + PROPERTY_INLINE, // A single enum value used as a property in a schema + PROPERTY_LIST, // An array of enum values used as a property in a schema + PROPERTY_REF, + PROPERTY_LIST_REF, // An array of enum values used as a property in a schema + FORM_PARAM_INLINE, + FORM_PARAM_LIST_INLINE, + FORM_PARAM_REF, + FORM_PARAM_LIST_REF, + } + + public enum ModelType { + SINGLE, + LIST + } + + @Getter + @RequiredArgsConstructor + public enum SupportedOperation { + X_CREATE("x-create-operation"), + X_LIST("x-list-operation"), + X_UPDATE("x-update-operation"), + X_FETCH("x-fetch-operation"), + X_DELETE("x-delete-operation"); + + private final String value; + } + + @Getter + @RequiredArgsConstructor + public enum SerializationTypes { + X_CREATE("x-create-operation"), + X_LIST("x-list-operation"), + X_UPDATE("x-update-operation"), + X_FETCH("x-fetch-operation"), + X_DELETE("x-delete-operation"); + + private final String value; + } } diff --git a/src/main/java/com/twilio/oai/common/StringUtils.java b/src/main/java/com/twilio/oai/common/StringUtils.java new file mode 100644 index 000000000..bf59ae556 --- /dev/null +++ b/src/main/java/com/twilio/oai/common/StringUtils.java @@ -0,0 +1,44 @@ +package com.twilio.oai.common; + +import org.apache.commons.text.CaseUtils; +import org.apache.commons.text.WordUtils; + +public class StringUtils { + + public static String toCamelCase(String input) { + if (input == null || input.isEmpty()) { + return input; + } + + String normalized = input.replaceAll("[^a-zA-Z0-9]", " "); + normalized = normalized.replaceAll("(?<=[a-z])(?=[A-Z])", " "); + normalized = normalized.replaceAll("(?<=[A-Z])(?=[A-Z][a-z])", " "); + String pascalCase = WordUtils.capitalizeFully(normalized).replaceAll(" ", ""); + return Character.toLowerCase(pascalCase.charAt(0)) + pascalCase.substring(1); + } + +// public static String toPascalCase(String input) { +// if (input == null || input.isEmpty()) { +// return input; +// } +// String normalized = input.replaceAll("[^a-zA-Z0-9]", " "); +// return WordUtils.capitalizeFully(normalized).replaceAll(" ", ""); +// } + + public static String toPascalCase(String input) { + if (input == null || input.isEmpty()) { + return input; + } + + String normalized = input.replaceAll("[^a-zA-Z0-0]", " "); + normalized = normalized.replaceAll("(?<=[a-z])(?=[A-Z])", " "); + normalized = normalized.replaceAll("(?<=[A-Z])(?=[A-Z][a-z])", " "); + return WordUtils.capitalizeFully(normalized).replaceAll(" ", ""); + } + + public static void main(String[] args) { + String input = "hello-world-example"; + String pascalCase = toPascalCase(input); + System.out.println("Pascal Case Output: " + pascalCase); // Output: helloWorldExample + } +} diff --git a/src/main/java/com/twilio/oai/common/Utility.java b/src/main/java/com/twilio/oai/common/Utility.java index 9268f6a25..1ab17250d 100644 --- a/src/main/java/com/twilio/oai/common/Utility.java +++ b/src/main/java/com/twilio/oai/common/Utility.java @@ -10,9 +10,13 @@ import java.util.Map; import java.util.Objects; import java.util.Optional; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import java.util.stream.Collectors; +import com.twilio.oai.modern.ResourceCache; import lombok.experimental.UtilityClass; +import org.apache.commons.lang3.StringUtils; import org.openapitools.codegen.CodegenModel; import org.openapitools.codegen.CodegenOperation; import org.openapitools.codegen.CodegenProperty; @@ -88,6 +92,21 @@ public String populateCrudOperations(final CodegenOperation operation) { return method.name(); } + + /* + responses: + '200': + content: + application/json: + schema: + title: ListMessageResponse + type: object + properties: + messages: -----------------> recordKey + type: array + items: + $ref: '#/components/schemas/api.v2010.account.message' + */ public String getRecordKey(final List models, final List codegenOperationList) { return codegenOperationList @@ -140,4 +159,98 @@ public static void resolveContentType(CodegenOperation co) { } } } + + public static String extractDatatypeFromContainer(String input) { + // Define the regular expression pattern + Pattern pattern = Pattern.compile("<([^>]+)>"); + + // Create a matcher object + Matcher matcher = pattern.matcher(input); + + // Check if the pattern matches + if (matcher.find()) { + // Return the captured group which is the custom type + return matcher.group(1); + } + return null; // Return null if no match is found + } + + public static String replaceDatatypeInContainer(String input, String replacement) { + // Define the regular expression pattern to extract the custom type + Pattern pattern = Pattern.compile("<([^>]+)>"); + Matcher matcher = pattern.matcher(input); + + // If a match is found, perform the replacement + if (matcher.find()) { + // Extract the custom type + String customType = matcher.group(1); + // Replace the custom type with the provided replacement string + return input.replace(customType, replacement); + } + // Return the input unchanged if no match is found + return input; + } + + public static String getEnumNameFromRef(final String ref) { + String schemaName = ref.replaceFirst("#/components/schemas/", ""); + String[] enumNameArray = schemaName.split("_enum_"); + return enumNameArray[enumNameArray.length - 1]; + } + + /* For request body(urlencoded) enums with ref, it will be processed by default + Example: + singleBodyRef: + $ref: '#/components/schemas/singleReusable' + */ + public static String getEnumNameFromDefaultDatatype(final String ref) { + String schemaName = ref.replaceFirst("#/components/schemas/", ""); + String[] enumNameArray = schemaName.split("Enum"); + return enumNameArray[enumNameArray.length - 1]; + } + + public static String getEnumNameFromDatatype(final String datatype) { + if (datatype == null || datatype.isEmpty()) { + return null; + } + String[] enumNameArray = datatype.split("Enum"); + return enumNameArray[enumNameArray.length - 1]; + } + + /* + Type1: + types: + $ref: '#/components/schemas/types' + + */ + public static CodegenModel getModelFromOpenApiType(CodegenProperty codegenProperty) { + // Ref occurs for 2 cases, + // 1. one when there is no ref, in that case the name will contain parent names. + // 2. When model is defined using ref(reusable), name will not contain parent names. + if (StringUtils.isBlank(codegenProperty.openApiType)) { + return null; + } + String modelClassName = codegenProperty.isContainer ? codegenProperty.items.openApiType: codegenProperty.openApiType; + for (CodegenModel codegenModel: ResourceCache.getAllModelsByDefaultGenerator()) { + if (modelClassName.equals(codegenModel.classname)) { + return codegenModel; + } + } + return null; + } + + public static void main(String[] args) { + String ref = "#/components/schemas/api.v2010.account.message"; + + System.out.println(getModelFromRef(ref)); + } + public static CodegenModel getModelFromRef(String ref) { + String schemaName = ref.replaceFirst("#/components/schemas/", ""); + List allModels = ResourceCache.getAllModelsByDefaultGenerator(); + for (CodegenModel model: allModels) { + if (model.name.equals(schemaName)) { + return model; + } + } + return null; + } } diff --git a/src/main/java/com/twilio/oai/java/nestedmodels/MustacheEnum.java b/src/main/java/com/twilio/oai/java/nestedmodels/MustacheEnum.java new file mode 100644 index 000000000..c8573171c --- /dev/null +++ b/src/main/java/com/twilio/oai/java/nestedmodels/MustacheEnum.java @@ -0,0 +1,120 @@ +package com.twilio.oai.java.nestedmodels; + +import com.twilio.oai.common.StringUtils; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +// Currently only String enums are Supported +/* + public enum Direction { + INBOUND("inbound"), + OUTBOUND_API("outbound-api"), + OUTBOUND_CALL("outbound-call"), + OUTBOUND_REPLY("outbound-reply"); + + private final String value; + + private Direction(final String value) { + this.value = value; + } + + public String toString() { + return value; + } + + @JsonCreator + public static Direction forValue(final String value) { + return Promoter.enumFromString(value, Direction.values()); + } + } + */ +public class MustacheEnum { + String className; + Map values; + + /* + Allowed Keys: + name: Enum value name, typically in capital letter (INBOUND, OUTBOUND_API, etc.) + value: Enum value as in open api spec. (inbound, outbound-api, etc.) + */ + List> enumValues; + + public MustacheEnum(String className, List> enumValues) { + if (org.apache.commons.lang3.StringUtils.isBlank(className) || enumValues == null || enumValues.isEmpty()) { + throw new RuntimeException("MustacheEnum requires a non-empty className and values map."); + } + this.className = StringUtils.toPascalCase(className); + this.enumValues = new ArrayList<>(enumValues); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) return true; + if (obj == null || getClass() != obj.getClass()) return false; + MustacheEnum that = (MustacheEnum) obj; + return className != null && className.equals(that.className); + } + + @Override + public int hashCode() { + return className != null ? className.hashCode() : 0; + } +} + +/* +# Fetching class name for enum +Example1: +--------- +- in: query + name: PauseBehaviorMethod + required: true + schema: + type: string + enum: + - Trial + - Full + +name = PascalCase(codegenParameter.baseName) + +Example2: +--------- +- in: header + name: X-Twilio-Webhook-Enabled + schema: + type: string + $ref: '#/components/schemas/account_enum_X_Twilio_Webhook_Enabled' + + + + +Example3: this is passed as property (parameter.items --> codegenProperty) +--------- +- in: header + name: DummyStatus + required: true + schema: + type: array + items: + $ref: '#/components/schemas/test_enum_status' +SplitEnum(codegenProperty.datatypeWithEnum) + +Example4: +--------- +- in: header + name: SomeStatus + required: true + schema: + type: array + items: + type: string + enum: + - active + - inactive + - pending + +PascalCase(codegenParameter.baseName) + */ diff --git a/src/main/java/com/twilio/oai/java/nestedmodels/MustacheModel.java b/src/main/java/com/twilio/oai/java/nestedmodels/MustacheModel.java new file mode 100644 index 000000000..c64507ada --- /dev/null +++ b/src/main/java/com/twilio/oai/java/nestedmodels/MustacheModel.java @@ -0,0 +1,4 @@ +package com.twilio.oai.java.nestedmodels; + +public class MustacheModel { +} diff --git a/src/main/java/com/twilio/oai/java/processor/enums/EnumProcessor.java b/src/main/java/com/twilio/oai/java/processor/enums/EnumProcessor.java new file mode 100644 index 000000000..d1d8db015 --- /dev/null +++ b/src/main/java/com/twilio/oai/java/processor/enums/EnumProcessor.java @@ -0,0 +1,9 @@ +package com.twilio.oai.java.processor.enums; + +import com.twilio.oai.common.EnumConstants.OpenApiEnumType; + +public interface EnumProcessor { + boolean shouldProcess(T schema); + void process(T schema); + OpenApiEnumType getType(); +} diff --git a/src/main/java/com/twilio/oai/java/processor/enums/parameter/ParameterEnumProcessor.java b/src/main/java/com/twilio/oai/java/processor/enums/parameter/ParameterEnumProcessor.java new file mode 100644 index 000000000..78c069bcc --- /dev/null +++ b/src/main/java/com/twilio/oai/java/processor/enums/parameter/ParameterEnumProcessor.java @@ -0,0 +1,7 @@ +package com.twilio.oai.java.processor.enums.parameter; + +import com.twilio.oai.java.processor.enums.EnumProcessor; +import org.openapitools.codegen.CodegenParameter; + +public interface ParameterEnumProcessor extends EnumProcessor { +} diff --git a/src/main/java/com/twilio/oai/java/processor/enums/parameter/ParameterEnumProcessorFactory.java b/src/main/java/com/twilio/oai/java/processor/enums/parameter/ParameterEnumProcessorFactory.java new file mode 100644 index 000000000..c77d4560a --- /dev/null +++ b/src/main/java/com/twilio/oai/java/processor/enums/parameter/ParameterEnumProcessorFactory.java @@ -0,0 +1,43 @@ +package com.twilio.oai.java.processor.enums.parameter; + +import com.twilio.oai.java.processor.enums.parameter.body.InlineBodyEnumProcessor; +import com.twilio.oai.java.processor.enums.parameter.body.InlineBodyListEnumProcessor; +import com.twilio.oai.java.processor.enums.parameter.body.ReusableBodyEnumProcessor; +import com.twilio.oai.java.processor.enums.parameter.body.ReusableBodyListEnumProcessor; +import com.twilio.oai.java.processor.enums.parameter.param.InlineListParamEnumProcessor; +import com.twilio.oai.java.processor.enums.parameter.param.InlineParamEnumProcessor; +import com.twilio.oai.java.processor.enums.parameter.param.ReusableListParamEnumProcessor; +import com.twilio.oai.java.processor.enums.parameter.param.ReusableParamEnumProcessor; +import org.openapitools.codegen.CodegenParameter; + +import java.util.List; + +public class ParameterEnumProcessorFactory { + private final List processors; + + public ParameterEnumProcessorFactory(final List processors) { + this.processors = List.of( + new InlineBodyEnumProcessor(), + new InlineBodyListEnumProcessor(), + new ReusableBodyEnumProcessor(), + new ReusableBodyListEnumProcessor(), + + new InlineListParamEnumProcessor(), + new InlineParamEnumProcessor(), + new ReusableListParamEnumProcessor(), + new ReusableParamEnumProcessor() + ); + } + + public void applyProcessor(CodegenParameter codegenParameter) { + if (codegenParameter.dataFormat != null && codegenParameter.dataFormat.equals("http-method")) { + return; + } + for (ParameterEnumProcessor parameterEnumProcessor: processors) { + if (parameterEnumProcessor.shouldProcess(codegenParameter)) { + parameterEnumProcessor.process(codegenParameter); + return; // Exit after the first processor that applies + } + } + } +} diff --git a/src/main/java/com/twilio/oai/java/processor/enums/parameter/body/InlineBodyEnumProcessor.java b/src/main/java/com/twilio/oai/java/processor/enums/parameter/body/InlineBodyEnumProcessor.java new file mode 100644 index 000000000..5a770036b --- /dev/null +++ b/src/main/java/com/twilio/oai/java/processor/enums/parameter/body/InlineBodyEnumProcessor.java @@ -0,0 +1,74 @@ +package com.twilio.oai.java.processor.enums.parameter.body; + +import com.twilio.oai.common.EnumConstants; +import com.twilio.oai.common.StringUtils; +import com.twilio.oai.java.nestedmodels.MustacheEnum; +import com.twilio.oai.java.processor.enums.parameter.ParameterEnumProcessor; +import com.twilio.oai.modern.ResourceCache; +import org.openapitools.codegen.CodegenParameter; + +import java.util.List; +import java.util.Map; + +import static com.twilio.oai.common.ApplicationConstants.DOT; +import static com.twilio.oai.common.ApplicationConstants.X_DATATYPE; +import static com.twilio.oai.common.ApplicationConstants.X_ENUM_TYPE; +import static com.twilio.oai.common.ApplicationConstants.X_VARIABLE_NAME; + +/* + application/x-www-form-urlencoded: + schema: + type: object + properties: + # PROPERTY_SINGLE + singleBody: + type: string + enum: + - available + - pending + - sold + */ +// Renamed from FormParamInlineStrategy +public class InlineBodyEnumProcessor implements ParameterEnumProcessor { + @Override + public boolean shouldProcess(CodegenParameter codegenParameter) { + if (codegenParameter.getSchema() != null) return false; + if (codegenParameter._enum != null && codegenParameter.isEnum && !codegenParameter.isContainer) { + return true; + } + return false; + } + + @Override + public void process(CodegenParameter codegenParameter) { + if (!shouldProcess(codegenParameter)) return; + type(codegenParameter); + variableName(codegenParameter); + datatype(codegenParameter); + cacheEnumClass(codegenParameter); + } + + @Override + public EnumConstants.OpenApiEnumType getType() { + return null; + } + + + private void type(CodegenParameter codegenParameter) { + codegenParameter.vendorExtensions.put(X_ENUM_TYPE, EnumConstants.OpenApiEnumType.FORM_PARAM_INLINE); + } + private void variableName(CodegenParameter codegenParameter) { + codegenParameter.vendorExtensions.put(X_VARIABLE_NAME, StringUtils.toCamelCase(codegenParameter.baseName)); + } + private void datatype(CodegenParameter codegenParameter) { + codegenParameter.vendorExtensions.put(X_DATATYPE, + ResourceCache.getResourceName() + DOT + StringUtils.toPascalCase(codegenParameter.baseName)); + } + + private void cacheEnumClass(CodegenParameter codegenParameter) { + List> enumValues = (List>) codegenParameter.allowableValues.get("enumVars"); + + MustacheEnum mustacheEnum = new MustacheEnum(StringUtils.toPascalCase(codegenParameter.baseName), enumValues); + ResourceCache.addToEnumClasses(mustacheEnum); + } +} diff --git a/src/main/java/com/twilio/oai/java/processor/enums/parameter/body/InlineBodyListEnumProcessor.java b/src/main/java/com/twilio/oai/java/processor/enums/parameter/body/InlineBodyListEnumProcessor.java new file mode 100644 index 000000000..602734f0e --- /dev/null +++ b/src/main/java/com/twilio/oai/java/processor/enums/parameter/body/InlineBodyListEnumProcessor.java @@ -0,0 +1,81 @@ +package com.twilio.oai.java.processor.enums.parameter.body; + +import com.twilio.oai.common.EnumConstants; +import com.twilio.oai.common.StringUtils; +import com.twilio.oai.common.Utility; +import com.twilio.oai.java.nestedmodels.MustacheEnum; +import com.twilio.oai.java.processor.enums.parameter.ParameterEnumProcessor; +import com.twilio.oai.modern.ResourceCache; +import org.openapitools.codegen.CodegenParameter; + +import java.util.List; +import java.util.Map; + +import static com.twilio.oai.common.ApplicationConstants.DOT; +import static com.twilio.oai.common.ApplicationConstants.X_DATATYPE; +import static com.twilio.oai.common.ApplicationConstants.X_ENUM_TYPE; +import static com.twilio.oai.common.ApplicationConstants.X_VARIABLE_NAME; + +/* + application/x-www-form-urlencoded: + schema: + type: object + properties: + # PROPERTY_ARRAY + singleBodyArray: + type: array + items: + type: string + enum: [ new, sale, featured ] + description: An array of enum values in the request body + example: [ new, featured ] + */ +public class InlineBodyListEnumProcessor implements ParameterEnumProcessor { + private final EnumConstants.OpenApiEnumType type = EnumConstants.OpenApiEnumType.FORM_PARAM_LIST_INLINE; + @Override + public boolean shouldProcess(CodegenParameter codegenParameter) { + if (codegenParameter.getSchema() != null) return false; + if (codegenParameter.items != null && codegenParameter.items._enum != null && codegenParameter.isEnum) { + return true; + } + return false; + } + + @Override + public void process(CodegenParameter codegenParameter) { + if (!shouldProcess(codegenParameter)) return; + type(codegenParameter); + variableName(codegenParameter); + datatype(codegenParameter); + cacheEnumClass(codegenParameter); + } + + @Override + public EnumConstants.OpenApiEnumType getType() { + return type; + } + + private void type(CodegenParameter codegenParameter) { + codegenParameter.vendorExtensions.put(X_ENUM_TYPE, EnumConstants.OpenApiEnumType.FORM_PARAM_INLINE); + } + private void variableName(CodegenParameter codegenParameter) { + codegenParameter.vendorExtensions.put(X_VARIABLE_NAME, StringUtils.toCamelCase(codegenParameter.baseName)); + } + private void datatype(CodegenParameter codegenParameter) { + // codegenParameter.dataType = List + // enumExistingDatatype = String + String enumExistingDatatype = Utility.extractDatatypeFromContainer(codegenParameter.dataType); + String enumClassName = StringUtils.toPascalCase(codegenParameter.baseName); + String enumNonContainerDatatype = ResourceCache.getResourceName() + DOT + enumClassName; + String resolvedDataType = Utility.replaceDatatypeInContainer(codegenParameter.dataType, enumNonContainerDatatype); + codegenParameter.vendorExtensions.put(X_DATATYPE, resolvedDataType); + } + + private void cacheEnumClass(CodegenParameter codegenParameter) { + String enumClassName = StringUtils.toPascalCase(codegenParameter.baseName); + List> enumValues = (List>) codegenParameter.allowableValues.get("enumVars"); + + MustacheEnum mustacheEnum = new MustacheEnum(enumClassName, enumValues); + ResourceCache.addToEnumClasses(mustacheEnum); + } +} diff --git a/src/main/java/com/twilio/oai/java/processor/enums/parameter/body/ReusableBodyEnumProcessor.java b/src/main/java/com/twilio/oai/java/processor/enums/parameter/body/ReusableBodyEnumProcessor.java new file mode 100644 index 000000000..c6bba7f27 --- /dev/null +++ b/src/main/java/com/twilio/oai/java/processor/enums/parameter/body/ReusableBodyEnumProcessor.java @@ -0,0 +1,73 @@ +package com.twilio.oai.java.processor.enums.parameter.body; + +import com.twilio.oai.common.EnumConstants; +import com.twilio.oai.common.StringUtils; +import com.twilio.oai.common.Utility; +import com.twilio.oai.java.nestedmodels.MustacheEnum; +import com.twilio.oai.java.processor.enums.parameter.ParameterEnumProcessor; +import com.twilio.oai.modern.ResourceCache; +import org.openapitools.codegen.CodegenParameter; + +import java.util.List; +import java.util.Map; + +import static com.twilio.oai.common.ApplicationConstants.DOT; +import static com.twilio.oai.common.ApplicationConstants.X_DATATYPE; +import static com.twilio.oai.common.ApplicationConstants.X_ENUM_TYPE; +import static com.twilio.oai.common.ApplicationConstants.X_VARIABLE_NAME; + +/* + application/x-www-form-urlencoded: + schema: + type: object + properties: + # REUSABLE_SINGLE + singleBodyRef: + $ref: '#/components/schemas/singleReusable' + description: A reusable single-value enum in the request body + */ +public class ReusableBodyEnumProcessor implements ParameterEnumProcessor { + private final EnumConstants.OpenApiEnumType type = EnumConstants.OpenApiEnumType.FORM_PARAM_REF; + @Override + public boolean shouldProcess(CodegenParameter codegenParameter) { + if (codegenParameter.getSchema() != null) return false; + if (!codegenParameter.isEnum && codegenParameter.isEnumRef) { + return true; + } + return false; + } + + @Override + public void process(CodegenParameter codegenParameter) { + if (!shouldProcess(codegenParameter)) return; + type(codegenParameter); + variableName(codegenParameter); + datatype(codegenParameter); + cacheEnumClass(codegenParameter); + } + + @Override + public EnumConstants.OpenApiEnumType getType() { + return type; + } + + private void type(CodegenParameter codegenParameter) { + codegenParameter.vendorExtensions.put(X_ENUM_TYPE, EnumConstants.OpenApiEnumType.FORM_PARAM_REF); + } + private void variableName(CodegenParameter codegenParameter) { + codegenParameter.vendorExtensions.put(X_VARIABLE_NAME, StringUtils.toCamelCase(codegenParameter.baseName)); + } + private void datatype(CodegenParameter codegenParameter) { + String enumDatatypeResolved = StringUtils.toPascalCase(Utility.getEnumNameFromDefaultDatatype(codegenParameter.dataType)); + codegenParameter.vendorExtensions.put(X_DATATYPE, ResourceCache.getResourceName() + DOT + enumDatatypeResolved); + } + + private void cacheEnumClass(CodegenParameter codegenParameter) { + // TODO: Best way to store = codegenParameter.allowableValues.get("enumVars") + String enumClassName = StringUtils.toPascalCase(Utility.getEnumNameFromDefaultDatatype(codegenParameter.dataType)); + List> enumValues = (List>) codegenParameter.allowableValues.get("enumVars"); + + MustacheEnum mustacheEnum = new MustacheEnum(enumClassName, enumValues); + ResourceCache.addToEnumClasses(mustacheEnum); + } +} diff --git a/src/main/java/com/twilio/oai/java/processor/enums/parameter/body/ReusableBodyListEnumProcessor.java b/src/main/java/com/twilio/oai/java/processor/enums/parameter/body/ReusableBodyListEnumProcessor.java new file mode 100644 index 000000000..cd7037eaf --- /dev/null +++ b/src/main/java/com/twilio/oai/java/processor/enums/parameter/body/ReusableBodyListEnumProcessor.java @@ -0,0 +1,106 @@ +package com.twilio.oai.java.processor.enums.parameter.body; + +import com.twilio.oai.common.EnumConstants; +import com.twilio.oai.common.StringUtils; +import com.twilio.oai.common.Utility; +import com.twilio.oai.java.nestedmodels.MustacheEnum; +import com.twilio.oai.java.processor.enums.parameter.ParameterEnumProcessor; +import com.twilio.oai.modern.ResourceCache; +import org.openapitools.codegen.CodegenModel; +import org.openapitools.codegen.CodegenParameter; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import static com.twilio.oai.common.ApplicationConstants.DOT; +import static com.twilio.oai.common.ApplicationConstants.X_DATATYPE; +import static com.twilio.oai.common.ApplicationConstants.X_ENUM_TYPE; +import static com.twilio.oai.common.ApplicationConstants.X_VARIABLE_NAME; + +/* + application/x-www-form-urlencoded: + schema: + type: object + properties: + # REUSABLE_ARRAY + singleBodyRefArray: + type: array + items: + $ref: '#/components/schemas/singleReusable' + description: An array of reusable enum in the request body + example: [ electronics, clothing ] + */ +// renamed from FormParamListRefStrategy +public class ReusableBodyListEnumProcessor implements ParameterEnumProcessor { + private final EnumConstants.OpenApiEnumType type = EnumConstants.OpenApiEnumType.FORM_PARAM_LIST_REF; + @Override + public boolean shouldProcess(CodegenParameter codegenParameter) { + if (codegenParameter.getSchema() != null) return false; + if (codegenParameter.items != null && codegenParameter.items.isEnumRef && !codegenParameter.items.isEnum) { + return true; + } + return false; + } + + @Override + public void process(CodegenParameter codegenParameter) { + if (!shouldProcess(codegenParameter)) return; + type(codegenParameter); + variableName(codegenParameter); + datatype(codegenParameter); + cacheEnumClass(codegenParameter); + } + + @Override + public EnumConstants.OpenApiEnumType getType() { + return type; + } + + private void type(CodegenParameter codegenParameter) { + codegenParameter.vendorExtensions.put(X_ENUM_TYPE, EnumConstants.OpenApiEnumType.FORM_PARAM_LIST_REF); + } + private void variableName(CodegenParameter codegenParameter) { + codegenParameter.vendorExtensions.put(X_VARIABLE_NAME, StringUtils.toCamelCase(codegenParameter.baseName)); + } + private void datatype(CodegenParameter codegenParameter) { + // codegenParameter.dataType = List + // enumExistingDatatype = AccountEnumStatus + String enumExistingDatatype = Utility.extractDatatypeFromContainer(codegenParameter.dataType); + // enumClassName = Status + String enumClassName = Utility.getEnumNameFromDatatype(enumExistingDatatype); + // enumNonContainerDatatype = Account.Status + String enumNonContainerDatatype = ResourceCache.getResourceName() + DOT + StringUtils.toPascalCase(enumClassName); + // resolvedDataType = List + String resolvedDataType = Utility.replaceDatatypeInContainer(codegenParameter.dataType, enumNonContainerDatatype); + codegenParameter.vendorExtensions.put(X_DATATYPE, resolvedDataType); + } + + private void cacheEnumClass(CodegenParameter codegenParameter) { + String baseDataType = Utility.extractDatatypeFromContainer(codegenParameter.dataType); + if (baseDataType == null) { + throw new RuntimeException("Not able to fetch enum baseType for List Enum with ref" + " DataType: " +codegenParameter.dataType); + } + String enumClassName = Utility.getEnumNameFromDatatype(baseDataType); + if (enumClassName == null) { + throw new RuntimeException("Not able to fetch enum class name from baseDataType for List Enum with ref" + + "baseType:"+ baseDataType + " DataType: " + codegenParameter.dataType); + } + + Map values = null; + List> enumValues = new ArrayList<>(); + + for (CodegenModel codegenModel: ResourceCache.getAllModelsByDefaultGenerator()) { + if (baseDataType.equals(codegenModel.classname)) { + values = codegenModel.allowableValues; + enumValues = (List>) codegenModel.allowableValues.get("enumVars"); + break; + } + } + if (enumValues == null || enumValues.isEmpty()) { + throw new RuntimeException("No enum values found for Enum" + " DataType: " +codegenParameter.dataType); + } + MustacheEnum mustacheEnum = new MustacheEnum(enumClassName, enumValues); + ResourceCache.addToEnumClasses(mustacheEnum); + } +} diff --git a/src/main/java/com/twilio/oai/java/processor/enums/parameter/param/InlineListParamEnumProcessor.java b/src/main/java/com/twilio/oai/java/processor/enums/parameter/param/InlineListParamEnumProcessor.java new file mode 100644 index 000000000..5eadec69b --- /dev/null +++ b/src/main/java/com/twilio/oai/java/processor/enums/parameter/param/InlineListParamEnumProcessor.java @@ -0,0 +1,81 @@ +package com.twilio.oai.java.processor.enums.parameter.param; + +import com.twilio.oai.common.EnumConstants.OpenApiEnumType; +import com.twilio.oai.common.StringUtils; +import com.twilio.oai.common.Utility; +import com.twilio.oai.java.nestedmodels.MustacheEnum; +import com.twilio.oai.java.processor.enums.parameter.ParameterEnumProcessor; +import com.twilio.oai.modern.ResourceCache; +import org.openapitools.codegen.CodegenParameter; + +import java.util.List; +import java.util.Map; + +import static com.twilio.oai.common.ApplicationConstants.DOT; +import static com.twilio.oai.common.ApplicationConstants.X_DATATYPE; +import static com.twilio.oai.common.ApplicationConstants.X_ENUM_TYPE; +import static com.twilio.oai.common.ApplicationConstants.X_VARIABLE_NAME; + +/* + Example: + - name: arrayParam + in: query + description: Order items using an array of enums + required: false + schema: + type: array + items: + type: string + enum: + - asc + - desc + example: [asc] + */ +public class InlineListParamEnumProcessor implements ParameterEnumProcessor { + + private final OpenApiEnumType type = OpenApiEnumType.PARAMETER_LIST_INLINE; + + @Override + public boolean shouldProcess(CodegenParameter codegenParameter) { + if (codegenParameter.getSchema() == null) return false; + if (codegenParameter.getSchema()._enum == null && + codegenParameter.getSchema().items != null && codegenParameter.getSchema().items._enum != null) { + return true; + } + return false; + } + + @Override + public void process(final CodegenParameter codegenParameter) { + if (!shouldProcess(codegenParameter)) return; + type(codegenParameter); + variableName(codegenParameter); + datatype(codegenParameter); + cacheEnumClass(codegenParameter); + } + + @Override + public OpenApiEnumType getType() { + return type; + } + + private void type(CodegenParameter codegenParameter) { + codegenParameter.vendorExtensions.put(X_ENUM_TYPE, OpenApiEnumType.PARAMETER_LIST_INLINE); + } + private void variableName(CodegenParameter codegenParameter) { + codegenParameter.vendorExtensions.put(X_VARIABLE_NAME, StringUtils.toCamelCase(codegenParameter.baseName)); + } + private void datatype(CodegenParameter codegenParameter) { + String enumClassName = StringUtils.toPascalCase(codegenParameter.baseName); + String enumNonContainerDatatype = ResourceCache.getResourceName() + DOT + StringUtils.toPascalCase(enumClassName); + String resolvedDataType = Utility.replaceDatatypeInContainer(codegenParameter.dataType, enumNonContainerDatatype); + codegenParameter.vendorExtensions.put(X_DATATYPE, resolvedDataType); + } + + private void cacheEnumClass(CodegenParameter codegenParameter) { + List> enumValues = (List>) codegenParameter.allowableValues.get("enumVars"); + + MustacheEnum mustacheEnum = new MustacheEnum( StringUtils.toPascalCase(codegenParameter.baseName), enumValues); + ResourceCache.addToEnumClasses(mustacheEnum); + } +} diff --git a/src/main/java/com/twilio/oai/java/processor/enums/parameter/param/InlineParamEnumProcessor.java b/src/main/java/com/twilio/oai/java/processor/enums/parameter/param/InlineParamEnumProcessor.java new file mode 100644 index 000000000..055e968e3 --- /dev/null +++ b/src/main/java/com/twilio/oai/java/processor/enums/parameter/param/InlineParamEnumProcessor.java @@ -0,0 +1,73 @@ +package com.twilio.oai.java.processor.enums.parameter.param; + +import com.twilio.oai.common.EnumConstants.OpenApiEnumType; +import com.twilio.oai.common.StringUtils; +import com.twilio.oai.java.nestedmodels.MustacheEnum; +import com.twilio.oai.java.processor.enums.parameter.ParameterEnumProcessor; +import com.twilio.oai.modern.ResourceCache; +import org.openapitools.codegen.CodegenParameter; + +import java.util.List; +import java.util.Map; + +import static com.twilio.oai.common.ApplicationConstants.DOT; +import static com.twilio.oai.common.ApplicationConstants.X_DATATYPE; +import static com.twilio.oai.common.ApplicationConstants.X_ENUM_TYPE; +import static com.twilio.oai.common.ApplicationConstants.X_VARIABLE_NAME; + +/* + - name: singleParam + in: query + description: A single enum value as a query parameter + required: false + schema: + type: string + enum: + - asc + - desc + example: asc + */ +public class InlineParamEnumProcessor implements ParameterEnumProcessor { + + private final OpenApiEnumType type = OpenApiEnumType.PARAMETER_INLINE; + + @Override + public void process(final CodegenParameter codegenParameter) { + if (!shouldProcess(codegenParameter)) return; + type(codegenParameter); + variableName(codegenParameter); + datatype(codegenParameter); + cacheEnumClass(codegenParameter); + } + + @Override + public OpenApiEnumType getType() { + return type; + } + + @Override + public boolean shouldProcess(CodegenParameter codegenParameter) { + if (codegenParameter.getSchema() == null) return false; + if (codegenParameter.getSchema()._enum != null && codegenParameter.isEnum) { + return true; + } + return false; + } + + private void type(CodegenParameter codegenParameter) { + codegenParameter.vendorExtensions.put(X_ENUM_TYPE, type); + } + private void variableName(CodegenParameter codegenParameter) { + codegenParameter.vendorExtensions.put(X_VARIABLE_NAME, StringUtils.toCamelCase(codegenParameter.baseName)); + } + private void datatype(CodegenParameter codegenParameter) { + codegenParameter.vendorExtensions.put(X_DATATYPE, + ResourceCache.getResourceName() + DOT + StringUtils.toPascalCase(codegenParameter.baseName)); + } + + private void cacheEnumClass(CodegenParameter codegenParameter) { + List> enumValues = (List>) codegenParameter.allowableValues.get("enumVars"); + MustacheEnum mustacheEnum = new MustacheEnum(StringUtils.toPascalCase(codegenParameter.baseName), enumValues); + ResourceCache.addToEnumClasses(mustacheEnum); + } +} diff --git a/src/main/java/com/twilio/oai/java/processor/enums/parameter/param/ReusableListParamEnumProcessor.java b/src/main/java/com/twilio/oai/java/processor/enums/parameter/param/ReusableListParamEnumProcessor.java new file mode 100644 index 000000000..21cb71b17 --- /dev/null +++ b/src/main/java/com/twilio/oai/java/processor/enums/parameter/param/ReusableListParamEnumProcessor.java @@ -0,0 +1,81 @@ +package com.twilio.oai.java.processor.enums.parameter.param; + +import com.twilio.oai.common.EnumConstants.OpenApiEnumType; +import com.twilio.oai.common.StringUtils; +import com.twilio.oai.common.Utility; +import com.twilio.oai.java.nestedmodels.MustacheEnum; +import com.twilio.oai.java.processor.enums.parameter.ParameterEnumProcessor; +import com.twilio.oai.modern.ResourceCache; +import org.openapitools.codegen.CodegenParameter; + +import java.util.List; +import java.util.Map; + +import static com.twilio.oai.common.ApplicationConstants.DOT; +import static com.twilio.oai.common.ApplicationConstants.X_DATATYPE; +import static com.twilio.oai.common.ApplicationConstants.X_ENUM_TYPE; +import static com.twilio.oai.common.ApplicationConstants.X_VARIABLE_NAME; + +/* + - name: arrayParamRef + in: query + required: false + description: An array parameter referencing a reusable schema + schema: + type: array + items: + $ref: '#/components/schemas/singleReusable' + */ +public class ReusableListParamEnumProcessor implements ParameterEnumProcessor { + + private final OpenApiEnumType type = OpenApiEnumType.PARAMETER_LIST_REF; + + @Override + public void process(final CodegenParameter codegenParameter) { + if (!shouldProcess(codegenParameter)) return; + type(codegenParameter); + variableName(codegenParameter); + datatype(codegenParameter); + cacheEnumClass(codegenParameter); + } + + @Override + public OpenApiEnumType getType() { + return type; + } + + @Override + public boolean shouldProcess(CodegenParameter codegenParameter) { + if (codegenParameter.getSchema() == null) return false; + if (codegenParameter.getSchema().items != null && codegenParameter.getSchema().items.getRef() != null + && codegenParameter.getSchema().items.isEnumRef) { + return true; + } + return false; + } + + private void type(CodegenParameter codegenParameter) { + codegenParameter.vendorExtensions.put(X_ENUM_TYPE, OpenApiEnumType.PARAMETER_LIST_REF); + } + private void variableName(CodegenParameter codegenParameter) { + codegenParameter.vendorExtensions.put(X_VARIABLE_NAME, StringUtils.toCamelCase(codegenParameter.baseName)); + } + private void datatype(CodegenParameter codegenParameter) { + // #/components/schemas/singleReusable or #/components/schemas/content_enum_single_reusable + // enumRefResolved = singleReusable + String enumRefResolved = Utility.getEnumNameFromRef(codegenParameter.getSchema().items.getRef()); + // enumNonContainerDatatype = Content.SingleReusable + String enumNonContainerDatatype = ResourceCache.getResourceName() + DOT + StringUtils.toPascalCase(enumRefResolved); + // resolvedDataType = List + String resolvedDataType = Utility.replaceDatatypeInContainer(codegenParameter.dataType, enumNonContainerDatatype); + codegenParameter.vendorExtensions.put(X_DATATYPE, resolvedDataType); + } + + private void cacheEnumClass(CodegenParameter codegenParameter) { + List> enumValues = (List>) codegenParameter.getSchema().items.allowableValues.get("enumVars"); + + MustacheEnum mustacheEnum = new MustacheEnum(StringUtils.toPascalCase( + Utility.getEnumNameFromRef(codegenParameter.getSchema().items.getRef())), enumValues); + ResourceCache.addToEnumClasses(mustacheEnum); + } +} diff --git a/src/main/java/com/twilio/oai/java/processor/enums/parameter/param/ReusableParamEnumProcessor.java b/src/main/java/com/twilio/oai/java/processor/enums/parameter/param/ReusableParamEnumProcessor.java new file mode 100644 index 000000000..9cb85fdc7 --- /dev/null +++ b/src/main/java/com/twilio/oai/java/processor/enums/parameter/param/ReusableParamEnumProcessor.java @@ -0,0 +1,68 @@ +package com.twilio.oai.java.processor.enums.parameter.param; + +import com.twilio.oai.common.EnumConstants.OpenApiEnumType; +import com.twilio.oai.common.StringUtils; +import com.twilio.oai.common.Utility; +import com.twilio.oai.java.nestedmodels.MustacheEnum; +import com.twilio.oai.java.processor.enums.parameter.ParameterEnumProcessor; +import com.twilio.oai.modern.ResourceCache; +import org.openapitools.codegen.CodegenParameter; + +import java.util.List; +import java.util.Map; + +import static com.twilio.oai.common.ApplicationConstants.DOT; +import static com.twilio.oai.common.ApplicationConstants.X_DATATYPE; +import static com.twilio.oai.common.ApplicationConstants.X_ENUM_TYPE; +import static com.twilio.oai.common.ApplicationConstants.X_VARIABLE_NAME; + +/* + - name: singleParamRef + in: header + schema: + $ref: '#/components/schemas/singleReusable' + */ +public class ReusableParamEnumProcessor implements ParameterEnumProcessor { + private final OpenApiEnumType type = OpenApiEnumType.PARAMETER_REF; + @Override + public void process(final CodegenParameter codegenParameter) { + if (!shouldProcess(codegenParameter)) return; + type(codegenParameter); + variableName(codegenParameter); + datatype(codegenParameter); + cacheEnumClass(codegenParameter); + } + + @Override + public OpenApiEnumType getType() { + return type; + } + + @Override + public boolean shouldProcess(CodegenParameter codegenParameter) { + if (codegenParameter.getSchema() == null) return false; + if (codegenParameter.getSchema().getRef() != null && codegenParameter.isEnumRef) { + return true; + } + return false; + } + + private void type(CodegenParameter codegenParameter) { + codegenParameter.vendorExtensions.put(X_ENUM_TYPE, OpenApiEnumType.PARAMETER_REF); + } + private void variableName(CodegenParameter codegenParameter) { + codegenParameter.vendorExtensions.put(X_VARIABLE_NAME, StringUtils.toCamelCase(codegenParameter.baseName)); + } + private void datatype(CodegenParameter codegenParameter) { + String enumRefResolved = Utility.getEnumNameFromRef(codegenParameter.getSchema().getRef()); + codegenParameter.vendorExtensions.put(X_DATATYPE, + ResourceCache.getResourceName() + DOT + StringUtils.toPascalCase(enumRefResolved)); + } + + private void cacheEnumClass(CodegenParameter codegenParameter) { + List> enumValues = (List>) codegenParameter.allowableValues.get("enumVars"); + MustacheEnum mustacheEnum = new MustacheEnum(StringUtils.toPascalCase( + Utility.getEnumNameFromRef(codegenParameter.getSchema().getRef())), enumValues); + ResourceCache.addToEnumClasses(mustacheEnum); + } +} diff --git a/src/main/java/com/twilio/oai/java/processor/enums/property/InlineListPropEnumProcessor.java b/src/main/java/com/twilio/oai/java/processor/enums/property/InlineListPropEnumProcessor.java new file mode 100644 index 000000000..77c2e9bd9 --- /dev/null +++ b/src/main/java/com/twilio/oai/java/processor/enums/property/InlineListPropEnumProcessor.java @@ -0,0 +1,61 @@ +package com.twilio.oai.java.processor.enums.property; + +import com.twilio.oai.common.EnumConstants.OpenApiEnumType; +import com.twilio.oai.common.StringUtils; +import com.twilio.oai.common.Utility; +import com.twilio.oai.java.nestedmodels.MustacheEnum; +import com.twilio.oai.modern.ResourceCache; +import org.openapitools.codegen.CodegenProperty; + +import java.util.List; +import java.util.Map; + +import static com.twilio.oai.common.ApplicationConstants.DOT; +import static com.twilio.oai.common.ApplicationConstants.X_DATATYPE; +import static com.twilio.oai.common.ApplicationConstants.X_ENUM_TYPE; +import static com.twilio.oai.common.ApplicationConstants.X_VARIABLE_NAME; + +public class InlineListPropEnumProcessor implements PropertyEnumProcessor { + private final OpenApiEnumType type = OpenApiEnumType.PROPERTY_LIST; + + @Override + public void process(final CodegenProperty codegenProperty) { + if (!shouldProcess(codegenProperty)) return; + type(codegenProperty); + variableName(codegenProperty); + datatype(codegenProperty); + cacheEnumClass(codegenProperty); + } + + public boolean shouldProcess(CodegenProperty codegenProperty) { + if (codegenProperty.isEnum && !codegenProperty.isEnumRef && codegenProperty.items != null && codegenProperty.items.get_enum() != null) { + return true; + } + return false; + } + + @Override + public OpenApiEnumType getType() { + // Return the type of enum this strategy identifies + return type; + } + + private void type(CodegenProperty codegenProperty) { + codegenProperty.vendorExtensions.put(X_ENUM_TYPE, type); + } + private void variableName(CodegenProperty codegenProperty) { + codegenProperty.vendorExtensions.put(X_VARIABLE_NAME, StringUtils.toCamelCase(codegenProperty.baseName)); + } + private void datatype(CodegenProperty codegenProperty) { + String enumClassName = StringUtils.toPascalCase(codegenProperty.baseName); + String enumNonContainerDatatype = ResourceCache.getResourceName() + DOT + StringUtils.toPascalCase(enumClassName); + String resolvedDataType = Utility.replaceDatatypeInContainer(codegenProperty.dataType, enumNonContainerDatatype); + codegenProperty.vendorExtensions.put(X_DATATYPE, resolvedDataType); + } + + private void cacheEnumClass(CodegenProperty codegenProperty) { + List> enumValues = (List>) codegenProperty.allowableValues.get("enumVars"); + MustacheEnum mustacheEnum = new MustacheEnum(StringUtils.toPascalCase(codegenProperty.baseName), enumValues); + ResourceCache.addToEnumClasses(mustacheEnum); + } +} diff --git a/src/main/java/com/twilio/oai/java/processor/enums/property/InlinePropEnumProcessor.java b/src/main/java/com/twilio/oai/java/processor/enums/property/InlinePropEnumProcessor.java new file mode 100644 index 000000000..e7556a207 --- /dev/null +++ b/src/main/java/com/twilio/oai/java/processor/enums/property/InlinePropEnumProcessor.java @@ -0,0 +1,72 @@ +package com.twilio.oai.java.processor.enums.property; + +import com.twilio.oai.StringHelper; +import com.twilio.oai.common.EnumConstants.OpenApiEnumType; +import com.twilio.oai.common.StringUtils; +import com.twilio.oai.java.nestedmodels.MustacheEnum; +import com.twilio.oai.modern.ResourceCache; +import org.openapitools.codegen.CodegenProperty; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static com.twilio.oai.common.ApplicationConstants.DOT; +import static com.twilio.oai.common.ApplicationConstants.X_DATATYPE; +import static com.twilio.oai.common.ApplicationConstants.X_ENUM_TYPE; +import static com.twilio.oai.common.ApplicationConstants.X_VARIABLE_NAME; + +/* +codegenProperty._enum = true +codegenProperty.isEnum = true +codegenProperty.isEnumRef = true + */ +public class InlinePropEnumProcessor implements PropertyEnumProcessor { + private final OpenApiEnumType type = OpenApiEnumType.PROPERTY_INLINE; + @Override + public void process(final CodegenProperty codegenProperty) { + if (!shouldProcess(codegenProperty)) return; + type(codegenProperty); + variableName(codegenProperty); + datatype(codegenProperty); + cacheEnumClass(codegenProperty); + } + + @Override + public OpenApiEnumType getType() { + return type; + } + + @Override + public boolean shouldProcess(CodegenProperty codegenProperty) { + if (codegenProperty.isEnum && codegenProperty.isEnumRef && codegenProperty.get_enum() != null) { + return true; + } + return false; + } + + private void type(CodegenProperty codegenProperty) { + codegenProperty.vendorExtensions.put(X_ENUM_TYPE, type); + } + private void variableName(CodegenProperty codegenProperty) { + codegenProperty.vendorExtensions.put(X_VARIABLE_NAME, StringUtils.toCamelCase(codegenProperty.baseName)); + } + private void datatype(CodegenProperty codegenProperty) { + codegenProperty.vendorExtensions.put(X_DATATYPE, + ResourceCache.getResourceName() + DOT + StringUtils.toPascalCase(codegenProperty.baseName)); + } + + private void cacheEnumClass(CodegenProperty codegenProperty) { + List> enumValues = new ArrayList<>(); + + for (String s : (List) codegenProperty.allowableValues.get("values")) { + HashMap valueMap = new HashMap<>(); + valueMap.put("name", StringHelper.toSnakeCase(s).toUpperCase()); + valueMap.put("value", "\"" + s + "\""); // adding extra quote as this is how enumVars are stored + enumValues.add(valueMap); + } + MustacheEnum mustacheEnum = new MustacheEnum(StringUtils.toPascalCase(codegenProperty.baseName), enumValues); + ResourceCache.addToEnumClasses(mustacheEnum); + } +} diff --git a/src/main/java/com/twilio/oai/java/processor/enums/property/PropertyEnumProcessor.java b/src/main/java/com/twilio/oai/java/processor/enums/property/PropertyEnumProcessor.java new file mode 100644 index 000000000..3fb850182 --- /dev/null +++ b/src/main/java/com/twilio/oai/java/processor/enums/property/PropertyEnumProcessor.java @@ -0,0 +1,7 @@ +package com.twilio.oai.java.processor.enums.property; + +import com.twilio.oai.java.processor.enums.EnumProcessor; +import org.openapitools.codegen.CodegenProperty; + +public interface PropertyEnumProcessor extends EnumProcessor { +} diff --git a/src/main/java/com/twilio/oai/java/processor/enums/property/PropertyEnumProcessorFactory.java b/src/main/java/com/twilio/oai/java/processor/enums/property/PropertyEnumProcessorFactory.java new file mode 100644 index 000000000..3f8a999df --- /dev/null +++ b/src/main/java/com/twilio/oai/java/processor/enums/property/PropertyEnumProcessorFactory.java @@ -0,0 +1,30 @@ +package com.twilio.oai.java.processor.enums.property; + +import org.openapitools.codegen.CodegenProperty; + +import java.util.List; + +public class PropertyEnumProcessorFactory { + private final List processors; + + public PropertyEnumProcessorFactory(final List processors) { + this.processors = List.of( + new InlineListPropEnumProcessor(), + new InlinePropEnumProcessor(), + new ReusableListPropEnumProcessor(), + new ReusablePropEnumProcessor() + ); + } + + public void applyProcessor(CodegenProperty codegenProperty) { + if (codegenProperty.dataFormat != null && codegenProperty.dataFormat.equals("http-method")) { + return; + } + for (PropertyEnumProcessor propertyEnumProcessor: processors) { + if (propertyEnumProcessor.shouldProcess(codegenProperty)) { + propertyEnumProcessor.process(codegenProperty); + return; // Exit after the first processor that applies + } + } + } +} diff --git a/src/main/java/com/twilio/oai/java/processor/enums/property/ReusableListPropEnumProcessor.java b/src/main/java/com/twilio/oai/java/processor/enums/property/ReusableListPropEnumProcessor.java new file mode 100644 index 000000000..e8c027186 --- /dev/null +++ b/src/main/java/com/twilio/oai/java/processor/enums/property/ReusableListPropEnumProcessor.java @@ -0,0 +1,67 @@ +package com.twilio.oai.java.processor.enums.property; + +import com.twilio.oai.common.EnumConstants.OpenApiEnumType; +import com.twilio.oai.common.StringUtils; +import com.twilio.oai.common.Utility; +import com.twilio.oai.java.nestedmodels.MustacheEnum; +import com.twilio.oai.modern.ResourceCache; +import org.openapitools.codegen.CodegenProperty; + +import java.util.List; +import java.util.Map; + +import static com.twilio.oai.common.ApplicationConstants.DOT; +import static com.twilio.oai.common.ApplicationConstants.X_DATATYPE; +import static com.twilio.oai.common.ApplicationConstants.X_ENUM_TYPE; +import static com.twilio.oai.common.ApplicationConstants.X_VARIABLE_NAME; + +public class ReusableListPropEnumProcessor implements PropertyEnumProcessor { + private final OpenApiEnumType type = OpenApiEnumType.PROPERTY_INLINE; + @Override + public void process(final CodegenProperty codegenProperty) { + if (!shouldProcess(codegenProperty)) return; + type(codegenProperty); + variableName(codegenProperty); + datatype(codegenProperty); + cacheEnumClass(codegenProperty); + } + + @Override + public OpenApiEnumType getType() { + return type; + } + + @Override + public boolean shouldProcess(CodegenProperty codegenProperty) { + if (codegenProperty.items != null && codegenProperty.items.isEnumRef && !codegenProperty.items.isEnum) { + return true; + } + return false; + } + + private void type(CodegenProperty codegenProperty) { + codegenProperty.vendorExtensions.put(X_ENUM_TYPE, type); + } + private void variableName(CodegenProperty codegenProperty) { + codegenProperty.vendorExtensions.put(X_VARIABLE_NAME, StringUtils.toCamelCase(codegenProperty.baseName)); + } + private void datatype(CodegenProperty codegenProperty) { + String enumExistingDatatype = Utility.extractDatatypeFromContainer(codegenProperty.dataType); + // enumClassName = Status + String enumClassName = Utility.getEnumNameFromDatatype(enumExistingDatatype); + // enumNonContainerDatatype = Account.Status + String enumNonContainerDatatype = ResourceCache.getResourceName() + DOT + StringUtils.toPascalCase(enumClassName); + // resolvedDataType = List + String resolvedDataType = Utility.replaceDatatypeInContainer(codegenProperty.dataType, enumNonContainerDatatype); + codegenProperty.vendorExtensions.put(X_DATATYPE, resolvedDataType); + } + + private void cacheEnumClass(CodegenProperty codegenProperty) { + String enumExistingDatatype = Utility.extractDatatypeFromContainer(codegenProperty.dataType); + String enumClassName = Utility.getEnumNameFromDatatype(enumExistingDatatype); + List> enumValues = (List>) codegenProperty.items.allowableValues.get("enumVars"); + + MustacheEnum mustacheEnum = new MustacheEnum(enumClassName, enumValues); + ResourceCache.addToEnumClasses(mustacheEnum); + } +} diff --git a/src/main/java/com/twilio/oai/java/processor/enums/property/ReusablePropEnumProcessor.java b/src/main/java/com/twilio/oai/java/processor/enums/property/ReusablePropEnumProcessor.java new file mode 100644 index 000000000..1396244c7 --- /dev/null +++ b/src/main/java/com/twilio/oai/java/processor/enums/property/ReusablePropEnumProcessor.java @@ -0,0 +1,68 @@ +package com.twilio.oai.java.processor.enums.property; + +import com.twilio.oai.StringHelper; +import com.twilio.oai.common.EnumConstants.OpenApiEnumType; +import com.twilio.oai.common.StringUtils; +import com.twilio.oai.common.Utility; +import com.twilio.oai.java.nestedmodels.MustacheEnum; +import com.twilio.oai.modern.ResourceCache; +import org.openapitools.codegen.CodegenProperty; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static com.twilio.oai.common.ApplicationConstants.DOT; +import static com.twilio.oai.common.ApplicationConstants.X_DATATYPE; +import static com.twilio.oai.common.ApplicationConstants.X_ENUM_TYPE; +import static com.twilio.oai.common.ApplicationConstants.X_VARIABLE_NAME; +public class ReusablePropEnumProcessor implements PropertyEnumProcessor { + private final OpenApiEnumType type = OpenApiEnumType.PROPERTY_REF; + @Override + public void process(final CodegenProperty codegenProperty) { + if (!shouldProcess(codegenProperty)) return; + type(codegenProperty); + variableName(codegenProperty); + datatype(codegenProperty); + cacheEnumClass(codegenProperty); + } + + @Override + public OpenApiEnumType getType() { + return type; + } + + @Override + public boolean shouldProcess(CodegenProperty codegenProperty) { + if (!codegenProperty.isEnum && codegenProperty.isEnumRef && codegenProperty.getRef() != null) { + return true; + } + return false; + } + + private void type(CodegenProperty codegenProperty) { + codegenProperty.vendorExtensions.put(X_ENUM_TYPE, type); + } + private void variableName(CodegenProperty codegenProperty) { + codegenProperty.vendorExtensions.put(X_VARIABLE_NAME, StringUtils.toCamelCase(codegenProperty.baseName)); + } + private void datatype(CodegenProperty codegenProperty) { + String enumDatatypeResolved = StringUtils.toPascalCase(Utility.getEnumNameFromDefaultDatatype(codegenProperty.getRef())); + codegenProperty.vendorExtensions.put(X_DATATYPE, ResourceCache.getResourceName() + DOT + enumDatatypeResolved); + } + + private void cacheEnumClass(CodegenProperty codegenProperty) { + System.out.println(codegenProperty.baseName); + String enumClassName = Utility.getEnumNameFromRef(codegenProperty.getRef()); + List> enumValues = new ArrayList<>(); + for (String s : (List) codegenProperty.allowableValues.get("values")) { + HashMap valueMap = new HashMap<>(); + valueMap.put("name", StringHelper.toSnakeCase(s).toUpperCase()); + valueMap.put("value", "\"" + s + "\""); // adding extra quote as this is how enumVars are stored + enumValues.add(valueMap); + } + MustacheEnum mustacheEnum = new MustacheEnum(StringUtils.toPascalCase(enumClassName), enumValues); + ResourceCache.addToEnumClasses(mustacheEnum); + } +} diff --git a/src/main/java/com/twilio/oai/java/strategy/enums/parameter/EnumIdentifierHandler.java b/src/main/java/com/twilio/oai/java/strategy/enums/parameter/EnumIdentifierHandler.java new file mode 100644 index 000000000..e863a57cd --- /dev/null +++ b/src/main/java/com/twilio/oai/java/strategy/enums/parameter/EnumIdentifierHandler.java @@ -0,0 +1,291 @@ +package com.twilio.oai.java.strategy.enums.parameter; + +import com.twilio.oai.common.EnumConstants; +import com.twilio.oai.common.StringUtils; +import com.twilio.oai.common.Utility; +import com.twilio.oai.java.strategy.enums.property.InlineListPropStrategy; +import com.twilio.oai.java.strategy.enums.property.RefListPropStrategy; +import com.twilio.oai.java.strategy.enums.property.RefPropStrategy; +import com.twilio.oai.java.strategy.enums.property.InlinePropStrategy; +import com.twilio.oai.java.strategy.enums.property.PropertyEnumProcessingStrategy; +import com.twilio.oai.modern.ResourceCache; +import org.openapitools.codegen.CodegenModel; +import org.openapitools.codegen.CodegenParameter; +import org.openapitools.codegen.CodegenProperty; + +import java.util.List; + +import static com.twilio.oai.common.ApplicationConstants.X_VARIABLE_NAME; +import static com.twilio.oai.common.ApplicationConstants.X_ENUM_TYPE; +import static com.twilio.oai.common.ApplicationConstants.X_DATATYPE; +import static com.twilio.oai.common.ApplicationConstants.DOT; + +// It does not do any processing, It will just return if a passed parameter or property is an Enum +public class EnumIdentifierHandler { + private final List parameterStrategies; + + private final List propertyStrategies; + + public EnumIdentifierHandler() { + parameterStrategies = List.of( + new InlineParamStrategy(), + new RefParamStrategy(), + new InlineListParamStrategy(), + new RefListParamStrategy(), + new FormParamInlineStrategy(), + new FormParamRefStrategy(), + new FormParamListStrategy(), + new FormParamListRefStrategy() + ); + + propertyStrategies = List.of( + new InlinePropStrategy(), + new RefPropStrategy(), + new InlineListPropStrategy(), + new RefListPropStrategy() + ); + } + + public void identify(CodegenParameter codegenParameter) { + if ("http-method".equals(codegenParameter.dataFormat)) { + return; + } + for (ParameterEnumProcessingStrategy strategy : parameterStrategies) { + if (strategy.isStrategyApplicable(codegenParameter)) { + System.out.println("Strategy matched: " + strategy.getType() + " Enum Basename: " + codegenParameter.baseName); + break; + } + } + } + public boolean identify(CodegenProperty codegenProperty) { + if ("http-method".equals(codegenProperty.dataFormat)) { + return false; + } + for (PropertyEnumProcessingStrategy strategy : propertyStrategies) { + if (strategy.isStrategyApplicable(codegenProperty)) { + System.out.println("Strategy matched: " + strategy.getType() + " Enum Basename: " + codegenProperty.baseName); + return true; + } + } + return false; + } + + public void identify(CodegenModel codegenModel) { + + } + + /* + .isEnum = true + .isEnumRef = true + .schema.isEnum = true + .ref = null + .isContainer = false + .items = null + + codegenParameter.schema._enum = enum array values + */ + private boolean isParameterSingle(CodegenParameter codegenParameter) { + if (codegenParameter.getSchema()._enum != null && codegenParameter.isEnum) { + System.out.println("Identified as single parameter enum: " + codegenParameter.baseName); + codegenParameter.vendorExtensions.put(X_ENUM_TYPE, EnumConstants.OpenApiEnumType.PARAMETER_INLINE); + + // Resolve + codegenParameter.vendorExtensions.put(X_VARIABLE_NAME, StringUtils.toCamelCase(codegenParameter.baseName)); + codegenParameter.vendorExtensions.put(X_DATATYPE, + ResourceCache.getResourceName() + DOT + StringUtils.toPascalCase(codegenParameter.baseName)); + return true; + } + return false; + } + + /* + isEnum = false + isEnumRef = true + schema.isEnum = false + ref = null + isContainer = false + items = null + + + + .schema._enum = null + .schema.items = null + .schema.ref = it gives ref to the enum + */ + private boolean isParameterRef(CodegenParameter codegenParameter) { + if (codegenParameter.getSchema().getRef() != null && codegenParameter.isEnumRef) { + // Identify + System.out.println("Identified as single parameter enum ref: " + codegenParameter.baseName); + codegenParameter.vendorExtensions.put(X_ENUM_TYPE, EnumConstants.OpenApiEnumType.PARAMETER_REF); + + /* Resolve + X_NAME_NAME: variable name + + */ + codegenParameter.vendorExtensions.put(X_VARIABLE_NAME, StringUtils.toCamelCase(codegenParameter.baseName)); + String enumRefResolved = Utility.getEnumNameFromRef(codegenParameter.getSchema().getRef()); + codegenParameter.vendorExtensions.put(X_DATATYPE, + ResourceCache.getResourceName() + DOT + StringUtils.toPascalCase(enumRefResolved)); + return true; + } + return false; + } + + /* + .isEnum = true + .isEnumRef = false + .schema.isEnum = true + .ref = null + .isContainer = true + .items = not null + .schema.ref = null + .schema.items.ref = it gives ref to the item + + .schema._enum = null + .schema.items._enum = enum array values + */ + private boolean isParameterArray(CodegenParameter codegenParameter) { + if (codegenParameter.getSchema()._enum == null && + codegenParameter.getSchema().items != null && codegenParameter.getSchema().items._enum != null) { + // Identify + System.out.println("Identified as array parameter enum: " + codegenParameter.baseName); + codegenParameter.vendorExtensions.put(X_ENUM_TYPE, EnumConstants.OpenApiEnumType.PARAMETER_LIST_INLINE); + + + // Resolve + codegenParameter.vendorExtensions.put(X_VARIABLE_NAME, StringUtils.toCamelCase(codegenParameter.baseName)); + + String enumClassName = StringUtils.toPascalCase(codegenParameter.baseName); + String enumNonContainerDatatype = ResourceCache.getResourceName() + DOT + StringUtils.toPascalCase(enumClassName); + String resolvedDataType = Utility.replaceDatatypeInContainer(codegenParameter.dataType, enumNonContainerDatatype); + codegenParameter.vendorExtensions.put(X_DATATYPE, resolvedDataType); + + return true; + } + return false; + } + + /* + isEnum = false + isEnumRef = false + schema.isEnum = false + ref = null + isContainer = true + items = not null + + + .schema._enum = null + .schema.items._enum = null + .schema.items.ref = it gives ref to the item + + */ + private boolean isParameterArrayRef(CodegenParameter codegenParameter) { + if (codegenParameter.getSchema().items != null && codegenParameter.getSchema().items.getRef() != null + && codegenParameter.getSchema().items.isEnumRef) { + System.out.println("Identified as array parameter enum ref: " + codegenParameter.baseName); + codegenParameter.vendorExtensions.put(X_ENUM_TYPE, EnumConstants.OpenApiEnumType.PARAMETER_LIST_REF); + + // Resolve + codegenParameter.vendorExtensions.put(X_VARIABLE_NAME, StringUtils.toCamelCase(codegenParameter.baseName)); + // #/components/schemas/singleReusable or #/components/schemas/content_enum_single_reusable + // enumRefResolved = singleReusable + String enumRefResolved = Utility.getEnumNameFromRef(codegenParameter.getSchema().items.getRef()); + // enumNonContainerDatatype = Content.SingleReusable + String enumNonContainerDatatype = ResourceCache.getResourceName() + DOT + StringUtils.toPascalCase(enumRefResolved); + // resolvedDataType = List + String resolvedDataType = Utility.replaceDatatypeInContainer(codegenParameter.dataType, enumNonContainerDatatype); + codegenParameter.vendorExtensions.put(X_DATATYPE, resolvedDataType); + + return true; + } + return false; + } + + /* + isEnum = true + isEnumRef = true + */ + private boolean isUrlEncodedBodySingle(CodegenParameter codegenParameter) { + if (codegenParameter._enum != null && codegenParameter.isEnum && !codegenParameter.isContainer) { + System.out.println("Identified as single url encoded body enum: " + codegenParameter.baseName); + codegenParameter.vendorExtensions.put(X_ENUM_TYPE, EnumConstants.OpenApiEnumType.FORM_PARAM_INLINE); + + // Resolve + codegenParameter.vendorExtensions.put(X_VARIABLE_NAME, StringUtils.toCamelCase(codegenParameter.baseName)); + codegenParameter.vendorExtensions.put(X_DATATYPE, + ResourceCache.getResourceName() + DOT + StringUtils.toPascalCase(codegenParameter.baseName)); + return true; + } + return false; + } + + private boolean isUrlEncodedBodyRef(CodegenParameter codegenParameter) { + if (!codegenParameter.isEnum && codegenParameter.isEnumRef) { + codegenParameter.vendorExtensions.put(X_ENUM_TYPE, EnumConstants.OpenApiEnumType.FORM_PARAM_REF); + codegenParameter.vendorExtensions.put(X_VARIABLE_NAME, StringUtils.toCamelCase(codegenParameter.baseName)); + String enumDatatypeResolved = Utility.getEnumNameFromDefaultDatatype(codegenParameter.dataType); + codegenParameter.vendorExtensions.put(X_DATATYPE, ResourceCache.getResourceName() + DOT + enumDatatypeResolved); + return true; + } + return false; + } + + + private boolean isUrlEncodedBodyArray(CodegenParameter codegenParameter) { + if (codegenParameter.items != null && codegenParameter.items._enum != null && codegenParameter.isEnum) { + System.out.println("Identified as single url encoded body enum: " + codegenParameter.baseName); + codegenParameter.vendorExtensions.put(X_ENUM_TYPE, EnumConstants.OpenApiEnumType.FORM_PARAM_INLINE); + + // Resolve + codegenParameter.vendorExtensions.put(X_VARIABLE_NAME, StringUtils.toCamelCase(codegenParameter.baseName)); + + // codegenParameter.dataType = List + // enumExistingDatatype = String + String enumExistingDatatype = Utility.extractDatatypeFromContainer(codegenParameter.dataType); + String enumClassName = StringUtils.toPascalCase(codegenParameter.baseName); + String enumNonContainerDatatype = ResourceCache.getResourceName() + DOT + StringUtils.toPascalCase(enumClassName); + String resolvedDataType = Utility.replaceDatatypeInContainer(codegenParameter.dataType, enumNonContainerDatatype); + codegenParameter.vendorExtensions.put(X_DATATYPE, resolvedDataType); + return true; + } + return false; + } + + private boolean isUrlEncodedBodyArrayRef(CodegenParameter codegenParameter) { + if (codegenParameter.items != null && codegenParameter.items.isEnumRef && !codegenParameter.items.isEnum) { + codegenParameter.vendorExtensions.put(X_ENUM_TYPE, EnumConstants.OpenApiEnumType.FORM_PARAM_LIST_REF); + + codegenParameter.vendorExtensions.put(X_VARIABLE_NAME, StringUtils.toCamelCase(codegenParameter.baseName)); + // codegenParameter.dataType = List + // enumExistingDatatype = AccountEnumStatus + String enumExistingDatatype = Utility.extractDatatypeFromContainer(codegenParameter.dataType); + // enumClassName = Status + String enumClassName = Utility.getEnumNameFromDatatype(enumExistingDatatype); + // enumNonContainerDatatype = Account.Status + String enumNonContainerDatatype = ResourceCache.getResourceName() + DOT + StringUtils.toPascalCase(enumClassName); + // resolvedDataType = List + String resolvedDataType = Utility.replaceDatatypeInContainer(codegenParameter.dataType, enumNonContainerDatatype); + codegenParameter.vendorExtensions.put(X_DATATYPE, resolvedDataType); + return true; + } + return false; + } + /* + + */ + private boolean isPropertySingle(CodegenProperty codegenProperty) { + return false; + } + /* + + */ + private boolean isReusableSingle(CodegenProperty codegenProperty) { + return false; + } + /* + + */ + private void isReusableArray(CodegenProperty codegenProperty) { + + } +} diff --git a/src/main/java/com/twilio/oai/java/strategy/enums/parameter/FormParamInlineStrategy.java b/src/main/java/com/twilio/oai/java/strategy/enums/parameter/FormParamInlineStrategy.java new file mode 100644 index 000000000..fc6820d4a --- /dev/null +++ b/src/main/java/com/twilio/oai/java/strategy/enums/parameter/FormParamInlineStrategy.java @@ -0,0 +1,80 @@ +package com.twilio.oai.java.strategy.enums.parameter; + +import com.twilio.oai.common.EnumConstants; +import com.twilio.oai.common.EnumConstants.OpenApiEnumType; +import com.twilio.oai.common.StringUtils; +import com.twilio.oai.java.nestedmodels.MustacheEnum; +import com.twilio.oai.modern.ResourceCache; +import org.openapitools.codegen.CodegenParameter; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import static com.twilio.oai.common.ApplicationConstants.DOT; +import static com.twilio.oai.common.ApplicationConstants.X_DATATYPE; +import static com.twilio.oai.common.ApplicationConstants.X_VARIABLE_NAME; +import static com.twilio.oai.common.ApplicationConstants.X_ENUM_TYPE; + +/* + application/x-www-form-urlencoded: + schema: + type: object + properties: + # PROPERTY_SINGLE + singleBody: + type: string + enum: + - available + - pending + - sold + */ +public class FormParamInlineStrategy implements ParameterEnumProcessingStrategy { + + private final OpenApiEnumType type = OpenApiEnumType.FORM_PARAM_INLINE; + + @Override + public boolean process(final CodegenParameter codegenParameter) { + if (codegenParameter.getSchema() != null) return false; + if (codegenParameter._enum != null && codegenParameter.isEnum && !codegenParameter.isContainer) { + type(codegenParameter); + variableName(codegenParameter); + datatype(codegenParameter); + cacheEnumClass(codegenParameter); + return true; + } + return false; + } + + @Override + public OpenApiEnumType getType() { + return type; + } + + @Override + public boolean isStrategyApplicable(CodegenParameter codegenParameter) { + if (codegenParameter.getSchema() != null) return false; + if (codegenParameter._enum != null && codegenParameter.isEnum && !codegenParameter.isContainer) { + return true; + } + return false; + } + + private void type(CodegenParameter codegenParameter) { + codegenParameter.vendorExtensions.put(X_ENUM_TYPE, EnumConstants.OpenApiEnumType.FORM_PARAM_INLINE); + } + private void variableName(CodegenParameter codegenParameter) { + codegenParameter.vendorExtensions.put(X_VARIABLE_NAME, StringUtils.toCamelCase(codegenParameter.baseName)); + } + private void datatype(CodegenParameter codegenParameter) { + codegenParameter.vendorExtensions.put(X_DATATYPE, + ResourceCache.getResourceName() + DOT + StringUtils.toPascalCase(codegenParameter.baseName)); + } + + private void cacheEnumClass(CodegenParameter codegenParameter) { + List> enumValues = (List>) codegenParameter.allowableValues.get("enumVars"); + + MustacheEnum mustacheEnum = new MustacheEnum(StringUtils.toPascalCase(codegenParameter.baseName), enumValues); + ResourceCache.addToEnumClasses(mustacheEnum); + } +} diff --git a/src/main/java/com/twilio/oai/java/strategy/enums/parameter/FormParamListRefStrategy.java b/src/main/java/com/twilio/oai/java/strategy/enums/parameter/FormParamListRefStrategy.java new file mode 100644 index 000000000..ebfeadbc5 --- /dev/null +++ b/src/main/java/com/twilio/oai/java/strategy/enums/parameter/FormParamListRefStrategy.java @@ -0,0 +1,111 @@ +package com.twilio.oai.java.strategy.enums.parameter; + +import com.twilio.oai.common.EnumConstants; +import com.twilio.oai.common.EnumConstants.OpenApiEnumType; +import com.twilio.oai.common.StringUtils; +import com.twilio.oai.common.Utility; +import com.twilio.oai.java.nestedmodels.MustacheEnum; +import com.twilio.oai.modern.ResourceCache; +import org.openapitools.codegen.CodegenModel; +import org.openapitools.codegen.CodegenParameter; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import static com.twilio.oai.common.ApplicationConstants.DOT; +import static com.twilio.oai.common.ApplicationConstants.X_DATATYPE; +import static com.twilio.oai.common.ApplicationConstants.X_VARIABLE_NAME; +import static com.twilio.oai.common.ApplicationConstants.X_ENUM_TYPE; + +/* + application/x-www-form-urlencoded: + schema: + type: object + properties: + # REUSABLE_ARRAY + singleBodyRefArray: + type: array + items: + $ref: '#/components/schemas/singleReusable' + description: An array of reusable enum in the request body + example: [ electronics, clothing ] + */ +public class FormParamListRefStrategy implements ParameterEnumProcessingStrategy { + + private final OpenApiEnumType type = OpenApiEnumType.FORM_PARAM_LIST_REF; + + @Override + public boolean process(final CodegenParameter codegenParameter) { + if (codegenParameter.getSchema() != null) return false; + if (codegenParameter.items != null && codegenParameter.items.isEnumRef && !codegenParameter.items.isEnum) { + type(codegenParameter); + variableName(codegenParameter); + datatype(codegenParameter); + cacheEnumClass(codegenParameter); + return true; + } + return false; + } + + @Override + public OpenApiEnumType getType() { + return type; + } + + @Override + public boolean isStrategyApplicable(CodegenParameter codegenParameter) { + if (codegenParameter.getSchema() != null) return false; + if (codegenParameter.items != null && codegenParameter.items.isEnumRef && !codegenParameter.items.isEnum) { + return true; + } + return false; + } + + private void type(CodegenParameter codegenParameter) { + codegenParameter.vendorExtensions.put(X_ENUM_TYPE, EnumConstants.OpenApiEnumType.FORM_PARAM_LIST_REF); + } + private void variableName(CodegenParameter codegenParameter) { + codegenParameter.vendorExtensions.put(X_VARIABLE_NAME, StringUtils.toCamelCase(codegenParameter.baseName)); + } + private void datatype(CodegenParameter codegenParameter) { + // codegenParameter.dataType = List + // enumExistingDatatype = AccountEnumStatus + String enumExistingDatatype = Utility.extractDatatypeFromContainer(codegenParameter.dataType); + // enumClassName = Status + String enumClassName = Utility.getEnumNameFromDatatype(enumExistingDatatype); + // enumNonContainerDatatype = Account.Status + String enumNonContainerDatatype = ResourceCache.getResourceName() + DOT + StringUtils.toPascalCase(enumClassName); + // resolvedDataType = List + String resolvedDataType = Utility.replaceDatatypeInContainer(codegenParameter.dataType, enumNonContainerDatatype); + codegenParameter.vendorExtensions.put(X_DATATYPE, resolvedDataType); + } + + private void cacheEnumClass(CodegenParameter codegenParameter) { + String baseDataType = Utility.extractDatatypeFromContainer(codegenParameter.dataType); + if (baseDataType == null) { + throw new RuntimeException("Not able to fetch enum baseType for List Enum with ref" + " DataType: " +codegenParameter.dataType); + } + String enumClassName = Utility.getEnumNameFromDatatype(baseDataType); + if (enumClassName == null) { + throw new RuntimeException("Not able to fetch enum class name from baseDataType for List Enum with ref" + + "baseType:"+ baseDataType + " DataType: " + codegenParameter.dataType); + } + + Map values = null; + List> enumValues = new ArrayList<>(); + + for (CodegenModel codegenModel: ResourceCache.getAllModelsByDefaultGenerator()) { + if (baseDataType.equals(codegenModel.classname)) { + values = codegenModel.allowableValues; + enumValues = (List>) codegenModel.allowableValues.get("enumVars"); + break; + } + } + if (enumValues == null || enumValues.isEmpty()) { + throw new RuntimeException("No enum values found for Enum" + " DataType: " +codegenParameter.dataType); + } + MustacheEnum mustacheEnum = new MustacheEnum(enumClassName, enumValues); + ResourceCache.addToEnumClasses(mustacheEnum); + } +} diff --git a/src/main/java/com/twilio/oai/java/strategy/enums/parameter/FormParamListStrategy.java b/src/main/java/com/twilio/oai/java/strategy/enums/parameter/FormParamListStrategy.java new file mode 100644 index 000000000..c952f2abf --- /dev/null +++ b/src/main/java/com/twilio/oai/java/strategy/enums/parameter/FormParamListStrategy.java @@ -0,0 +1,88 @@ +package com.twilio.oai.java.strategy.enums.parameter; + +import com.twilio.oai.common.EnumConstants; +import com.twilio.oai.common.EnumConstants.OpenApiEnumType; +import com.twilio.oai.common.StringUtils; +import com.twilio.oai.common.Utility; +import com.twilio.oai.java.nestedmodels.MustacheEnum; +import com.twilio.oai.modern.ResourceCache; +import org.openapitools.codegen.CodegenParameter; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import static com.twilio.oai.common.ApplicationConstants.DOT; +import static com.twilio.oai.common.ApplicationConstants.X_DATATYPE; +import static com.twilio.oai.common.ApplicationConstants.X_VARIABLE_NAME; +import static com.twilio.oai.common.ApplicationConstants.X_ENUM_TYPE; + +/* + application/x-www-form-urlencoded: + schema: + type: object + properties: + # PROPERTY_ARRAY + singleBodyArray: + type: array + items: + type: string + enum: [ new, sale, featured ] + description: An array of enum values in the request body + example: [ new, featured ] + */ +public class FormParamListStrategy implements ParameterEnumProcessingStrategy { + + private final OpenApiEnumType type = OpenApiEnumType.FORM_PARAM_LIST_INLINE; + + @Override + public boolean process(final CodegenParameter codegenParameter) { + if (codegenParameter.getSchema() != null) return false; + if (codegenParameter.items != null && codegenParameter.items._enum != null && codegenParameter.isEnum) { + type(codegenParameter); + variableName(codegenParameter); + datatype(codegenParameter); + cacheEnumClass(codegenParameter); + return true; + } + return false; + } + + @Override + public OpenApiEnumType getType() { + return type; + } + + @Override + public boolean isStrategyApplicable(CodegenParameter codegenParameter) { + if (codegenParameter.getSchema() != null) return false; + if (codegenParameter.items != null && codegenParameter.items._enum != null && codegenParameter.isEnum) { + return true; + } + return false; + } + + private void type(CodegenParameter codegenParameter) { + codegenParameter.vendorExtensions.put(X_ENUM_TYPE, EnumConstants.OpenApiEnumType.FORM_PARAM_INLINE); + } + private void variableName(CodegenParameter codegenParameter) { + codegenParameter.vendorExtensions.put(X_VARIABLE_NAME, StringUtils.toCamelCase(codegenParameter.baseName)); + } + private void datatype(CodegenParameter codegenParameter) { + // codegenParameter.dataType = List + // enumExistingDatatype = String + String enumExistingDatatype = Utility.extractDatatypeFromContainer(codegenParameter.dataType); + String enumClassName = StringUtils.toPascalCase(codegenParameter.baseName); + String enumNonContainerDatatype = ResourceCache.getResourceName() + DOT + enumClassName; + String resolvedDataType = Utility.replaceDatatypeInContainer(codegenParameter.dataType, enumNonContainerDatatype); + codegenParameter.vendorExtensions.put(X_DATATYPE, resolvedDataType); + } + + private void cacheEnumClass(CodegenParameter codegenParameter) { + String enumClassName = StringUtils.toPascalCase(codegenParameter.baseName); + List> enumValues = (List>) codegenParameter.allowableValues.get("enumVars"); + + MustacheEnum mustacheEnum = new MustacheEnum(enumClassName, enumValues); + ResourceCache.addToEnumClasses(mustacheEnum); + } +} diff --git a/src/main/java/com/twilio/oai/java/strategy/enums/parameter/FormParamRefStrategy.java b/src/main/java/com/twilio/oai/java/strategy/enums/parameter/FormParamRefStrategy.java new file mode 100644 index 000000000..9a2b98786 --- /dev/null +++ b/src/main/java/com/twilio/oai/java/strategy/enums/parameter/FormParamRefStrategy.java @@ -0,0 +1,80 @@ +package com.twilio.oai.java.strategy.enums.parameter; + +import com.twilio.oai.common.EnumConstants; +import com.twilio.oai.common.EnumConstants.OpenApiEnumType; +import com.twilio.oai.common.StringUtils; +import com.twilio.oai.common.Utility; +import com.twilio.oai.java.nestedmodels.MustacheEnum; +import com.twilio.oai.modern.ResourceCache; +import org.openapitools.codegen.CodegenParameter; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import static com.twilio.oai.common.ApplicationConstants.DOT; +import static com.twilio.oai.common.ApplicationConstants.X_DATATYPE; +import static com.twilio.oai.common.ApplicationConstants.X_VARIABLE_NAME; +import static com.twilio.oai.common.ApplicationConstants.X_ENUM_TYPE; + +/* + application/x-www-form-urlencoded: + schema: + type: object + properties: + # REUSABLE_SINGLE + singleBodyRef: + $ref: '#/components/schemas/singleReusable' + description: A reusable single-value enum in the request body + */ +public class FormParamRefStrategy implements ParameterEnumProcessingStrategy { + + private final OpenApiEnumType type = OpenApiEnumType.FORM_PARAM_REF; + + @Override + public boolean process(final CodegenParameter codegenParameter) { + if (codegenParameter.getSchema() != null) return false; + if (!codegenParameter.isEnum && codegenParameter.isEnumRef) { + type(codegenParameter); + variableName(codegenParameter); + datatype(codegenParameter); + cacheEnumClass(codegenParameter); + return true; + } + return false; + } + + @Override + public OpenApiEnumType getType() { + return type; + } + + @Override + public boolean isStrategyApplicable(CodegenParameter codegenParameter) { + if (codegenParameter.getSchema() != null) return false; + if (!codegenParameter.isEnum && codegenParameter.isEnumRef) { + return true; + } + return false; + } + + private void type(CodegenParameter codegenParameter) { + codegenParameter.vendorExtensions.put(X_ENUM_TYPE, EnumConstants.OpenApiEnumType.FORM_PARAM_REF); + } + private void variableName(CodegenParameter codegenParameter) { + codegenParameter.vendorExtensions.put(X_VARIABLE_NAME, StringUtils.toCamelCase(codegenParameter.baseName)); + } + private void datatype(CodegenParameter codegenParameter) { + String enumDatatypeResolved = StringUtils.toPascalCase(Utility.getEnumNameFromDefaultDatatype(codegenParameter.dataType)); + codegenParameter.vendorExtensions.put(X_DATATYPE, ResourceCache.getResourceName() + DOT + enumDatatypeResolved); + } + + private void cacheEnumClass(CodegenParameter codegenParameter) { + // TODO: Best way to store = codegenParameter.allowableValues.get("enumVars") + String enumClassName = StringUtils.toPascalCase(Utility.getEnumNameFromDefaultDatatype(codegenParameter.dataType)); + List> enumValues = (List>) codegenParameter.allowableValues.get("enumVars"); + + MustacheEnum mustacheEnum = new MustacheEnum(enumClassName, enumValues); + ResourceCache.addToEnumClasses(mustacheEnum); + } +} diff --git a/src/main/java/com/twilio/oai/java/strategy/enums/parameter/InlineListParamStrategy.java b/src/main/java/com/twilio/oai/java/strategy/enums/parameter/InlineListParamStrategy.java new file mode 100644 index 000000000..d9f59c655 --- /dev/null +++ b/src/main/java/com/twilio/oai/java/strategy/enums/parameter/InlineListParamStrategy.java @@ -0,0 +1,87 @@ +package com.twilio.oai.java.strategy.enums.parameter; + +import com.twilio.oai.common.EnumConstants; +import com.twilio.oai.common.EnumConstants.OpenApiEnumType; +import com.twilio.oai.common.StringUtils; +import com.twilio.oai.common.Utility; +import com.twilio.oai.java.nestedmodels.MustacheEnum; +import com.twilio.oai.modern.ResourceCache; +import org.openapitools.codegen.CodegenParameter; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import static com.twilio.oai.common.ApplicationConstants.DOT; +import static com.twilio.oai.common.ApplicationConstants.X_DATATYPE; +import static com.twilio.oai.common.ApplicationConstants.X_VARIABLE_NAME; +import static com.twilio.oai.common.ApplicationConstants.X_ENUM_TYPE; + +/* + Example: + - name: arrayParam + in: query + description: Order items using an array of enums + required: false + schema: + type: array + items: + type: string + enum: + - asc + - desc + example: [asc] + */ +public class InlineListParamStrategy implements ParameterEnumProcessingStrategy { + + private final OpenApiEnumType type = OpenApiEnumType.PARAMETER_LIST_INLINE; + + @Override + public boolean process(final CodegenParameter codegenParameter) { + if (codegenParameter.getSchema() == null) return false; + if (codegenParameter.getSchema()._enum == null && + codegenParameter.getSchema().items != null && codegenParameter.getSchema().items._enum != null) { + type(codegenParameter); + variableName(codegenParameter); + datatype(codegenParameter); + cacheEnumClass(codegenParameter); + return true; + } + return false; + } + + @Override + public OpenApiEnumType getType() { + return type; + } + + @Override + public boolean isStrategyApplicable(CodegenParameter codegenParameter) { + if (codegenParameter.getSchema() == null) return false; + if (codegenParameter.getSchema()._enum == null && + codegenParameter.getSchema().items != null && codegenParameter.getSchema().items._enum != null) { + return true; + } + return false; + } + + private void type(CodegenParameter codegenParameter) { + codegenParameter.vendorExtensions.put(X_ENUM_TYPE, EnumConstants.OpenApiEnumType.PARAMETER_LIST_INLINE); + } + private void variableName(CodegenParameter codegenParameter) { + codegenParameter.vendorExtensions.put(X_VARIABLE_NAME, StringUtils.toCamelCase(codegenParameter.baseName)); + } + private void datatype(CodegenParameter codegenParameter) { + String enumClassName = StringUtils.toPascalCase(codegenParameter.baseName); + String enumNonContainerDatatype = ResourceCache.getResourceName() + DOT + StringUtils.toPascalCase(enumClassName); + String resolvedDataType = Utility.replaceDatatypeInContainer(codegenParameter.dataType, enumNonContainerDatatype); + codegenParameter.vendorExtensions.put(X_DATATYPE, resolvedDataType); + } + + private void cacheEnumClass(CodegenParameter codegenParameter) { + List> enumValues = (List>) codegenParameter.allowableValues.get("enumVars"); + + MustacheEnum mustacheEnum = new MustacheEnum( StringUtils.toPascalCase(codegenParameter.baseName), enumValues); + ResourceCache.addToEnumClasses(mustacheEnum); + } +} diff --git a/src/main/java/com/twilio/oai/java/strategy/enums/parameter/InlineParamStrategy.java b/src/main/java/com/twilio/oai/java/strategy/enums/parameter/InlineParamStrategy.java new file mode 100644 index 000000000..ad4cf1fb7 --- /dev/null +++ b/src/main/java/com/twilio/oai/java/strategy/enums/parameter/InlineParamStrategy.java @@ -0,0 +1,77 @@ +package com.twilio.oai.java.strategy.enums.parameter; + +import com.twilio.oai.common.EnumConstants.OpenApiEnumType; +import com.twilio.oai.common.StringUtils; +import com.twilio.oai.java.nestedmodels.MustacheEnum; +import com.twilio.oai.modern.ResourceCache; +import org.openapitools.codegen.CodegenParameter; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import static com.twilio.oai.common.ApplicationConstants.DOT; +import static com.twilio.oai.common.ApplicationConstants.X_DATATYPE; +import static com.twilio.oai.common.ApplicationConstants.X_VARIABLE_NAME; +import static com.twilio.oai.common.ApplicationConstants.X_ENUM_TYPE; + +/* + - name: singleParam + in: query + description: A single enum value as a query parameter + required: false + schema: + type: string + enum: + - asc + - desc + example: asc + */ +public class InlineParamStrategy implements ParameterEnumProcessingStrategy { + + private final OpenApiEnumType type = OpenApiEnumType.PARAMETER_INLINE; + + @Override + public boolean process(final CodegenParameter codegenParameter) { + if (codegenParameter.getSchema() == null) return false; + if (codegenParameter.getSchema()._enum != null && codegenParameter.isEnum) { + type(codegenParameter); + variableName(codegenParameter); + datatype(codegenParameter); + cacheEnumClass(codegenParameter); + return true; + } + return false; + } + + @Override + public OpenApiEnumType getType() { + return type; + } + + @Override + public boolean isStrategyApplicable(CodegenParameter codegenParameter) { + if (codegenParameter.getSchema() == null) return false; + if (codegenParameter.getSchema()._enum != null && codegenParameter.isEnum) { + return true; + } + return false; + } + + private void type(CodegenParameter codegenParameter) { + codegenParameter.vendorExtensions.put(X_ENUM_TYPE, type); + } + private void variableName(CodegenParameter codegenParameter) { + codegenParameter.vendorExtensions.put(X_VARIABLE_NAME, StringUtils.toCamelCase(codegenParameter.baseName)); + } + private void datatype(CodegenParameter codegenParameter) { + codegenParameter.vendorExtensions.put(X_DATATYPE, + ResourceCache.getResourceName() + DOT + StringUtils.toPascalCase(codegenParameter.baseName)); + } + + private void cacheEnumClass(CodegenParameter codegenParameter) { + List> enumValues = (List>) codegenParameter.allowableValues.get("enumVars"); + MustacheEnum mustacheEnum = new MustacheEnum(StringUtils.toPascalCase(codegenParameter.baseName), enumValues); + ResourceCache.addToEnumClasses(mustacheEnum); + } +} diff --git a/src/main/java/com/twilio/oai/java/strategy/enums/parameter/ParameterEnumProcessingStrategy.java b/src/main/java/com/twilio/oai/java/strategy/enums/parameter/ParameterEnumProcessingStrategy.java new file mode 100644 index 000000000..bdef8d94b --- /dev/null +++ b/src/main/java/com/twilio/oai/java/strategy/enums/parameter/ParameterEnumProcessingStrategy.java @@ -0,0 +1,11 @@ +package com.twilio.oai.java.strategy.enums.parameter; + +import com.twilio.oai.common.EnumConstants.OpenApiEnumType; +import org.openapitools.codegen.CodegenParameter; + +public interface ParameterEnumProcessingStrategy { + boolean process(CodegenParameter codegenParameter); + OpenApiEnumType getType(); + + boolean isStrategyApplicable(CodegenParameter codegenParameter); +} diff --git a/src/main/java/com/twilio/oai/java/strategy/enums/parameter/RefListParamStrategy.java b/src/main/java/com/twilio/oai/java/strategy/enums/parameter/RefListParamStrategy.java new file mode 100644 index 000000000..f5e0f7642 --- /dev/null +++ b/src/main/java/com/twilio/oai/java/strategy/enums/parameter/RefListParamStrategy.java @@ -0,0 +1,88 @@ +package com.twilio.oai.java.strategy.enums.parameter; + +import com.twilio.oai.common.EnumConstants; +import com.twilio.oai.common.EnumConstants.OpenApiEnumType; +import com.twilio.oai.common.StringUtils; +import com.twilio.oai.common.Utility; +import com.twilio.oai.java.nestedmodels.MustacheEnum; +import com.twilio.oai.modern.ResourceCache; +import org.openapitools.codegen.CodegenParameter; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import static com.twilio.oai.common.ApplicationConstants.DOT; +import static com.twilio.oai.common.ApplicationConstants.X_DATATYPE; +import static com.twilio.oai.common.ApplicationConstants.X_VARIABLE_NAME; +import static com.twilio.oai.common.ApplicationConstants.X_ENUM_TYPE; + +/* + - name: arrayParamRef + in: query + required: false + description: An array parameter referencing a reusable schema + schema: + type: array + items: + $ref: '#/components/schemas/singleReusable' + */ +public class RefListParamStrategy implements ParameterEnumProcessingStrategy { + + private final OpenApiEnumType type = OpenApiEnumType.PARAMETER_LIST_REF; + + @Override + public boolean process(final CodegenParameter codegenParameter) { + if (codegenParameter.getSchema() == null) return false; + if (codegenParameter.getSchema().items != null && codegenParameter.getSchema().items.getRef() != null + && codegenParameter.getSchema().items.isEnumRef) { + + type(codegenParameter); + variableName(codegenParameter); + datatype(codegenParameter); + cacheEnumClass(codegenParameter); + return true; + } + return false; + } + + @Override + public OpenApiEnumType getType() { + return type; + } + + @Override + public boolean isStrategyApplicable(CodegenParameter codegenParameter) { + if (codegenParameter.getSchema() == null) return false; + if (codegenParameter.getSchema().items != null && codegenParameter.getSchema().items.getRef() != null + && codegenParameter.getSchema().items.isEnumRef) { + return true; + } + return false; + } + + private void type(CodegenParameter codegenParameter) { + codegenParameter.vendorExtensions.put(X_ENUM_TYPE, EnumConstants.OpenApiEnumType.PARAMETER_LIST_REF); + } + private void variableName(CodegenParameter codegenParameter) { + codegenParameter.vendorExtensions.put(X_VARIABLE_NAME, StringUtils.toCamelCase(codegenParameter.baseName)); + } + private void datatype(CodegenParameter codegenParameter) { + // #/components/schemas/singleReusable or #/components/schemas/content_enum_single_reusable + // enumRefResolved = singleReusable + String enumRefResolved = Utility.getEnumNameFromRef(codegenParameter.getSchema().items.getRef()); + // enumNonContainerDatatype = Content.SingleReusable + String enumNonContainerDatatype = ResourceCache.getResourceName() + DOT + StringUtils.toPascalCase(enumRefResolved); + // resolvedDataType = List + String resolvedDataType = Utility.replaceDatatypeInContainer(codegenParameter.dataType, enumNonContainerDatatype); + codegenParameter.vendorExtensions.put(X_DATATYPE, resolvedDataType); + } + + private void cacheEnumClass(CodegenParameter codegenParameter) { + List> enumValues = (List>) codegenParameter.getSchema().items.allowableValues.get("enumVars"); + + MustacheEnum mustacheEnum = new MustacheEnum(StringUtils.toPascalCase( + Utility.getEnumNameFromRef(codegenParameter.getSchema().items.getRef())), enumValues); + ResourceCache.addToEnumClasses(mustacheEnum); + } +} diff --git a/src/main/java/com/twilio/oai/java/strategy/enums/parameter/RefParamStrategy.java b/src/main/java/com/twilio/oai/java/strategy/enums/parameter/RefParamStrategy.java new file mode 100644 index 000000000..32dab90eb --- /dev/null +++ b/src/main/java/com/twilio/oai/java/strategy/enums/parameter/RefParamStrategy.java @@ -0,0 +1,74 @@ +package com.twilio.oai.java.strategy.enums.parameter; + +import com.twilio.oai.common.EnumConstants; +import com.twilio.oai.common.EnumConstants.OpenApiEnumType; +import com.twilio.oai.common.StringUtils; +import com.twilio.oai.common.Utility; +import com.twilio.oai.java.nestedmodels.MustacheEnum; +import com.twilio.oai.modern.ResourceCache; +import org.openapitools.codegen.CodegenParameter; + +import java.util.List; +import java.util.Map; + +import static com.twilio.oai.common.ApplicationConstants.DOT; +import static com.twilio.oai.common.ApplicationConstants.X_DATATYPE; +import static com.twilio.oai.common.ApplicationConstants.X_VARIABLE_NAME; +import static com.twilio.oai.common.ApplicationConstants.X_ENUM_TYPE; + +/* + - name: singleParamRef + in: header + schema: + $ref: '#/components/schemas/singleReusable' + */ +public class RefParamStrategy implements ParameterEnumProcessingStrategy { + + private final OpenApiEnumType type = OpenApiEnumType.PARAMETER_REF; + + @Override + public boolean process(final CodegenParameter codegenParameter) { + if (codegenParameter.getSchema() == null) return false; + if (codegenParameter.getSchema().getRef() != null && codegenParameter.isEnumRef) { + type(codegenParameter); + variableName(codegenParameter); + datatype(codegenParameter); + cacheEnumClass(codegenParameter); + return true; + } + return false; + } + + @Override + public OpenApiEnumType getType() { + return type; + } + + @Override + public boolean isStrategyApplicable(CodegenParameter codegenParameter) { + if (codegenParameter.getSchema() == null) return false; + if (codegenParameter.getSchema().getRef() != null && codegenParameter.isEnumRef) { + return true; + } + return false; + } + + private void type(CodegenParameter codegenParameter) { + codegenParameter.vendorExtensions.put(X_ENUM_TYPE, EnumConstants.OpenApiEnumType.PARAMETER_REF); + } + private void variableName(CodegenParameter codegenParameter) { + codegenParameter.vendorExtensions.put(X_VARIABLE_NAME, StringUtils.toCamelCase(codegenParameter.baseName)); + } + private void datatype(CodegenParameter codegenParameter) { + String enumRefResolved = Utility.getEnumNameFromRef(codegenParameter.getSchema().getRef()); + codegenParameter.vendorExtensions.put(X_DATATYPE, + ResourceCache.getResourceName() + DOT + StringUtils.toPascalCase(enumRefResolved)); + } + + private void cacheEnumClass(CodegenParameter codegenParameter) { + List> enumValues = (List>) codegenParameter.allowableValues.get("enumVars"); + MustacheEnum mustacheEnum = new MustacheEnum(StringUtils.toPascalCase( + Utility.getEnumNameFromRef(codegenParameter.getSchema().getRef())), enumValues); + ResourceCache.addToEnumClasses(mustacheEnum); + } +} diff --git a/src/main/java/com/twilio/oai/java/strategy/enums/property/InlineListPropStrategy.java b/src/main/java/com/twilio/oai/java/strategy/enums/property/InlineListPropStrategy.java new file mode 100644 index 000000000..2a9344634 --- /dev/null +++ b/src/main/java/com/twilio/oai/java/strategy/enums/property/InlineListPropStrategy.java @@ -0,0 +1,66 @@ +package com.twilio.oai.java.strategy.enums.property; + +import com.twilio.oai.common.EnumConstants.OpenApiEnumType; +import com.twilio.oai.common.StringUtils; +import com.twilio.oai.common.Utility; +import com.twilio.oai.java.nestedmodels.MustacheEnum; +import com.twilio.oai.modern.ResourceCache; +import org.openapitools.codegen.CodegenParameter; +import org.openapitools.codegen.CodegenProperty; + +import java.util.List; +import java.util.Map; + +import static com.twilio.oai.common.ApplicationConstants.DOT; +import static com.twilio.oai.common.ApplicationConstants.X_VARIABLE_NAME; +import static com.twilio.oai.common.ApplicationConstants.X_DATATYPE; +import static com.twilio.oai.common.ApplicationConstants.X_ENUM_TYPE; + +public class InlineListPropStrategy implements PropertyEnumProcessingStrategy { + private final OpenApiEnumType type = OpenApiEnumType.PROPERTY_LIST; + + @Override + public boolean process(final CodegenProperty codegenProperty) { + if (codegenProperty.isEnum && !codegenProperty.isEnumRef && codegenProperty.items != null && codegenProperty.items.get_enum() != null) { + type(codegenProperty); + variableName(codegenProperty); + datatype(codegenProperty); + cacheEnumClass(codegenProperty); + return true; + } + // Check if the parameter is a single enum type + return false; + } + + @Override + public OpenApiEnumType getType() { + // Return the type of enum this strategy identifies + return type; + } + + private void type(CodegenProperty codegenProperty) { + codegenProperty.vendorExtensions.put(X_ENUM_TYPE, type); + } + private void variableName(CodegenProperty codegenProperty) { + codegenProperty.vendorExtensions.put(X_VARIABLE_NAME, StringUtils.toCamelCase(codegenProperty.baseName)); + } + private void datatype(CodegenProperty codegenProperty) { + String enumClassName = StringUtils.toPascalCase(codegenProperty.baseName); + String enumNonContainerDatatype = ResourceCache.getResourceName() + DOT + StringUtils.toPascalCase(enumClassName); + String resolvedDataType = Utility.replaceDatatypeInContainer(codegenProperty.dataType, enumNonContainerDatatype); + codegenProperty.vendorExtensions.put(X_DATATYPE, resolvedDataType); + } + + public boolean isStrategyApplicable(CodegenProperty codegenProperty) { + if (codegenProperty.isEnum && !codegenProperty.isEnumRef && codegenProperty.items != null && codegenProperty.items.get_enum() != null) { + return true; + } + return false; + } + + private void cacheEnumClass(CodegenProperty codegenProperty) { + List> enumValues = (List>) codegenProperty.allowableValues.get("enumVars"); + MustacheEnum mustacheEnum = new MustacheEnum(StringUtils.toPascalCase(codegenProperty.baseName), enumValues); + ResourceCache.addToEnumClasses(mustacheEnum); + } +} diff --git a/src/main/java/com/twilio/oai/java/strategy/enums/property/InlinePropStrategy.java b/src/main/java/com/twilio/oai/java/strategy/enums/property/InlinePropStrategy.java new file mode 100644 index 000000000..5d0e66348 --- /dev/null +++ b/src/main/java/com/twilio/oai/java/strategy/enums/property/InlinePropStrategy.java @@ -0,0 +1,75 @@ +package com.twilio.oai.java.strategy.enums.property; + +import static com.twilio.oai.common.ApplicationConstants.DOT; +import static com.twilio.oai.common.ApplicationConstants.X_VARIABLE_NAME; +import static com.twilio.oai.common.ApplicationConstants.X_DATATYPE; +import static com.twilio.oai.common.ApplicationConstants.X_ENUM_TYPE; + +import com.twilio.oai.StringHelper; +import com.twilio.oai.common.EnumConstants.OpenApiEnumType; +import com.twilio.oai.common.StringUtils; +import com.twilio.oai.java.nestedmodels.MustacheEnum; +import com.twilio.oai.modern.ResourceCache; +import org.openapitools.codegen.CodegenProperty; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/* +codegenProperty._enum = true +codegenProperty.isEnum = true +codegenProperty.isEnumRef = true + */ +public class InlinePropStrategy implements PropertyEnumProcessingStrategy { + private final OpenApiEnumType type = OpenApiEnumType.PROPERTY_INLINE; + @Override + public boolean process(final CodegenProperty codegenProperty) { + if (codegenProperty.isEnum && codegenProperty.isEnumRef && codegenProperty.get_enum() != null) { + type(codegenProperty); + variableName(codegenProperty); + datatype(codegenProperty); + cacheEnumClass(codegenProperty); + return true; + } + return false; + } + + @Override + public OpenApiEnumType getType() { + return type; + } + + @Override + public boolean isStrategyApplicable(CodegenProperty codegenProperty) { + if (codegenProperty.isEnum && codegenProperty.isEnumRef && codegenProperty.get_enum() != null) { + return true; + } + return false; + } + + private void type(CodegenProperty codegenProperty) { + codegenProperty.vendorExtensions.put(X_ENUM_TYPE, type); + } + private void variableName(CodegenProperty codegenProperty) { + codegenProperty.vendorExtensions.put(X_VARIABLE_NAME, StringUtils.toCamelCase(codegenProperty.baseName)); + } + private void datatype(CodegenProperty codegenProperty) { + codegenProperty.vendorExtensions.put(X_DATATYPE, + ResourceCache.getResourceName() + DOT + StringUtils.toPascalCase(codegenProperty.baseName)); + } + + private void cacheEnumClass(CodegenProperty codegenProperty) { + List> enumValues = new ArrayList<>(); + + for (String s : (List) codegenProperty.allowableValues.get("values")) { + HashMap valueMap = new HashMap<>(); + valueMap.put("name", StringHelper.toSnakeCase(s).toUpperCase()); + valueMap.put("value", "\"" + s + "\""); // adding extra quote as this is how enumVars are stored + enumValues.add(valueMap); + } + MustacheEnum mustacheEnum = new MustacheEnum(StringUtils.toPascalCase(codegenProperty.baseName), enumValues); + ResourceCache.addToEnumClasses(mustacheEnum); + } +} diff --git a/src/main/java/com/twilio/oai/java/strategy/enums/property/PropertyEnumProcessingStrategy.java b/src/main/java/com/twilio/oai/java/strategy/enums/property/PropertyEnumProcessingStrategy.java new file mode 100644 index 000000000..ad9b78559 --- /dev/null +++ b/src/main/java/com/twilio/oai/java/strategy/enums/property/PropertyEnumProcessingStrategy.java @@ -0,0 +1,11 @@ +package com.twilio.oai.java.strategy.enums.property; + +import com.twilio.oai.common.EnumConstants; +import org.openapitools.codegen.CodegenProperty; + +public interface PropertyEnumProcessingStrategy { + boolean process(CodegenProperty codegenProperty); + EnumConstants.OpenApiEnumType getType(); + + boolean isStrategyApplicable(CodegenProperty codegenProperty); +} diff --git a/src/main/java/com/twilio/oai/java/strategy/enums/property/RefListPropStrategy.java b/src/main/java/com/twilio/oai/java/strategy/enums/property/RefListPropStrategy.java new file mode 100644 index 000000000..32acd8186 --- /dev/null +++ b/src/main/java/com/twilio/oai/java/strategy/enums/property/RefListPropStrategy.java @@ -0,0 +1,74 @@ +package com.twilio.oai.java.strategy.enums.property; + +import com.twilio.oai.common.EnumConstants.OpenApiEnumType; +import com.twilio.oai.common.StringUtils; +import com.twilio.oai.common.Utility; +import com.twilio.oai.java.nestedmodels.MustacheEnum; +import com.twilio.oai.modern.ResourceCache; +import org.checkerframework.checker.units.qual.A; +import org.openapitools.codegen.CodegenProperty; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static com.twilio.oai.common.ApplicationConstants.X_VARIABLE_NAME; +import static com.twilio.oai.common.ApplicationConstants.X_ENUM_TYPE; +import static com.twilio.oai.common.ApplicationConstants.DOT; +import static com.twilio.oai.common.ApplicationConstants.X_DATATYPE; + +public class RefListPropStrategy implements PropertyEnumProcessingStrategy { + private final OpenApiEnumType type = OpenApiEnumType.PROPERTY_INLINE; + @Override + public boolean process(final CodegenProperty codegenProperty) { + if (codegenProperty.items != null && codegenProperty.items.isEnumRef && !codegenProperty.items.isEnum) { + type(codegenProperty); + variableName(codegenProperty); + datatype(codegenProperty); + cacheEnumClass(codegenProperty); + return true; + } + // Check if the parameter is a single enum type + return false; + } + + @Override + public OpenApiEnumType getType() { + return type; + } + + @Override + public boolean isStrategyApplicable(CodegenProperty codegenProperty) { + if (codegenProperty.items != null && codegenProperty.items.isEnumRef && !codegenProperty.items.isEnum) { + return true; + } + return false; + } + + private void type(CodegenProperty codegenProperty) { + codegenProperty.vendorExtensions.put(X_ENUM_TYPE, type); + } + private void variableName(CodegenProperty codegenProperty) { + codegenProperty.vendorExtensions.put(X_VARIABLE_NAME, StringUtils.toCamelCase(codegenProperty.baseName)); + } + private void datatype(CodegenProperty codegenProperty) { + String enumExistingDatatype = Utility.extractDatatypeFromContainer(codegenProperty.dataType); + // enumClassName = Status + String enumClassName = Utility.getEnumNameFromDatatype(enumExistingDatatype); + // enumNonContainerDatatype = Account.Status + String enumNonContainerDatatype = ResourceCache.getResourceName() + DOT + StringUtils.toPascalCase(enumClassName); + // resolvedDataType = List + String resolvedDataType = Utility.replaceDatatypeInContainer(codegenProperty.dataType, enumNonContainerDatatype); + codegenProperty.vendorExtensions.put(X_DATATYPE, resolvedDataType); + } + + private void cacheEnumClass(CodegenProperty codegenProperty) { + String enumExistingDatatype = Utility.extractDatatypeFromContainer(codegenProperty.dataType); + String enumClassName = Utility.getEnumNameFromDatatype(enumExistingDatatype); + List> enumValues = (List>) codegenProperty.items.allowableValues.get("enumVars"); + + MustacheEnum mustacheEnum = new MustacheEnum(enumClassName, enumValues); + ResourceCache.addToEnumClasses(mustacheEnum); + } +} diff --git a/src/main/java/com/twilio/oai/java/strategy/enums/property/RefPropStrategy.java b/src/main/java/com/twilio/oai/java/strategy/enums/property/RefPropStrategy.java new file mode 100644 index 000000000..1228eaddc --- /dev/null +++ b/src/main/java/com/twilio/oai/java/strategy/enums/property/RefPropStrategy.java @@ -0,0 +1,72 @@ +package com.twilio.oai.java.strategy.enums.property; + +import com.twilio.oai.StringHelper; +import com.twilio.oai.common.EnumConstants.OpenApiEnumType; +import com.twilio.oai.common.StringUtils; +import com.twilio.oai.common.Utility; +import com.twilio.oai.java.nestedmodels.MustacheEnum; +import com.twilio.oai.modern.ResourceCache; +import org.openapitools.codegen.CodegenParameter; +import org.openapitools.codegen.CodegenProperty; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static com.twilio.oai.common.ApplicationConstants.DOT; +import static com.twilio.oai.common.ApplicationConstants.X_DATATYPE; +import static com.twilio.oai.common.ApplicationConstants.X_VARIABLE_NAME; +import static com.twilio.oai.common.ApplicationConstants.X_ENUM_TYPE; +public class RefPropStrategy implements PropertyEnumProcessingStrategy { + private final OpenApiEnumType type = OpenApiEnumType.PROPERTY_REF; + @Override + public boolean process(final CodegenProperty codegenProperty) { + if (!codegenProperty.isEnum && codegenProperty.isEnumRef && codegenProperty.getRef() != null) { + type(codegenProperty); + variableName(codegenProperty); + datatype(codegenProperty); + cacheEnumClass(codegenProperty); + return true; + } + return false; + } + + @Override + public OpenApiEnumType getType() { + return type; + } + + @Override + public boolean isStrategyApplicable(CodegenProperty codegenProperty) { + if (!codegenProperty.isEnum && codegenProperty.isEnumRef && codegenProperty.getRef() != null) { + return true; + } + return false; + } + + private void type(CodegenProperty codegenProperty) { + codegenProperty.vendorExtensions.put(X_ENUM_TYPE, type); + } + private void variableName(CodegenProperty codegenProperty) { + codegenProperty.vendorExtensions.put(X_VARIABLE_NAME, StringUtils.toCamelCase(codegenProperty.baseName)); + } + private void datatype(CodegenProperty codegenProperty) { + String enumDatatypeResolved = StringUtils.toPascalCase(Utility.getEnumNameFromDefaultDatatype(codegenProperty.getRef())); + codegenProperty.vendorExtensions.put(X_DATATYPE, ResourceCache.getResourceName() + DOT + enumDatatypeResolved); + } + + private void cacheEnumClass(CodegenProperty codegenProperty) { + System.out.println(codegenProperty.baseName); + String enumClassName = Utility.getEnumNameFromRef(codegenProperty.getRef()); + List> enumValues = new ArrayList<>(); + for (String s : (List) codegenProperty.allowableValues.get("values")) { + HashMap valueMap = new HashMap<>(); + valueMap.put("name", StringHelper.toSnakeCase(s).toUpperCase()); + valueMap.put("value", "\"" + s + "\""); // adding extra quote as this is how enumVars are stored + enumValues.add(valueMap); + } + MustacheEnum mustacheEnum = new MustacheEnum(StringUtils.toPascalCase(enumClassName), enumValues); + ResourceCache.addToEnumClasses(mustacheEnum); + } +} diff --git a/src/main/java/com/twilio/oai/modern/ResourceCache.java b/src/main/java/com/twilio/oai/modern/ResourceCache.java new file mode 100644 index 000000000..d10cfb012 --- /dev/null +++ b/src/main/java/com/twilio/oai/modern/ResourceCache.java @@ -0,0 +1,54 @@ +package com.twilio.oai.modern; + +import com.twilio.oai.java.nestedmodels.MustacheEnum; +import com.twilio.oai.java.nestedmodels.MustacheModel; +import lombok.Getter; +import lombok.Setter; +import org.openapitools.codegen.CodegenModel; +import org.openapitools.codegen.CodegenParameter; +import org.openapitools.codegen.CodegenProperty; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.TreeSet; + +public class ResourceCache { + @Getter + @Setter + public static String resourceName; + + @Getter + @Setter + public static Set response = new TreeSet<>((p1, p2) -> p1.baseName.compareTo(p2.baseName)); + + @Getter + public static List allModelsByDefaultGenerator = new ArrayList<>(); + @Getter + public static Set modelClassesForMustache = new HashSet<>(); + @Getter + public static Set enumsClassesForMustache = new HashSet<>(); + + public static void setAllModelsByDefaultGenerator(List allModelsByDefaultGenerator) { + ResourceCache.allModelsByDefaultGenerator = new ArrayList<>(allModelsByDefaultGenerator); + } + + public static void addToModelClasses(MustacheModel mustacheModel) { + ResourceCache.modelClassesForMustache.add(mustacheModel); + } + + public static void addToEnumClasses(MustacheEnum mustacheEnum) { + ResourceCache.enumsClassesForMustache.add(mustacheEnum); + } + + public static void clear() { + resourceName = null; + modelClassesForMustache.clear(); + enumsClassesForMustache.clear(); + response.clear(); + } + public static void clearAllModelsByDefaultGenerator() { + allModelsByDefaultGenerator.clear(); + } +} From 9e2a1d8ab2d36c4d3925a5f313e5941cb038bcec Mon Sep 17 00:00:00 2001 From: sbansla <104902068+sbansla@users.noreply.github.com> Date: Wed, 6 Aug 2025 12:53:56 +0530 Subject: [PATCH 03/38] doc: added uml diagram for enum processor design (#665) added uml diagram for enum processor design --- .../twilio/oai/java/processor/enums/enum.puml | 68 +++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 src/main/java/com/twilio/oai/java/processor/enums/enum.puml diff --git a/src/main/java/com/twilio/oai/java/processor/enums/enum.puml b/src/main/java/com/twilio/oai/java/processor/enums/enum.puml new file mode 100644 index 000000000..e19eb568c --- /dev/null +++ b/src/main/java/com/twilio/oai/java/processor/enums/enum.puml @@ -0,0 +1,68 @@ +@startuml + interface EnumProcessor { + + boolean shouldProcess(T schema) + + void process(T schema) + + OpenApiEnumType getType() + } + + package "enums" { + interface ParameterEnumProcessor { + + boolean shouldProcess(CodegenParameter schema) + + void process(CodegenParameter schema) + + OpenApiEnumType getType() + } + + interface PropertyEnumProcessor { + + boolean shouldProcess(CodegenProperty schema) + + void process(CodegenProperty schema) + + OpenApiEnumType getType() + } + + class ParameterEnumProcessorFactory { + - List processors + + void applyProcessor(CodegenParameter codegenParameter) + } + + class PropertyEnumProcessorFactory { + - List processors + + void applyProcessor(CodegenProperty codegenProperty) + } + + package "parameter" { + class InlineBodyEnumProcessor + class InlineBodyListEnumProcessor + class ReusableBodyEnumProcessor + class ReusableBodyListEnumProcessor + class InlineListParamEnumProcessor + class InlineParamEnumProcessor + class ReusableListParamEnumProcessor + class ReusableParamEnumProcessor + } + + package "property" { + class InlineListPropEnumProcessor + class InlinePropEnumProcessor + class ReusableListPropEnumProcessor + class ReusablePropEnumProcessor + } + } + +EnumProcessor <|.. ParameterEnumProcessor +EnumProcessor <|.. PropertyEnumProcessor +ParameterEnumProcessorFactory o-- ParameterEnumProcessor +PropertyEnumProcessorFactory o-- PropertyEnumProcessor + +ParameterEnumProcessor <|-- InlineBodyEnumProcessor +ParameterEnumProcessor <|-- InlineBodyListEnumProcessor +ParameterEnumProcessor <|-- ReusableBodyEnumProcessor +ParameterEnumProcessor <|-- ReusableBodyListEnumProcessor +ParameterEnumProcessor <|-- InlineListParamEnumProcessor +ParameterEnumProcessor <|-- InlineParamEnumProcessor +ParameterEnumProcessor <|-- ReusableListParamEnumProcessor +ParameterEnumProcessor <|-- ReusableParamEnumProcessor + +PropertyEnumProcessor <|-- InlineListPropEnumProcessor +PropertyEnumProcessor <|-- InlinePropEnumProcessor +PropertyEnumProcessor <|-- ReusableListPropEnumProcessor +PropertyEnumProcessor <|-- ReusablePropEnumProcessor +@enduml \ No newline at end of file From fa68524d4605dcef19a49dd82178767f2fef8e7b Mon Sep 17 00:00:00 2001 From: sbansla <104902068+sbansla@users.noreply.github.com> Date: Wed, 6 Aug 2025 13:03:04 +0530 Subject: [PATCH 04/38] chore: Create common factory for enum (#666) Added spec for enum and created common factory for processing parameter and property type enums. --- examples/spec/twilio_enum_v1.yaml | 106 ++++++++++++++++++ .../processor/enums/EnumProcessorFactory.java | 69 ++++++++++++ .../twilio/oai/java/processor/enums/enum.puml | 28 +++-- .../ParameterEnumProcessorFactory.java | 43 ------- .../PropertyEnumProcessorFactory.java | 30 ----- 5 files changed, 188 insertions(+), 88 deletions(-) create mode 100644 examples/spec/twilio_enum_v1.yaml create mode 100644 src/main/java/com/twilio/oai/java/processor/enums/EnumProcessorFactory.java delete mode 100644 src/main/java/com/twilio/oai/java/processor/enums/parameter/ParameterEnumProcessorFactory.java delete mode 100644 src/main/java/com/twilio/oai/java/processor/enums/property/PropertyEnumProcessorFactory.java diff --git a/examples/spec/twilio_enum_v1.yaml b/examples/spec/twilio_enum_v1.yaml new file mode 100644 index 000000000..2de5aaa20 --- /dev/null +++ b/examples/spec/twilio_enum_v1.yaml @@ -0,0 +1,106 @@ +info: + contact: + email: support@twilio.com + name: Twilio Support + url: https://support.twilio.com + description: This is the public Twilio REST API. + license: + name: Apache 2.0 + url: https://www.apache.org/licenses/LICENSE-2.0.html + termsOfService: https://www.twilio.com/legal/tos + title: Twilio - CONTENT + version: 1.11.0 +openapi: 3.0.1 + +paths: + /v1/content: + servers: + - url: https://enum.twilio.com + get: + summary: Retrieve items with various filter options + parameters: + # PARAMETER_SINGLE + - name: singleParam + in: query + description: A single enum value as a query parameter + required: false + schema: + type: string + enum: + - asc + - desc + example: asc + + # PARAMETER_ARRAY + - name: arrayParam + in: query + description: Order items using an array of enums + required: false + schema: + type: array + items: + type: string + enum: + - asc + - desc + example: [asc] + + # PARAMETER_ARRAY + - name: arrayParamRef + in: query + required: false + description: An array parameter referencing a reusable schema + schema: + type: array + items: + $ref: '#/components/schemas/singleReusable' + + - name: singleParamRef + in: header + schema: + $ref: '#/components/schemas/singleReusable' + + responses: + '200': + description: A list of items + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/Item' + +components: + schemas: + Item: + type: object + properties: + # PROPERTY_SINGLE + singleProperty: + type: string + enum: [available, pending, sold] + description: A single enum value as a property in a schema + example: available + + # PROPERTY_ARRAY + arrayProperty: + type: array + items: + type: string + enum: [new, sale, featured] + description: An array of enum values in a schema property + example: [new, featured] + + # REUSABLE_ARRAY + arrayReusable: + type: array + items: + $ref: '#/components/schemas/singleReusable' + description: An array of reusable enum defined in components + example: [electronics, clothing] + + # REUSABLE_SINGLE + singleReusable: + type: string + enum: [electronics, furniture, clothing] + description: A reusable single-value enum defined in components \ No newline at end of file diff --git a/src/main/java/com/twilio/oai/java/processor/enums/EnumProcessorFactory.java b/src/main/java/com/twilio/oai/java/processor/enums/EnumProcessorFactory.java new file mode 100644 index 000000000..a7ce62a03 --- /dev/null +++ b/src/main/java/com/twilio/oai/java/processor/enums/EnumProcessorFactory.java @@ -0,0 +1,69 @@ +package com.twilio.oai.java.processor.enums; + +import com.twilio.oai.java.processor.enums.parameter.ParameterEnumProcessor; +import com.twilio.oai.java.processor.enums.parameter.body.InlineBodyEnumProcessor; +import com.twilio.oai.java.processor.enums.parameter.body.InlineBodyListEnumProcessor; +import com.twilio.oai.java.processor.enums.parameter.body.ReusableBodyEnumProcessor; +import com.twilio.oai.java.processor.enums.parameter.body.ReusableBodyListEnumProcessor; +import com.twilio.oai.java.processor.enums.parameter.param.InlineListParamEnumProcessor; +import com.twilio.oai.java.processor.enums.parameter.param.InlineParamEnumProcessor; +import com.twilio.oai.java.processor.enums.parameter.param.ReusableListParamEnumProcessor; +import com.twilio.oai.java.processor.enums.parameter.param.ReusableParamEnumProcessor; +import com.twilio.oai.java.processor.enums.property.InlineListPropEnumProcessor; +import com.twilio.oai.java.processor.enums.property.InlinePropEnumProcessor; +import com.twilio.oai.java.processor.enums.property.PropertyEnumProcessor; +import com.twilio.oai.java.processor.enums.property.ReusableListPropEnumProcessor; +import com.twilio.oai.java.processor.enums.property.ReusablePropEnumProcessor; +import org.openapitools.codegen.CodegenParameter; +import org.openapitools.codegen.CodegenProperty; + +import java.util.List; + +public class EnumProcessorFactory { + private final List parameterEnumProcessors; + private final List propertyEnumProcessors; + + public EnumProcessorFactory() { + this.parameterEnumProcessors = List.of( + new InlineBodyEnumProcessor(), + new InlineBodyListEnumProcessor(), + new ReusableBodyEnumProcessor(), + new ReusableBodyListEnumProcessor(), + + new InlineListParamEnumProcessor(), + new InlineParamEnumProcessor(), + new ReusableListParamEnumProcessor(), + new ReusableParamEnumProcessor() + ); + + this.propertyEnumProcessors = List.of( + new InlineListPropEnumProcessor(), + new InlinePropEnumProcessor(), + new ReusableListPropEnumProcessor(), + new ReusablePropEnumProcessor() + ); + } + + public void applyProcessor(CodegenParameter codegenParameter) { + if (codegenParameter.dataFormat != null && codegenParameter.dataFormat.equals("http-method")) { + return; + } + for (ParameterEnumProcessor parameterEnumProcessor: parameterEnumProcessors) { + if (parameterEnumProcessor.shouldProcess(codegenParameter)) { + parameterEnumProcessor.process(codegenParameter); + return; // Exit after the first processor that applies + } + } + } + public void applyProcessor(CodegenProperty codegenProperty) { + if (codegenProperty.dataFormat != null && codegenProperty.dataFormat.equals("http-method")) { + return; + } + for (PropertyEnumProcessor propertyEnumProcessor: propertyEnumProcessors) { + if (propertyEnumProcessor.shouldProcess(codegenProperty)) { + propertyEnumProcessor.process(codegenProperty); + return; // Exit after the first processor that applies + } + } + } +} \ No newline at end of file diff --git a/src/main/java/com/twilio/oai/java/processor/enums/enum.puml b/src/main/java/com/twilio/oai/java/processor/enums/enum.puml index e19eb568c..30d0d9018 100644 --- a/src/main/java/com/twilio/oai/java/processor/enums/enum.puml +++ b/src/main/java/com/twilio/oai/java/processor/enums/enum.puml @@ -5,7 +5,7 @@ + OpenApiEnumType getType() } - package "enums" { + interface ParameterEnumProcessor { + boolean shouldProcess(CodegenParameter schema) + void process(CodegenParameter schema) @@ -17,18 +17,16 @@ + void process(CodegenProperty schema) + OpenApiEnumType getType() } - - class ParameterEnumProcessorFactory { - - List processors + + class EnumProcessorFactory { + - List parameterEnumProcessors + - List propertyEnumProcessors + + EnumProcessorFactory() + void applyProcessor(CodegenParameter codegenParameter) - } - - class PropertyEnumProcessorFactory { - - List processors + void applyProcessor(CodegenProperty codegenProperty) } - package "parameter" { + class InlineBodyEnumProcessor class InlineBodyListEnumProcessor class ReusableBodyEnumProcessor @@ -37,20 +35,20 @@ class InlineParamEnumProcessor class ReusableListParamEnumProcessor class ReusableParamEnumProcessor - } - package "property" { + + class InlineListPropEnumProcessor class InlinePropEnumProcessor class ReusableListPropEnumProcessor class ReusablePropEnumProcessor - } - } + EnumProcessor <|.. ParameterEnumProcessor EnumProcessor <|.. PropertyEnumProcessor -ParameterEnumProcessorFactory o-- ParameterEnumProcessor -PropertyEnumProcessorFactory o-- PropertyEnumProcessor + +EnumProcessorFactory o-- ParameterEnumProcessor +EnumProcessorFactory o-- PropertyEnumProcessor ParameterEnumProcessor <|-- InlineBodyEnumProcessor ParameterEnumProcessor <|-- InlineBodyListEnumProcessor diff --git a/src/main/java/com/twilio/oai/java/processor/enums/parameter/ParameterEnumProcessorFactory.java b/src/main/java/com/twilio/oai/java/processor/enums/parameter/ParameterEnumProcessorFactory.java deleted file mode 100644 index c77d4560a..000000000 --- a/src/main/java/com/twilio/oai/java/processor/enums/parameter/ParameterEnumProcessorFactory.java +++ /dev/null @@ -1,43 +0,0 @@ -package com.twilio.oai.java.processor.enums.parameter; - -import com.twilio.oai.java.processor.enums.parameter.body.InlineBodyEnumProcessor; -import com.twilio.oai.java.processor.enums.parameter.body.InlineBodyListEnumProcessor; -import com.twilio.oai.java.processor.enums.parameter.body.ReusableBodyEnumProcessor; -import com.twilio.oai.java.processor.enums.parameter.body.ReusableBodyListEnumProcessor; -import com.twilio.oai.java.processor.enums.parameter.param.InlineListParamEnumProcessor; -import com.twilio.oai.java.processor.enums.parameter.param.InlineParamEnumProcessor; -import com.twilio.oai.java.processor.enums.parameter.param.ReusableListParamEnumProcessor; -import com.twilio.oai.java.processor.enums.parameter.param.ReusableParamEnumProcessor; -import org.openapitools.codegen.CodegenParameter; - -import java.util.List; - -public class ParameterEnumProcessorFactory { - private final List processors; - - public ParameterEnumProcessorFactory(final List processors) { - this.processors = List.of( - new InlineBodyEnumProcessor(), - new InlineBodyListEnumProcessor(), - new ReusableBodyEnumProcessor(), - new ReusableBodyListEnumProcessor(), - - new InlineListParamEnumProcessor(), - new InlineParamEnumProcessor(), - new ReusableListParamEnumProcessor(), - new ReusableParamEnumProcessor() - ); - } - - public void applyProcessor(CodegenParameter codegenParameter) { - if (codegenParameter.dataFormat != null && codegenParameter.dataFormat.equals("http-method")) { - return; - } - for (ParameterEnumProcessor parameterEnumProcessor: processors) { - if (parameterEnumProcessor.shouldProcess(codegenParameter)) { - parameterEnumProcessor.process(codegenParameter); - return; // Exit after the first processor that applies - } - } - } -} diff --git a/src/main/java/com/twilio/oai/java/processor/enums/property/PropertyEnumProcessorFactory.java b/src/main/java/com/twilio/oai/java/processor/enums/property/PropertyEnumProcessorFactory.java deleted file mode 100644 index 3f8a999df..000000000 --- a/src/main/java/com/twilio/oai/java/processor/enums/property/PropertyEnumProcessorFactory.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.twilio.oai.java.processor.enums.property; - -import org.openapitools.codegen.CodegenProperty; - -import java.util.List; - -public class PropertyEnumProcessorFactory { - private final List processors; - - public PropertyEnumProcessorFactory(final List processors) { - this.processors = List.of( - new InlineListPropEnumProcessor(), - new InlinePropEnumProcessor(), - new ReusableListPropEnumProcessor(), - new ReusablePropEnumProcessor() - ); - } - - public void applyProcessor(CodegenProperty codegenProperty) { - if (codegenProperty.dataFormat != null && codegenProperty.dataFormat.equals("http-method")) { - return; - } - for (PropertyEnumProcessor propertyEnumProcessor: processors) { - if (propertyEnumProcessor.shouldProcess(codegenProperty)) { - propertyEnumProcessor.process(codegenProperty); - return; // Exit after the first processor that applies - } - } - } -} From 14b6c73f6fc3717abfdf34e3ffdcaa50b531e808 Mon Sep 17 00:00:00 2001 From: sbansla <104902068+sbansla@users.noreply.github.com> Date: Wed, 6 Aug 2025 14:44:54 +0530 Subject: [PATCH 05/38] chore: Parameter processor for twilio-java generatiom (#667) Added parameter processor and injected enum factory. Made enum factory as singleton class. --- .../processor/enums/EnumProcessorFactory.java | 28 ++++++++++++++++- .../parameter/ParameterProcessor.java | 30 +++++++++++++++++++ 2 files changed, 57 insertions(+), 1 deletion(-) create mode 100644 src/main/java/com/twilio/oai/java/processor/parameter/ParameterProcessor.java diff --git a/src/main/java/com/twilio/oai/java/processor/enums/EnumProcessorFactory.java b/src/main/java/com/twilio/oai/java/processor/enums/EnumProcessorFactory.java index a7ce62a03..0e374be98 100644 --- a/src/main/java/com/twilio/oai/java/processor/enums/EnumProcessorFactory.java +++ b/src/main/java/com/twilio/oai/java/processor/enums/EnumProcessorFactory.java @@ -19,11 +19,37 @@ import java.util.List; +/* + * Factory class to manage and apply enum processors for CodegenParameter and CodegenProperty. + * + * This class is implemented as a singleton to ensure that only one instance of the factory exists + * throughout the application. + * + * The processors (e.g., `InlineBodyEnumProcessor`, `ReusablePropEnumProcessor`) are instantiated + * during the initialization of the factory. Since the factory is a singleton, these processor + * instances effectively behave as singletons within the context of the factory. There is no need + * to make these processor classes singleton themselves, as their lifecycle is already managed + * by the factory. + * + */ public class EnumProcessorFactory { + + public static EnumProcessorFactory instance; private final List parameterEnumProcessors; private final List propertyEnumProcessors; - public EnumProcessorFactory() { + public static synchronized EnumProcessorFactory getInstance() { + if (instance == null) { + synchronized (EnumProcessorFactory.class) { + if (instance == null) { + instance = new EnumProcessorFactory(); + } + } + } + return instance; + } + + private EnumProcessorFactory() { this.parameterEnumProcessors = List.of( new InlineBodyEnumProcessor(), new InlineBodyListEnumProcessor(), diff --git a/src/main/java/com/twilio/oai/java/processor/parameter/ParameterProcessor.java b/src/main/java/com/twilio/oai/java/processor/parameter/ParameterProcessor.java new file mode 100644 index 000000000..0e06fcb0f --- /dev/null +++ b/src/main/java/com/twilio/oai/java/processor/parameter/ParameterProcessor.java @@ -0,0 +1,30 @@ +package com.twilio.oai.java.processor.parameter; + +import com.twilio.oai.java.processor.enums.EnumProcessorFactory; +import org.openapitools.codegen.CodegenOperation; + +/* + * This class includes processing of path, query, header and required parameters. + */ +public class ParameterProcessor { + + public static ParameterProcessor instance; + EnumProcessorFactory enumProcessorFactory; + private ParameterProcessor () { + this.enumProcessorFactory = EnumProcessorFactory.getInstance(); + } + + public static synchronized ParameterProcessor getInstance() { + if (instance == null) { + instance = new ParameterProcessor(); + } + return instance; + } + + public void process(final CodegenOperation codegenOperation) { + codegenOperation.queryParams.forEach(param -> enumProcessorFactory.applyProcessor(param)); + codegenOperation.pathParams.forEach(param -> enumProcessorFactory.applyProcessor(param)); + codegenOperation.headerParams.forEach(param -> enumProcessorFactory.applyProcessor(param)); + codegenOperation.requiredParams.forEach(param -> enumProcessorFactory.applyProcessor(param)); + } +} \ No newline at end of file From fe09ea5b6d2aaae3fc4ecae25321e4e2a88fb246 Mon Sep 17 00:00:00 2001 From: sbansla <104902068+sbansla@users.noreply.github.com> Date: Wed, 6 Aug 2025 15:41:00 +0530 Subject: [PATCH 06/38] created operation processor (#668) Created operation processor and injected in api resource builder. --- .../twilio/oai/TwilioJavaGeneratorModern.java | 9 ++-- .../oai/java/JavaApiResourceBuilder.java | 45 ++++++++++++++++++- .../processor/JavaOperationProcessor.java | 27 +++++++++++ 3 files changed, 76 insertions(+), 5 deletions(-) create mode 100644 src/main/java/com/twilio/oai/java/processor/JavaOperationProcessor.java diff --git a/src/main/java/com/twilio/oai/TwilioJavaGeneratorModern.java b/src/main/java/com/twilio/oai/TwilioJavaGeneratorModern.java index d874c0ec7..946423d83 100644 --- a/src/main/java/com/twilio/oai/TwilioJavaGeneratorModern.java +++ b/src/main/java/com/twilio/oai/TwilioJavaGeneratorModern.java @@ -118,8 +118,11 @@ public String getHelp() { } private JavaApiResource processCodegenOperations(List operations) { - JavaApiResourceBuilder javaApiResourceBuilder = new JavaApiResourceBuilder(this); - javaApiResourceBuilder.process(operations); - return javaApiResourceBuilder.build(); + JavaApiResource apiResource = new JavaApiResourceBuilder(this, operations) + .resourceName() + .recordKey() + .processOperations() + .build(); + return apiResource; } } diff --git a/src/main/java/com/twilio/oai/java/JavaApiResourceBuilder.java b/src/main/java/com/twilio/oai/java/JavaApiResourceBuilder.java index 3a6d3e11d..a20104404 100644 --- a/src/main/java/com/twilio/oai/java/JavaApiResourceBuilder.java +++ b/src/main/java/com/twilio/oai/java/JavaApiResourceBuilder.java @@ -1,16 +1,57 @@ package com.twilio.oai.java; import com.twilio.oai.TwilioJavaGeneratorModern; +import com.twilio.oai.common.Utility; +import com.twilio.oai.java.processor.JavaOperationProcessor; +import com.twilio.oai.modern.ResourceCache; +import org.apache.commons.lang3.StringUtils; import org.openapitools.codegen.CodegenOperation; +import java.util.ArrayList; +import java.util.Arrays; import java.util.List; +import static com.twilio.oai.common.ApplicationConstants.PATH_SEPARATOR_PLACEHOLDER; + public class JavaApiResourceBuilder { + // ApiName, example: Message + String resourceName; + // key used for pagination in list operation + String recordKey; TwilioJavaGeneratorModern twilioJavaGenerator; - public JavaApiResourceBuilder(TwilioJavaGeneratorModern twilioJavaGenerator) { + final JavaOperationProcessor operationProcessor; + List operations; + public JavaApiResourceBuilder(TwilioJavaGeneratorModern twilioJavaGenerator, List operations) { this.twilioJavaGenerator = twilioJavaGenerator; + this.operations = operations; + this.operationProcessor = JavaOperationProcessor.getInstance(); + } + + // Bug: path should not end with '/' + // example: /2010-04-01/Accounts.json, otherwise directory structure will not be created properly. + public JavaApiResourceBuilder resourceName() { + ResourceCache.setResourceName(""); // Clear + operations.forEach(co -> { + List filePathArray = new ArrayList<>(Arrays.asList(co.baseName.split(PATH_SEPARATOR_PLACEHOLDER))); + if (!filePathArray.isEmpty() && StringUtils.isNotBlank(filePathArray.get(filePathArray.size() - 1))) { + resourceName = filePathArray.get(filePathArray.size() - 1); + } + }); + ResourceCache.setResourceName(resourceName); + return this; } - public void process(List operations) { + + public JavaApiResourceBuilder recordKey() { + this.recordKey = Utility.getRecordKey(ResourceCache.allModelsByDefaultGenerator, operations); + return this; + } + + public JavaApiResourceBuilder processOperations() { + if (this.resourceName == null) { + throw new RuntimeException("Resource name must be set before processing operations."); + } + operations.forEach(operation -> operationProcessor.process(operation)); + return this; } public JavaApiResource build() { diff --git a/src/main/java/com/twilio/oai/java/processor/JavaOperationProcessor.java b/src/main/java/com/twilio/oai/java/processor/JavaOperationProcessor.java new file mode 100644 index 000000000..bc351e4ae --- /dev/null +++ b/src/main/java/com/twilio/oai/java/processor/JavaOperationProcessor.java @@ -0,0 +1,27 @@ +package com.twilio.oai.java.processor; + +import com.twilio.oai.java.processor.parameter.ParameterProcessor; +import org.openapitools.codegen.CodegenOperation; + +public class JavaOperationProcessor { + + public static JavaOperationProcessor instance; + public static synchronized JavaOperationProcessor getInstance() { + if (instance == null) { + synchronized (JavaOperationProcessor.class) { + if (instance == null) { + instance = new JavaOperationProcessor(); + } + } + } + return instance; + } + + private JavaOperationProcessor() { + + } + + public void process(final CodegenOperation codegenOperation) { + ParameterProcessor.getInstance().process(codegenOperation); + } +} From 43f51ff9db21b6c7d462bdf06bd9f4c7c20738e6 Mon Sep 17 00:00:00 2001 From: sbansla <104902068+sbansla@users.noreply.github.com> Date: Wed, 6 Aug 2025 15:55:16 +0530 Subject: [PATCH 07/38] added urlencoded processor (#669) Added url encoded body processor --- .../twilio/oai/java/MustacheConstants.java | 55 +++++++++++++++++++ .../processor/JavaOperationProcessor.java | 2 + .../requestbody/RequestBodyProcessor.java | 9 +++ .../RequestBodyProcessorFactory.java | 36 ++++++++++++ .../requestbody/UrlEncodedProcessor.java | 31 +++++++++++ 5 files changed, 133 insertions(+) create mode 100644 src/main/java/com/twilio/oai/java/MustacheConstants.java create mode 100644 src/main/java/com/twilio/oai/java/processor/requestbody/RequestBodyProcessor.java create mode 100644 src/main/java/com/twilio/oai/java/processor/requestbody/RequestBodyProcessorFactory.java create mode 100644 src/main/java/com/twilio/oai/java/processor/requestbody/UrlEncodedProcessor.java diff --git a/src/main/java/com/twilio/oai/java/MustacheConstants.java b/src/main/java/com/twilio/oai/java/MustacheConstants.java new file mode 100644 index 000000000..3c7993f5e --- /dev/null +++ b/src/main/java/com/twilio/oai/java/MustacheConstants.java @@ -0,0 +1,55 @@ +package com.twilio.oai.java; + +import lombok.AccessLevel; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.RequiredArgsConstructor; + +import java.util.Map; + + +// This class contains only those constants which are used in mustache templates. +@NoArgsConstructor(access = AccessLevel.PRIVATE) +public class MustacheConstants { + // It is used to define the content type of the request body in mustache templates which is defined in twilio-java. + // If content type constant changes in twilio-java then it's value should be updated as well. + public static final String X_REQUEST_LANGUAGE_CONTENT_TYPE_CONSTANT = "x-request-content-type"; + public static final String X_REQUEST_HTTP_METHOD = "x-http-method"; + public static final String X_IS_LIST_OP = "x-is-list-op"; + public static final String ACTION_TYPE = "x-common-action-type"; + public static final String ACTION_METHOD = "x-common-action-method"; + + public static final Map serializaationMapping = Map.of( + "application/x-www-form-urlencoded", "if ($paramName != null) { request.addPostParam($stringCapParamName, $paramName.toString())}", + "application/json", "Json", + "multipart/form-data", "MultipartFormData" + ); + + + // Used with "x-common-action-type" + @Getter + @RequiredArgsConstructor + public enum ActionType { + CREATOR("Creator"), + READER("Reader"), + UPDATER("Updater"), + DELETER("Deleter"), + FETCHER("Fetcher"); + + private final String value; + } + + // Used with "x-common-action-method" + @Getter + @RequiredArgsConstructor + public enum ActionMethod { + CREATE("create"), + READ("read"), + UPDATE("update"), + DELETE("delete"), + FETCH("fetch"); + + private final String value; + } + +} diff --git a/src/main/java/com/twilio/oai/java/processor/JavaOperationProcessor.java b/src/main/java/com/twilio/oai/java/processor/JavaOperationProcessor.java index bc351e4ae..c83438bcf 100644 --- a/src/main/java/com/twilio/oai/java/processor/JavaOperationProcessor.java +++ b/src/main/java/com/twilio/oai/java/processor/JavaOperationProcessor.java @@ -1,6 +1,7 @@ package com.twilio.oai.java.processor; import com.twilio.oai.java.processor.parameter.ParameterProcessor; +import com.twilio.oai.java.processor.requestbody.RequestBodyProcessorFactory; import org.openapitools.codegen.CodegenOperation; public class JavaOperationProcessor { @@ -23,5 +24,6 @@ private JavaOperationProcessor() { public void process(final CodegenOperation codegenOperation) { ParameterProcessor.getInstance().process(codegenOperation); + RequestBodyProcessorFactory.getInstance().process(codegenOperation); } } diff --git a/src/main/java/com/twilio/oai/java/processor/requestbody/RequestBodyProcessor.java b/src/main/java/com/twilio/oai/java/processor/requestbody/RequestBodyProcessor.java new file mode 100644 index 000000000..9f8377821 --- /dev/null +++ b/src/main/java/com/twilio/oai/java/processor/requestbody/RequestBodyProcessor.java @@ -0,0 +1,9 @@ +package com.twilio.oai.java.processor.requestbody; + +import org.openapitools.codegen.CodegenOperation; + +public interface RequestBodyProcessor { + void process(CodegenOperation codegenOperation); + String getContentType(); + boolean shouldProcess(CodegenOperation codegenOperation); +} diff --git a/src/main/java/com/twilio/oai/java/processor/requestbody/RequestBodyProcessorFactory.java b/src/main/java/com/twilio/oai/java/processor/requestbody/RequestBodyProcessorFactory.java new file mode 100644 index 000000000..f2cdfd749 --- /dev/null +++ b/src/main/java/com/twilio/oai/java/processor/requestbody/RequestBodyProcessorFactory.java @@ -0,0 +1,36 @@ +package com.twilio.oai.java.processor.requestbody; + +import org.openapitools.codegen.CodegenOperation; + +import java.util.List; + +public class RequestBodyProcessorFactory { + private static RequestBodyProcessorFactory instance; + private final List requestBodyProcessors; + + private RequestBodyProcessorFactory() { + this.requestBodyProcessors = List.of( + new UrlEncodedProcessor() + ); + } + + public static synchronized RequestBodyProcessorFactory getInstance() { + if (instance == null) { + synchronized (RequestBodyProcessorFactory.class) { + if (instance == null) { + instance = new RequestBodyProcessorFactory(); + } + } + } + return instance; + } + + public void process(final CodegenOperation codegenOperation) { + for (RequestBodyProcessor requestBodyProcessor: requestBodyProcessors) { + if (requestBodyProcessor.shouldProcess(codegenOperation)) { + requestBodyProcessor.process(codegenOperation); + return; // Exit after the first processor that applies + } + } + } +} diff --git a/src/main/java/com/twilio/oai/java/processor/requestbody/UrlEncodedProcessor.java b/src/main/java/com/twilio/oai/java/processor/requestbody/UrlEncodedProcessor.java new file mode 100644 index 000000000..5ec8afc5a --- /dev/null +++ b/src/main/java/com/twilio/oai/java/processor/requestbody/UrlEncodedProcessor.java @@ -0,0 +1,31 @@ +package com.twilio.oai.java.processor.requestbody; + +import com.twilio.oai.java.processor.enums.EnumProcessorFactory; +import org.openapitools.codegen.CodegenOperation; + +import static com.twilio.oai.common.ApplicationConstants.X_REQUEST_CONTENT_TYPE; +import static com.twilio.oai.java.MustacheConstants.X_REQUEST_LANGUAGE_CONTENT_TYPE_CONSTANT; + +public class UrlEncodedProcessor implements RequestBodyProcessor { + final EnumProcessorFactory enumFactory = EnumProcessorFactory.getInstance(); + @Override + public void process(CodegenOperation codegenOperation) { + codegenOperation.vendorExtensions.put(X_REQUEST_CONTENT_TYPE, getContentType()); + codegenOperation.vendorExtensions.put(X_REQUEST_LANGUAGE_CONTENT_TYPE_CONSTANT, "FORM_URLENCODED"); + codegenOperation.formParams.forEach(parameter -> { + enumFactory.applyProcessor(parameter); + //Promoter.addPromoter(parameter); + }); + } + + @Override + public String getContentType() { + return "application/x-www-form-urlencoded"; + } + + @Override + public boolean shouldProcess(final CodegenOperation codegenOperation) { + if (codegenOperation.formParams != null && !codegenOperation.formParams.isEmpty()) return true; + return false; + } +} From 010b0e8a35ca4bf895e9ecd38aca99d74e376b04 Mon Sep 17 00:00:00 2001 From: sbansla <104902068+sbansla@users.noreply.github.com> Date: Wed, 6 Aug 2025 16:05:31 +0530 Subject: [PATCH 08/38] Update schema mapping (#670) added typemapping to convert format to java specific data type and added importmapping for the java datatypes that are mapping to format in open api spec. --- .../twilio/oai/TwilioJavaGeneratorModern.java | 15 +- .../twilio/oai/java/JavaTemplateUpdater.java | 151 ++++++++++++++++++ .../java/format/JavaUpdateDefaultMapping.java | 88 ++++++++++ .../OpenApiSpecFormatFeatureConstants.java | 114 +++++++++++++ 4 files changed, 367 insertions(+), 1 deletion(-) create mode 100644 src/main/java/com/twilio/oai/java/JavaTemplateUpdater.java create mode 100644 src/main/java/com/twilio/oai/java/format/JavaUpdateDefaultMapping.java create mode 100644 src/main/java/com/twilio/oai/java/format/OpenApiSpecFormatFeatureConstants.java diff --git a/src/main/java/com/twilio/oai/TwilioJavaGeneratorModern.java b/src/main/java/com/twilio/oai/TwilioJavaGeneratorModern.java index 946423d83..5643218dd 100644 --- a/src/main/java/com/twilio/oai/TwilioJavaGeneratorModern.java +++ b/src/main/java/com/twilio/oai/TwilioJavaGeneratorModern.java @@ -3,8 +3,12 @@ import com.google.common.collect.ImmutableMap; import com.samskivert.mustache.Mustache.Lambda; import com.twilio.oai.common.EnumConstants; +import com.twilio.oai.common.Utility; import com.twilio.oai.java.JavaApiResource; import com.twilio.oai.java.JavaApiResourceBuilder; +import com.twilio.oai.java.JavaTemplateUpdater; +import com.twilio.oai.java.format.JavaUpdateDefaultMapping; +import com.twilio.oai.modern.ResourceCache; import com.twilio.oai.resolver.java.JavaCaseResolver; import com.twilio.oai.resource.ResourceMap; import com.twilio.oai.templating.mustache.ReplaceHyphenLambda; @@ -22,7 +26,10 @@ public class TwilioJavaGeneratorModern extends JavaClientCodegen { + + JavaUpdateDefaultMapping javaUpdateDefaultMapping = new JavaUpdateDefaultMapping(); private final TwilioCodegenAdapter twilioCodegen; + JavaTemplateUpdater templateUpdater = new JavaTemplateUpdater(); private final DirectoryStructureService directoryStructureService = new DirectoryStructureService( additionalProperties, new ResourceMap(new Inflector()), @@ -43,6 +50,8 @@ public String toExampleValue(Schema schema) { public void processOpts() { super.processOpts(); this.modelTemplateFiles.clear(); + javaUpdateDefaultMapping.typeMapping(this.typeMapping); + javaUpdateDefaultMapping.importMapping(this.importMapping); twilioCodegen.processOpts(); } @@ -54,6 +63,7 @@ public void processOpenAPI(final OpenAPI openAPI) { twilioCodegen.setDomain(domain); twilioCodegen.setVersion(version); twilioCodegen.setOutputDir(domain, version); + javaUpdateDefaultMapping.removePropertiesFromCustomModels(openAPI); directoryStructureService.configure(openAPI); } @@ -72,6 +82,9 @@ public String getTypeDeclaration(Schema schema) { @Override public Map postProcessAllModels(final Map allModels) { final Map results = super.postProcessAllModels(allModels); + ResourceCache.clearAllModelsByDefaultGenerator(); + // Update allModels from Default generator in ResourceCache. + Utility.addModelsToLocalModelList(results, ResourceCache.getAllModelsByDefaultGenerator()); directoryStructureService.postProcessAllModels(results, modelFormatMap); // Return an empty collection so no model files get generated. @@ -88,7 +101,7 @@ public String getSchemaType(Schema p) { @Override public OperationsMap postProcessOperationsWithModels(final OperationsMap objs, List allModels) { final OperationsMap results = super.postProcessOperationsWithModels(objs, allModels); - //ResourceCache.clear(); + ResourceCache.clear(); final List opList = directoryStructureService.processOperations(results); JavaApiResource apiResource = processCodegenOperations(opList); results.put("resources", apiResource); diff --git a/src/main/java/com/twilio/oai/java/JavaTemplateUpdater.java b/src/main/java/com/twilio/oai/java/JavaTemplateUpdater.java new file mode 100644 index 000000000..7a39da4fb --- /dev/null +++ b/src/main/java/com/twilio/oai/java/JavaTemplateUpdater.java @@ -0,0 +1,151 @@ +package com.twilio.oai.java; + +import com.twilio.oai.TwilioJavaGeneratorModern; +import com.twilio.oai.common.EnumConstants; +import org.openapitools.codegen.CodegenOperation; + +import java.util.AbstractMap; +import java.util.Map; + +import static com.twilio.oai.java.MustacheConstants.ActionMethod; +import static com.twilio.oai.java.MustacheConstants.ActionType; + +/* +The JavaTemplateFile class is responsible for managing template mappings for Java code generation. +It defines mappings between operation IDs (starting strings) +and corresponding template files (mustache files) along with their generated file extensions. +Example: + Key: Represents the starting string of the operationId (e.g., "create", "fetch"). + Value: Represents a mapping between the mustache template file and the generated file extension using AbstractMap.SimpleEntry. +Note: We don't creating mapping based in http method, we create mapping using operationId. + */ +public class JavaTemplateUpdater { + public static final String API_TEMPLATE = "api.mustache"; + public static final String NESTED_MODELS = "models.mustache"; + + Map apiOperationTemplate; + Map apiTemplate; + + public JavaTemplateUpdater() { + // Available templates for Java code generation. + apiOperationTemplate = Map.of( + "create", new AbstractMap.SimpleEntry<>("creator.mustache", "Creator.java"), + "fetch", new AbstractMap.SimpleEntry<>("fetcher.mustache", "Fetcher.java"), + "delete", new AbstractMap.SimpleEntry<>("deleter.mustache", "Deleter.java"), + "list", new AbstractMap.SimpleEntry<>("reader.mustache", "Reader.java"), + "update", new AbstractMap.SimpleEntry<>("updater.mustache", "Updater.java") + ); + apiTemplate = Map.of( + API_TEMPLATE, new AbstractMap.SimpleEntry<>("api.mustache", ".java") + ); +// Map nestedModelTemplate = Map.of( +// NESTED_MODELS, new AbstractMap.SimpleEntry<>("models.mustache", "Model.java") +// ); + } + + public void addApiTemplate(TwilioJavaGeneratorModern twilioJavaGenerator, java.util.List operations) { + clearApiTemplate(twilioJavaGenerator); + for (CodegenOperation operation : operations) { + String operationId = operation.operationId; + if (operationId == null || operationId.isEmpty()) { + throw new RuntimeException("Operation ID cannot be null or empty for path: " + operation.path); + } + if (Create.isCreate(operation)) { + Create.add(twilioJavaGenerator, operation, apiOperationTemplate); + } else if (List.isList(operation)) { + List.add(twilioJavaGenerator, operation, apiOperationTemplate); + } else if (Update.isUpdate(operation)) { + Update.add(twilioJavaGenerator, operation, apiOperationTemplate); + } else if (Delete.isDelete(operation)) { + Delete.add(twilioJavaGenerator, operation, apiOperationTemplate); + } else if (Fetch.isFetch(operation)) { + Fetch.add(twilioJavaGenerator, operation, apiOperationTemplate); + } else { + throw new RuntimeException("Unsupported operation type for operationId: " + operationId); + } + } + } + + void clearApiTemplate(TwilioJavaGeneratorModern twilioJavaGenerator) { + // Clear the existing templates + twilioJavaGenerator.apiTemplateFiles().clear(); + // Add the default API template + twilioJavaGenerator.apiTemplateFiles().put(API_TEMPLATE, ".java"); + } +} + +class Create { + public static void add(TwilioJavaGeneratorModern twilioJavaGenerator, CodegenOperation codegenOperation, Map apiOperationTemplate) { + codegenOperation.vendorExtensions.put(EnumConstants.SupportedOperation.X_CREATE.getValue(), true); + String key = (String) apiOperationTemplate.get("create").getKey(); + String value = (String) apiOperationTemplate.get("create").getValue(); + twilioJavaGenerator.apiTemplateFiles().put(key, value); + + codegenOperation.vendorExtensions.put(MustacheConstants.ACTION_TYPE, ActionType.CREATOR.getValue()); + codegenOperation.vendorExtensions.put(MustacheConstants.ACTION_METHOD, ActionMethod.CREATE.getValue()); + } + public static boolean isCreate(CodegenOperation codegenOperation) { + return codegenOperation.operationId.toLowerCase().startsWith("create"); + } +} + +class List { + public static void add(TwilioJavaGeneratorModern twilioJavaGenerator, CodegenOperation codegenOperation, Map apiOperationTemplate) { + codegenOperation.vendorExtensions.put(EnumConstants.SupportedOperation.X_LIST.getValue(), true); + String key = (String) apiOperationTemplate.get("list").getKey(); + String value = (String) apiOperationTemplate.get("list").getValue(); + twilioJavaGenerator.apiTemplateFiles().put(key, value); + codegenOperation.vendorExtensions.put(MustacheConstants.X_IS_LIST_OP, true); + + codegenOperation.vendorExtensions.put(MustacheConstants.ACTION_TYPE, ActionType.READER.getValue()); + codegenOperation.vendorExtensions.put(MustacheConstants.ACTION_METHOD, ActionMethod.READ.getValue()); + } + public static boolean isList(CodegenOperation codegenOperation) { + return codegenOperation.operationId.toLowerCase().startsWith("list"); + } +} + +class Update { + public static void add(TwilioJavaGeneratorModern twilioJavaGenerator, CodegenOperation codegenOperation, Map apiOperationTemplate) { + codegenOperation.vendorExtensions.put(EnumConstants.SupportedOperation.X_UPDATE.getValue(), true); + String key = (String) apiOperationTemplate.get("update").getKey(); + String value = (String) apiOperationTemplate.get("update").getValue(); + twilioJavaGenerator.apiTemplateFiles().put(key, value); + + codegenOperation.vendorExtensions.put(MustacheConstants.ACTION_TYPE, ActionType.UPDATER.getValue()); + codegenOperation.vendorExtensions.put(MustacheConstants.ACTION_METHOD, ActionMethod.UPDATE.getValue()); + } + public static boolean isUpdate(CodegenOperation codegenOperation) { + return codegenOperation.operationId.toLowerCase().startsWith("update"); + } +} + +class Delete { + public static void add(TwilioJavaGeneratorModern twilioJavaGenerator, CodegenOperation codegenOperation, Map apiOperationTemplate) { + codegenOperation.vendorExtensions.put(EnumConstants.SupportedOperation.X_DELETE.getValue(), true); + String key = (String) apiOperationTemplate.get("delete").getKey(); + String value = (String) apiOperationTemplate.get("delete").getValue(); + twilioJavaGenerator.apiTemplateFiles().put(key, value); + + codegenOperation.vendorExtensions.put(MustacheConstants.ACTION_TYPE, ActionType.DELETER.getValue()); + codegenOperation.vendorExtensions.put(MustacheConstants.ACTION_METHOD, ActionMethod.DELETE.getValue()); + } + public static boolean isDelete(CodegenOperation codegenOperation) { + return codegenOperation.operationId.toLowerCase().startsWith("delete"); + } +} + +class Fetch { + public static void add(TwilioJavaGeneratorModern twilioJavaGenerator, CodegenOperation codegenOperation, Map apiOperationTemplate) { + codegenOperation.vendorExtensions.put(EnumConstants.SupportedOperation.X_FETCH.getValue(), true); + String key = (String) apiOperationTemplate.get("fetch").getKey(); + String value = (String) apiOperationTemplate.get("fetch").getValue(); + twilioJavaGenerator.apiTemplateFiles().put(key, value); + + codegenOperation.vendorExtensions.put(MustacheConstants.ACTION_TYPE, ActionType.FETCHER.getValue()); + codegenOperation.vendorExtensions.put(MustacheConstants.ACTION_METHOD, ActionMethod.FETCH.getValue()); + } + public static boolean isFetch(CodegenOperation codegenOperation) { + return codegenOperation.operationId.toLowerCase().startsWith("fetch"); + } +} \ No newline at end of file diff --git a/src/main/java/com/twilio/oai/java/format/JavaUpdateDefaultMapping.java b/src/main/java/com/twilio/oai/java/format/JavaUpdateDefaultMapping.java new file mode 100644 index 000000000..f00656b9b --- /dev/null +++ b/src/main/java/com/twilio/oai/java/format/JavaUpdateDefaultMapping.java @@ -0,0 +1,88 @@ +package com.twilio.oai.java.format; + +import com.twilio.oai.java.format.OpenApiSpecFormatFeatureConstants; +import io.swagger.v3.oas.models.OpenAPI; + +import java.util.HashSet; +import java.util.Map; + +public class JavaUpdateDefaultMapping { + HashSet customFormatWithProperties = new HashSet<>(); + + /* + If a property in the OpenAPI specification is defined as + date_generated: + type: string + format: date-time + The expected datatype for the above is: OffsetDateTime + The expected import is: java.time.OffsetDateTime + + Example: + typeMapping.put("string+date-time", "OffsetDateTime"); + importMapping.put("OffsetDateTime", "java.time.OffsetDateTime"); + + class AbstractJavaCodegen, method: public String getSchemaType(Schema p) at this place dataType is set + */ + // TODO: Anytype is pending + public void typeMapping(Map typeMapping) { + typeMapping.putAll(OpenApiSpecFormatFeatureConstants.getPredefinedTypeMappings()); + } + + public void importMapping(Map importMapping) { + // This is an example of how to add a custom import mapping. + importMapping.putAll(OpenApiSpecFormatFeatureConstants.getPredefinedImportMappings()); + } + + public void modelTemplateFiles(Map modelTemplateFiles) { + // Do not generate models + modelTemplateFiles.clear(); + } + + /* + If a parameter or property in the OpenAPI specification has properties defined, then generator considers it as a complex type. + So to avoid that, we remove the properties from the custom models, So that typeMapping can be used to map the type to a custom class. + + Alternative is to remove properties from the OpenAPI specification itself, but that might be used by doc team. + + Example: + dummyName: + type: object + format: ice-server + properties: + credential: + type: string + username: + type: string + url: + type: string + urls: + type: string + */ + public void removePropertiesFromCustomModels(OpenAPI openAPI) { + customFormatWithProperties.add("ice-server"); + customFormatWithProperties.add("subscribe-rule"); + customFormatWithProperties.add("recording-rule"); + customFormatWithProperties.add("inbound-call-price"); + customFormatWithProperties.add("inbound-sms-price"); + customFormatWithProperties.add("outbound-call-price"); + customFormatWithProperties.add("outbound-call-price-with-origin"); + customFormatWithProperties.add("outbound-prefix-price"); + customFormatWithProperties.add("outbound-sms-price"); + customFormatWithProperties.add("phone-number-capabilities"); + customFormatWithProperties.add("phone-number-price"); + customFormatWithProperties.add("prefixed-collapsible-map"); + customFormatWithProperties.add("prefixed-collapsible-map-AddOns"); + customFormatWithProperties.add("outbound-prefix-price-with-origin"); + customFormatWithProperties.add("string-map"); + customFormatWithProperties.add("uri-map"); + + openAPI.getComponents().getSchemas() + .forEach((name, schema) -> { + if (customFormatWithProperties.contains(schema.getFormat())) { + if (schema.getProperties() != null) { + schema.setProperties(null); + } + } + }); + } +} \ No newline at end of file diff --git a/src/main/java/com/twilio/oai/java/format/OpenApiSpecFormatFeatureConstants.java b/src/main/java/com/twilio/oai/java/format/OpenApiSpecFormatFeatureConstants.java new file mode 100644 index 000000000..82360de11 --- /dev/null +++ b/src/main/java/com/twilio/oai/java/format/OpenApiSpecFormatFeatureConstants.java @@ -0,0 +1,114 @@ +package com.twilio.oai.java.format; + +import java.util.HashMap; +import java.util.Map; + +/* +Must be kept in sync with src/main/resources/config/java.json + */ +public class OpenApiSpecFormatFeatureConstants { + + /* + * inputType -> Customer will provide inputType. + * promoter -> Promoter will use this to convert the inputType to the desired type. + * key (format) -> The key is the format defined in the OpenAPI Spec. + * + * This can be applied to setters. For example, if a query parameter is of the format "phone-number", + * two setters will be created: one for `PhoneNumber` and another for `String`. + * The promoter logic will be applied to the `String` setter. + */ +// public final static Map PROMOTIONS = Map.of( +// "url", new Promotion("String", "Promoter.uriFromString({})"), +// "phone-number", new Promotion("String", "Promoter.phoneNumberFromString({})"), +// "twiml", new Promotion("String", "Promoter.twimlFromString({})") +// ); + + /* + * key (format) -> The key is the format defined in the OpenAPI Spec. + * value -> deserializer class name in twilio-java + */ + public final static Map DESERIALIZER = Map.of( + // Covers Hydrate mentioned in java.json + "date-time-rfc-2822", "com.twilio.converter.RFC2822Deserializer", + "date-time", "com.twilio.converter.ISO8601Deserializer", + "date", "com.twilio.converter.LocalDateDeserializer", + // Covers deserialize mentioned in java.json + "currency", "com.twilio.converter.CurrencyDeserializer" + ); + + /* + * key -> The key is the combination of type+format defined in the OpenAPI Spec. + * value -> The value is the Java type that should be used for that combination. + */ + final static Map getPredefinedTypeMappings() { + final Map predefinedTypeMappings = new HashMap<>(); + // The following two mappings may seem unnecessary, but they are essential. + // They address a bug that incorrectly converts Map to MapStringString. + predefinedTypeMappings.put("Map", "Map"); + predefinedTypeMappings.put("Map", "Map"); + + predefinedTypeMappings.put("string+phone-number", "PhoneNumber"); + predefinedTypeMappings.put("string+uri", "URI"); + predefinedTypeMappings.put("string+url", "URI"); + predefinedTypeMappings.put("string+currency", "Currency"); + predefinedTypeMappings.put("string+date-time", "ZonedDateTime"); + predefinedTypeMappings.put("string+date", "LocalDate"); + predefinedTypeMappings.put("string+endpoint", "Endpoint"); + predefinedTypeMappings.put("string+http-method", "HttpMethod"); + predefinedTypeMappings.put("string+twiml", "com.twilio.type.Twiml"); + predefinedTypeMappings.put("string+date-time-rfc-2822", "ZonedDateTime"); + + predefinedTypeMappings.put("object+ice-server", "IceServer"); + predefinedTypeMappings.put("object+subscribe-rule", "SubscribeRule"); + predefinedTypeMappings.put("object+recording-rule", "RecordingRule"); + predefinedTypeMappings.put("object+inbound-call-price", "InboundCallPrice"); + predefinedTypeMappings.put("object+inbound-sms-price", "InboundSmsPrice"); + predefinedTypeMappings.put("object+outbound-call-price", "OutboundCallPrice"); + predefinedTypeMappings.put("object+outbound-call-price-with-origin", "OutboundCallPriceWithOrigin"); + predefinedTypeMappings.put("object+outbound-prefix-price", "OutboundPrefixPrice"); + predefinedTypeMappings.put("object+outbound-sms-price", "OutboundSmsPrice"); + predefinedTypeMappings.put("object+phone-number-capabilities", "PhoneNumberCapabilities"); + predefinedTypeMappings.put("object+phone-number-price", "PhoneNumberPrice"); + predefinedTypeMappings.put("object+prefixed-collapsible-map", "Map"); + predefinedTypeMappings.put("object+prefixed-collapsible-map-AddOns", "Map"); + predefinedTypeMappings.put("object+outbound-prefix-price-with-origin", "OutboundPrefixPriceWithOrigin"); + predefinedTypeMappings.put("object+string-map", "Map"); + predefinedTypeMappings.put("object+uri-map", "Map"); + return predefinedTypeMappings; + } + + /* + * key -> Java datatype + * value -> Java import statement for key + */ + public static Map getPredefinedImportMappings() { + + Map predefinedImportMappings = new HashMap<>(); + predefinedImportMappings.put("PhoneNumber", "com.twilio.type.PhoneNumber"); + predefinedImportMappings.put("URI", "java.net.URI"); + predefinedImportMappings.put("Currency", "java.util.Currency"); + predefinedImportMappings.put("HttpMethod", "com.twilio.http.HttpMethod"); + predefinedImportMappings.put("Endpoint", "com.twilio.type.Endpoint"); + predefinedImportMappings.put("ZonedDateTime", "java.time.ZonedDateTime"); + + predefinedImportMappings.put("IceServer", "com.twilio.type.IceServer"); + predefinedImportMappings.put("SubscribeRule", "com.twilio.type.SubscribeRule"); + predefinedImportMappings.put("RecordingRule", "com.twilio.type.RecordingRule"); + predefinedImportMappings.put("PhoneNumberCapabilities", "com.twilio.type.PhoneNumberCapabilities"); + predefinedImportMappings.put("FeedbackIssue", "com.twilio.type.FeedbackIssue"); + predefinedImportMappings.put("PhoneNumberPrice", "com.twilio.type.PhoneNumberPrice"); + predefinedImportMappings.put("OutboundSmsPrice", "com.twilio.type.OutboundSmsPrice"); + predefinedImportMappings.put("InboundSmsPrice", "com.twilio.type.InboundSmsPrice"); + predefinedImportMappings.put("OutboundPrefixPrice", "com.twilio.type.OutboundPrefixPrice"); + predefinedImportMappings.put("InboundCallPrice", "com.twilio.type.InboundCallPrice"); + predefinedImportMappings.put("OutboundCallPrice", "com.twilio.type.OutboundCallPrice"); + predefinedImportMappings.put("OutboundCallPriceWithOrigin", "com.twilio.type.OutboundCallPriceWithOrigin"); + predefinedImportMappings.put("OutboundPrefixPriceWithOrigin", "com.twilio.type.OutboundPrefixPriceWithOrigin"); + predefinedImportMappings.put("PrefixedCollapsibleMap", "com.twilio.converter.PrefixedCollapsibleMap"); + //predefinedImportMappings.put("Map", "java.util.Map"); + + return predefinedImportMappings; + } +} + + From f73f7adf81fb0d5909479f00148b4575d9b7a89c Mon Sep 17 00:00:00 2001 From: sbansla <104902068+sbansla@users.noreply.github.com> Date: Wed, 6 Aug 2025 16:11:39 +0530 Subject: [PATCH 09/38] added mustache template files (#671) Add twilio-java modern mustache template files. --- .../resources/twilio-java-modern/Readme.md | 0 .../resources/twilio-java-modern/api.mustache | 18 +++++++ .../common/addHeaderParams.mustache | 22 ++++++++ .../common/addPostParams.mustache | 23 +++++++++ .../common/addQueryParams.mustache | 36 +++++++++++++ .../common/constructors.mustache | 7 +++ .../common/generateUri.mustache | 17 +++++++ .../common/instanceVariables.mustache | 12 +++++ .../common/operationMethod.mustache | 51 +++++++++++++++++++ .../common/setters.mustache | 20 ++++++++ .../twilio-java-modern/creator.mustache | 28 ++++++++++ .../twilio-java-modern/deleter.mustache | 25 +++++++++ .../twilio-java-modern/enums.mustache | 22 ++++++++ .../twilio-java-modern/fetcher.mustache | 25 +++++++++ .../twilio-java-modern/licenseInfo.mustache | 13 +++++ .../twilio-java-modern/models.mustache | 28 ++++++++++ .../twilio-java-modern/reader.mustache | 25 +++++++++ .../reader/operationMethod.mustache | 49 ++++++++++++++++++ .../twilio-java-modern/response.mustache | 8 +++ .../twilio-java-modern/staticMethods.mustache | 36 +++++++++++++ .../twilio-java-modern/updater.mustache | 27 ++++++++++ 21 files changed, 492 insertions(+) create mode 100644 src/main/resources/twilio-java-modern/Readme.md create mode 100644 src/main/resources/twilio-java-modern/api.mustache create mode 100644 src/main/resources/twilio-java-modern/common/addHeaderParams.mustache create mode 100644 src/main/resources/twilio-java-modern/common/addPostParams.mustache create mode 100644 src/main/resources/twilio-java-modern/common/addQueryParams.mustache create mode 100644 src/main/resources/twilio-java-modern/common/constructors.mustache create mode 100644 src/main/resources/twilio-java-modern/common/generateUri.mustache create mode 100644 src/main/resources/twilio-java-modern/common/instanceVariables.mustache create mode 100644 src/main/resources/twilio-java-modern/common/operationMethod.mustache create mode 100644 src/main/resources/twilio-java-modern/common/setters.mustache create mode 100644 src/main/resources/twilio-java-modern/creator.mustache create mode 100644 src/main/resources/twilio-java-modern/deleter.mustache create mode 100644 src/main/resources/twilio-java-modern/enums.mustache create mode 100644 src/main/resources/twilio-java-modern/fetcher.mustache create mode 100644 src/main/resources/twilio-java-modern/licenseInfo.mustache create mode 100644 src/main/resources/twilio-java-modern/models.mustache create mode 100644 src/main/resources/twilio-java-modern/reader.mustache create mode 100644 src/main/resources/twilio-java-modern/reader/operationMethod.mustache create mode 100644 src/main/resources/twilio-java-modern/response.mustache create mode 100644 src/main/resources/twilio-java-modern/staticMethods.mustache create mode 100644 src/main/resources/twilio-java-modern/updater.mustache diff --git a/src/main/resources/twilio-java-modern/Readme.md b/src/main/resources/twilio-java-modern/Readme.md new file mode 100644 index 000000000..e69de29bb diff --git a/src/main/resources/twilio-java-modern/api.mustache b/src/main/resources/twilio-java-modern/api.mustache new file mode 100644 index 000000000..1a9b41991 --- /dev/null +++ b/src/main/resources/twilio-java-modern/api.mustache @@ -0,0 +1,18 @@ +{{>licenseInfo}} +{{#imports}} +import {{import}}; +{{/imports}} +import com.twilio.constant.EnumConstants.ParameterType; +{{#resources}} + +@JsonIgnoreProperties(ignoreUnknown = true) +@ToString +public class {{resourceName}} extends Resource { + +{{>enums}} +{{>models}} +{{>staticMethods}} +{{>response}} +} +{{/resources}} + diff --git a/src/main/resources/twilio-java-modern/common/addHeaderParams.mustache b/src/main/resources/twilio-java-modern/common/addHeaderParams.mustache new file mode 100644 index 000000000..0d42baee3 --- /dev/null +++ b/src/main/resources/twilio-java-modern/common/addHeaderParams.mustache @@ -0,0 +1,22 @@ +private void addHeaderParams(final Request request) { +{{#headerParams}} + +{{! -- case1 Normal Parameter (Non Array, Non equality parameter)}} +{{^isArray}} +{{^vendorExtensions.x-inequality-main}} + if ({{paramName}} != null) { + Serializer.toString(request, "{{baseName}}", param, ParameterType.HEADER); + } +{{/vendorExtensions.x-inequality-main}} +{{/isArray}} +{{! -- Case2: Array Parameter }} +{{#isArray}} + if ({{paramName}} != null) { + for ({{baseType}} param: {{paramName}}) { + Serializer.toString(request, "{{baseName}}", param, ParameterType.HEADER); + } + } +{{/isArray}} + +{{/headerParams}} +} \ No newline at end of file diff --git a/src/main/resources/twilio-java-modern/common/addPostParams.mustache b/src/main/resources/twilio-java-modern/common/addPostParams.mustache new file mode 100644 index 000000000..1d1277432 --- /dev/null +++ b/src/main/resources/twilio-java-modern/common/addPostParams.mustache @@ -0,0 +1,23 @@ +private void addPostParams(final Request request) { +{{#formParams}} + + {{! -- case1 Normal Parameter (Non Array, Non equality parameter)}} +{{^isArray}} +{{^vendorExtensions.x-inequality-main}} + if ({{paramName}} != null) { + Serializer.toString(request, "{{baseName}}", param, ParameterType.URLENCODED); + } +{{/vendorExtensions.x-inequality-main}} +{{/isArray}} + +{{! -- Case2: Array Parameter }} +{{#isArray}} + if ({{paramName}} != null) { + for ({{baseType}} param: {{paramName}}) { + Serializer.toString(request, "{{baseName}}", param, ParameterType.URLENCODED); + } + } +{{/isArray}} + +{{/formParams}} +} \ No newline at end of file diff --git a/src/main/resources/twilio-java-modern/common/addQueryParams.mustache b/src/main/resources/twilio-java-modern/common/addQueryParams.mustache new file mode 100644 index 000000000..62586cabe --- /dev/null +++ b/src/main/resources/twilio-java-modern/common/addQueryParams.mustache @@ -0,0 +1,36 @@ +private void addQueryParams(final Request request) { +{{! -- 4 cases: Normal parameter, Eqality parameter(Message), Ineqality Parameter(MessageBefore, MessageAfter)}, List Parameter }} +{{#queryParams}} +{{^vendorExtensions.x-has-before-or-after}}{{! -- These serialize in equality field}} + +{{! -- case1 Normal Parameter (Non Array, Non equality parameter)}} +{{^isArray}} +{{^vendorExtensions.x-inequality-main}} + if ({{paramName}} != null) { + Serializer.toString(request, "{{baseName}}", {{paramName}}, ParameterType.QUERY); + } +{{/vendorExtensions.x-inequality-main}} +{{/isArray}} + +{{! -- Case2: Inequality Parameter, Non Array }} +{{! -- Case3: Add before and after with inequality parameter }} +{{^isArray}} +{{#vendorExtensions.x-inequality-main}} + if ({{paramName}} != null) { + Serializer.toString(request, "{{baseName}}", {{paramName}}, {{paramName}}Before, {{paramName}}After); + } +{{/vendorExtensions.x-inequality-main}} +{{/isArray}} + +{{! -- Case4: Array Parameter }} +{{#isArray}} + if ({{paramName}} != null) { + for ({{baseType}} param: {{paramName}}) { + Serializer.toString(request, "{{baseName}}", param, ParameterType.QUERY); + } + } +{{/isArray}} + +{{/vendorExtensions.x-has-before-or-after}} +{{/queryParams}} +} \ No newline at end of file diff --git a/src/main/resources/twilio-java-modern/common/constructors.mustache b/src/main/resources/twilio-java-modern/common/constructors.mustache new file mode 100644 index 000000000..31e2970e5 --- /dev/null +++ b/src/main/resources/twilio-java-modern/common/constructors.mustache @@ -0,0 +1,7 @@ +{{#vendorExtensions.x-signature-list}} + public {{resourceName}}Creator({{#.}}final {{{dataType}}} {{paramName}}{{^-last}}, {{/-last}}{{/.}}) { + {{#.}} + this.{{paramName}} = {{paramName}}; + {{/.}} + } +{{/vendorExtensions.x-signature-list}} \ No newline at end of file diff --git a/src/main/resources/twilio-java-modern/common/generateUri.mustache b/src/main/resources/twilio-java-modern/common/generateUri.mustache new file mode 100644 index 000000000..3ebe8b578 --- /dev/null +++ b/src/main/resources/twilio-java-modern/common/generateUri.mustache @@ -0,0 +1,17 @@ + +{{#vendorExtensions.parentUrl}} + String path = "{{{vendorExtensions.parentUrl}}}"; +{{/vendorExtensions.parentUrl}} +{{^vendorExtensions.parentUrl}} + String path = "{{{path}}}"; +{{/vendorExtensions.parentUrl}} + +{{#pathParams}} + {{#vendorExtensions.x-is-account-sid}} + this.{{paramName}} = this.{{paramName}} == null ? client.getAccountSid() : this.{{paramName}}; + path = path.replace("{"+"{{baseName}}"+"}", this.{{paramName}}.toString()); + {{/vendorExtensions.x-is-account-sid}} + {{^vendorExtensions.x-is-account-sid}} + path = path.replace("{"+"{{baseName}}"+"}", this.{{paramName}}.toString()); + {{/vendorExtensions.x-is-account-sid}} +{{/pathParams}} diff --git a/src/main/resources/twilio-java-modern/common/instanceVariables.mustache b/src/main/resources/twilio-java-modern/common/instanceVariables.mustache new file mode 100644 index 000000000..5aa1fae53 --- /dev/null +++ b/src/main/resources/twilio-java-modern/common/instanceVariables.mustache @@ -0,0 +1,12 @@ +{{#pathParams}} + private {{{dataType}}} {{paramName}}; +{{/pathParams}} +{{#queryParams}} + private {{{dataType}}} {{paramName}}; +{{/queryParams}} +{{#headerParams}} + private {{{dataType}}} {{paramName}}; +{{/headerParams}} +{{#formParams}} + private {{{dataType}}} {{paramName}}; +{{/formParams}} \ No newline at end of file diff --git a/src/main/resources/twilio-java-modern/common/operationMethod.mustache b/src/main/resources/twilio-java-modern/common/operationMethod.mustache new file mode 100644 index 000000000..c518e5cba --- /dev/null +++ b/src/main/resources/twilio-java-modern/common/operationMethod.mustache @@ -0,0 +1,51 @@ +{{! +resourceName: Api Name as identified by Directory Structure service +x-common-action-method: used to define operation method and can have values: create, read, update, delete, fetch + Example: https://github.com/twilio/twilio-java/blob/9c2ba4dbc185c5576e67fbeb82ec6f4899093e79/src/main/java/com/twilio/rest/api/v2010/account/MessageCreator.java#L309 + +httpMethod: http method associated in the current operation. +domainName: example api, video, chat, etc. These can be found in Domains.java in twilio-java +vendorExtensions.x-content-type: content type of the request, example: application/json, application/x-www-form-urlencoded +}} + @Override + public {{resourceName}} {{vendorExtensions.x-common-action-method}}(final TwilioRestClient client) { + {{>common/generateUri}} + + Request request = new Request( + HttpMethod.{{httpMethod}}, + Domains.{{#lambda.uppercase}}{{domainName}}{{/lambda.uppercase}}.toString(), + path + ); + {{#vendorExtensions.x-request-content-type}} + request.setContentType(EnumConstants.ContentType.{{vendorExtensions.x-request-content-type}}); + {{/vendorExtensions.x-request-content-type}} + {{#queryParams.0}} + addQueryParams(request); + {{/queryParams.0}} + {{#headerParams.0}} + addHeaderParams(request); + {{/headerParams.0}} + {{#formParams.0}} + addPostParams(request); + {{/formParams.0}} + {{#bodyParams.0}} + addPostParams(request, client); + {{/bodyParams.0}} + + Response response = client.request(request); + + if (response == null) { + throw new ApiConnectionException("{{resourceName}} creation failed: Unable to connect to server"); + } else if (!TwilioRestClient.SUCCESS.test(response.getStatusCode())) { + RestException restException = RestException.fromJson( + response.getStream(), + client.getObjectMapper() + ); + if (restException == null) { + throw new ApiException("Server Error, no content", response.getStatusCode()); + } + throw new ApiException(restException); + } + + return {{resourceName}}.fromJson(response.getStream(), client.getObjectMapper()); + } \ No newline at end of file diff --git a/src/main/resources/twilio-java-modern/common/setters.mustache b/src/main/resources/twilio-java-modern/common/setters.mustache new file mode 100644 index 000000000..b52f1e769 --- /dev/null +++ b/src/main/resources/twilio-java-modern/common/setters.mustache @@ -0,0 +1,20 @@ +{{#vendorExtensions.x-setter-methods}} + +public {{resourceName}}{{vendorExtensions.x-common-action-type}} set{{#lambda.titlecase}}{{paramName}}{{/lambda.titlecase}}(final {{{dataType}}} {{paramName}}){ + this.{{paramName}} = {{paramName}}; + return this; +} + +{{! Optional setter-- Ideally this shouldn't exists, keeping it for backward compatibility }} +{{#isArray}} +public {{resourceName}}{{vendorExtensions.x-common-action-type}} set{{#lambda.titlecase}}{{paramName}}{{/lambda.titlecase}}(final {{{baseType}}} {{paramName}}){ + return set{{#lambda.titlecase}}{{paramName}}{{/lambda.titlecase}}(Promoter.listOfOne({{paramName}})); +} +{{/isArray}} +{{! Optional setter, vendorExtensions.x-promotion stores promotion method}} +{{#vendorExtensions.x-promotion}} +public {{resourceName}}{{vendorExtensions.x-common-action-type}} set{{#lambda.titlecase}}{{paramName}}{{/lambda.titlecase}}(final String {{paramName}}){ + return set{{#lambda.titlecase}}{{paramName}}{{/lambda.titlecase}}({{vendorExtensions.x-promotion}}); +} +{{/vendorExtensions.x-promotion}} +{{/vendorExtensions.x-setter-methods}} \ No newline at end of file diff --git a/src/main/resources/twilio-java-modern/creator.mustache b/src/main/resources/twilio-java-modern/creator.mustache new file mode 100644 index 000000000..f3d505b04 --- /dev/null +++ b/src/main/resources/twilio-java-modern/creator.mustache @@ -0,0 +1,28 @@ +{{>licenseInfo}} +{{#imports}} +import {{import}}; +{{/imports}} +import com.twilio.constant.EnumConstants.ParameterType; + +{{#resources}} +{{#operations}} +{{#vendorExtensions.x-create-operation}} +public class {{resourceName}} extends Creator<{{resourceName}}> { + +{{>common/instanceVariables}} +{{>common/constructors}} +{{>common/setters}} +{{>common/operationMethod}} +{{#queryParams.0}} + {{>common/addQueryParams}} +{{/queryParams.0}} +{{#formParams.0}} + {{>common/addPostParams}} +{{/formParams.0}} +{{#headerParams.0}} + {{>common/addHeaderParams}} +{{/headerParams.0}} +} +{{/vendorExtensions.x-create-operation}} +{{/operations}} +{{/resources}} \ No newline at end of file diff --git a/src/main/resources/twilio-java-modern/deleter.mustache b/src/main/resources/twilio-java-modern/deleter.mustache new file mode 100644 index 000000000..ed1c034f7 --- /dev/null +++ b/src/main/resources/twilio-java-modern/deleter.mustache @@ -0,0 +1,25 @@ +{{>licenseInfo}} +{{#imports}} +import {{import}}; +{{/imports}} +import com.twilio.constant.EnumConstants.ParameterType; + +{{#resources}} + {{#operations}} + {{#vendorExtensions.x-delete-operation}} + public class {{resourceName}} extends Deleter<{{resourceName}}> { + + {{>common/instanceVariables}} + {{>common/constructors}} + {{>common/setters}} + {{>common/operationMethod}} + {{#queryParams.0}} + {{>common/addQueryParams}} + {{/queryParams.0}} + {{#headerParams.0}} + {{>common/addHeaderParams}} + {{/headerParams.0}} + } + {{/vendorExtensions.x-delete-operation}} + {{/operations}} +{{/resources}} \ No newline at end of file diff --git a/src/main/resources/twilio-java-modern/enums.mustache b/src/main/resources/twilio-java-modern/enums.mustache new file mode 100644 index 000000000..df814c378 --- /dev/null +++ b/src/main/resources/twilio-java-modern/enums.mustache @@ -0,0 +1,22 @@ +{{#mustacheEnums}} +public enum {{className}} { +{{#enumValues}} + {{name}}({{{value}}}){{^-last}},{{/-last}} +{{/enumValues}} + + private final String value; + + private {{className}}(final String value) { + this.value = value; + } + + public String toString() { + return value; + } + + @JsonCreator + public static {{className}} forValue(final String value) { + return Promoter.enumFromString(value, {{className}}.values()); + } +} +{{/mustacheEnums}} \ No newline at end of file diff --git a/src/main/resources/twilio-java-modern/fetcher.mustache b/src/main/resources/twilio-java-modern/fetcher.mustache new file mode 100644 index 000000000..e73b093e8 --- /dev/null +++ b/src/main/resources/twilio-java-modern/fetcher.mustache @@ -0,0 +1,25 @@ +{{>licenseInfo}} +{{#imports}} +import {{import}}; +{{/imports}} +import com.twilio.constant.EnumConstants.ParameterType; + +{{#resources}} +{{#operations}} +{{#vendorExtensions.x-fetch-operation}} + public class {{resourceName}} extends Fetcher<{{resourceName}}> { + + {{>common/instanceVariables}} + {{>common/constructors}} + {{>common/setters}} + {{>common/operationMethod}} + {{#queryParams.0}} + {{>common/addQueryParams}} + {{/queryParams.0}} + {{#headerParams.0}} + {{>common/addHeaderParams}} + {{/headerParams.0}} + } +{{/vendorExtensions.x-fetch-operation}} +{{/operations}} +{{/resources}} \ No newline at end of file diff --git a/src/main/resources/twilio-java-modern/licenseInfo.mustache b/src/main/resources/twilio-java-modern/licenseInfo.mustache new file mode 100644 index 000000000..62ae6193c --- /dev/null +++ b/src/main/resources/twilio-java-modern/licenseInfo.mustache @@ -0,0 +1,13 @@ +/* + * This code was generated by + * ___ _ _ _ _ _ _ ____ ____ ____ _ ____ ____ _ _ ____ ____ ____ ___ __ __ + * | | | | | | | | | __ | | |__| | __ | __ |___ |\ | |___ |__/ |__| | | | |__/ + * | |_|_| | |___ | |__| |__| | | | |__] |___ | \| |___ | \ | | | |__| | \ + * + * {{{appName}}} + * {{{appDescription}}} + * + * NOTE: This class is auto generated by OpenAPI Generator. + * https://openapi-generator.tech + * Do not edit the class manually. + */ diff --git a/src/main/resources/twilio-java-modern/models.mustache b/src/main/resources/twilio-java-modern/models.mustache new file mode 100644 index 000000000..a04bfb227 --- /dev/null +++ b/src/main/resources/twilio-java-modern/models.mustache @@ -0,0 +1,28 @@ +{{#mustacheModels}} + + @JsonDeserialize(builder = {{className}}.Builder.class) + @JsonInclude(JsonInclude.Include.NON_EMPTY) + @ToString + @Builder + public static class {{className}} { + {{#mandatoryProperties}} + public {{classname}}({{#.}}final {{{dataType}}} {{name}}{{^-last}}, {{/-last}}{{/.}} ) { + {{#.}} + this.{{name}} = {{name}}; + {{/.}} + } + {{/mandatoryProperties}} + + {{#optionalProperties}} + {{#vendorExtensions.x-deserializer}} + @JsonDeserialize(using = {{vendorExtensions.x-deserializer}}.class) + {{/vendorExtensions.x-deserializer}} + @JsonInclude(JsonInclude.Include.NON_EMPTY) + @JsonProperty("{{{baseName}}}") + @Getter @Setter private {{{dataType}}} {{name}}; + + {{/optionalProperties}} + @JsonPOJOBuilder(withPrefix = "") + public static class Builder {} + } +{{/mustacheModels}} diff --git a/src/main/resources/twilio-java-modern/reader.mustache b/src/main/resources/twilio-java-modern/reader.mustache new file mode 100644 index 000000000..992ba1412 --- /dev/null +++ b/src/main/resources/twilio-java-modern/reader.mustache @@ -0,0 +1,25 @@ +{{>licenseInfo}} +{{#imports}} +import {{import}}; +{{/imports}} +import com.twilio.constant.EnumConstants.ParameterType; + +{{#resources}} +{{#operations}} +{{#vendorExtensions.x-fetch-operation}} +public class {{resourceName}} extends Fetcher<{{resourceName}}> { + + {{>common/instanceVariables}} + {{>common/constructors}} + {{>common/setters}} + {{>reader/operationMethod}} +{{#queryParams.0}} + {{>common/addQueryParams}} +{{/queryParams.0}} +{{#headerParams.0}} + {{>common/addHeaderParams}} +{{/headerParams.0}} +} +{{/vendorExtensions.x-fetch-operation}} +{{/operations}} +{{/resources}} \ No newline at end of file diff --git a/src/main/resources/twilio-java-modern/reader/operationMethod.mustache b/src/main/resources/twilio-java-modern/reader/operationMethod.mustache new file mode 100644 index 000000000..521d95943 --- /dev/null +++ b/src/main/resources/twilio-java-modern/reader/operationMethod.mustache @@ -0,0 +1,49 @@ +{{! +resourceName: Api Name as identified by Directory Structure service +recordKey: +httpMethod: http method associated in the current operation. +domainName: example api, video, chat, etc. These can be found in Domains.java in twilio-java +}} + @Override + public ResourceSet<{{resourceName}}> read(final TwilioRestClient client) { + return new ResourceSet<>(this, client, firstPage(client)); + } + + public Page<{{resourceName}}> firstPage(final TwilioRestClient client) { + {{>common/generateUri}} + Request request = new Request( + HttpMethod.{{httpMethod}}, + Domains.{{#lambda.uppercase}}{{domainName}}{{/lambda.uppercase}}.toString(), + path + ); + {{#queryParams.0}} + addQueryParams(request); + {{/queryParams.0}} + {{#headerParams.0}} + addHeaderParams(request); + {{/headerParams.0}} + + return pageForRequest(client, request); + } + + private Page<{{resourceName}}> pageForRequest(final TwilioRestClient client, final Request request) { + Response response = client.request(request); + if (response == null) { + throw new ApiConnectionException("{{resourceName}} creation failed: Unable to connect to server"); + } else if (!TwilioRestClient.SUCCESS.test(response.getStatusCode())) { + RestException restException = RestException.fromJson( + response.getStream(), + client.getObjectMapper()); + + if (restException == null) { + throw new ApiException("Server Error, no content", response.getStatusCode()); + } + throw new ApiException(restException); + } {{! end of else if }} + + return Page.fromJson( + "{{recordKey}}", + response.getContent(), + {{resourceName}}.class, + client.getObjectMapper()); + } \ No newline at end of file diff --git a/src/main/resources/twilio-java-modern/response.mustache b/src/main/resources/twilio-java-modern/response.mustache new file mode 100644 index 000000000..ac2e1d034 --- /dev/null +++ b/src/main/resources/twilio-java-modern/response.mustache @@ -0,0 +1,8 @@ +{{#response}} + @Getter + @JsonProperty("{{baseName}}") +{{#vendorExtensions.x-deserializer}} + @JsonDeserialize(using = {{vendorExtensions.x-deserializer}}) +{{/vendorExtensions.x-deserializer}} + private final {{{dataType}}} {{name}}; +{{/response}} \ No newline at end of file diff --git a/src/main/resources/twilio-java-modern/staticMethods.mustache b/src/main/resources/twilio-java-modern/staticMethods.mustache new file mode 100644 index 000000000..6619ad96e --- /dev/null +++ b/src/main/resources/twilio-java-modern/staticMethods.mustache @@ -0,0 +1,36 @@ + /** + * Converts a JSON String into a {{resourceName}} object using the provided ObjectMapper. + * + * @param json Raw JSON String + * @param objectMapper Jackson ObjectMapper + * @return {{resourceName}} object represented by the provided JSON + */ + public static {{apiName}} fromJson(final String json, final ObjectMapper objectMapper) { + // Convert all checked exceptions to Runtime + try { + return objectMapper.readValue(json, {{resourceName}}.class); + } catch (final JsonMappingException | JsonParseException e) { + throw new ApiException(e.getMessage(), e); + } catch (final IOException e) { + throw new ApiConnectionException(e.getMessage(), e); + } + } + + /** + * Converts a JSON InputStream into a {{resourceName}} object using the provided + * ObjectMapper. + * + * @param json Raw JSON InputStream + * @param objectMapper Jackson ObjectMapper + * @return {{resourceName}} object represented by the provided JSON + */ + public static {{resourceName}} fromJson(final InputStream json, final ObjectMapper objectMapper) { + // Convert all checked exceptions to Runtime + try { + return objectMapper.readValue(json, {{resourceName}}.class); + } catch (final JsonMappingException | JsonParseException e) { + throw new ApiException(e.getMessage(), e); + } catch (final IOException e) { + throw new ApiConnectionException(e.getMessage(), e); + } + } \ No newline at end of file diff --git a/src/main/resources/twilio-java-modern/updater.mustache b/src/main/resources/twilio-java-modern/updater.mustache new file mode 100644 index 000000000..18a04d70a --- /dev/null +++ b/src/main/resources/twilio-java-modern/updater.mustache @@ -0,0 +1,27 @@ +{{>licenseInfo}} +{{#imports}} +import {{import}}; +{{/imports}} +import com.twilio.constant.EnumConstants.ParameterType; + +{{#resources}} +{{#operations}} +{{#vendorExtensions.x-update-operation}} + public class {{resourceName}} extends Updater<{{resourceName}}> { + {{>common/instanceVariables}} + {{>common/constructors}} + {{>common/setters}} + {{>common/operationMethod}} + {{#queryParams.0}} + {{>common/addQueryParams}} + {{/queryParams.0}} + {{#formParams.0}} + {{>common/addPostParams}} + {{/formParams.0}} + {{#headerParams.0}} + {{>common/addHeaderParams}} + {{/headerParams.0}} + } +{{/vendorExtensions.x-update-operation}} +{{/operations}} +{{/resources}} \ No newline at end of file From d9871ef7796a2f30c7ceeba9dbf0d7c683c34bcd Mon Sep 17 00:00:00 2001 From: sbansla <104902068+sbansla@users.noreply.github.com> Date: Wed, 6 Aug 2025 16:51:09 +0530 Subject: [PATCH 10/38] added constructor, settermethod and inequality feature (#672) added constructor, settermethod and inequality feature (#672) --- .../twilio/oai/java/feature/Inequality.java | 67 +++++++ .../java/feature/SetterMethodGenerator.java | 36 ++++ .../constructor/ConstructorFactory.java | 38 ++++ .../constructor/ConstructorGenerator.java | 8 + .../constructor/JsonConstructorGenerator.java | 18 ++ .../UrlencodedBodyConstructorGenerator.java | 178 ++++++++++++++++++ .../processor/JavaOperationProcessor.java | 8 + 7 files changed, 353 insertions(+) create mode 100644 src/main/java/com/twilio/oai/java/feature/Inequality.java create mode 100644 src/main/java/com/twilio/oai/java/feature/SetterMethodGenerator.java create mode 100644 src/main/java/com/twilio/oai/java/feature/constructor/ConstructorFactory.java create mode 100644 src/main/java/com/twilio/oai/java/feature/constructor/ConstructorGenerator.java create mode 100644 src/main/java/com/twilio/oai/java/feature/constructor/JsonConstructorGenerator.java create mode 100644 src/main/java/com/twilio/oai/java/feature/constructor/UrlencodedBodyConstructorGenerator.java diff --git a/src/main/java/com/twilio/oai/java/feature/Inequality.java b/src/main/java/com/twilio/oai/java/feature/Inequality.java new file mode 100644 index 000000000..ef35d7a71 --- /dev/null +++ b/src/main/java/com/twilio/oai/java/feature/Inequality.java @@ -0,0 +1,67 @@ +package com.twilio.oai.java.feature; + +import org.openapitools.codegen.CodegenOperation; +import org.openapitools.codegen.CodegenParameter; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/* + * Main aim is to identify inequality fields in the parameters, so that serialization can be handled correctly. + */ +public class Inequality { + public void process(CodegenOperation codegenOperation) { + Map> groupedItems = new HashMap<>(); + + codegenOperation.queryParams.forEach(param -> groupItems(param, groupedItems)); + addVendorExtension(groupedItems); + groupedItems.clear(); + // Currently supported only for query parameters. + +// codegenOperation.pathParams.forEach(param -> groupItems(param, groupedItems)); +// addVendorExtension(groupedItems); +// groupedItems.clear(); +// +// codegenOperation.headerParams.forEach(param -> groupItems(param, groupedItems)); +// addVendorExtension(groupedItems); +// groupedItems.clear(); +// +// codegenOperation.formParams.forEach(param -> groupItems(param, groupedItems)); +// addVendorExtension(groupedItems); +// groupedItems.clear(); + } + + private void groupItems (CodegenParameter codegenParameter, Map> groupedItems) { + String baseName = getBaseName(codegenParameter); + if (!groupedItems.containsKey(baseName)) { + groupedItems.put(baseName, new ArrayList<>()); + } + groupedItems.get(baseName).add(codegenParameter); + } + + private void addVendorExtension(Map> groupedItems) { + for (Map.Entry> entry : groupedItems.entrySet()) { + List values = entry.getValue(); + if (values.size() > 1) { + // Add a vendor extension to indicate that there are multiple parameters with the same base name + String baseName = entry.getKey(); + for (CodegenParameter param : values) { + if (baseName.equals(param.baseName)) { + param.vendorExtensions.put("x-inequality-main", true); + } else { + param.vendorExtensions.put("x-has-before-or-after", true); + } + } + } + } + } + + private String getBaseName(CodegenParameter codegenParameter) { + if (codegenParameter.baseName.endsWith(">") || codegenParameter.baseName.endsWith("<")) { + return codegenParameter.baseName.substring(0, codegenParameter.baseName.length() - 1); + } + return codegenParameter.baseName; + } +} diff --git a/src/main/java/com/twilio/oai/java/feature/SetterMethodGenerator.java b/src/main/java/com/twilio/oai/java/feature/SetterMethodGenerator.java new file mode 100644 index 000000000..602b19b5f --- /dev/null +++ b/src/main/java/com/twilio/oai/java/feature/SetterMethodGenerator.java @@ -0,0 +1,36 @@ +package com.twilio.oai.java.feature; + +import com.twilio.oai.java.processor.enums.EnumProcessorFactory; +import org.openapitools.codegen.CodegenOperation; +import org.openapitools.codegen.CodegenParameter; + +import java.util.ArrayList; +import java.util.List; + +// Add all setter variables for an operation which is non path parameters +public class SetterMethodGenerator { + public static SetterMethodGenerator instance; + + private SetterMethodGenerator() { + } + public static synchronized SetterMethodGenerator getInstance() { + if (instance == null) { + synchronized (SetterMethodGenerator.class) { + if (instance == null) { + instance = new SetterMethodGenerator(); + } + } + } + return instance; + } + + public void apply(final CodegenOperation codegenOperation) { + List codegenParameters = new ArrayList<>(); + codegenOperation.allParams.forEach(param -> { + if (!param.isPathParam) { + codegenParameters.add(param); + } + }); + codegenOperation.vendorExtensions.put("x-non-path-params", codegenParameters); + } +} diff --git a/src/main/java/com/twilio/oai/java/feature/constructor/ConstructorFactory.java b/src/main/java/com/twilio/oai/java/feature/constructor/ConstructorFactory.java new file mode 100644 index 000000000..20efc2ba7 --- /dev/null +++ b/src/main/java/com/twilio/oai/java/feature/constructor/ConstructorFactory.java @@ -0,0 +1,38 @@ +package com.twilio.oai.java.feature.constructor; + +import org.openapitools.codegen.CodegenOperation; + +import java.util.List; + +public class ConstructorFactory { + public static ConstructorFactory instance; + + public static synchronized ConstructorFactory getInstance() { + if (instance == null) { + synchronized (ConstructorFactory.class) { + if (instance == null) { + instance = new ConstructorFactory(); + } + } + } + return instance; + } + + private final List constructorGenerators; + + private ConstructorFactory() { + constructorGenerators = List.of( + //new JsonConstructorGenerator(), + new UrlencodedBodyConstructorGenerator() + ); + } + + public void applyFeature(CodegenOperation codegenOperation) { + for (ConstructorGenerator constructorGenerator: constructorGenerators) { + if (constructorGenerator.shouldApply(codegenOperation)) { + constructorGenerator.apply(codegenOperation); + return; // Exit after the first processor that applies + } + } + } +} diff --git a/src/main/java/com/twilio/oai/java/feature/constructor/ConstructorGenerator.java b/src/main/java/com/twilio/oai/java/feature/constructor/ConstructorGenerator.java new file mode 100644 index 000000000..93233431c --- /dev/null +++ b/src/main/java/com/twilio/oai/java/feature/constructor/ConstructorGenerator.java @@ -0,0 +1,8 @@ +package com.twilio.oai.java.feature.constructor; + +import org.openapitools.codegen.CodegenOperation; + +public interface ConstructorGenerator { + void apply(CodegenOperation codegenOperation); + boolean shouldApply(CodegenOperation codegenOperation); +} diff --git a/src/main/java/com/twilio/oai/java/feature/constructor/JsonConstructorGenerator.java b/src/main/java/com/twilio/oai/java/feature/constructor/JsonConstructorGenerator.java new file mode 100644 index 000000000..7b0b15582 --- /dev/null +++ b/src/main/java/com/twilio/oai/java/feature/constructor/JsonConstructorGenerator.java @@ -0,0 +1,18 @@ +package com.twilio.oai.java.feature.constructor; + +import org.openapitools.codegen.CodegenOperation; + +public class JsonConstructorGenerator implements ConstructorGenerator { + + @Override + public void apply(CodegenOperation codegenOperation) { + // This method is intentionally left empty as the JSON constructor does not require any specific processing. + // The JSON constructor is automatically generated by the OpenAPI generator. + codegenOperation.vendorExtensions.put("x-java-constructor", true); + } + + @Override + public boolean shouldApply(CodegenOperation codegenOperation) { + return false; + } +} diff --git a/src/main/java/com/twilio/oai/java/feature/constructor/UrlencodedBodyConstructorGenerator.java b/src/main/java/com/twilio/oai/java/feature/constructor/UrlencodedBodyConstructorGenerator.java new file mode 100644 index 000000000..10bba72f2 --- /dev/null +++ b/src/main/java/com/twilio/oai/java/feature/constructor/UrlencodedBodyConstructorGenerator.java @@ -0,0 +1,178 @@ +package com.twilio.oai.java.feature.constructor; + +import com.google.common.collect.Lists; +import com.twilio.oai.StringHelper; +import org.openapitools.codegen.CodegenOperation; +import org.openapitools.codegen.CodegenParameter; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Optional; +import java.util.stream.Collectors; + +import static com.twilio.oai.api.JavaApiResourceBuilder.SIGNATURE_LIST; +import static com.twilio.oai.common.ApplicationConstants.ACCOUNT_SID_VEND_EXT; + +/* + This class builds the constructor parameters from mandatory fields from parameter(path, query, header), request body and conditional fields + from request body. + */ +public class UrlencodedBodyConstructorGenerator implements ConstructorGenerator { + public void apply(CodegenOperation codegenOperation) { + codegenOperation.vendorExtensions.put("x-java-constructor", true); + codegenOperation.vendorExtensions.put(SIGNATURE_LIST, generateSignatureListModern(codegenOperation)); + System.out.println(codegenOperation.vendorExtensions.get(SIGNATURE_LIST)); + } + + public boolean shouldApply(CodegenOperation codegenOperation) { + // Check if the operation consumes application/x-www-form-urlencoded + if (codegenOperation.consumes == null || codegenOperation.consumes.isEmpty()) { + return false; + } + return codegenOperation.consumes.stream() + .anyMatch(mediaType -> mediaType.get("mediaType").equals("application/x-www-form-urlencoded")); + } + + public List> generateSignatureListModern(final CodegenOperation codegenOperation) { + List requiredParams = codegenOperation.requiredParams; + + CodegenParameter accountSidParam = null; + Optional optionalParam = codegenOperation.pathParams.stream() + .filter(param -> param.vendorExtensions.containsKey(ACCOUNT_SID_VEND_EXT)).findAny(); + if(optionalParam.isPresent()){ + accountSidParam = optionalParam.get(); + } + + List> conditionalParameterDoubleList = getConditionalParameters(codegenOperation); + conditionalParameterDoubleList = Lists.cartesianProduct(conditionalParameterDoubleList); + // conditionalParameterDoubleList contains list of constructors only from conditional parameters + // We need to filter out similar constructors. + List> filteredConditionalCodegenParam = filterConditionalParametersByDatatype(conditionalParameterDoubleList); + + // Combine required and conditional parameters to form the signature list + List> signatureList = new ArrayList<>(); + for(List paramList : filteredConditionalCodegenParam){ + signatureList.add(addAllToList(codegenOperation.requiredParams, paramList)); + if( accountSidParam != null) { + signatureList.add(addAllToList(List.of(accountSidParam), requiredParams, paramList)); + } + } + return signatureList; + } + + @SafeVarargs + private final List mergeLists(List... lists) { + return Arrays.stream(lists).flatMap(List::stream).collect(Collectors.toList()); + } + + /* + The `conditionalParameterDoubleList` contains combinations of constructors derived solely from conditional parameters. + It is necessary to filter out constructors with similar parameter combinations to ensure uniqueness. + */ + private List> filterConditionalParametersByDatatype(List> conditionalParameterDoubleList) { + List> filteredConditionalCodegenParam = new ArrayList<>(); + HashSet> signatureHashSet = new HashSet<>(); + for (List paramList : conditionalParameterDoubleList) { + List orderedParamList = paramList.stream().map(p -> p.dataType).collect(Collectors.toList()); + if (signatureHashSet.add(orderedParamList)) { + filteredConditionalCodegenParam.add(paramList); + } + } + return filteredConditionalCodegenParam; + } + + private List> getConditionalParameters(CodegenOperation codegenOperation) { + List> conditionalCodegenParam = new ArrayList<>(); + + if (codegenOperation.vendorExtensions.containsKey("x-twilio")) { + HashMap twilioVendorExtension = (HashMap) codegenOperation.vendorExtensions.get("x-twilio"); + if (twilioVendorExtension.containsKey("conditional")) { + List> conditionalParamDoubleList = (List>) twilioVendorExtension.get("conditional"); + + // Look for conditional parameters in body + for (List conditionalParamList : conditionalParamDoubleList) { + List foundParameters = new ArrayList<>(); + for (String cp : conditionalParamList) { + CodegenParameter matchedParam = null; + for (CodegenParameter formParam : codegenOperation.formParams) { + if (!formParam.required + && StringHelper.camelize(formParam.baseName, true) + .equals(StringHelper.camelize(cp, true))) { + matchedParam = formParam; + break; + } + } + if (matchedParam == null) { + throw new IllegalArgumentException("Parameter not found: " + cp); + } + foundParameters.add(matchedParam); + } + conditionalCodegenParam.add(foundParameters); + } + + // Remove similar datatype parameters because they will create same constructors + List> filteredConditionalCodegenParam = new ArrayList<>(); + for (List cpList : conditionalCodegenParam) { + if (cpList.size() <= 1 || !cpList.get(0).dataType.equals(cpList.get(1).dataType)) { + filteredConditionalCodegenParam.add(cpList); + } + } + conditionalCodegenParam = filteredConditionalCodegenParam; } + } + + return conditionalCodegenParam; + } + + public ArrayList> generateSignatureList(final CodegenOperation co) { + CodegenParameter accountSidParam = null; + List> conditionalCodegenParam = new ArrayList<>(); + Optional optionalParam = co.allParams.stream() + .filter(param -> param.vendorExtensions.containsKey("x-account-sid")).findAny(); + if (optionalParam.isPresent()) { + accountSidParam = optionalParam.get(); + } + + if (co.vendorExtensions.containsKey("x-twilio")) { + HashMap twilioVendorExtension = (HashMap) co.vendorExtensions.get("x-twilio"); + if (twilioVendorExtension.containsKey("conditional")) { + List> conditionalParams = (List>) twilioVendorExtension.get("conditional"); + conditionalCodegenParam = conditionalParams.stream().map( + paramList -> paramList.stream().map( + cp -> co.optionalParams.stream().filter( + op -> op.paramName.equals(cp) + ).findAny().get() + ).collect(Collectors.toList())).collect(Collectors.toList()); + conditionalCodegenParam = conditionalCodegenParam.stream() + .filter(cpList -> (cpList.size() <= 1 || !cpList.get(0).dataType.equals(cpList.get(1).dataType))) + .collect(Collectors.toList()); + } + } + + conditionalCodegenParam = Lists.cartesianProduct(conditionalCodegenParam); + List> filteredConditionalCodegenParam = new ArrayList<>(); + HashSet> signatureHashSet = new HashSet<>(); + for (List paramList : conditionalCodegenParam) { + List orderedParamList = paramList.stream().map(p -> p.dataType).collect(Collectors.toList()); + if (!signatureHashSet.contains(orderedParamList)) { + filteredConditionalCodegenParam.add(paramList); + signatureHashSet.add(orderedParamList); + } + } + + ArrayList> signatureList = new ArrayList<>(); + for (List paramList : filteredConditionalCodegenParam) { + signatureList.add(addAllToList(co.requiredParams, paramList)); + if (accountSidParam != null) { + signatureList.add(addAllToList(List.of(accountSidParam), co.requiredParams, paramList)); + } + } + return signatureList; + } + + private List addAllToList(List... lists) { + return Arrays.stream(lists).flatMap(List::stream).collect(Collectors.toList()); + } +} \ No newline at end of file diff --git a/src/main/java/com/twilio/oai/java/processor/JavaOperationProcessor.java b/src/main/java/com/twilio/oai/java/processor/JavaOperationProcessor.java index c83438bcf..f7e73d6d4 100644 --- a/src/main/java/com/twilio/oai/java/processor/JavaOperationProcessor.java +++ b/src/main/java/com/twilio/oai/java/processor/JavaOperationProcessor.java @@ -1,5 +1,7 @@ package com.twilio.oai.java.processor; +import com.twilio.oai.java.feature.SetterMethodGenerator; +import com.twilio.oai.java.feature.constructor.ConstructorFactory; import com.twilio.oai.java.processor.parameter.ParameterProcessor; import com.twilio.oai.java.processor.requestbody.RequestBodyProcessorFactory; import org.openapitools.codegen.CodegenOperation; @@ -25,5 +27,11 @@ private JavaOperationProcessor() { public void process(final CodegenOperation codegenOperation) { ParameterProcessor.getInstance().process(codegenOperation); RequestBodyProcessorFactory.getInstance().process(codegenOperation); + + + + // All Features should be applied after processors are completed + ConstructorFactory.getInstance().applyFeature(codegenOperation); + SetterMethodGenerator.getInstance().apply(codegenOperation); } } From 17ed8bc157ab06f14d3db4754fa2e75533fc1b91 Mon Sep 17 00:00:00 2001 From: sbansla <104902068+sbansla@users.noreply.github.com> Date: Wed, 6 Aug 2025 20:12:25 +0530 Subject: [PATCH 11/38] Add format specific features (#673) --- .../twilio/oai/java/format/Deserializer.java | 14 +++++++ .../OpenApiSpecFormatFeatureConstants.java | 10 ++--- .../com/twilio/oai/java/format/Promoter.java | 37 +++++++++++++++++++ .../com/twilio/oai/java/format/Promotion.java | 12 ++++++ 4 files changed, 68 insertions(+), 5 deletions(-) create mode 100644 src/main/java/com/twilio/oai/java/format/Deserializer.java create mode 100644 src/main/java/com/twilio/oai/java/format/Promoter.java create mode 100644 src/main/java/com/twilio/oai/java/format/Promotion.java diff --git a/src/main/java/com/twilio/oai/java/format/Deserializer.java b/src/main/java/com/twilio/oai/java/format/Deserializer.java new file mode 100644 index 000000000..22ae9af02 --- /dev/null +++ b/src/main/java/com/twilio/oai/java/format/Deserializer.java @@ -0,0 +1,14 @@ +package com.twilio.oai.java.format; + +import org.openapitools.codegen.CodegenProperty; + +public class Deserializer { + + public static void addDeserializer(CodegenProperty codegenProperty) { + if (codegenProperty.getFormat() != null && OpenApiSpecFormatFeatureConstants.DESERIALIZER.containsKey(codegenProperty.getFormat())) { + String deserializer = OpenApiSpecFormatFeatureConstants.DESERIALIZER.get(codegenProperty.getFormat()); + codegenProperty.vendorExtensions.put("x-deserializer", deserializer); + System.out.println(deserializer); + } + } +} \ No newline at end of file diff --git a/src/main/java/com/twilio/oai/java/format/OpenApiSpecFormatFeatureConstants.java b/src/main/java/com/twilio/oai/java/format/OpenApiSpecFormatFeatureConstants.java index 82360de11..2568c6127 100644 --- a/src/main/java/com/twilio/oai/java/format/OpenApiSpecFormatFeatureConstants.java +++ b/src/main/java/com/twilio/oai/java/format/OpenApiSpecFormatFeatureConstants.java @@ -17,11 +17,11 @@ public class OpenApiSpecFormatFeatureConstants { * two setters will be created: one for `PhoneNumber` and another for `String`. * The promoter logic will be applied to the `String` setter. */ -// public final static Map PROMOTIONS = Map.of( -// "url", new Promotion("String", "Promoter.uriFromString({})"), -// "phone-number", new Promotion("String", "Promoter.phoneNumberFromString({})"), -// "twiml", new Promotion("String", "Promoter.twimlFromString({})") -// ); + public final static Map PROMOTIONS = Map.of( + "url", new Promotion("String", "Promoter.uriFromString({})"), + "phone-number", new Promotion("String", "Promoter.phoneNumberFromString({})"), + "twiml", new Promotion("String", "Promoter.twimlFromString({})") + ); /* * key (format) -> The key is the format defined in the OpenAPI Spec. diff --git a/src/main/java/com/twilio/oai/java/format/Promoter.java b/src/main/java/com/twilio/oai/java/format/Promoter.java new file mode 100644 index 000000000..b4e1c1407 --- /dev/null +++ b/src/main/java/com/twilio/oai/java/format/Promoter.java @@ -0,0 +1,37 @@ +package com.twilio.oai.java.format; + +import org.openapitools.codegen.CodegenOperation; +import org.openapitools.codegen.CodegenParameter; + +import java.util.List; +import java.util.stream.Collectors; + +/* + * The `Promoter` class is responsible for adding additional methods to provide flexibility + * for customers to pass `String` as an input parameter instead of specific objects. + * + * Promoters are applied only to inputs such as query, header, and URL-encoded form body parameters. + * These additional methods are generated alongside the required setter methods. + * + * Note: + * - Promoters cannot be applied to path parameters because path parameters cannot be custom objects + * defined in `PROMOTIONS`. + * - The promoter logic uses the `{{paramName}}` placeholder in the setter method argument to ensure + * proper substitution of parameter names. + */ +public class Promoter { + public static void addPromoter(final CodegenParameter codegenParameter) { + if (codegenParameter.dataFormat != null && OpenApiSpecFormatFeatureConstants.PROMOTIONS.containsKey(codegenParameter.dataFormat)) { + Promotion promotion = OpenApiSpecFormatFeatureConstants.PROMOTIONS.get(codegenParameter.dataFormat); + String promoter = promotion.getPromoter(); + String promoterToBeUsedInMustache = promoter.replace("{}", codegenParameter.paramName); + codegenParameter.vendorExtensions.put("x-promotion", promoterToBeUsedInMustache); + } + } + + public static void addPromotor(final CodegenOperation codegenOperation) { + List setterParameters = codegenOperation.allParams.stream().filter(param -> !param.isPathParam).collect(Collectors.toList()); + setterParameters.forEach(param -> addPromoter(param)); + codegenOperation.vendorExtensions.put("x-setter-methods", setterParameters); + } +} diff --git a/src/main/java/com/twilio/oai/java/format/Promotion.java b/src/main/java/com/twilio/oai/java/format/Promotion.java new file mode 100644 index 000000000..141a2d556 --- /dev/null +++ b/src/main/java/com/twilio/oai/java/format/Promotion.java @@ -0,0 +1,12 @@ +package com.twilio.oai.java.format; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@AllArgsConstructor +public class Promotion { + @Getter + String inputType; + @Getter + String promoter; +} From 5048693a5b6554c04058ed04b2825c71ac7f6c43 Mon Sep 17 00:00:00 2001 From: sbansla <104902068+sbansla@users.noreply.github.com> Date: Wed, 6 Aug 2025 22:23:18 +0530 Subject: [PATCH 12/38] added recursive traverser, json response processor, model processor, deserializer, added test spec for enum (#674) --- .../java/twilio_customfeature_v1.yaml | 2 + examples/test_spec/twilio_format_v1.yaml | 0 examples/test_spec/twilio_nestedmodel_v1.yaml | 2 + examples/test_spec/twilio_parameters_v1.yaml | 2 + examples/test_spec/twilio_request_v1.yaml | 3 + examples/test_spec/twilio_response_v1.yaml | 3 + examples/test_spec/twilio_testenum_v1.yaml | 114 +++++++ src/main/java/com/twilio/oai/LoggerUtil.java | 26 ++ .../twilio/oai/TwilioJavaGeneratorModern.java | 3 +- .../java/com/twilio/oai/common/Utility.java | 2 +- .../com/twilio/oai/java/JavaApiResource.java | 24 +- .../oai/java/JavaApiResourceBuilder.java | 1 - .../oai/{modern => java}/ResourceCache.java | 3 +- .../oai/java/nestedmodels/MustacheModel.java | 47 +++ .../processor/JavaOperationProcessor.java | 7 +- .../processor/enums/EnumProcessorFactory.java | 34 ++ .../body/InlineBodyEnumProcessor.java | 2 +- .../body/InlineBodyListEnumProcessor.java | 2 +- .../body/ReusableBodyEnumProcessor.java | 2 +- .../body/ReusableBodyListEnumProcessor.java | 2 +- .../param/InlineListParamEnumProcessor.java | 2 +- .../param/InlineParamEnumProcessor.java | 2 +- .../param/ReusableListParamEnumProcessor.java | 2 +- .../param/ReusableParamEnumProcessor.java | 2 +- .../property/InlineListPropEnumProcessor.java | 2 +- .../property/InlinePropEnumProcessor.java | 2 +- .../ReusableListPropEnumProcessor.java | 2 +- .../property/ReusablePropEnumProcessor.java | 2 +- .../processor/model/ListModelStrategy.java | 58 ++++ .../java/processor/model/ModelProcessor.java | 9 + .../model/ModelProcessorFactory.java | 38 +++ .../processor/model/SingleModelStrategy.java | 57 ++++ .../requestbody/JsonRequestProcessor.java | 41 +++ .../requestbody/RecursiveModelProcessor.java | 74 +++++ .../RequestBodyProcessorFactory.java | 5 +- .../responsebody/JsonResponseProcessor.java | 90 ++++++ .../responsebody/ResponseProcessor.java | 9 + .../ResponseProcessorFactory.java | 26 ++ .../parameter/EnumIdentifierHandler.java | 291 ------------------ .../parameter/FormParamInlineStrategy.java | 80 ----- .../parameter/FormParamListRefStrategy.java | 111 ------- .../parameter/FormParamListStrategy.java | 88 ------ .../enums/parameter/FormParamRefStrategy.java | 80 ----- .../parameter/InlineListParamStrategy.java | 87 ------ .../enums/parameter/InlineParamStrategy.java | 77 ----- .../ParameterEnumProcessingStrategy.java | 11 - .../enums/parameter/RefListParamStrategy.java | 88 ------ .../enums/parameter/RefParamStrategy.java | 74 ----- .../property/InlineListPropStrategy.java | 66 ---- .../enums/property/InlinePropStrategy.java | 75 ----- .../PropertyEnumProcessingStrategy.java | 11 - .../enums/property/RefListPropStrategy.java | 74 ----- .../enums/property/RefPropStrategy.java | 72 ----- .../com/twilio/oai/TwilioGeneratorTest.java | 5 +- 54 files changed, 683 insertions(+), 1311 deletions(-) create mode 100644 examples/test_spec/java/twilio_customfeature_v1.yaml create mode 100644 examples/test_spec/twilio_format_v1.yaml create mode 100644 examples/test_spec/twilio_nestedmodel_v1.yaml create mode 100644 examples/test_spec/twilio_parameters_v1.yaml create mode 100644 examples/test_spec/twilio_request_v1.yaml create mode 100644 examples/test_spec/twilio_response_v1.yaml create mode 100644 examples/test_spec/twilio_testenum_v1.yaml create mode 100644 src/main/java/com/twilio/oai/LoggerUtil.java rename src/main/java/com/twilio/oai/{modern => java}/ResourceCache.java (95%) create mode 100644 src/main/java/com/twilio/oai/java/processor/model/ListModelStrategy.java create mode 100644 src/main/java/com/twilio/oai/java/processor/model/ModelProcessor.java create mode 100644 src/main/java/com/twilio/oai/java/processor/model/ModelProcessorFactory.java create mode 100644 src/main/java/com/twilio/oai/java/processor/model/SingleModelStrategy.java create mode 100644 src/main/java/com/twilio/oai/java/processor/requestbody/JsonRequestProcessor.java create mode 100644 src/main/java/com/twilio/oai/java/processor/requestbody/RecursiveModelProcessor.java create mode 100644 src/main/java/com/twilio/oai/java/processor/responsebody/JsonResponseProcessor.java create mode 100644 src/main/java/com/twilio/oai/java/processor/responsebody/ResponseProcessor.java create mode 100644 src/main/java/com/twilio/oai/java/processor/responsebody/ResponseProcessorFactory.java delete mode 100644 src/main/java/com/twilio/oai/java/strategy/enums/parameter/EnumIdentifierHandler.java delete mode 100644 src/main/java/com/twilio/oai/java/strategy/enums/parameter/FormParamInlineStrategy.java delete mode 100644 src/main/java/com/twilio/oai/java/strategy/enums/parameter/FormParamListRefStrategy.java delete mode 100644 src/main/java/com/twilio/oai/java/strategy/enums/parameter/FormParamListStrategy.java delete mode 100644 src/main/java/com/twilio/oai/java/strategy/enums/parameter/FormParamRefStrategy.java delete mode 100644 src/main/java/com/twilio/oai/java/strategy/enums/parameter/InlineListParamStrategy.java delete mode 100644 src/main/java/com/twilio/oai/java/strategy/enums/parameter/InlineParamStrategy.java delete mode 100644 src/main/java/com/twilio/oai/java/strategy/enums/parameter/ParameterEnumProcessingStrategy.java delete mode 100644 src/main/java/com/twilio/oai/java/strategy/enums/parameter/RefListParamStrategy.java delete mode 100644 src/main/java/com/twilio/oai/java/strategy/enums/parameter/RefParamStrategy.java delete mode 100644 src/main/java/com/twilio/oai/java/strategy/enums/property/InlineListPropStrategy.java delete mode 100644 src/main/java/com/twilio/oai/java/strategy/enums/property/InlinePropStrategy.java delete mode 100644 src/main/java/com/twilio/oai/java/strategy/enums/property/PropertyEnumProcessingStrategy.java delete mode 100644 src/main/java/com/twilio/oai/java/strategy/enums/property/RefListPropStrategy.java delete mode 100644 src/main/java/com/twilio/oai/java/strategy/enums/property/RefPropStrategy.java diff --git a/examples/test_spec/java/twilio_customfeature_v1.yaml b/examples/test_spec/java/twilio_customfeature_v1.yaml new file mode 100644 index 000000000..4d479ff56 --- /dev/null +++ b/examples/test_spec/java/twilio_customfeature_v1.yaml @@ -0,0 +1,2 @@ +# This spec is twilio-java specific and Tests following +# 1. It tests custom feature for twilio-java examples: constructors, DateInequality \ No newline at end of file diff --git a/examples/test_spec/twilio_format_v1.yaml b/examples/test_spec/twilio_format_v1.yaml new file mode 100644 index 000000000..e69de29bb diff --git a/examples/test_spec/twilio_nestedmodel_v1.yaml b/examples/test_spec/twilio_nestedmodel_v1.yaml new file mode 100644 index 000000000..940719838 --- /dev/null +++ b/examples/test_spec/twilio_nestedmodel_v1.yaml @@ -0,0 +1,2 @@ +# This spec tests followings +# 1. Nested model in request body and component schema \ No newline at end of file diff --git a/examples/test_spec/twilio_parameters_v1.yaml b/examples/test_spec/twilio_parameters_v1.yaml new file mode 100644 index 000000000..3bf9e1cd2 --- /dev/null +++ b/examples/test_spec/twilio_parameters_v1.yaml @@ -0,0 +1,2 @@ +# This spec tests followings +# 1. All types of parameters(query, header, path) \ No newline at end of file diff --git a/examples/test_spec/twilio_request_v1.yaml b/examples/test_spec/twilio_request_v1.yaml new file mode 100644 index 000000000..eaa212c6d --- /dev/null +++ b/examples/test_spec/twilio_request_v1.yaml @@ -0,0 +1,3 @@ +# This spec tests followings +# 1. All types of request body(urlencoded, json) +# 2. Tests pagination for both type of request body. \ No newline at end of file diff --git a/examples/test_spec/twilio_response_v1.yaml b/examples/test_spec/twilio_response_v1.yaml new file mode 100644 index 000000000..3188edba5 --- /dev/null +++ b/examples/test_spec/twilio_response_v1.yaml @@ -0,0 +1,3 @@ +# This spec tests followings +# 1. All types of response body(json) +# 2. Tests paginated response. \ No newline at end of file diff --git a/examples/test_spec/twilio_testenum_v1.yaml b/examples/test_spec/twilio_testenum_v1.yaml new file mode 100644 index 000000000..fa019f500 --- /dev/null +++ b/examples/test_spec/twilio_testenum_v1.yaml @@ -0,0 +1,114 @@ +# This spec Tests following +# 1. All types of enums, There are 8 types of Enum to be tested +info: + contact: + email: support@twilio.com + name: Twilio Support + url: https://support.twilio.com + description: This is the public Twilio REST API. + license: + name: Apache 2.0 + url: https://www.apache.org/licenses/LICENSE-2.0.html + termsOfService: https://www.twilio.com/legal/tos + title: Twilio - CONTENT + version: 1.11.0 +openapi: 3.0.1 + +paths: + /v1/enum/{id}: + servers: + - url: https://testenum.twilio.com + get: + operationId: FetchAbc + summary: Retrieve items with various filter options + parameters: + - name: id + in: path + required: true + description: The unique identifier for the enum item + schema: + type: string + # 1. PARAMETER_SINGLE + - name: singleParam + in: query + description: A single enum value as a query parameter + required: false + schema: + type: string + enum: + - asc + - desc + example: asc + + # 2. PARAMETER_ARRAY + - name: arrayParam + in: query + description: Order items using an array of enums + required: false + schema: + type: array + items: + type: string + enum: + - asc + - desc + example: [asc] + + # 3. PARAMETER_ARRAY Referencing Reusable Schema + - name: arrayParamRef + in: query + required: false + description: An array parameter referencing a reusable schema + schema: + type: array + items: + $ref: '#/components/schemas/singleReusable' + + # 4. PARAMETER_REUSABLE_SINGLE + - name: singleParamRef + in: header + schema: + $ref: '#/components/schemas/singleReusable' + + responses: + '200': + description: A list of items + content: + application/json: + schema: + $ref: '#/components/schemas/Item' + +components: + schemas: + Item: + type: object + properties: + # 5. PROPERTY_SINGLE + singleProperty: + type: string + enum: [available, pending, sold] + description: A single enum value as a property in a schema + example: available + + # 6. PROPERTY_ARRAY + arrayProperty: + type: array + items: + type: string + enum: [new, sale, featured] + description: An array of enum values in a schema property + example: [new, featured] + + # 7. REUSABLE_ARRAY + arrayReusable: + type: array + items: + $ref: '#/components/schemas/singleReusable' + description: An array of reusable enum defined in components + example: [electronics, clothing] + + # 8. REUSABLE_SINGLE + singleReusable: + type: string + enum: [electronics, furniture, clothing] + description: A reusable single-value enum defined in components \ No newline at end of file diff --git a/src/main/java/com/twilio/oai/LoggerUtil.java b/src/main/java/com/twilio/oai/LoggerUtil.java new file mode 100644 index 000000000..6ee6c8d48 --- /dev/null +++ b/src/main/java/com/twilio/oai/LoggerUtil.java @@ -0,0 +1,26 @@ +package com.twilio.oai; + +import java.util.logging.Logger; + + +import java.util.logging.Logger; + +public class LoggerUtil { + private static final Logger LOGGER = Logger.getLogger(LoggerUtil.class.getName()); + + private LoggerUtil() { + // Private constructor to prevent instantiation + } + + public static void logWarning(String className, String message) { + LOGGER.warning("[" + className + "] " + message); + } + + public static void logInfo(String className, String message) { + LOGGER.info("[" + className + "] " + message); + } + + public static void logSevere(String className, String message) { + LOGGER.severe("[" + className + "] " + message); + } +} diff --git a/src/main/java/com/twilio/oai/TwilioJavaGeneratorModern.java b/src/main/java/com/twilio/oai/TwilioJavaGeneratorModern.java index 5643218dd..eb3ef4694 100644 --- a/src/main/java/com/twilio/oai/TwilioJavaGeneratorModern.java +++ b/src/main/java/com/twilio/oai/TwilioJavaGeneratorModern.java @@ -8,7 +8,7 @@ import com.twilio.oai.java.JavaApiResourceBuilder; import com.twilio.oai.java.JavaTemplateUpdater; import com.twilio.oai.java.format.JavaUpdateDefaultMapping; -import com.twilio.oai.modern.ResourceCache; +import com.twilio.oai.java.ResourceCache; import com.twilio.oai.resolver.java.JavaCaseResolver; import com.twilio.oai.resource.ResourceMap; import com.twilio.oai.templating.mustache.ReplaceHyphenLambda; @@ -131,6 +131,7 @@ public String getHelp() { } private JavaApiResource processCodegenOperations(List operations) { + templateUpdater.addApiTemplate(this, operations); JavaApiResource apiResource = new JavaApiResourceBuilder(this, operations) .resourceName() .recordKey() diff --git a/src/main/java/com/twilio/oai/common/Utility.java b/src/main/java/com/twilio/oai/common/Utility.java index 1ab17250d..31dcb2400 100644 --- a/src/main/java/com/twilio/oai/common/Utility.java +++ b/src/main/java/com/twilio/oai/common/Utility.java @@ -14,7 +14,7 @@ import java.util.regex.Pattern; import java.util.stream.Collectors; -import com.twilio.oai.modern.ResourceCache; +import com.twilio.oai.java.ResourceCache; import lombok.experimental.UtilityClass; import org.apache.commons.lang3.StringUtils; import org.openapitools.codegen.CodegenModel; diff --git a/src/main/java/com/twilio/oai/java/JavaApiResource.java b/src/main/java/com/twilio/oai/java/JavaApiResource.java index a69773c2b..75118ca56 100644 --- a/src/main/java/com/twilio/oai/java/JavaApiResource.java +++ b/src/main/java/com/twilio/oai/java/JavaApiResource.java @@ -1,7 +1,29 @@ package com.twilio.oai.java; +import com.twilio.oai.java.nestedmodels.MustacheEnum; +import com.twilio.oai.java.nestedmodels.MustacheModel; +import org.openapitools.codegen.CodegenOperation; +import org.openapitools.codegen.CodegenProperty; + +import java.util.HashSet; +import java.util.List; +import java.util.Set; + public class JavaApiResource { - public JavaApiResource(JavaApiResourceBuilder builder) { + String resourceName; + String recordKey; + Set mustacheEnums; + Set mustacheModels; + List operations; + Set response; + public JavaApiResource(JavaApiResourceBuilder builder) { + resourceName = ResourceCache.resourceName; + recordKey = builder.recordKey; + this.operations = builder.operations; + this.mustacheEnums = new HashSet<>(ResourceCache.getEnumsClassesForMustache()); + this.mustacheModels = new HashSet<>(ResourceCache.getModelClassesForMustache()); + this.response = ResourceCache.response; } } + diff --git a/src/main/java/com/twilio/oai/java/JavaApiResourceBuilder.java b/src/main/java/com/twilio/oai/java/JavaApiResourceBuilder.java index a20104404..d96dd580b 100644 --- a/src/main/java/com/twilio/oai/java/JavaApiResourceBuilder.java +++ b/src/main/java/com/twilio/oai/java/JavaApiResourceBuilder.java @@ -3,7 +3,6 @@ import com.twilio.oai.TwilioJavaGeneratorModern; import com.twilio.oai.common.Utility; import com.twilio.oai.java.processor.JavaOperationProcessor; -import com.twilio.oai.modern.ResourceCache; import org.apache.commons.lang3.StringUtils; import org.openapitools.codegen.CodegenOperation; diff --git a/src/main/java/com/twilio/oai/modern/ResourceCache.java b/src/main/java/com/twilio/oai/java/ResourceCache.java similarity index 95% rename from src/main/java/com/twilio/oai/modern/ResourceCache.java rename to src/main/java/com/twilio/oai/java/ResourceCache.java index d10cfb012..76b13b064 100644 --- a/src/main/java/com/twilio/oai/modern/ResourceCache.java +++ b/src/main/java/com/twilio/oai/java/ResourceCache.java @@ -1,11 +1,10 @@ -package com.twilio.oai.modern; +package com.twilio.oai.java; import com.twilio.oai.java.nestedmodels.MustacheEnum; import com.twilio.oai.java.nestedmodels.MustacheModel; import lombok.Getter; import lombok.Setter; import org.openapitools.codegen.CodegenModel; -import org.openapitools.codegen.CodegenParameter; import org.openapitools.codegen.CodegenProperty; import java.util.ArrayList; diff --git a/src/main/java/com/twilio/oai/java/nestedmodels/MustacheModel.java b/src/main/java/com/twilio/oai/java/nestedmodels/MustacheModel.java index c64507ada..55c63f9ed 100644 --- a/src/main/java/com/twilio/oai/java/nestedmodels/MustacheModel.java +++ b/src/main/java/com/twilio/oai/java/nestedmodels/MustacheModel.java @@ -1,4 +1,51 @@ package com.twilio.oai.java.nestedmodels; +import com.twilio.oai.common.Utility; +import org.checkerframework.checker.units.qual.A; +import org.openapitools.codegen.CodegenModel; +import org.openapitools.codegen.CodegenProperty; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +// Models can be created out of json request body or json response body. public class MustacheModel { + String className; + + // Used in either builder or setter + List optionalProperties; + + // Used in constructor + List mandatoryProperties; + + public MustacheModel(CodegenProperty codegenProperty, CodegenModel codegenModel) { + this.className = codegenModel.classname; + + this.optionalProperties = codegenModel.vars.stream() + .filter(codegenProperty1 -> !codegenProperty1.required) + .collect(Collectors.toList()); + this.mandatoryProperties = codegenModel.vars.stream() + .filter(codegenProperty1 -> codegenProperty1.required) + .collect(Collectors.toList()); + } + + public MustacheModel(String className, List mandatoryProperties, List optionalProperties) { + this.className = className; + this.mandatoryProperties = new ArrayList<>(mandatoryProperties); + this.optionalProperties = new ArrayList<>(optionalProperties); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) return true; + if (obj == null || getClass() != obj.getClass()) return false; + MustacheModel that = (MustacheModel) obj; + return className != null && className.equals(that.className); + } + + @Override + public int hashCode() { + return className != null ? className.hashCode() : 0; + } } diff --git a/src/main/java/com/twilio/oai/java/processor/JavaOperationProcessor.java b/src/main/java/com/twilio/oai/java/processor/JavaOperationProcessor.java index f7e73d6d4..e8ebca87c 100644 --- a/src/main/java/com/twilio/oai/java/processor/JavaOperationProcessor.java +++ b/src/main/java/com/twilio/oai/java/processor/JavaOperationProcessor.java @@ -4,6 +4,7 @@ import com.twilio.oai.java.feature.constructor.ConstructorFactory; import com.twilio.oai.java.processor.parameter.ParameterProcessor; import com.twilio.oai.java.processor.requestbody.RequestBodyProcessorFactory; +import com.twilio.oai.java.processor.responsebody.ResponseProcessorFactory; import org.openapitools.codegen.CodegenOperation; public class JavaOperationProcessor { @@ -20,14 +21,12 @@ public static synchronized JavaOperationProcessor getInstance() { return instance; } - private JavaOperationProcessor() { - - } + private JavaOperationProcessor() { } public void process(final CodegenOperation codegenOperation) { ParameterProcessor.getInstance().process(codegenOperation); RequestBodyProcessorFactory.getInstance().process(codegenOperation); - + ResponseProcessorFactory.getInstance().process(codegenOperation); // All Features should be applied after processors are completed diff --git a/src/main/java/com/twilio/oai/java/processor/enums/EnumProcessorFactory.java b/src/main/java/com/twilio/oai/java/processor/enums/EnumProcessorFactory.java index 0e374be98..5b52c4628 100644 --- a/src/main/java/com/twilio/oai/java/processor/enums/EnumProcessorFactory.java +++ b/src/main/java/com/twilio/oai/java/processor/enums/EnumProcessorFactory.java @@ -19,6 +19,8 @@ import java.util.List; +import static com.twilio.oai.common.ApplicationConstants.X_DATATYPE; + /* * Factory class to manage and apply enum processors for CodegenParameter and CodegenProperty. * @@ -77,10 +79,23 @@ public void applyProcessor(CodegenParameter codegenParameter) { for (ParameterEnumProcessor parameterEnumProcessor: parameterEnumProcessors) { if (parameterEnumProcessor.shouldProcess(codegenParameter)) { parameterEnumProcessor.process(codegenParameter); + // TODO: to be deleted later. + addDataType(codegenParameter); return; // Exit after the first processor that applies } } } + + // TODO: to be deleted later. + private void addDataType(CodegenParameter codegenParameter) { + codegenParameter.dataType = (String)codegenParameter.vendorExtensions.get(X_DATATYPE); + } + + // TODO: to be deleted later. + private void addDataType(CodegenProperty codegenProperty) { + codegenProperty.dataType = (String)codegenProperty.vendorExtensions.get(X_DATATYPE); + } + public void applyProcessor(CodegenProperty codegenProperty) { if (codegenProperty.dataFormat != null && codegenProperty.dataFormat.equals("http-method")) { return; @@ -88,8 +103,27 @@ public void applyProcessor(CodegenProperty codegenProperty) { for (PropertyEnumProcessor propertyEnumProcessor: propertyEnumProcessors) { if (propertyEnumProcessor.shouldProcess(codegenProperty)) { propertyEnumProcessor.process(codegenProperty); + addDataType(codegenProperty); return; // Exit after the first processor that applies } } } + + public boolean isEnum(final CodegenParameter codegenParameter) { + for (ParameterEnumProcessor parameterEnumProcessor: parameterEnumProcessors) { + if (parameterEnumProcessor.shouldProcess(codegenParameter)) { + return true; // If any processor can process, it's considered an enum + } + } + return false; + } + + public boolean isEnum(final CodegenProperty codegenProperty) { + for (PropertyEnumProcessor propertyEnumProcessor : propertyEnumProcessors) { + if (propertyEnumProcessor.shouldProcess(codegenProperty)) { + return true; // If any processor can process, it's considered an enum + } + } + return false; + } } \ No newline at end of file diff --git a/src/main/java/com/twilio/oai/java/processor/enums/parameter/body/InlineBodyEnumProcessor.java b/src/main/java/com/twilio/oai/java/processor/enums/parameter/body/InlineBodyEnumProcessor.java index 5a770036b..98b98b5cf 100644 --- a/src/main/java/com/twilio/oai/java/processor/enums/parameter/body/InlineBodyEnumProcessor.java +++ b/src/main/java/com/twilio/oai/java/processor/enums/parameter/body/InlineBodyEnumProcessor.java @@ -4,7 +4,7 @@ import com.twilio.oai.common.StringUtils; import com.twilio.oai.java.nestedmodels.MustacheEnum; import com.twilio.oai.java.processor.enums.parameter.ParameterEnumProcessor; -import com.twilio.oai.modern.ResourceCache; +import com.twilio.oai.java.ResourceCache; import org.openapitools.codegen.CodegenParameter; import java.util.List; diff --git a/src/main/java/com/twilio/oai/java/processor/enums/parameter/body/InlineBodyListEnumProcessor.java b/src/main/java/com/twilio/oai/java/processor/enums/parameter/body/InlineBodyListEnumProcessor.java index 602734f0e..223486722 100644 --- a/src/main/java/com/twilio/oai/java/processor/enums/parameter/body/InlineBodyListEnumProcessor.java +++ b/src/main/java/com/twilio/oai/java/processor/enums/parameter/body/InlineBodyListEnumProcessor.java @@ -5,7 +5,7 @@ import com.twilio.oai.common.Utility; import com.twilio.oai.java.nestedmodels.MustacheEnum; import com.twilio.oai.java.processor.enums.parameter.ParameterEnumProcessor; -import com.twilio.oai.modern.ResourceCache; +import com.twilio.oai.java.ResourceCache; import org.openapitools.codegen.CodegenParameter; import java.util.List; diff --git a/src/main/java/com/twilio/oai/java/processor/enums/parameter/body/ReusableBodyEnumProcessor.java b/src/main/java/com/twilio/oai/java/processor/enums/parameter/body/ReusableBodyEnumProcessor.java index c6bba7f27..07ea04929 100644 --- a/src/main/java/com/twilio/oai/java/processor/enums/parameter/body/ReusableBodyEnumProcessor.java +++ b/src/main/java/com/twilio/oai/java/processor/enums/parameter/body/ReusableBodyEnumProcessor.java @@ -5,7 +5,7 @@ import com.twilio.oai.common.Utility; import com.twilio.oai.java.nestedmodels.MustacheEnum; import com.twilio.oai.java.processor.enums.parameter.ParameterEnumProcessor; -import com.twilio.oai.modern.ResourceCache; +import com.twilio.oai.java.ResourceCache; import org.openapitools.codegen.CodegenParameter; import java.util.List; diff --git a/src/main/java/com/twilio/oai/java/processor/enums/parameter/body/ReusableBodyListEnumProcessor.java b/src/main/java/com/twilio/oai/java/processor/enums/parameter/body/ReusableBodyListEnumProcessor.java index cd7037eaf..b962684f6 100644 --- a/src/main/java/com/twilio/oai/java/processor/enums/parameter/body/ReusableBodyListEnumProcessor.java +++ b/src/main/java/com/twilio/oai/java/processor/enums/parameter/body/ReusableBodyListEnumProcessor.java @@ -5,7 +5,7 @@ import com.twilio.oai.common.Utility; import com.twilio.oai.java.nestedmodels.MustacheEnum; import com.twilio.oai.java.processor.enums.parameter.ParameterEnumProcessor; -import com.twilio.oai.modern.ResourceCache; +import com.twilio.oai.java.ResourceCache; import org.openapitools.codegen.CodegenModel; import org.openapitools.codegen.CodegenParameter; diff --git a/src/main/java/com/twilio/oai/java/processor/enums/parameter/param/InlineListParamEnumProcessor.java b/src/main/java/com/twilio/oai/java/processor/enums/parameter/param/InlineListParamEnumProcessor.java index 5eadec69b..7797ab7f0 100644 --- a/src/main/java/com/twilio/oai/java/processor/enums/parameter/param/InlineListParamEnumProcessor.java +++ b/src/main/java/com/twilio/oai/java/processor/enums/parameter/param/InlineListParamEnumProcessor.java @@ -5,7 +5,7 @@ import com.twilio.oai.common.Utility; import com.twilio.oai.java.nestedmodels.MustacheEnum; import com.twilio.oai.java.processor.enums.parameter.ParameterEnumProcessor; -import com.twilio.oai.modern.ResourceCache; +import com.twilio.oai.java.ResourceCache; import org.openapitools.codegen.CodegenParameter; import java.util.List; diff --git a/src/main/java/com/twilio/oai/java/processor/enums/parameter/param/InlineParamEnumProcessor.java b/src/main/java/com/twilio/oai/java/processor/enums/parameter/param/InlineParamEnumProcessor.java index 055e968e3..13b174782 100644 --- a/src/main/java/com/twilio/oai/java/processor/enums/parameter/param/InlineParamEnumProcessor.java +++ b/src/main/java/com/twilio/oai/java/processor/enums/parameter/param/InlineParamEnumProcessor.java @@ -4,7 +4,7 @@ import com.twilio.oai.common.StringUtils; import com.twilio.oai.java.nestedmodels.MustacheEnum; import com.twilio.oai.java.processor.enums.parameter.ParameterEnumProcessor; -import com.twilio.oai.modern.ResourceCache; +import com.twilio.oai.java.ResourceCache; import org.openapitools.codegen.CodegenParameter; import java.util.List; diff --git a/src/main/java/com/twilio/oai/java/processor/enums/parameter/param/ReusableListParamEnumProcessor.java b/src/main/java/com/twilio/oai/java/processor/enums/parameter/param/ReusableListParamEnumProcessor.java index 21cb71b17..eca1b5d73 100644 --- a/src/main/java/com/twilio/oai/java/processor/enums/parameter/param/ReusableListParamEnumProcessor.java +++ b/src/main/java/com/twilio/oai/java/processor/enums/parameter/param/ReusableListParamEnumProcessor.java @@ -5,7 +5,7 @@ import com.twilio.oai.common.Utility; import com.twilio.oai.java.nestedmodels.MustacheEnum; import com.twilio.oai.java.processor.enums.parameter.ParameterEnumProcessor; -import com.twilio.oai.modern.ResourceCache; +import com.twilio.oai.java.ResourceCache; import org.openapitools.codegen.CodegenParameter; import java.util.List; diff --git a/src/main/java/com/twilio/oai/java/processor/enums/parameter/param/ReusableParamEnumProcessor.java b/src/main/java/com/twilio/oai/java/processor/enums/parameter/param/ReusableParamEnumProcessor.java index 9cb85fdc7..68b804cb8 100644 --- a/src/main/java/com/twilio/oai/java/processor/enums/parameter/param/ReusableParamEnumProcessor.java +++ b/src/main/java/com/twilio/oai/java/processor/enums/parameter/param/ReusableParamEnumProcessor.java @@ -5,7 +5,7 @@ import com.twilio.oai.common.Utility; import com.twilio.oai.java.nestedmodels.MustacheEnum; import com.twilio.oai.java.processor.enums.parameter.ParameterEnumProcessor; -import com.twilio.oai.modern.ResourceCache; +import com.twilio.oai.java.ResourceCache; import org.openapitools.codegen.CodegenParameter; import java.util.List; diff --git a/src/main/java/com/twilio/oai/java/processor/enums/property/InlineListPropEnumProcessor.java b/src/main/java/com/twilio/oai/java/processor/enums/property/InlineListPropEnumProcessor.java index 77c2e9bd9..e40b652b5 100644 --- a/src/main/java/com/twilio/oai/java/processor/enums/property/InlineListPropEnumProcessor.java +++ b/src/main/java/com/twilio/oai/java/processor/enums/property/InlineListPropEnumProcessor.java @@ -4,7 +4,7 @@ import com.twilio.oai.common.StringUtils; import com.twilio.oai.common.Utility; import com.twilio.oai.java.nestedmodels.MustacheEnum; -import com.twilio.oai.modern.ResourceCache; +import com.twilio.oai.java.ResourceCache; import org.openapitools.codegen.CodegenProperty; import java.util.List; diff --git a/src/main/java/com/twilio/oai/java/processor/enums/property/InlinePropEnumProcessor.java b/src/main/java/com/twilio/oai/java/processor/enums/property/InlinePropEnumProcessor.java index e7556a207..2d02af04b 100644 --- a/src/main/java/com/twilio/oai/java/processor/enums/property/InlinePropEnumProcessor.java +++ b/src/main/java/com/twilio/oai/java/processor/enums/property/InlinePropEnumProcessor.java @@ -4,7 +4,7 @@ import com.twilio.oai.common.EnumConstants.OpenApiEnumType; import com.twilio.oai.common.StringUtils; import com.twilio.oai.java.nestedmodels.MustacheEnum; -import com.twilio.oai.modern.ResourceCache; +import com.twilio.oai.java.ResourceCache; import org.openapitools.codegen.CodegenProperty; import java.util.ArrayList; diff --git a/src/main/java/com/twilio/oai/java/processor/enums/property/ReusableListPropEnumProcessor.java b/src/main/java/com/twilio/oai/java/processor/enums/property/ReusableListPropEnumProcessor.java index e8c027186..7ed0b42a9 100644 --- a/src/main/java/com/twilio/oai/java/processor/enums/property/ReusableListPropEnumProcessor.java +++ b/src/main/java/com/twilio/oai/java/processor/enums/property/ReusableListPropEnumProcessor.java @@ -4,7 +4,7 @@ import com.twilio.oai.common.StringUtils; import com.twilio.oai.common.Utility; import com.twilio.oai.java.nestedmodels.MustacheEnum; -import com.twilio.oai.modern.ResourceCache; +import com.twilio.oai.java.ResourceCache; import org.openapitools.codegen.CodegenProperty; import java.util.List; diff --git a/src/main/java/com/twilio/oai/java/processor/enums/property/ReusablePropEnumProcessor.java b/src/main/java/com/twilio/oai/java/processor/enums/property/ReusablePropEnumProcessor.java index 1396244c7..e1de60784 100644 --- a/src/main/java/com/twilio/oai/java/processor/enums/property/ReusablePropEnumProcessor.java +++ b/src/main/java/com/twilio/oai/java/processor/enums/property/ReusablePropEnumProcessor.java @@ -5,7 +5,7 @@ import com.twilio.oai.common.StringUtils; import com.twilio.oai.common.Utility; import com.twilio.oai.java.nestedmodels.MustacheEnum; -import com.twilio.oai.modern.ResourceCache; +import com.twilio.oai.java.ResourceCache; import org.openapitools.codegen.CodegenProperty; import java.util.ArrayList; diff --git a/src/main/java/com/twilio/oai/java/processor/model/ListModelStrategy.java b/src/main/java/com/twilio/oai/java/processor/model/ListModelStrategy.java new file mode 100644 index 000000000..f279c8c1f --- /dev/null +++ b/src/main/java/com/twilio/oai/java/processor/model/ListModelStrategy.java @@ -0,0 +1,58 @@ +package com.twilio.oai.java.processor.model; + +import com.twilio.oai.common.EnumConstants.ModelType; +import com.twilio.oai.common.StringUtils; +import com.twilio.oai.common.Utility; +import com.twilio.oai.java.nestedmodels.MustacheModel; +import com.twilio.oai.java.ResourceCache; +import org.openapitools.codegen.CodegenModel; +import org.openapitools.codegen.CodegenProperty; + +import static com.twilio.oai.common.ApplicationConstants.DOT; +import static com.twilio.oai.common.ApplicationConstants.X_DATATYPE; +import static com.twilio.oai.common.ApplicationConstants.X_MODEL_TYPE; +import static com.twilio.oai.common.ApplicationConstants.X_VARIABLE_NAME; + +public class ListModelStrategy implements ModelProcessor { + ModelType type = ModelType.LIST; + @Override + public void process(CodegenProperty codegenProperty, CodegenModel codegenModel) { + if (!codegenProperty.isContainer) return; + type(codegenProperty); + variableName(codegenProperty); + dataType(codegenProperty); + cacheModelClass(codegenProperty, codegenModel); + + } + + @Override + public boolean shouldProcess(CodegenProperty codegenProperty, CodegenModel codegenModel) { + if (codegenProperty.isContainer) return true; + return false; + } + + public ModelType getType() { + return type; + } + + + private void type(final CodegenProperty codegenProperty) { + codegenProperty.vendorExtensions.put(X_MODEL_TYPE, type); + } + + private void variableName(CodegenProperty codegenProperty) { + codegenProperty.vendorExtensions.put(X_VARIABLE_NAME, StringUtils.toCamelCase(codegenProperty.baseName)); + } + // basetype + private void dataType(CodegenProperty codegenProperty) { + //TODO: Need to identify whether the property is defined using ref or directly defined property + String datatypeInsideContainer = Utility.extractDatatypeFromContainer(codegenProperty.dataType); + String updatedDataType = Utility.replaceDatatypeInContainer(codegenProperty.dataType, ResourceCache.getResourceName() + DOT + datatypeInsideContainer); + codegenProperty.vendorExtensions.put(X_DATATYPE, updatedDataType); + } + + private void cacheModelClass(CodegenProperty codegenProperty, CodegenModel codegenModel) { + MustacheModel mustacheModel = new MustacheModel(codegenProperty, codegenModel); + ResourceCache.addToModelClasses(mustacheModel); + } +} diff --git a/src/main/java/com/twilio/oai/java/processor/model/ModelProcessor.java b/src/main/java/com/twilio/oai/java/processor/model/ModelProcessor.java new file mode 100644 index 000000000..1d912ad4a --- /dev/null +++ b/src/main/java/com/twilio/oai/java/processor/model/ModelProcessor.java @@ -0,0 +1,9 @@ +package com.twilio.oai.java.processor.model; + +import org.openapitools.codegen.CodegenModel; +import org.openapitools.codegen.CodegenProperty; + +public interface ModelProcessor { + boolean shouldProcess(CodegenProperty codegenProperty, CodegenModel codegenModel); + void process(CodegenProperty codegenProperty, CodegenModel codegenModel); +} diff --git a/src/main/java/com/twilio/oai/java/processor/model/ModelProcessorFactory.java b/src/main/java/com/twilio/oai/java/processor/model/ModelProcessorFactory.java new file mode 100644 index 000000000..9bda10caf --- /dev/null +++ b/src/main/java/com/twilio/oai/java/processor/model/ModelProcessorFactory.java @@ -0,0 +1,38 @@ +package com.twilio.oai.java.processor.model; + +import org.openapitools.codegen.CodegenModel; +import org.openapitools.codegen.CodegenProperty; + +import java.util.List; + +public class ModelProcessorFactory { + + private static ModelProcessorFactory instance; + private final List modelProcessors; + public static synchronized ModelProcessorFactory getInstance() { + if (instance == null) { + synchronized (ModelProcessorFactory.class) { + if (instance == null) { + instance = new ModelProcessorFactory(); + } + } + } + return instance; + } + + private ModelProcessorFactory() { + modelProcessors = List.of( + new SingleModelStrategy(), + new ListModelStrategy() + ); + } + + public void applyProcessor(CodegenProperty codegenProperty, CodegenModel codegenModel) { + for (ModelProcessor modelProcessor : modelProcessors) { + if (modelProcessor.shouldProcess(codegenProperty, codegenModel)) { + modelProcessor.process(codegenProperty, codegenModel); + return; + } + } + } +} diff --git a/src/main/java/com/twilio/oai/java/processor/model/SingleModelStrategy.java b/src/main/java/com/twilio/oai/java/processor/model/SingleModelStrategy.java new file mode 100644 index 000000000..447fec690 --- /dev/null +++ b/src/main/java/com/twilio/oai/java/processor/model/SingleModelStrategy.java @@ -0,0 +1,57 @@ +package com.twilio.oai.java.processor.model; + + +import com.twilio.oai.common.StringUtils; +import com.twilio.oai.java.nestedmodels.MustacheModel; +import com.twilio.oai.java.ResourceCache; +import org.openapitools.codegen.CodegenModel; +import org.openapitools.codegen.CodegenProperty; + +import static com.twilio.oai.common.ApplicationConstants.DOT; +import static com.twilio.oai.common.ApplicationConstants.X_DATATYPE; +import static com.twilio.oai.common.ApplicationConstants.X_MODEL_TYPE; +import static com.twilio.oai.common.ApplicationConstants.X_VARIABLE_NAME; +import static com.twilio.oai.common.EnumConstants.ModelType; +public class SingleModelStrategy implements ModelProcessor { + ModelType type = ModelType.SINGLE; + + @Override + public boolean shouldProcess(CodegenProperty codegenProperty, CodegenModel codegenModel) { + if (!codegenProperty.isContainer) return true; + return false; + } + + @Override + public void process(CodegenProperty codegenProperty, CodegenModel codegenModel) { + if (codegenProperty.isContainer) return; + type(codegenProperty); + variableName(codegenProperty); + dataType(codegenProperty); + cacheModelClass(codegenProperty, codegenModel); + } + + public ModelType getType() { + return type; + } + + private void type(final CodegenProperty codegenProperty) { + codegenProperty.vendorExtensions.put(X_MODEL_TYPE, type); + } + + private void variableName(CodegenProperty codegenProperty) { + // This will be used in CRUDF(creator, reader etc) classes. + codegenProperty.vendorExtensions.put(X_VARIABLE_NAME, StringUtils.toCamelCase(codegenProperty.baseName)); + } + // basetype + private void dataType(CodegenProperty codegenProperty) { + //TODO: Need to identify whether the property is defined using ref or directly defined property + codegenProperty.vendorExtensions.put(X_DATATYPE, ResourceCache.getResourceName() + DOT + codegenProperty.dataType); + } + + private void cacheModelClass(CodegenProperty codegenProperty, CodegenModel codegenModel) { + MustacheModel mustacheModel = new MustacheModel(codegenProperty, codegenModel); + ResourceCache.addToModelClasses(mustacheModel); + } + + +} diff --git a/src/main/java/com/twilio/oai/java/processor/requestbody/JsonRequestProcessor.java b/src/main/java/com/twilio/oai/java/processor/requestbody/JsonRequestProcessor.java new file mode 100644 index 000000000..81098fb8e --- /dev/null +++ b/src/main/java/com/twilio/oai/java/processor/requestbody/JsonRequestProcessor.java @@ -0,0 +1,41 @@ +package com.twilio.oai.java.processor.requestbody; + +import com.twilio.oai.LoggerUtil; +import org.openapitools.codegen.CodegenOperation; + +import static com.twilio.oai.common.ApplicationConstants.X_REQUEST_CONTENT_TYPE; +import static com.twilio.oai.java.MustacheConstants.X_REQUEST_LANGUAGE_CONTENT_TYPE_CONSTANT; + +public class JsonRequestProcessor implements RequestBodyProcessor { + final RecursiveModelProcessor recursiveModelProcessor = new RecursiveModelProcessor(); + public JsonRequestProcessor() { + // Constructor can be used for initialization if needed + } + + @Override + public boolean shouldProcess(final CodegenOperation codegenOperation) { + // TODO + return false; + } + + @Override + public void process(CodegenOperation codegenOperation) { + codegenOperation.vendorExtensions.put(X_REQUEST_CONTENT_TYPE, getContentType()); + codegenOperation.vendorExtensions.put(X_REQUEST_CONTENT_TYPE, getContentType()); + codegenOperation.vendorExtensions.put(X_REQUEST_LANGUAGE_CONTENT_TYPE_CONSTANT, "JSON"); + System.out.println(codegenOperation.operationId); + if (!codegenOperation.getHasBodyParam()) return; + if (codegenOperation.bodyParams.size() > 1) { + LoggerUtil.logSevere(this.getClass().getName(), "Multiple request bodies found " + codegenOperation.operationId); + } + + + recursiveModelProcessor.processBody(codegenOperation); + + } + + @Override + public String getContentType() { + return "application/json"; + } +} diff --git a/src/main/java/com/twilio/oai/java/processor/requestbody/RecursiveModelProcessor.java b/src/main/java/com/twilio/oai/java/processor/requestbody/RecursiveModelProcessor.java new file mode 100644 index 000000000..999784259 --- /dev/null +++ b/src/main/java/com/twilio/oai/java/processor/requestbody/RecursiveModelProcessor.java @@ -0,0 +1,74 @@ +package com.twilio.oai.java.processor.requestbody; + +import com.twilio.oai.common.Utility; +import com.twilio.oai.java.format.Deserializer; +import com.twilio.oai.java.processor.enums.EnumProcessorFactory; +import com.twilio.oai.java.processor.model.ModelProcessorFactory; +import org.openapitools.codegen.CodegenModel; +import org.openapitools.codegen.CodegenOperation; +import org.openapitools.codegen.CodegenProperty; + +public class RecursiveModelProcessor { + EnumProcessorFactory enumProcessorFactory = EnumProcessorFactory.getInstance(); + ModelProcessorFactory modelProcessorFactory = ModelProcessorFactory.getInstance(); + + public void processBody(CodegenOperation codegenOperation) { + // codegenOperation.bodyParam.vars.get(3).ref: #/components/schemas/types + codegenOperation.bodyParam.vars.forEach(property -> processModelRecursively(property)); + } + + public void processResponse(final CodegenOperation codegenOperation) { + // Make sure to filter pagination models. + return ; + } + + + // DFS based recursive logic + private void processModelRecursively(final CodegenProperty codegenProperty) { + CodegenModel codegenModel = Utility.getModelFromOpenApiType(codegenProperty); + /* + This code block has access to all the codegenProperty for a nested model. + Add your logic to process the property. + Start + */ + + + if (isEnum(codegenProperty)) { + // Logic 1: Enum Logic + processEnum(codegenProperty); + return; + } + if (codegenModel == null) { + // For non ref models, CodegenModel will be present. Non model nor enum. + // Logic 3: Normal variable logic + Deserializer.addDeserializer(codegenProperty); + + return; + } + // Logic 2: nested model logic + modelProcessorFactory.applyProcessor(codegenProperty, codegenModel); + + /* + End + */ + + + + // A Model has been identified, look for child models + if (codegenModel.vars != null && !codegenModel.vars.isEmpty()) { + for (CodegenProperty modelProperty : codegenModel.vars) { + processModelRecursively(modelProperty); + } + } + } + + + + private boolean isEnum(CodegenProperty codegenProperty) { + return enumProcessorFactory.isEnum(codegenProperty); + } + + private void processEnum(CodegenProperty codegenProperty) { + enumProcessorFactory.applyProcessor(codegenProperty); + } +} diff --git a/src/main/java/com/twilio/oai/java/processor/requestbody/RequestBodyProcessorFactory.java b/src/main/java/com/twilio/oai/java/processor/requestbody/RequestBodyProcessorFactory.java index f2cdfd749..7bc940919 100644 --- a/src/main/java/com/twilio/oai/java/processor/requestbody/RequestBodyProcessorFactory.java +++ b/src/main/java/com/twilio/oai/java/processor/requestbody/RequestBodyProcessorFactory.java @@ -10,7 +10,8 @@ public class RequestBodyProcessorFactory { private RequestBodyProcessorFactory() { this.requestBodyProcessors = List.of( - new UrlEncodedProcessor() + new UrlEncodedProcessor(), + new JsonRequestProcessor() ); } @@ -26,7 +27,7 @@ public static synchronized RequestBodyProcessorFactory getInstance() { } public void process(final CodegenOperation codegenOperation) { - for (RequestBodyProcessor requestBodyProcessor: requestBodyProcessors) { + for (RequestBodyProcessor requestBodyProcessor : requestBodyProcessors) { if (requestBodyProcessor.shouldProcess(codegenOperation)) { requestBodyProcessor.process(codegenOperation); return; // Exit after the first processor that applies diff --git a/src/main/java/com/twilio/oai/java/processor/responsebody/JsonResponseProcessor.java b/src/main/java/com/twilio/oai/java/processor/responsebody/JsonResponseProcessor.java new file mode 100644 index 000000000..56cba625c --- /dev/null +++ b/src/main/java/com/twilio/oai/java/processor/responsebody/JsonResponseProcessor.java @@ -0,0 +1,90 @@ +package com.twilio.oai.java.processor.responsebody; + +import com.twilio.oai.common.Utility; +import com.twilio.oai.java.format.Deserializer; +import com.twilio.oai.java.ResourceCache; +import com.twilio.oai.java.processor.enums.EnumProcessorFactory; +import org.openapitools.codegen.CodegenMediaType; +import org.openapitools.codegen.CodegenModel; +import org.openapitools.codegen.CodegenOperation; +import org.openapitools.codegen.CodegenProperty; +import org.openapitools.codegen.CodegenResponse; + +import java.util.Map; + +public class JsonResponseProcessor implements ResponseProcessor { + EnumProcessorFactory enumProcessorFactory = EnumProcessorFactory.getInstance(); + @Override + public void process(final CodegenOperation codegenOperation) { + System.out.println(codegenOperation.operationId); + + CodegenModel codegenModel = getModel(codegenOperation); + if (codegenModel == null) return; + CodegenModel responseModel = codegenModel; + + if (codegenOperation.operationId.toLowerCase().startsWith("list")) { + responseModel = getModelFromListOperation(codegenModel); + if (responseModel == null) return; + } + + responseModel.vars.forEach(codegenProperty -> { + enumProcessorFactory.applyProcessor(codegenProperty); + Deserializer.addDeserializer(codegenProperty); + }); + responseModel.vars.forEach(ResourceCache.getResponse()::add); + } + + //model.vars.get(0).items.ref to get actual output + private CodegenModel getModelFromListOperation(CodegenModel codegenModel) { + System.out.println(codegenModel); + for (CodegenProperty codegenProperty: codegenModel.vars) { + // We expect list operation to have pagination. + if (codegenProperty.isContainer) { + String ref = codegenProperty.items.getRef(); + CodegenModel responseModel = Utility.getModelFromRef(ref); + return responseModel; + } + } + return null; + } + + public boolean shouldProcess(final CodegenOperation codegenOperation) { + System.out.println(codegenOperation.operationId); + if (codegenOperation.produces != null && !codegenOperation.produces.isEmpty()) { + for (Map contentType : codegenOperation.produces) { + if (getContentType().equals(contentType.get("mediaType"))) { + return true; + } + } + } + return false; + } + + @Override + public String getContentType() { + return "application/json"; + } + + // if $ref, model name: codegenOperation.responses.get(0).content.get("application/json").schema.getRef() + // output: #/components/schemas/api.v2010.account.message + private CodegenModel getModel(final CodegenOperation codegenOperation) { + if (codegenOperation.responses != null && !codegenOperation.responses.isEmpty()) { + for (CodegenResponse codegenResponse: codegenOperation.responses) { + if (codegenResponse.is2xx || codegenResponse.is3xx) { + if (codegenResponse == null) return null; + CodegenMediaType codegenMediaType = codegenResponse.getContent().get(getContentType()); + if (codegenMediaType == null) return null; + if (codegenMediaType.getSchema().isContainer) { + // It covers special case in which response is list + // TODO: Handle in future. + } + String ref = codegenMediaType.getSchema().getRef(); + CodegenModel model = Utility.getModelFromRef(ref); + return model; + + } + } + } + return null; + } +} diff --git a/src/main/java/com/twilio/oai/java/processor/responsebody/ResponseProcessor.java b/src/main/java/com/twilio/oai/java/processor/responsebody/ResponseProcessor.java new file mode 100644 index 000000000..32422a7a6 --- /dev/null +++ b/src/main/java/com/twilio/oai/java/processor/responsebody/ResponseProcessor.java @@ -0,0 +1,9 @@ +package com.twilio.oai.java.processor.responsebody; + +import org.openapitools.codegen.CodegenOperation; + +public interface ResponseProcessor { + void process(CodegenOperation codegenOperation); + String getContentType(); + boolean shouldProcess(CodegenOperation codegenOperation); +} diff --git a/src/main/java/com/twilio/oai/java/processor/responsebody/ResponseProcessorFactory.java b/src/main/java/com/twilio/oai/java/processor/responsebody/ResponseProcessorFactory.java new file mode 100644 index 000000000..d67553649 --- /dev/null +++ b/src/main/java/com/twilio/oai/java/processor/responsebody/ResponseProcessorFactory.java @@ -0,0 +1,26 @@ +package com.twilio.oai.java.processor.responsebody; + +import org.openapitools.codegen.CodegenOperation; + +import java.util.ArrayList; +import java.util.List; + +public class ResponseProcessorFactory { + private final List processors = new ArrayList<>(); + private static final ResponseProcessorFactory INSTANCE = new ResponseProcessorFactory(); + + private ResponseProcessorFactory() { + processors.add(new JsonResponseProcessor()); + } + + public static ResponseProcessorFactory getInstance() { + return INSTANCE; + } + public void process(final CodegenOperation codegenOperation) { + for (ResponseProcessor responseProcessor : processors) { + if (responseProcessor.shouldProcess(codegenOperation)) { + responseProcessor.process(codegenOperation); + } + } + } +} diff --git a/src/main/java/com/twilio/oai/java/strategy/enums/parameter/EnumIdentifierHandler.java b/src/main/java/com/twilio/oai/java/strategy/enums/parameter/EnumIdentifierHandler.java deleted file mode 100644 index e863a57cd..000000000 --- a/src/main/java/com/twilio/oai/java/strategy/enums/parameter/EnumIdentifierHandler.java +++ /dev/null @@ -1,291 +0,0 @@ -package com.twilio.oai.java.strategy.enums.parameter; - -import com.twilio.oai.common.EnumConstants; -import com.twilio.oai.common.StringUtils; -import com.twilio.oai.common.Utility; -import com.twilio.oai.java.strategy.enums.property.InlineListPropStrategy; -import com.twilio.oai.java.strategy.enums.property.RefListPropStrategy; -import com.twilio.oai.java.strategy.enums.property.RefPropStrategy; -import com.twilio.oai.java.strategy.enums.property.InlinePropStrategy; -import com.twilio.oai.java.strategy.enums.property.PropertyEnumProcessingStrategy; -import com.twilio.oai.modern.ResourceCache; -import org.openapitools.codegen.CodegenModel; -import org.openapitools.codegen.CodegenParameter; -import org.openapitools.codegen.CodegenProperty; - -import java.util.List; - -import static com.twilio.oai.common.ApplicationConstants.X_VARIABLE_NAME; -import static com.twilio.oai.common.ApplicationConstants.X_ENUM_TYPE; -import static com.twilio.oai.common.ApplicationConstants.X_DATATYPE; -import static com.twilio.oai.common.ApplicationConstants.DOT; - -// It does not do any processing, It will just return if a passed parameter or property is an Enum -public class EnumIdentifierHandler { - private final List parameterStrategies; - - private final List propertyStrategies; - - public EnumIdentifierHandler() { - parameterStrategies = List.of( - new InlineParamStrategy(), - new RefParamStrategy(), - new InlineListParamStrategy(), - new RefListParamStrategy(), - new FormParamInlineStrategy(), - new FormParamRefStrategy(), - new FormParamListStrategy(), - new FormParamListRefStrategy() - ); - - propertyStrategies = List.of( - new InlinePropStrategy(), - new RefPropStrategy(), - new InlineListPropStrategy(), - new RefListPropStrategy() - ); - } - - public void identify(CodegenParameter codegenParameter) { - if ("http-method".equals(codegenParameter.dataFormat)) { - return; - } - for (ParameterEnumProcessingStrategy strategy : parameterStrategies) { - if (strategy.isStrategyApplicable(codegenParameter)) { - System.out.println("Strategy matched: " + strategy.getType() + " Enum Basename: " + codegenParameter.baseName); - break; - } - } - } - public boolean identify(CodegenProperty codegenProperty) { - if ("http-method".equals(codegenProperty.dataFormat)) { - return false; - } - for (PropertyEnumProcessingStrategy strategy : propertyStrategies) { - if (strategy.isStrategyApplicable(codegenProperty)) { - System.out.println("Strategy matched: " + strategy.getType() + " Enum Basename: " + codegenProperty.baseName); - return true; - } - } - return false; - } - - public void identify(CodegenModel codegenModel) { - - } - - /* - .isEnum = true - .isEnumRef = true - .schema.isEnum = true - .ref = null - .isContainer = false - .items = null - - codegenParameter.schema._enum = enum array values - */ - private boolean isParameterSingle(CodegenParameter codegenParameter) { - if (codegenParameter.getSchema()._enum != null && codegenParameter.isEnum) { - System.out.println("Identified as single parameter enum: " + codegenParameter.baseName); - codegenParameter.vendorExtensions.put(X_ENUM_TYPE, EnumConstants.OpenApiEnumType.PARAMETER_INLINE); - - // Resolve - codegenParameter.vendorExtensions.put(X_VARIABLE_NAME, StringUtils.toCamelCase(codegenParameter.baseName)); - codegenParameter.vendorExtensions.put(X_DATATYPE, - ResourceCache.getResourceName() + DOT + StringUtils.toPascalCase(codegenParameter.baseName)); - return true; - } - return false; - } - - /* - isEnum = false - isEnumRef = true - schema.isEnum = false - ref = null - isContainer = false - items = null - - - - .schema._enum = null - .schema.items = null - .schema.ref = it gives ref to the enum - */ - private boolean isParameterRef(CodegenParameter codegenParameter) { - if (codegenParameter.getSchema().getRef() != null && codegenParameter.isEnumRef) { - // Identify - System.out.println("Identified as single parameter enum ref: " + codegenParameter.baseName); - codegenParameter.vendorExtensions.put(X_ENUM_TYPE, EnumConstants.OpenApiEnumType.PARAMETER_REF); - - /* Resolve - X_NAME_NAME: variable name - - */ - codegenParameter.vendorExtensions.put(X_VARIABLE_NAME, StringUtils.toCamelCase(codegenParameter.baseName)); - String enumRefResolved = Utility.getEnumNameFromRef(codegenParameter.getSchema().getRef()); - codegenParameter.vendorExtensions.put(X_DATATYPE, - ResourceCache.getResourceName() + DOT + StringUtils.toPascalCase(enumRefResolved)); - return true; - } - return false; - } - - /* - .isEnum = true - .isEnumRef = false - .schema.isEnum = true - .ref = null - .isContainer = true - .items = not null - .schema.ref = null - .schema.items.ref = it gives ref to the item - - .schema._enum = null - .schema.items._enum = enum array values - */ - private boolean isParameterArray(CodegenParameter codegenParameter) { - if (codegenParameter.getSchema()._enum == null && - codegenParameter.getSchema().items != null && codegenParameter.getSchema().items._enum != null) { - // Identify - System.out.println("Identified as array parameter enum: " + codegenParameter.baseName); - codegenParameter.vendorExtensions.put(X_ENUM_TYPE, EnumConstants.OpenApiEnumType.PARAMETER_LIST_INLINE); - - - // Resolve - codegenParameter.vendorExtensions.put(X_VARIABLE_NAME, StringUtils.toCamelCase(codegenParameter.baseName)); - - String enumClassName = StringUtils.toPascalCase(codegenParameter.baseName); - String enumNonContainerDatatype = ResourceCache.getResourceName() + DOT + StringUtils.toPascalCase(enumClassName); - String resolvedDataType = Utility.replaceDatatypeInContainer(codegenParameter.dataType, enumNonContainerDatatype); - codegenParameter.vendorExtensions.put(X_DATATYPE, resolvedDataType); - - return true; - } - return false; - } - - /* - isEnum = false - isEnumRef = false - schema.isEnum = false - ref = null - isContainer = true - items = not null - - - .schema._enum = null - .schema.items._enum = null - .schema.items.ref = it gives ref to the item - - */ - private boolean isParameterArrayRef(CodegenParameter codegenParameter) { - if (codegenParameter.getSchema().items != null && codegenParameter.getSchema().items.getRef() != null - && codegenParameter.getSchema().items.isEnumRef) { - System.out.println("Identified as array parameter enum ref: " + codegenParameter.baseName); - codegenParameter.vendorExtensions.put(X_ENUM_TYPE, EnumConstants.OpenApiEnumType.PARAMETER_LIST_REF); - - // Resolve - codegenParameter.vendorExtensions.put(X_VARIABLE_NAME, StringUtils.toCamelCase(codegenParameter.baseName)); - // #/components/schemas/singleReusable or #/components/schemas/content_enum_single_reusable - // enumRefResolved = singleReusable - String enumRefResolved = Utility.getEnumNameFromRef(codegenParameter.getSchema().items.getRef()); - // enumNonContainerDatatype = Content.SingleReusable - String enumNonContainerDatatype = ResourceCache.getResourceName() + DOT + StringUtils.toPascalCase(enumRefResolved); - // resolvedDataType = List - String resolvedDataType = Utility.replaceDatatypeInContainer(codegenParameter.dataType, enumNonContainerDatatype); - codegenParameter.vendorExtensions.put(X_DATATYPE, resolvedDataType); - - return true; - } - return false; - } - - /* - isEnum = true - isEnumRef = true - */ - private boolean isUrlEncodedBodySingle(CodegenParameter codegenParameter) { - if (codegenParameter._enum != null && codegenParameter.isEnum && !codegenParameter.isContainer) { - System.out.println("Identified as single url encoded body enum: " + codegenParameter.baseName); - codegenParameter.vendorExtensions.put(X_ENUM_TYPE, EnumConstants.OpenApiEnumType.FORM_PARAM_INLINE); - - // Resolve - codegenParameter.vendorExtensions.put(X_VARIABLE_NAME, StringUtils.toCamelCase(codegenParameter.baseName)); - codegenParameter.vendorExtensions.put(X_DATATYPE, - ResourceCache.getResourceName() + DOT + StringUtils.toPascalCase(codegenParameter.baseName)); - return true; - } - return false; - } - - private boolean isUrlEncodedBodyRef(CodegenParameter codegenParameter) { - if (!codegenParameter.isEnum && codegenParameter.isEnumRef) { - codegenParameter.vendorExtensions.put(X_ENUM_TYPE, EnumConstants.OpenApiEnumType.FORM_PARAM_REF); - codegenParameter.vendorExtensions.put(X_VARIABLE_NAME, StringUtils.toCamelCase(codegenParameter.baseName)); - String enumDatatypeResolved = Utility.getEnumNameFromDefaultDatatype(codegenParameter.dataType); - codegenParameter.vendorExtensions.put(X_DATATYPE, ResourceCache.getResourceName() + DOT + enumDatatypeResolved); - return true; - } - return false; - } - - - private boolean isUrlEncodedBodyArray(CodegenParameter codegenParameter) { - if (codegenParameter.items != null && codegenParameter.items._enum != null && codegenParameter.isEnum) { - System.out.println("Identified as single url encoded body enum: " + codegenParameter.baseName); - codegenParameter.vendorExtensions.put(X_ENUM_TYPE, EnumConstants.OpenApiEnumType.FORM_PARAM_INLINE); - - // Resolve - codegenParameter.vendorExtensions.put(X_VARIABLE_NAME, StringUtils.toCamelCase(codegenParameter.baseName)); - - // codegenParameter.dataType = List - // enumExistingDatatype = String - String enumExistingDatatype = Utility.extractDatatypeFromContainer(codegenParameter.dataType); - String enumClassName = StringUtils.toPascalCase(codegenParameter.baseName); - String enumNonContainerDatatype = ResourceCache.getResourceName() + DOT + StringUtils.toPascalCase(enumClassName); - String resolvedDataType = Utility.replaceDatatypeInContainer(codegenParameter.dataType, enumNonContainerDatatype); - codegenParameter.vendorExtensions.put(X_DATATYPE, resolvedDataType); - return true; - } - return false; - } - - private boolean isUrlEncodedBodyArrayRef(CodegenParameter codegenParameter) { - if (codegenParameter.items != null && codegenParameter.items.isEnumRef && !codegenParameter.items.isEnum) { - codegenParameter.vendorExtensions.put(X_ENUM_TYPE, EnumConstants.OpenApiEnumType.FORM_PARAM_LIST_REF); - - codegenParameter.vendorExtensions.put(X_VARIABLE_NAME, StringUtils.toCamelCase(codegenParameter.baseName)); - // codegenParameter.dataType = List - // enumExistingDatatype = AccountEnumStatus - String enumExistingDatatype = Utility.extractDatatypeFromContainer(codegenParameter.dataType); - // enumClassName = Status - String enumClassName = Utility.getEnumNameFromDatatype(enumExistingDatatype); - // enumNonContainerDatatype = Account.Status - String enumNonContainerDatatype = ResourceCache.getResourceName() + DOT + StringUtils.toPascalCase(enumClassName); - // resolvedDataType = List - String resolvedDataType = Utility.replaceDatatypeInContainer(codegenParameter.dataType, enumNonContainerDatatype); - codegenParameter.vendorExtensions.put(X_DATATYPE, resolvedDataType); - return true; - } - return false; - } - /* - - */ - private boolean isPropertySingle(CodegenProperty codegenProperty) { - return false; - } - /* - - */ - private boolean isReusableSingle(CodegenProperty codegenProperty) { - return false; - } - /* - - */ - private void isReusableArray(CodegenProperty codegenProperty) { - - } -} diff --git a/src/main/java/com/twilio/oai/java/strategy/enums/parameter/FormParamInlineStrategy.java b/src/main/java/com/twilio/oai/java/strategy/enums/parameter/FormParamInlineStrategy.java deleted file mode 100644 index fc6820d4a..000000000 --- a/src/main/java/com/twilio/oai/java/strategy/enums/parameter/FormParamInlineStrategy.java +++ /dev/null @@ -1,80 +0,0 @@ -package com.twilio.oai.java.strategy.enums.parameter; - -import com.twilio.oai.common.EnumConstants; -import com.twilio.oai.common.EnumConstants.OpenApiEnumType; -import com.twilio.oai.common.StringUtils; -import com.twilio.oai.java.nestedmodels.MustacheEnum; -import com.twilio.oai.modern.ResourceCache; -import org.openapitools.codegen.CodegenParameter; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - -import static com.twilio.oai.common.ApplicationConstants.DOT; -import static com.twilio.oai.common.ApplicationConstants.X_DATATYPE; -import static com.twilio.oai.common.ApplicationConstants.X_VARIABLE_NAME; -import static com.twilio.oai.common.ApplicationConstants.X_ENUM_TYPE; - -/* - application/x-www-form-urlencoded: - schema: - type: object - properties: - # PROPERTY_SINGLE - singleBody: - type: string - enum: - - available - - pending - - sold - */ -public class FormParamInlineStrategy implements ParameterEnumProcessingStrategy { - - private final OpenApiEnumType type = OpenApiEnumType.FORM_PARAM_INLINE; - - @Override - public boolean process(final CodegenParameter codegenParameter) { - if (codegenParameter.getSchema() != null) return false; - if (codegenParameter._enum != null && codegenParameter.isEnum && !codegenParameter.isContainer) { - type(codegenParameter); - variableName(codegenParameter); - datatype(codegenParameter); - cacheEnumClass(codegenParameter); - return true; - } - return false; - } - - @Override - public OpenApiEnumType getType() { - return type; - } - - @Override - public boolean isStrategyApplicable(CodegenParameter codegenParameter) { - if (codegenParameter.getSchema() != null) return false; - if (codegenParameter._enum != null && codegenParameter.isEnum && !codegenParameter.isContainer) { - return true; - } - return false; - } - - private void type(CodegenParameter codegenParameter) { - codegenParameter.vendorExtensions.put(X_ENUM_TYPE, EnumConstants.OpenApiEnumType.FORM_PARAM_INLINE); - } - private void variableName(CodegenParameter codegenParameter) { - codegenParameter.vendorExtensions.put(X_VARIABLE_NAME, StringUtils.toCamelCase(codegenParameter.baseName)); - } - private void datatype(CodegenParameter codegenParameter) { - codegenParameter.vendorExtensions.put(X_DATATYPE, - ResourceCache.getResourceName() + DOT + StringUtils.toPascalCase(codegenParameter.baseName)); - } - - private void cacheEnumClass(CodegenParameter codegenParameter) { - List> enumValues = (List>) codegenParameter.allowableValues.get("enumVars"); - - MustacheEnum mustacheEnum = new MustacheEnum(StringUtils.toPascalCase(codegenParameter.baseName), enumValues); - ResourceCache.addToEnumClasses(mustacheEnum); - } -} diff --git a/src/main/java/com/twilio/oai/java/strategy/enums/parameter/FormParamListRefStrategy.java b/src/main/java/com/twilio/oai/java/strategy/enums/parameter/FormParamListRefStrategy.java deleted file mode 100644 index ebfeadbc5..000000000 --- a/src/main/java/com/twilio/oai/java/strategy/enums/parameter/FormParamListRefStrategy.java +++ /dev/null @@ -1,111 +0,0 @@ -package com.twilio.oai.java.strategy.enums.parameter; - -import com.twilio.oai.common.EnumConstants; -import com.twilio.oai.common.EnumConstants.OpenApiEnumType; -import com.twilio.oai.common.StringUtils; -import com.twilio.oai.common.Utility; -import com.twilio.oai.java.nestedmodels.MustacheEnum; -import com.twilio.oai.modern.ResourceCache; -import org.openapitools.codegen.CodegenModel; -import org.openapitools.codegen.CodegenParameter; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - -import static com.twilio.oai.common.ApplicationConstants.DOT; -import static com.twilio.oai.common.ApplicationConstants.X_DATATYPE; -import static com.twilio.oai.common.ApplicationConstants.X_VARIABLE_NAME; -import static com.twilio.oai.common.ApplicationConstants.X_ENUM_TYPE; - -/* - application/x-www-form-urlencoded: - schema: - type: object - properties: - # REUSABLE_ARRAY - singleBodyRefArray: - type: array - items: - $ref: '#/components/schemas/singleReusable' - description: An array of reusable enum in the request body - example: [ electronics, clothing ] - */ -public class FormParamListRefStrategy implements ParameterEnumProcessingStrategy { - - private final OpenApiEnumType type = OpenApiEnumType.FORM_PARAM_LIST_REF; - - @Override - public boolean process(final CodegenParameter codegenParameter) { - if (codegenParameter.getSchema() != null) return false; - if (codegenParameter.items != null && codegenParameter.items.isEnumRef && !codegenParameter.items.isEnum) { - type(codegenParameter); - variableName(codegenParameter); - datatype(codegenParameter); - cacheEnumClass(codegenParameter); - return true; - } - return false; - } - - @Override - public OpenApiEnumType getType() { - return type; - } - - @Override - public boolean isStrategyApplicable(CodegenParameter codegenParameter) { - if (codegenParameter.getSchema() != null) return false; - if (codegenParameter.items != null && codegenParameter.items.isEnumRef && !codegenParameter.items.isEnum) { - return true; - } - return false; - } - - private void type(CodegenParameter codegenParameter) { - codegenParameter.vendorExtensions.put(X_ENUM_TYPE, EnumConstants.OpenApiEnumType.FORM_PARAM_LIST_REF); - } - private void variableName(CodegenParameter codegenParameter) { - codegenParameter.vendorExtensions.put(X_VARIABLE_NAME, StringUtils.toCamelCase(codegenParameter.baseName)); - } - private void datatype(CodegenParameter codegenParameter) { - // codegenParameter.dataType = List - // enumExistingDatatype = AccountEnumStatus - String enumExistingDatatype = Utility.extractDatatypeFromContainer(codegenParameter.dataType); - // enumClassName = Status - String enumClassName = Utility.getEnumNameFromDatatype(enumExistingDatatype); - // enumNonContainerDatatype = Account.Status - String enumNonContainerDatatype = ResourceCache.getResourceName() + DOT + StringUtils.toPascalCase(enumClassName); - // resolvedDataType = List - String resolvedDataType = Utility.replaceDatatypeInContainer(codegenParameter.dataType, enumNonContainerDatatype); - codegenParameter.vendorExtensions.put(X_DATATYPE, resolvedDataType); - } - - private void cacheEnumClass(CodegenParameter codegenParameter) { - String baseDataType = Utility.extractDatatypeFromContainer(codegenParameter.dataType); - if (baseDataType == null) { - throw new RuntimeException("Not able to fetch enum baseType for List Enum with ref" + " DataType: " +codegenParameter.dataType); - } - String enumClassName = Utility.getEnumNameFromDatatype(baseDataType); - if (enumClassName == null) { - throw new RuntimeException("Not able to fetch enum class name from baseDataType for List Enum with ref" - + "baseType:"+ baseDataType + " DataType: " + codegenParameter.dataType); - } - - Map values = null; - List> enumValues = new ArrayList<>(); - - for (CodegenModel codegenModel: ResourceCache.getAllModelsByDefaultGenerator()) { - if (baseDataType.equals(codegenModel.classname)) { - values = codegenModel.allowableValues; - enumValues = (List>) codegenModel.allowableValues.get("enumVars"); - break; - } - } - if (enumValues == null || enumValues.isEmpty()) { - throw new RuntimeException("No enum values found for Enum" + " DataType: " +codegenParameter.dataType); - } - MustacheEnum mustacheEnum = new MustacheEnum(enumClassName, enumValues); - ResourceCache.addToEnumClasses(mustacheEnum); - } -} diff --git a/src/main/java/com/twilio/oai/java/strategy/enums/parameter/FormParamListStrategy.java b/src/main/java/com/twilio/oai/java/strategy/enums/parameter/FormParamListStrategy.java deleted file mode 100644 index c952f2abf..000000000 --- a/src/main/java/com/twilio/oai/java/strategy/enums/parameter/FormParamListStrategy.java +++ /dev/null @@ -1,88 +0,0 @@ -package com.twilio.oai.java.strategy.enums.parameter; - -import com.twilio.oai.common.EnumConstants; -import com.twilio.oai.common.EnumConstants.OpenApiEnumType; -import com.twilio.oai.common.StringUtils; -import com.twilio.oai.common.Utility; -import com.twilio.oai.java.nestedmodels.MustacheEnum; -import com.twilio.oai.modern.ResourceCache; -import org.openapitools.codegen.CodegenParameter; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - -import static com.twilio.oai.common.ApplicationConstants.DOT; -import static com.twilio.oai.common.ApplicationConstants.X_DATATYPE; -import static com.twilio.oai.common.ApplicationConstants.X_VARIABLE_NAME; -import static com.twilio.oai.common.ApplicationConstants.X_ENUM_TYPE; - -/* - application/x-www-form-urlencoded: - schema: - type: object - properties: - # PROPERTY_ARRAY - singleBodyArray: - type: array - items: - type: string - enum: [ new, sale, featured ] - description: An array of enum values in the request body - example: [ new, featured ] - */ -public class FormParamListStrategy implements ParameterEnumProcessingStrategy { - - private final OpenApiEnumType type = OpenApiEnumType.FORM_PARAM_LIST_INLINE; - - @Override - public boolean process(final CodegenParameter codegenParameter) { - if (codegenParameter.getSchema() != null) return false; - if (codegenParameter.items != null && codegenParameter.items._enum != null && codegenParameter.isEnum) { - type(codegenParameter); - variableName(codegenParameter); - datatype(codegenParameter); - cacheEnumClass(codegenParameter); - return true; - } - return false; - } - - @Override - public OpenApiEnumType getType() { - return type; - } - - @Override - public boolean isStrategyApplicable(CodegenParameter codegenParameter) { - if (codegenParameter.getSchema() != null) return false; - if (codegenParameter.items != null && codegenParameter.items._enum != null && codegenParameter.isEnum) { - return true; - } - return false; - } - - private void type(CodegenParameter codegenParameter) { - codegenParameter.vendorExtensions.put(X_ENUM_TYPE, EnumConstants.OpenApiEnumType.FORM_PARAM_INLINE); - } - private void variableName(CodegenParameter codegenParameter) { - codegenParameter.vendorExtensions.put(X_VARIABLE_NAME, StringUtils.toCamelCase(codegenParameter.baseName)); - } - private void datatype(CodegenParameter codegenParameter) { - // codegenParameter.dataType = List - // enumExistingDatatype = String - String enumExistingDatatype = Utility.extractDatatypeFromContainer(codegenParameter.dataType); - String enumClassName = StringUtils.toPascalCase(codegenParameter.baseName); - String enumNonContainerDatatype = ResourceCache.getResourceName() + DOT + enumClassName; - String resolvedDataType = Utility.replaceDatatypeInContainer(codegenParameter.dataType, enumNonContainerDatatype); - codegenParameter.vendorExtensions.put(X_DATATYPE, resolvedDataType); - } - - private void cacheEnumClass(CodegenParameter codegenParameter) { - String enumClassName = StringUtils.toPascalCase(codegenParameter.baseName); - List> enumValues = (List>) codegenParameter.allowableValues.get("enumVars"); - - MustacheEnum mustacheEnum = new MustacheEnum(enumClassName, enumValues); - ResourceCache.addToEnumClasses(mustacheEnum); - } -} diff --git a/src/main/java/com/twilio/oai/java/strategy/enums/parameter/FormParamRefStrategy.java b/src/main/java/com/twilio/oai/java/strategy/enums/parameter/FormParamRefStrategy.java deleted file mode 100644 index 9a2b98786..000000000 --- a/src/main/java/com/twilio/oai/java/strategy/enums/parameter/FormParamRefStrategy.java +++ /dev/null @@ -1,80 +0,0 @@ -package com.twilio.oai.java.strategy.enums.parameter; - -import com.twilio.oai.common.EnumConstants; -import com.twilio.oai.common.EnumConstants.OpenApiEnumType; -import com.twilio.oai.common.StringUtils; -import com.twilio.oai.common.Utility; -import com.twilio.oai.java.nestedmodels.MustacheEnum; -import com.twilio.oai.modern.ResourceCache; -import org.openapitools.codegen.CodegenParameter; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - -import static com.twilio.oai.common.ApplicationConstants.DOT; -import static com.twilio.oai.common.ApplicationConstants.X_DATATYPE; -import static com.twilio.oai.common.ApplicationConstants.X_VARIABLE_NAME; -import static com.twilio.oai.common.ApplicationConstants.X_ENUM_TYPE; - -/* - application/x-www-form-urlencoded: - schema: - type: object - properties: - # REUSABLE_SINGLE - singleBodyRef: - $ref: '#/components/schemas/singleReusable' - description: A reusable single-value enum in the request body - */ -public class FormParamRefStrategy implements ParameterEnumProcessingStrategy { - - private final OpenApiEnumType type = OpenApiEnumType.FORM_PARAM_REF; - - @Override - public boolean process(final CodegenParameter codegenParameter) { - if (codegenParameter.getSchema() != null) return false; - if (!codegenParameter.isEnum && codegenParameter.isEnumRef) { - type(codegenParameter); - variableName(codegenParameter); - datatype(codegenParameter); - cacheEnumClass(codegenParameter); - return true; - } - return false; - } - - @Override - public OpenApiEnumType getType() { - return type; - } - - @Override - public boolean isStrategyApplicable(CodegenParameter codegenParameter) { - if (codegenParameter.getSchema() != null) return false; - if (!codegenParameter.isEnum && codegenParameter.isEnumRef) { - return true; - } - return false; - } - - private void type(CodegenParameter codegenParameter) { - codegenParameter.vendorExtensions.put(X_ENUM_TYPE, EnumConstants.OpenApiEnumType.FORM_PARAM_REF); - } - private void variableName(CodegenParameter codegenParameter) { - codegenParameter.vendorExtensions.put(X_VARIABLE_NAME, StringUtils.toCamelCase(codegenParameter.baseName)); - } - private void datatype(CodegenParameter codegenParameter) { - String enumDatatypeResolved = StringUtils.toPascalCase(Utility.getEnumNameFromDefaultDatatype(codegenParameter.dataType)); - codegenParameter.vendorExtensions.put(X_DATATYPE, ResourceCache.getResourceName() + DOT + enumDatatypeResolved); - } - - private void cacheEnumClass(CodegenParameter codegenParameter) { - // TODO: Best way to store = codegenParameter.allowableValues.get("enumVars") - String enumClassName = StringUtils.toPascalCase(Utility.getEnumNameFromDefaultDatatype(codegenParameter.dataType)); - List> enumValues = (List>) codegenParameter.allowableValues.get("enumVars"); - - MustacheEnum mustacheEnum = new MustacheEnum(enumClassName, enumValues); - ResourceCache.addToEnumClasses(mustacheEnum); - } -} diff --git a/src/main/java/com/twilio/oai/java/strategy/enums/parameter/InlineListParamStrategy.java b/src/main/java/com/twilio/oai/java/strategy/enums/parameter/InlineListParamStrategy.java deleted file mode 100644 index d9f59c655..000000000 --- a/src/main/java/com/twilio/oai/java/strategy/enums/parameter/InlineListParamStrategy.java +++ /dev/null @@ -1,87 +0,0 @@ -package com.twilio.oai.java.strategy.enums.parameter; - -import com.twilio.oai.common.EnumConstants; -import com.twilio.oai.common.EnumConstants.OpenApiEnumType; -import com.twilio.oai.common.StringUtils; -import com.twilio.oai.common.Utility; -import com.twilio.oai.java.nestedmodels.MustacheEnum; -import com.twilio.oai.modern.ResourceCache; -import org.openapitools.codegen.CodegenParameter; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - -import static com.twilio.oai.common.ApplicationConstants.DOT; -import static com.twilio.oai.common.ApplicationConstants.X_DATATYPE; -import static com.twilio.oai.common.ApplicationConstants.X_VARIABLE_NAME; -import static com.twilio.oai.common.ApplicationConstants.X_ENUM_TYPE; - -/* - Example: - - name: arrayParam - in: query - description: Order items using an array of enums - required: false - schema: - type: array - items: - type: string - enum: - - asc - - desc - example: [asc] - */ -public class InlineListParamStrategy implements ParameterEnumProcessingStrategy { - - private final OpenApiEnumType type = OpenApiEnumType.PARAMETER_LIST_INLINE; - - @Override - public boolean process(final CodegenParameter codegenParameter) { - if (codegenParameter.getSchema() == null) return false; - if (codegenParameter.getSchema()._enum == null && - codegenParameter.getSchema().items != null && codegenParameter.getSchema().items._enum != null) { - type(codegenParameter); - variableName(codegenParameter); - datatype(codegenParameter); - cacheEnumClass(codegenParameter); - return true; - } - return false; - } - - @Override - public OpenApiEnumType getType() { - return type; - } - - @Override - public boolean isStrategyApplicable(CodegenParameter codegenParameter) { - if (codegenParameter.getSchema() == null) return false; - if (codegenParameter.getSchema()._enum == null && - codegenParameter.getSchema().items != null && codegenParameter.getSchema().items._enum != null) { - return true; - } - return false; - } - - private void type(CodegenParameter codegenParameter) { - codegenParameter.vendorExtensions.put(X_ENUM_TYPE, EnumConstants.OpenApiEnumType.PARAMETER_LIST_INLINE); - } - private void variableName(CodegenParameter codegenParameter) { - codegenParameter.vendorExtensions.put(X_VARIABLE_NAME, StringUtils.toCamelCase(codegenParameter.baseName)); - } - private void datatype(CodegenParameter codegenParameter) { - String enumClassName = StringUtils.toPascalCase(codegenParameter.baseName); - String enumNonContainerDatatype = ResourceCache.getResourceName() + DOT + StringUtils.toPascalCase(enumClassName); - String resolvedDataType = Utility.replaceDatatypeInContainer(codegenParameter.dataType, enumNonContainerDatatype); - codegenParameter.vendorExtensions.put(X_DATATYPE, resolvedDataType); - } - - private void cacheEnumClass(CodegenParameter codegenParameter) { - List> enumValues = (List>) codegenParameter.allowableValues.get("enumVars"); - - MustacheEnum mustacheEnum = new MustacheEnum( StringUtils.toPascalCase(codegenParameter.baseName), enumValues); - ResourceCache.addToEnumClasses(mustacheEnum); - } -} diff --git a/src/main/java/com/twilio/oai/java/strategy/enums/parameter/InlineParamStrategy.java b/src/main/java/com/twilio/oai/java/strategy/enums/parameter/InlineParamStrategy.java deleted file mode 100644 index ad4cf1fb7..000000000 --- a/src/main/java/com/twilio/oai/java/strategy/enums/parameter/InlineParamStrategy.java +++ /dev/null @@ -1,77 +0,0 @@ -package com.twilio.oai.java.strategy.enums.parameter; - -import com.twilio.oai.common.EnumConstants.OpenApiEnumType; -import com.twilio.oai.common.StringUtils; -import com.twilio.oai.java.nestedmodels.MustacheEnum; -import com.twilio.oai.modern.ResourceCache; -import org.openapitools.codegen.CodegenParameter; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - -import static com.twilio.oai.common.ApplicationConstants.DOT; -import static com.twilio.oai.common.ApplicationConstants.X_DATATYPE; -import static com.twilio.oai.common.ApplicationConstants.X_VARIABLE_NAME; -import static com.twilio.oai.common.ApplicationConstants.X_ENUM_TYPE; - -/* - - name: singleParam - in: query - description: A single enum value as a query parameter - required: false - schema: - type: string - enum: - - asc - - desc - example: asc - */ -public class InlineParamStrategy implements ParameterEnumProcessingStrategy { - - private final OpenApiEnumType type = OpenApiEnumType.PARAMETER_INLINE; - - @Override - public boolean process(final CodegenParameter codegenParameter) { - if (codegenParameter.getSchema() == null) return false; - if (codegenParameter.getSchema()._enum != null && codegenParameter.isEnum) { - type(codegenParameter); - variableName(codegenParameter); - datatype(codegenParameter); - cacheEnumClass(codegenParameter); - return true; - } - return false; - } - - @Override - public OpenApiEnumType getType() { - return type; - } - - @Override - public boolean isStrategyApplicable(CodegenParameter codegenParameter) { - if (codegenParameter.getSchema() == null) return false; - if (codegenParameter.getSchema()._enum != null && codegenParameter.isEnum) { - return true; - } - return false; - } - - private void type(CodegenParameter codegenParameter) { - codegenParameter.vendorExtensions.put(X_ENUM_TYPE, type); - } - private void variableName(CodegenParameter codegenParameter) { - codegenParameter.vendorExtensions.put(X_VARIABLE_NAME, StringUtils.toCamelCase(codegenParameter.baseName)); - } - private void datatype(CodegenParameter codegenParameter) { - codegenParameter.vendorExtensions.put(X_DATATYPE, - ResourceCache.getResourceName() + DOT + StringUtils.toPascalCase(codegenParameter.baseName)); - } - - private void cacheEnumClass(CodegenParameter codegenParameter) { - List> enumValues = (List>) codegenParameter.allowableValues.get("enumVars"); - MustacheEnum mustacheEnum = new MustacheEnum(StringUtils.toPascalCase(codegenParameter.baseName), enumValues); - ResourceCache.addToEnumClasses(mustacheEnum); - } -} diff --git a/src/main/java/com/twilio/oai/java/strategy/enums/parameter/ParameterEnumProcessingStrategy.java b/src/main/java/com/twilio/oai/java/strategy/enums/parameter/ParameterEnumProcessingStrategy.java deleted file mode 100644 index bdef8d94b..000000000 --- a/src/main/java/com/twilio/oai/java/strategy/enums/parameter/ParameterEnumProcessingStrategy.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.twilio.oai.java.strategy.enums.parameter; - -import com.twilio.oai.common.EnumConstants.OpenApiEnumType; -import org.openapitools.codegen.CodegenParameter; - -public interface ParameterEnumProcessingStrategy { - boolean process(CodegenParameter codegenParameter); - OpenApiEnumType getType(); - - boolean isStrategyApplicable(CodegenParameter codegenParameter); -} diff --git a/src/main/java/com/twilio/oai/java/strategy/enums/parameter/RefListParamStrategy.java b/src/main/java/com/twilio/oai/java/strategy/enums/parameter/RefListParamStrategy.java deleted file mode 100644 index f5e0f7642..000000000 --- a/src/main/java/com/twilio/oai/java/strategy/enums/parameter/RefListParamStrategy.java +++ /dev/null @@ -1,88 +0,0 @@ -package com.twilio.oai.java.strategy.enums.parameter; - -import com.twilio.oai.common.EnumConstants; -import com.twilio.oai.common.EnumConstants.OpenApiEnumType; -import com.twilio.oai.common.StringUtils; -import com.twilio.oai.common.Utility; -import com.twilio.oai.java.nestedmodels.MustacheEnum; -import com.twilio.oai.modern.ResourceCache; -import org.openapitools.codegen.CodegenParameter; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - -import static com.twilio.oai.common.ApplicationConstants.DOT; -import static com.twilio.oai.common.ApplicationConstants.X_DATATYPE; -import static com.twilio.oai.common.ApplicationConstants.X_VARIABLE_NAME; -import static com.twilio.oai.common.ApplicationConstants.X_ENUM_TYPE; - -/* - - name: arrayParamRef - in: query - required: false - description: An array parameter referencing a reusable schema - schema: - type: array - items: - $ref: '#/components/schemas/singleReusable' - */ -public class RefListParamStrategy implements ParameterEnumProcessingStrategy { - - private final OpenApiEnumType type = OpenApiEnumType.PARAMETER_LIST_REF; - - @Override - public boolean process(final CodegenParameter codegenParameter) { - if (codegenParameter.getSchema() == null) return false; - if (codegenParameter.getSchema().items != null && codegenParameter.getSchema().items.getRef() != null - && codegenParameter.getSchema().items.isEnumRef) { - - type(codegenParameter); - variableName(codegenParameter); - datatype(codegenParameter); - cacheEnumClass(codegenParameter); - return true; - } - return false; - } - - @Override - public OpenApiEnumType getType() { - return type; - } - - @Override - public boolean isStrategyApplicable(CodegenParameter codegenParameter) { - if (codegenParameter.getSchema() == null) return false; - if (codegenParameter.getSchema().items != null && codegenParameter.getSchema().items.getRef() != null - && codegenParameter.getSchema().items.isEnumRef) { - return true; - } - return false; - } - - private void type(CodegenParameter codegenParameter) { - codegenParameter.vendorExtensions.put(X_ENUM_TYPE, EnumConstants.OpenApiEnumType.PARAMETER_LIST_REF); - } - private void variableName(CodegenParameter codegenParameter) { - codegenParameter.vendorExtensions.put(X_VARIABLE_NAME, StringUtils.toCamelCase(codegenParameter.baseName)); - } - private void datatype(CodegenParameter codegenParameter) { - // #/components/schemas/singleReusable or #/components/schemas/content_enum_single_reusable - // enumRefResolved = singleReusable - String enumRefResolved = Utility.getEnumNameFromRef(codegenParameter.getSchema().items.getRef()); - // enumNonContainerDatatype = Content.SingleReusable - String enumNonContainerDatatype = ResourceCache.getResourceName() + DOT + StringUtils.toPascalCase(enumRefResolved); - // resolvedDataType = List - String resolvedDataType = Utility.replaceDatatypeInContainer(codegenParameter.dataType, enumNonContainerDatatype); - codegenParameter.vendorExtensions.put(X_DATATYPE, resolvedDataType); - } - - private void cacheEnumClass(CodegenParameter codegenParameter) { - List> enumValues = (List>) codegenParameter.getSchema().items.allowableValues.get("enumVars"); - - MustacheEnum mustacheEnum = new MustacheEnum(StringUtils.toPascalCase( - Utility.getEnumNameFromRef(codegenParameter.getSchema().items.getRef())), enumValues); - ResourceCache.addToEnumClasses(mustacheEnum); - } -} diff --git a/src/main/java/com/twilio/oai/java/strategy/enums/parameter/RefParamStrategy.java b/src/main/java/com/twilio/oai/java/strategy/enums/parameter/RefParamStrategy.java deleted file mode 100644 index 32dab90eb..000000000 --- a/src/main/java/com/twilio/oai/java/strategy/enums/parameter/RefParamStrategy.java +++ /dev/null @@ -1,74 +0,0 @@ -package com.twilio.oai.java.strategy.enums.parameter; - -import com.twilio.oai.common.EnumConstants; -import com.twilio.oai.common.EnumConstants.OpenApiEnumType; -import com.twilio.oai.common.StringUtils; -import com.twilio.oai.common.Utility; -import com.twilio.oai.java.nestedmodels.MustacheEnum; -import com.twilio.oai.modern.ResourceCache; -import org.openapitools.codegen.CodegenParameter; - -import java.util.List; -import java.util.Map; - -import static com.twilio.oai.common.ApplicationConstants.DOT; -import static com.twilio.oai.common.ApplicationConstants.X_DATATYPE; -import static com.twilio.oai.common.ApplicationConstants.X_VARIABLE_NAME; -import static com.twilio.oai.common.ApplicationConstants.X_ENUM_TYPE; - -/* - - name: singleParamRef - in: header - schema: - $ref: '#/components/schemas/singleReusable' - */ -public class RefParamStrategy implements ParameterEnumProcessingStrategy { - - private final OpenApiEnumType type = OpenApiEnumType.PARAMETER_REF; - - @Override - public boolean process(final CodegenParameter codegenParameter) { - if (codegenParameter.getSchema() == null) return false; - if (codegenParameter.getSchema().getRef() != null && codegenParameter.isEnumRef) { - type(codegenParameter); - variableName(codegenParameter); - datatype(codegenParameter); - cacheEnumClass(codegenParameter); - return true; - } - return false; - } - - @Override - public OpenApiEnumType getType() { - return type; - } - - @Override - public boolean isStrategyApplicable(CodegenParameter codegenParameter) { - if (codegenParameter.getSchema() == null) return false; - if (codegenParameter.getSchema().getRef() != null && codegenParameter.isEnumRef) { - return true; - } - return false; - } - - private void type(CodegenParameter codegenParameter) { - codegenParameter.vendorExtensions.put(X_ENUM_TYPE, EnumConstants.OpenApiEnumType.PARAMETER_REF); - } - private void variableName(CodegenParameter codegenParameter) { - codegenParameter.vendorExtensions.put(X_VARIABLE_NAME, StringUtils.toCamelCase(codegenParameter.baseName)); - } - private void datatype(CodegenParameter codegenParameter) { - String enumRefResolved = Utility.getEnumNameFromRef(codegenParameter.getSchema().getRef()); - codegenParameter.vendorExtensions.put(X_DATATYPE, - ResourceCache.getResourceName() + DOT + StringUtils.toPascalCase(enumRefResolved)); - } - - private void cacheEnumClass(CodegenParameter codegenParameter) { - List> enumValues = (List>) codegenParameter.allowableValues.get("enumVars"); - MustacheEnum mustacheEnum = new MustacheEnum(StringUtils.toPascalCase( - Utility.getEnumNameFromRef(codegenParameter.getSchema().getRef())), enumValues); - ResourceCache.addToEnumClasses(mustacheEnum); - } -} diff --git a/src/main/java/com/twilio/oai/java/strategy/enums/property/InlineListPropStrategy.java b/src/main/java/com/twilio/oai/java/strategy/enums/property/InlineListPropStrategy.java deleted file mode 100644 index 2a9344634..000000000 --- a/src/main/java/com/twilio/oai/java/strategy/enums/property/InlineListPropStrategy.java +++ /dev/null @@ -1,66 +0,0 @@ -package com.twilio.oai.java.strategy.enums.property; - -import com.twilio.oai.common.EnumConstants.OpenApiEnumType; -import com.twilio.oai.common.StringUtils; -import com.twilio.oai.common.Utility; -import com.twilio.oai.java.nestedmodels.MustacheEnum; -import com.twilio.oai.modern.ResourceCache; -import org.openapitools.codegen.CodegenParameter; -import org.openapitools.codegen.CodegenProperty; - -import java.util.List; -import java.util.Map; - -import static com.twilio.oai.common.ApplicationConstants.DOT; -import static com.twilio.oai.common.ApplicationConstants.X_VARIABLE_NAME; -import static com.twilio.oai.common.ApplicationConstants.X_DATATYPE; -import static com.twilio.oai.common.ApplicationConstants.X_ENUM_TYPE; - -public class InlineListPropStrategy implements PropertyEnumProcessingStrategy { - private final OpenApiEnumType type = OpenApiEnumType.PROPERTY_LIST; - - @Override - public boolean process(final CodegenProperty codegenProperty) { - if (codegenProperty.isEnum && !codegenProperty.isEnumRef && codegenProperty.items != null && codegenProperty.items.get_enum() != null) { - type(codegenProperty); - variableName(codegenProperty); - datatype(codegenProperty); - cacheEnumClass(codegenProperty); - return true; - } - // Check if the parameter is a single enum type - return false; - } - - @Override - public OpenApiEnumType getType() { - // Return the type of enum this strategy identifies - return type; - } - - private void type(CodegenProperty codegenProperty) { - codegenProperty.vendorExtensions.put(X_ENUM_TYPE, type); - } - private void variableName(CodegenProperty codegenProperty) { - codegenProperty.vendorExtensions.put(X_VARIABLE_NAME, StringUtils.toCamelCase(codegenProperty.baseName)); - } - private void datatype(CodegenProperty codegenProperty) { - String enumClassName = StringUtils.toPascalCase(codegenProperty.baseName); - String enumNonContainerDatatype = ResourceCache.getResourceName() + DOT + StringUtils.toPascalCase(enumClassName); - String resolvedDataType = Utility.replaceDatatypeInContainer(codegenProperty.dataType, enumNonContainerDatatype); - codegenProperty.vendorExtensions.put(X_DATATYPE, resolvedDataType); - } - - public boolean isStrategyApplicable(CodegenProperty codegenProperty) { - if (codegenProperty.isEnum && !codegenProperty.isEnumRef && codegenProperty.items != null && codegenProperty.items.get_enum() != null) { - return true; - } - return false; - } - - private void cacheEnumClass(CodegenProperty codegenProperty) { - List> enumValues = (List>) codegenProperty.allowableValues.get("enumVars"); - MustacheEnum mustacheEnum = new MustacheEnum(StringUtils.toPascalCase(codegenProperty.baseName), enumValues); - ResourceCache.addToEnumClasses(mustacheEnum); - } -} diff --git a/src/main/java/com/twilio/oai/java/strategy/enums/property/InlinePropStrategy.java b/src/main/java/com/twilio/oai/java/strategy/enums/property/InlinePropStrategy.java deleted file mode 100644 index 5d0e66348..000000000 --- a/src/main/java/com/twilio/oai/java/strategy/enums/property/InlinePropStrategy.java +++ /dev/null @@ -1,75 +0,0 @@ -package com.twilio.oai.java.strategy.enums.property; - -import static com.twilio.oai.common.ApplicationConstants.DOT; -import static com.twilio.oai.common.ApplicationConstants.X_VARIABLE_NAME; -import static com.twilio.oai.common.ApplicationConstants.X_DATATYPE; -import static com.twilio.oai.common.ApplicationConstants.X_ENUM_TYPE; - -import com.twilio.oai.StringHelper; -import com.twilio.oai.common.EnumConstants.OpenApiEnumType; -import com.twilio.oai.common.StringUtils; -import com.twilio.oai.java.nestedmodels.MustacheEnum; -import com.twilio.oai.modern.ResourceCache; -import org.openapitools.codegen.CodegenProperty; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/* -codegenProperty._enum = true -codegenProperty.isEnum = true -codegenProperty.isEnumRef = true - */ -public class InlinePropStrategy implements PropertyEnumProcessingStrategy { - private final OpenApiEnumType type = OpenApiEnumType.PROPERTY_INLINE; - @Override - public boolean process(final CodegenProperty codegenProperty) { - if (codegenProperty.isEnum && codegenProperty.isEnumRef && codegenProperty.get_enum() != null) { - type(codegenProperty); - variableName(codegenProperty); - datatype(codegenProperty); - cacheEnumClass(codegenProperty); - return true; - } - return false; - } - - @Override - public OpenApiEnumType getType() { - return type; - } - - @Override - public boolean isStrategyApplicable(CodegenProperty codegenProperty) { - if (codegenProperty.isEnum && codegenProperty.isEnumRef && codegenProperty.get_enum() != null) { - return true; - } - return false; - } - - private void type(CodegenProperty codegenProperty) { - codegenProperty.vendorExtensions.put(X_ENUM_TYPE, type); - } - private void variableName(CodegenProperty codegenProperty) { - codegenProperty.vendorExtensions.put(X_VARIABLE_NAME, StringUtils.toCamelCase(codegenProperty.baseName)); - } - private void datatype(CodegenProperty codegenProperty) { - codegenProperty.vendorExtensions.put(X_DATATYPE, - ResourceCache.getResourceName() + DOT + StringUtils.toPascalCase(codegenProperty.baseName)); - } - - private void cacheEnumClass(CodegenProperty codegenProperty) { - List> enumValues = new ArrayList<>(); - - for (String s : (List) codegenProperty.allowableValues.get("values")) { - HashMap valueMap = new HashMap<>(); - valueMap.put("name", StringHelper.toSnakeCase(s).toUpperCase()); - valueMap.put("value", "\"" + s + "\""); // adding extra quote as this is how enumVars are stored - enumValues.add(valueMap); - } - MustacheEnum mustacheEnum = new MustacheEnum(StringUtils.toPascalCase(codegenProperty.baseName), enumValues); - ResourceCache.addToEnumClasses(mustacheEnum); - } -} diff --git a/src/main/java/com/twilio/oai/java/strategy/enums/property/PropertyEnumProcessingStrategy.java b/src/main/java/com/twilio/oai/java/strategy/enums/property/PropertyEnumProcessingStrategy.java deleted file mode 100644 index ad9b78559..000000000 --- a/src/main/java/com/twilio/oai/java/strategy/enums/property/PropertyEnumProcessingStrategy.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.twilio.oai.java.strategy.enums.property; - -import com.twilio.oai.common.EnumConstants; -import org.openapitools.codegen.CodegenProperty; - -public interface PropertyEnumProcessingStrategy { - boolean process(CodegenProperty codegenProperty); - EnumConstants.OpenApiEnumType getType(); - - boolean isStrategyApplicable(CodegenProperty codegenProperty); -} diff --git a/src/main/java/com/twilio/oai/java/strategy/enums/property/RefListPropStrategy.java b/src/main/java/com/twilio/oai/java/strategy/enums/property/RefListPropStrategy.java deleted file mode 100644 index 32acd8186..000000000 --- a/src/main/java/com/twilio/oai/java/strategy/enums/property/RefListPropStrategy.java +++ /dev/null @@ -1,74 +0,0 @@ -package com.twilio.oai.java.strategy.enums.property; - -import com.twilio.oai.common.EnumConstants.OpenApiEnumType; -import com.twilio.oai.common.StringUtils; -import com.twilio.oai.common.Utility; -import com.twilio.oai.java.nestedmodels.MustacheEnum; -import com.twilio.oai.modern.ResourceCache; -import org.checkerframework.checker.units.qual.A; -import org.openapitools.codegen.CodegenProperty; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import static com.twilio.oai.common.ApplicationConstants.X_VARIABLE_NAME; -import static com.twilio.oai.common.ApplicationConstants.X_ENUM_TYPE; -import static com.twilio.oai.common.ApplicationConstants.DOT; -import static com.twilio.oai.common.ApplicationConstants.X_DATATYPE; - -public class RefListPropStrategy implements PropertyEnumProcessingStrategy { - private final OpenApiEnumType type = OpenApiEnumType.PROPERTY_INLINE; - @Override - public boolean process(final CodegenProperty codegenProperty) { - if (codegenProperty.items != null && codegenProperty.items.isEnumRef && !codegenProperty.items.isEnum) { - type(codegenProperty); - variableName(codegenProperty); - datatype(codegenProperty); - cacheEnumClass(codegenProperty); - return true; - } - // Check if the parameter is a single enum type - return false; - } - - @Override - public OpenApiEnumType getType() { - return type; - } - - @Override - public boolean isStrategyApplicable(CodegenProperty codegenProperty) { - if (codegenProperty.items != null && codegenProperty.items.isEnumRef && !codegenProperty.items.isEnum) { - return true; - } - return false; - } - - private void type(CodegenProperty codegenProperty) { - codegenProperty.vendorExtensions.put(X_ENUM_TYPE, type); - } - private void variableName(CodegenProperty codegenProperty) { - codegenProperty.vendorExtensions.put(X_VARIABLE_NAME, StringUtils.toCamelCase(codegenProperty.baseName)); - } - private void datatype(CodegenProperty codegenProperty) { - String enumExistingDatatype = Utility.extractDatatypeFromContainer(codegenProperty.dataType); - // enumClassName = Status - String enumClassName = Utility.getEnumNameFromDatatype(enumExistingDatatype); - // enumNonContainerDatatype = Account.Status - String enumNonContainerDatatype = ResourceCache.getResourceName() + DOT + StringUtils.toPascalCase(enumClassName); - // resolvedDataType = List - String resolvedDataType = Utility.replaceDatatypeInContainer(codegenProperty.dataType, enumNonContainerDatatype); - codegenProperty.vendorExtensions.put(X_DATATYPE, resolvedDataType); - } - - private void cacheEnumClass(CodegenProperty codegenProperty) { - String enumExistingDatatype = Utility.extractDatatypeFromContainer(codegenProperty.dataType); - String enumClassName = Utility.getEnumNameFromDatatype(enumExistingDatatype); - List> enumValues = (List>) codegenProperty.items.allowableValues.get("enumVars"); - - MustacheEnum mustacheEnum = new MustacheEnum(enumClassName, enumValues); - ResourceCache.addToEnumClasses(mustacheEnum); - } -} diff --git a/src/main/java/com/twilio/oai/java/strategy/enums/property/RefPropStrategy.java b/src/main/java/com/twilio/oai/java/strategy/enums/property/RefPropStrategy.java deleted file mode 100644 index 1228eaddc..000000000 --- a/src/main/java/com/twilio/oai/java/strategy/enums/property/RefPropStrategy.java +++ /dev/null @@ -1,72 +0,0 @@ -package com.twilio.oai.java.strategy.enums.property; - -import com.twilio.oai.StringHelper; -import com.twilio.oai.common.EnumConstants.OpenApiEnumType; -import com.twilio.oai.common.StringUtils; -import com.twilio.oai.common.Utility; -import com.twilio.oai.java.nestedmodels.MustacheEnum; -import com.twilio.oai.modern.ResourceCache; -import org.openapitools.codegen.CodegenParameter; -import org.openapitools.codegen.CodegenProperty; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import static com.twilio.oai.common.ApplicationConstants.DOT; -import static com.twilio.oai.common.ApplicationConstants.X_DATATYPE; -import static com.twilio.oai.common.ApplicationConstants.X_VARIABLE_NAME; -import static com.twilio.oai.common.ApplicationConstants.X_ENUM_TYPE; -public class RefPropStrategy implements PropertyEnumProcessingStrategy { - private final OpenApiEnumType type = OpenApiEnumType.PROPERTY_REF; - @Override - public boolean process(final CodegenProperty codegenProperty) { - if (!codegenProperty.isEnum && codegenProperty.isEnumRef && codegenProperty.getRef() != null) { - type(codegenProperty); - variableName(codegenProperty); - datatype(codegenProperty); - cacheEnumClass(codegenProperty); - return true; - } - return false; - } - - @Override - public OpenApiEnumType getType() { - return type; - } - - @Override - public boolean isStrategyApplicable(CodegenProperty codegenProperty) { - if (!codegenProperty.isEnum && codegenProperty.isEnumRef && codegenProperty.getRef() != null) { - return true; - } - return false; - } - - private void type(CodegenProperty codegenProperty) { - codegenProperty.vendorExtensions.put(X_ENUM_TYPE, type); - } - private void variableName(CodegenProperty codegenProperty) { - codegenProperty.vendorExtensions.put(X_VARIABLE_NAME, StringUtils.toCamelCase(codegenProperty.baseName)); - } - private void datatype(CodegenProperty codegenProperty) { - String enumDatatypeResolved = StringUtils.toPascalCase(Utility.getEnumNameFromDefaultDatatype(codegenProperty.getRef())); - codegenProperty.vendorExtensions.put(X_DATATYPE, ResourceCache.getResourceName() + DOT + enumDatatypeResolved); - } - - private void cacheEnumClass(CodegenProperty codegenProperty) { - System.out.println(codegenProperty.baseName); - String enumClassName = Utility.getEnumNameFromRef(codegenProperty.getRef()); - List> enumValues = new ArrayList<>(); - for (String s : (List) codegenProperty.allowableValues.get("values")) { - HashMap valueMap = new HashMap<>(); - valueMap.put("name", StringHelper.toSnakeCase(s).toUpperCase()); - valueMap.put("value", "\"" + s + "\""); // adding extra quote as this is how enumVars are stored - enumValues.add(valueMap); - } - MustacheEnum mustacheEnum = new MustacheEnum(StringUtils.toPascalCase(enumClassName), enumValues); - ResourceCache.addToEnumClasses(mustacheEnum); - } -} diff --git a/src/test/java/com/twilio/oai/TwilioGeneratorTest.java b/src/test/java/com/twilio/oai/TwilioGeneratorTest.java index b77ba704e..2c57dd829 100644 --- a/src/test/java/com/twilio/oai/TwilioGeneratorTest.java +++ b/src/test/java/com/twilio/oai/TwilioGeneratorTest.java @@ -28,7 +28,7 @@ public class TwilioGeneratorTest { @Parameterized.Parameters public static Collection generators() { - return Arrays.asList(Generator.TWILIO_JAVA); + return Arrays.asList(Generator.TWILIO_JAVA_MODERN); } private final Generator generator; @@ -40,7 +40,8 @@ public static void setUp() { @Test public void launchGenerator() { - final String pathname = "examples/spec/twilio_api_v2010.yaml"; + //final String pathname = "examples/spec/twilio_api_v2010.yaml"; + final String pathname = "examples/test_spec/twilio_testenum_v1.yaml"; File filesList[] ; File directoryPath = new File(pathname); if (directoryPath.isDirectory()) { From 117de52f567f281f0777f963f1cdb73648df11b3 Mon Sep 17 00:00:00 2001 From: sbansla <104902068+sbansla@users.noreply.github.com> Date: Wed, 6 Aug 2025 23:36:16 +0530 Subject: [PATCH 13/38] fixed promoter and corrected api class names (#676) --- examples/test_spec/twilio_parameters_v1.yaml | 78 ++++++++++++++++++- examples/test_spec/twilio_testenum_v1.yaml | 1 + .../twilio/oai/java/JavaTemplateUpdater.java | 5 +- .../{ => constants}/MustacheConstants.java | 2 +- .../java/feature/SetterMethodGenerator.java | 10 +-- .../UrlencodedBodyConstructorGenerator.java | 12 +-- .../com/twilio/oai/java/format/Promoter.java | 3 +- .../processor/JavaOperationProcessor.java | 2 + .../parameter/ParameterProcessor.java | 3 + .../requestbody/JsonRequestProcessor.java | 2 +- .../requestbody/UrlEncodedProcessor.java | 2 +- .../common/constructors.mustache | 2 +- .../twilio-java-modern/creator.mustache | 2 +- .../twilio-java-modern/deleter.mustache | 2 +- .../twilio-java-modern/fetcher.mustache | 2 +- .../twilio-java-modern/reader.mustache | 2 +- .../twilio-java-modern/updater.mustache | 2 +- 17 files changed, 106 insertions(+), 26 deletions(-) rename src/main/java/com/twilio/oai/java/{ => constants}/MustacheConstants.java (97%) diff --git a/examples/test_spec/twilio_parameters_v1.yaml b/examples/test_spec/twilio_parameters_v1.yaml index 3bf9e1cd2..77ce3ab33 100644 --- a/examples/test_spec/twilio_parameters_v1.yaml +++ b/examples/test_spec/twilio_parameters_v1.yaml @@ -1,2 +1,78 @@ # This spec tests followings -# 1. All types of parameters(query, header, path) \ No newline at end of file +# 1. All types of parameters(query, header, path) + +info: + contact: + email: support@twilio.com + name: Twilio Support + url: https://support.twilio.com + description: This is the public Twilio REST API. + license: + name: Apache 2.0 + url: https://www.apache.org/licenses/LICENSE-2.0.html + termsOfService: https://www.twilio.com/legal/tos + title: Twilio - PARAMETERS + version: 1.11.0 +openapi: 3.0.1 + +paths: + /v1/parameter/{id}: + servers: + - url: https://testparameter.twilio.com + post: + operationId: CreateParameter + parameters: + - name: id + in: path + required: true + description: The unique identifier for the enum item + schema: + type: string + - name: queryParamDoubleRequired + in: query + description: A single enum value as a query parameter + required: required + schema: + type: string + - name: queryParamBoolean + in: query + description: A single enum value as a query parameter + required: false + schema: + type: boolean + - name: queryParamString + in: query + description: A single enum value as a query parameter + required: false + schema: + type: string + - name: queryParamInteger + in: query + description: A single enum value as a query parameter + required: false + schema: + type: integer + + + requestBody: + content: + application/x-www-form-urlencoded: + schema: + type: object + title: CreateParameterRequest + properties: + To: + type: string + format: phone-number + responses: + '201': + description: Parameter created successfully + content: + application/json: + schema: + type: object + properties: + id: + type: string + status: + type: string diff --git a/examples/test_spec/twilio_testenum_v1.yaml b/examples/test_spec/twilio_testenum_v1.yaml index fa019f500..fadccb586 100644 --- a/examples/test_spec/twilio_testenum_v1.yaml +++ b/examples/test_spec/twilio_testenum_v1.yaml @@ -1,5 +1,6 @@ # This spec Tests following # 1. All types of enums, There are 8 types of Enum to be tested +# 2. Enums as a query, header parameter info: contact: email: support@twilio.com diff --git a/src/main/java/com/twilio/oai/java/JavaTemplateUpdater.java b/src/main/java/com/twilio/oai/java/JavaTemplateUpdater.java index 7a39da4fb..97d618ca5 100644 --- a/src/main/java/com/twilio/oai/java/JavaTemplateUpdater.java +++ b/src/main/java/com/twilio/oai/java/JavaTemplateUpdater.java @@ -2,13 +2,14 @@ import com.twilio.oai.TwilioJavaGeneratorModern; import com.twilio.oai.common.EnumConstants; +import com.twilio.oai.java.constants.MustacheConstants; import org.openapitools.codegen.CodegenOperation; import java.util.AbstractMap; import java.util.Map; -import static com.twilio.oai.java.MustacheConstants.ActionMethod; -import static com.twilio.oai.java.MustacheConstants.ActionType; +import static com.twilio.oai.java.constants.MustacheConstants.ActionMethod; +import static com.twilio.oai.java.constants.MustacheConstants.ActionType; /* The JavaTemplateFile class is responsible for managing template mappings for Java code generation. diff --git a/src/main/java/com/twilio/oai/java/MustacheConstants.java b/src/main/java/com/twilio/oai/java/constants/MustacheConstants.java similarity index 97% rename from src/main/java/com/twilio/oai/java/MustacheConstants.java rename to src/main/java/com/twilio/oai/java/constants/MustacheConstants.java index 3c7993f5e..6dce31699 100644 --- a/src/main/java/com/twilio/oai/java/MustacheConstants.java +++ b/src/main/java/com/twilio/oai/java/constants/MustacheConstants.java @@ -1,4 +1,4 @@ -package com.twilio.oai.java; +package com.twilio.oai.java.constants; import lombok.AccessLevel; import lombok.Getter; diff --git a/src/main/java/com/twilio/oai/java/feature/SetterMethodGenerator.java b/src/main/java/com/twilio/oai/java/feature/SetterMethodGenerator.java index 602b19b5f..5b637a969 100644 --- a/src/main/java/com/twilio/oai/java/feature/SetterMethodGenerator.java +++ b/src/main/java/com/twilio/oai/java/feature/SetterMethodGenerator.java @@ -6,6 +6,7 @@ import java.util.ArrayList; import java.util.List; +import java.util.stream.Collectors; // Add all setter variables for an operation which is non path parameters public class SetterMethodGenerator { @@ -25,12 +26,7 @@ public static synchronized SetterMethodGenerator getInstance() { } public void apply(final CodegenOperation codegenOperation) { - List codegenParameters = new ArrayList<>(); - codegenOperation.allParams.forEach(param -> { - if (!param.isPathParam) { - codegenParameters.add(param); - } - }); - codegenOperation.vendorExtensions.put("x-non-path-params", codegenParameters); + List setterParameters = codegenOperation.allParams.stream().filter(param -> !param.isPathParam).collect(Collectors.toList()); + codegenOperation.vendorExtensions.put("x-setter-methods", setterParameters); } } diff --git a/src/main/java/com/twilio/oai/java/feature/constructor/UrlencodedBodyConstructorGenerator.java b/src/main/java/com/twilio/oai/java/feature/constructor/UrlencodedBodyConstructorGenerator.java index 10bba72f2..b1b8a48b8 100644 --- a/src/main/java/com/twilio/oai/java/feature/constructor/UrlencodedBodyConstructorGenerator.java +++ b/src/main/java/com/twilio/oai/java/feature/constructor/UrlencodedBodyConstructorGenerator.java @@ -28,12 +28,14 @@ public void apply(CodegenOperation codegenOperation) { } public boolean shouldApply(CodegenOperation codegenOperation) { + // TODO + return true; // Check if the operation consumes application/x-www-form-urlencoded - if (codegenOperation.consumes == null || codegenOperation.consumes.isEmpty()) { - return false; - } - return codegenOperation.consumes.stream() - .anyMatch(mediaType -> mediaType.get("mediaType").equals("application/x-www-form-urlencoded")); +// if (codegenOperation.consumes == null || codegenOperation.consumes.isEmpty()) { +// return false; +// } +// return codegenOperation.consumes.stream() +// .anyMatch(mediaType -> mediaType.get("mediaType").equals("application/x-www-form-urlencoded")); } public List> generateSignatureListModern(final CodegenOperation codegenOperation) { diff --git a/src/main/java/com/twilio/oai/java/format/Promoter.java b/src/main/java/com/twilio/oai/java/format/Promoter.java index b4e1c1407..e7983bb7a 100644 --- a/src/main/java/com/twilio/oai/java/format/Promoter.java +++ b/src/main/java/com/twilio/oai/java/format/Promoter.java @@ -29,9 +29,8 @@ public static void addPromoter(final CodegenParameter codegenParameter) { } } - public static void addPromotor(final CodegenOperation codegenOperation) { + public static void addPromoter(final CodegenOperation codegenOperation) { List setterParameters = codegenOperation.allParams.stream().filter(param -> !param.isPathParam).collect(Collectors.toList()); setterParameters.forEach(param -> addPromoter(param)); - codegenOperation.vendorExtensions.put("x-setter-methods", setterParameters); } } diff --git a/src/main/java/com/twilio/oai/java/processor/JavaOperationProcessor.java b/src/main/java/com/twilio/oai/java/processor/JavaOperationProcessor.java index e8ebca87c..e0845652f 100644 --- a/src/main/java/com/twilio/oai/java/processor/JavaOperationProcessor.java +++ b/src/main/java/com/twilio/oai/java/processor/JavaOperationProcessor.java @@ -2,6 +2,7 @@ import com.twilio.oai.java.feature.SetterMethodGenerator; import com.twilio.oai.java.feature.constructor.ConstructorFactory; +import com.twilio.oai.java.format.Promoter; import com.twilio.oai.java.processor.parameter.ParameterProcessor; import com.twilio.oai.java.processor.requestbody.RequestBodyProcessorFactory; import com.twilio.oai.java.processor.responsebody.ResponseProcessorFactory; @@ -32,5 +33,6 @@ public void process(final CodegenOperation codegenOperation) { // All Features should be applied after processors are completed ConstructorFactory.getInstance().applyFeature(codegenOperation); SetterMethodGenerator.getInstance().apply(codegenOperation); + Promoter.addPromoter(codegenOperation); } } diff --git a/src/main/java/com/twilio/oai/java/processor/parameter/ParameterProcessor.java b/src/main/java/com/twilio/oai/java/processor/parameter/ParameterProcessor.java index 0e06fcb0f..eaa17992c 100644 --- a/src/main/java/com/twilio/oai/java/processor/parameter/ParameterProcessor.java +++ b/src/main/java/com/twilio/oai/java/processor/parameter/ParameterProcessor.java @@ -26,5 +26,8 @@ public void process(final CodegenOperation codegenOperation) { codegenOperation.pathParams.forEach(param -> enumProcessorFactory.applyProcessor(param)); codegenOperation.headerParams.forEach(param -> enumProcessorFactory.applyProcessor(param)); codegenOperation.requiredParams.forEach(param -> enumProcessorFactory.applyProcessor(param)); + + // Required for setter methods and promotion method generation + codegenOperation.allParams.forEach(param -> enumProcessorFactory.applyProcessor(param)); } } \ No newline at end of file diff --git a/src/main/java/com/twilio/oai/java/processor/requestbody/JsonRequestProcessor.java b/src/main/java/com/twilio/oai/java/processor/requestbody/JsonRequestProcessor.java index 81098fb8e..cd80d388c 100644 --- a/src/main/java/com/twilio/oai/java/processor/requestbody/JsonRequestProcessor.java +++ b/src/main/java/com/twilio/oai/java/processor/requestbody/JsonRequestProcessor.java @@ -4,7 +4,7 @@ import org.openapitools.codegen.CodegenOperation; import static com.twilio.oai.common.ApplicationConstants.X_REQUEST_CONTENT_TYPE; -import static com.twilio.oai.java.MustacheConstants.X_REQUEST_LANGUAGE_CONTENT_TYPE_CONSTANT; +import static com.twilio.oai.java.constants.MustacheConstants.X_REQUEST_LANGUAGE_CONTENT_TYPE_CONSTANT; public class JsonRequestProcessor implements RequestBodyProcessor { final RecursiveModelProcessor recursiveModelProcessor = new RecursiveModelProcessor(); diff --git a/src/main/java/com/twilio/oai/java/processor/requestbody/UrlEncodedProcessor.java b/src/main/java/com/twilio/oai/java/processor/requestbody/UrlEncodedProcessor.java index 5ec8afc5a..3498ab0cb 100644 --- a/src/main/java/com/twilio/oai/java/processor/requestbody/UrlEncodedProcessor.java +++ b/src/main/java/com/twilio/oai/java/processor/requestbody/UrlEncodedProcessor.java @@ -4,7 +4,7 @@ import org.openapitools.codegen.CodegenOperation; import static com.twilio.oai.common.ApplicationConstants.X_REQUEST_CONTENT_TYPE; -import static com.twilio.oai.java.MustacheConstants.X_REQUEST_LANGUAGE_CONTENT_TYPE_CONSTANT; +import static com.twilio.oai.java.constants.MustacheConstants.X_REQUEST_LANGUAGE_CONTENT_TYPE_CONSTANT; public class UrlEncodedProcessor implements RequestBodyProcessor { final EnumProcessorFactory enumFactory = EnumProcessorFactory.getInstance(); diff --git a/src/main/resources/twilio-java-modern/common/constructors.mustache b/src/main/resources/twilio-java-modern/common/constructors.mustache index 31e2970e5..3aa4a722c 100644 --- a/src/main/resources/twilio-java-modern/common/constructors.mustache +++ b/src/main/resources/twilio-java-modern/common/constructors.mustache @@ -1,5 +1,5 @@ {{#vendorExtensions.x-signature-list}} - public {{resourceName}}Creator({{#.}}final {{{dataType}}} {{paramName}}{{^-last}}, {{/-last}}{{/.}}) { + public {{resourceName}}{{vendorExtensions.x-common-action-type}}({{#.}}final {{{dataType}}} {{paramName}}{{^-last}}, {{/-last}}{{/.}}) { {{#.}} this.{{paramName}} = {{paramName}}; {{/.}} diff --git a/src/main/resources/twilio-java-modern/creator.mustache b/src/main/resources/twilio-java-modern/creator.mustache index f3d505b04..1bab4b4ec 100644 --- a/src/main/resources/twilio-java-modern/creator.mustache +++ b/src/main/resources/twilio-java-modern/creator.mustache @@ -7,7 +7,7 @@ import com.twilio.constant.EnumConstants.ParameterType; {{#resources}} {{#operations}} {{#vendorExtensions.x-create-operation}} -public class {{resourceName}} extends Creator<{{resourceName}}> { +public class {{resourceName}}Creator extends Creator<{{resourceName}}> { {{>common/instanceVariables}} {{>common/constructors}} diff --git a/src/main/resources/twilio-java-modern/deleter.mustache b/src/main/resources/twilio-java-modern/deleter.mustache index ed1c034f7..1db4469ee 100644 --- a/src/main/resources/twilio-java-modern/deleter.mustache +++ b/src/main/resources/twilio-java-modern/deleter.mustache @@ -7,7 +7,7 @@ import com.twilio.constant.EnumConstants.ParameterType; {{#resources}} {{#operations}} {{#vendorExtensions.x-delete-operation}} - public class {{resourceName}} extends Deleter<{{resourceName}}> { + public class {{resourceName}}Deleter extends Deleter<{{resourceName}}> { {{>common/instanceVariables}} {{>common/constructors}} diff --git a/src/main/resources/twilio-java-modern/fetcher.mustache b/src/main/resources/twilio-java-modern/fetcher.mustache index e73b093e8..dd34200af 100644 --- a/src/main/resources/twilio-java-modern/fetcher.mustache +++ b/src/main/resources/twilio-java-modern/fetcher.mustache @@ -7,7 +7,7 @@ import com.twilio.constant.EnumConstants.ParameterType; {{#resources}} {{#operations}} {{#vendorExtensions.x-fetch-operation}} - public class {{resourceName}} extends Fetcher<{{resourceName}}> { + public class {{resourceName}}Fetcher extends Fetcher<{{resourceName}}> { {{>common/instanceVariables}} {{>common/constructors}} diff --git a/src/main/resources/twilio-java-modern/reader.mustache b/src/main/resources/twilio-java-modern/reader.mustache index 992ba1412..a5fbdc761 100644 --- a/src/main/resources/twilio-java-modern/reader.mustache +++ b/src/main/resources/twilio-java-modern/reader.mustache @@ -7,7 +7,7 @@ import com.twilio.constant.EnumConstants.ParameterType; {{#resources}} {{#operations}} {{#vendorExtensions.x-fetch-operation}} -public class {{resourceName}} extends Fetcher<{{resourceName}}> { +public class {{resourceName}}Reader extends Fetcher<{{resourceName}}> { {{>common/instanceVariables}} {{>common/constructors}} diff --git a/src/main/resources/twilio-java-modern/updater.mustache b/src/main/resources/twilio-java-modern/updater.mustache index 18a04d70a..b2606a8ae 100644 --- a/src/main/resources/twilio-java-modern/updater.mustache +++ b/src/main/resources/twilio-java-modern/updater.mustache @@ -7,7 +7,7 @@ import com.twilio.constant.EnumConstants.ParameterType; {{#resources}} {{#operations}} {{#vendorExtensions.x-update-operation}} - public class {{resourceName}} extends Updater<{{resourceName}}> { + public class {{resourceName}}Updater extends Updater<{{resourceName}}> { {{>common/instanceVariables}} {{>common/constructors}} {{>common/setters}} From b7b452099446427e4f4d4d19eb8c08dd218d1ceb Mon Sep 17 00:00:00 2001 From: sbansla <104902068+sbansla@users.noreply.github.com> Date: Fri, 29 Aug 2025 10:15:06 +0530 Subject: [PATCH 14/38] Testing twilio-java modernisation (#678) --- examples/test_spec/twilio_auth_v1.yaml | 10 ++ examples/test_spec/twilio_request_v1.yaml | 100 +++++++++++++++++- examples/test_spec/twilio_testenum_v1.yaml | 21 +++- pom.xml | 2 +- .../twilio/oai/TwilioJavaGeneratorModern.java | 2 + .../com/twilio/oai/TwilioPythonGenerator.java | 27 ++--- .../java/com/twilio/oai/common/Utility.java | 8 +- .../com/twilio/oai/java/JavaApiResource.java | 5 + .../oai/java/JavaApiResourceBuilder.java | 15 +++ .../java/feature/SetterMethodGenerator.java | 2 + .../java/feature/datamodels/DataModel.java | 9 ++ .../feature/datamodels/DataModelManager.java | 46 ++++++++ .../oai/java/feature/datamodels/OneOf.java | 20 ++++ .../oai/java/nestedmodels/MustacheOneOf.java | 4 + .../processor/JavaOperationProcessor.java | 3 + .../java/processor/PaginationStrategy.java | 7 ++ .../oai/java/processor/auth/BasicAuth.java | 31 ++++++ .../oai/java/processor/auth/NoAuth.java | 27 +++++ .../twilio/oai/java/processor/auth/OAuth.java | 22 ++++ .../oai/java/processor/auth/OrgsOAuth.java | 35 ++++++ .../processor/auth/SecuritySchemeManager.java | 59 +++++++++++ .../auth/SecuritySchemeProcessor.java | 13 +++ .../model/ModelProcessorFactory.java | 4 + .../requestbody/JsonRequestProcessor.java | 1 + .../requestbody/RecursiveModelProcessor.java | 11 +- .../responsebody/JsonResponseProcessor.java | 1 + .../allConstructors.mustache | 64 +++++++++++ .../resources/twilio-java-modern/api.mustache | 11 +- .../common/addHeaderParams.mustache | 4 +- .../common/addPostParams.mustache | 4 +- .../common/addQueryParams.mustache | 6 +- .../common/imports.mustache | 54 ++++++++++ .../twilio-java-modern/creator.mustache | 13 ++- .../creator/operationMethod.mustache | 51 +++++++++ .../creator/setters.mustache | 20 ++++ .../twilio-java-modern/deleter.mustache | 12 +-- .../deleter/operationMethod.mustache | 44 ++++++++ .../deleter/setters.mustache | 20 ++++ .../twilio-java-modern/enums.mustache | 2 +- .../equalsAndHashcode.mustache | 26 +++++ .../twilio-java-modern/fetcher.mustache | 12 +-- .../fetcher/operationMethod.mustache | 44 ++++++++ .../fetcher/setters.mustache | 20 ++++ .../twilio-java-modern/reader.mustache | 18 ++-- .../reader/operationMethod.mustache | 20 +++- .../reader/paginationMethods.mustache | 0 .../reader/setters.mustache | 20 ++++ .../twilio-java-modern/response.mustache | 40 ++++++- .../twilio-java-modern/staticMethods.mustache | 2 +- .../twilio-java-modern/updater.mustache | 12 +-- .../updater/operationMethod.mustache | 51 +++++++++ .../updater/setters.mustache | 20 ++++ .../twilio-python/api-single.mustache | 1 - .../com/twilio/oai/TwilioGeneratorTest.java | 7 +- 54 files changed, 1002 insertions(+), 81 deletions(-) create mode 100644 examples/test_spec/twilio_auth_v1.yaml create mode 100644 src/main/java/com/twilio/oai/java/feature/datamodels/DataModel.java create mode 100644 src/main/java/com/twilio/oai/java/feature/datamodels/DataModelManager.java create mode 100644 src/main/java/com/twilio/oai/java/feature/datamodels/OneOf.java create mode 100644 src/main/java/com/twilio/oai/java/nestedmodels/MustacheOneOf.java create mode 100644 src/main/java/com/twilio/oai/java/processor/PaginationStrategy.java create mode 100644 src/main/java/com/twilio/oai/java/processor/auth/BasicAuth.java create mode 100644 src/main/java/com/twilio/oai/java/processor/auth/NoAuth.java create mode 100644 src/main/java/com/twilio/oai/java/processor/auth/OAuth.java create mode 100644 src/main/java/com/twilio/oai/java/processor/auth/OrgsOAuth.java create mode 100644 src/main/java/com/twilio/oai/java/processor/auth/SecuritySchemeManager.java create mode 100644 src/main/java/com/twilio/oai/java/processor/auth/SecuritySchemeProcessor.java create mode 100644 src/main/resources/twilio-java-modern/allConstructors.mustache create mode 100644 src/main/resources/twilio-java-modern/common/imports.mustache create mode 100644 src/main/resources/twilio-java-modern/creator/operationMethod.mustache create mode 100644 src/main/resources/twilio-java-modern/creator/setters.mustache create mode 100644 src/main/resources/twilio-java-modern/deleter/operationMethod.mustache create mode 100644 src/main/resources/twilio-java-modern/deleter/setters.mustache create mode 100644 src/main/resources/twilio-java-modern/equalsAndHashcode.mustache create mode 100644 src/main/resources/twilio-java-modern/fetcher/operationMethod.mustache create mode 100644 src/main/resources/twilio-java-modern/fetcher/setters.mustache create mode 100644 src/main/resources/twilio-java-modern/reader/paginationMethods.mustache create mode 100644 src/main/resources/twilio-java-modern/reader/setters.mustache create mode 100644 src/main/resources/twilio-java-modern/updater/operationMethod.mustache create mode 100644 src/main/resources/twilio-java-modern/updater/setters.mustache diff --git a/examples/test_spec/twilio_auth_v1.yaml b/examples/test_spec/twilio_auth_v1.yaml new file mode 100644 index 000000000..a6d5e7b9d --- /dev/null +++ b/examples/test_spec/twilio_auth_v1.yaml @@ -0,0 +1,10 @@ +components: + securitySchemes: + oAuth2ClientCredentials: + type: oauth2 + flows: + clientCredentials: + tokenUrl: https://preview-iam.twilio.com/v1/token + scopes: {} +paths: + \ No newline at end of file diff --git a/examples/test_spec/twilio_request_v1.yaml b/examples/test_spec/twilio_request_v1.yaml index eaa212c6d..cf07b84a3 100644 --- a/examples/test_spec/twilio_request_v1.yaml +++ b/examples/test_spec/twilio_request_v1.yaml @@ -1,3 +1,101 @@ # This spec tests followings # 1. All types of request body(urlencoded, json) -# 2. Tests pagination for both type of request body. \ No newline at end of file +# 2. Tests pagination for both type of request body. + +info: + contact: + email: support@twilio.com + name: Twilio Support + url: https://support.twilio.com + description: This is the public Twilio REST API. + license: + name: Apache 2.0 + url: https://www.apache.org/licenses/LICENSE-2.0.html + termsOfService: https://www.twilio.com/legal/tos + title: Twilio - REQUEST BODY TEST + version: 1.11.0 +openapi: 3.0.1 + +components: + schemas: + UpdateRequestBodyRequest: + type: object + properties: + username: + type: string + password: + type: string +paths: + /v1/requestbody: + servers: + - url: https://testparameter.twilio.com + post: + operationId: CreateRequestBody + parameters: + - name: queryParamStringRequired + in: query + description: A single enum value as a query parameter + required: required + schema: + type: string + requestBody: + content: + application/x-www-form-urlencoded: + schema: + # 1. Inline request body + type: object + title: CreateRequestBodyRequest + properties: + username: + type: string + password: + type: string + + responses: + '201': + description: Parameter created successfully + content: + application/json: + schema: + type: object + properties: + id: + type: string + status: + type: string + + /v1/requestbody/{id}: + servers: + - url: https://testparameter.twilio.com + post: + operationId: UpdateRequestBody + parameters: + - name: id + in: path + required: true + schema: + type: string + - name: queryParamStringRequired + in: query + required: required + schema: + type: string + requestBody: + content: + application/x-www-form-urlencoded: + schema: + # 2. Reusable request body + $ref: '#/components/schemas/UpdateRequestBodyRequest' + + responses: + '201': + description: Parameter created successfully + content: + application/json: + schema: + type: object + properties: + id: + type: string + status: + type: string \ No newline at end of file diff --git a/examples/test_spec/twilio_testenum_v1.yaml b/examples/test_spec/twilio_testenum_v1.yaml index fadccb586..470aed46a 100644 --- a/examples/test_spec/twilio_testenum_v1.yaml +++ b/examples/test_spec/twilio_testenum_v1.yaml @@ -107,9 +107,28 @@ components: $ref: '#/components/schemas/singleReusable' description: An array of reusable enum defined in components example: [electronics, clothing] + status: + $ref: '#/components/schemas/message_enum_status' # 8. REUSABLE_SINGLE singleReusable: type: string enum: [electronics, furniture, clothing] - description: A reusable single-value enum defined in components \ No newline at end of file + description: A reusable single-value enum defined in components + message_enum_status: + type: string + enum: + - queued + - sending + - sent + - failed + - delivered + - undelivered + - receiving + - received + - accepted + - scheduled + - read + - partially_delivered + - canceled + description: test \ No newline at end of file diff --git a/pom.xml b/pom.xml index 45bf70981..21ba1bdec 100644 --- a/pom.xml +++ b/pom.xml @@ -124,7 +124,7 @@ UTF-8 - 6.6.0 + 7.13.0 1.0.0 4.13.2 diff --git a/src/main/java/com/twilio/oai/TwilioJavaGeneratorModern.java b/src/main/java/com/twilio/oai/TwilioJavaGeneratorModern.java index eb3ef4694..602311786 100644 --- a/src/main/java/com/twilio/oai/TwilioJavaGeneratorModern.java +++ b/src/main/java/com/twilio/oai/TwilioJavaGeneratorModern.java @@ -52,6 +52,7 @@ public void processOpts() { this.modelTemplateFiles.clear(); javaUpdateDefaultMapping.typeMapping(this.typeMapping); javaUpdateDefaultMapping.importMapping(this.importMapping); + javaUpdateDefaultMapping.modelTemplateFiles(this.modelTemplateFiles); twilioCodegen.processOpts(); } @@ -136,6 +137,7 @@ private JavaApiResource processCodegenOperations(List operatio .resourceName() .recordKey() .processOperations() + .namespaceSubPart(operations.get(0)) .build(); return apiResource; } diff --git a/src/main/java/com/twilio/oai/TwilioPythonGenerator.java b/src/main/java/com/twilio/oai/TwilioPythonGenerator.java index 3a8629731..f09f23ee1 100644 --- a/src/main/java/com/twilio/oai/TwilioPythonGenerator.java +++ b/src/main/java/com/twilio/oai/TwilioPythonGenerator.java @@ -24,21 +24,22 @@ import io.swagger.v3.oas.models.PathItem; import org.openapitools.codegen.CodegenModel; import org.openapitools.codegen.CodegenOperation; -import org.openapitools.codegen.languages.PythonLegacyClientCodegen; +import org.openapitools.codegen.languages.PythonClientCodegen; +//import org.openapitools.codegen.languages.PythonLegacyClientCodegen; import org.openapitools.codegen.model.ModelMap; import org.openapitools.codegen.model.ModelsMap; import org.openapitools.codegen.model.OperationsMap; import static com.twilio.oai.common.ApplicationConstants.CONFIG_PYTHON_JSON_PATH; -public class TwilioPythonGenerator extends PythonLegacyClientCodegen { +public class TwilioPythonGenerator extends PythonClientCodegen { private final TwilioCodegenAdapter twilioCodegen; private final PythonApiActionTemplate actionTemplate = new PythonApiActionTemplate(this); private final IResourceTree resourceTree = new ResourceMap(new Inflector()); private final DirectoryStructureService directoryStructureService = new DirectoryStructureService( - additionalProperties, - resourceTree, - new PythonCaseResolver()); + additionalProperties, + resourceTree, + new PythonCaseResolver()); private final List allModels = new ArrayList<>(); private final Map modelFormatMap = new HashMap<>(); public static final String JSON_INGRESS = "json_ingress"; @@ -79,9 +80,9 @@ public String apiFilename(final String templateName, final String tag) { final String resourcePath = pathsEntry.getKey(); final PathItem path = pathsEntry.getValue(); final boolean isMatchingPath = path - .readOperations() - .stream() - .anyMatch(operation -> operation.getTags().contains(tag)); + .readOperations() + .stream() + .anyMatch(operation -> operation.getTags().contains(tag)); final boolean pathHasDependents = !resourceTree.dependents(resourcePath).isEmpty(); return isMatchingPath && pathHasDependents; @@ -120,15 +121,15 @@ public OperationsMap postProcessOperationsWithModels(final OperationsMap objs, L private ApiResources generateResources(final List opList) { final IConventionMapper conventionMapper = new LanguageConventionResolver(CONFIG_PYTHON_JSON_PATH); final PythonCodegenModelResolver codegenModelResolver = new PythonCodegenModelResolver(conventionMapper, - modelFormatMap, - List.of(EnumConstants.PythonDataTypes.values())); + modelFormatMap, + List.of(EnumConstants.PythonDataTypes.values())); PythonApiResourceBuilder pythonApiResourceBuilder = new PythonApiResourceBuilder(actionTemplate, opList, allModels, directoryStructureService, twilioCodegen.getToggles(JSON_INGRESS)); pythonApiResourceBuilder.updateApiPath() - .updateTemplate() - .updateOperations(new PythonParameterResolver(conventionMapper, codegenModelResolver)); + .updateTemplate() + .updateOperations(new PythonParameterResolver(conventionMapper, codegenModelResolver)); return pythonApiResourceBuilder.updateResponseModel(new PythonPropertyResolver(conventionMapper), codegenModelResolver) - .build(); + .build(); } @Override diff --git a/src/main/java/com/twilio/oai/common/Utility.java b/src/main/java/com/twilio/oai/common/Utility.java index 31dcb2400..c99db0b66 100644 --- a/src/main/java/com/twilio/oai/common/Utility.java +++ b/src/main/java/com/twilio/oai/common/Utility.java @@ -198,13 +198,17 @@ public static String getEnumNameFromRef(final String ref) { } /* For request body(urlencoded) enums with ref, it will be processed by default - Example: + Example1: singleBodyRef: $ref: '#/components/schemas/singleReusable' + + Example2: + status: + $ref: '#/components/schemas/message_enum_status' */ public static String getEnumNameFromDefaultDatatype(final String ref) { String schemaName = ref.replaceFirst("#/components/schemas/", ""); - String[] enumNameArray = schemaName.split("Enum"); + String[] enumNameArray = schemaName.split("_enum_"); return enumNameArray[enumNameArray.length - 1]; } diff --git a/src/main/java/com/twilio/oai/java/JavaApiResource.java b/src/main/java/com/twilio/oai/java/JavaApiResource.java index 75118ca56..b8c963ba6 100644 --- a/src/main/java/com/twilio/oai/java/JavaApiResource.java +++ b/src/main/java/com/twilio/oai/java/JavaApiResource.java @@ -16,7 +16,10 @@ public class JavaApiResource { Set mustacheModels; List operations; Set response; + String namespaceSubPart; + Boolean responseFlag = null; // true or NUll + public JavaApiResource(JavaApiResourceBuilder builder) { resourceName = ResourceCache.resourceName; recordKey = builder.recordKey; @@ -24,6 +27,8 @@ public JavaApiResource(JavaApiResourceBuilder builder) { this.mustacheEnums = new HashSet<>(ResourceCache.getEnumsClassesForMustache()); this.mustacheModels = new HashSet<>(ResourceCache.getModelClassesForMustache()); this.response = ResourceCache.response; + if (response != null && !response.isEmpty()) responseFlag = true; + this.namespaceSubPart = builder.namespaceSubPart; } } diff --git a/src/main/java/com/twilio/oai/java/JavaApiResourceBuilder.java b/src/main/java/com/twilio/oai/java/JavaApiResourceBuilder.java index d96dd580b..8a0f1f4bf 100644 --- a/src/main/java/com/twilio/oai/java/JavaApiResourceBuilder.java +++ b/src/main/java/com/twilio/oai/java/JavaApiResourceBuilder.java @@ -9,6 +9,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.stream.Collectors; import static com.twilio.oai.common.ApplicationConstants.PATH_SEPARATOR_PLACEHOLDER; @@ -20,6 +21,7 @@ public class JavaApiResourceBuilder { TwilioJavaGeneratorModern twilioJavaGenerator; final JavaOperationProcessor operationProcessor; List operations; + String namespaceSubPart; public JavaApiResourceBuilder(TwilioJavaGeneratorModern twilioJavaGenerator, List operations) { this.twilioJavaGenerator = twilioJavaGenerator; this.operations = operations; @@ -53,6 +55,19 @@ public JavaApiResourceBuilder processOperations() { return this; } + public JavaApiResourceBuilder namespaceSubPart(CodegenOperation codegenOperation) { + List filePathArray = new ArrayList<>(Arrays.asList(codegenOperation.baseName.split(PATH_SEPARATOR_PLACEHOLDER))); + filePathArray.remove(filePathArray.size()-1); + if (!filePathArray.isEmpty()) { + final String namespacePath = filePathArray + .stream() + .map(String::toLowerCase) + .collect(Collectors.joining(".")); + namespaceSubPart = "." + namespacePath; + } + return this; + } + public JavaApiResource build() { return new JavaApiResource(this); } diff --git a/src/main/java/com/twilio/oai/java/feature/SetterMethodGenerator.java b/src/main/java/com/twilio/oai/java/feature/SetterMethodGenerator.java index 5b637a969..ae5de7895 100644 --- a/src/main/java/com/twilio/oai/java/feature/SetterMethodGenerator.java +++ b/src/main/java/com/twilio/oai/java/feature/SetterMethodGenerator.java @@ -1,10 +1,12 @@ package com.twilio.oai.java.feature; +import com.twilio.oai.java.constants.MustacheConstants; import com.twilio.oai.java.processor.enums.EnumProcessorFactory; import org.openapitools.codegen.CodegenOperation; import org.openapitools.codegen.CodegenParameter; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; import java.util.stream.Collectors; diff --git a/src/main/java/com/twilio/oai/java/feature/datamodels/DataModel.java b/src/main/java/com/twilio/oai/java/feature/datamodels/DataModel.java new file mode 100644 index 000000000..90096bea1 --- /dev/null +++ b/src/main/java/com/twilio/oai/java/feature/datamodels/DataModel.java @@ -0,0 +1,9 @@ +package com.twilio.oai.java.feature.datamodels; + +import org.openapitools.codegen.CodegenModel; +import org.openapitools.codegen.CodegenOperation; + +public interface DataModel { + void apply(CodegenModel codegenModel); + boolean shouldApply(CodegenModel codegenModel); +} diff --git a/src/main/java/com/twilio/oai/java/feature/datamodels/DataModelManager.java b/src/main/java/com/twilio/oai/java/feature/datamodels/DataModelManager.java new file mode 100644 index 000000000..3d30ce692 --- /dev/null +++ b/src/main/java/com/twilio/oai/java/feature/datamodels/DataModelManager.java @@ -0,0 +1,46 @@ +package com.twilio.oai.java.feature.datamodels; + +import org.openapitools.codegen.CodegenModel; + +import java.util.List; + +public class DataModelManager { + + public static DataModelManager instance; + List dataModels; + + private DataModelManager() { + dataModels = List.of( + new OneOf() + ); + } + + public static synchronized DataModelManager getInstance() { + if (instance == null) { + synchronized (DataModelManager.class) { + if (instance == null) { + instance = new DataModelManager(); + } + } + } + return instance; + } + + public void apply(final CodegenModel codegenModel) { + for (DataModel dataModel: dataModels) { + if (dataModel.shouldApply(codegenModel)) { + dataModel.apply(codegenModel); + return; // Can a CodegenModel have multiple datamodels at same level, if yes don't return ? + } + } + } + + public boolean shouldApply(final CodegenModel codegenModel) { + for (DataModel dataModel : dataModels) { + if (dataModel.shouldApply(codegenModel)) { + return true; + } + } + return false; + } +} diff --git a/src/main/java/com/twilio/oai/java/feature/datamodels/OneOf.java b/src/main/java/com/twilio/oai/java/feature/datamodels/OneOf.java new file mode 100644 index 000000000..b7796f40d --- /dev/null +++ b/src/main/java/com/twilio/oai/java/feature/datamodels/OneOf.java @@ -0,0 +1,20 @@ +package com.twilio.oai.java.feature.datamodels; + +import org.openapitools.codegen.CodegenModel; + +public class OneOf implements DataModel { + + @Override + public void apply(final CodegenModel codegenModel) { + System.out.println(codegenModel); + + } + + @Override + public boolean shouldApply(final CodegenModel codegenModel) { + if (codegenModel == null || codegenModel.oneOf == null || codegenModel.oneOf.isEmpty()) { + return false; + } + return true; + } +} diff --git a/src/main/java/com/twilio/oai/java/nestedmodels/MustacheOneOf.java b/src/main/java/com/twilio/oai/java/nestedmodels/MustacheOneOf.java new file mode 100644 index 000000000..8ca9f1fba --- /dev/null +++ b/src/main/java/com/twilio/oai/java/nestedmodels/MustacheOneOf.java @@ -0,0 +1,4 @@ +package com.twilio.oai.java.nestedmodels; + +public class MustacheOneOf { +} diff --git a/src/main/java/com/twilio/oai/java/processor/JavaOperationProcessor.java b/src/main/java/com/twilio/oai/java/processor/JavaOperationProcessor.java index e0845652f..4266ac9b3 100644 --- a/src/main/java/com/twilio/oai/java/processor/JavaOperationProcessor.java +++ b/src/main/java/com/twilio/oai/java/processor/JavaOperationProcessor.java @@ -3,6 +3,7 @@ import com.twilio.oai.java.feature.SetterMethodGenerator; import com.twilio.oai.java.feature.constructor.ConstructorFactory; import com.twilio.oai.java.format.Promoter; +import com.twilio.oai.java.processor.auth.SecuritySchemeManager; import com.twilio.oai.java.processor.parameter.ParameterProcessor; import com.twilio.oai.java.processor.requestbody.RequestBodyProcessorFactory; import com.twilio.oai.java.processor.responsebody.ResponseProcessorFactory; @@ -25,6 +26,8 @@ public static synchronized JavaOperationProcessor getInstance() { private JavaOperationProcessor() { } public void process(final CodegenOperation codegenOperation) { + SecuritySchemeManager.getInstance().applyProcessor(codegenOperation); + ParameterProcessor.getInstance().process(codegenOperation); RequestBodyProcessorFactory.getInstance().process(codegenOperation); ResponseProcessorFactory.getInstance().process(codegenOperation); diff --git a/src/main/java/com/twilio/oai/java/processor/PaginationStrategy.java b/src/main/java/com/twilio/oai/java/processor/PaginationStrategy.java new file mode 100644 index 000000000..baf90d45a --- /dev/null +++ b/src/main/java/com/twilio/oai/java/processor/PaginationStrategy.java @@ -0,0 +1,7 @@ +package com.twilio.oai.java.processor; + +/* +There are 2 types pagination strategies are supported nextPrev and direct. + */ +public interface PaginationStrategy { +} diff --git a/src/main/java/com/twilio/oai/java/processor/auth/BasicAuth.java b/src/main/java/com/twilio/oai/java/processor/auth/BasicAuth.java new file mode 100644 index 000000000..17b34197e --- /dev/null +++ b/src/main/java/com/twilio/oai/java/processor/auth/BasicAuth.java @@ -0,0 +1,31 @@ +package com.twilio.oai.java.processor.auth; + +import org.openapitools.codegen.CodegenOperation; +import org.openapitools.codegen.CodegenSecurity; + +import java.util.HashMap; +import java.util.List; + +import static com.twilio.oai.resolver.java.JavaConventionResolver.AUTH_IMPORT_CLASS; +import static com.twilio.oai.resolver.java.JavaConventionResolver.HTTP_CLASS_PREFIX; + +public class BasicAuth implements SecuritySchemeProcessor { + @Override + public void process(CodegenOperation codegenOperation) { + HashMap authAttributes = new HashMap<>(); + authAttributes.put(AUTH_IMPORT_CLASS, ""); + authAttributes.put(HTTP_CLASS_PREFIX, ""); + codegenOperation.vendorExtensions.put(authAttributesExtension, authAttributes); + } + + @Override + public boolean shouldProcess(CodegenOperation codegenOperation) { + List securities = codegenOperation.authMethods; + if (securities == null || securities.isEmpty()) return false; // No Authentication + if (securities.size() > 1) { + throw new RuntimeException("Multiple auth methods are not supported. Please use only one auth method per operation."); + } + CodegenSecurity security = securities.get(0); + return security.isBasic; + } +} diff --git a/src/main/java/com/twilio/oai/java/processor/auth/NoAuth.java b/src/main/java/com/twilio/oai/java/processor/auth/NoAuth.java new file mode 100644 index 000000000..4eef9260f --- /dev/null +++ b/src/main/java/com/twilio/oai/java/processor/auth/NoAuth.java @@ -0,0 +1,27 @@ +package com.twilio.oai.java.processor.auth; + +import org.openapitools.codegen.CodegenOperation; + +import java.util.HashMap; + +import static com.twilio.oai.resolver.java.JavaConventionResolver.AUTH_IMPORT_CLASS; +import static com.twilio.oai.resolver.java.JavaConventionResolver.HTTP_CLASS_PREFIX; +import static com.twilio.oai.resolver.java.JavaConventionResolver.NOAUTH_HTTP_CLASS_PREFIX; +import static com.twilio.oai.resolver.java.JavaConventionResolver.NOAUTH_IMPORT_CLASS; + +public class NoAuth implements SecuritySchemeProcessor { + + @Override + public void process(CodegenOperation codegenOperation) { + HashMap authAttributes = new HashMap<>(); + authAttributes.put(AUTH_IMPORT_CLASS, NOAUTH_IMPORT_CLASS); + authAttributes.put(HTTP_CLASS_PREFIX, NOAUTH_HTTP_CLASS_PREFIX); + codegenOperation.vendorExtensions.put(authAttributesExtension, authAttributes); + } + + @Override + public boolean shouldProcess(CodegenOperation codegenOperation) { + // This processor is for operations that do not require authentication + return true; + } +} diff --git a/src/main/java/com/twilio/oai/java/processor/auth/OAuth.java b/src/main/java/com/twilio/oai/java/processor/auth/OAuth.java new file mode 100644 index 000000000..bb109dcf0 --- /dev/null +++ b/src/main/java/com/twilio/oai/java/processor/auth/OAuth.java @@ -0,0 +1,22 @@ +package com.twilio.oai.java.processor.auth; + +import org.openapitools.codegen.CodegenOperation; +import org.openapitools.codegen.CodegenSecurity; + +import java.util.List; + +// Placeholder class, OAuth is not added to security schemes. +public class OAuth implements SecuritySchemeProcessor { + + @Override + public void process(CodegenOperation codegenOperation) { + // Implement the logic to process the CodegenOperation for OAuth + // This could include setting up OAuth-specific parameters, headers, etc. + } + + // Currently we are using same classes for OAuth and Basic Authentication, Thus no differentiation required. + @Override + public boolean shouldProcess(CodegenOperation codegenOperation) { + return false; + } +} diff --git a/src/main/java/com/twilio/oai/java/processor/auth/OrgsOAuth.java b/src/main/java/com/twilio/oai/java/processor/auth/OrgsOAuth.java new file mode 100644 index 000000000..2090e6eb7 --- /dev/null +++ b/src/main/java/com/twilio/oai/java/processor/auth/OrgsOAuth.java @@ -0,0 +1,35 @@ +package com.twilio.oai.java.processor.auth; + +import org.openapitools.codegen.CodegenOperation; +import org.openapitools.codegen.CodegenSecurity; + +import java.util.HashMap; +import java.util.List; + +import static com.twilio.oai.resolver.java.JavaConventionResolver.AUTH_IMPORT_CLASS; +import static com.twilio.oai.resolver.java.JavaConventionResolver.BEARER_AUTH_HTTP_CLASS_PREFIX; +import static com.twilio.oai.resolver.java.JavaConventionResolver.BEARER_AUTH_IMPORT_CLASS; +import static com.twilio.oai.resolver.java.JavaConventionResolver.HTTP_CLASS_PREFIX; + +public class OrgsOAuth implements SecuritySchemeProcessor { + + + @Override + public void process(CodegenOperation codegenOperation) { + HashMap authAttributes = new HashMap<>(); + authAttributes.put(AUTH_IMPORT_CLASS, BEARER_AUTH_IMPORT_CLASS); + authAttributes.put(HTTP_CLASS_PREFIX, BEARER_AUTH_HTTP_CLASS_PREFIX); + codegenOperation.vendorExtensions.put(authAttributesExtension, authAttributes); + } + + @Override + public boolean shouldProcess(CodegenOperation codegenOperation) { + List securities = codegenOperation.authMethods; + if (securities == null || securities.isEmpty()) return false; // No Authentication + if (securities.size() > 1) { + throw new RuntimeException("Multiple auth methods are not supported. Please use only one auth method per operation."); + } + CodegenSecurity security = securities.get(0); + return security.isOAuth; + } +} diff --git a/src/main/java/com/twilio/oai/java/processor/auth/SecuritySchemeManager.java b/src/main/java/com/twilio/oai/java/processor/auth/SecuritySchemeManager.java new file mode 100644 index 000000000..85195eb59 --- /dev/null +++ b/src/main/java/com/twilio/oai/java/processor/auth/SecuritySchemeManager.java @@ -0,0 +1,59 @@ +package com.twilio.oai.java.processor.auth; + +import org.openapitools.codegen.CodegenOperation; +import org.openapitools.codegen.CodegenSecurity; + +import java.util.List; + +public class SecuritySchemeManager { + public static SecuritySchemeManager instance; + private final List securitySchemeProcessors; + + public static synchronized SecuritySchemeManager getInstance() { + if (instance == null) { + synchronized (SecuritySchemeManager.class) { + if (instance == null) { + instance = new SecuritySchemeManager(); + } + } + } + return instance; + } + + private SecuritySchemeManager() { + this.securitySchemeProcessors = List.of( + new NoAuth(), + new BasicAuth(), + new OrgsOAuth() + ); + } + + public void applyProcessor(CodegenOperation codegenOperation) { + + for (SecuritySchemeProcessor securitySchemeProcessor : securitySchemeProcessors) { + if (securitySchemeProcessor.shouldProcess(codegenOperation)) { + securitySchemeProcessor.process(codegenOperation); + } + } + } +} +/* +ArrayList authMethods = (ArrayList) co.authMethods; +HashMap authAttributes = new HashMap<>(); + if(authMethods == null){ + authAttributes.put(AUTH_IMPORT_CLASS, NOAUTH_IMPORT_CLASS); + authAttributes.put(HTTP_CLASS_PREFIX, NOAUTH_HTTP_CLASS_PREFIX); + }else{ + for(CodegenSecurity c : authMethods){ + if(c.isOAuth == true){ + authAttributes.put(AUTH_IMPORT_CLASS, BEARER_AUTH_IMPORT_CLASS); + authAttributes.put(HTTP_CLASS_PREFIX, BEARER_AUTH_HTTP_CLASS_PREFIX); + } + else{ + authAttributes.put(AUTH_IMPORT_CLASS, EMPTY_STRING); + authAttributes.put(HTTP_CLASS_PREFIX, EMPTY_STRING); + } + } + } + co.vendorExtensions.put("x-auth-attributes", authAttributes); + */ \ No newline at end of file diff --git a/src/main/java/com/twilio/oai/java/processor/auth/SecuritySchemeProcessor.java b/src/main/java/com/twilio/oai/java/processor/auth/SecuritySchemeProcessor.java new file mode 100644 index 000000000..5633177ef --- /dev/null +++ b/src/main/java/com/twilio/oai/java/processor/auth/SecuritySchemeProcessor.java @@ -0,0 +1,13 @@ +package com.twilio.oai.java.processor.auth; + +import org.openapitools.codegen.CodegenOperation; + +import java.util.Map; + +// Orgs OAuth and Basic Auth has different RestClients. +// Set "x-auth-attributes" for different type of authentication +public interface SecuritySchemeProcessor { + String authAttributesExtension = "x-auth-attributes"; + void process(CodegenOperation codegenOperation); + boolean shouldProcess(CodegenOperation codegenOperation); +} diff --git a/src/main/java/com/twilio/oai/java/processor/model/ModelProcessorFactory.java b/src/main/java/com/twilio/oai/java/processor/model/ModelProcessorFactory.java index 9bda10caf..3cd5e546f 100644 --- a/src/main/java/com/twilio/oai/java/processor/model/ModelProcessorFactory.java +++ b/src/main/java/com/twilio/oai/java/processor/model/ModelProcessorFactory.java @@ -1,5 +1,6 @@ package com.twilio.oai.java.processor.model; +import com.twilio.oai.java.feature.datamodels.DataModelManager; import org.openapitools.codegen.CodegenModel; import org.openapitools.codegen.CodegenProperty; @@ -9,6 +10,7 @@ public class ModelProcessorFactory { private static ModelProcessorFactory instance; private final List modelProcessors; + private DataModelManager dataModelManager = DataModelManager.getInstance(); public static synchronized ModelProcessorFactory getInstance() { if (instance == null) { synchronized (ModelProcessorFactory.class) { @@ -28,6 +30,8 @@ private ModelProcessorFactory() { } public void applyProcessor(CodegenProperty codegenProperty, CodegenModel codegenModel) { + + // Process for (ModelProcessor modelProcessor : modelProcessors) { if (modelProcessor.shouldProcess(codegenProperty, codegenModel)) { modelProcessor.process(codegenProperty, codegenModel); diff --git a/src/main/java/com/twilio/oai/java/processor/requestbody/JsonRequestProcessor.java b/src/main/java/com/twilio/oai/java/processor/requestbody/JsonRequestProcessor.java index cd80d388c..c18ccba2c 100644 --- a/src/main/java/com/twilio/oai/java/processor/requestbody/JsonRequestProcessor.java +++ b/src/main/java/com/twilio/oai/java/processor/requestbody/JsonRequestProcessor.java @@ -15,6 +15,7 @@ public JsonRequestProcessor() { @Override public boolean shouldProcess(final CodegenOperation codegenOperation) { // TODO + if (codegenOperation.bodyParams != null && !codegenOperation.bodyParams.isEmpty()) return true; return false; } diff --git a/src/main/java/com/twilio/oai/java/processor/requestbody/RecursiveModelProcessor.java b/src/main/java/com/twilio/oai/java/processor/requestbody/RecursiveModelProcessor.java index 999784259..0b5086ee1 100644 --- a/src/main/java/com/twilio/oai/java/processor/requestbody/RecursiveModelProcessor.java +++ b/src/main/java/com/twilio/oai/java/processor/requestbody/RecursiveModelProcessor.java @@ -1,6 +1,7 @@ package com.twilio.oai.java.processor.requestbody; import com.twilio.oai.common.Utility; +import com.twilio.oai.java.feature.datamodels.DataModelManager; import com.twilio.oai.java.format.Deserializer; import com.twilio.oai.java.processor.enums.EnumProcessorFactory; import com.twilio.oai.java.processor.model.ModelProcessorFactory; @@ -8,6 +9,8 @@ import org.openapitools.codegen.CodegenOperation; import org.openapitools.codegen.CodegenProperty; +import java.util.List; + public class RecursiveModelProcessor { EnumProcessorFactory enumProcessorFactory = EnumProcessorFactory.getInstance(); ModelProcessorFactory modelProcessorFactory = ModelProcessorFactory.getInstance(); @@ -15,6 +18,7 @@ public class RecursiveModelProcessor { public void processBody(CodegenOperation codegenOperation) { // codegenOperation.bodyParam.vars.get(3).ref: #/components/schemas/types codegenOperation.bodyParam.vars.forEach(property -> processModelRecursively(property)); + } public void processResponse(final CodegenOperation codegenOperation) { @@ -29,10 +33,9 @@ private void processModelRecursively(final CodegenProperty codegenProperty) { /* This code block has access to all the codegenProperty for a nested model. Add your logic to process the property. - Start + ------------------ Start ------------------ */ - if (isEnum(codegenProperty)) { // Logic 1: Enum Logic processEnum(codegenProperty); @@ -49,7 +52,7 @@ private void processModelRecursively(final CodegenProperty codegenProperty) { modelProcessorFactory.applyProcessor(codegenProperty, codegenModel); /* - End + ------------------ End ------------------ */ @@ -62,8 +65,6 @@ private void processModelRecursively(final CodegenProperty codegenProperty) { } } - - private boolean isEnum(CodegenProperty codegenProperty) { return enumProcessorFactory.isEnum(codegenProperty); } diff --git a/src/main/java/com/twilio/oai/java/processor/responsebody/JsonResponseProcessor.java b/src/main/java/com/twilio/oai/java/processor/responsebody/JsonResponseProcessor.java index 56cba625c..b0e4a3671 100644 --- a/src/main/java/com/twilio/oai/java/processor/responsebody/JsonResponseProcessor.java +++ b/src/main/java/com/twilio/oai/java/processor/responsebody/JsonResponseProcessor.java @@ -79,6 +79,7 @@ private CodegenModel getModel(final CodegenOperation codegenOperation) { // TODO: Handle in future. } String ref = codegenMediaType.getSchema().getRef(); + if (ref == null) return null; CodegenModel model = Utility.getModelFromRef(ref); return model; diff --git a/src/main/resources/twilio-java-modern/allConstructors.mustache b/src/main/resources/twilio-java-modern/allConstructors.mustache new file mode 100644 index 000000000..2ac4ec1f7 --- /dev/null +++ b/src/main/resources/twilio-java-modern/allConstructors.mustache @@ -0,0 +1,64 @@ + +{{#operations}} +{{#vendorExtensions.x-create-operation}} +{{#vendorExtensions.x-signature-list}} + + public static {{resourceName}}Creator creator({{#.}}final {{{dataType}}} {{paramName}}{{^-last}}, {{/-last}}{{/.}}) { + return new {{resourceName}}Creator( + {{#.}} {{paramName}}{{^-last}}, {{/-last}}{{/.}} + ); + } + +{{/vendorExtensions.x-signature-list}} +{{/vendorExtensions.x-create-operation}} + + +{{#vendorExtensions.x-delete-operation}} +{{#vendorExtensions.x-signature-list}} + + public static {{resourceName}}Deleter deleter({{#.}}final {{{dataType}}} {{paramName}}{{^-last}}, {{/-last}}{{/.}}) { + return new {{resourceName}}Deleter( + {{#.}} {{paramName}}{{^-last}}, {{/-last}}{{/.}} + ); + } + +{{/vendorExtensions.x-signature-list}} +{{/vendorExtensions.x-delete-operation}} + +{{#vendorExtensions.x-fetch-operation}} +{{#vendorExtensions.x-signature-list}} + + public static {{resourceName}}Fetcher fetcher({{#.}}final {{{dataType}}} {{paramName}}{{^-last}}, {{/-last}}{{/.}}) { + return new {{resourceName}}Fetcher( + {{#.}} {{paramName}}{{^-last}}, {{/-last}}{{/.}} + ); + } + +{{/vendorExtensions.x-signature-list}} +{{/vendorExtensions.x-fetch-operation}} + +{{#vendorExtensions.x-list-operation}} +{{#vendorExtensions.x-signature-list}} + + public static {{resourceName}}Reader reader({{#.}}final {{{dataType}}} {{paramName}}{{^-last}}, {{/-last}}{{/.}}) { + return new {{resourceName}}Reader( + {{#.}} {{paramName}}{{^-last}}, {{/-last}}{{/.}} + ); + } + +{{/vendorExtensions.x-signature-list}} +{{/vendorExtensions.x-list-operation}} + +{{#vendorExtensions.x-update-operation}} +{{#vendorExtensions.x-signature-list}} + + public {{resourceName}}Updater updater({{#.}}final {{{dataType}}} {{paramName}}{{^-last}}, {{/-last}}{{/.}}) { + return new {{resourceName}}Updater( + {{#.}} {{paramName}}{{^-last}}, {{/-last}}{{/.}} + ); + } + +{{/vendorExtensions.x-signature-list}} +{{/vendorExtensions.x-update-operation}} + +{{/operations}} diff --git a/src/main/resources/twilio-java-modern/api.mustache b/src/main/resources/twilio-java-modern/api.mustache index 1a9b41991..f38a63e80 100644 --- a/src/main/resources/twilio-java-modern/api.mustache +++ b/src/main/resources/twilio-java-modern/api.mustache @@ -1,14 +1,17 @@ {{>licenseInfo}} -{{#imports}} -import {{import}}; -{{/imports}} -import com.twilio.constant.EnumConstants.ParameterType; {{#resources}} +package com.twilio.rest.{{domainPackage}}.{{apiVersion}}{{namespaceSubPart}}; + +{{>common/imports}} +import com.twilio.base.Resource; +import java.io.IOException; +import com.fasterxml.jackson.core.JsonParseException; @JsonIgnoreProperties(ignoreUnknown = true) @ToString public class {{resourceName}} extends Resource { +{{>allConstructors}} {{>enums}} {{>models}} {{>staticMethods}} diff --git a/src/main/resources/twilio-java-modern/common/addHeaderParams.mustache b/src/main/resources/twilio-java-modern/common/addHeaderParams.mustache index 0d42baee3..50105e54d 100644 --- a/src/main/resources/twilio-java-modern/common/addHeaderParams.mustache +++ b/src/main/resources/twilio-java-modern/common/addHeaderParams.mustache @@ -5,7 +5,7 @@ private void addHeaderParams(final Request request) { {{^isArray}} {{^vendorExtensions.x-inequality-main}} if ({{paramName}} != null) { - Serializer.toString(request, "{{baseName}}", param, ParameterType.HEADER); + Serializer.toString(request, "{{{baseName}}}", {{paramName}}, ParameterType.HEADER); } {{/vendorExtensions.x-inequality-main}} {{/isArray}} @@ -13,7 +13,7 @@ private void addHeaderParams(final Request request) { {{#isArray}} if ({{paramName}} != null) { for ({{baseType}} param: {{paramName}}) { - Serializer.toString(request, "{{baseName}}", param, ParameterType.HEADER); + Serializer.toString(request, "{{{baseName}}}", param, ParameterType.HEADER); } } {{/isArray}} diff --git a/src/main/resources/twilio-java-modern/common/addPostParams.mustache b/src/main/resources/twilio-java-modern/common/addPostParams.mustache index 1d1277432..cbd1705b6 100644 --- a/src/main/resources/twilio-java-modern/common/addPostParams.mustache +++ b/src/main/resources/twilio-java-modern/common/addPostParams.mustache @@ -5,7 +5,7 @@ private void addPostParams(final Request request) { {{^isArray}} {{^vendorExtensions.x-inequality-main}} if ({{paramName}} != null) { - Serializer.toString(request, "{{baseName}}", param, ParameterType.URLENCODED); + Serializer.toString(request, "{{{baseName}}}", {{paramName}}, ParameterType.URLENCODED); } {{/vendorExtensions.x-inequality-main}} {{/isArray}} @@ -14,7 +14,7 @@ private void addPostParams(final Request request) { {{#isArray}} if ({{paramName}} != null) { for ({{baseType}} param: {{paramName}}) { - Serializer.toString(request, "{{baseName}}", param, ParameterType.URLENCODED); + Serializer.toString(request, "{{{baseName}}}", param, ParameterType.URLENCODED); } } {{/isArray}} diff --git a/src/main/resources/twilio-java-modern/common/addQueryParams.mustache b/src/main/resources/twilio-java-modern/common/addQueryParams.mustache index 62586cabe..857f55571 100644 --- a/src/main/resources/twilio-java-modern/common/addQueryParams.mustache +++ b/src/main/resources/twilio-java-modern/common/addQueryParams.mustache @@ -7,7 +7,7 @@ private void addQueryParams(final Request request) { {{^isArray}} {{^vendorExtensions.x-inequality-main}} if ({{paramName}} != null) { - Serializer.toString(request, "{{baseName}}", {{paramName}}, ParameterType.QUERY); + Serializer.toString(request, "{{{baseName}}}", {{paramName}}, ParameterType.QUERY); } {{/vendorExtensions.x-inequality-main}} {{/isArray}} @@ -17,7 +17,7 @@ private void addQueryParams(final Request request) { {{^isArray}} {{#vendorExtensions.x-inequality-main}} if ({{paramName}} != null) { - Serializer.toString(request, "{{baseName}}", {{paramName}}, {{paramName}}Before, {{paramName}}After); + Serializer.toString(request, "{{{baseName}}}", {{paramName}}, {{paramName}}Before, {{paramName}}After); } {{/vendorExtensions.x-inequality-main}} {{/isArray}} @@ -26,7 +26,7 @@ private void addQueryParams(final Request request) { {{#isArray}} if ({{paramName}} != null) { for ({{baseType}} param: {{paramName}}) { - Serializer.toString(request, "{{baseName}}", param, ParameterType.QUERY); + Serializer.toString(request, "{{{baseName}}}", param, ParameterType.QUERY); } } {{/isArray}} diff --git a/src/main/resources/twilio-java-modern/common/imports.mustache b/src/main/resources/twilio-java-modern/common/imports.mustache new file mode 100644 index 000000000..90bcdcc3b --- /dev/null +++ b/src/main/resources/twilio-java-modern/common/imports.mustache @@ -0,0 +1,54 @@ +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.JsonMappingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; + +import com.twilio.base.Creator; +import com.twilio.base.Deleter; +import com.twilio.base.Fetcher; +import com.twilio.base.Reader; +import com.twilio.base.Updater; +import com.twilio.constant.EnumConstants; +import com.twilio.constant.EnumConstants.ParameterType; +import com.twilio.converter.Promoter; +import com.twilio.converter.Serializer; +import com.twilio.exception.ApiConnectionException; +import com.twilio.exception.ApiException; +import com.twilio.exception.RestException; +import com.twilio.http.HttpMethod; +import com.twilio.http.Request; +import com.twilio.http.Response; +import com.twilio.http.TwilioRestClient; +import com.twilio.rest.Domains; +import com.twilio.type.FeedbackIssue; +import com.twilio.type.IceServer; +import com.twilio.type.InboundCallPrice; +import com.twilio.type.InboundSmsPrice; +import com.twilio.type.OutboundCallPrice; +import com.twilio.type.OutboundCallPriceWithOrigin; +import com.twilio.type.OutboundPrefixPrice; +import com.twilio.type.OutboundPrefixPriceWithOrigin; +import com.twilio.type.OutboundSmsPrice; +import com.twilio.type.PhoneNumberCapabilities; +import com.twilio.type.PhoneNumberPrice; +import com.twilio.type.RecordingRule; +import com.twilio.type.SubscribeRule; +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; + +import java.io.InputStream; +import java.math.BigDecimal; +import java.net.URI; +import java.time.LocalDate; +import java.time.ZonedDateTime; +import java.util.Currency; +import java.util.List; +import java.util.Map; +import com.twilio.type.*; +import java.util.Objects; +import com.twilio.base.Resource; +import java.io.IOException; +import com.fasterxml.jackson.core.JsonParseException; \ No newline at end of file diff --git a/src/main/resources/twilio-java-modern/creator.mustache b/src/main/resources/twilio-java-modern/creator.mustache index 1bab4b4ec..7b46f64b9 100644 --- a/src/main/resources/twilio-java-modern/creator.mustache +++ b/src/main/resources/twilio-java-modern/creator.mustache @@ -1,18 +1,17 @@ {{>licenseInfo}} -{{#imports}} -import {{import}}; -{{/imports}} -import com.twilio.constant.EnumConstants.ParameterType; - {{#resources}} +package com.twilio.rest.{{domainPackage}}.{{apiVersion}}{{namespaceSubPart}}; + +{{>common/imports}} + {{#operations}} {{#vendorExtensions.x-create-operation}} public class {{resourceName}}Creator extends Creator<{{resourceName}}> { {{>common/instanceVariables}} {{>common/constructors}} -{{>common/setters}} -{{>common/operationMethod}} +{{>creator/setters}} +{{>creator/operationMethod}} {{#queryParams.0}} {{>common/addQueryParams}} {{/queryParams.0}} diff --git a/src/main/resources/twilio-java-modern/creator/operationMethod.mustache b/src/main/resources/twilio-java-modern/creator/operationMethod.mustache new file mode 100644 index 000000000..c518e5cba --- /dev/null +++ b/src/main/resources/twilio-java-modern/creator/operationMethod.mustache @@ -0,0 +1,51 @@ +{{! +resourceName: Api Name as identified by Directory Structure service +x-common-action-method: used to define operation method and can have values: create, read, update, delete, fetch + Example: https://github.com/twilio/twilio-java/blob/9c2ba4dbc185c5576e67fbeb82ec6f4899093e79/src/main/java/com/twilio/rest/api/v2010/account/MessageCreator.java#L309 + +httpMethod: http method associated in the current operation. +domainName: example api, video, chat, etc. These can be found in Domains.java in twilio-java +vendorExtensions.x-content-type: content type of the request, example: application/json, application/x-www-form-urlencoded +}} + @Override + public {{resourceName}} {{vendorExtensions.x-common-action-method}}(final TwilioRestClient client) { + {{>common/generateUri}} + + Request request = new Request( + HttpMethod.{{httpMethod}}, + Domains.{{#lambda.uppercase}}{{domainName}}{{/lambda.uppercase}}.toString(), + path + ); + {{#vendorExtensions.x-request-content-type}} + request.setContentType(EnumConstants.ContentType.{{vendorExtensions.x-request-content-type}}); + {{/vendorExtensions.x-request-content-type}} + {{#queryParams.0}} + addQueryParams(request); + {{/queryParams.0}} + {{#headerParams.0}} + addHeaderParams(request); + {{/headerParams.0}} + {{#formParams.0}} + addPostParams(request); + {{/formParams.0}} + {{#bodyParams.0}} + addPostParams(request, client); + {{/bodyParams.0}} + + Response response = client.request(request); + + if (response == null) { + throw new ApiConnectionException("{{resourceName}} creation failed: Unable to connect to server"); + } else if (!TwilioRestClient.SUCCESS.test(response.getStatusCode())) { + RestException restException = RestException.fromJson( + response.getStream(), + client.getObjectMapper() + ); + if (restException == null) { + throw new ApiException("Server Error, no content", response.getStatusCode()); + } + throw new ApiException(restException); + } + + return {{resourceName}}.fromJson(response.getStream(), client.getObjectMapper()); + } \ No newline at end of file diff --git a/src/main/resources/twilio-java-modern/creator/setters.mustache b/src/main/resources/twilio-java-modern/creator/setters.mustache new file mode 100644 index 000000000..841e0e79d --- /dev/null +++ b/src/main/resources/twilio-java-modern/creator/setters.mustache @@ -0,0 +1,20 @@ +{{#vendorExtensions.x-setter-methods}} + +public {{resourceName}}Creator set{{#lambda.titlecase}}{{paramName}}{{/lambda.titlecase}}(final {{{dataType}}} {{paramName}}){ + this.{{paramName}} = {{paramName}}; + return this; +} + +{{! Optional setter-- Ideally this shouldn't exists, keeping it for backward compatibility }} +{{#isArray}} +public {{resourceName}}Creator set{{#lambda.titlecase}}{{paramName}}{{/lambda.titlecase}}(final {{{baseType}}} {{paramName}}){ + return set{{#lambda.titlecase}}{{paramName}}{{/lambda.titlecase}}(Promoter.listOfOne({{paramName}})); +} +{{/isArray}} +{{! Optional setter, vendorExtensions.x-promotion stores promotion method}} +{{#vendorExtensions.x-promotion}} +public {{resourceName}}Creator set{{#lambda.titlecase}}{{paramName}}{{/lambda.titlecase}}(final String {{paramName}}){ + return set{{#lambda.titlecase}}{{paramName}}{{/lambda.titlecase}}({{vendorExtensions.x-promotion}}); +} +{{/vendorExtensions.x-promotion}} +{{/vendorExtensions.x-setter-methods}} \ No newline at end of file diff --git a/src/main/resources/twilio-java-modern/deleter.mustache b/src/main/resources/twilio-java-modern/deleter.mustache index 1db4469ee..e4cdeb330 100644 --- a/src/main/resources/twilio-java-modern/deleter.mustache +++ b/src/main/resources/twilio-java-modern/deleter.mustache @@ -1,18 +1,16 @@ {{>licenseInfo}} -{{#imports}} -import {{import}}; -{{/imports}} -import com.twilio.constant.EnumConstants.ParameterType; - {{#resources}} +package com.twilio.rest.{{domainPackage}}.{{apiVersion}}{{namespaceSubPart}}; +{{>common/imports}} + {{#operations}} {{#vendorExtensions.x-delete-operation}} public class {{resourceName}}Deleter extends Deleter<{{resourceName}}> { {{>common/instanceVariables}} {{>common/constructors}} - {{>common/setters}} - {{>common/operationMethod}} + {{>deleter/setters}} + {{>deleter/operationMethod}} {{#queryParams.0}} {{>common/addQueryParams}} {{/queryParams.0}} diff --git a/src/main/resources/twilio-java-modern/deleter/operationMethod.mustache b/src/main/resources/twilio-java-modern/deleter/operationMethod.mustache new file mode 100644 index 000000000..e8a2e85f1 --- /dev/null +++ b/src/main/resources/twilio-java-modern/deleter/operationMethod.mustache @@ -0,0 +1,44 @@ +{{! +resourceName: Api Name as identified by Directory Structure service +x-common-action-method: used to define operation method and can have values: create, read, update, delete, fetch + Example: https://github.com/twilio/twilio-java/blob/9c2ba4dbc185c5576e67fbeb82ec6f4899093e79/src/main/java/com/twilio/rest/api/v2010/account/MessageCreator.java#L309 + +httpMethod: http method associated in the current operation. +domainName: example api, video, chat, etc. These can be found in Domains.java in twilio-java +vendorExtensions.x-content-type: content type of the request, example: application/json, application/x-www-form-urlencoded +}} + @Override + public boolean delete(final TwilioRestClient client) { + {{>common/generateUri}} + + Request request = new Request( + HttpMethod.{{httpMethod}}, + Domains.{{#lambda.uppercase}}{{domainName}}{{/lambda.uppercase}}.toString(), + path + ); + {{#vendorExtensions.x-request-content-type}} + request.setContentType(EnumConstants.ContentType.{{vendorExtensions.x-request-content-type}}); + {{/vendorExtensions.x-request-content-type}} + {{#queryParams.0}} + addQueryParams(request); + {{/queryParams.0}} + {{#headerParams.0}} + addHeaderParams(request); + {{/headerParams.0}} + + Response response = client.request(request); + + if (response == null) { + throw new ApiConnectionException("{{resourceName}} delete failed: Unable to connect to server"); + } else if (!TwilioRestClient.SUCCESS.test(response.getStatusCode())) { + RestException restException = RestException.fromJson( + response.getStream(), + client.getObjectMapper() + ); + if (restException == null) { + throw new ApiException("Server Error, no content", response.getStatusCode()); + } + throw new ApiException(restException); + } + return response.getStatusCode() == 204; + } \ No newline at end of file diff --git a/src/main/resources/twilio-java-modern/deleter/setters.mustache b/src/main/resources/twilio-java-modern/deleter/setters.mustache new file mode 100644 index 000000000..a40899655 --- /dev/null +++ b/src/main/resources/twilio-java-modern/deleter/setters.mustache @@ -0,0 +1,20 @@ +{{#vendorExtensions.x-setter-methods}} + +public {{resourceName}}Deleter set{{#lambda.titlecase}}{{paramName}}{{/lambda.titlecase}}(final {{{dataType}}} {{paramName}}){ + this.{{paramName}} = {{paramName}}; + return this; +} + +{{! Optional setter-- Ideally this shouldn't exists, keeping it for backward compatibility }} +{{#isArray}} +public {{resourceName}}Deleter set{{#lambda.titlecase}}{{paramName}}{{/lambda.titlecase}}(final {{{baseType}}} {{paramName}}){ + return set{{#lambda.titlecase}}{{paramName}}{{/lambda.titlecase}}(Promoter.listOfOne({{paramName}})); +} +{{/isArray}} +{{! Optional setter, vendorExtensions.x-promotion stores promotion method}} +{{#vendorExtensions.x-promotion}} +public {{resourceName}}Deleter set{{#lambda.titlecase}}{{paramName}}{{/lambda.titlecase}}(final String {{paramName}}){ + return set{{#lambda.titlecase}}{{paramName}}{{/lambda.titlecase}}({{vendorExtensions.x-promotion}}); +} +{{/vendorExtensions.x-promotion}} +{{/vendorExtensions.x-setter-methods}} \ No newline at end of file diff --git a/src/main/resources/twilio-java-modern/enums.mustache b/src/main/resources/twilio-java-modern/enums.mustache index df814c378..6e13ae918 100644 --- a/src/main/resources/twilio-java-modern/enums.mustache +++ b/src/main/resources/twilio-java-modern/enums.mustache @@ -1,7 +1,7 @@ {{#mustacheEnums}} public enum {{className}} { {{#enumValues}} - {{name}}({{{value}}}){{^-last}},{{/-last}} + {{name}}({{{value}}}){{^-last}},{{/-last}}{{#-last}};{{/-last}} {{/enumValues}} private final String value; diff --git a/src/main/resources/twilio-java-modern/equalsAndHashcode.mustache b/src/main/resources/twilio-java-modern/equalsAndHashcode.mustache new file mode 100644 index 000000000..88548827b --- /dev/null +++ b/src/main/resources/twilio-java-modern/equalsAndHashcode.mustache @@ -0,0 +1,26 @@ +@Override +public boolean equals(final Object o) { + if (this == o) { + return true; + } + + if (o == null || getClass() != o.getClass()) { + return false; + } + + {{resourceName}} other = ({{resourceName}}) o; + return ( + {{#response}} + Objects.equals({{name}}, other.{{name}}){{^-last}} && {{/-last}} + {{/response}} + ); +} + +@Override +public int hashCode() { + return Objects.hash( + {{#response}} + {{name}}{{^-last}}, {{/-last}} + {{/response}} + ); +} diff --git a/src/main/resources/twilio-java-modern/fetcher.mustache b/src/main/resources/twilio-java-modern/fetcher.mustache index dd34200af..1c0280c97 100644 --- a/src/main/resources/twilio-java-modern/fetcher.mustache +++ b/src/main/resources/twilio-java-modern/fetcher.mustache @@ -1,18 +1,16 @@ {{>licenseInfo}} -{{#imports}} -import {{import}}; -{{/imports}} -import com.twilio.constant.EnumConstants.ParameterType; - {{#resources}} +package com.twilio.rest.{{domainPackage}}.{{apiVersion}}{{namespaceSubPart}}; +{{>common/imports}} + {{#operations}} {{#vendorExtensions.x-fetch-operation}} public class {{resourceName}}Fetcher extends Fetcher<{{resourceName}}> { {{>common/instanceVariables}} {{>common/constructors}} - {{>common/setters}} - {{>common/operationMethod}} + {{>fetcher/setters}} + {{>fetcher/operationMethod}} {{#queryParams.0}} {{>common/addQueryParams}} {{/queryParams.0}} diff --git a/src/main/resources/twilio-java-modern/fetcher/operationMethod.mustache b/src/main/resources/twilio-java-modern/fetcher/operationMethod.mustache new file mode 100644 index 000000000..caaee3b13 --- /dev/null +++ b/src/main/resources/twilio-java-modern/fetcher/operationMethod.mustache @@ -0,0 +1,44 @@ +{{! +resourceName: Api Name as identified by Directory Structure service +x-common-action-method: used to define operation method and can have values: create, read, update, delete, fetch + Example: https://github.com/twilio/twilio-java/blob/9c2ba4dbc185c5576e67fbeb82ec6f4899093e79/src/main/java/com/twilio/rest/api/v2010/account/MessageCreator.java#L309 + +httpMethod: http method associated in the current operation. +domainName: example api, video, chat, etc. These can be found in Domains.java in twilio-java +vendorExtensions.x-content-type: content type of the request, example: application/json, application/x-www-form-urlencoded +}} + @Override + public {{resourceName}} fetch(final TwilioRestClient client) { + {{>common/generateUri}} + + Request request = new Request( + HttpMethod.{{httpMethod}}, + Domains.{{#lambda.uppercase}}{{domainName}}{{/lambda.uppercase}}.toString(), + path + ); + {{#vendorExtensions.x-request-content-type}} + request.setContentType(EnumConstants.ContentType.{{vendorExtensions.x-request-content-type}}); + {{/vendorExtensions.x-request-content-type}} + {{#queryParams.0}} + addQueryParams(request); + {{/queryParams.0}} + {{#headerParams.0}} + addHeaderParams(request); + {{/headerParams.0}} + + Response response = client.request(request); + + if (response == null) { + throw new ApiConnectionException("{{resourceName}} fetch failed: Unable to connect to server"); + } else if (!TwilioRestClient.SUCCESS.test(response.getStatusCode())) { + RestException restException = RestException.fromJson( + response.getStream(), + client.getObjectMapper() + ); + if (restException == null) { + throw new ApiException("Server Error, no content", response.getStatusCode()); + } + throw new ApiException(restException); + } + return {{resourceName}}.fromJson(response.getStream(), client.getObjectMapper()); + } \ No newline at end of file diff --git a/src/main/resources/twilio-java-modern/fetcher/setters.mustache b/src/main/resources/twilio-java-modern/fetcher/setters.mustache new file mode 100644 index 000000000..f7134c7d3 --- /dev/null +++ b/src/main/resources/twilio-java-modern/fetcher/setters.mustache @@ -0,0 +1,20 @@ +{{#vendorExtensions.x-setter-methods}} + +public {{resourceName}}Fetcher set{{#lambda.titlecase}}{{paramName}}{{/lambda.titlecase}}(final {{{dataType}}} {{paramName}}){ + this.{{paramName}} = {{paramName}}; + return this; +} + +{{! Optional setter-- Ideally this shouldn't exists, keeping it for backward compatibility }} +{{#isArray}} +public {{resourceName}}Fetcher set{{#lambda.titlecase}}{{paramName}}{{/lambda.titlecase}}(final {{{baseType}}} {{paramName}}){ + return set{{#lambda.titlecase}}{{paramName}}{{/lambda.titlecase}}(Promoter.listOfOne({{paramName}})); +} +{{/isArray}} +{{! Optional setter, vendorExtensions.x-promotion stores promotion method}} +{{#vendorExtensions.x-promotion}} +public {{resourceName}}Fetcher set{{#lambda.titlecase}}{{paramName}}{{/lambda.titlecase}}(final String {{paramName}}){ + return set{{#lambda.titlecase}}{{paramName}}{{/lambda.titlecase}}({{vendorExtensions.x-promotion}}); +} +{{/vendorExtensions.x-promotion}} +{{/vendorExtensions.x-setter-methods}} \ No newline at end of file diff --git a/src/main/resources/twilio-java-modern/reader.mustache b/src/main/resources/twilio-java-modern/reader.mustache index a5fbdc761..74ae0f226 100644 --- a/src/main/resources/twilio-java-modern/reader.mustache +++ b/src/main/resources/twilio-java-modern/reader.mustache @@ -1,17 +1,17 @@ {{>licenseInfo}} -{{#imports}} -import {{import}}; -{{/imports}} -import com.twilio.constant.EnumConstants.ParameterType; - {{#resources}} +package com.twilio.rest.{{domainPackage}}.{{apiVersion}}{{namespaceSubPart}}; +{{>common/imports}} +import com.twilio.base.Page; +import com.twilio.base.ResourceSet; + {{#operations}} -{{#vendorExtensions.x-fetch-operation}} -public class {{resourceName}}Reader extends Fetcher<{{resourceName}}> { +{{#vendorExtensions.x-list-operation}} +public class {{resourceName}}Reader extends Reader<{{resourceName}}> { {{>common/instanceVariables}} {{>common/constructors}} - {{>common/setters}} + {{>reader/setters}} {{>reader/operationMethod}} {{#queryParams.0}} {{>common/addQueryParams}} @@ -20,6 +20,6 @@ public class {{resourceName}}Reader extends Fetcher<{{resourceName}}> { {{>common/addHeaderParams}} {{/headerParams.0}} } -{{/vendorExtensions.x-fetch-operation}} +{{/vendorExtensions.x-list-operation}} {{/operations}} {{/resources}} \ No newline at end of file diff --git a/src/main/resources/twilio-java-modern/reader/operationMethod.mustache b/src/main/resources/twilio-java-modern/reader/operationMethod.mustache index 521d95943..5acc99074 100644 --- a/src/main/resources/twilio-java-modern/reader/operationMethod.mustache +++ b/src/main/resources/twilio-java-modern/reader/operationMethod.mustache @@ -29,7 +29,7 @@ domainName: example api, video, chat, etc. These can be found in Domains.java in private Page<{{resourceName}}> pageForRequest(final TwilioRestClient client, final Request request) { Response response = client.request(request); if (response == null) { - throw new ApiConnectionException("{{resourceName}} creation failed: Unable to connect to server"); + throw new ApiConnectionException("{{resourceName}} read failed: Unable to connect to server"); } else if (!TwilioRestClient.SUCCESS.test(response.getStatusCode())) { RestException restException = RestException.fromJson( response.getStream(), @@ -46,4 +46,22 @@ domainName: example api, video, chat, etc. These can be found in Domains.java in response.getContent(), {{resourceName}}.class, client.getObjectMapper()); + } + + @Override + public Page<{{resourceName}}> previousPage(final Page<{{resourceName}}> page, final TwilioRestClient client ) { + Request request = new Request(HttpMethod.GET, page.getPreviousPageUrl(Domains.API.toString())); + return pageForRequest(client, request); + } + + @Override + public Page<{{resourceName}}> nextPage(final Page<{{resourceName}}> page, final TwilioRestClient client) { + Request request = new Request(HttpMethod.GET, page.getNextPageUrl(Domains.API.toString())); + return pageForRequest(client, request); + } + + @Override + public Page<{{resourceName}}> getPage(final String targetUrl, final TwilioRestClient client) { + Request request = new Request(HttpMethod.GET, targetUrl); + return pageForRequest(client, request); } \ No newline at end of file diff --git a/src/main/resources/twilio-java-modern/reader/paginationMethods.mustache b/src/main/resources/twilio-java-modern/reader/paginationMethods.mustache new file mode 100644 index 000000000..e69de29bb diff --git a/src/main/resources/twilio-java-modern/reader/setters.mustache b/src/main/resources/twilio-java-modern/reader/setters.mustache new file mode 100644 index 000000000..749017bbd --- /dev/null +++ b/src/main/resources/twilio-java-modern/reader/setters.mustache @@ -0,0 +1,20 @@ +{{#vendorExtensions.x-setter-methods}} + +public {{resourceName}}Reader set{{#lambda.titlecase}}{{paramName}}{{/lambda.titlecase}}(final {{{dataType}}} {{paramName}}){ + this.{{paramName}} = {{paramName}}; + return this; +} + +{{! Optional setter-- Ideally this shouldn't exists, keeping it for backward compatibility }} +{{#isArray}} +public {{resourceName}}Reader set{{#lambda.titlecase}}{{paramName}}{{/lambda.titlecase}}(final {{{baseType}}} {{paramName}}){ + return set{{#lambda.titlecase}}{{paramName}}{{/lambda.titlecase}}(Promoter.listOfOne({{paramName}})); +} +{{/isArray}} +{{! Optional setter, vendorExtensions.x-promotion stores promotion method}} +{{#vendorExtensions.x-promotion}} +public {{resourceName}}Reader set{{#lambda.titlecase}}{{paramName}}{{/lambda.titlecase}}(final String {{paramName}}){ + return set{{#lambda.titlecase}}{{paramName}}{{/lambda.titlecase}}({{vendorExtensions.x-promotion}}); +} +{{/vendorExtensions.x-promotion}} +{{/vendorExtensions.x-setter-methods}} \ No newline at end of file diff --git a/src/main/resources/twilio-java-modern/response.mustache b/src/main/resources/twilio-java-modern/response.mustache index ac2e1d034..e13bb653c 100644 --- a/src/main/resources/twilio-java-modern/response.mustache +++ b/src/main/resources/twilio-java-modern/response.mustache @@ -1,8 +1,42 @@ +{{! -- Instance variables}} +{{#responseFlag}} + + {{#response}} @Getter + private final {{{dataType}}} {{name}}; +{{/response}} + +{{! -- Private Constructor}} +@JsonCreator +private {{resourceName}}( +{{#response}} @JsonProperty("{{baseName}}") {{#vendorExtensions.x-deserializer}} - @JsonDeserialize(using = {{vendorExtensions.x-deserializer}}) + @JsonDeserialize(using = {{vendorExtensions.x-deserializer}}.class) {{/vendorExtensions.x-deserializer}} - private final {{{dataType}}} {{name}}; -{{/response}} \ No newline at end of file + final {{{dataType}}} {{name}}{{^-last}}, {{/-last}} +{{/response}} +){ +{{#response}} + this.{{name}} = {{name}}; +{{/response}} +} + +{{>equalsAndHashcode}} +{{/responseFlag}} + +{{^responseFlag}} +@JsonCreator +private {{resourceName}}() {} + +@Override +public boolean equals(Object obj) { + return obj != null && obj.getClass() == this.getClass(); +} + +@Override +public int hashCode() { + return 1; +} +{{/responseFlag}} \ No newline at end of file diff --git a/src/main/resources/twilio-java-modern/staticMethods.mustache b/src/main/resources/twilio-java-modern/staticMethods.mustache index 6619ad96e..903f7fc14 100644 --- a/src/main/resources/twilio-java-modern/staticMethods.mustache +++ b/src/main/resources/twilio-java-modern/staticMethods.mustache @@ -5,7 +5,7 @@ * @param objectMapper Jackson ObjectMapper * @return {{resourceName}} object represented by the provided JSON */ - public static {{apiName}} fromJson(final String json, final ObjectMapper objectMapper) { + public static {{resourceName}} fromJson(final String json, final ObjectMapper objectMapper) { // Convert all checked exceptions to Runtime try { return objectMapper.readValue(json, {{resourceName}}.class); diff --git a/src/main/resources/twilio-java-modern/updater.mustache b/src/main/resources/twilio-java-modern/updater.mustache index b2606a8ae..1da336a3a 100644 --- a/src/main/resources/twilio-java-modern/updater.mustache +++ b/src/main/resources/twilio-java-modern/updater.mustache @@ -1,17 +1,15 @@ {{>licenseInfo}} -{{#imports}} -import {{import}}; -{{/imports}} -import com.twilio.constant.EnumConstants.ParameterType; - {{#resources}} +package com.twilio.rest.{{domainPackage}}.{{apiVersion}}{{namespaceSubPart}}; +{{>common/imports}} + {{#operations}} {{#vendorExtensions.x-update-operation}} public class {{resourceName}}Updater extends Updater<{{resourceName}}> { {{>common/instanceVariables}} {{>common/constructors}} - {{>common/setters}} - {{>common/operationMethod}} + {{>updater/setters}} + {{>updater/operationMethod}} {{#queryParams.0}} {{>common/addQueryParams}} {{/queryParams.0}} diff --git a/src/main/resources/twilio-java-modern/updater/operationMethod.mustache b/src/main/resources/twilio-java-modern/updater/operationMethod.mustache new file mode 100644 index 000000000..4e9d7bfb6 --- /dev/null +++ b/src/main/resources/twilio-java-modern/updater/operationMethod.mustache @@ -0,0 +1,51 @@ +{{! +resourceName: Api Name as identified by Directory Structure service +x-common-action-method: used to define operation method and can have values: create, read, update, delete, fetch + Example: https://github.com/twilio/twilio-java/blob/9c2ba4dbc185c5576e67fbeb82ec6f4899093e79/src/main/java/com/twilio/rest/api/v2010/account/MessageCreator.java#L309 + +httpMethod: http method associated in the current operation. +domainName: example api, video, chat, etc. These can be found in Domains.java in twilio-java +vendorExtensions.x-content-type: content type of the request, example: application/json, application/x-www-form-urlencoded +}} + @Override + public {{resourceName}} {{vendorExtensions.x-common-action-method}}(final TwilioRestClient client) { + {{>common/generateUri}} + + Request request = new Request( + HttpMethod.{{httpMethod}}, + Domains.{{#lambda.uppercase}}{{domainName}}{{/lambda.uppercase}}.toString(), + path + ); + {{#vendorExtensions.x-request-content-type}} + request.setContentType(EnumConstants.ContentType.{{vendorExtensions.x-request-content-type}}); + {{/vendorExtensions.x-request-content-type}} + {{#queryParams.0}} + addQueryParams(request); + {{/queryParams.0}} + {{#headerParams.0}} + addHeaderParams(request); + {{/headerParams.0}} + {{#formParams.0}} + addPostParams(request); + {{/formParams.0}} + {{#bodyParams.0}} + addPostParams(request, client); + {{/bodyParams.0}} + + Response response = client.request(request); + + if (response == null) { + throw new ApiConnectionException("{{resourceName}} update failed: Unable to connect to server"); + } else if (!TwilioRestClient.SUCCESS.test(response.getStatusCode())) { + RestException restException = RestException.fromJson( + response.getStream(), + client.getObjectMapper() + ); + if (restException == null) { + throw new ApiException("Server Error, no content", response.getStatusCode()); + } + throw new ApiException(restException); + } + + return {{resourceName}}.fromJson(response.getStream(), client.getObjectMapper()); + } \ No newline at end of file diff --git a/src/main/resources/twilio-java-modern/updater/setters.mustache b/src/main/resources/twilio-java-modern/updater/setters.mustache new file mode 100644 index 000000000..fe89a495b --- /dev/null +++ b/src/main/resources/twilio-java-modern/updater/setters.mustache @@ -0,0 +1,20 @@ +{{#vendorExtensions.x-setter-methods}} + +public {{resourceName}}Updater set{{#lambda.titlecase}}{{paramName}}{{/lambda.titlecase}}(final {{{dataType}}} {{paramName}}){ + this.{{paramName}} = {{paramName}}; + return this; +} + +{{! Optional setter-- Ideally this shouldn't exists, keeping it for backward compatibility }} +{{#isArray}} +public {{resourceName}}Updater set{{#lambda.titlecase}}{{paramName}}{{/lambda.titlecase}}(final {{{baseType}}} {{paramName}}){ + return set{{#lambda.titlecase}}{{paramName}}{{/lambda.titlecase}}(Promoter.listOfOne({{paramName}})); +} +{{/isArray}} +{{! Optional setter, vendorExtensions.x-promotion stores promotion method}} +{{#vendorExtensions.x-promotion}} +public {{resourceName}}Updater set{{#lambda.titlecase}}{{paramName}}{{/lambda.titlecase}}(final String {{paramName}}){ + return set{{#lambda.titlecase}}{{paramName}}{{/lambda.titlecase}}({{vendorExtensions.x-promotion}}); +} +{{/vendorExtensions.x-promotion}} +{{/vendorExtensions.x-setter-methods}} \ No newline at end of file diff --git a/src/main/resources/twilio-python/api-single.mustache b/src/main/resources/twilio-python/api-single.mustache index b95cea015..ae8ce0f37 100644 --- a/src/main/resources/twilio-python/api-single.mustache +++ b/src/main/resources/twilio-python/api-single.mustache @@ -1,7 +1,6 @@ {{>licenseInfo}} {{#resources}} from datetime import date, datetime -from decimal import Decimal from typing import Any, Dict, List, Optional, Union, Iterator, AsyncIterator from twilio.base import deserialize, serialize, values {{#instancePath}}from twilio.base.instance_context import InstanceContext{{/instancePath}} diff --git a/src/test/java/com/twilio/oai/TwilioGeneratorTest.java b/src/test/java/com/twilio/oai/TwilioGeneratorTest.java index 2c57dd829..a44b23aee 100644 --- a/src/test/java/com/twilio/oai/TwilioGeneratorTest.java +++ b/src/test/java/com/twilio/oai/TwilioGeneratorTest.java @@ -40,8 +40,9 @@ public static void setUp() { @Test public void launchGenerator() { - //final String pathname = "examples/spec/twilio_api_v2010.yaml"; - final String pathname = "examples/test_spec/twilio_testenum_v1.yaml"; + final String pathname = "examples/spec/twilio_api_v2010.yaml"; + //final String pathname = "examples/test_spec/twilio_testenum_v1.yaml"; + //final String pathname = "/Users/sbansla/Documents/code/twilio-oai/spec/yaml/twilio_content_v1.yaml"; File filesList[] ; File directoryPath = new File(pathname); if (directoryPath.isDirectory()) { @@ -54,7 +55,7 @@ public void launchGenerator() { .setGeneratorName(generator.getValue()) .setInputSpec(file.getPath()) .setOutputDir("codegen/" + generator.getValue()) - .setInlineSchemaNameDefaults(Map.of("arrayItemSuffix", "")) + //.setInlineSchemaNameDefaults(Map.of("arrayItemSuffix", "")) .addGlobalProperty("apiTests", "false") .addGlobalProperty("apiDocs", "false"); final ClientOptInput clientOptInput = configurator.toClientOptInput(); From 627115997b2cb70766de53588403addbf3593c78 Mon Sep 17 00:00:00 2001 From: sbansla <104902068+sbansla@users.noreply.github.com> Date: Fri, 12 Sep 2025 12:21:22 +0530 Subject: [PATCH 15/38] chore: prepared java modern for release (#682) --- examples/test_spec/twilio_datamodels_v1.yaml | 212 ++++++++++++++++++ examples/test_spec/twilio_oneOf_v1.yaml | 110 +++++++++ .../twilio/oai/TwilioJavaGeneratorModern.java | 22 +- .../com/twilio/oai/common/EnumConstants.java | 1 + .../java/com/twilio/oai/common/Utility.java | 11 +- .../com/twilio/oai/java/JavaApiResource.java | 9 +- .../oai/java/JavaApiResourceBuilder.java | 7 +- .../com/twilio/oai/java/ResourceCache.java | 3 +- .../twilio/oai/java/cache/ResourceCache2.java | 66 ++++++ .../oai/java/cache/ResourceCacheContext.java | 19 ++ .../twilio/oai/java/feature/Inequality.java | 2 + .../java/feature/SetterMethodGenerator.java | 6 +- .../constructor/ConstructorFactory.java | 2 +- .../constructor/ConstructorGenerator.java | 59 ++++- .../constructor/JsonConstructorGenerator.java | 79 ++++++- .../UrlencodedBodyConstructorGenerator.java | 138 ++++++------ .../java/feature/datamodels/DataModel.java | 2 +- .../feature/datamodels/DataModelManager.java | 13 +- .../oai/java/feature/datamodels/OneOf.java | 32 ++- .../java/format/JavaUpdateDefaultMapping.java | 6 + .../OpenApiSpecFormatFeatureConstants.java | 6 +- .../com/twilio/oai/java/format/Promoter.java | 7 +- .../oai/java/nestedmodels/MustacheModel.java | 20 +- .../oai/java/nestedmodels/MustacheOneOf.java | 21 ++ .../java/nestedmodels/MustacheOneOfIface.java | 15 ++ .../twilio/oai/java/processor/auth/OAuth.java | 3 - .../processor/auth/SecuritySchemeManager.java | 1 - .../auth/SecuritySchemeProcessor.java | 2 - .../body/InlineBodyEnumProcessor.java | 6 +- .../body/InlineBodyListEnumProcessor.java | 13 +- .../body/ReusableBodyEnumProcessor.java | 6 +- .../body/ReusableBodyListEnumProcessor.java | 16 +- .../param/InlineListParamEnumProcessor.java | 15 +- .../param/InlineParamEnumProcessor.java | 6 +- .../param/ReusableListParamEnumProcessor.java | 13 +- .../param/ReusableParamEnumProcessor.java | 6 +- .../property/InlineListPropEnumProcessor.java | 13 +- .../property/InlinePropEnumProcessor.java | 6 +- .../ReusableListPropEnumProcessor.java | 13 +- .../property/ReusablePropEnumProcessor.java | 6 +- .../processor/model/ListModelStrategy.java | 6 +- .../model/ModelProcessorFactory.java | 2 - .../processor/model/SingleModelStrategy.java | 6 +- .../model/parameter/ModelProcessor.java | 9 + .../parameter/ParamModelProcessorManager.java | 40 ++++ .../model/parameter/SingleModelStrategy.java | 56 +++++ .../parameter/ParameterProcessor.java | 14 ++ .../requestbody/JsonRequestProcessor.java | 55 ++++- .../requestbody/RecursiveModelProcessor.java | 43 +++- .../responsebody/JsonResponseProcessor.java | 12 +- .../allConstructors.mustache | 2 +- .../common/addPostParamsJson.mustache | 8 + .../common/imports.mustache | 7 +- .../common/instanceVariables.mustache | 5 +- .../twilio-java-modern/creator.mustache | 3 + .../twilio-java-modern/models.mustache | 24 +- .../twilio-java-modern/staticMethods.mustache | 12 + .../twilio-java-modern/updater.mustache | 3 + .../com/twilio/oai/TwilioGeneratorTest.java | 2 - 59 files changed, 1119 insertions(+), 183 deletions(-) create mode 100644 examples/test_spec/twilio_datamodels_v1.yaml create mode 100644 examples/test_spec/twilio_oneOf_v1.yaml create mode 100644 src/main/java/com/twilio/oai/java/cache/ResourceCache2.java create mode 100644 src/main/java/com/twilio/oai/java/cache/ResourceCacheContext.java create mode 100644 src/main/java/com/twilio/oai/java/nestedmodels/MustacheOneOfIface.java create mode 100644 src/main/java/com/twilio/oai/java/processor/model/parameter/ModelProcessor.java create mode 100644 src/main/java/com/twilio/oai/java/processor/model/parameter/ParamModelProcessorManager.java create mode 100644 src/main/java/com/twilio/oai/java/processor/model/parameter/SingleModelStrategy.java create mode 100644 src/main/resources/twilio-java-modern/common/addPostParamsJson.mustache diff --git a/examples/test_spec/twilio_datamodels_v1.yaml b/examples/test_spec/twilio_datamodels_v1.yaml new file mode 100644 index 000000000..57eb06230 --- /dev/null +++ b/examples/test_spec/twilio_datamodels_v1.yaml @@ -0,0 +1,212 @@ +openapi: 3.1.0 +info: + title: OneOf API Examples + version: 1.0.0 +servers: + - url: https://api.twilio.com + +paths: + /v1/directOneOf: + post: + operationId: CreateDirectOneOf + summary: Direct oneOf in request body + requestBody: + required: true + content: + application/json: + schema: + oneOf: + - $ref: '#/components/schemas/Cat' + - $ref: '#/components/schemas/Dog' + responses: + '200': + description: Success + +# /v1/nestedOneOf: +# post: +# operationId: CreateNestedOneOf +# summary: Nested oneOf in request body +# requestBody: +# required: true +# content: +# application/json: +# schema: +# type: object +# properties: +# pet: +# oneOf: +# - $ref: '#/components/schemas/Cat' +# - $ref: '#/components/schemas/Dog' +# owner: +# type: string +# responses: +# '200': +# description: Success +# +# /v1/multipleNestedOneOf: +# post: +# operationId: CreateMultipleDirectOneOf +# summary: Multiple nested oneOf in request body +# requestBody: +# required: true +# content: +# application/json: +# schema: +# type: object +# properties: +# petDetails: +# type: object +# properties: +# pet: +# oneOf: +# - $ref: '#/components/schemas/Cat' +# - $ref: '#/components/schemas/Dog' +# additionalInfo: +# oneOf: +# - $ref: '#/components/schemas/One' +# - $ref: '#/components/schemas/Two' +# owner: +# type: string +# responses: +# '200': +# description: Success +# +# /v1/arrayOfOneOf: +# post: +# operationId: CreateArrayOfOneOf +# summary: Array of oneOf in request body +# requestBody: +# required: true +# content: +# application/json: +# schema: +# type: object +# properties: +# pets: +# type: array +# items: +# oneOf: +# - $ref: '#/components/schemas/Cat' +# - $ref: '#/components/schemas/Dog' +# responses: +# '200': +# description: Success +# /v1/parallelOneOfAndObject: +# post: +# operationId: CreateParallelOneOfAndObject +# summary: OneOf and normal object in parallel +# requestBody: +# required: true +# content: +# application/json: +# schema: +# type: object +# properties: +# pet: +# oneOf: +# - $ref: '#/components/schemas/Cat' +# - $ref: '#/components/schemas/Dog' +# owner: +# type: object +# properties: +# name: +# type: string +# age: +# type: integer +# responses: +# '200': +# description: Success +# +# /v1/oneOfWithAdditionalProperties: +# post: +# operationId: CreateOneOfWithAdditionalProperties +# summary: OneOf with additional properties +# requestBody: +# required: true +# content: +# application/json: +# schema: +# type: object +# properties: +# pet: +# oneOf: +# - $ref: '#/components/schemas/Cat' +# - $ref: '#/components/schemas/Dog' +# metadata: +# type: object +# additionalProperties: +# type: string +# responses: +# '200': +# description: Success +# +# /v1/oneOfWithRequiredFields: +# post: +# operationId: CreateOneOfWithRequiredFields +# summary: OneOf with required fields in parallel +# requestBody: +# required: true +# content: +# application/json: +# schema: +# type: object +# required: +# - pet +# - owner +# properties: +# pet: +# oneOf: +# - $ref: '#/components/schemas/Cat' +# - $ref: '#/components/schemas/Dog' +# owner: +# type: object +# properties: +# name: +# type: string +# contact: +# type: string +# responses: +# '200': +# description: Success + +components: + schemas: + Cat: + type: object + properties: + type: + type: string + enum: [cat] + name: + type: string + huntingSkill: + type: string + enum: [clueless, lazy, adventurous, aggressive] + + Dog: + type: object + properties: + type: + type: string + enum: [dog] + name: + type: string + packSize: + type: integer + minimum: 0 + + One: + type: object + properties: + param1: + type: string + param2: + type: string + + Two: + type: object + properties: + object1: + type: string + object2: + type: string \ No newline at end of file diff --git a/examples/test_spec/twilio_oneOf_v1.yaml b/examples/test_spec/twilio_oneOf_v1.yaml new file mode 100644 index 000000000..831bf8a24 --- /dev/null +++ b/examples/test_spec/twilio_oneOf_v1.yaml @@ -0,0 +1,110 @@ +openapi: 3.1.0 +info: + title: Number Pool Service + description: |- + This service is an entry point for all Number Pool CRUD requests. + version: 1.0.0 + contact: + name: 'Number Pool Service' + url: 'https://wiki.hq.twilio.com/display/MSG/Messaging+Services' + license: + name: Apache 2.0 + url: https://www.apache.org/licenses/LICENSE-2.0.html +servers: + - url: https://oneOf.twilio.com +paths: + /v1/pets: + post: + operationId: CreatePet + summary: Add a pet (cat or dog) + requestBody: + required: true + content: + application/json: + schema: +# properties: +# RecordingStatusCallback: +# format: uri +# type: string +# RecordingStatusCallbackEvent: +# items: +# type: string +# type: array + $ref: '#/components/schemas/Cat' +# title: MyPet +# oneOf: +# - $ref: '#/components/schemas/Cat' +# - $ref: '#/components/schemas/Dog' + responses: + '200': + description: Returns the created pet (cat or dog) + content: + application/json: + schema: + $ref: '#/components/schemas/Cat' +# allOf: +# - type: object +# properties: +# account_sid: +# type: string +# nullable: true +# - title: MyPet_Response +# $ref: '#/components/schemas/MyPet_Response' +# - oneOf: +# - $ref: '#/components/schemas/Cat' +# - $ref: '#/components/schemas/Dog' + +components: + schemas: + MyPet_Response: + type: object + properties: + cat: + $ref: '#/components/schemas/Cat' + dog: + $ref: '#/components/schemas/Dog' + Cat: + allOf: + - type: object + properties: + account_sid: + type: string + - oneOf: + - $ref: '#/components/schemas/One' + - $ref: '#/components/schemas/Two' +# type: +# type: string +# enum: [cat] +# name: +# type: string +# huntingSkill: +# type: string +# enum: [clueless, lazy, adventurous, aggressive] + + Dog: + type: object + properties: + type: + type: string + enum: [dog] + name: + type: string + packSize: + type: integer + minimum: 0 + One: + type: object + properties: + param1: + type: string + param2: + type: string + dog: + $ref: '#/components/schemas/Dog' + Two: + type: object + properties: + object1: + type: string + object2: + type: string diff --git a/src/main/java/com/twilio/oai/TwilioJavaGeneratorModern.java b/src/main/java/com/twilio/oai/TwilioJavaGeneratorModern.java index 602311786..efeca055d 100644 --- a/src/main/java/com/twilio/oai/TwilioJavaGeneratorModern.java +++ b/src/main/java/com/twilio/oai/TwilioJavaGeneratorModern.java @@ -7,8 +7,9 @@ import com.twilio.oai.java.JavaApiResource; import com.twilio.oai.java.JavaApiResourceBuilder; import com.twilio.oai.java.JavaTemplateUpdater; +import com.twilio.oai.java.cache.ResourceCache2; +import com.twilio.oai.java.cache.ResourceCacheContext; import com.twilio.oai.java.format.JavaUpdateDefaultMapping; -import com.twilio.oai.java.ResourceCache; import com.twilio.oai.resolver.java.JavaCaseResolver; import com.twilio.oai.resource.ResourceMap; import com.twilio.oai.templating.mustache.ReplaceHyphenLambda; @@ -27,6 +28,7 @@ public class TwilioJavaGeneratorModern extends JavaClientCodegen { + ResourceCache2 resourceCache2 = new ResourceCache2(); JavaUpdateDefaultMapping javaUpdateDefaultMapping = new JavaUpdateDefaultMapping(); private final TwilioCodegenAdapter twilioCodegen; JavaTemplateUpdater templateUpdater = new JavaTemplateUpdater(); @@ -38,6 +40,8 @@ public class TwilioJavaGeneratorModern extends JavaClientCodegen { public TwilioJavaGeneratorModern() { super(); + ResourceCacheContext.clear(); + ResourceCacheContext.set(resourceCache2); this.additionalProperties.put("serializationLibrary", "jackson"); twilioCodegen = new TwilioCodegenAdapter(this, getName()); sourceFolder = ""; @@ -52,6 +56,7 @@ public void processOpts() { this.modelTemplateFiles.clear(); javaUpdateDefaultMapping.typeMapping(this.typeMapping); javaUpdateDefaultMapping.importMapping(this.importMapping); + javaUpdateDefaultMapping.removeReservedWords(this.reservedWords); javaUpdateDefaultMapping.modelTemplateFiles(this.modelTemplateFiles); twilioCodegen.processOpts(); } @@ -72,7 +77,7 @@ public void processOpenAPI(final OpenAPI openAPI) { public String toApiFilename(final String name) { return directoryStructureService.toApiFilename(super.toApiFilename(name)); } - + // DO NOT REMOVE this method even though it is not override. @Override public String getTypeDeclaration(Schema schema) { @@ -83,9 +88,12 @@ public String getTypeDeclaration(Schema schema) { @Override public Map postProcessAllModels(final Map allModels) { final Map results = super.postProcessAllModels(allModels); - ResourceCache.clearAllModelsByDefaultGenerator(); + ResourceCache2 cache2 = ResourceCacheContext.get(); + ResourceCacheContext.set(cache2); + ResourceCacheContext.clear(); + //ResourceCache.clearAllModelsByDefaultGenerator(); // Update allModels from Default generator in ResourceCache. - Utility.addModelsToLocalModelList(results, ResourceCache.getAllModelsByDefaultGenerator()); + Utility.addModelsToLocalModelList(results, cache2.getAllModelsByDefaultGenerator()); directoryStructureService.postProcessAllModels(results, modelFormatMap); // Return an empty collection so no model files get generated. @@ -97,12 +105,13 @@ public String getSchemaType(Schema p) { String schemaType = super.getSchemaType(p); return schemaType; } - + // Run once per operation groups @Override public OperationsMap postProcessOperationsWithModels(final OperationsMap objs, List allModels) { final OperationsMap results = super.postProcessOperationsWithModels(objs, allModels); - ResourceCache.clear(); + //ResourceCache.clear(); + ResourceCacheContext.clear(); final List opList = directoryStructureService.processOperations(results); JavaApiResource apiResource = processCodegenOperations(opList); results.put("resources", apiResource); @@ -132,6 +141,7 @@ public String getHelp() { } private JavaApiResource processCodegenOperations(List operations) { + //DataModelManager.getInstance().apply(); templateUpdater.addApiTemplate(this, operations); JavaApiResource apiResource = new JavaApiResourceBuilder(this, operations) .resourceName() diff --git a/src/main/java/com/twilio/oai/common/EnumConstants.java b/src/main/java/com/twilio/oai/common/EnumConstants.java index 334c27d28..14791474a 100644 --- a/src/main/java/com/twilio/oai/common/EnumConstants.java +++ b/src/main/java/com/twilio/oai/common/EnumConstants.java @@ -11,6 +11,7 @@ public enum Generator { TWILIO_CSHARP("twilio-csharp"), TWILIO_JAVA("twilio-java"), TWILIO_JAVA_MODERN("twilio-java-modern"), + TWILIO_JAVA_TEST("twilio-java-test"), TWILIO_NODE("twilio-node"), TWILIO_PHP("twilio-php"), TWILIO_PYTHON("twilio-python"), diff --git a/src/main/java/com/twilio/oai/common/Utility.java b/src/main/java/com/twilio/oai/common/Utility.java index c99db0b66..23d99fd6b 100644 --- a/src/main/java/com/twilio/oai/common/Utility.java +++ b/src/main/java/com/twilio/oai/common/Utility.java @@ -14,7 +14,7 @@ import java.util.regex.Pattern; import java.util.stream.Collectors; -import com.twilio.oai.java.ResourceCache; +import com.twilio.oai.java.cache.ResourceCacheContext; import lombok.experimental.UtilityClass; import org.apache.commons.lang3.StringUtils; import org.openapitools.codegen.CodegenModel; @@ -207,7 +207,12 @@ public static String getEnumNameFromRef(final String ref) { $ref: '#/components/schemas/message_enum_status' */ public static String getEnumNameFromDefaultDatatype(final String ref) { + if (ref == null) return null; String schemaName = ref.replaceFirst("#/components/schemas/", ""); + if (ref.equals(schemaName)) { + // No change in schemaName + return getEnumNameFromDatatype(ref); + } String[] enumNameArray = schemaName.split("_enum_"); return enumNameArray[enumNameArray.length - 1]; } @@ -234,7 +239,7 @@ public static CodegenModel getModelFromOpenApiType(CodegenProperty codegenProper return null; } String modelClassName = codegenProperty.isContainer ? codegenProperty.items.openApiType: codegenProperty.openApiType; - for (CodegenModel codegenModel: ResourceCache.getAllModelsByDefaultGenerator()) { + for (CodegenModel codegenModel: ResourceCacheContext.get().getAllModelsByDefaultGenerator()) { if (modelClassName.equals(codegenModel.classname)) { return codegenModel; } @@ -249,7 +254,7 @@ public static void main(String[] args) { } public static CodegenModel getModelFromRef(String ref) { String schemaName = ref.replaceFirst("#/components/schemas/", ""); - List allModels = ResourceCache.getAllModelsByDefaultGenerator(); + List allModels = ResourceCacheContext.get().getAllModelsByDefaultGenerator(); for (CodegenModel model: allModels) { if (model.name.equals(schemaName)) { return model; diff --git a/src/main/java/com/twilio/oai/java/JavaApiResource.java b/src/main/java/com/twilio/oai/java/JavaApiResource.java index b8c963ba6..392dc06e8 100644 --- a/src/main/java/com/twilio/oai/java/JavaApiResource.java +++ b/src/main/java/com/twilio/oai/java/JavaApiResource.java @@ -1,5 +1,6 @@ package com.twilio.oai.java; +import com.twilio.oai.java.cache.ResourceCacheContext; import com.twilio.oai.java.nestedmodels.MustacheEnum; import com.twilio.oai.java.nestedmodels.MustacheModel; import org.openapitools.codegen.CodegenOperation; @@ -21,12 +22,12 @@ public class JavaApiResource { Boolean responseFlag = null; // true or NUll public JavaApiResource(JavaApiResourceBuilder builder) { - resourceName = ResourceCache.resourceName; + resourceName = ResourceCacheContext.get().getResourceName(); recordKey = builder.recordKey; this.operations = builder.operations; - this.mustacheEnums = new HashSet<>(ResourceCache.getEnumsClassesForMustache()); - this.mustacheModels = new HashSet<>(ResourceCache.getModelClassesForMustache()); - this.response = ResourceCache.response; + this.mustacheEnums = new HashSet<>(ResourceCacheContext.get().getEnumsClassesForMustache()); + this.mustacheModels = new HashSet<>(ResourceCacheContext.get().getModelClassesForMustache()); + this.response = ResourceCacheContext.get().getResponse(); if (response != null && !response.isEmpty()) responseFlag = true; this.namespaceSubPart = builder.namespaceSubPart; } diff --git a/src/main/java/com/twilio/oai/java/JavaApiResourceBuilder.java b/src/main/java/com/twilio/oai/java/JavaApiResourceBuilder.java index 8a0f1f4bf..3f06f3f71 100644 --- a/src/main/java/com/twilio/oai/java/JavaApiResourceBuilder.java +++ b/src/main/java/com/twilio/oai/java/JavaApiResourceBuilder.java @@ -2,6 +2,7 @@ import com.twilio.oai.TwilioJavaGeneratorModern; import com.twilio.oai.common.Utility; +import com.twilio.oai.java.cache.ResourceCacheContext; import com.twilio.oai.java.processor.JavaOperationProcessor; import org.apache.commons.lang3.StringUtils; import org.openapitools.codegen.CodegenOperation; @@ -31,19 +32,19 @@ public JavaApiResourceBuilder(TwilioJavaGeneratorModern twilioJavaGenerator, Lis // Bug: path should not end with '/' // example: /2010-04-01/Accounts.json, otherwise directory structure will not be created properly. public JavaApiResourceBuilder resourceName() { - ResourceCache.setResourceName(""); // Clear + //ResourceCacheContext.get().setResourceName(""); // Clear operations.forEach(co -> { List filePathArray = new ArrayList<>(Arrays.asList(co.baseName.split(PATH_SEPARATOR_PLACEHOLDER))); if (!filePathArray.isEmpty() && StringUtils.isNotBlank(filePathArray.get(filePathArray.size() - 1))) { resourceName = filePathArray.get(filePathArray.size() - 1); } }); - ResourceCache.setResourceName(resourceName); + ResourceCacheContext.get().setResourceName(resourceName); return this; } public JavaApiResourceBuilder recordKey() { - this.recordKey = Utility.getRecordKey(ResourceCache.allModelsByDefaultGenerator, operations); + this.recordKey = Utility.getRecordKey(ResourceCacheContext.get().getAllModelsByDefaultGenerator(), operations); return this; } diff --git a/src/main/java/com/twilio/oai/java/ResourceCache.java b/src/main/java/com/twilio/oai/java/ResourceCache.java index 76b13b064..b5f9f5519 100644 --- a/src/main/java/com/twilio/oai/java/ResourceCache.java +++ b/src/main/java/com/twilio/oai/java/ResourceCache.java @@ -1,7 +1,7 @@ package com.twilio.oai.java; import com.twilio.oai.java.nestedmodels.MustacheEnum; -import com.twilio.oai.java.nestedmodels.MustacheModel; +import com.twilio.oai.java.nestedmodels.MustacheModel;; import lombok.Getter; import lombok.Setter; import org.openapitools.codegen.CodegenModel; @@ -26,6 +26,7 @@ public class ResourceCache { public static List allModelsByDefaultGenerator = new ArrayList<>(); @Getter public static Set modelClassesForMustache = new HashSet<>(); + @Getter public static Set enumsClassesForMustache = new HashSet<>(); diff --git a/src/main/java/com/twilio/oai/java/cache/ResourceCache2.java b/src/main/java/com/twilio/oai/java/cache/ResourceCache2.java new file mode 100644 index 000000000..5aaef466d --- /dev/null +++ b/src/main/java/com/twilio/oai/java/cache/ResourceCache2.java @@ -0,0 +1,66 @@ +package com.twilio.oai.java.cache; + +import com.twilio.oai.java.nestedmodels.MustacheEnum; +import com.twilio.oai.java.nestedmodels.MustacheModel; +import com.twilio.oai.java.nestedmodels.MustacheOneOfIface; +import lombok.Getter; +import lombok.Setter; +import org.checkerframework.checker.units.qual.A; +import org.openapitools.codegen.CodegenModel; +import org.openapitools.codegen.CodegenProperty; + +import java.util.*; + +public class ResourceCache2 { + + @Getter + @Setter + private String resourceName; + + @Getter + @Setter + private Set response = new TreeSet<>((p1, p2) -> p1.baseName.compareTo(p2.baseName)); + + @Getter + private ArrayList allModelsByDefaultGenerator = new ArrayList<>(); + @Getter + private Set modelClassesForMustache = new HashSet<>(); + + @Getter + private Set oneOfInterfaces = new HashSet<>(); + + @Getter + private Set enumsClassesForMustache = new HashSet<>(); + + public void setAllModelsByDefaultGenerator(ArrayList allModelsByDefaultGenerator) { + this.allModelsByDefaultGenerator = new ArrayList<>(allModelsByDefaultGenerator); + } + + public ArrayList getAllModelsByDefaultGenerator() { + return this.allModelsByDefaultGenerator; + } + public void addToModelClasses(MustacheModel mustacheModel) { + this.modelClassesForMustache.add(mustacheModel); + } + + public void addToEnumClasses(MustacheEnum mustacheEnum) { + this.enumsClassesForMustache.add(mustacheEnum); + } + + public void addToOneOfInterfaces(MustacheOneOfIface oneOfIFace) { + this.oneOfInterfaces.add(oneOfIFace); + } + + // Clear at group of operation level, at method: postProcessOperationsWithModels + public void clear() { + resourceName = ""; + modelClassesForMustache.clear(); + enumsClassesForMustache.clear(); + response.clear(); + } + + // No need to clear + public void clearAllModelsByDefaultGenerator() { + allModelsByDefaultGenerator.clear(); + } +} diff --git a/src/main/java/com/twilio/oai/java/cache/ResourceCacheContext.java b/src/main/java/com/twilio/oai/java/cache/ResourceCacheContext.java new file mode 100644 index 000000000..c6e8651c5 --- /dev/null +++ b/src/main/java/com/twilio/oai/java/cache/ResourceCacheContext.java @@ -0,0 +1,19 @@ +package com.twilio.oai.java.cache; + + +public class ResourceCacheContext { + private static final ThreadLocal CACHE = new ThreadLocal<>(); + + public static void set(ResourceCache2 cache) { + CACHE.set(cache); + } + + public static ResourceCache2 get() { + return CACHE.get(); + } + + public static void clear() { + if (CACHE.get() != null) CACHE.get().clear(); + } +} + diff --git a/src/main/java/com/twilio/oai/java/feature/Inequality.java b/src/main/java/com/twilio/oai/java/feature/Inequality.java index ef35d7a71..9438c3382 100644 --- a/src/main/java/com/twilio/oai/java/feature/Inequality.java +++ b/src/main/java/com/twilio/oai/java/feature/Inequality.java @@ -58,6 +58,8 @@ private void addVendorExtension(Map> groupedItems } } + // Input: DateCreated, DateCreated>, DateCreated< + // Output: DateCreated, DateCreated, DateCreated private String getBaseName(CodegenParameter codegenParameter) { if (codegenParameter.baseName.endsWith(">") || codegenParameter.baseName.endsWith("<")) { return codegenParameter.baseName.substring(0, codegenParameter.baseName.length() - 1); diff --git a/src/main/java/com/twilio/oai/java/feature/SetterMethodGenerator.java b/src/main/java/com/twilio/oai/java/feature/SetterMethodGenerator.java index ae5de7895..b9d3dc95b 100644 --- a/src/main/java/com/twilio/oai/java/feature/SetterMethodGenerator.java +++ b/src/main/java/com/twilio/oai/java/feature/SetterMethodGenerator.java @@ -28,7 +28,11 @@ public static synchronized SetterMethodGenerator getInstance() { } public void apply(final CodegenOperation codegenOperation) { - List setterParameters = codegenOperation.allParams.stream().filter(param -> !param.isPathParam).collect(Collectors.toList()); + //List setterParameters = codegenOperation.allParams.stream().filter(param -> !param.isPathParam).collect(Collectors.toList()); + List setterParameters = new ArrayList<>(codegenOperation.bodyParams); + setterParameters.addAll(codegenOperation.formParams); + setterParameters.addAll(codegenOperation.queryParams); + setterParameters.addAll(codegenOperation.headerParams); codegenOperation.vendorExtensions.put("x-setter-methods", setterParameters); } } diff --git a/src/main/java/com/twilio/oai/java/feature/constructor/ConstructorFactory.java b/src/main/java/com/twilio/oai/java/feature/constructor/ConstructorFactory.java index 20efc2ba7..d375ce937 100644 --- a/src/main/java/com/twilio/oai/java/feature/constructor/ConstructorFactory.java +++ b/src/main/java/com/twilio/oai/java/feature/constructor/ConstructorFactory.java @@ -22,7 +22,7 @@ public static synchronized ConstructorFactory getInstance() { private ConstructorFactory() { constructorGenerators = List.of( - //new JsonConstructorGenerator(), + new JsonConstructorGenerator(), new UrlencodedBodyConstructorGenerator() ); } diff --git a/src/main/java/com/twilio/oai/java/feature/constructor/ConstructorGenerator.java b/src/main/java/com/twilio/oai/java/feature/constructor/ConstructorGenerator.java index 93233431c..9947eaf26 100644 --- a/src/main/java/com/twilio/oai/java/feature/constructor/ConstructorGenerator.java +++ b/src/main/java/com/twilio/oai/java/feature/constructor/ConstructorGenerator.java @@ -1,8 +1,61 @@ package com.twilio.oai.java.feature.constructor; +import com.twilio.oai.StringHelper; import org.openapitools.codegen.CodegenOperation; +import org.openapitools.codegen.CodegenParameter; -public interface ConstructorGenerator { - void apply(CodegenOperation codegenOperation); - boolean shouldApply(CodegenOperation codegenOperation); +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.stream.Collectors; + +public abstract class ConstructorGenerator { + abstract void apply(CodegenOperation codegenOperation); + abstract boolean shouldApply(CodegenOperation codegenOperation); + + public List> getConditionalParameters(CodegenOperation codegenOperation) { + List> conditionalCodegenParam = new ArrayList<>(); + + if (codegenOperation.vendorExtensions.containsKey("x-twilio")) { + HashMap twilioVendorExtension = (HashMap) codegenOperation.vendorExtensions.get("x-twilio"); + if (twilioVendorExtension.containsKey("conditional")) { + List> conditionalParamDoubleList = (List>) twilioVendorExtension.get("conditional"); + + // Look for conditional parameters in body + // Add to conditionalCodegenParam from conditionalParamDoubleList + lookForConditionalParameterInBody(conditionalParamDoubleList, conditionalCodegenParam, codegenOperation); + + // Remove similar datatype parameters because they will create same constructors + List> filteredConditionalCodegenParam = new ArrayList<>(); + for (List cpList : conditionalCodegenParam) { + if (cpList.size() <= 1 || !cpList.get(0).dataType.equals(cpList.get(1).dataType)) { + filteredConditionalCodegenParam.add(cpList); + } + } + conditionalCodegenParam = filteredConditionalCodegenParam; } + } + + return conditionalCodegenParam; + } + + /* + The `conditionalParameterDoubleList` contains combinations of constructors derived solely from conditional parameters. + It is necessary to filter out constructors with similar parameter combinations to ensure uniqueness. + */ + public List> filterConditionalParametersByDatatype(List> conditionalParameterDoubleList) { + List> filteredConditionalCodegenParam = new ArrayList<>(); + HashSet> signatureHashSet = new HashSet<>(); + for (List paramList : conditionalParameterDoubleList) { + List orderedParamList = paramList.stream().map(p -> p.dataType).collect(Collectors.toList()); + if (signatureHashSet.add(orderedParamList)) { + filteredConditionalCodegenParam.add(paramList); + } + } + return filteredConditionalCodegenParam; + } + + // Look for conditional parameters in body + abstract void lookForConditionalParameterInBody(List> conditionalParamDoubleList, + List> conditionalCodegenParam, CodegenOperation codegenOperation); } diff --git a/src/main/java/com/twilio/oai/java/feature/constructor/JsonConstructorGenerator.java b/src/main/java/com/twilio/oai/java/feature/constructor/JsonConstructorGenerator.java index 7b0b15582..d9646ed7e 100644 --- a/src/main/java/com/twilio/oai/java/feature/constructor/JsonConstructorGenerator.java +++ b/src/main/java/com/twilio/oai/java/feature/constructor/JsonConstructorGenerator.java @@ -1,18 +1,93 @@ package com.twilio.oai.java.feature.constructor; +import com.google.common.collect.Lists; +import com.twilio.oai.StringHelper; +import com.twilio.oai.java.cache.ResourceCacheContext; import org.openapitools.codegen.CodegenOperation; +import org.openapitools.codegen.CodegenParameter; -public class JsonConstructorGenerator implements ConstructorGenerator { +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Optional; +import java.util.stream.Collectors; + +import static com.twilio.oai.api.JavaApiResourceBuilder.SIGNATURE_LIST; +import static com.twilio.oai.common.ApplicationConstants.ACCOUNT_SID_VEND_EXT; +import static com.twilio.oai.common.ApplicationConstants.DOT; + +public class JsonConstructorGenerator extends ConstructorGenerator { @Override public void apply(CodegenOperation codegenOperation) { // This method is intentionally left empty as the JSON constructor does not require any specific processing. // The JSON constructor is automatically generated by the OpenAPI generator. codegenOperation.vendorExtensions.put("x-java-constructor", true); + + List> constructors = generateSignatureListModern(codegenOperation); + + codegenOperation.vendorExtensions.put(SIGNATURE_LIST, generateSignatureListModern(codegenOperation)); + } @Override public boolean shouldApply(CodegenOperation codegenOperation) { - return false; + if (codegenOperation.consumes == null || codegenOperation.consumes.isEmpty()) { + return false; + } + boolean shouldApply = codegenOperation.consumes.stream() + .anyMatch(mediaType -> mediaType.get("mediaType").equals("application/json")); + return shouldApply; + } + + public List> generateSignatureListModern(final CodegenOperation codegenOperation) { + List requiredParams = codegenOperation.requiredParams; + // This is required because requiredParams are not resolved. + //applyDataTypeToBodyParams(requiredParams); + CodegenParameter accountSidParam = null; + Optional optionalParam = codegenOperation.pathParams.stream() + .filter(param -> param.vendorExtensions.containsKey(ACCOUNT_SID_VEND_EXT)).findAny(); + if(optionalParam.isPresent()){ + accountSidParam = optionalParam.get(); + } + + List> conditionalParameterDoubleList = getConditionalParameters(codegenOperation); + conditionalParameterDoubleList = Lists.cartesianProduct(conditionalParameterDoubleList); + // conditionalParameterDoubleList contains list of constructors only from conditional parameters + // We need to filter out similar constructors. + List> filteredConditionalCodegenParam = filterConditionalParametersByDatatype(conditionalParameterDoubleList); + + // Combine required and conditional parameters to form the signature list + List> signatureList = new ArrayList<>(); + for(List paramList : filteredConditionalCodegenParam){ + signatureList.add(addAllToList(codegenOperation.requiredParams, paramList)); + if( accountSidParam != null) { + signatureList.add(addAllToList(List.of(accountSidParam), requiredParams, paramList)); + } + } + return signatureList; + } + + private void applyDataTypeToBodyParams(List requiredParams) { + requiredParams.forEach(param -> { + if (param.isBodyParam) { + param.dataType = ResourceCacheContext.get().getResourceName() + DOT + param.dataType; + } + }); + } + + + public void lookForConditionalParameterInBody(List> conditionalParamDoubleList, + List> conditionalCodegenParam, CodegenOperation codegenOperation) { +// conditionalParamDoubleList.stream().map( +// paramList -> paramList.stream().map( +// cp -> codegenOperation.bodyParams.get(0).filter( +// op -> op.name.equals(StringHelper.camelize(cp, true)) +// ).findAny().get() +// ).collect(Collectors.toList())).collect(Collectors.toList()); + } + + private List addAllToList(List... lists) { + return Arrays.stream(lists).flatMap(List::stream).collect(Collectors.toList()); } } diff --git a/src/main/java/com/twilio/oai/java/feature/constructor/UrlencodedBodyConstructorGenerator.java b/src/main/java/com/twilio/oai/java/feature/constructor/UrlencodedBodyConstructorGenerator.java index b1b8a48b8..28110d9bf 100644 --- a/src/main/java/com/twilio/oai/java/feature/constructor/UrlencodedBodyConstructorGenerator.java +++ b/src/main/java/com/twilio/oai/java/feature/constructor/UrlencodedBodyConstructorGenerator.java @@ -20,7 +20,7 @@ This class builds the constructor parameters from mandatory fields from parameter(path, query, header), request body and conditional fields from request body. */ -public class UrlencodedBodyConstructorGenerator implements ConstructorGenerator { +public class UrlencodedBodyConstructorGenerator extends ConstructorGenerator { public void apply(CodegenOperation codegenOperation) { codegenOperation.vendorExtensions.put("x-java-constructor", true); codegenOperation.vendorExtensions.put(SIGNATURE_LIST, generateSignatureListModern(codegenOperation)); @@ -29,13 +29,39 @@ public void apply(CodegenOperation codegenOperation) { public boolean shouldApply(CodegenOperation codegenOperation) { // TODO - return true; + //return true; // Check if the operation consumes application/x-www-form-urlencoded -// if (codegenOperation.consumes == null || codegenOperation.consumes.isEmpty()) { -// return false; -// } -// return codegenOperation.consumes.stream() -// .anyMatch(mediaType -> mediaType.get("mediaType").equals("application/x-www-form-urlencoded")); + if (codegenOperation.consumes == null || codegenOperation.consumes.isEmpty()) { + return true; + } + boolean shouldApply = codegenOperation.consumes.stream() + .anyMatch(mediaType -> mediaType.get("mediaType").equals("application/x-www-form-urlencoded")); + return shouldApply; + } + + + public void lookForConditionalParameterInBody(List> conditionalParamDoubleList, + List> conditionalCodegenParam, CodegenOperation codegenOperation) { + + for (List conditionalParamList : conditionalParamDoubleList) { + List foundParameters = new ArrayList<>(); + for (String cp : conditionalParamList) { + CodegenParameter matchedParam = null; + for (CodegenParameter formParam : codegenOperation.formParams) { + if (!formParam.required + && StringHelper.camelize(formParam.baseName, true) + .equals(StringHelper.camelize(cp, true))) { + matchedParam = formParam; + break; + } + } + if (matchedParam == null) { + throw new IllegalArgumentException("Parameter not found: " + cp); + } + foundParameters.add(matchedParam); + } + conditionalCodegenParam.add(foundParameters); + } } public List> generateSignatureListModern(final CodegenOperation codegenOperation) { @@ -70,63 +96,49 @@ private final List mergeLists(List... lists) { return Arrays.stream(lists).flatMap(List::stream).collect(Collectors.toList()); } - /* - The `conditionalParameterDoubleList` contains combinations of constructors derived solely from conditional parameters. - It is necessary to filter out constructors with similar parameter combinations to ensure uniqueness. - */ - private List> filterConditionalParametersByDatatype(List> conditionalParameterDoubleList) { - List> filteredConditionalCodegenParam = new ArrayList<>(); - HashSet> signatureHashSet = new HashSet<>(); - for (List paramList : conditionalParameterDoubleList) { - List orderedParamList = paramList.stream().map(p -> p.dataType).collect(Collectors.toList()); - if (signatureHashSet.add(orderedParamList)) { - filteredConditionalCodegenParam.add(paramList); - } - } - return filteredConditionalCodegenParam; - } - - private List> getConditionalParameters(CodegenOperation codegenOperation) { - List> conditionalCodegenParam = new ArrayList<>(); - - if (codegenOperation.vendorExtensions.containsKey("x-twilio")) { - HashMap twilioVendorExtension = (HashMap) codegenOperation.vendorExtensions.get("x-twilio"); - if (twilioVendorExtension.containsKey("conditional")) { - List> conditionalParamDoubleList = (List>) twilioVendorExtension.get("conditional"); - - // Look for conditional parameters in body - for (List conditionalParamList : conditionalParamDoubleList) { - List foundParameters = new ArrayList<>(); - for (String cp : conditionalParamList) { - CodegenParameter matchedParam = null; - for (CodegenParameter formParam : codegenOperation.formParams) { - if (!formParam.required - && StringHelper.camelize(formParam.baseName, true) - .equals(StringHelper.camelize(cp, true))) { - matchedParam = formParam; - break; - } - } - if (matchedParam == null) { - throw new IllegalArgumentException("Parameter not found: " + cp); - } - foundParameters.add(matchedParam); - } - conditionalCodegenParam.add(foundParameters); - } - - // Remove similar datatype parameters because they will create same constructors - List> filteredConditionalCodegenParam = new ArrayList<>(); - for (List cpList : conditionalCodegenParam) { - if (cpList.size() <= 1 || !cpList.get(0).dataType.equals(cpList.get(1).dataType)) { - filteredConditionalCodegenParam.add(cpList); - } - } - conditionalCodegenParam = filteredConditionalCodegenParam; } - } - return conditionalCodegenParam; - } + +// private List> getConditionalParameters(CodegenOperation codegenOperation) { +// List> conditionalCodegenParam = new ArrayList<>(); +// +// if (codegenOperation.vendorExtensions.containsKey("x-twilio")) { +// HashMap twilioVendorExtension = (HashMap) codegenOperation.vendorExtensions.get("x-twilio"); +// if (twilioVendorExtension.containsKey("conditional")) { +// List> conditionalParamDoubleList = (List>) twilioVendorExtension.get("conditional"); +// +// // Look for conditional parameters in body +// for (List conditionalParamList : conditionalParamDoubleList) { +// List foundParameters = new ArrayList<>(); +// for (String cp : conditionalParamList) { +// CodegenParameter matchedParam = null; +// for (CodegenParameter formParam : codegenOperation.formParams) { +// if (!formParam.required +// && StringHelper.camelize(formParam.baseName, true) +// .equals(StringHelper.camelize(cp, true))) { +// matchedParam = formParam; +// break; +// } +// } +// if (matchedParam == null) { +// throw new IllegalArgumentException("Parameter not found: " + cp); +// } +// foundParameters.add(matchedParam); +// } +// conditionalCodegenParam.add(foundParameters); +// } +// +// // Remove similar datatype parameters because they will create same constructors +// List> filteredConditionalCodegenParam = new ArrayList<>(); +// for (List cpList : conditionalCodegenParam) { +// if (cpList.size() <= 1 || !cpList.get(0).dataType.equals(cpList.get(1).dataType)) { +// filteredConditionalCodegenParam.add(cpList); +// } +// } +// conditionalCodegenParam = filteredConditionalCodegenParam; } +// } +// +// return conditionalCodegenParam; +// } public ArrayList> generateSignatureList(final CodegenOperation co) { CodegenParameter accountSidParam = null; diff --git a/src/main/java/com/twilio/oai/java/feature/datamodels/DataModel.java b/src/main/java/com/twilio/oai/java/feature/datamodels/DataModel.java index 90096bea1..4d7e7526b 100644 --- a/src/main/java/com/twilio/oai/java/feature/datamodels/DataModel.java +++ b/src/main/java/com/twilio/oai/java/feature/datamodels/DataModel.java @@ -4,6 +4,6 @@ import org.openapitools.codegen.CodegenOperation; public interface DataModel { - void apply(CodegenModel codegenModel); + void apply(CodegenOperation codegenOperation); boolean shouldApply(CodegenModel codegenModel); } diff --git a/src/main/java/com/twilio/oai/java/feature/datamodels/DataModelManager.java b/src/main/java/com/twilio/oai/java/feature/datamodels/DataModelManager.java index 3d30ce692..98f0e9320 100644 --- a/src/main/java/com/twilio/oai/java/feature/datamodels/DataModelManager.java +++ b/src/main/java/com/twilio/oai/java/feature/datamodels/DataModelManager.java @@ -1,5 +1,6 @@ package com.twilio.oai.java.feature.datamodels; +import com.twilio.oai.java.cache.ResourceCacheContext; import org.openapitools.codegen.CodegenModel; import java.util.List; @@ -26,11 +27,13 @@ public static synchronized DataModelManager getInstance() { return instance; } - public void apply(final CodegenModel codegenModel) { - for (DataModel dataModel: dataModels) { - if (dataModel.shouldApply(codegenModel)) { - dataModel.apply(codegenModel); - return; // Can a CodegenModel have multiple datamodels at same level, if yes don't return ? + public void apply() { + for (CodegenModel codegenModel: ResourceCacheContext.get().getAllModelsByDefaultGenerator()) { + for (DataModel dataModel: dataModels) { + if (dataModel.shouldApply(codegenModel)) { + //dataModel.apply(); + // Can a CodegenModel have multiple datamodels at same level, if yes don't return ? + } } } } diff --git a/src/main/java/com/twilio/oai/java/feature/datamodels/OneOf.java b/src/main/java/com/twilio/oai/java/feature/datamodels/OneOf.java index b7796f40d..74b884b2a 100644 --- a/src/main/java/com/twilio/oai/java/feature/datamodels/OneOf.java +++ b/src/main/java/com/twilio/oai/java/feature/datamodels/OneOf.java @@ -1,12 +1,28 @@ package com.twilio.oai.java.feature.datamodels; +import com.twilio.oai.java.cache.ResourceCacheContext; +import com.twilio.oai.java.nestedmodels.MustacheOneOfIface; import org.openapitools.codegen.CodegenModel; +import org.openapitools.codegen.CodegenOperation; -public class OneOf implements DataModel { +import java.util.Map; +import java.util.Set; +/* + This class has 2 responsibilities + 1. Identifying oneOf interfaces and ignore it so that concrete classes shouldn't generate. + 2. Identify the concrete classes from interfaces and create relationship between concrete class and interface. +*/ +public class OneOf implements DataModel { + Map allModelsMap = ResourceCacheContext.get().getAllModelsByDefaultGenerator().stream() + .collect(java.util.stream.Collectors.toMap(m -> m.name, m -> m)); + @Override - public void apply(final CodegenModel codegenModel) { - System.out.println(codegenModel); + public void apply(final CodegenOperation codegenOperation) { + + } + + private void resolveOneOf(CodegenOperation codegenOperation) { } @@ -17,4 +33,14 @@ public boolean shouldApply(final CodegenModel codegenModel) { } return true; } + + public void addInterfaceMustache(CodegenModel codegenModel) { + MustacheOneOfIface oneOfIface = new MustacheOneOfIface(codegenModel.classname); + ResourceCacheContext.get().addToOneOfInterfaces(oneOfIface); + + } + + public void addImplMustache() { + + } } diff --git a/src/main/java/com/twilio/oai/java/format/JavaUpdateDefaultMapping.java b/src/main/java/com/twilio/oai/java/format/JavaUpdateDefaultMapping.java index f00656b9b..dea363e2d 100644 --- a/src/main/java/com/twilio/oai/java/format/JavaUpdateDefaultMapping.java +++ b/src/main/java/com/twilio/oai/java/format/JavaUpdateDefaultMapping.java @@ -5,6 +5,7 @@ import java.util.HashSet; import java.util.Map; +import java.util.Set; public class JavaUpdateDefaultMapping { HashSet customFormatWithProperties = new HashSet<>(); @@ -37,6 +38,11 @@ public void modelTemplateFiles(Map modelTemplateFiles) { // Do not generate models modelTemplateFiles.clear(); } + + public void removeReservedWords(Set reservedWords) { + // Do not generate models + reservedWords.remove("localdate"); + } /* If a parameter or property in the OpenAPI specification has properties defined, then generator considers it as a complex type. diff --git a/src/main/java/com/twilio/oai/java/format/OpenApiSpecFormatFeatureConstants.java b/src/main/java/com/twilio/oai/java/format/OpenApiSpecFormatFeatureConstants.java index 2568c6127..b6ecdab36 100644 --- a/src/main/java/com/twilio/oai/java/format/OpenApiSpecFormatFeatureConstants.java +++ b/src/main/java/com/twilio/oai/java/format/OpenApiSpecFormatFeatureConstants.java @@ -47,15 +47,17 @@ final static Map getPredefinedTypeMappings() { predefinedTypeMappings.put("Map", "Map"); predefinedTypeMappings.put("Map", "Map"); - predefinedTypeMappings.put("string+phone-number", "PhoneNumber"); + predefinedTypeMappings.put("string+phone-number", "com.twilio.type.PhoneNumber"); + predefinedTypeMappings.put("com.twilio.type.PhoneNumber", "com.twilio.type.PhoneNumber"); predefinedTypeMappings.put("string+uri", "URI"); predefinedTypeMappings.put("string+url", "URI"); predefinedTypeMappings.put("string+currency", "Currency"); predefinedTypeMappings.put("string+date-time", "ZonedDateTime"); predefinedTypeMappings.put("string+date", "LocalDate"); + //predefinedTypeMappings.put("LocalDate", "LocalDate"); predefinedTypeMappings.put("string+endpoint", "Endpoint"); predefinedTypeMappings.put("string+http-method", "HttpMethod"); - predefinedTypeMappings.put("string+twiml", "com.twilio.type.Twiml"); + predefinedTypeMappings.put("string+twiml", "Twiml"); predefinedTypeMappings.put("string+date-time-rfc-2822", "ZonedDateTime"); predefinedTypeMappings.put("object+ice-server", "IceServer"); diff --git a/src/main/java/com/twilio/oai/java/format/Promoter.java b/src/main/java/com/twilio/oai/java/format/Promoter.java index e7983bb7a..7d6547ef7 100644 --- a/src/main/java/com/twilio/oai/java/format/Promoter.java +++ b/src/main/java/com/twilio/oai/java/format/Promoter.java @@ -3,6 +3,7 @@ import org.openapitools.codegen.CodegenOperation; import org.openapitools.codegen.CodegenParameter; +import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; @@ -30,7 +31,11 @@ public static void addPromoter(final CodegenParameter codegenParameter) { } public static void addPromoter(final CodegenOperation codegenOperation) { - List setterParameters = codegenOperation.allParams.stream().filter(param -> !param.isPathParam).collect(Collectors.toList()); + //List setterParameters = codegenOperation.allParams.stream().filter(param -> !param.isPathParam).collect(Collectors.toList()); + List setterParameters = new ArrayList<>(codegenOperation.bodyParams); + setterParameters.addAll(codegenOperation.formParams); + setterParameters.addAll(codegenOperation.queryParams); + setterParameters.addAll(codegenOperation.headerParams); setterParameters.forEach(param -> addPromoter(param)); } } diff --git a/src/main/java/com/twilio/oai/java/nestedmodels/MustacheModel.java b/src/main/java/com/twilio/oai/java/nestedmodels/MustacheModel.java index 55c63f9ed..9fe1585d0 100644 --- a/src/main/java/com/twilio/oai/java/nestedmodels/MustacheModel.java +++ b/src/main/java/com/twilio/oai/java/nestedmodels/MustacheModel.java @@ -3,6 +3,7 @@ import com.twilio.oai.common.Utility; import org.checkerframework.checker.units.qual.A; import org.openapitools.codegen.CodegenModel; +import org.openapitools.codegen.CodegenParameter; import org.openapitools.codegen.CodegenProperty; import java.util.ArrayList; @@ -14,7 +15,7 @@ public class MustacheModel { String className; // Used in either builder or setter - List optionalProperties; + List allProperties; // Used in constructor List mandatoryProperties; @@ -22,18 +23,27 @@ public class MustacheModel { public MustacheModel(CodegenProperty codegenProperty, CodegenModel codegenModel) { this.className = codegenModel.classname; - this.optionalProperties = codegenModel.vars.stream() - .filter(codegenProperty1 -> !codegenProperty1.required) + this.allProperties = new ArrayList<>(codegenModel.vars); + + this.mandatoryProperties = codegenModel.vars.stream() + .filter(codegenProperty1 -> codegenProperty1.required) .collect(Collectors.toList()); + } + + public MustacheModel(CodegenParameter codegenParameter, CodegenModel codegenModel) { + this.className = codegenModel.classname; + + this.allProperties = new ArrayList<>(codegenModel.vars); + this.mandatoryProperties = codegenModel.vars.stream() .filter(codegenProperty1 -> codegenProperty1.required) .collect(Collectors.toList()); } - public MustacheModel(String className, List mandatoryProperties, List optionalProperties) { + public MustacheModel(String className, List mandatoryProperties, List allProperties) { this.className = className; this.mandatoryProperties = new ArrayList<>(mandatoryProperties); - this.optionalProperties = new ArrayList<>(optionalProperties); + this.allProperties = new ArrayList<>(allProperties); } @Override diff --git a/src/main/java/com/twilio/oai/java/nestedmodels/MustacheOneOf.java b/src/main/java/com/twilio/oai/java/nestedmodels/MustacheOneOf.java index 8ca9f1fba..ad79d2a6f 100644 --- a/src/main/java/com/twilio/oai/java/nestedmodels/MustacheOneOf.java +++ b/src/main/java/com/twilio/oai/java/nestedmodels/MustacheOneOf.java @@ -1,4 +1,25 @@ package com.twilio.oai.java.nestedmodels; +// Implementation of OneOf interface for Mustache templates public class MustacheOneOf { + String className; + String discriminator; + + public MustacheOneOf(String className, String discriminator) { + this.className = className; + this.discriminator = discriminator; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) return true; + if (obj == null || getClass() != obj.getClass()) return false; + MustacheOneOf that = (MustacheOneOf) obj; + return className != null && className.equals(that.className); + } + + @Override + public int hashCode() { + return className != null ? className.hashCode() : 0; + } } diff --git a/src/main/java/com/twilio/oai/java/nestedmodels/MustacheOneOfIface.java b/src/main/java/com/twilio/oai/java/nestedmodels/MustacheOneOfIface.java new file mode 100644 index 000000000..c25bbd140 --- /dev/null +++ b/src/main/java/com/twilio/oai/java/nestedmodels/MustacheOneOfIface.java @@ -0,0 +1,15 @@ +package com.twilio.oai.java.nestedmodels; + +public class MustacheOneOfIface { + String interfaceClassName; + String discriminator; + + public MustacheOneOfIface(String interfaceClassName) { + this.interfaceClassName = interfaceClassName; + } + + public MustacheOneOfIface(String interfaceClassName, String discriminator) { + this.interfaceClassName = interfaceClassName; + this.discriminator = discriminator; + } +} diff --git a/src/main/java/com/twilio/oai/java/processor/auth/OAuth.java b/src/main/java/com/twilio/oai/java/processor/auth/OAuth.java index bb109dcf0..bc442c157 100644 --- a/src/main/java/com/twilio/oai/java/processor/auth/OAuth.java +++ b/src/main/java/com/twilio/oai/java/processor/auth/OAuth.java @@ -1,9 +1,6 @@ package com.twilio.oai.java.processor.auth; import org.openapitools.codegen.CodegenOperation; -import org.openapitools.codegen.CodegenSecurity; - -import java.util.List; // Placeholder class, OAuth is not added to security schemes. public class OAuth implements SecuritySchemeProcessor { diff --git a/src/main/java/com/twilio/oai/java/processor/auth/SecuritySchemeManager.java b/src/main/java/com/twilio/oai/java/processor/auth/SecuritySchemeManager.java index 85195eb59..8eaba5327 100644 --- a/src/main/java/com/twilio/oai/java/processor/auth/SecuritySchemeManager.java +++ b/src/main/java/com/twilio/oai/java/processor/auth/SecuritySchemeManager.java @@ -1,7 +1,6 @@ package com.twilio.oai.java.processor.auth; import org.openapitools.codegen.CodegenOperation; -import org.openapitools.codegen.CodegenSecurity; import java.util.List; diff --git a/src/main/java/com/twilio/oai/java/processor/auth/SecuritySchemeProcessor.java b/src/main/java/com/twilio/oai/java/processor/auth/SecuritySchemeProcessor.java index 5633177ef..8c516b628 100644 --- a/src/main/java/com/twilio/oai/java/processor/auth/SecuritySchemeProcessor.java +++ b/src/main/java/com/twilio/oai/java/processor/auth/SecuritySchemeProcessor.java @@ -2,8 +2,6 @@ import org.openapitools.codegen.CodegenOperation; -import java.util.Map; - // Orgs OAuth and Basic Auth has different RestClients. // Set "x-auth-attributes" for different type of authentication public interface SecuritySchemeProcessor { diff --git a/src/main/java/com/twilio/oai/java/processor/enums/parameter/body/InlineBodyEnumProcessor.java b/src/main/java/com/twilio/oai/java/processor/enums/parameter/body/InlineBodyEnumProcessor.java index 98b98b5cf..c60944fcf 100644 --- a/src/main/java/com/twilio/oai/java/processor/enums/parameter/body/InlineBodyEnumProcessor.java +++ b/src/main/java/com/twilio/oai/java/processor/enums/parameter/body/InlineBodyEnumProcessor.java @@ -2,9 +2,9 @@ import com.twilio.oai.common.EnumConstants; import com.twilio.oai.common.StringUtils; +import com.twilio.oai.java.cache.ResourceCacheContext; import com.twilio.oai.java.nestedmodels.MustacheEnum; import com.twilio.oai.java.processor.enums.parameter.ParameterEnumProcessor; -import com.twilio.oai.java.ResourceCache; import org.openapitools.codegen.CodegenParameter; import java.util.List; @@ -62,13 +62,13 @@ private void variableName(CodegenParameter codegenParameter) { } private void datatype(CodegenParameter codegenParameter) { codegenParameter.vendorExtensions.put(X_DATATYPE, - ResourceCache.getResourceName() + DOT + StringUtils.toPascalCase(codegenParameter.baseName)); + ResourceCacheContext.get().getResourceName() + DOT + StringUtils.toPascalCase(codegenParameter.baseName)); } private void cacheEnumClass(CodegenParameter codegenParameter) { List> enumValues = (List>) codegenParameter.allowableValues.get("enumVars"); MustacheEnum mustacheEnum = new MustacheEnum(StringUtils.toPascalCase(codegenParameter.baseName), enumValues); - ResourceCache.addToEnumClasses(mustacheEnum); + ResourceCacheContext.get().addToEnumClasses(mustacheEnum); } } diff --git a/src/main/java/com/twilio/oai/java/processor/enums/parameter/body/InlineBodyListEnumProcessor.java b/src/main/java/com/twilio/oai/java/processor/enums/parameter/body/InlineBodyListEnumProcessor.java index 223486722..0319a7ae3 100644 --- a/src/main/java/com/twilio/oai/java/processor/enums/parameter/body/InlineBodyListEnumProcessor.java +++ b/src/main/java/com/twilio/oai/java/processor/enums/parameter/body/InlineBodyListEnumProcessor.java @@ -3,9 +3,9 @@ import com.twilio.oai.common.EnumConstants; import com.twilio.oai.common.StringUtils; import com.twilio.oai.common.Utility; +import com.twilio.oai.java.cache.ResourceCacheContext; import com.twilio.oai.java.nestedmodels.MustacheEnum; import com.twilio.oai.java.processor.enums.parameter.ParameterEnumProcessor; -import com.twilio.oai.java.ResourceCache; import org.openapitools.codegen.CodegenParameter; import java.util.List; @@ -66,9 +66,16 @@ private void datatype(CodegenParameter codegenParameter) { // enumExistingDatatype = String String enumExistingDatatype = Utility.extractDatatypeFromContainer(codegenParameter.dataType); String enumClassName = StringUtils.toPascalCase(codegenParameter.baseName); - String enumNonContainerDatatype = ResourceCache.getResourceName() + DOT + enumClassName; + String enumNonContainerDatatype = ResourceCacheContext.get().getResourceName() + DOT + enumClassName; String resolvedDataType = Utility.replaceDatatypeInContainer(codegenParameter.dataType, enumNonContainerDatatype); codegenParameter.vendorExtensions.put(X_DATATYPE, resolvedDataType); + + // Resolve BaseType for List as it is used in promoter as setter method. + String baseType = Utility.getEnumNameFromDatatype(codegenParameter.baseType); + if (baseType != null) { + String resolvedBaseType = ResourceCacheContext.get().getResourceName() + DOT + StringUtils.toPascalCase(baseType); + codegenParameter.baseType = resolvedBaseType; + } } private void cacheEnumClass(CodegenParameter codegenParameter) { @@ -76,6 +83,6 @@ private void cacheEnumClass(CodegenParameter codegenParameter) { List> enumValues = (List>) codegenParameter.allowableValues.get("enumVars"); MustacheEnum mustacheEnum = new MustacheEnum(enumClassName, enumValues); - ResourceCache.addToEnumClasses(mustacheEnum); + ResourceCacheContext.get().addToEnumClasses(mustacheEnum); } } diff --git a/src/main/java/com/twilio/oai/java/processor/enums/parameter/body/ReusableBodyEnumProcessor.java b/src/main/java/com/twilio/oai/java/processor/enums/parameter/body/ReusableBodyEnumProcessor.java index 07ea04929..8d74ca741 100644 --- a/src/main/java/com/twilio/oai/java/processor/enums/parameter/body/ReusableBodyEnumProcessor.java +++ b/src/main/java/com/twilio/oai/java/processor/enums/parameter/body/ReusableBodyEnumProcessor.java @@ -3,9 +3,9 @@ import com.twilio.oai.common.EnumConstants; import com.twilio.oai.common.StringUtils; import com.twilio.oai.common.Utility; +import com.twilio.oai.java.cache.ResourceCacheContext; import com.twilio.oai.java.nestedmodels.MustacheEnum; import com.twilio.oai.java.processor.enums.parameter.ParameterEnumProcessor; -import com.twilio.oai.java.ResourceCache; import org.openapitools.codegen.CodegenParameter; import java.util.List; @@ -59,7 +59,7 @@ private void variableName(CodegenParameter codegenParameter) { } private void datatype(CodegenParameter codegenParameter) { String enumDatatypeResolved = StringUtils.toPascalCase(Utility.getEnumNameFromDefaultDatatype(codegenParameter.dataType)); - codegenParameter.vendorExtensions.put(X_DATATYPE, ResourceCache.getResourceName() + DOT + enumDatatypeResolved); + codegenParameter.vendorExtensions.put(X_DATATYPE, ResourceCacheContext.get().getResourceName() + DOT + enumDatatypeResolved); } private void cacheEnumClass(CodegenParameter codegenParameter) { @@ -68,6 +68,6 @@ private void cacheEnumClass(CodegenParameter codegenParameter) { List> enumValues = (List>) codegenParameter.allowableValues.get("enumVars"); MustacheEnum mustacheEnum = new MustacheEnum(enumClassName, enumValues); - ResourceCache.addToEnumClasses(mustacheEnum); + ResourceCacheContext.get().addToEnumClasses(mustacheEnum); } } diff --git a/src/main/java/com/twilio/oai/java/processor/enums/parameter/body/ReusableBodyListEnumProcessor.java b/src/main/java/com/twilio/oai/java/processor/enums/parameter/body/ReusableBodyListEnumProcessor.java index b962684f6..017b48842 100644 --- a/src/main/java/com/twilio/oai/java/processor/enums/parameter/body/ReusableBodyListEnumProcessor.java +++ b/src/main/java/com/twilio/oai/java/processor/enums/parameter/body/ReusableBodyListEnumProcessor.java @@ -3,9 +3,9 @@ import com.twilio.oai.common.EnumConstants; import com.twilio.oai.common.StringUtils; import com.twilio.oai.common.Utility; +import com.twilio.oai.java.cache.ResourceCacheContext; import com.twilio.oai.java.nestedmodels.MustacheEnum; import com.twilio.oai.java.processor.enums.parameter.ParameterEnumProcessor; -import com.twilio.oai.java.ResourceCache; import org.openapitools.codegen.CodegenModel; import org.openapitools.codegen.CodegenParameter; @@ -70,10 +70,17 @@ private void datatype(CodegenParameter codegenParameter) { // enumClassName = Status String enumClassName = Utility.getEnumNameFromDatatype(enumExistingDatatype); // enumNonContainerDatatype = Account.Status - String enumNonContainerDatatype = ResourceCache.getResourceName() + DOT + StringUtils.toPascalCase(enumClassName); + String enumNonContainerDatatype = ResourceCacheContext.get().getResourceName() + DOT + StringUtils.toPascalCase(enumClassName); // resolvedDataType = List String resolvedDataType = Utility.replaceDatatypeInContainer(codegenParameter.dataType, enumNonContainerDatatype); codegenParameter.vendorExtensions.put(X_DATATYPE, resolvedDataType); + + // Resolve BaseType for List as it is used in promoter as setter method. + String baseType = Utility.getEnumNameFromDatatype(codegenParameter.baseType); + if (baseType != null) { + String resolvedBaseType = ResourceCacheContext.get().getResourceName() + DOT + StringUtils.toPascalCase(baseType); + codegenParameter.baseType = resolvedBaseType; + } } private void cacheEnumClass(CodegenParameter codegenParameter) { @@ -90,7 +97,7 @@ private void cacheEnumClass(CodegenParameter codegenParameter) { Map values = null; List> enumValues = new ArrayList<>(); - for (CodegenModel codegenModel: ResourceCache.getAllModelsByDefaultGenerator()) { + for (CodegenModel codegenModel: ResourceCacheContext.get().getAllModelsByDefaultGenerator()) { if (baseDataType.equals(codegenModel.classname)) { values = codegenModel.allowableValues; enumValues = (List>) codegenModel.allowableValues.get("enumVars"); @@ -98,9 +105,10 @@ private void cacheEnumClass(CodegenParameter codegenParameter) { } } if (enumValues == null || enumValues.isEmpty()) { + System.out.println("Exception occurred:" + codegenParameter.baseName); throw new RuntimeException("No enum values found for Enum" + " DataType: " +codegenParameter.dataType); } MustacheEnum mustacheEnum = new MustacheEnum(enumClassName, enumValues); - ResourceCache.addToEnumClasses(mustacheEnum); + ResourceCacheContext.get().addToEnumClasses(mustacheEnum); } } diff --git a/src/main/java/com/twilio/oai/java/processor/enums/parameter/param/InlineListParamEnumProcessor.java b/src/main/java/com/twilio/oai/java/processor/enums/parameter/param/InlineListParamEnumProcessor.java index 7797ab7f0..345eb5399 100644 --- a/src/main/java/com/twilio/oai/java/processor/enums/parameter/param/InlineListParamEnumProcessor.java +++ b/src/main/java/com/twilio/oai/java/processor/enums/parameter/param/InlineListParamEnumProcessor.java @@ -3,9 +3,9 @@ import com.twilio.oai.common.EnumConstants.OpenApiEnumType; import com.twilio.oai.common.StringUtils; import com.twilio.oai.common.Utility; +import com.twilio.oai.java.cache.ResourceCacheContext; import com.twilio.oai.java.nestedmodels.MustacheEnum; import com.twilio.oai.java.processor.enums.parameter.ParameterEnumProcessor; -import com.twilio.oai.java.ResourceCache; import org.openapitools.codegen.CodegenParameter; import java.util.List; @@ -67,15 +67,24 @@ private void variableName(CodegenParameter codegenParameter) { } private void datatype(CodegenParameter codegenParameter) { String enumClassName = StringUtils.toPascalCase(codegenParameter.baseName); - String enumNonContainerDatatype = ResourceCache.getResourceName() + DOT + StringUtils.toPascalCase(enumClassName); + String enumNonContainerDatatype = ResourceCacheContext.get().getResourceName() + DOT + StringUtils.toPascalCase(enumClassName); String resolvedDataType = Utility.replaceDatatypeInContainer(codegenParameter.dataType, enumNonContainerDatatype); codegenParameter.vendorExtensions.put(X_DATATYPE, resolvedDataType); + + // Resolve BaseType for List as it is used in promoter as setter method. + String baseType = Utility.getEnumNameFromDatatype(codegenParameter.baseType); + if (baseType != null) { + String resolvedBaseType = ResourceCacheContext.get().getResourceName() + DOT + StringUtils.toPascalCase(baseType); + codegenParameter.baseType = resolvedBaseType; + } + // enumNonContainerDatatype = Account.Status + } private void cacheEnumClass(CodegenParameter codegenParameter) { List> enumValues = (List>) codegenParameter.allowableValues.get("enumVars"); MustacheEnum mustacheEnum = new MustacheEnum( StringUtils.toPascalCase(codegenParameter.baseName), enumValues); - ResourceCache.addToEnumClasses(mustacheEnum); + ResourceCacheContext.get().addToEnumClasses(mustacheEnum); } } diff --git a/src/main/java/com/twilio/oai/java/processor/enums/parameter/param/InlineParamEnumProcessor.java b/src/main/java/com/twilio/oai/java/processor/enums/parameter/param/InlineParamEnumProcessor.java index 13b174782..46b516ecd 100644 --- a/src/main/java/com/twilio/oai/java/processor/enums/parameter/param/InlineParamEnumProcessor.java +++ b/src/main/java/com/twilio/oai/java/processor/enums/parameter/param/InlineParamEnumProcessor.java @@ -2,9 +2,9 @@ import com.twilio.oai.common.EnumConstants.OpenApiEnumType; import com.twilio.oai.common.StringUtils; +import com.twilio.oai.java.cache.ResourceCacheContext; import com.twilio.oai.java.nestedmodels.MustacheEnum; import com.twilio.oai.java.processor.enums.parameter.ParameterEnumProcessor; -import com.twilio.oai.java.ResourceCache; import org.openapitools.codegen.CodegenParameter; import java.util.List; @@ -62,12 +62,12 @@ private void variableName(CodegenParameter codegenParameter) { } private void datatype(CodegenParameter codegenParameter) { codegenParameter.vendorExtensions.put(X_DATATYPE, - ResourceCache.getResourceName() + DOT + StringUtils.toPascalCase(codegenParameter.baseName)); + ResourceCacheContext.get().getResourceName() + DOT + StringUtils.toPascalCase(codegenParameter.baseName)); } private void cacheEnumClass(CodegenParameter codegenParameter) { List> enumValues = (List>) codegenParameter.allowableValues.get("enumVars"); MustacheEnum mustacheEnum = new MustacheEnum(StringUtils.toPascalCase(codegenParameter.baseName), enumValues); - ResourceCache.addToEnumClasses(mustacheEnum); + ResourceCacheContext.get().addToEnumClasses(mustacheEnum); } } diff --git a/src/main/java/com/twilio/oai/java/processor/enums/parameter/param/ReusableListParamEnumProcessor.java b/src/main/java/com/twilio/oai/java/processor/enums/parameter/param/ReusableListParamEnumProcessor.java index eca1b5d73..35d106116 100644 --- a/src/main/java/com/twilio/oai/java/processor/enums/parameter/param/ReusableListParamEnumProcessor.java +++ b/src/main/java/com/twilio/oai/java/processor/enums/parameter/param/ReusableListParamEnumProcessor.java @@ -3,9 +3,9 @@ import com.twilio.oai.common.EnumConstants.OpenApiEnumType; import com.twilio.oai.common.StringUtils; import com.twilio.oai.common.Utility; +import com.twilio.oai.java.cache.ResourceCacheContext; import com.twilio.oai.java.nestedmodels.MustacheEnum; import com.twilio.oai.java.processor.enums.parameter.ParameterEnumProcessor; -import com.twilio.oai.java.ResourceCache; import org.openapitools.codegen.CodegenParameter; import java.util.List; @@ -65,10 +65,17 @@ private void datatype(CodegenParameter codegenParameter) { // enumRefResolved = singleReusable String enumRefResolved = Utility.getEnumNameFromRef(codegenParameter.getSchema().items.getRef()); // enumNonContainerDatatype = Content.SingleReusable - String enumNonContainerDatatype = ResourceCache.getResourceName() + DOT + StringUtils.toPascalCase(enumRefResolved); + String enumNonContainerDatatype = ResourceCacheContext.get().getResourceName() + DOT + StringUtils.toPascalCase(enumRefResolved); // resolvedDataType = List String resolvedDataType = Utility.replaceDatatypeInContainer(codegenParameter.dataType, enumNonContainerDatatype); codegenParameter.vendorExtensions.put(X_DATATYPE, resolvedDataType); + + // Resolve BaseType for List as it is used in promoter as setter method. + String baseType = Utility.getEnumNameFromDatatype(codegenParameter.baseType); + if (baseType != null) { + String resolvedBaseType = ResourceCacheContext.get().getResourceName() + DOT + StringUtils.toPascalCase(baseType); + codegenParameter.baseType = resolvedBaseType; + } } private void cacheEnumClass(CodegenParameter codegenParameter) { @@ -76,6 +83,6 @@ private void cacheEnumClass(CodegenParameter codegenParameter) { MustacheEnum mustacheEnum = new MustacheEnum(StringUtils.toPascalCase( Utility.getEnumNameFromRef(codegenParameter.getSchema().items.getRef())), enumValues); - ResourceCache.addToEnumClasses(mustacheEnum); + ResourceCacheContext.get().addToEnumClasses(mustacheEnum); } } diff --git a/src/main/java/com/twilio/oai/java/processor/enums/parameter/param/ReusableParamEnumProcessor.java b/src/main/java/com/twilio/oai/java/processor/enums/parameter/param/ReusableParamEnumProcessor.java index 68b804cb8..0ca681c50 100644 --- a/src/main/java/com/twilio/oai/java/processor/enums/parameter/param/ReusableParamEnumProcessor.java +++ b/src/main/java/com/twilio/oai/java/processor/enums/parameter/param/ReusableParamEnumProcessor.java @@ -3,9 +3,9 @@ import com.twilio.oai.common.EnumConstants.OpenApiEnumType; import com.twilio.oai.common.StringUtils; import com.twilio.oai.common.Utility; +import com.twilio.oai.java.cache.ResourceCacheContext; import com.twilio.oai.java.nestedmodels.MustacheEnum; import com.twilio.oai.java.processor.enums.parameter.ParameterEnumProcessor; -import com.twilio.oai.java.ResourceCache; import org.openapitools.codegen.CodegenParameter; import java.util.List; @@ -56,13 +56,13 @@ private void variableName(CodegenParameter codegenParameter) { private void datatype(CodegenParameter codegenParameter) { String enumRefResolved = Utility.getEnumNameFromRef(codegenParameter.getSchema().getRef()); codegenParameter.vendorExtensions.put(X_DATATYPE, - ResourceCache.getResourceName() + DOT + StringUtils.toPascalCase(enumRefResolved)); + ResourceCacheContext.get().getResourceName() + DOT + StringUtils.toPascalCase(enumRefResolved)); } private void cacheEnumClass(CodegenParameter codegenParameter) { List> enumValues = (List>) codegenParameter.allowableValues.get("enumVars"); MustacheEnum mustacheEnum = new MustacheEnum(StringUtils.toPascalCase( Utility.getEnumNameFromRef(codegenParameter.getSchema().getRef())), enumValues); - ResourceCache.addToEnumClasses(mustacheEnum); + ResourceCacheContext.get().addToEnumClasses(mustacheEnum); } } diff --git a/src/main/java/com/twilio/oai/java/processor/enums/property/InlineListPropEnumProcessor.java b/src/main/java/com/twilio/oai/java/processor/enums/property/InlineListPropEnumProcessor.java index e40b652b5..308616018 100644 --- a/src/main/java/com/twilio/oai/java/processor/enums/property/InlineListPropEnumProcessor.java +++ b/src/main/java/com/twilio/oai/java/processor/enums/property/InlineListPropEnumProcessor.java @@ -3,8 +3,8 @@ import com.twilio.oai.common.EnumConstants.OpenApiEnumType; import com.twilio.oai.common.StringUtils; import com.twilio.oai.common.Utility; +import com.twilio.oai.java.cache.ResourceCacheContext; import com.twilio.oai.java.nestedmodels.MustacheEnum; -import com.twilio.oai.java.ResourceCache; import org.openapitools.codegen.CodegenProperty; import java.util.List; @@ -48,14 +48,21 @@ private void variableName(CodegenProperty codegenProperty) { } private void datatype(CodegenProperty codegenProperty) { String enumClassName = StringUtils.toPascalCase(codegenProperty.baseName); - String enumNonContainerDatatype = ResourceCache.getResourceName() + DOT + StringUtils.toPascalCase(enumClassName); + String enumNonContainerDatatype = ResourceCacheContext.get().getResourceName() + DOT + StringUtils.toPascalCase(enumClassName); String resolvedDataType = Utility.replaceDatatypeInContainer(codegenProperty.dataType, enumNonContainerDatatype); codegenProperty.vendorExtensions.put(X_DATATYPE, resolvedDataType); + + // Resolve BaseType for List as it is used in promoter as setter method. + String baseType = Utility.getEnumNameFromDatatype(codegenProperty.baseType); + if (baseType != null) { + String resolvedBaseType = ResourceCacheContext.get().getResourceName() + DOT + StringUtils.toPascalCase(baseType); + codegenProperty.baseType = resolvedBaseType; + } } private void cacheEnumClass(CodegenProperty codegenProperty) { List> enumValues = (List>) codegenProperty.allowableValues.get("enumVars"); MustacheEnum mustacheEnum = new MustacheEnum(StringUtils.toPascalCase(codegenProperty.baseName), enumValues); - ResourceCache.addToEnumClasses(mustacheEnum); + ResourceCacheContext.get().addToEnumClasses(mustacheEnum); } } diff --git a/src/main/java/com/twilio/oai/java/processor/enums/property/InlinePropEnumProcessor.java b/src/main/java/com/twilio/oai/java/processor/enums/property/InlinePropEnumProcessor.java index 2d02af04b..f9351e6a3 100644 --- a/src/main/java/com/twilio/oai/java/processor/enums/property/InlinePropEnumProcessor.java +++ b/src/main/java/com/twilio/oai/java/processor/enums/property/InlinePropEnumProcessor.java @@ -3,8 +3,8 @@ import com.twilio.oai.StringHelper; import com.twilio.oai.common.EnumConstants.OpenApiEnumType; import com.twilio.oai.common.StringUtils; +import com.twilio.oai.java.cache.ResourceCacheContext; import com.twilio.oai.java.nestedmodels.MustacheEnum; -import com.twilio.oai.java.ResourceCache; import org.openapitools.codegen.CodegenProperty; import java.util.ArrayList; @@ -54,7 +54,7 @@ private void variableName(CodegenProperty codegenProperty) { } private void datatype(CodegenProperty codegenProperty) { codegenProperty.vendorExtensions.put(X_DATATYPE, - ResourceCache.getResourceName() + DOT + StringUtils.toPascalCase(codegenProperty.baseName)); + ResourceCacheContext.get().getResourceName() + DOT + StringUtils.toPascalCase(codegenProperty.baseName)); } private void cacheEnumClass(CodegenProperty codegenProperty) { @@ -67,6 +67,6 @@ private void cacheEnumClass(CodegenProperty codegenProperty) { enumValues.add(valueMap); } MustacheEnum mustacheEnum = new MustacheEnum(StringUtils.toPascalCase(codegenProperty.baseName), enumValues); - ResourceCache.addToEnumClasses(mustacheEnum); + ResourceCacheContext.get().addToEnumClasses(mustacheEnum); } } diff --git a/src/main/java/com/twilio/oai/java/processor/enums/property/ReusableListPropEnumProcessor.java b/src/main/java/com/twilio/oai/java/processor/enums/property/ReusableListPropEnumProcessor.java index 7ed0b42a9..cf1da6b5a 100644 --- a/src/main/java/com/twilio/oai/java/processor/enums/property/ReusableListPropEnumProcessor.java +++ b/src/main/java/com/twilio/oai/java/processor/enums/property/ReusableListPropEnumProcessor.java @@ -3,8 +3,8 @@ import com.twilio.oai.common.EnumConstants.OpenApiEnumType; import com.twilio.oai.common.StringUtils; import com.twilio.oai.common.Utility; +import com.twilio.oai.java.cache.ResourceCacheContext; import com.twilio.oai.java.nestedmodels.MustacheEnum; -import com.twilio.oai.java.ResourceCache; import org.openapitools.codegen.CodegenProperty; import java.util.List; @@ -50,10 +50,17 @@ private void datatype(CodegenProperty codegenProperty) { // enumClassName = Status String enumClassName = Utility.getEnumNameFromDatatype(enumExistingDatatype); // enumNonContainerDatatype = Account.Status - String enumNonContainerDatatype = ResourceCache.getResourceName() + DOT + StringUtils.toPascalCase(enumClassName); + String enumNonContainerDatatype = ResourceCacheContext.get().getResourceName() + DOT + StringUtils.toPascalCase(enumClassName); // resolvedDataType = List String resolvedDataType = Utility.replaceDatatypeInContainer(codegenProperty.dataType, enumNonContainerDatatype); codegenProperty.vendorExtensions.put(X_DATATYPE, resolvedDataType); + + // Resolve BaseType for List as it is used in promoter as setter method. + String baseType = Utility.getEnumNameFromDatatype(codegenProperty.baseType); + if (baseType != null) { + String resolvedBaseType = ResourceCacheContext.get().getResourceName() + DOT + StringUtils.toPascalCase(baseType); + codegenProperty.baseType = resolvedBaseType; + } } private void cacheEnumClass(CodegenProperty codegenProperty) { @@ -62,6 +69,6 @@ private void cacheEnumClass(CodegenProperty codegenProperty) { List> enumValues = (List>) codegenProperty.items.allowableValues.get("enumVars"); MustacheEnum mustacheEnum = new MustacheEnum(enumClassName, enumValues); - ResourceCache.addToEnumClasses(mustacheEnum); + ResourceCacheContext.get().addToEnumClasses(mustacheEnum); } } diff --git a/src/main/java/com/twilio/oai/java/processor/enums/property/ReusablePropEnumProcessor.java b/src/main/java/com/twilio/oai/java/processor/enums/property/ReusablePropEnumProcessor.java index e1de60784..190202449 100644 --- a/src/main/java/com/twilio/oai/java/processor/enums/property/ReusablePropEnumProcessor.java +++ b/src/main/java/com/twilio/oai/java/processor/enums/property/ReusablePropEnumProcessor.java @@ -4,8 +4,8 @@ import com.twilio.oai.common.EnumConstants.OpenApiEnumType; import com.twilio.oai.common.StringUtils; import com.twilio.oai.common.Utility; +import com.twilio.oai.java.cache.ResourceCacheContext; import com.twilio.oai.java.nestedmodels.MustacheEnum; -import com.twilio.oai.java.ResourceCache; import org.openapitools.codegen.CodegenProperty; import java.util.ArrayList; @@ -49,7 +49,7 @@ private void variableName(CodegenProperty codegenProperty) { } private void datatype(CodegenProperty codegenProperty) { String enumDatatypeResolved = StringUtils.toPascalCase(Utility.getEnumNameFromDefaultDatatype(codegenProperty.getRef())); - codegenProperty.vendorExtensions.put(X_DATATYPE, ResourceCache.getResourceName() + DOT + enumDatatypeResolved); + codegenProperty.vendorExtensions.put(X_DATATYPE, ResourceCacheContext.get().getResourceName() + DOT + enumDatatypeResolved); } private void cacheEnumClass(CodegenProperty codegenProperty) { @@ -63,6 +63,6 @@ private void cacheEnumClass(CodegenProperty codegenProperty) { enumValues.add(valueMap); } MustacheEnum mustacheEnum = new MustacheEnum(StringUtils.toPascalCase(enumClassName), enumValues); - ResourceCache.addToEnumClasses(mustacheEnum); + ResourceCacheContext.get().addToEnumClasses(mustacheEnum); } } diff --git a/src/main/java/com/twilio/oai/java/processor/model/ListModelStrategy.java b/src/main/java/com/twilio/oai/java/processor/model/ListModelStrategy.java index f279c8c1f..6819b4578 100644 --- a/src/main/java/com/twilio/oai/java/processor/model/ListModelStrategy.java +++ b/src/main/java/com/twilio/oai/java/processor/model/ListModelStrategy.java @@ -3,8 +3,8 @@ import com.twilio.oai.common.EnumConstants.ModelType; import com.twilio.oai.common.StringUtils; import com.twilio.oai.common.Utility; +import com.twilio.oai.java.cache.ResourceCacheContext; import com.twilio.oai.java.nestedmodels.MustacheModel; -import com.twilio.oai.java.ResourceCache; import org.openapitools.codegen.CodegenModel; import org.openapitools.codegen.CodegenProperty; @@ -47,12 +47,12 @@ private void variableName(CodegenProperty codegenProperty) { private void dataType(CodegenProperty codegenProperty) { //TODO: Need to identify whether the property is defined using ref or directly defined property String datatypeInsideContainer = Utility.extractDatatypeFromContainer(codegenProperty.dataType); - String updatedDataType = Utility.replaceDatatypeInContainer(codegenProperty.dataType, ResourceCache.getResourceName() + DOT + datatypeInsideContainer); + String updatedDataType = Utility.replaceDatatypeInContainer(codegenProperty.dataType, ResourceCacheContext.get().getResourceName() + DOT + datatypeInsideContainer); codegenProperty.vendorExtensions.put(X_DATATYPE, updatedDataType); } private void cacheModelClass(CodegenProperty codegenProperty, CodegenModel codegenModel) { MustacheModel mustacheModel = new MustacheModel(codegenProperty, codegenModel); - ResourceCache.addToModelClasses(mustacheModel); + ResourceCacheContext.get().addToModelClasses(mustacheModel); } } diff --git a/src/main/java/com/twilio/oai/java/processor/model/ModelProcessorFactory.java b/src/main/java/com/twilio/oai/java/processor/model/ModelProcessorFactory.java index 3cd5e546f..79e33cc56 100644 --- a/src/main/java/com/twilio/oai/java/processor/model/ModelProcessorFactory.java +++ b/src/main/java/com/twilio/oai/java/processor/model/ModelProcessorFactory.java @@ -1,6 +1,5 @@ package com.twilio.oai.java.processor.model; -import com.twilio.oai.java.feature.datamodels.DataModelManager; import org.openapitools.codegen.CodegenModel; import org.openapitools.codegen.CodegenProperty; @@ -10,7 +9,6 @@ public class ModelProcessorFactory { private static ModelProcessorFactory instance; private final List modelProcessors; - private DataModelManager dataModelManager = DataModelManager.getInstance(); public static synchronized ModelProcessorFactory getInstance() { if (instance == null) { synchronized (ModelProcessorFactory.class) { diff --git a/src/main/java/com/twilio/oai/java/processor/model/SingleModelStrategy.java b/src/main/java/com/twilio/oai/java/processor/model/SingleModelStrategy.java index 447fec690..f64526599 100644 --- a/src/main/java/com/twilio/oai/java/processor/model/SingleModelStrategy.java +++ b/src/main/java/com/twilio/oai/java/processor/model/SingleModelStrategy.java @@ -2,8 +2,8 @@ import com.twilio.oai.common.StringUtils; +import com.twilio.oai.java.cache.ResourceCacheContext; import com.twilio.oai.java.nestedmodels.MustacheModel; -import com.twilio.oai.java.ResourceCache; import org.openapitools.codegen.CodegenModel; import org.openapitools.codegen.CodegenProperty; @@ -45,12 +45,12 @@ private void variableName(CodegenProperty codegenProperty) { // basetype private void dataType(CodegenProperty codegenProperty) { //TODO: Need to identify whether the property is defined using ref or directly defined property - codegenProperty.vendorExtensions.put(X_DATATYPE, ResourceCache.getResourceName() + DOT + codegenProperty.dataType); + codegenProperty.vendorExtensions.put(X_DATATYPE, ResourceCacheContext.get().getResourceName() + DOT + codegenProperty.dataType); } private void cacheModelClass(CodegenProperty codegenProperty, CodegenModel codegenModel) { MustacheModel mustacheModel = new MustacheModel(codegenProperty, codegenModel); - ResourceCache.addToModelClasses(mustacheModel); + ResourceCacheContext.get().addToModelClasses(mustacheModel); } diff --git a/src/main/java/com/twilio/oai/java/processor/model/parameter/ModelProcessor.java b/src/main/java/com/twilio/oai/java/processor/model/parameter/ModelProcessor.java new file mode 100644 index 000000000..b0ab5cbac --- /dev/null +++ b/src/main/java/com/twilio/oai/java/processor/model/parameter/ModelProcessor.java @@ -0,0 +1,9 @@ +package com.twilio.oai.java.processor.model.parameter; + +import org.openapitools.codegen.CodegenModel; +import org.openapitools.codegen.CodegenParameter; + +public interface ModelProcessor { + boolean shouldProcess(CodegenParameter codegenParameter, CodegenModel codegenModel); + void process(CodegenParameter codegenParameter, CodegenModel codegenModel); +} diff --git a/src/main/java/com/twilio/oai/java/processor/model/parameter/ParamModelProcessorManager.java b/src/main/java/com/twilio/oai/java/processor/model/parameter/ParamModelProcessorManager.java new file mode 100644 index 000000000..071477e04 --- /dev/null +++ b/src/main/java/com/twilio/oai/java/processor/model/parameter/ParamModelProcessorManager.java @@ -0,0 +1,40 @@ +package com.twilio.oai.java.processor.model.parameter; + + +import com.twilio.oai.java.processor.model.ModelProcessorFactory; +import org.openapitools.codegen.CodegenModel; +import org.openapitools.codegen.CodegenParameter; + +import java.util.List; + +public class ParamModelProcessorManager { + private static ParamModelProcessorManager instance; + private final List modelProcessors; + public static synchronized ParamModelProcessorManager getInstance() { + if (instance == null) { + synchronized (ModelProcessorFactory.class) { + if (instance == null) { + instance = new ParamModelProcessorManager(); + } + } + } + return instance; + } + + private ParamModelProcessorManager() { + modelProcessors = List.of( + new SingleModelStrategy() + ); + } + + public void applyProcessor(CodegenParameter codegenParameter, CodegenModel codegenModel) { + + // Process + for (ModelProcessor modelProcessor : modelProcessors) { + if (modelProcessor.shouldProcess(codegenParameter, codegenModel)) { + modelProcessor.process(codegenParameter, codegenModel); + return; + } + } + } +} diff --git a/src/main/java/com/twilio/oai/java/processor/model/parameter/SingleModelStrategy.java b/src/main/java/com/twilio/oai/java/processor/model/parameter/SingleModelStrategy.java new file mode 100644 index 000000000..3f5aa0737 --- /dev/null +++ b/src/main/java/com/twilio/oai/java/processor/model/parameter/SingleModelStrategy.java @@ -0,0 +1,56 @@ +package com.twilio.oai.java.processor.model.parameter; + +import com.twilio.oai.common.EnumConstants; +import com.twilio.oai.common.StringUtils; +import com.twilio.oai.java.cache.ResourceCacheContext; +import com.twilio.oai.java.nestedmodels.MustacheModel; +import org.openapitools.codegen.CodegenModel; +import org.openapitools.codegen.CodegenParameter; + +import static com.twilio.oai.common.ApplicationConstants.DOT; +import static com.twilio.oai.common.ApplicationConstants.X_MODEL_TYPE; +import static com.twilio.oai.common.ApplicationConstants.X_VARIABLE_NAME; + +public class SingleModelStrategy implements ModelProcessor { + EnumConstants.ModelType type = EnumConstants.ModelType.SINGLE; + + @Override + public boolean shouldProcess(CodegenParameter codegenParameter, CodegenModel codegenModel) { + if (!codegenParameter.isContainer) return true; + return false; + } + + @Override + public void process(CodegenParameter codegenParameter, CodegenModel codegenModel) { + if (codegenParameter.isContainer) return; + type(codegenParameter); + variableName(codegenParameter); + dataType(codegenParameter); + cacheModelClass(codegenParameter, codegenModel); + } + + public EnumConstants.ModelType getType() { + return type; + } + + private void type(final CodegenParameter codegenParameter) { + codegenParameter.vendorExtensions.put(X_MODEL_TYPE, type); + } + + private void variableName(CodegenParameter codegenParameter) { + // This will be used in CRUDF(creator, reader etc) classes. + codegenParameter.vendorExtensions.put(X_VARIABLE_NAME, StringUtils.toCamelCase(codegenParameter.baseName)); + } + // basetype + private void dataType(CodegenParameter codegenParameter) { + //TODO: Need to identify whether the property is defined using ref or directly defined property + //codegenParameter.vendorExtensions.put(X_DATATYPE, ResourceCacheContext.get().getResourceName() + DOT + codegenParameter.dataType); + codegenParameter.dataType = ResourceCacheContext.get().getResourceName() + DOT + codegenParameter.dataType; + } + + private void cacheModelClass(CodegenParameter codegenParameter, CodegenModel codegenModel) { + MustacheModel mustacheModel = new MustacheModel(codegenParameter, codegenModel); + ResourceCacheContext.get().addToModelClasses(mustacheModel); + } + +} diff --git a/src/main/java/com/twilio/oai/java/processor/parameter/ParameterProcessor.java b/src/main/java/com/twilio/oai/java/processor/parameter/ParameterProcessor.java index eaa17992c..7fadcc98a 100644 --- a/src/main/java/com/twilio/oai/java/processor/parameter/ParameterProcessor.java +++ b/src/main/java/com/twilio/oai/java/processor/parameter/ParameterProcessor.java @@ -22,6 +22,18 @@ public static synchronized ParameterProcessor getInstance() { } public void process(final CodegenOperation codegenOperation) { + codegenOperation.pathParams.forEach(param -> { + param.paramName = "path" + param.paramName; + }); + + codegenOperation.allParams.stream().filter(param -> param.isPathParam).forEach(param -> { + param.paramName = "path" + param.paramName; + }); + + codegenOperation.requiredParams.stream().filter(param -> param.isPathParam).forEach(param -> { + param.paramName = "path" + param.paramName; + }); + codegenOperation.queryParams.forEach(param -> enumProcessorFactory.applyProcessor(param)); codegenOperation.pathParams.forEach(param -> enumProcessorFactory.applyProcessor(param)); codegenOperation.headerParams.forEach(param -> enumProcessorFactory.applyProcessor(param)); @@ -29,5 +41,7 @@ public void process(final CodegenOperation codegenOperation) { // Required for setter methods and promotion method generation codegenOperation.allParams.forEach(param -> enumProcessorFactory.applyProcessor(param)); + + //codegenOperation.allParams.forEach(param -> enumProcessorFactory.applyProcessor(param)); } } \ No newline at end of file diff --git a/src/main/java/com/twilio/oai/java/processor/requestbody/JsonRequestProcessor.java b/src/main/java/com/twilio/oai/java/processor/requestbody/JsonRequestProcessor.java index c18ccba2c..ed4509aa5 100644 --- a/src/main/java/com/twilio/oai/java/processor/requestbody/JsonRequestProcessor.java +++ b/src/main/java/com/twilio/oai/java/processor/requestbody/JsonRequestProcessor.java @@ -18,7 +18,11 @@ public boolean shouldProcess(final CodegenOperation codegenOperation) { if (codegenOperation.bodyParams != null && !codegenOperation.bodyParams.isEmpty()) return true; return false; } - + + /* + Note: + In json request body parameter could appear as list of codegenProperty or codegenParameter + */ @Override public void process(CodegenOperation codegenOperation) { codegenOperation.vendorExtensions.put(X_REQUEST_CONTENT_TYPE, getContentType()); @@ -29,14 +33,57 @@ public void process(CodegenOperation codegenOperation) { if (codegenOperation.bodyParams.size() > 1) { LoggerUtil.logSevere(this.getClass().getName(), "Multiple request bodies found " + codegenOperation.operationId); } + + processParameter(codegenOperation); - - recursiveModelProcessor.processBody(codegenOperation); - +// if (codegenOperation.bodyParam.vars != null && codegenOperation.bodyParam.vars.size() > 0) { +// processProperty(codegenOperation); +// } else { +// processParameter(codegenOperation); +// } } @Override public String getContentType() { return "application/json"; } + + + /* + If you see in below example, there is no property defined. + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/Cat' + + Cat: + allOf: + - type: object + properties: + account_sid: + type: string + - oneOf: + - $ref: '#/components/schemas/One' + - $ref: '#/components/schemas/Two' + */ + // Process list: codegenOperation.bodyParams + private void processParameter(CodegenOperation codegenOperation) { + if (codegenOperation.bodyParams.isEmpty()) return; + // Request Body has oneOf and its instance variables will be present as CodegenParameter + codegenOperation.bodyParams.stream().forEach(codegenParameter -> recursiveModelProcessor.process(codegenParameter)); + // Used in constructor generation. + codegenOperation.requiredParams.stream().forEach(codegenParameter -> recursiveModelProcessor.process(codegenParameter)); + + + + } + + // List of instance variable can be processed by list: codegenOperation.bodyParam.vars + private void processProperty(CodegenOperation codegenOperation) { + if (codegenOperation.bodyParam != null && codegenOperation.bodyParam.vars.isEmpty()) return; + codegenOperation.bodyParams.stream().forEach(codegenParameter -> recursiveModelProcessor.process(codegenParameter)); + //codegenOperation.bodyParam.vars.stream().forEach(property -> recursiveModelProcessor.processModelRecursively(property)); + } } diff --git a/src/main/java/com/twilio/oai/java/processor/requestbody/RecursiveModelProcessor.java b/src/main/java/com/twilio/oai/java/processor/requestbody/RecursiveModelProcessor.java index 0b5086ee1..f8b0fc989 100644 --- a/src/main/java/com/twilio/oai/java/processor/requestbody/RecursiveModelProcessor.java +++ b/src/main/java/com/twilio/oai/java/processor/requestbody/RecursiveModelProcessor.java @@ -1,26 +1,61 @@ package com.twilio.oai.java.processor.requestbody; import com.twilio.oai.common.Utility; -import com.twilio.oai.java.feature.datamodels.DataModelManager; +import com.twilio.oai.java.cache.ResourceCacheContext; import com.twilio.oai.java.format.Deserializer; import com.twilio.oai.java.processor.enums.EnumProcessorFactory; import com.twilio.oai.java.processor.model.ModelProcessorFactory; +import com.twilio.oai.java.processor.model.parameter.ParamModelProcessorManager; import org.openapitools.codegen.CodegenModel; import org.openapitools.codegen.CodegenOperation; +import org.openapitools.codegen.CodegenParameter; import org.openapitools.codegen.CodegenProperty; -import java.util.List; - public class RecursiveModelProcessor { EnumProcessorFactory enumProcessorFactory = EnumProcessorFactory.getInstance(); ModelProcessorFactory modelProcessorFactory = ModelProcessorFactory.getInstance(); + ParamModelProcessorManager paramModelProcessorManager = ParamModelProcessorManager.getInstance(); public void processBody(CodegenOperation codegenOperation) { // codegenOperation.bodyParam.vars.get(3).ref: #/components/schemas/types + codegenOperation.bodyParam.vars.forEach(property -> processModelRecursively(property)); } + public void process(CodegenProperty codegenProperty) { + processModelRecursively(codegenProperty); + } + + public void process(CodegenParameter codegenParameter) { + CodegenModel codegenModel = ResourceCacheContext.get().getAllModelsByDefaultGenerator().stream() + .filter(model -> model.classname.equalsIgnoreCase(codegenParameter.dataType)) + .findFirst() + .orElse(null); + if (codegenModel == null) return; + + paramModelProcessorManager.applyProcessor(codegenParameter, codegenModel); + + if (codegenModel.vars != null && !codegenModel.vars.isEmpty()) { + for (CodegenProperty modelProperty : codegenModel.vars) { + processModelRecursively(modelProperty); + } + } + } + + // Only in case of oneOf or allOf + public void processModelRecursively(CodegenParameter codegenParameter, CodegenModel codegenModel) { + + + paramModelProcessorManager.applyProcessor(codegenParameter, codegenModel); + + if (codegenModel.vars != null && !codegenModel.vars.isEmpty()) { + for (CodegenProperty modelProperty : codegenModel.vars) { + processModelRecursively(modelProperty); + } + } + } + public void processResponse(final CodegenOperation codegenOperation) { // Make sure to filter pagination models. return ; @@ -28,7 +63,7 @@ public void processResponse(final CodegenOperation codegenOperation) { // DFS based recursive logic - private void processModelRecursively(final CodegenProperty codegenProperty) { + public void processModelRecursively(final CodegenProperty codegenProperty) { CodegenModel codegenModel = Utility.getModelFromOpenApiType(codegenProperty); /* This code block has access to all the codegenProperty for a nested model. diff --git a/src/main/java/com/twilio/oai/java/processor/responsebody/JsonResponseProcessor.java b/src/main/java/com/twilio/oai/java/processor/responsebody/JsonResponseProcessor.java index b0e4a3671..528ce1c32 100644 --- a/src/main/java/com/twilio/oai/java/processor/responsebody/JsonResponseProcessor.java +++ b/src/main/java/com/twilio/oai/java/processor/responsebody/JsonResponseProcessor.java @@ -1,9 +1,10 @@ package com.twilio.oai.java.processor.responsebody; import com.twilio.oai.common.Utility; +import com.twilio.oai.java.cache.ResourceCacheContext; import com.twilio.oai.java.format.Deserializer; -import com.twilio.oai.java.ResourceCache; import com.twilio.oai.java.processor.enums.EnumProcessorFactory; +import com.twilio.oai.java.processor.requestbody.RecursiveModelProcessor; import org.openapitools.codegen.CodegenMediaType; import org.openapitools.codegen.CodegenModel; import org.openapitools.codegen.CodegenOperation; @@ -14,10 +15,14 @@ public class JsonResponseProcessor implements ResponseProcessor { EnumProcessorFactory enumProcessorFactory = EnumProcessorFactory.getInstance(); + RecursiveModelProcessor recursiveModelProcessor = new RecursiveModelProcessor(); @Override public void process(final CodegenOperation codegenOperation) { System.out.println(codegenOperation.operationId); + // delete operation does not have response body + if (codegenOperation.operationId.toLowerCase().startsWith("delete")) return; + CodegenModel codegenModel = getModel(codegenOperation); if (codegenModel == null) return; CodegenModel responseModel = codegenModel; @@ -31,7 +36,8 @@ public void process(final CodegenOperation codegenOperation) { enumProcessorFactory.applyProcessor(codegenProperty); Deserializer.addDeserializer(codegenProperty); }); - responseModel.vars.forEach(ResourceCache.getResponse()::add); + responseModel.vars.stream().forEach(property -> recursiveModelProcessor.process(property)); + responseModel.vars.forEach(ResourceCacheContext.get().getResponse()::add); } //model.vars.get(0).items.ref to get actual output @@ -71,7 +77,7 @@ private CodegenModel getModel(final CodegenOperation codegenOperation) { if (codegenOperation.responses != null && !codegenOperation.responses.isEmpty()) { for (CodegenResponse codegenResponse: codegenOperation.responses) { if (codegenResponse.is2xx || codegenResponse.is3xx) { - if (codegenResponse == null) return null; + if (codegenResponse == null || codegenResponse.getContent() == null) return null; CodegenMediaType codegenMediaType = codegenResponse.getContent().get(getContentType()); if (codegenMediaType == null) return null; if (codegenMediaType.getSchema().isContainer) { diff --git a/src/main/resources/twilio-java-modern/allConstructors.mustache b/src/main/resources/twilio-java-modern/allConstructors.mustache index 2ac4ec1f7..26fc4e4bb 100644 --- a/src/main/resources/twilio-java-modern/allConstructors.mustache +++ b/src/main/resources/twilio-java-modern/allConstructors.mustache @@ -52,7 +52,7 @@ {{#vendorExtensions.x-update-operation}} {{#vendorExtensions.x-signature-list}} - public {{resourceName}}Updater updater({{#.}}final {{{dataType}}} {{paramName}}{{^-last}}, {{/-last}}{{/.}}) { + public static {{resourceName}}Updater updater({{#.}}final {{{dataType}}} {{paramName}}{{^-last}}, {{/-last}}{{/.}}) { return new {{resourceName}}Updater( {{#.}} {{paramName}}{{^-last}}, {{/-last}}{{/.}} ); diff --git a/src/main/resources/twilio-java-modern/common/addPostParamsJson.mustache b/src/main/resources/twilio-java-modern/common/addPostParamsJson.mustache new file mode 100644 index 000000000..d87b90b7c --- /dev/null +++ b/src/main/resources/twilio-java-modern/common/addPostParamsJson.mustache @@ -0,0 +1,8 @@ +private void addPostParams(final Request request, TwilioRestClient client) { + ObjectMapper objectMapper = client.getObjectMapper(); + {{#bodyParams}} + if ({{paramName}} != null) { + request.setBody({{resourceName}}.toJson({{paramName}}, objectMapper)); + } + {{/bodyParams}} +} \ No newline at end of file diff --git a/src/main/resources/twilio-java-modern/common/imports.mustache b/src/main/resources/twilio-java-modern/common/imports.mustache index 90bcdcc3b..487a9f6f5 100644 --- a/src/main/resources/twilio-java-modern/common/imports.mustache +++ b/src/main/resources/twilio-java-modern/common/imports.mustache @@ -35,10 +35,12 @@ import com.twilio.type.PhoneNumberCapabilities; import com.twilio.type.PhoneNumberPrice; import com.twilio.type.RecordingRule; import com.twilio.type.SubscribeRule; +import lombok.Builder; import lombok.Getter; import lombok.Setter; import lombok.ToString; + import java.io.InputStream; import java.math.BigDecimal; import java.net.URI; @@ -51,4 +53,7 @@ import com.twilio.type.*; import java.util.Objects; import com.twilio.base.Resource; import java.io.IOException; -import com.fasterxml.jackson.core.JsonParseException; \ No newline at end of file +import com.fasterxml.jackson.core.JsonParseException; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder; +import com.fasterxml.jackson.core.JsonProcessingException; \ No newline at end of file diff --git a/src/main/resources/twilio-java-modern/common/instanceVariables.mustache b/src/main/resources/twilio-java-modern/common/instanceVariables.mustache index 5aa1fae53..6040b44dd 100644 --- a/src/main/resources/twilio-java-modern/common/instanceVariables.mustache +++ b/src/main/resources/twilio-java-modern/common/instanceVariables.mustache @@ -9,4 +9,7 @@ {{/headerParams}} {{#formParams}} private {{{dataType}}} {{paramName}}; -{{/formParams}} \ No newline at end of file +{{/formParams}} +{{#bodyParams}} + private {{{dataType}}} {{paramName}}; +{{/bodyParams}} \ No newline at end of file diff --git a/src/main/resources/twilio-java-modern/creator.mustache b/src/main/resources/twilio-java-modern/creator.mustache index 7b46f64b9..521f180c0 100644 --- a/src/main/resources/twilio-java-modern/creator.mustache +++ b/src/main/resources/twilio-java-modern/creator.mustache @@ -21,6 +21,9 @@ public class {{resourceName}}Creator extends Creator<{{resourceName}}> { {{#headerParams.0}} {{>common/addHeaderParams}} {{/headerParams.0}} +{{#bodyParams.0}} + {{>common/addPostParamsJson}} +{{/bodyParams.0}} } {{/vendorExtensions.x-create-operation}} {{/operations}} diff --git a/src/main/resources/twilio-java-modern/models.mustache b/src/main/resources/twilio-java-modern/models.mustache index a04bfb227..b23a58c91 100644 --- a/src/main/resources/twilio-java-modern/models.mustache +++ b/src/main/resources/twilio-java-modern/models.mustache @@ -1,19 +1,19 @@ {{#mustacheModels}} - @JsonDeserialize(builder = {{className}}.Builder.class) + //@JsonDeserialize(builder = {{className}}.Builder.class) @JsonInclude(JsonInclude.Include.NON_EMPTY) @ToString - @Builder +{{!@Builder}} public static class {{className}} { + {{#mandatoryProperties.0}} + public {{className}}({{#mandatoryProperties}} final {{{dataType}}} {{name}}{{^-last}}, {{/-last}} {{/mandatoryProperties}}) { {{#mandatoryProperties}} - public {{classname}}({{#.}}final {{{dataType}}} {{name}}{{^-last}}, {{/-last}}{{/.}} ) { - {{#.}} - this.{{name}} = {{name}}; - {{/.}} - } + this.{{name}} = {{name}}; {{/mandatoryProperties}} - - {{#optionalProperties}} + } + {{/mandatoryProperties.0}} + + {{#allProperties}} {{#vendorExtensions.x-deserializer}} @JsonDeserialize(using = {{vendorExtensions.x-deserializer}}.class) {{/vendorExtensions.x-deserializer}} @@ -21,8 +21,8 @@ @JsonProperty("{{{baseName}}}") @Getter @Setter private {{{dataType}}} {{name}}; - {{/optionalProperties}} - @JsonPOJOBuilder(withPrefix = "") - public static class Builder {} + {{/allProperties}} +{{! @JsonPOJOBuilder(withPrefix = "") +public static class Builder {}} } {{/mustacheModels}} diff --git a/src/main/resources/twilio-java-modern/staticMethods.mustache b/src/main/resources/twilio-java-modern/staticMethods.mustache index 903f7fc14..b24223857 100644 --- a/src/main/resources/twilio-java-modern/staticMethods.mustache +++ b/src/main/resources/twilio-java-modern/staticMethods.mustache @@ -33,4 +33,16 @@ } catch (final IOException e) { throw new ApiConnectionException(e.getMessage(), e); } + } + + public static String toJson(Object object, ObjectMapper mapper) { + try { + return mapper.writeValueAsString(object); + } catch (final JsonMappingException e) { + throw new ApiException(e.getMessage(), e); + } catch (JsonProcessingException e) { + throw new ApiException(e.getMessage(), e); + } catch (final IOException e) { + throw new ApiConnectionException(e.getMessage(), e); + } } \ No newline at end of file diff --git a/src/main/resources/twilio-java-modern/updater.mustache b/src/main/resources/twilio-java-modern/updater.mustache index 1da336a3a..e447ea9f5 100644 --- a/src/main/resources/twilio-java-modern/updater.mustache +++ b/src/main/resources/twilio-java-modern/updater.mustache @@ -19,6 +19,9 @@ package com.twilio.rest.{{domainPackage}}.{{apiVersion}}{{namespaceSubPart}}; {{#headerParams.0}} {{>common/addHeaderParams}} {{/headerParams.0}} + {{#bodyParams.0}} + {{>common/addPostParamsJson}} + {{/bodyParams.0}} } {{/vendorExtensions.x-update-operation}} {{/operations}} diff --git a/src/test/java/com/twilio/oai/TwilioGeneratorTest.java b/src/test/java/com/twilio/oai/TwilioGeneratorTest.java index a44b23aee..02acf94b8 100644 --- a/src/test/java/com/twilio/oai/TwilioGeneratorTest.java +++ b/src/test/java/com/twilio/oai/TwilioGeneratorTest.java @@ -41,8 +41,6 @@ public static void setUp() { @Test public void launchGenerator() { final String pathname = "examples/spec/twilio_api_v2010.yaml"; - //final String pathname = "examples/test_spec/twilio_testenum_v1.yaml"; - //final String pathname = "/Users/sbansla/Documents/code/twilio-oai/spec/yaml/twilio_content_v1.yaml"; File filesList[] ; File directoryPath = new File(pathname); if (directoryPath.isDirectory()) { From b064d81c6086810516f18bab9e2d35e91c663c18 Mon Sep 17 00:00:00 2001 From: sbansla Date: Fri, 12 Sep 2025 15:51:44 +0530 Subject: [PATCH 16/38] test enabled --- .github/workflows/test.yml | 70 +++++++++++++++++++------------------- 1 file changed, 35 insertions(+), 35 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index c5b9da6bb..4093d3ae7 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -25,42 +25,42 @@ jobs: with: fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis -# - name: Set up Java 11 -# uses: actions/setup-java@v4 -# with: -# distribution: 'zulu' -# java-version: '11' -# -# - name: Login to Docker Hub -# if: env.DOCKER_LOGIN -# uses: docker/login-action@v3 -# with: -# username: ${{ secrets.DOCKER_USERNAME }} -# password: ${{ secrets.DOCKER_AUTH_TOKEN }} -# -# - name: Run unit tests -# run: make test -# -# - name: Run helper tests and sonar analysis -# run: make test-docker SONAR_TOKEN=${{ secrets.SONAR_TOKEN }} LANGUAGES=${{ matrix.language }} -# -# - name: Show git status and fail on diff -# run: | -# git status -# git diff -# test -z "$(git status --porcelain)" -# -# - name: Remove pom file # Otherwise, the Sonar action fails and recommends using the Maven plugin -# run: rm pom.xml + - name: Set up Java 11 + uses: actions/setup-java@v4 + with: + distribution: 'zulu' + java-version: '11' + + - name: Login to Docker Hub + if: env.DOCKER_LOGIN + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_AUTH_TOKEN }} + + - name: Run unit tests + run: make test + + - name: Run helper tests and sonar analysis + run: make test-docker SONAR_TOKEN=${{ secrets.SONAR_TOKEN }} LANGUAGES=${{ matrix.language }} -# - name: Install SonarCloud scanner and run analysis -# uses: SonarSource/sonarcloud-github-action@master -# if: (github.event_name == 'pull_request' || github.ref_type == 'branch') && !github.event.pull_request.head.repo.fork && startsWith(matrix.language, 'csharp') != true -# with: -# projectBaseDir: examples/${{ matrix.language }} -# env: -# GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed to get PR information, if any -# SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} + - name: Show git status and fail on diff + run: | + git status + git diff + test -z "$(git status --porcelain)" + + - name: Remove pom file # Otherwise, the Sonar action fails and recommends using the Maven plugin + run: rm pom.xml + + - name: Install SonarCloud scanner and run analysis + uses: SonarSource/sonarcloud-github-action@master + if: (github.event_name == 'pull_request' || github.ref_type == 'branch') && !github.event.pull_request.head.repo.fork && startsWith(matrix.language, 'csharp') != true + with: + projectBaseDir: examples/${{ matrix.language }} + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed to get PR information, if any + SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} notify-on-failure: name: Slack notify on failure From 6ccaae0f05c01b4c6daf44df1e63e75d2b221057 Mon Sep 17 00:00:00 2001 From: sbansla Date: Fri, 12 Sep 2025 15:52:58 +0530 Subject: [PATCH 17/38] disabled sonar --- .github/workflows/test.yml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 4093d3ae7..fc7470505 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -53,14 +53,14 @@ jobs: - name: Remove pom file # Otherwise, the Sonar action fails and recommends using the Maven plugin run: rm pom.xml - - name: Install SonarCloud scanner and run analysis - uses: SonarSource/sonarcloud-github-action@master - if: (github.event_name == 'pull_request' || github.ref_type == 'branch') && !github.event.pull_request.head.repo.fork && startsWith(matrix.language, 'csharp') != true - with: - projectBaseDir: examples/${{ matrix.language }} - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed to get PR information, if any - SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} +# - name: Install SonarCloud scanner and run analysis +# uses: SonarSource/sonarcloud-github-action@master +# if: (github.event_name == 'pull_request' || github.ref_type == 'branch') && !github.event.pull_request.head.repo.fork && startsWith(matrix.language, 'csharp') != true +# with: +# projectBaseDir: examples/${{ matrix.language }} +# env: +# GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed to get PR information, if any +# SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} notify-on-failure: name: Slack notify on failure From 8c68faec129e9925d95e31c8747073c4bb1ddd99 Mon Sep 17 00:00:00 2001 From: sbansla Date: Fri, 12 Sep 2025 15:55:27 +0530 Subject: [PATCH 18/38] disabled python release --- .../com/twilio/oai/TwilioPythonGenerator.java | 298 +++++++++--------- 1 file changed, 149 insertions(+), 149 deletions(-) diff --git a/src/main/java/com/twilio/oai/TwilioPythonGenerator.java b/src/main/java/com/twilio/oai/TwilioPythonGenerator.java index f09f23ee1..92c67f7a2 100644 --- a/src/main/java/com/twilio/oai/TwilioPythonGenerator.java +++ b/src/main/java/com/twilio/oai/TwilioPythonGenerator.java @@ -1,149 +1,149 @@ -package com.twilio.oai; - -import com.twilio.oai.api.ApiResources; -import com.twilio.oai.api.PythonApiResourceBuilder; -import com.twilio.oai.common.EnumConstants; -import com.twilio.oai.common.Utility; -import com.twilio.oai.resolver.IConventionMapper; -import com.twilio.oai.resolver.LanguageConventionResolver; -import com.twilio.oai.resolver.python.PythonCodegenModelResolver; -import com.twilio.oai.resolver.python.PythonCaseResolver; -import com.twilio.oai.resolver.python.PythonParameterResolver; -import com.twilio.oai.resolver.python.PythonPropertyResolver; -import com.twilio.oai.resource.IResourceTree; -import com.twilio.oai.resource.ResourceMap; -import com.twilio.oai.template.PythonApiActionTemplate; - -import java.io.File; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import io.swagger.v3.oas.models.OpenAPI; -import io.swagger.v3.oas.models.PathItem; -import org.openapitools.codegen.CodegenModel; -import org.openapitools.codegen.CodegenOperation; -import org.openapitools.codegen.languages.PythonClientCodegen; -//import org.openapitools.codegen.languages.PythonLegacyClientCodegen; -import org.openapitools.codegen.model.ModelMap; -import org.openapitools.codegen.model.ModelsMap; -import org.openapitools.codegen.model.OperationsMap; - -import static com.twilio.oai.common.ApplicationConstants.CONFIG_PYTHON_JSON_PATH; - -public class TwilioPythonGenerator extends PythonClientCodegen { - private final TwilioCodegenAdapter twilioCodegen; - private final PythonApiActionTemplate actionTemplate = new PythonApiActionTemplate(this); - private final IResourceTree resourceTree = new ResourceMap(new Inflector()); - private final DirectoryStructureService directoryStructureService = new DirectoryStructureService( - additionalProperties, - resourceTree, - new PythonCaseResolver()); - private final List allModels = new ArrayList<>(); - private final Map modelFormatMap = new HashMap<>(); - public static final String JSON_INGRESS = "json_ingress"; - - public TwilioPythonGenerator() { - super(); - twilioCodegen = new TwilioCodegenAdapter(this, getName()); - packageName = ""; - - typeMapping.put("array", "List"); - } - - @Override - public void processOpts() { - twilioCodegen.processOpts(); - } - - @Override - public void processOpenAPI(final OpenAPI openAPI) { - String domain = StringHelper.toSnakeCase(twilioCodegen.getDomainFromOpenAPI(openAPI)); - String version = StringHelper.toSnakeCase(twilioCodegen.getVersionFromOpenAPI(openAPI)); - twilioCodegen.setDomain(domain); - twilioCodegen.setVersion(version); - twilioCodegen.setOutputDir(domain, version); - - openAPI.getPaths().forEach(resourceTree::addResource); - resourceTree.getResources().forEach(resource -> resource.updateFamily(resourceTree)); - - directoryStructureService.configure(openAPI); - } - - @Override - public String apiFilename(final String templateName, final String tag) { - final String initFilename = "__init__.py"; - final String filename = actionTemplate.apiFilename(templateName, super.apiFilename(templateName, tag)); - - final boolean isInitFile = this.openAPI.getPaths().entrySet().stream().anyMatch(pathsEntry -> { - final String resourcePath = pathsEntry.getKey(); - final PathItem path = pathsEntry.getValue(); - final boolean isMatchingPath = path - .readOperations() - .stream() - .anyMatch(operation -> operation.getTags().contains(tag)); - final boolean pathHasDependents = !resourceTree.dependents(resourcePath).isEmpty(); - - return isMatchingPath && pathHasDependents; - }); - - if (isInitFile && !filename.endsWith(initFilename)) { - return PathUtils.removeExtension(filename) + File.separator + initFilename; - } - - return filename; - } - - @Override - public String toApiFilename(final String name) { - return directoryStructureService.toApiFilename(name); - } - - @Override - public Map postProcessAllModels(final Map allModels) { - final Map results = super.postProcessAllModels(allModels); - - Utility.addModelsToLocalModelList(results, this.allModels); - directoryStructureService.postProcessAllModels(results, modelFormatMap); - - // Return an empty collection so no model files get generated. - return new HashMap<>(); - } - - @Override - public OperationsMap postProcessOperationsWithModels(final OperationsMap objs, List allModels) { - final List opList = directoryStructureService.processOperations(objs); - objs.put("resources", generateResources(opList)); - return objs; - } - - private ApiResources generateResources(final List opList) { - final IConventionMapper conventionMapper = new LanguageConventionResolver(CONFIG_PYTHON_JSON_PATH); - final PythonCodegenModelResolver codegenModelResolver = new PythonCodegenModelResolver(conventionMapper, - modelFormatMap, - List.of(EnumConstants.PythonDataTypes.values())); - - PythonApiResourceBuilder pythonApiResourceBuilder = new PythonApiResourceBuilder(actionTemplate, opList, allModels, directoryStructureService, twilioCodegen.getToggles(JSON_INGRESS)); - pythonApiResourceBuilder.updateApiPath() - .updateTemplate() - .updateOperations(new PythonParameterResolver(conventionMapper, codegenModelResolver)); - return pythonApiResourceBuilder.updateResponseModel(new PythonPropertyResolver(conventionMapper), codegenModelResolver) - .build(); - } - - @Override - public String getName() { - return EnumConstants.Generator.TWILIO_PYTHON.getValue(); - } - - @Override - public String toParamName(final String name) { - return StringHelper.toSnakeCase(twilioCodegen.toParamName(name)); - } - - @Override - public String defaultTemplatingEngine() { - return "twilio-handlebars"; - } -} +//package com.twilio.oai; +// +//import com.twilio.oai.api.ApiResources; +//import com.twilio.oai.api.PythonApiResourceBuilder; +//import com.twilio.oai.common.EnumConstants; +//import com.twilio.oai.common.Utility; +//import com.twilio.oai.resolver.IConventionMapper; +//import com.twilio.oai.resolver.LanguageConventionResolver; +//import com.twilio.oai.resolver.python.PythonCodegenModelResolver; +//import com.twilio.oai.resolver.python.PythonCaseResolver; +//import com.twilio.oai.resolver.python.PythonParameterResolver; +//import com.twilio.oai.resolver.python.PythonPropertyResolver; +//import com.twilio.oai.resource.IResourceTree; +//import com.twilio.oai.resource.ResourceMap; +//import com.twilio.oai.template.PythonApiActionTemplate; +// +//import java.io.File; +//import java.util.ArrayList; +//import java.util.HashMap; +//import java.util.List; +//import java.util.Map; +// +//import io.swagger.v3.oas.models.OpenAPI; +//import io.swagger.v3.oas.models.PathItem; +//import org.openapitools.codegen.CodegenModel; +//import org.openapitools.codegen.CodegenOperation; +//import org.openapitools.codegen.languages.PythonClientCodegen; +////import org.openapitools.codegen.languages.PythonLegacyClientCodegen; +//import org.openapitools.codegen.model.ModelMap; +//import org.openapitools.codegen.model.ModelsMap; +//import org.openapitools.codegen.model.OperationsMap; +// +//import static com.twilio.oai.common.ApplicationConstants.CONFIG_PYTHON_JSON_PATH; +// +//public class TwilioPythonGenerator extends PythonClientCodegen { +// private final TwilioCodegenAdapter twilioCodegen; +// private final PythonApiActionTemplate actionTemplate = new PythonApiActionTemplate(this); +// private final IResourceTree resourceTree = new ResourceMap(new Inflector()); +// private final DirectoryStructureService directoryStructureService = new DirectoryStructureService( +// additionalProperties, +// resourceTree, +// new PythonCaseResolver()); +// private final List allModels = new ArrayList<>(); +// private final Map modelFormatMap = new HashMap<>(); +// public static final String JSON_INGRESS = "json_ingress"; +// +// public TwilioPythonGenerator() { +// super(); +// twilioCodegen = new TwilioCodegenAdapter(this, getName()); +// packageName = ""; +// +// typeMapping.put("array", "List"); +// } +// +// @Override +// public void processOpts() { +// twilioCodegen.processOpts(); +// } +// +// @Override +// public void processOpenAPI(final OpenAPI openAPI) { +// String domain = StringHelper.toSnakeCase(twilioCodegen.getDomainFromOpenAPI(openAPI)); +// String version = StringHelper.toSnakeCase(twilioCodegen.getVersionFromOpenAPI(openAPI)); +// twilioCodegen.setDomain(domain); +// twilioCodegen.setVersion(version); +// twilioCodegen.setOutputDir(domain, version); +// +// openAPI.getPaths().forEach(resourceTree::addResource); +// resourceTree.getResources().forEach(resource -> resource.updateFamily(resourceTree)); +// +// directoryStructureService.configure(openAPI); +// } +// +// @Override +// public String apiFilename(final String templateName, final String tag) { +// final String initFilename = "__init__.py"; +// final String filename = actionTemplate.apiFilename(templateName, super.apiFilename(templateName, tag)); +// +// final boolean isInitFile = this.openAPI.getPaths().entrySet().stream().anyMatch(pathsEntry -> { +// final String resourcePath = pathsEntry.getKey(); +// final PathItem path = pathsEntry.getValue(); +// final boolean isMatchingPath = path +// .readOperations() +// .stream() +// .anyMatch(operation -> operation.getTags().contains(tag)); +// final boolean pathHasDependents = !resourceTree.dependents(resourcePath).isEmpty(); +// +// return isMatchingPath && pathHasDependents; +// }); +// +// if (isInitFile && !filename.endsWith(initFilename)) { +// return PathUtils.removeExtension(filename) + File.separator + initFilename; +// } +// +// return filename; +// } +// +// @Override +// public String toApiFilename(final String name) { +// return directoryStructureService.toApiFilename(name); +// } +// +// @Override +// public Map postProcessAllModels(final Map allModels) { +// final Map results = super.postProcessAllModels(allModels); +// +// Utility.addModelsToLocalModelList(results, this.allModels); +// directoryStructureService.postProcessAllModels(results, modelFormatMap); +// +// // Return an empty collection so no model files get generated. +// return new HashMap<>(); +// } +// +// @Override +// public OperationsMap postProcessOperationsWithModels(final OperationsMap objs, List allModels) { +// final List opList = directoryStructureService.processOperations(objs); +// objs.put("resources", generateResources(opList)); +// return objs; +// } +// +// private ApiResources generateResources(final List opList) { +// final IConventionMapper conventionMapper = new LanguageConventionResolver(CONFIG_PYTHON_JSON_PATH); +// final PythonCodegenModelResolver codegenModelResolver = new PythonCodegenModelResolver(conventionMapper, +// modelFormatMap, +// List.of(EnumConstants.PythonDataTypes.values())); +// +// PythonApiResourceBuilder pythonApiResourceBuilder = new PythonApiResourceBuilder(actionTemplate, opList, allModels, directoryStructureService, twilioCodegen.getToggles(JSON_INGRESS)); +// pythonApiResourceBuilder.updateApiPath() +// .updateTemplate() +// .updateOperations(new PythonParameterResolver(conventionMapper, codegenModelResolver)); +// return pythonApiResourceBuilder.updateResponseModel(new PythonPropertyResolver(conventionMapper), codegenModelResolver) +// .build(); +// } +// +// @Override +// public String getName() { +// return EnumConstants.Generator.TWILIO_PYTHON.getValue(); +// } +// +// @Override +// public String toParamName(final String name) { +// return StringHelper.toSnakeCase(twilioCodegen.toParamName(name)); +// } +// +// @Override +// public String defaultTemplatingEngine() { +// return "twilio-handlebars"; +// } +//} From e25edfc65c8d83f8624e687476e1b9b0a8fc731f Mon Sep 17 00:00:00 2001 From: sbansla Date: Fri, 12 Sep 2025 16:02:29 +0530 Subject: [PATCH 19/38] remove spec --- examples/{spec => test_spec}/twilio_enum_v1.yaml | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename examples/{spec => test_spec}/twilio_enum_v1.yaml (100%) diff --git a/examples/spec/twilio_enum_v1.yaml b/examples/test_spec/twilio_enum_v1.yaml similarity index 100% rename from examples/spec/twilio_enum_v1.yaml rename to examples/test_spec/twilio_enum_v1.yaml From 6609f4a2e573578d7fff76bf1ca7789819b0a47a Mon Sep 17 00:00:00 2001 From: sbansla Date: Fri, 12 Sep 2025 16:12:59 +0530 Subject: [PATCH 20/38] skipped orgs spec --- .../{spec => skipped_orgs_spec}/twilio_iam_organizations.yaml | 0 .../{spec => skipped_orgs_spec}/twilio_iam_organizations_v1.yaml | 0 .../twilio_iam_organizations_versionless.yaml | 0 examples/{spec => skipped_orgs_spec}/twilio_iam_v1.yaml | 0 4 files changed, 0 insertions(+), 0 deletions(-) rename examples/{spec => skipped_orgs_spec}/twilio_iam_organizations.yaml (100%) rename examples/{spec => skipped_orgs_spec}/twilio_iam_organizations_v1.yaml (100%) rename examples/{spec => skipped_orgs_spec}/twilio_iam_organizations_versionless.yaml (100%) rename examples/{spec => skipped_orgs_spec}/twilio_iam_v1.yaml (100%) diff --git a/examples/spec/twilio_iam_organizations.yaml b/examples/skipped_orgs_spec/twilio_iam_organizations.yaml similarity index 100% rename from examples/spec/twilio_iam_organizations.yaml rename to examples/skipped_orgs_spec/twilio_iam_organizations.yaml diff --git a/examples/spec/twilio_iam_organizations_v1.yaml b/examples/skipped_orgs_spec/twilio_iam_organizations_v1.yaml similarity index 100% rename from examples/spec/twilio_iam_organizations_v1.yaml rename to examples/skipped_orgs_spec/twilio_iam_organizations_v1.yaml diff --git a/examples/spec/twilio_iam_organizations_versionless.yaml b/examples/skipped_orgs_spec/twilio_iam_organizations_versionless.yaml similarity index 100% rename from examples/spec/twilio_iam_organizations_versionless.yaml rename to examples/skipped_orgs_spec/twilio_iam_organizations_versionless.yaml diff --git a/examples/spec/twilio_iam_v1.yaml b/examples/skipped_orgs_spec/twilio_iam_v1.yaml similarity index 100% rename from examples/spec/twilio_iam_v1.yaml rename to examples/skipped_orgs_spec/twilio_iam_v1.yaml From 96724ede7e9eeac79c0d79e4a3c8acb6cb09780f Mon Sep 17 00:00:00 2001 From: sbansla Date: Fri, 12 Sep 2025 17:23:27 +0530 Subject: [PATCH 21/38] renamed twilio-java to twilio-java-legacy --- .../com/twilio/oai/TwilioJavaGenerator.java | 6 +- .../twilio/oai/TwilioJavaGeneratorModern.java | 2 +- .../com/twilio/oai/common/EnumConstants.java | 1 + .../resolver/java/JavaParameterResolver.java | 2 +- .../resolver/java/JavaPropertyResolver.java | 2 +- .../resolver/node/NodePropertyResolver.java | 2 +- src/main/resources/config/toggles.json | 2 +- .../resources/twilio-java-legacy/api.mustache | 167 ++++++++++++++ .../api_doc.mustache | 0 .../api_test.mustache | 0 .../twilio-java-legacy/creator.mustache | 136 ++++++++++++ .../dateParams.mustache | 0 .../dateTimeGroupParams.mustache | 0 .../twilio-java-legacy/deleter.mustache | 129 +++++++++++ .../twilio-java-legacy/enums.mustache | 24 +++ .../twilio-java-legacy/fetcher.mustache | 131 +++++++++++ .../generate_uri.mustache | 0 .../headerParams.mustache | 0 .../licenseInfo.mustache | 0 .../twilio-java-legacy/models.mustache | 41 ++++ .../packageName.mustache | 0 .../postParams.mustache | 0 .../postParams_body.mustache | 0 .../prefixedCollapsibleMapQParams.mustache | 0 .../queryParams.mustache | 0 .../twilio-java-legacy/reader.mustache | 186 ++++++++++++++++ .../responseModel.mustache | 0 .../twilio-java-legacy/updater.mustache | 132 ++++++++++++ .../resources/twilio-java-modern/api.mustache | 21 -- .../twilio-java-modern/creator.mustache | 30 --- .../twilio-java-modern/deleter.mustache | 23 -- .../twilio-java-modern/enums.mustache | 22 -- .../twilio-java-modern/fetcher.mustache | 23 -- .../twilio-java-modern/models.mustache | 28 --- .../twilio-java-modern/reader.mustache | 25 --- .../twilio-java-modern/updater.mustache | 28 --- .../Readme.md | 0 .../allConstructors.mustache | 0 src/main/resources/twilio-java/api.mustache | 162 +------------- .../common/addHeaderParams.mustache | 0 .../common/addPostParams.mustache | 0 .../common/addPostParamsJson.mustache | 0 .../common/addQueryParams.mustache | 0 .../common/constructors.mustache | 0 .../common/generateUri.mustache | 0 .../common/imports.mustache | 0 .../common/instanceVariables.mustache | 0 .../common/operationMethod.mustache | 0 .../common/setters.mustache | 0 .../resources/twilio-java/creator.mustache | 156 +++----------- .../creator/operationMethod.mustache | 0 .../creator/setters.mustache | 0 .../resources/twilio-java/deleter.mustache | 144 ++----------- .../deleter/operationMethod.mustache | 0 .../deleter/setters.mustache | 0 src/main/resources/twilio-java/enums.mustache | 34 ++- .../equalsAndHashcode.mustache | 0 .../resources/twilio-java/fetcher.mustache | 146 ++----------- .../fetcher/operationMethod.mustache | 0 .../fetcher/setters.mustache | 0 .../resources/twilio-java/models.mustache | 65 +++--- .../resources/twilio-java/reader.mustache | 203 ++---------------- .../reader/operationMethod.mustache | 0 .../reader/paginationMethods.mustache | 0 .../reader/setters.mustache | 0 .../response.mustache | 0 .../staticMethods.mustache | 0 .../resources/twilio-java/updater.mustache | 152 +++---------- .../updater/operationMethod.mustache | 0 .../updater/setters.mustache | 0 .../com/twilio/oai/TwilioGeneratorTest.java | 2 +- src/test/resources/config/test_toggles.json | 2 +- 72 files changed, 1115 insertions(+), 1114 deletions(-) create mode 100644 src/main/resources/twilio-java-legacy/api.mustache rename src/main/resources/{twilio-java => twilio-java-legacy}/api_doc.mustache (100%) rename src/main/resources/{twilio-java => twilio-java-legacy}/api_test.mustache (100%) create mode 100644 src/main/resources/twilio-java-legacy/creator.mustache rename src/main/resources/{twilio-java => twilio-java-legacy}/dateParams.mustache (100%) rename src/main/resources/{twilio-java => twilio-java-legacy}/dateTimeGroupParams.mustache (100%) create mode 100644 src/main/resources/twilio-java-legacy/deleter.mustache create mode 100644 src/main/resources/twilio-java-legacy/enums.mustache create mode 100644 src/main/resources/twilio-java-legacy/fetcher.mustache rename src/main/resources/{twilio-java => twilio-java-legacy}/generate_uri.mustache (100%) rename src/main/resources/{twilio-java => twilio-java-legacy}/headerParams.mustache (100%) rename src/main/resources/{twilio-java-modern => twilio-java-legacy}/licenseInfo.mustache (100%) create mode 100644 src/main/resources/twilio-java-legacy/models.mustache rename src/main/resources/{twilio-java => twilio-java-legacy}/packageName.mustache (100%) rename src/main/resources/{twilio-java => twilio-java-legacy}/postParams.mustache (100%) rename src/main/resources/{twilio-java => twilio-java-legacy}/postParams_body.mustache (100%) rename src/main/resources/{twilio-java => twilio-java-legacy}/prefixedCollapsibleMapQParams.mustache (100%) rename src/main/resources/{twilio-java => twilio-java-legacy}/queryParams.mustache (100%) create mode 100644 src/main/resources/twilio-java-legacy/reader.mustache rename src/main/resources/{twilio-java => twilio-java-legacy}/responseModel.mustache (100%) create mode 100644 src/main/resources/twilio-java-legacy/updater.mustache delete mode 100644 src/main/resources/twilio-java-modern/api.mustache delete mode 100644 src/main/resources/twilio-java-modern/creator.mustache delete mode 100644 src/main/resources/twilio-java-modern/deleter.mustache delete mode 100644 src/main/resources/twilio-java-modern/enums.mustache delete mode 100644 src/main/resources/twilio-java-modern/fetcher.mustache delete mode 100644 src/main/resources/twilio-java-modern/models.mustache delete mode 100644 src/main/resources/twilio-java-modern/reader.mustache delete mode 100644 src/main/resources/twilio-java-modern/updater.mustache rename src/main/resources/{twilio-java-modern => twilio-java}/Readme.md (100%) rename src/main/resources/{twilio-java-modern => twilio-java}/allConstructors.mustache (100%) rename src/main/resources/{twilio-java-modern => twilio-java}/common/addHeaderParams.mustache (100%) rename src/main/resources/{twilio-java-modern => twilio-java}/common/addPostParams.mustache (100%) rename src/main/resources/{twilio-java-modern => twilio-java}/common/addPostParamsJson.mustache (100%) rename src/main/resources/{twilio-java-modern => twilio-java}/common/addQueryParams.mustache (100%) rename src/main/resources/{twilio-java-modern => twilio-java}/common/constructors.mustache (100%) rename src/main/resources/{twilio-java-modern => twilio-java}/common/generateUri.mustache (100%) rename src/main/resources/{twilio-java-modern => twilio-java}/common/imports.mustache (100%) rename src/main/resources/{twilio-java-modern => twilio-java}/common/instanceVariables.mustache (100%) rename src/main/resources/{twilio-java-modern => twilio-java}/common/operationMethod.mustache (100%) rename src/main/resources/{twilio-java-modern => twilio-java}/common/setters.mustache (100%) rename src/main/resources/{twilio-java-modern => twilio-java}/creator/operationMethod.mustache (100%) rename src/main/resources/{twilio-java-modern => twilio-java}/creator/setters.mustache (100%) rename src/main/resources/{twilio-java-modern => twilio-java}/deleter/operationMethod.mustache (100%) rename src/main/resources/{twilio-java-modern => twilio-java}/deleter/setters.mustache (100%) rename src/main/resources/{twilio-java-modern => twilio-java}/equalsAndHashcode.mustache (100%) rename src/main/resources/{twilio-java-modern => twilio-java}/fetcher/operationMethod.mustache (100%) rename src/main/resources/{twilio-java-modern => twilio-java}/fetcher/setters.mustache (100%) rename src/main/resources/{twilio-java-modern => twilio-java}/reader/operationMethod.mustache (100%) rename src/main/resources/{twilio-java-modern => twilio-java}/reader/paginationMethods.mustache (100%) rename src/main/resources/{twilio-java-modern => twilio-java}/reader/setters.mustache (100%) rename src/main/resources/{twilio-java-modern => twilio-java}/response.mustache (100%) rename src/main/resources/{twilio-java-modern => twilio-java}/staticMethods.mustache (100%) rename src/main/resources/{twilio-java-modern => twilio-java}/updater/operationMethod.mustache (100%) rename src/main/resources/{twilio-java-modern => twilio-java}/updater/setters.mustache (100%) diff --git a/src/main/java/com/twilio/oai/TwilioJavaGenerator.java b/src/main/java/com/twilio/oai/TwilioJavaGenerator.java index dbd6f9981..16a327730 100644 --- a/src/main/java/com/twilio/oai/TwilioJavaGenerator.java +++ b/src/main/java/com/twilio/oai/TwilioJavaGenerator.java @@ -157,12 +157,12 @@ protected ImmutableMap.Builder addMustacheLambdas() { @Override public String getName() { - return EnumConstants.Generator.TWILIO_JAVA.getValue(); + return EnumConstants.Generator.TWILIO_JAVA_LEGACY.getValue(); } @Override public String getHelp() { - return "Generates the twilio-java helper library."; + return "Generates the twilio-java-legacy helper library."; } private JavaApiResources processCodegenOperations(List opList) { @@ -174,7 +174,7 @@ private JavaApiResources processCodegenOperations(List opList) .updateApiPath() .updateTemplate(); final Boolean isIngress = twilioCodegen.getToggles(JSON_INGRESS). - get(EnumConstants.Generator.TWILIO_JAVA.getValue()); + get(EnumConstants.Generator.TWILIO_JAVA_LEGACY.getValue()); javaApiResourceBuilder.updateOperations(new JavaParameterResolver(conventionMapper)) .updateResponseModel(new JavaPropertyResolver(conventionMapper), codegenModelResolver); if (isIngress) { diff --git a/src/main/java/com/twilio/oai/TwilioJavaGeneratorModern.java b/src/main/java/com/twilio/oai/TwilioJavaGeneratorModern.java index efeca055d..5cced9f22 100644 --- a/src/main/java/com/twilio/oai/TwilioJavaGeneratorModern.java +++ b/src/main/java/com/twilio/oai/TwilioJavaGeneratorModern.java @@ -132,7 +132,7 @@ public String toParamName(final String name) { @Override public String getName() { - return EnumConstants.Generator.TWILIO_JAVA_MODERN.getValue(); + return EnumConstants.Generator.TWILIO_JAVA.getValue(); } @Override diff --git a/src/main/java/com/twilio/oai/common/EnumConstants.java b/src/main/java/com/twilio/oai/common/EnumConstants.java index f4bdef0e0..06b8b6ccd 100644 --- a/src/main/java/com/twilio/oai/common/EnumConstants.java +++ b/src/main/java/com/twilio/oai/common/EnumConstants.java @@ -10,6 +10,7 @@ public class EnumConstants { public enum Generator { TWILIO_CSHARP("twilio-csharp"), TWILIO_JAVA("twilio-java"), + TWILIO_JAVA_LEGACY("twilio-java-legacy"), TWILIO_JAVA_MODERN("twilio-java-modern"), TWILIO_JAVA_TEST("twilio-java-test"), TWILIO_NODE("twilio-node"), diff --git a/src/main/java/com/twilio/oai/resolver/java/JavaParameterResolver.java b/src/main/java/com/twilio/oai/resolver/java/JavaParameterResolver.java index a384b2c1b..eb7c88e3a 100644 --- a/src/main/java/com/twilio/oai/resolver/java/JavaParameterResolver.java +++ b/src/main/java/com/twilio/oai/resolver/java/JavaParameterResolver.java @@ -66,7 +66,7 @@ public void resolveProperties(CodegenParameter parameter, ApiResourceBuilder api parameter.allowableValues = null; }); parameter.paramName = StringHelper.toFirstLetterLower(parameter.paramName); - if (apiResourceBuilder.getToggleMap().getOrDefault(EnumConstants.Generator.TWILIO_JAVA.getValue(), Boolean.FALSE) ) { + if (apiResourceBuilder.getToggleMap().getOrDefault(EnumConstants.Generator.TWILIO_JAVA_LEGACY.getValue(), Boolean.FALSE) ) { resolveIngressModel(parameter, apiResourceBuilder); } } diff --git a/src/main/java/com/twilio/oai/resolver/java/JavaPropertyResolver.java b/src/main/java/com/twilio/oai/resolver/java/JavaPropertyResolver.java index 09fe2a11c..8f86c1b45 100644 --- a/src/main/java/com/twilio/oai/resolver/java/JavaPropertyResolver.java +++ b/src/main/java/com/twilio/oai/resolver/java/JavaPropertyResolver.java @@ -45,7 +45,7 @@ public void resolveProperties(CodegenProperty property, ApiResourceBuilder apiR (key, value) -> property.getVendorExtensions().merge(key, value, (oldValue, newValue) -> newValue) ); - if (apiResourceBuilder.getToggleMap().getOrDefault(EnumConstants.Generator.TWILIO_JAVA.getValue(), Boolean.FALSE) ) { + if (apiResourceBuilder.getToggleMap().getOrDefault(EnumConstants.Generator.TWILIO_JAVA_LEGACY.getValue(), Boolean.FALSE) ) { resolveIngressModel(property, apiResourceBuilder); } } diff --git a/src/main/java/com/twilio/oai/resolver/node/NodePropertyResolver.java b/src/main/java/com/twilio/oai/resolver/node/NodePropertyResolver.java index c613f383a..c52369518 100644 --- a/src/main/java/com/twilio/oai/resolver/node/NodePropertyResolver.java +++ b/src/main/java/com/twilio/oai/resolver/node/NodePropertyResolver.java @@ -41,7 +41,7 @@ public void resolveProperties(CodegenProperty property, ApiResourceBuilder apiR (key, value) -> property.getVendorExtensions().merge(key, value, (oldValue, newValue) -> newValue) ); - if (apiResourceBuilder.getToggleMap().getOrDefault(EnumConstants.Generator.TWILIO_JAVA.getValue(), Boolean.FALSE) ) { + if (apiResourceBuilder.getToggleMap().getOrDefault(EnumConstants.Generator.TWILIO_JAVA_LEGACY.getValue(), Boolean.FALSE) ) { resolveIngressModel(property, apiResourceBuilder); } } diff --git a/src/main/resources/config/toggles.json b/src/main/resources/config/toggles.json index a2aed71bf..012819918 100644 --- a/src/main/resources/config/toggles.json +++ b/src/main/resources/config/toggles.json @@ -1,6 +1,6 @@ { "json_ingress": { - "twilio-java": true, + "twilio-java-legacy": true, "twilio-node": true, "twilio-python": true, "twilio-ruby": true, diff --git a/src/main/resources/twilio-java-legacy/api.mustache b/src/main/resources/twilio-java-legacy/api.mustache new file mode 100644 index 000000000..deaa723ed --- /dev/null +++ b/src/main/resources/twilio-java-legacy/api.mustache @@ -0,0 +1,167 @@ +{{>licenseInfo}} +{{#resources}} +package com.twilio.rest.{{domainPackage}}.{{apiVersion}}{{namespaceSubPart}}; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.core.JsonParseException; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonMappingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.twilio.base{{authMethodPackage}}.Resource; +import com.twilio.converter.Converter; +import java.util.Currency; +import com.twilio.converter.DateConverter; +import com.twilio.converter.Promoter; +import com.twilio.converter.PrefixedCollapsibleMap; +import com.twilio.converter.CurrencyDeserializer; +import com.twilio.exception.ApiConnectionException; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; + +import com.twilio.exception.ApiException; +import com.twilio.exception.RestException; +import com.twilio.http.HttpMethod; +import com.twilio.http.Request; +import com.twilio.http.Response; +import com.twilio.http.TwilioRestClient; +import com.twilio.rest.Domains; + +import lombok.ToString; + +import java.io.IOException; +import java.io.InputStream; +import java.net.URI; +import java.time.ZonedDateTime; + +{{^fullJavaUtil}} +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +{{/fullJavaUtil}} + +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; + +import java.util.Map; +import java.time.LocalDate; +import java.math.BigDecimal; +import com.twilio.type.PhoneNumberCapabilities; +import com.twilio.type.FeedbackIssue; +import com.twilio.type.IceServer; +import com.twilio.type.InboundCallPrice; +import com.twilio.type.OutboundPrefixPriceWithOrigin; +import com.twilio.type.OutboundPrefixPrice; +import com.twilio.type.OutboundCallPriceWithOrigin; +import com.twilio.type.PhoneNumberPrice; +import com.twilio.type.InboundSmsPrice; +import com.twilio.type.OutboundSmsPrice; +import com.twilio.type.OutboundCallPrice; +import com.twilio.type.RecordingRule; +import com.twilio.type.SubscribeRule; + +@JsonIgnoreProperties(ignoreUnknown = true) +@ToString +public class {{apiName}} extends Resource { + private static final long serialVersionUID = {{serialVersionUID}}L; + + {{>models}} + {{#apiOperations}} + {{#vendorExtensions.x-is-create-operation}} + {{#vendorExtensions.x-signature-list}} + public static {{apiName}}Creator creator({{#.}}final {{{dataType}}} {{{paramName}}}{{^-last}}, {{/-last}}{{/.}}){ + return new {{apiName}}Creator({{#.}}{{{paramName}}}{{^-last}}, {{/-last}}{{/.}}); + } + {{/vendorExtensions.x-signature-list}} + + {{/vendorExtensions.x-is-create-operation}} + {{#vendorExtensions.x-is-fetch-operation}} + {{#vendorExtensions.x-signature-list}} + public static {{apiName}}Fetcher fetcher({{#.}}final {{{dataType}}} {{{paramName}}}{{^-last}}, {{/-last}}{{/.}}){ + return new {{apiName}}Fetcher({{#.}}{{{paramName}}}{{^-last}}, {{/-last}}{{/.}}); + } + {{/vendorExtensions.x-signature-list}} + + {{/vendorExtensions.x-is-fetch-operation}} + {{#vendorExtensions.x-is-delete-operation}} + {{#vendorExtensions.x-signature-list}} + public static {{apiName}}Deleter deleter({{#.}}final {{{dataType}}} {{{paramName}}}{{^-last}}, {{/-last}}{{/.}}){ + return new {{apiName}}Deleter({{#.}}{{{paramName}}}{{^-last}}, {{/-last}}{{/.}}); + } + {{/vendorExtensions.x-signature-list}} + + {{/vendorExtensions.x-is-delete-operation}} + {{#vendorExtensions.x-is-read-operation}} + {{#vendorExtensions.x-signature-list}} + public static {{apiName}}Reader reader({{#.}}final {{{dataType}}} {{{paramName}}}{{^-last}}, {{/-last}}{{/.}}){ + return new {{apiName}}Reader({{#.}}{{{paramName}}}{{^-last}}, {{/-last}}{{/.}}); + } + {{/vendorExtensions.x-signature-list}} + + {{/vendorExtensions.x-is-read-operation}} + {{#vendorExtensions.x-is-update-operation}} + {{#vendorExtensions.x-signature-list}} + public static {{apiName}}Updater updater({{#.}}final {{{dataType}}} {{{paramName}}}{{^-last}}, {{/-last}}{{/.}}){ + return new {{apiName}}Updater({{#.}}{{{paramName}}}{{^-last}}, {{/-last}}{{/.}}); + } + {{/vendorExtensions.x-signature-list}} + + {{/vendorExtensions.x-is-update-operation}} + {{/apiOperations}} + /** + * Converts a JSON String into a {{apiName}} object using the provided ObjectMapper. + * + * @param json Raw JSON String + * @param objectMapper Jackson ObjectMapper + * @return {{apiName}} object represented by the provided JSON + */ + public static {{apiName}} fromJson(final String json, final ObjectMapper objectMapper) { + // Convert all checked exceptions to Runtime + try { + return objectMapper.readValue(json, {{apiName}}.class); + } catch (final JsonMappingException | JsonParseException e) { + throw new ApiException(e.getMessage(), e); + } catch (final IOException e) { + throw new ApiConnectionException(e.getMessage(), e); + } + } + + /** + * Converts a JSON InputStream into a {{apiName}} object using the provided + * ObjectMapper. + * + * @param json Raw JSON InputStream + * @param objectMapper Jackson ObjectMapper + * @return {{apiName}} object represented by the provided JSON + */ + public static {{apiName}} fromJson(final InputStream json, final ObjectMapper objectMapper) { + // Convert all checked exceptions to Runtime + try { + return objectMapper.readValue(json, {{apiName}}.class); + } catch (final JsonMappingException | JsonParseException e) { + throw new ApiException(e.getMessage(), e); + } catch (final IOException e) { + throw new ApiConnectionException(e.getMessage(), e); + } + } + {{#hasNestedRequestBody}} + public static String toJson(Object object, ObjectMapper mapper) { + try { + return mapper.writeValueAsString(object); + } catch (final JsonMappingException e) { + throw new ApiException(e.getMessage(), e); + } catch (JsonProcessingException e) { + throw new ApiException(e.getMessage(), e); + } catch (final IOException e) { + throw new ApiConnectionException(e.getMessage(), e); + } + }{{/hasNestedRequestBody}} +{{>responseModel}} +{{>enums}} +} +{{/resources}} + diff --git a/src/main/resources/twilio-java/api_doc.mustache b/src/main/resources/twilio-java-legacy/api_doc.mustache similarity index 100% rename from src/main/resources/twilio-java/api_doc.mustache rename to src/main/resources/twilio-java-legacy/api_doc.mustache diff --git a/src/main/resources/twilio-java/api_test.mustache b/src/main/resources/twilio-java-legacy/api_test.mustache similarity index 100% rename from src/main/resources/twilio-java/api_test.mustache rename to src/main/resources/twilio-java-legacy/api_test.mustache diff --git a/src/main/resources/twilio-java-legacy/creator.mustache b/src/main/resources/twilio-java-legacy/creator.mustache new file mode 100644 index 000000000..1c19dac2e --- /dev/null +++ b/src/main/resources/twilio-java-legacy/creator.mustache @@ -0,0 +1,136 @@ +{{>licenseInfo}} +{{#resources}} +package com.twilio.rest.{{domainPackage}}.{{apiVersion}}{{namespaceSubPart}}; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.twilio.constant.EnumConstants; +import com.twilio.converter.Promoter; +import com.twilio.exception.ApiConnectionException; +import com.twilio.converter.PrefixedCollapsibleMap; +import com.twilio.converter.Converter; +import com.twilio.exception.ApiException; +import com.twilio.exception.RestException; +import com.twilio.http.HttpMethod; +import com.twilio.http.Response; +import com.twilio.rest.Domains; +import java.math.BigDecimal; +import java.util.List; +import java.util.Map; +import java.time.LocalDate; +import com.twilio.converter.Converter; +import java.time.ZonedDateTime; +import java.io.IOException; +import java.io.InputStream; +import java.math.BigDecimal; +import java.net.URI; +import java.time.format.DateTimeFormatter; +import com.twilio.converter.DateConverter; + +{{^fullJavaUtil}} +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.UUID; +{{/fullJavaUtil}} + +import lombok.ToString; + +import java.net.URI; + +{{#apiOperations}} +{{#vendorExtensions.x-is-create-operation}} +import com.twilio.base{{vendorExtensions.x-auth-attributes.x-auth-import-class}}.Creator; +import com.twilio.http{{vendorExtensions.x-auth-attributes.x-auth-import-class}}.{{vendorExtensions.x-auth-attributes.x-http-class-prefix}}Request; +import com.twilio.http{{vendorExtensions.x-auth-attributes.x-auth-import-class}}.{{vendorExtensions.x-auth-attributes.x-http-class-prefix}}TwilioRestClient; + +public class {{apiName}}Creator extends Creator<{{apiName}}>{ +{{#allParams}} + private {{{dataType}}} {{paramName}}; +{{/allParams}} + +{{#vendorExtensions.x-signature-list}} + public {{apiName}}Creator({{#.}}final {{{dataType}}} {{paramName}}{{^-last}}, {{/-last}}{{/.}}) { + {{#.}} + this.{{paramName}} = {{paramName}}; + {{/.}} + } +{{/vendorExtensions.x-signature-list}} + +{{#vendorExtensions.x-non-path-params}} + public {{apiName}}Creator set{{#lambda.titlecase}}{{paramName}}{{/lambda.titlecase}}(final {{{dataType}}} {{paramName}}){ + this.{{paramName}} = {{paramName}}; + return this; + } +{{#isArray}} + public {{apiName}}Creator set{{#lambda.titlecase}}{{paramName}}{{/lambda.titlecase}}(final {{{baseType}}} {{paramName}}){ + return set{{#lambda.titlecase}}{{paramName}}{{/lambda.titlecase}}(Promoter.listOfOne({{paramName}})); + } +{{/isArray}} +{{#vendorExtensions.x-promotions}} +{{#entrySet}} + + public {{apiName}}Creator set{{#lambda.titlecase}}{{paramName}}{{/lambda.titlecase}}(final {{#lambda.titlecase}}{{key}}{{/lambda.titlecase}} {{paramName}}){ + return set{{#lambda.titlecase}}{{paramName}}{{/lambda.titlecase}}({{value}}); + } +{{/entrySet}} +{{/vendorExtensions.x-promotions}} +{{/vendorExtensions.x-non-path-params}} + + @Override + public {{apiName}} create(final {{vendorExtensions.x-auth-attributes.x-http-class-prefix}}TwilioRestClient client){ +{{>generate_uri}} + {{vendorExtensions.x-auth-attributes.x-http-class-prefix}}Request request = new {{vendorExtensions.x-auth-attributes.x-http-class-prefix}}Request( + {{vendorExtensions.x-http-method}}, + Domains.{{#lambda.uppercase}}{{domainName}}{{/lambda.uppercase}}.toString(), + path + ); + {{#queryParams.0}} + addQueryParams(request); + {{/queryParams.0}} + {{^vendorExtensions.x-is-json}} + request.setContentType(EnumConstants.ContentType.FORM_URLENCODED); + {{/vendorExtensions.x-is-json}} + {{#vendorExtensions.x-is-json}} + request.setContentType(EnumConstants.ContentType.JSON); + {{/vendorExtensions.x-is-json}} + {{#formParams.0}} + addPostParams(request); + {{/formParams.0}} + {{#bodyParams.0}} + addPostParams(request, client); + {{/bodyParams.0}} + {{#headerParams.0}} + addHeaderParams(request); + {{/headerParams.0}} + Response response = client.request(request); + if (response == null) { + throw new ApiConnectionException("{{apiName}} creation failed: Unable to connect to server"); + } else if (!{{vendorExtensions.x-auth-attributes.x-http-class-prefix}}TwilioRestClient.SUCCESS.test(response.getStatusCode())) { + RestException restException = RestException.fromJson(response.getStream(), client.getObjectMapper()); + if (restException == null) { + throw new ApiException("Server Error, no content", response.getStatusCode()); + } + throw new ApiException(restException); + } + + return {{apiName}}.fromJson(response.getStream(), client.getObjectMapper()); + } +{{#vendorExtensions.x-has-form-params}} +{{>postParams}} +{{/vendorExtensions.x-has-form-params}} +{{#vendorExtensions.x-has-body-params}} +{{>postParams_body}} +{{/vendorExtensions.x-has-body-params}} +{{#vendorExtensions.x-has-header-params}} +{{>headerParams}} +{{/vendorExtensions.x-has-header-params}} +{{#vendorExtensions.x-has-query-params}} + private void addQueryParams(final {{vendorExtensions.x-auth-attributes.x-http-class-prefix}}Request request) { +{{>queryParams}} } +{{/vendorExtensions.x-has-query-params}} +} +{{/vendorExtensions.x-is-create-operation}} +{{/apiOperations}} +{{/resources}} diff --git a/src/main/resources/twilio-java/dateParams.mustache b/src/main/resources/twilio-java-legacy/dateParams.mustache similarity index 100% rename from src/main/resources/twilio-java/dateParams.mustache rename to src/main/resources/twilio-java-legacy/dateParams.mustache diff --git a/src/main/resources/twilio-java/dateTimeGroupParams.mustache b/src/main/resources/twilio-java-legacy/dateTimeGroupParams.mustache similarity index 100% rename from src/main/resources/twilio-java/dateTimeGroupParams.mustache rename to src/main/resources/twilio-java-legacy/dateTimeGroupParams.mustache diff --git a/src/main/resources/twilio-java-legacy/deleter.mustache b/src/main/resources/twilio-java-legacy/deleter.mustache new file mode 100644 index 000000000..082c5df14 --- /dev/null +++ b/src/main/resources/twilio-java-legacy/deleter.mustache @@ -0,0 +1,129 @@ +{{>licenseInfo}} +{{#resources}} +package com.twilio.rest.{{domainPackage}}.{{apiVersion}}{{namespaceSubPart}}; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.twilio.converter.Promoter; +import com.twilio.constant.EnumConstants; +import com.twilio.exception.ApiConnectionException; +import com.twilio.converter.PrefixedCollapsibleMap; +import com.twilio.exception.ApiException; +import com.twilio.converter.Converter; +import com.twilio.exception.RestException; +import com.twilio.http.HttpMethod; +import com.twilio.http.Response; +import com.twilio.rest.Domains; +import java.time.LocalDate; +import java.io.IOException; +import java.io.InputStream; +import java.math.BigDecimal; +import java.net.URI; +import java.time.ZonedDateTime; +import java.time.format.DateTimeFormatter; +import com.twilio.converter.DateConverter; + +{{^fullJavaUtil}} +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +{{/fullJavaUtil}} + +import lombok.ToString; + +{{#apiOperations}} +{{#vendorExtensions.x-is-delete-operation}} +import com.twilio.base{{vendorExtensions.x-auth-attributes.x-auth-import-class}}.Deleter; +import com.twilio.http{{vendorExtensions.x-auth-attributes.x-auth-import-class}}.{{vendorExtensions.x-auth-attributes.x-http-class-prefix}}Request; +import com.twilio.http{{vendorExtensions.x-auth-attributes.x-auth-import-class}}.{{vendorExtensions.x-auth-attributes.x-http-class-prefix}}TwilioRestClient; + +public class {{apiName}}Deleter extends Deleter<{{apiName}}> { +{{#allParams}} + private {{{dataType}}} {{paramName}}; +{{/allParams}} + +{{#vendorExtensions.x-signature-list}} + public {{apiName}}Deleter({{#.}}final {{{dataType}}} {{paramName}}{{^-last}}, {{/-last}}{{/.}}){ + {{#.}} + this.{{paramName}} = {{paramName}}; + {{/.}} + } +{{/vendorExtensions.x-signature-list}} + +{{#vendorExtensions.x-non-path-params}} + public {{apiName}}Deleter set{{#lambda.titlecase}}{{paramName}}{{/lambda.titlecase}}(final {{{dataType}}} {{paramName}}){ + this.{{paramName}} = {{paramName}}; + return this; + } +{{#isArray}} + public {{apiName}}Deleter set{{#lambda.titlecase}}{{paramName}}{{/lambda.titlecase}}(final {{{baseType}}} {{paramName}}){ + return set{{#lambda.titlecase}}{{paramName}}{{/lambda.titlecase}}(Promoter.listOfOne({{paramName}})); + } +{{/isArray}} +{{#vendorExtensions.x-promotions}} +{{#entrySet}} + + public {{apiName}}Deleter set{{#lambda.titlecase}}{{paramName}}{{/lambda.titlecase}}(final {{#lambda.titlecase}}{{key}}{{/lambda.titlecase}} {{paramName}}){ + return set{{#lambda.titlecase}}{{paramName}}{{/lambda.titlecase}}({{value}}); + } +{{/entrySet}} +{{/vendorExtensions.x-promotions}} +{{/vendorExtensions.x-non-path-params}} + + @Override + public boolean delete(final {{vendorExtensions.x-auth-attributes.x-http-class-prefix}}TwilioRestClient client) { +{{>generate_uri}} + {{vendorExtensions.x-auth-attributes.x-http-class-prefix}}Request request = new {{vendorExtensions.x-auth-attributes.x-http-class-prefix}}Request( + {{vendorExtensions.x-http-method}}, + Domains.{{#lambda.uppercase}}{{domainName}}{{/lambda.uppercase}}.toString(), + path + ); + {{#queryParams.0}} + addQueryParams(request); + {{/queryParams.0}} + {{^vendorExtensions.x-is-json}} + request.setContentType(EnumConstants.ContentType.FORM_URLENCODED); + {{/vendorExtensions.x-is-json}} + {{#vendorExtensions.x-is-json}} + request.setContentType(EnumConstants.ContentType.JSON); + {{/vendorExtensions.x-is-json}} + {{#formParams.0}} + addPostParams(request); + {{/formParams.0}} + {{#bodyParams.0}} + addPostParams(request, client); + {{/bodyParams.0}} + {{#headerParams.0}} + addHeaderParams(request); + {{/headerParams.0}} + Response response = client.request(request); + + if (response == null) { + throw new ApiConnectionException("{{apiName}} delete failed: Unable to connect to server"); + } else if (!{{vendorExtensions.x-auth-attributes.x-http-class-prefix}}TwilioRestClient.SUCCESS.test(response.getStatusCode())) { + RestException restException = RestException.fromJson(response.getStream(), client.getObjectMapper()); + if (restException == null) { + throw new ApiException("Server Error, no content", response.getStatusCode()); + } + throw new ApiException(restException); + } + return response.getStatusCode() == 204; + } +{{#vendorExtensions.x-has-form-params}} +{{>postParams}} +{{/vendorExtensions.x-has-form-params}} +{{#vendorExtensions.x-has-body-params}} +{{>postParams_body}} +{{/vendorExtensions.x-has-body-params}} +{{#vendorExtensions.x-has-header-params}} +{{>headerParams}} +{{/vendorExtensions.x-has-header-params}} +{{#vendorExtensions.x-has-query-params}} + private void addQueryParams(final {{vendorExtensions.x-auth-attributes.x-http-class-prefix}}Request request) { +{{>queryParams}} } +{{/vendorExtensions.x-has-query-params}} +} +{{/vendorExtensions.x-is-delete-operation}} +{{/apiOperations}} +{{/resources}} diff --git a/src/main/resources/twilio-java-legacy/enums.mustache b/src/main/resources/twilio-java-legacy/enums.mustache new file mode 100644 index 000000000..43c17f9fa --- /dev/null +++ b/src/main/resources/twilio-java-legacy/enums.mustache @@ -0,0 +1,24 @@ +{{#enums}} + public enum {{#lambda.titlecase}}{{{enumName}}}{{/lambda.titlecase}} { + {{#allowableValues}} + {{#values}} + {{#lambda.uppercase}}{{#lambda.replacehyphen}}{{{.}}}{{/lambda.replacehyphen}}({{/lambda.uppercase}}"{{{.}}}"){{^-last}},{{/-last}}{{#-last}};{{/-last}} + {{/values}} + {{/allowableValues}} + + private final String value; + + private {{#lambda.titlecase}}{{{enumName}}}{{/lambda.titlecase}}(final String value) { + this.value = value; + } + + public String toString() { + return value; + } + + @JsonCreator + public static {{#lambda.titlecase}}{{{enumName}}}{{/lambda.titlecase}} forValue(final String value) { + return Promoter.enumFromString(value, {{#lambda.titlecase}}{{{enumName}}}{{/lambda.titlecase}}.values()); + } + } +{{/enums}} \ No newline at end of file diff --git a/src/main/resources/twilio-java-legacy/fetcher.mustache b/src/main/resources/twilio-java-legacy/fetcher.mustache new file mode 100644 index 000000000..34be9003b --- /dev/null +++ b/src/main/resources/twilio-java-legacy/fetcher.mustache @@ -0,0 +1,131 @@ +{{>licenseInfo}} +{{#resources}} +package com.twilio.rest.{{domainPackage}}.{{apiVersion}}{{namespaceSubPart}}; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.twilio.constant.EnumConstants; +import com.twilio.converter.Promoter; +import com.twilio.exception.ApiConnectionException; +import com.twilio.converter.PrefixedCollapsibleMap; +import com.twilio.converter.Converter; +import com.twilio.exception.ApiException; +import com.twilio.exception.RestException; +import com.twilio.http.HttpMethod; +import com.twilio.http.Response; +import com.twilio.rest.Domains; + +import java.io.IOException; +import java.io.InputStream; +import java.math.BigDecimal; +import java.net.URI; +import java.time.ZonedDateTime; +import java.time.LocalDate; +import java.time.format.DateTimeFormatter; +import com.twilio.converter.DateConverter; + +{{^fullJavaUtil}} +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +{{/fullJavaUtil}} + +import lombok.ToString; + +{{#apiOperations}} +{{#vendorExtensions.x-is-fetch-operation}} +import com.twilio.base{{vendorExtensions.x-auth-attributes.x-auth-import-class}}.Fetcher; +import com.twilio.http{{vendorExtensions.x-auth-attributes.x-auth-import-class}}.{{vendorExtensions.x-auth-attributes.x-http-class-prefix}}Request; +import com.twilio.http{{vendorExtensions.x-auth-attributes.x-auth-import-class}}.{{vendorExtensions.x-auth-attributes.x-http-class-prefix}}TwilioRestClient; + +public class {{apiName}}Fetcher extends Fetcher<{{apiName}}> { +{{#allParams}} + private {{{dataType}}} {{paramName}}; +{{/allParams}} + +{{#vendorExtensions.x-signature-list}} + public {{apiName}}Fetcher({{#.}}final {{{dataType}}} {{paramName}}{{^-last}}, {{/-last}}{{/.}}){ + {{#.}} + this.{{paramName}} = {{paramName}}; + {{/.}} + } +{{/vendorExtensions.x-signature-list}} + +{{#vendorExtensions.x-non-path-params}} + public {{apiName}}Fetcher set{{#lambda.titlecase}}{{paramName}}{{/lambda.titlecase}}(final {{{dataType}}} {{paramName}}){ + this.{{paramName}} = {{paramName}}; + return this; + } +{{#isArray}} + public {{apiName}}Fetcher set{{#lambda.titlecase}}{{paramName}}{{/lambda.titlecase}}(final {{{baseType}}} {{paramName}}){ + return set{{#lambda.titlecase}}{{paramName}}{{/lambda.titlecase}}(Promoter.listOfOne({{paramName}})); + } +{{/isArray}} +{{#vendorExtensions.x-promotions}} +{{#entrySet}} + + public {{apiName}}Fetcher set{{#lambda.titlecase}}{{paramName}}{{/lambda.titlecase}}(final {{#lambda.titlecase}}{{key}}{{/lambda.titlecase}} {{paramName}}){ + return set{{#lambda.titlecase}}{{paramName}}{{/lambda.titlecase}}({{value}}); + } +{{/entrySet}} +{{/vendorExtensions.x-promotions}} +{{/vendorExtensions.x-non-path-params}} + + @Override + public {{apiName}} fetch(final {{vendorExtensions.x-auth-attributes.x-http-class-prefix}}TwilioRestClient client) { +{{>generate_uri}} + {{vendorExtensions.x-auth-attributes.x-http-class-prefix}}Request request = new {{vendorExtensions.x-auth-attributes.x-http-class-prefix}}Request( + {{vendorExtensions.x-http-method}}, + Domains.{{#lambda.uppercase}}{{domainName}}{{/lambda.uppercase}}.toString(), + path + ); + {{#queryParams.0}} + addQueryParams(request); + {{/queryParams.0}} + {{^vendorExtensions.x-is-json}} + request.setContentType(EnumConstants.ContentType.FORM_URLENCODED); + {{/vendorExtensions.x-is-json}} + {{#vendorExtensions.x-is-json}} + request.setContentType(EnumConstants.ContentType.JSON); + {{/vendorExtensions.x-is-json}} + {{#formParams.0}} + addPostParams(request); + {{/formParams.0}} + {{#bodyParams.0}} + addPostParams(request, client); + {{/bodyParams.0}} + {{#headerParams.0}} + addHeaderParams(request); + {{/headerParams.0}} + Response response = client.request(request); + + if (response == null) { + throw new ApiConnectionException("{{apiName}} fetch failed: Unable to connect to server"); + } else if (!{{vendorExtensions.x-auth-attributes.x-http-class-prefix}}TwilioRestClient.SUCCESS.test(response.getStatusCode())) { + RestException restException = RestException.fromJson(response.getStream(), client.getObjectMapper()); + if (restException == null) { + throw new ApiException("Server Error, no content", response.getStatusCode()); + } + throw new ApiException(restException); + } + + return {{apiName}}.fromJson(response.getStream(), client.getObjectMapper()); + } +{{#vendorExtensions.x-has-form-params}} +{{>postParams}} +{{/vendorExtensions.x-has-form-params}} +{{#vendorExtensions.x-has-body-params}} +{{>postParams_body}} +{{/vendorExtensions.x-has-body-params}} +{{#vendorExtensions.x-has-header-params}} +{{>headerParams}} +{{/vendorExtensions.x-has-header-params}} +{{#vendorExtensions.x-has-query-params}} + private void addQueryParams(final {{vendorExtensions.x-auth-attributes.x-http-class-prefix}}Request request) { +{{>queryParams}} } +{{/vendorExtensions.x-has-query-params}} +} +{{/vendorExtensions.x-is-fetch-operation}} +{{/apiOperations}} +{{/resources}} diff --git a/src/main/resources/twilio-java/generate_uri.mustache b/src/main/resources/twilio-java-legacy/generate_uri.mustache similarity index 100% rename from src/main/resources/twilio-java/generate_uri.mustache rename to src/main/resources/twilio-java-legacy/generate_uri.mustache diff --git a/src/main/resources/twilio-java/headerParams.mustache b/src/main/resources/twilio-java-legacy/headerParams.mustache similarity index 100% rename from src/main/resources/twilio-java/headerParams.mustache rename to src/main/resources/twilio-java-legacy/headerParams.mustache diff --git a/src/main/resources/twilio-java-modern/licenseInfo.mustache b/src/main/resources/twilio-java-legacy/licenseInfo.mustache similarity index 100% rename from src/main/resources/twilio-java-modern/licenseInfo.mustache rename to src/main/resources/twilio-java-legacy/licenseInfo.mustache diff --git a/src/main/resources/twilio-java-legacy/models.mustache b/src/main/resources/twilio-java-legacy/models.mustache new file mode 100644 index 000000000..a95788f86 --- /dev/null +++ b/src/main/resources/twilio-java-legacy/models.mustache @@ -0,0 +1,41 @@ + + {{#resources.nestedModels}} + @ToString + static public class {{classname}} { + {{#vars}} + @JsonInclude(JsonInclude.Include.NON_EMPTY) + @JsonProperty("{{{baseName}}}") + {{#vendorExtensions.x-ref-enum}} + @Getter @Setter private {{{datatypeWithEnum}}} {{name}}; + {{/vendorExtensions.x-ref-enum}} + {{^vendorExtensions.x-ref-enum}} + @Getter @Setter private {{{dataType}}} {{name}}; + {{/vendorExtensions.x-ref-enum}} + {{^isMap}} + {{^isFreeFormObject}} + {{^isAnyType}} + {{#vendorExtensions.x-serialize}} + public String get{{#lambda.titlecase}}{{name}}{{/lambda.titlecase}}() { + return {{vendorExtensions.x-serialize}}; + }{{/vendorExtensions.x-serialize}} + {{/isAnyType}} + {{/isFreeFormObject}} + {{/isMap}} + {{/vars}} + {{#vendorExtensions.x-constructor-required}} + {{#vendorExtensions.x-model-parameters}} + public {{classname}}({{#.}}final {{{dataType}}} {{name}}{{^-last}}, {{/-last}}{{/.}} ) { + {{#.}} + this.{{name}} = {{name}}; + {{/.}} + } + {{/vendorExtensions.x-model-parameters}} + {{/vendorExtensions.x-constructor-required}} + + {{^vendorExtensions.x-response}} + public static {{classname}} fromJson(String jsonString, ObjectMapper mapper) throws IOException { + return mapper.readValue(jsonString, {{classname}}.class); + } + {{/vendorExtensions.x-response}} + } + {{/resources.nestedModels}} diff --git a/src/main/resources/twilio-java/packageName.mustache b/src/main/resources/twilio-java-legacy/packageName.mustache similarity index 100% rename from src/main/resources/twilio-java/packageName.mustache rename to src/main/resources/twilio-java-legacy/packageName.mustache diff --git a/src/main/resources/twilio-java/postParams.mustache b/src/main/resources/twilio-java-legacy/postParams.mustache similarity index 100% rename from src/main/resources/twilio-java/postParams.mustache rename to src/main/resources/twilio-java-legacy/postParams.mustache diff --git a/src/main/resources/twilio-java/postParams_body.mustache b/src/main/resources/twilio-java-legacy/postParams_body.mustache similarity index 100% rename from src/main/resources/twilio-java/postParams_body.mustache rename to src/main/resources/twilio-java-legacy/postParams_body.mustache diff --git a/src/main/resources/twilio-java/prefixedCollapsibleMapQParams.mustache b/src/main/resources/twilio-java-legacy/prefixedCollapsibleMapQParams.mustache similarity index 100% rename from src/main/resources/twilio-java/prefixedCollapsibleMapQParams.mustache rename to src/main/resources/twilio-java-legacy/prefixedCollapsibleMapQParams.mustache diff --git a/src/main/resources/twilio-java/queryParams.mustache b/src/main/resources/twilio-java-legacy/queryParams.mustache similarity index 100% rename from src/main/resources/twilio-java/queryParams.mustache rename to src/main/resources/twilio-java-legacy/queryParams.mustache diff --git a/src/main/resources/twilio-java-legacy/reader.mustache b/src/main/resources/twilio-java-legacy/reader.mustache new file mode 100644 index 000000000..0297987bd --- /dev/null +++ b/src/main/resources/twilio-java-legacy/reader.mustache @@ -0,0 +1,186 @@ +{{>licenseInfo}} +{{#resources}} +package com.twilio.rest.{{domainPackage}}.{{apiVersion}}{{namespaceSubPart}}; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.twilio.constant.EnumConstants; +import com.twilio.converter.Promoter; +import com.twilio.exception.ApiConnectionException; +import com.twilio.converter.PrefixedCollapsibleMap; +import com.twilio.converter.Converter; +import com.twilio.exception.ApiException; +import com.twilio.exception.RestException; +import com.twilio.http.HttpMethod; +import com.twilio.http.Response; +import com.twilio.rest.Domains; +import java.time.LocalDate; +import java.time.ZonedDateTime; +import java.io.IOException; +import java.io.InputStream; +import java.math.BigDecimal; +import java.net.URI; +import java.time.format.DateTimeFormatter; +import com.twilio.converter.DateConverter; + +{{^fullJavaUtil}} +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +{{/fullJavaUtil}} + +import lombok.ToString; + +{{#apiOperations}} +{{#vendorExtensions.x-is-read-operation}} +import com.twilio.base{{vendorExtensions.x-auth-attributes.x-auth-import-class}}.Page; +import com.twilio.base{{vendorExtensions.x-auth-attributes.x-auth-import-class}}.Reader; +import com.twilio.base{{vendorExtensions.x-auth-attributes.x-auth-import-class}}.ResourceSet; +import com.twilio.http{{vendorExtensions.x-auth-attributes.x-auth-import-class}}.{{vendorExtensions.x-auth-attributes.x-http-class-prefix}}Request; +import com.twilio.http{{vendorExtensions.x-auth-attributes.x-auth-import-class}}.{{vendorExtensions.x-auth-attributes.x-http-class-prefix}}TwilioRestClient; + +public class {{apiName}}Reader extends Reader<{{apiName}}> { +{{#allParams}} + private {{{dataType}}} {{paramName}}; +{{/allParams}} + +{{#vendorExtensions.x-signature-list}} + public {{apiName}}Reader({{#.}}final {{{dataType}}} {{paramName}}{{^-last}}, {{/-last}}{{/.}}){ + {{#.}} + this.{{paramName}} = {{paramName}}; + {{/.}} + } +{{/vendorExtensions.x-signature-list}} + +{{#vendorExtensions.x-non-path-params}} + public {{apiName}}Reader set{{#lambda.titlecase}}{{paramName}}{{/lambda.titlecase}}(final {{{dataType}}} {{paramName}}){ + this.{{paramName}} = {{paramName}}; + return this; + } +{{#isArray}} + public {{apiName}}Reader set{{#lambda.titlecase}}{{paramName}}{{/lambda.titlecase}}(final {{{baseType}}} {{paramName}}){ + return set{{#lambda.titlecase}}{{paramName}}{{/lambda.titlecase}}(Promoter.listOfOne({{paramName}})); + } +{{/isArray}} +{{#vendorExtensions.x-promotions}} +{{#entrySet}} + + public {{apiName}}Reader set{{#lambda.titlecase}}{{paramName}}{{/lambda.titlecase}}(final {{#lambda.titlecase}}{{key}}{{/lambda.titlecase}} {{paramName}}){ + return set{{#lambda.titlecase}}{{paramName}}{{/lambda.titlecase}}({{value}}); + } +{{/entrySet}} +{{/vendorExtensions.x-promotions}} +{{/vendorExtensions.x-non-path-params}} + + @Override + public ResourceSet<{{apiName}}> read(final {{vendorExtensions.x-auth-attributes.x-http-class-prefix}}TwilioRestClient client) { + return new ResourceSet<>(this, client, firstPage(client)); + } + + public Page<{{apiName}}> firstPage(final {{vendorExtensions.x-auth-attributes.x-http-class-prefix}}TwilioRestClient client) { + String path = "{{{path}}}"; + {{#allParams}} + {{#vendorExtensions.x-is-account-sid}} + this.{{paramName}} = this.{{paramName}} == null ? client.getAccountSid() : this.{{paramName}}; + path = path.replace("{"+"{{baseName}}"+"}", this.{{paramName}}.toString()); + {{/vendorExtensions.x-is-account-sid}} + {{/allParams}} + {{#requiredParams}} + path = path.replace("{"+"{{baseName}}"+"}", this.{{paramName}}.toString()); + {{/requiredParams}} + + {{vendorExtensions.x-auth-attributes.x-http-class-prefix}}Request request = new {{vendorExtensions.x-auth-attributes.x-http-class-prefix}}Request( + {{vendorExtensions.x-http-method}}, + Domains.{{#lambda.uppercase}}{{domainName}}{{/lambda.uppercase}}.toString(), + path + ); + + {{#queryParams.0}} + addQueryParams(request); + {{/queryParams.0}} + {{^vendorExtensions.x-is-json}} + request.setContentType(EnumConstants.ContentType.FORM_URLENCODED); + {{/vendorExtensions.x-is-json}} + {{#vendorExtensions.x-is-json}} + request.setContentType(EnumConstants.ContentType.JSON); + {{/vendorExtensions.x-is-json}} + {{#formParams.0}} + addPostParams(request); + {{/formParams.0}} + {{#bodyParams.0}} + addPostParams(request, client); + {{/bodyParams.0}} + {{#headerParams.0}} + addHeaderParams(request); + {{/headerParams.0}} + return pageForRequest(client, request); + } + + private Page<{{apiName}}> pageForRequest(final {{vendorExtensions.x-auth-attributes.x-http-class-prefix}}TwilioRestClient client, final {{vendorExtensions.x-auth-attributes.x-http-class-prefix}}Request request) { + Response response = client.request(request); + + if (response == null) { + throw new ApiConnectionException("{{apiName}} read failed: Unable to connect to server"); + } else if (!{{vendorExtensions.x-auth-attributes.x-http-class-prefix}}TwilioRestClient.SUCCESS.test(response.getStatusCode())) { + RestException restException = RestException.fromJson(response.getStream(), client.getObjectMapper()); + if (restException == null) { + throw new ApiException("Server Error, no content", response.getStatusCode()); + } + throw new ApiException(restException); + } + + return Page.fromJson( + "{{recordKey}}", + response.getContent(), + {{apiName}}.class, + client.getObjectMapper() + ); + } + + @Override + public Page<{{apiName}}> previousPage(final Page<{{apiName}}> page, final {{vendorExtensions.x-auth-attributes.x-http-class-prefix}}TwilioRestClient client) { + {{vendorExtensions.x-auth-attributes.x-http-class-prefix}}Request request = new {{vendorExtensions.x-auth-attributes.x-http-class-prefix}}Request( + {{vendorExtensions.x-http-method}}, + page.getPreviousPageUrl(Domains.{{#lambda.uppercase}}{{domainName}}{{/lambda.uppercase}}.toString()) + ); + return pageForRequest(client, request); + } + + + @Override + public Page<{{apiName}}> nextPage(final Page<{{apiName}}> page, final {{vendorExtensions.x-auth-attributes.x-http-class-prefix}}TwilioRestClient client) { + {{vendorExtensions.x-auth-attributes.x-http-class-prefix}}Request request = new {{vendorExtensions.x-auth-attributes.x-http-class-prefix}}Request( + {{vendorExtensions.x-http-method}}, + page.getNextPageUrl(Domains.{{#lambda.uppercase}}{{domainName}}{{/lambda.uppercase}}.toString()) + ); + return pageForRequest(client, request); + } + + @Override + public Page<{{apiName}}> getPage(final String targetUrl, final {{vendorExtensions.x-auth-attributes.x-http-class-prefix}}TwilioRestClient client) { + {{vendorExtensions.x-auth-attributes.x-http-class-prefix}}Request request = new {{vendorExtensions.x-auth-attributes.x-http-class-prefix}}Request( + HttpMethod.GET, + targetUrl + ); + + return pageForRequest(client, request); + } +{{#vendorExtensions.x-has-form-params}} +{{>postParams}} +{{/vendorExtensions.x-has-form-params}} +{{#vendorExtensions.x-has-header-params}} +{{>headerParams}} +{{/vendorExtensions.x-has-header-params}} +{{#vendorExtensions.x-has-query-params}} + private void addQueryParams(final {{vendorExtensions.x-auth-attributes.x-http-class-prefix}}Request request) { +{{>queryParams}} + if(getPageSize() != null) { + request.addQueryParam("PageSize", Integer.toString(getPageSize())); + } + } +{{/vendorExtensions.x-has-query-params}} +} +{{/vendorExtensions.x-is-read-operation}} +{{/apiOperations}} +{{/resources}} diff --git a/src/main/resources/twilio-java/responseModel.mustache b/src/main/resources/twilio-java-legacy/responseModel.mustache similarity index 100% rename from src/main/resources/twilio-java/responseModel.mustache rename to src/main/resources/twilio-java-legacy/responseModel.mustache diff --git a/src/main/resources/twilio-java-legacy/updater.mustache b/src/main/resources/twilio-java-legacy/updater.mustache new file mode 100644 index 000000000..d14fd7661 --- /dev/null +++ b/src/main/resources/twilio-java-legacy/updater.mustache @@ -0,0 +1,132 @@ +{{>licenseInfo}} +{{#resources}} +package com.twilio.rest.{{domainPackage}}.{{apiVersion}}{{namespaceSubPart}}; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.twilio.constant.EnumConstants; +import com.twilio.converter.Promoter; +import com.twilio.exception.ApiConnectionException; +import com.twilio.converter.PrefixedCollapsibleMap; +import com.twilio.converter.Converter; +import com.twilio.exception.ApiException; +import com.twilio.exception.RestException; +import com.twilio.http.HttpMethod; +import com.twilio.http.Response; +import com.twilio.rest.Domains; +import java.time.format.DateTimeFormatter; +import com.twilio.converter.DateConverter; + +import java.io.IOException; +import java.io.InputStream; +import java.math.BigDecimal; +import java.net.URI; +import java.time.ZonedDateTime; +import java.time.LocalDate; + +{{^fullJavaUtil}} +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +{{/fullJavaUtil}} + +import lombok.ToString; + +{{#apiOperations}} +{{#vendorExtensions.x-is-update-operation}} +import com.twilio.base{{vendorExtensions.x-auth-attributes.x-auth-import-class}}.Updater; +import com.twilio.http{{vendorExtensions.x-auth-attributes.x-auth-import-class}}.{{vendorExtensions.x-auth-attributes.x-http-class-prefix}}Request; +import com.twilio.http{{vendorExtensions.x-auth-attributes.x-auth-import-class}}.{{vendorExtensions.x-auth-attributes.x-http-class-prefix}}TwilioRestClient; + + +public class {{apiName}}Updater extends Updater<{{apiName}}>{ +{{#allParams}} + private {{{dataType}}} {{paramName}}; +{{/allParams}} + +{{#vendorExtensions.x-signature-list}} + public {{apiName}}Updater({{#.}}final {{{dataType}}} {{paramName}}{{^-last}}, {{/-last}}{{/.}}){ + {{#.}} + this.{{paramName}} = {{paramName}}; + {{/.}} + } +{{/vendorExtensions.x-signature-list}} + +{{#vendorExtensions.x-non-path-params}} + public {{apiName}}Updater set{{#lambda.titlecase}}{{paramName}}{{/lambda.titlecase}}(final {{{dataType}}} {{paramName}}){ + this.{{paramName}} = {{paramName}}; + return this; + } +{{#isArray}} + public {{apiName}}Updater set{{#lambda.titlecase}}{{paramName}}{{/lambda.titlecase}}(final {{{baseType}}} {{paramName}}){ + return set{{#lambda.titlecase}}{{paramName}}{{/lambda.titlecase}}(Promoter.listOfOne({{paramName}})); + } +{{/isArray}} +{{#vendorExtensions.x-promotions}} +{{#entrySet}} + + public {{apiName}}Updater set{{#lambda.titlecase}}{{paramName}}{{/lambda.titlecase}}(final {{#lambda.titlecase}}{{key}}{{/lambda.titlecase}} {{paramName}}){ + return set{{#lambda.titlecase}}{{paramName}}{{/lambda.titlecase}}({{value}}); + } +{{/entrySet}} +{{/vendorExtensions.x-promotions}} +{{/vendorExtensions.x-non-path-params}} + + @Override + public {{apiName}} update(final {{vendorExtensions.x-auth-attributes.x-http-class-prefix}}TwilioRestClient client){ +{{>generate_uri}} + {{vendorExtensions.x-auth-attributes.x-http-class-prefix}}Request request = new {{vendorExtensions.x-auth-attributes.x-http-class-prefix}}Request( + {{vendorExtensions.x-http-method}}, + Domains.{{#lambda.uppercase}}{{domainName}}{{/lambda.uppercase}}.toString(), + path + ); + {{#queryParams.0}} + addQueryParams(request); + {{/queryParams.0}} + {{^vendorExtensions.x-is-json}} + request.setContentType(EnumConstants.ContentType.FORM_URLENCODED); + {{/vendorExtensions.x-is-json}} + {{#vendorExtensions.x-is-json}} + request.setContentType(EnumConstants.ContentType.JSON); + {{/vendorExtensions.x-is-json}} + {{#formParams.0}} + addPostParams(request); + {{/formParams.0}} + {{#bodyParams.0}} + addPostParams(request, client); + {{/bodyParams.0}} + {{#headerParams.0}} + addHeaderParams(request); + {{/headerParams.0}} + Response response = client.request(request); + if (response == null) { + throw new ApiConnectionException("{{apiName}} update failed: Unable to connect to server"); + } else if (!{{vendorExtensions.x-auth-attributes.x-http-class-prefix}}TwilioRestClient.SUCCESS.test(response.getStatusCode())) { + RestException restException = RestException.fromJson(response.getStream(), client.getObjectMapper()); + if (restException == null) { + throw new ApiException("Server Error, no content", response.getStatusCode()); + } + throw new ApiException(restException); + } + + return {{apiName}}.fromJson(response.getStream(), client.getObjectMapper()); + } + +{{#vendorExtensions.x-has-form-params}} +{{>postParams}} +{{/vendorExtensions.x-has-form-params}} +{{#vendorExtensions.x-has-body-params}} +{{>postParams_body}} +{{/vendorExtensions.x-has-body-params}} +{{#vendorExtensions.x-has-header-params}} +{{>headerParams}} +{{/vendorExtensions.x-has-header-params}} +{{#vendorExtensions.x-has-query-params}} + private void addQueryParams(final {{vendorExtensions.x-auth-attributes.x-http-class-prefix}}Request request) { +{{>queryParams}} } +{{/vendorExtensions.x-has-query-params}} +} +{{/vendorExtensions.x-is-update-operation}} +{{/apiOperations}} +{{/resources}} diff --git a/src/main/resources/twilio-java-modern/api.mustache b/src/main/resources/twilio-java-modern/api.mustache deleted file mode 100644 index f38a63e80..000000000 --- a/src/main/resources/twilio-java-modern/api.mustache +++ /dev/null @@ -1,21 +0,0 @@ -{{>licenseInfo}} -{{#resources}} -package com.twilio.rest.{{domainPackage}}.{{apiVersion}}{{namespaceSubPart}}; - -{{>common/imports}} -import com.twilio.base.Resource; -import java.io.IOException; -import com.fasterxml.jackson.core.JsonParseException; - -@JsonIgnoreProperties(ignoreUnknown = true) -@ToString -public class {{resourceName}} extends Resource { - -{{>allConstructors}} -{{>enums}} -{{>models}} -{{>staticMethods}} -{{>response}} -} -{{/resources}} - diff --git a/src/main/resources/twilio-java-modern/creator.mustache b/src/main/resources/twilio-java-modern/creator.mustache deleted file mode 100644 index 521f180c0..000000000 --- a/src/main/resources/twilio-java-modern/creator.mustache +++ /dev/null @@ -1,30 +0,0 @@ -{{>licenseInfo}} -{{#resources}} -package com.twilio.rest.{{domainPackage}}.{{apiVersion}}{{namespaceSubPart}}; - -{{>common/imports}} - -{{#operations}} -{{#vendorExtensions.x-create-operation}} -public class {{resourceName}}Creator extends Creator<{{resourceName}}> { - -{{>common/instanceVariables}} -{{>common/constructors}} -{{>creator/setters}} -{{>creator/operationMethod}} -{{#queryParams.0}} - {{>common/addQueryParams}} -{{/queryParams.0}} -{{#formParams.0}} - {{>common/addPostParams}} -{{/formParams.0}} -{{#headerParams.0}} - {{>common/addHeaderParams}} -{{/headerParams.0}} -{{#bodyParams.0}} - {{>common/addPostParamsJson}} -{{/bodyParams.0}} -} -{{/vendorExtensions.x-create-operation}} -{{/operations}} -{{/resources}} \ No newline at end of file diff --git a/src/main/resources/twilio-java-modern/deleter.mustache b/src/main/resources/twilio-java-modern/deleter.mustache deleted file mode 100644 index e4cdeb330..000000000 --- a/src/main/resources/twilio-java-modern/deleter.mustache +++ /dev/null @@ -1,23 +0,0 @@ -{{>licenseInfo}} -{{#resources}} -package com.twilio.rest.{{domainPackage}}.{{apiVersion}}{{namespaceSubPart}}; -{{>common/imports}} - - {{#operations}} - {{#vendorExtensions.x-delete-operation}} - public class {{resourceName}}Deleter extends Deleter<{{resourceName}}> { - - {{>common/instanceVariables}} - {{>common/constructors}} - {{>deleter/setters}} - {{>deleter/operationMethod}} - {{#queryParams.0}} - {{>common/addQueryParams}} - {{/queryParams.0}} - {{#headerParams.0}} - {{>common/addHeaderParams}} - {{/headerParams.0}} - } - {{/vendorExtensions.x-delete-operation}} - {{/operations}} -{{/resources}} \ No newline at end of file diff --git a/src/main/resources/twilio-java-modern/enums.mustache b/src/main/resources/twilio-java-modern/enums.mustache deleted file mode 100644 index 6e13ae918..000000000 --- a/src/main/resources/twilio-java-modern/enums.mustache +++ /dev/null @@ -1,22 +0,0 @@ -{{#mustacheEnums}} -public enum {{className}} { -{{#enumValues}} - {{name}}({{{value}}}){{^-last}},{{/-last}}{{#-last}};{{/-last}} -{{/enumValues}} - - private final String value; - - private {{className}}(final String value) { - this.value = value; - } - - public String toString() { - return value; - } - - @JsonCreator - public static {{className}} forValue(final String value) { - return Promoter.enumFromString(value, {{className}}.values()); - } -} -{{/mustacheEnums}} \ No newline at end of file diff --git a/src/main/resources/twilio-java-modern/fetcher.mustache b/src/main/resources/twilio-java-modern/fetcher.mustache deleted file mode 100644 index 1c0280c97..000000000 --- a/src/main/resources/twilio-java-modern/fetcher.mustache +++ /dev/null @@ -1,23 +0,0 @@ -{{>licenseInfo}} -{{#resources}} -package com.twilio.rest.{{domainPackage}}.{{apiVersion}}{{namespaceSubPart}}; -{{>common/imports}} - -{{#operations}} -{{#vendorExtensions.x-fetch-operation}} - public class {{resourceName}}Fetcher extends Fetcher<{{resourceName}}> { - - {{>common/instanceVariables}} - {{>common/constructors}} - {{>fetcher/setters}} - {{>fetcher/operationMethod}} - {{#queryParams.0}} - {{>common/addQueryParams}} - {{/queryParams.0}} - {{#headerParams.0}} - {{>common/addHeaderParams}} - {{/headerParams.0}} - } -{{/vendorExtensions.x-fetch-operation}} -{{/operations}} -{{/resources}} \ No newline at end of file diff --git a/src/main/resources/twilio-java-modern/models.mustache b/src/main/resources/twilio-java-modern/models.mustache deleted file mode 100644 index b23a58c91..000000000 --- a/src/main/resources/twilio-java-modern/models.mustache +++ /dev/null @@ -1,28 +0,0 @@ -{{#mustacheModels}} - - //@JsonDeserialize(builder = {{className}}.Builder.class) - @JsonInclude(JsonInclude.Include.NON_EMPTY) - @ToString -{{!@Builder}} - public static class {{className}} { - {{#mandatoryProperties.0}} - public {{className}}({{#mandatoryProperties}} final {{{dataType}}} {{name}}{{^-last}}, {{/-last}} {{/mandatoryProperties}}) { - {{#mandatoryProperties}} - this.{{name}} = {{name}}; - {{/mandatoryProperties}} - } - {{/mandatoryProperties.0}} - - {{#allProperties}} - {{#vendorExtensions.x-deserializer}} - @JsonDeserialize(using = {{vendorExtensions.x-deserializer}}.class) - {{/vendorExtensions.x-deserializer}} - @JsonInclude(JsonInclude.Include.NON_EMPTY) - @JsonProperty("{{{baseName}}}") - @Getter @Setter private {{{dataType}}} {{name}}; - - {{/allProperties}} -{{! @JsonPOJOBuilder(withPrefix = "") -public static class Builder {}} - } -{{/mustacheModels}} diff --git a/src/main/resources/twilio-java-modern/reader.mustache b/src/main/resources/twilio-java-modern/reader.mustache deleted file mode 100644 index 74ae0f226..000000000 --- a/src/main/resources/twilio-java-modern/reader.mustache +++ /dev/null @@ -1,25 +0,0 @@ -{{>licenseInfo}} -{{#resources}} -package com.twilio.rest.{{domainPackage}}.{{apiVersion}}{{namespaceSubPart}}; -{{>common/imports}} -import com.twilio.base.Page; -import com.twilio.base.ResourceSet; - -{{#operations}} -{{#vendorExtensions.x-list-operation}} -public class {{resourceName}}Reader extends Reader<{{resourceName}}> { - - {{>common/instanceVariables}} - {{>common/constructors}} - {{>reader/setters}} - {{>reader/operationMethod}} -{{#queryParams.0}} - {{>common/addQueryParams}} -{{/queryParams.0}} -{{#headerParams.0}} - {{>common/addHeaderParams}} -{{/headerParams.0}} -} -{{/vendorExtensions.x-list-operation}} -{{/operations}} -{{/resources}} \ No newline at end of file diff --git a/src/main/resources/twilio-java-modern/updater.mustache b/src/main/resources/twilio-java-modern/updater.mustache deleted file mode 100644 index e447ea9f5..000000000 --- a/src/main/resources/twilio-java-modern/updater.mustache +++ /dev/null @@ -1,28 +0,0 @@ -{{>licenseInfo}} -{{#resources}} -package com.twilio.rest.{{domainPackage}}.{{apiVersion}}{{namespaceSubPart}}; -{{>common/imports}} - -{{#operations}} -{{#vendorExtensions.x-update-operation}} - public class {{resourceName}}Updater extends Updater<{{resourceName}}> { - {{>common/instanceVariables}} - {{>common/constructors}} - {{>updater/setters}} - {{>updater/operationMethod}} - {{#queryParams.0}} - {{>common/addQueryParams}} - {{/queryParams.0}} - {{#formParams.0}} - {{>common/addPostParams}} - {{/formParams.0}} - {{#headerParams.0}} - {{>common/addHeaderParams}} - {{/headerParams.0}} - {{#bodyParams.0}} - {{>common/addPostParamsJson}} - {{/bodyParams.0}} - } -{{/vendorExtensions.x-update-operation}} -{{/operations}} -{{/resources}} \ No newline at end of file diff --git a/src/main/resources/twilio-java-modern/Readme.md b/src/main/resources/twilio-java/Readme.md similarity index 100% rename from src/main/resources/twilio-java-modern/Readme.md rename to src/main/resources/twilio-java/Readme.md diff --git a/src/main/resources/twilio-java-modern/allConstructors.mustache b/src/main/resources/twilio-java/allConstructors.mustache similarity index 100% rename from src/main/resources/twilio-java-modern/allConstructors.mustache rename to src/main/resources/twilio-java/allConstructors.mustache diff --git a/src/main/resources/twilio-java/api.mustache b/src/main/resources/twilio-java/api.mustache index deaa723ed..f38a63e80 100644 --- a/src/main/resources/twilio-java/api.mustache +++ b/src/main/resources/twilio-java/api.mustache @@ -2,166 +2,20 @@ {{#resources}} package com.twilio.rest.{{domainPackage}}.{{apiVersion}}{{namespaceSubPart}}; -import com.fasterxml.jackson.annotation.JsonCreator; -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonInclude; -import com.fasterxml.jackson.annotation.JsonProperty; -import com.fasterxml.jackson.core.JsonParseException; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.JsonMappingException; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.twilio.base{{authMethodPackage}}.Resource; -import com.twilio.converter.Converter; -import java.util.Currency; -import com.twilio.converter.DateConverter; -import com.twilio.converter.Promoter; -import com.twilio.converter.PrefixedCollapsibleMap; -import com.twilio.converter.CurrencyDeserializer; -import com.twilio.exception.ApiConnectionException; -import com.fasterxml.jackson.databind.annotation.JsonDeserialize; - -import com.twilio.exception.ApiException; -import com.twilio.exception.RestException; -import com.twilio.http.HttpMethod; -import com.twilio.http.Request; -import com.twilio.http.Response; -import com.twilio.http.TwilioRestClient; -import com.twilio.rest.Domains; - -import lombok.ToString; - +{{>common/imports}} +import com.twilio.base.Resource; import java.io.IOException; -import java.io.InputStream; -import java.net.URI; -import java.time.ZonedDateTime; - -{{^fullJavaUtil}} -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Objects; -{{/fullJavaUtil}} - -import lombok.Getter; -import lombok.Setter; -import lombok.ToString; - -import java.util.Map; -import java.time.LocalDate; -import java.math.BigDecimal; -import com.twilio.type.PhoneNumberCapabilities; -import com.twilio.type.FeedbackIssue; -import com.twilio.type.IceServer; -import com.twilio.type.InboundCallPrice; -import com.twilio.type.OutboundPrefixPriceWithOrigin; -import com.twilio.type.OutboundPrefixPrice; -import com.twilio.type.OutboundCallPriceWithOrigin; -import com.twilio.type.PhoneNumberPrice; -import com.twilio.type.InboundSmsPrice; -import com.twilio.type.OutboundSmsPrice; -import com.twilio.type.OutboundCallPrice; -import com.twilio.type.RecordingRule; -import com.twilio.type.SubscribeRule; +import com.fasterxml.jackson.core.JsonParseException; @JsonIgnoreProperties(ignoreUnknown = true) @ToString -public class {{apiName}} extends Resource { - private static final long serialVersionUID = {{serialVersionUID}}L; - - {{>models}} - {{#apiOperations}} - {{#vendorExtensions.x-is-create-operation}} - {{#vendorExtensions.x-signature-list}} - public static {{apiName}}Creator creator({{#.}}final {{{dataType}}} {{{paramName}}}{{^-last}}, {{/-last}}{{/.}}){ - return new {{apiName}}Creator({{#.}}{{{paramName}}}{{^-last}}, {{/-last}}{{/.}}); - } - {{/vendorExtensions.x-signature-list}} - - {{/vendorExtensions.x-is-create-operation}} - {{#vendorExtensions.x-is-fetch-operation}} - {{#vendorExtensions.x-signature-list}} - public static {{apiName}}Fetcher fetcher({{#.}}final {{{dataType}}} {{{paramName}}}{{^-last}}, {{/-last}}{{/.}}){ - return new {{apiName}}Fetcher({{#.}}{{{paramName}}}{{^-last}}, {{/-last}}{{/.}}); - } - {{/vendorExtensions.x-signature-list}} - - {{/vendorExtensions.x-is-fetch-operation}} - {{#vendorExtensions.x-is-delete-operation}} - {{#vendorExtensions.x-signature-list}} - public static {{apiName}}Deleter deleter({{#.}}final {{{dataType}}} {{{paramName}}}{{^-last}}, {{/-last}}{{/.}}){ - return new {{apiName}}Deleter({{#.}}{{{paramName}}}{{^-last}}, {{/-last}}{{/.}}); - } - {{/vendorExtensions.x-signature-list}} - - {{/vendorExtensions.x-is-delete-operation}} - {{#vendorExtensions.x-is-read-operation}} - {{#vendorExtensions.x-signature-list}} - public static {{apiName}}Reader reader({{#.}}final {{{dataType}}} {{{paramName}}}{{^-last}}, {{/-last}}{{/.}}){ - return new {{apiName}}Reader({{#.}}{{{paramName}}}{{^-last}}, {{/-last}}{{/.}}); - } - {{/vendorExtensions.x-signature-list}} - - {{/vendorExtensions.x-is-read-operation}} - {{#vendorExtensions.x-is-update-operation}} - {{#vendorExtensions.x-signature-list}} - public static {{apiName}}Updater updater({{#.}}final {{{dataType}}} {{{paramName}}}{{^-last}}, {{/-last}}{{/.}}){ - return new {{apiName}}Updater({{#.}}{{{paramName}}}{{^-last}}, {{/-last}}{{/.}}); - } - {{/vendorExtensions.x-signature-list}} - - {{/vendorExtensions.x-is-update-operation}} - {{/apiOperations}} - /** - * Converts a JSON String into a {{apiName}} object using the provided ObjectMapper. - * - * @param json Raw JSON String - * @param objectMapper Jackson ObjectMapper - * @return {{apiName}} object represented by the provided JSON - */ - public static {{apiName}} fromJson(final String json, final ObjectMapper objectMapper) { - // Convert all checked exceptions to Runtime - try { - return objectMapper.readValue(json, {{apiName}}.class); - } catch (final JsonMappingException | JsonParseException e) { - throw new ApiException(e.getMessage(), e); - } catch (final IOException e) { - throw new ApiConnectionException(e.getMessage(), e); - } - } +public class {{resourceName}} extends Resource { - /** - * Converts a JSON InputStream into a {{apiName}} object using the provided - * ObjectMapper. - * - * @param json Raw JSON InputStream - * @param objectMapper Jackson ObjectMapper - * @return {{apiName}} object represented by the provided JSON - */ - public static {{apiName}} fromJson(final InputStream json, final ObjectMapper objectMapper) { - // Convert all checked exceptions to Runtime - try { - return objectMapper.readValue(json, {{apiName}}.class); - } catch (final JsonMappingException | JsonParseException e) { - throw new ApiException(e.getMessage(), e); - } catch (final IOException e) { - throw new ApiConnectionException(e.getMessage(), e); - } - } - {{#hasNestedRequestBody}} - public static String toJson(Object object, ObjectMapper mapper) { - try { - return mapper.writeValueAsString(object); - } catch (final JsonMappingException e) { - throw new ApiException(e.getMessage(), e); - } catch (JsonProcessingException e) { - throw new ApiException(e.getMessage(), e); - } catch (final IOException e) { - throw new ApiConnectionException(e.getMessage(), e); - } - }{{/hasNestedRequestBody}} -{{>responseModel}} +{{>allConstructors}} {{>enums}} +{{>models}} +{{>staticMethods}} +{{>response}} } {{/resources}} diff --git a/src/main/resources/twilio-java-modern/common/addHeaderParams.mustache b/src/main/resources/twilio-java/common/addHeaderParams.mustache similarity index 100% rename from src/main/resources/twilio-java-modern/common/addHeaderParams.mustache rename to src/main/resources/twilio-java/common/addHeaderParams.mustache diff --git a/src/main/resources/twilio-java-modern/common/addPostParams.mustache b/src/main/resources/twilio-java/common/addPostParams.mustache similarity index 100% rename from src/main/resources/twilio-java-modern/common/addPostParams.mustache rename to src/main/resources/twilio-java/common/addPostParams.mustache diff --git a/src/main/resources/twilio-java-modern/common/addPostParamsJson.mustache b/src/main/resources/twilio-java/common/addPostParamsJson.mustache similarity index 100% rename from src/main/resources/twilio-java-modern/common/addPostParamsJson.mustache rename to src/main/resources/twilio-java/common/addPostParamsJson.mustache diff --git a/src/main/resources/twilio-java-modern/common/addQueryParams.mustache b/src/main/resources/twilio-java/common/addQueryParams.mustache similarity index 100% rename from src/main/resources/twilio-java-modern/common/addQueryParams.mustache rename to src/main/resources/twilio-java/common/addQueryParams.mustache diff --git a/src/main/resources/twilio-java-modern/common/constructors.mustache b/src/main/resources/twilio-java/common/constructors.mustache similarity index 100% rename from src/main/resources/twilio-java-modern/common/constructors.mustache rename to src/main/resources/twilio-java/common/constructors.mustache diff --git a/src/main/resources/twilio-java-modern/common/generateUri.mustache b/src/main/resources/twilio-java/common/generateUri.mustache similarity index 100% rename from src/main/resources/twilio-java-modern/common/generateUri.mustache rename to src/main/resources/twilio-java/common/generateUri.mustache diff --git a/src/main/resources/twilio-java-modern/common/imports.mustache b/src/main/resources/twilio-java/common/imports.mustache similarity index 100% rename from src/main/resources/twilio-java-modern/common/imports.mustache rename to src/main/resources/twilio-java/common/imports.mustache diff --git a/src/main/resources/twilio-java-modern/common/instanceVariables.mustache b/src/main/resources/twilio-java/common/instanceVariables.mustache similarity index 100% rename from src/main/resources/twilio-java-modern/common/instanceVariables.mustache rename to src/main/resources/twilio-java/common/instanceVariables.mustache diff --git a/src/main/resources/twilio-java-modern/common/operationMethod.mustache b/src/main/resources/twilio-java/common/operationMethod.mustache similarity index 100% rename from src/main/resources/twilio-java-modern/common/operationMethod.mustache rename to src/main/resources/twilio-java/common/operationMethod.mustache diff --git a/src/main/resources/twilio-java-modern/common/setters.mustache b/src/main/resources/twilio-java/common/setters.mustache similarity index 100% rename from src/main/resources/twilio-java-modern/common/setters.mustache rename to src/main/resources/twilio-java/common/setters.mustache diff --git a/src/main/resources/twilio-java/creator.mustache b/src/main/resources/twilio-java/creator.mustache index 1c19dac2e..521f180c0 100644 --- a/src/main/resources/twilio-java/creator.mustache +++ b/src/main/resources/twilio-java/creator.mustache @@ -2,135 +2,29 @@ {{#resources}} package com.twilio.rest.{{domainPackage}}.{{apiVersion}}{{namespaceSubPart}}; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.twilio.constant.EnumConstants; -import com.twilio.converter.Promoter; -import com.twilio.exception.ApiConnectionException; -import com.twilio.converter.PrefixedCollapsibleMap; -import com.twilio.converter.Converter; -import com.twilio.exception.ApiException; -import com.twilio.exception.RestException; -import com.twilio.http.HttpMethod; -import com.twilio.http.Response; -import com.twilio.rest.Domains; -import java.math.BigDecimal; -import java.util.List; -import java.util.Map; -import java.time.LocalDate; -import com.twilio.converter.Converter; -import java.time.ZonedDateTime; -import java.io.IOException; -import java.io.InputStream; -import java.math.BigDecimal; -import java.net.URI; -import java.time.format.DateTimeFormatter; -import com.twilio.converter.DateConverter; - -{{^fullJavaUtil}} -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.UUID; -{{/fullJavaUtil}} - -import lombok.ToString; - -import java.net.URI; - -{{#apiOperations}} -{{#vendorExtensions.x-is-create-operation}} -import com.twilio.base{{vendorExtensions.x-auth-attributes.x-auth-import-class}}.Creator; -import com.twilio.http{{vendorExtensions.x-auth-attributes.x-auth-import-class}}.{{vendorExtensions.x-auth-attributes.x-http-class-prefix}}Request; -import com.twilio.http{{vendorExtensions.x-auth-attributes.x-auth-import-class}}.{{vendorExtensions.x-auth-attributes.x-http-class-prefix}}TwilioRestClient; - -public class {{apiName}}Creator extends Creator<{{apiName}}>{ -{{#allParams}} - private {{{dataType}}} {{paramName}}; -{{/allParams}} - -{{#vendorExtensions.x-signature-list}} - public {{apiName}}Creator({{#.}}final {{{dataType}}} {{paramName}}{{^-last}}, {{/-last}}{{/.}}) { - {{#.}} - this.{{paramName}} = {{paramName}}; - {{/.}} - } -{{/vendorExtensions.x-signature-list}} - -{{#vendorExtensions.x-non-path-params}} - public {{apiName}}Creator set{{#lambda.titlecase}}{{paramName}}{{/lambda.titlecase}}(final {{{dataType}}} {{paramName}}){ - this.{{paramName}} = {{paramName}}; - return this; - } -{{#isArray}} - public {{apiName}}Creator set{{#lambda.titlecase}}{{paramName}}{{/lambda.titlecase}}(final {{{baseType}}} {{paramName}}){ - return set{{#lambda.titlecase}}{{paramName}}{{/lambda.titlecase}}(Promoter.listOfOne({{paramName}})); - } -{{/isArray}} -{{#vendorExtensions.x-promotions}} -{{#entrySet}} - - public {{apiName}}Creator set{{#lambda.titlecase}}{{paramName}}{{/lambda.titlecase}}(final {{#lambda.titlecase}}{{key}}{{/lambda.titlecase}} {{paramName}}){ - return set{{#lambda.titlecase}}{{paramName}}{{/lambda.titlecase}}({{value}}); - } -{{/entrySet}} -{{/vendorExtensions.x-promotions}} -{{/vendorExtensions.x-non-path-params}} - - @Override - public {{apiName}} create(final {{vendorExtensions.x-auth-attributes.x-http-class-prefix}}TwilioRestClient client){ -{{>generate_uri}} - {{vendorExtensions.x-auth-attributes.x-http-class-prefix}}Request request = new {{vendorExtensions.x-auth-attributes.x-http-class-prefix}}Request( - {{vendorExtensions.x-http-method}}, - Domains.{{#lambda.uppercase}}{{domainName}}{{/lambda.uppercase}}.toString(), - path - ); - {{#queryParams.0}} - addQueryParams(request); - {{/queryParams.0}} - {{^vendorExtensions.x-is-json}} - request.setContentType(EnumConstants.ContentType.FORM_URLENCODED); - {{/vendorExtensions.x-is-json}} - {{#vendorExtensions.x-is-json}} - request.setContentType(EnumConstants.ContentType.JSON); - {{/vendorExtensions.x-is-json}} - {{#formParams.0}} - addPostParams(request); - {{/formParams.0}} - {{#bodyParams.0}} - addPostParams(request, client); - {{/bodyParams.0}} - {{#headerParams.0}} - addHeaderParams(request); - {{/headerParams.0}} - Response response = client.request(request); - if (response == null) { - throw new ApiConnectionException("{{apiName}} creation failed: Unable to connect to server"); - } else if (!{{vendorExtensions.x-auth-attributes.x-http-class-prefix}}TwilioRestClient.SUCCESS.test(response.getStatusCode())) { - RestException restException = RestException.fromJson(response.getStream(), client.getObjectMapper()); - if (restException == null) { - throw new ApiException("Server Error, no content", response.getStatusCode()); - } - throw new ApiException(restException); - } - - return {{apiName}}.fromJson(response.getStream(), client.getObjectMapper()); - } -{{#vendorExtensions.x-has-form-params}} -{{>postParams}} -{{/vendorExtensions.x-has-form-params}} -{{#vendorExtensions.x-has-body-params}} -{{>postParams_body}} -{{/vendorExtensions.x-has-body-params}} -{{#vendorExtensions.x-has-header-params}} -{{>headerParams}} -{{/vendorExtensions.x-has-header-params}} -{{#vendorExtensions.x-has-query-params}} - private void addQueryParams(final {{vendorExtensions.x-auth-attributes.x-http-class-prefix}}Request request) { -{{>queryParams}} } -{{/vendorExtensions.x-has-query-params}} +{{>common/imports}} + +{{#operations}} +{{#vendorExtensions.x-create-operation}} +public class {{resourceName}}Creator extends Creator<{{resourceName}}> { + +{{>common/instanceVariables}} +{{>common/constructors}} +{{>creator/setters}} +{{>creator/operationMethod}} +{{#queryParams.0}} + {{>common/addQueryParams}} +{{/queryParams.0}} +{{#formParams.0}} + {{>common/addPostParams}} +{{/formParams.0}} +{{#headerParams.0}} + {{>common/addHeaderParams}} +{{/headerParams.0}} +{{#bodyParams.0}} + {{>common/addPostParamsJson}} +{{/bodyParams.0}} } -{{/vendorExtensions.x-is-create-operation}} -{{/apiOperations}} -{{/resources}} +{{/vendorExtensions.x-create-operation}} +{{/operations}} +{{/resources}} \ No newline at end of file diff --git a/src/main/resources/twilio-java-modern/creator/operationMethod.mustache b/src/main/resources/twilio-java/creator/operationMethod.mustache similarity index 100% rename from src/main/resources/twilio-java-modern/creator/operationMethod.mustache rename to src/main/resources/twilio-java/creator/operationMethod.mustache diff --git a/src/main/resources/twilio-java-modern/creator/setters.mustache b/src/main/resources/twilio-java/creator/setters.mustache similarity index 100% rename from src/main/resources/twilio-java-modern/creator/setters.mustache rename to src/main/resources/twilio-java/creator/setters.mustache diff --git a/src/main/resources/twilio-java/deleter.mustache b/src/main/resources/twilio-java/deleter.mustache index 082c5df14..e4cdeb330 100644 --- a/src/main/resources/twilio-java/deleter.mustache +++ b/src/main/resources/twilio-java/deleter.mustache @@ -1,129 +1,23 @@ {{>licenseInfo}} {{#resources}} package com.twilio.rest.{{domainPackage}}.{{apiVersion}}{{namespaceSubPart}}; - -import com.fasterxml.jackson.databind.ObjectMapper; -import com.twilio.converter.Promoter; -import com.twilio.constant.EnumConstants; -import com.twilio.exception.ApiConnectionException; -import com.twilio.converter.PrefixedCollapsibleMap; -import com.twilio.exception.ApiException; -import com.twilio.converter.Converter; -import com.twilio.exception.RestException; -import com.twilio.http.HttpMethod; -import com.twilio.http.Response; -import com.twilio.rest.Domains; -import java.time.LocalDate; -import java.io.IOException; -import java.io.InputStream; -import java.math.BigDecimal; -import java.net.URI; -import java.time.ZonedDateTime; -import java.time.format.DateTimeFormatter; -import com.twilio.converter.DateConverter; - -{{^fullJavaUtil}} -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Objects; -{{/fullJavaUtil}} - -import lombok.ToString; - -{{#apiOperations}} -{{#vendorExtensions.x-is-delete-operation}} -import com.twilio.base{{vendorExtensions.x-auth-attributes.x-auth-import-class}}.Deleter; -import com.twilio.http{{vendorExtensions.x-auth-attributes.x-auth-import-class}}.{{vendorExtensions.x-auth-attributes.x-http-class-prefix}}Request; -import com.twilio.http{{vendorExtensions.x-auth-attributes.x-auth-import-class}}.{{vendorExtensions.x-auth-attributes.x-http-class-prefix}}TwilioRestClient; - -public class {{apiName}}Deleter extends Deleter<{{apiName}}> { -{{#allParams}} - private {{{dataType}}} {{paramName}}; -{{/allParams}} - -{{#vendorExtensions.x-signature-list}} - public {{apiName}}Deleter({{#.}}final {{{dataType}}} {{paramName}}{{^-last}}, {{/-last}}{{/.}}){ - {{#.}} - this.{{paramName}} = {{paramName}}; - {{/.}} - } -{{/vendorExtensions.x-signature-list}} - -{{#vendorExtensions.x-non-path-params}} - public {{apiName}}Deleter set{{#lambda.titlecase}}{{paramName}}{{/lambda.titlecase}}(final {{{dataType}}} {{paramName}}){ - this.{{paramName}} = {{paramName}}; - return this; - } -{{#isArray}} - public {{apiName}}Deleter set{{#lambda.titlecase}}{{paramName}}{{/lambda.titlecase}}(final {{{baseType}}} {{paramName}}){ - return set{{#lambda.titlecase}}{{paramName}}{{/lambda.titlecase}}(Promoter.listOfOne({{paramName}})); - } -{{/isArray}} -{{#vendorExtensions.x-promotions}} -{{#entrySet}} - - public {{apiName}}Deleter set{{#lambda.titlecase}}{{paramName}}{{/lambda.titlecase}}(final {{#lambda.titlecase}}{{key}}{{/lambda.titlecase}} {{paramName}}){ - return set{{#lambda.titlecase}}{{paramName}}{{/lambda.titlecase}}({{value}}); - } -{{/entrySet}} -{{/vendorExtensions.x-promotions}} -{{/vendorExtensions.x-non-path-params}} - - @Override - public boolean delete(final {{vendorExtensions.x-auth-attributes.x-http-class-prefix}}TwilioRestClient client) { -{{>generate_uri}} - {{vendorExtensions.x-auth-attributes.x-http-class-prefix}}Request request = new {{vendorExtensions.x-auth-attributes.x-http-class-prefix}}Request( - {{vendorExtensions.x-http-method}}, - Domains.{{#lambda.uppercase}}{{domainName}}{{/lambda.uppercase}}.toString(), - path - ); - {{#queryParams.0}} - addQueryParams(request); - {{/queryParams.0}} - {{^vendorExtensions.x-is-json}} - request.setContentType(EnumConstants.ContentType.FORM_URLENCODED); - {{/vendorExtensions.x-is-json}} - {{#vendorExtensions.x-is-json}} - request.setContentType(EnumConstants.ContentType.JSON); - {{/vendorExtensions.x-is-json}} - {{#formParams.0}} - addPostParams(request); - {{/formParams.0}} - {{#bodyParams.0}} - addPostParams(request, client); - {{/bodyParams.0}} - {{#headerParams.0}} - addHeaderParams(request); - {{/headerParams.0}} - Response response = client.request(request); - - if (response == null) { - throw new ApiConnectionException("{{apiName}} delete failed: Unable to connect to server"); - } else if (!{{vendorExtensions.x-auth-attributes.x-http-class-prefix}}TwilioRestClient.SUCCESS.test(response.getStatusCode())) { - RestException restException = RestException.fromJson(response.getStream(), client.getObjectMapper()); - if (restException == null) { - throw new ApiException("Server Error, no content", response.getStatusCode()); +{{>common/imports}} + + {{#operations}} + {{#vendorExtensions.x-delete-operation}} + public class {{resourceName}}Deleter extends Deleter<{{resourceName}}> { + + {{>common/instanceVariables}} + {{>common/constructors}} + {{>deleter/setters}} + {{>deleter/operationMethod}} + {{#queryParams.0}} + {{>common/addQueryParams}} + {{/queryParams.0}} + {{#headerParams.0}} + {{>common/addHeaderParams}} + {{/headerParams.0}} } - throw new ApiException(restException); - } - return response.getStatusCode() == 204; - } -{{#vendorExtensions.x-has-form-params}} -{{>postParams}} -{{/vendorExtensions.x-has-form-params}} -{{#vendorExtensions.x-has-body-params}} -{{>postParams_body}} -{{/vendorExtensions.x-has-body-params}} -{{#vendorExtensions.x-has-header-params}} -{{>headerParams}} -{{/vendorExtensions.x-has-header-params}} -{{#vendorExtensions.x-has-query-params}} - private void addQueryParams(final {{vendorExtensions.x-auth-attributes.x-http-class-prefix}}Request request) { -{{>queryParams}} } -{{/vendorExtensions.x-has-query-params}} -} -{{/vendorExtensions.x-is-delete-operation}} -{{/apiOperations}} -{{/resources}} + {{/vendorExtensions.x-delete-operation}} + {{/operations}} +{{/resources}} \ No newline at end of file diff --git a/src/main/resources/twilio-java-modern/deleter/operationMethod.mustache b/src/main/resources/twilio-java/deleter/operationMethod.mustache similarity index 100% rename from src/main/resources/twilio-java-modern/deleter/operationMethod.mustache rename to src/main/resources/twilio-java/deleter/operationMethod.mustache diff --git a/src/main/resources/twilio-java-modern/deleter/setters.mustache b/src/main/resources/twilio-java/deleter/setters.mustache similarity index 100% rename from src/main/resources/twilio-java-modern/deleter/setters.mustache rename to src/main/resources/twilio-java/deleter/setters.mustache diff --git a/src/main/resources/twilio-java/enums.mustache b/src/main/resources/twilio-java/enums.mustache index 43c17f9fa..6e13ae918 100644 --- a/src/main/resources/twilio-java/enums.mustache +++ b/src/main/resources/twilio-java/enums.mustache @@ -1,24 +1,22 @@ -{{#enums}} - public enum {{#lambda.titlecase}}{{{enumName}}}{{/lambda.titlecase}} { - {{#allowableValues}} - {{#values}} - {{#lambda.uppercase}}{{#lambda.replacehyphen}}{{{.}}}{{/lambda.replacehyphen}}({{/lambda.uppercase}}"{{{.}}}"){{^-last}},{{/-last}}{{#-last}};{{/-last}} - {{/values}} - {{/allowableValues}} +{{#mustacheEnums}} +public enum {{className}} { +{{#enumValues}} + {{name}}({{{value}}}){{^-last}},{{/-last}}{{#-last}};{{/-last}} +{{/enumValues}} - private final String value; + private final String value; - private {{#lambda.titlecase}}{{{enumName}}}{{/lambda.titlecase}}(final String value) { + private {{className}}(final String value) { this.value = value; - } + } - public String toString() { - return value; - } + public String toString() { + return value; + } - @JsonCreator - public static {{#lambda.titlecase}}{{{enumName}}}{{/lambda.titlecase}} forValue(final String value) { - return Promoter.enumFromString(value, {{#lambda.titlecase}}{{{enumName}}}{{/lambda.titlecase}}.values()); - } + @JsonCreator + public static {{className}} forValue(final String value) { + return Promoter.enumFromString(value, {{className}}.values()); } -{{/enums}} \ No newline at end of file +} +{{/mustacheEnums}} \ No newline at end of file diff --git a/src/main/resources/twilio-java-modern/equalsAndHashcode.mustache b/src/main/resources/twilio-java/equalsAndHashcode.mustache similarity index 100% rename from src/main/resources/twilio-java-modern/equalsAndHashcode.mustache rename to src/main/resources/twilio-java/equalsAndHashcode.mustache diff --git a/src/main/resources/twilio-java/fetcher.mustache b/src/main/resources/twilio-java/fetcher.mustache index 34be9003b..1c0280c97 100644 --- a/src/main/resources/twilio-java/fetcher.mustache +++ b/src/main/resources/twilio-java/fetcher.mustache @@ -1,131 +1,23 @@ {{>licenseInfo}} {{#resources}} package com.twilio.rest.{{domainPackage}}.{{apiVersion}}{{namespaceSubPart}}; - -import com.fasterxml.jackson.databind.ObjectMapper; -import com.twilio.constant.EnumConstants; -import com.twilio.converter.Promoter; -import com.twilio.exception.ApiConnectionException; -import com.twilio.converter.PrefixedCollapsibleMap; -import com.twilio.converter.Converter; -import com.twilio.exception.ApiException; -import com.twilio.exception.RestException; -import com.twilio.http.HttpMethod; -import com.twilio.http.Response; -import com.twilio.rest.Domains; - -import java.io.IOException; -import java.io.InputStream; -import java.math.BigDecimal; -import java.net.URI; -import java.time.ZonedDateTime; -import java.time.LocalDate; -import java.time.format.DateTimeFormatter; -import com.twilio.converter.DateConverter; - -{{^fullJavaUtil}} -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Objects; -{{/fullJavaUtil}} - -import lombok.ToString; - -{{#apiOperations}} -{{#vendorExtensions.x-is-fetch-operation}} -import com.twilio.base{{vendorExtensions.x-auth-attributes.x-auth-import-class}}.Fetcher; -import com.twilio.http{{vendorExtensions.x-auth-attributes.x-auth-import-class}}.{{vendorExtensions.x-auth-attributes.x-http-class-prefix}}Request; -import com.twilio.http{{vendorExtensions.x-auth-attributes.x-auth-import-class}}.{{vendorExtensions.x-auth-attributes.x-http-class-prefix}}TwilioRestClient; - -public class {{apiName}}Fetcher extends Fetcher<{{apiName}}> { -{{#allParams}} - private {{{dataType}}} {{paramName}}; -{{/allParams}} - -{{#vendorExtensions.x-signature-list}} - public {{apiName}}Fetcher({{#.}}final {{{dataType}}} {{paramName}}{{^-last}}, {{/-last}}{{/.}}){ - {{#.}} - this.{{paramName}} = {{paramName}}; - {{/.}} - } -{{/vendorExtensions.x-signature-list}} - -{{#vendorExtensions.x-non-path-params}} - public {{apiName}}Fetcher set{{#lambda.titlecase}}{{paramName}}{{/lambda.titlecase}}(final {{{dataType}}} {{paramName}}){ - this.{{paramName}} = {{paramName}}; - return this; - } -{{#isArray}} - public {{apiName}}Fetcher set{{#lambda.titlecase}}{{paramName}}{{/lambda.titlecase}}(final {{{baseType}}} {{paramName}}){ - return set{{#lambda.titlecase}}{{paramName}}{{/lambda.titlecase}}(Promoter.listOfOne({{paramName}})); - } -{{/isArray}} -{{#vendorExtensions.x-promotions}} -{{#entrySet}} - - public {{apiName}}Fetcher set{{#lambda.titlecase}}{{paramName}}{{/lambda.titlecase}}(final {{#lambda.titlecase}}{{key}}{{/lambda.titlecase}} {{paramName}}){ - return set{{#lambda.titlecase}}{{paramName}}{{/lambda.titlecase}}({{value}}); - } -{{/entrySet}} -{{/vendorExtensions.x-promotions}} -{{/vendorExtensions.x-non-path-params}} - - @Override - public {{apiName}} fetch(final {{vendorExtensions.x-auth-attributes.x-http-class-prefix}}TwilioRestClient client) { -{{>generate_uri}} - {{vendorExtensions.x-auth-attributes.x-http-class-prefix}}Request request = new {{vendorExtensions.x-auth-attributes.x-http-class-prefix}}Request( - {{vendorExtensions.x-http-method}}, - Domains.{{#lambda.uppercase}}{{domainName}}{{/lambda.uppercase}}.toString(), - path - ); - {{#queryParams.0}} - addQueryParams(request); - {{/queryParams.0}} - {{^vendorExtensions.x-is-json}} - request.setContentType(EnumConstants.ContentType.FORM_URLENCODED); - {{/vendorExtensions.x-is-json}} - {{#vendorExtensions.x-is-json}} - request.setContentType(EnumConstants.ContentType.JSON); - {{/vendorExtensions.x-is-json}} - {{#formParams.0}} - addPostParams(request); - {{/formParams.0}} - {{#bodyParams.0}} - addPostParams(request, client); - {{/bodyParams.0}} - {{#headerParams.0}} - addHeaderParams(request); - {{/headerParams.0}} - Response response = client.request(request); - - if (response == null) { - throw new ApiConnectionException("{{apiName}} fetch failed: Unable to connect to server"); - } else if (!{{vendorExtensions.x-auth-attributes.x-http-class-prefix}}TwilioRestClient.SUCCESS.test(response.getStatusCode())) { - RestException restException = RestException.fromJson(response.getStream(), client.getObjectMapper()); - if (restException == null) { - throw new ApiException("Server Error, no content", response.getStatusCode()); - } - throw new ApiException(restException); - } - - return {{apiName}}.fromJson(response.getStream(), client.getObjectMapper()); +{{>common/imports}} + +{{#operations}} +{{#vendorExtensions.x-fetch-operation}} + public class {{resourceName}}Fetcher extends Fetcher<{{resourceName}}> { + + {{>common/instanceVariables}} + {{>common/constructors}} + {{>fetcher/setters}} + {{>fetcher/operationMethod}} + {{#queryParams.0}} + {{>common/addQueryParams}} + {{/queryParams.0}} + {{#headerParams.0}} + {{>common/addHeaderParams}} + {{/headerParams.0}} } -{{#vendorExtensions.x-has-form-params}} -{{>postParams}} -{{/vendorExtensions.x-has-form-params}} -{{#vendorExtensions.x-has-body-params}} -{{>postParams_body}} -{{/vendorExtensions.x-has-body-params}} -{{#vendorExtensions.x-has-header-params}} -{{>headerParams}} -{{/vendorExtensions.x-has-header-params}} -{{#vendorExtensions.x-has-query-params}} - private void addQueryParams(final {{vendorExtensions.x-auth-attributes.x-http-class-prefix}}Request request) { -{{>queryParams}} } -{{/vendorExtensions.x-has-query-params}} -} -{{/vendorExtensions.x-is-fetch-operation}} -{{/apiOperations}} -{{/resources}} +{{/vendorExtensions.x-fetch-operation}} +{{/operations}} +{{/resources}} \ No newline at end of file diff --git a/src/main/resources/twilio-java-modern/fetcher/operationMethod.mustache b/src/main/resources/twilio-java/fetcher/operationMethod.mustache similarity index 100% rename from src/main/resources/twilio-java-modern/fetcher/operationMethod.mustache rename to src/main/resources/twilio-java/fetcher/operationMethod.mustache diff --git a/src/main/resources/twilio-java-modern/fetcher/setters.mustache b/src/main/resources/twilio-java/fetcher/setters.mustache similarity index 100% rename from src/main/resources/twilio-java-modern/fetcher/setters.mustache rename to src/main/resources/twilio-java/fetcher/setters.mustache diff --git a/src/main/resources/twilio-java/models.mustache b/src/main/resources/twilio-java/models.mustache index a95788f86..b23a58c91 100644 --- a/src/main/resources/twilio-java/models.mustache +++ b/src/main/resources/twilio-java/models.mustache @@ -1,41 +1,28 @@ +{{#mustacheModels}} - {{#resources.nestedModels}} - @ToString - static public class {{classname}} { - {{#vars}} - @JsonInclude(JsonInclude.Include.NON_EMPTY) - @JsonProperty("{{{baseName}}}") - {{#vendorExtensions.x-ref-enum}} - @Getter @Setter private {{{datatypeWithEnum}}} {{name}}; - {{/vendorExtensions.x-ref-enum}} - {{^vendorExtensions.x-ref-enum}} - @Getter @Setter private {{{dataType}}} {{name}}; - {{/vendorExtensions.x-ref-enum}} - {{^isMap}} - {{^isFreeFormObject}} - {{^isAnyType}} - {{#vendorExtensions.x-serialize}} - public String get{{#lambda.titlecase}}{{name}}{{/lambda.titlecase}}() { - return {{vendorExtensions.x-serialize}}; - }{{/vendorExtensions.x-serialize}} - {{/isAnyType}} - {{/isFreeFormObject}} - {{/isMap}} - {{/vars}} - {{#vendorExtensions.x-constructor-required}} - {{#vendorExtensions.x-model-parameters}} - public {{classname}}({{#.}}final {{{dataType}}} {{name}}{{^-last}}, {{/-last}}{{/.}} ) { - {{#.}} - this.{{name}} = {{name}}; - {{/.}} - } - {{/vendorExtensions.x-model-parameters}} - {{/vendorExtensions.x-constructor-required}} + //@JsonDeserialize(builder = {{className}}.Builder.class) + @JsonInclude(JsonInclude.Include.NON_EMPTY) + @ToString +{{!@Builder}} + public static class {{className}} { + {{#mandatoryProperties.0}} + public {{className}}({{#mandatoryProperties}} final {{{dataType}}} {{name}}{{^-last}}, {{/-last}} {{/mandatoryProperties}}) { + {{#mandatoryProperties}} + this.{{name}} = {{name}}; + {{/mandatoryProperties}} + } + {{/mandatoryProperties.0}} + + {{#allProperties}} + {{#vendorExtensions.x-deserializer}} + @JsonDeserialize(using = {{vendorExtensions.x-deserializer}}.class) + {{/vendorExtensions.x-deserializer}} + @JsonInclude(JsonInclude.Include.NON_EMPTY) + @JsonProperty("{{{baseName}}}") + @Getter @Setter private {{{dataType}}} {{name}}; - {{^vendorExtensions.x-response}} - public static {{classname}} fromJson(String jsonString, ObjectMapper mapper) throws IOException { - return mapper.readValue(jsonString, {{classname}}.class); - } - {{/vendorExtensions.x-response}} - } - {{/resources.nestedModels}} + {{/allProperties}} +{{! @JsonPOJOBuilder(withPrefix = "") +public static class Builder {}} + } +{{/mustacheModels}} diff --git a/src/main/resources/twilio-java/reader.mustache b/src/main/resources/twilio-java/reader.mustache index 0297987bd..74ae0f226 100644 --- a/src/main/resources/twilio-java/reader.mustache +++ b/src/main/resources/twilio-java/reader.mustache @@ -1,186 +1,25 @@ {{>licenseInfo}} {{#resources}} package com.twilio.rest.{{domainPackage}}.{{apiVersion}}{{namespaceSubPart}}; - -import com.fasterxml.jackson.databind.ObjectMapper; -import com.twilio.constant.EnumConstants; -import com.twilio.converter.Promoter; -import com.twilio.exception.ApiConnectionException; -import com.twilio.converter.PrefixedCollapsibleMap; -import com.twilio.converter.Converter; -import com.twilio.exception.ApiException; -import com.twilio.exception.RestException; -import com.twilio.http.HttpMethod; -import com.twilio.http.Response; -import com.twilio.rest.Domains; -import java.time.LocalDate; -import java.time.ZonedDateTime; -import java.io.IOException; -import java.io.InputStream; -import java.math.BigDecimal; -import java.net.URI; -import java.time.format.DateTimeFormatter; -import com.twilio.converter.DateConverter; - -{{^fullJavaUtil}} -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Objects; -{{/fullJavaUtil}} - -import lombok.ToString; - -{{#apiOperations}} -{{#vendorExtensions.x-is-read-operation}} -import com.twilio.base{{vendorExtensions.x-auth-attributes.x-auth-import-class}}.Page; -import com.twilio.base{{vendorExtensions.x-auth-attributes.x-auth-import-class}}.Reader; -import com.twilio.base{{vendorExtensions.x-auth-attributes.x-auth-import-class}}.ResourceSet; -import com.twilio.http{{vendorExtensions.x-auth-attributes.x-auth-import-class}}.{{vendorExtensions.x-auth-attributes.x-http-class-prefix}}Request; -import com.twilio.http{{vendorExtensions.x-auth-attributes.x-auth-import-class}}.{{vendorExtensions.x-auth-attributes.x-http-class-prefix}}TwilioRestClient; - -public class {{apiName}}Reader extends Reader<{{apiName}}> { -{{#allParams}} - private {{{dataType}}} {{paramName}}; -{{/allParams}} - -{{#vendorExtensions.x-signature-list}} - public {{apiName}}Reader({{#.}}final {{{dataType}}} {{paramName}}{{^-last}}, {{/-last}}{{/.}}){ - {{#.}} - this.{{paramName}} = {{paramName}}; - {{/.}} - } -{{/vendorExtensions.x-signature-list}} - -{{#vendorExtensions.x-non-path-params}} - public {{apiName}}Reader set{{#lambda.titlecase}}{{paramName}}{{/lambda.titlecase}}(final {{{dataType}}} {{paramName}}){ - this.{{paramName}} = {{paramName}}; - return this; - } -{{#isArray}} - public {{apiName}}Reader set{{#lambda.titlecase}}{{paramName}}{{/lambda.titlecase}}(final {{{baseType}}} {{paramName}}){ - return set{{#lambda.titlecase}}{{paramName}}{{/lambda.titlecase}}(Promoter.listOfOne({{paramName}})); - } -{{/isArray}} -{{#vendorExtensions.x-promotions}} -{{#entrySet}} - - public {{apiName}}Reader set{{#lambda.titlecase}}{{paramName}}{{/lambda.titlecase}}(final {{#lambda.titlecase}}{{key}}{{/lambda.titlecase}} {{paramName}}){ - return set{{#lambda.titlecase}}{{paramName}}{{/lambda.titlecase}}({{value}}); - } -{{/entrySet}} -{{/vendorExtensions.x-promotions}} -{{/vendorExtensions.x-non-path-params}} - - @Override - public ResourceSet<{{apiName}}> read(final {{vendorExtensions.x-auth-attributes.x-http-class-prefix}}TwilioRestClient client) { - return new ResourceSet<>(this, client, firstPage(client)); - } - - public Page<{{apiName}}> firstPage(final {{vendorExtensions.x-auth-attributes.x-http-class-prefix}}TwilioRestClient client) { - String path = "{{{path}}}"; - {{#allParams}} - {{#vendorExtensions.x-is-account-sid}} - this.{{paramName}} = this.{{paramName}} == null ? client.getAccountSid() : this.{{paramName}}; - path = path.replace("{"+"{{baseName}}"+"}", this.{{paramName}}.toString()); - {{/vendorExtensions.x-is-account-sid}} - {{/allParams}} - {{#requiredParams}} - path = path.replace("{"+"{{baseName}}"+"}", this.{{paramName}}.toString()); - {{/requiredParams}} - - {{vendorExtensions.x-auth-attributes.x-http-class-prefix}}Request request = new {{vendorExtensions.x-auth-attributes.x-http-class-prefix}}Request( - {{vendorExtensions.x-http-method}}, - Domains.{{#lambda.uppercase}}{{domainName}}{{/lambda.uppercase}}.toString(), - path - ); - - {{#queryParams.0}} - addQueryParams(request); - {{/queryParams.0}} - {{^vendorExtensions.x-is-json}} - request.setContentType(EnumConstants.ContentType.FORM_URLENCODED); - {{/vendorExtensions.x-is-json}} - {{#vendorExtensions.x-is-json}} - request.setContentType(EnumConstants.ContentType.JSON); - {{/vendorExtensions.x-is-json}} - {{#formParams.0}} - addPostParams(request); - {{/formParams.0}} - {{#bodyParams.0}} - addPostParams(request, client); - {{/bodyParams.0}} - {{#headerParams.0}} - addHeaderParams(request); - {{/headerParams.0}} - return pageForRequest(client, request); - } - - private Page<{{apiName}}> pageForRequest(final {{vendorExtensions.x-auth-attributes.x-http-class-prefix}}TwilioRestClient client, final {{vendorExtensions.x-auth-attributes.x-http-class-prefix}}Request request) { - Response response = client.request(request); - - if (response == null) { - throw new ApiConnectionException("{{apiName}} read failed: Unable to connect to server"); - } else if (!{{vendorExtensions.x-auth-attributes.x-http-class-prefix}}TwilioRestClient.SUCCESS.test(response.getStatusCode())) { - RestException restException = RestException.fromJson(response.getStream(), client.getObjectMapper()); - if (restException == null) { - throw new ApiException("Server Error, no content", response.getStatusCode()); - } - throw new ApiException(restException); - } - - return Page.fromJson( - "{{recordKey}}", - response.getContent(), - {{apiName}}.class, - client.getObjectMapper() - ); - } - - @Override - public Page<{{apiName}}> previousPage(final Page<{{apiName}}> page, final {{vendorExtensions.x-auth-attributes.x-http-class-prefix}}TwilioRestClient client) { - {{vendorExtensions.x-auth-attributes.x-http-class-prefix}}Request request = new {{vendorExtensions.x-auth-attributes.x-http-class-prefix}}Request( - {{vendorExtensions.x-http-method}}, - page.getPreviousPageUrl(Domains.{{#lambda.uppercase}}{{domainName}}{{/lambda.uppercase}}.toString()) - ); - return pageForRequest(client, request); - } - - - @Override - public Page<{{apiName}}> nextPage(final Page<{{apiName}}> page, final {{vendorExtensions.x-auth-attributes.x-http-class-prefix}}TwilioRestClient client) { - {{vendorExtensions.x-auth-attributes.x-http-class-prefix}}Request request = new {{vendorExtensions.x-auth-attributes.x-http-class-prefix}}Request( - {{vendorExtensions.x-http-method}}, - page.getNextPageUrl(Domains.{{#lambda.uppercase}}{{domainName}}{{/lambda.uppercase}}.toString()) - ); - return pageForRequest(client, request); - } - - @Override - public Page<{{apiName}}> getPage(final String targetUrl, final {{vendorExtensions.x-auth-attributes.x-http-class-prefix}}TwilioRestClient client) { - {{vendorExtensions.x-auth-attributes.x-http-class-prefix}}Request request = new {{vendorExtensions.x-auth-attributes.x-http-class-prefix}}Request( - HttpMethod.GET, - targetUrl - ); - - return pageForRequest(client, request); - } -{{#vendorExtensions.x-has-form-params}} -{{>postParams}} -{{/vendorExtensions.x-has-form-params}} -{{#vendorExtensions.x-has-header-params}} -{{>headerParams}} -{{/vendorExtensions.x-has-header-params}} -{{#vendorExtensions.x-has-query-params}} - private void addQueryParams(final {{vendorExtensions.x-auth-attributes.x-http-class-prefix}}Request request) { -{{>queryParams}} - if(getPageSize() != null) { - request.addQueryParam("PageSize", Integer.toString(getPageSize())); - } - } -{{/vendorExtensions.x-has-query-params}} +{{>common/imports}} +import com.twilio.base.Page; +import com.twilio.base.ResourceSet; + +{{#operations}} +{{#vendorExtensions.x-list-operation}} +public class {{resourceName}}Reader extends Reader<{{resourceName}}> { + + {{>common/instanceVariables}} + {{>common/constructors}} + {{>reader/setters}} + {{>reader/operationMethod}} +{{#queryParams.0}} + {{>common/addQueryParams}} +{{/queryParams.0}} +{{#headerParams.0}} + {{>common/addHeaderParams}} +{{/headerParams.0}} } -{{/vendorExtensions.x-is-read-operation}} -{{/apiOperations}} -{{/resources}} +{{/vendorExtensions.x-list-operation}} +{{/operations}} +{{/resources}} \ No newline at end of file diff --git a/src/main/resources/twilio-java-modern/reader/operationMethod.mustache b/src/main/resources/twilio-java/reader/operationMethod.mustache similarity index 100% rename from src/main/resources/twilio-java-modern/reader/operationMethod.mustache rename to src/main/resources/twilio-java/reader/operationMethod.mustache diff --git a/src/main/resources/twilio-java-modern/reader/paginationMethods.mustache b/src/main/resources/twilio-java/reader/paginationMethods.mustache similarity index 100% rename from src/main/resources/twilio-java-modern/reader/paginationMethods.mustache rename to src/main/resources/twilio-java/reader/paginationMethods.mustache diff --git a/src/main/resources/twilio-java-modern/reader/setters.mustache b/src/main/resources/twilio-java/reader/setters.mustache similarity index 100% rename from src/main/resources/twilio-java-modern/reader/setters.mustache rename to src/main/resources/twilio-java/reader/setters.mustache diff --git a/src/main/resources/twilio-java-modern/response.mustache b/src/main/resources/twilio-java/response.mustache similarity index 100% rename from src/main/resources/twilio-java-modern/response.mustache rename to src/main/resources/twilio-java/response.mustache diff --git a/src/main/resources/twilio-java-modern/staticMethods.mustache b/src/main/resources/twilio-java/staticMethods.mustache similarity index 100% rename from src/main/resources/twilio-java-modern/staticMethods.mustache rename to src/main/resources/twilio-java/staticMethods.mustache diff --git a/src/main/resources/twilio-java/updater.mustache b/src/main/resources/twilio-java/updater.mustache index d14fd7661..e447ea9f5 100644 --- a/src/main/resources/twilio-java/updater.mustache +++ b/src/main/resources/twilio-java/updater.mustache @@ -1,132 +1,28 @@ {{>licenseInfo}} {{#resources}} package com.twilio.rest.{{domainPackage}}.{{apiVersion}}{{namespaceSubPart}}; - -import com.fasterxml.jackson.databind.ObjectMapper; -import com.twilio.constant.EnumConstants; -import com.twilio.converter.Promoter; -import com.twilio.exception.ApiConnectionException; -import com.twilio.converter.PrefixedCollapsibleMap; -import com.twilio.converter.Converter; -import com.twilio.exception.ApiException; -import com.twilio.exception.RestException; -import com.twilio.http.HttpMethod; -import com.twilio.http.Response; -import com.twilio.rest.Domains; -import java.time.format.DateTimeFormatter; -import com.twilio.converter.DateConverter; - -import java.io.IOException; -import java.io.InputStream; -import java.math.BigDecimal; -import java.net.URI; -import java.time.ZonedDateTime; -import java.time.LocalDate; - -{{^fullJavaUtil}} -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Objects; -{{/fullJavaUtil}} - -import lombok.ToString; - -{{#apiOperations}} -{{#vendorExtensions.x-is-update-operation}} -import com.twilio.base{{vendorExtensions.x-auth-attributes.x-auth-import-class}}.Updater; -import com.twilio.http{{vendorExtensions.x-auth-attributes.x-auth-import-class}}.{{vendorExtensions.x-auth-attributes.x-http-class-prefix}}Request; -import com.twilio.http{{vendorExtensions.x-auth-attributes.x-auth-import-class}}.{{vendorExtensions.x-auth-attributes.x-http-class-prefix}}TwilioRestClient; - - -public class {{apiName}}Updater extends Updater<{{apiName}}>{ -{{#allParams}} - private {{{dataType}}} {{paramName}}; -{{/allParams}} - -{{#vendorExtensions.x-signature-list}} - public {{apiName}}Updater({{#.}}final {{{dataType}}} {{paramName}}{{^-last}}, {{/-last}}{{/.}}){ - {{#.}} - this.{{paramName}} = {{paramName}}; - {{/.}} +{{>common/imports}} + +{{#operations}} +{{#vendorExtensions.x-update-operation}} + public class {{resourceName}}Updater extends Updater<{{resourceName}}> { + {{>common/instanceVariables}} + {{>common/constructors}} + {{>updater/setters}} + {{>updater/operationMethod}} + {{#queryParams.0}} + {{>common/addQueryParams}} + {{/queryParams.0}} + {{#formParams.0}} + {{>common/addPostParams}} + {{/formParams.0}} + {{#headerParams.0}} + {{>common/addHeaderParams}} + {{/headerParams.0}} + {{#bodyParams.0}} + {{>common/addPostParamsJson}} + {{/bodyParams.0}} } -{{/vendorExtensions.x-signature-list}} - -{{#vendorExtensions.x-non-path-params}} - public {{apiName}}Updater set{{#lambda.titlecase}}{{paramName}}{{/lambda.titlecase}}(final {{{dataType}}} {{paramName}}){ - this.{{paramName}} = {{paramName}}; - return this; - } -{{#isArray}} - public {{apiName}}Updater set{{#lambda.titlecase}}{{paramName}}{{/lambda.titlecase}}(final {{{baseType}}} {{paramName}}){ - return set{{#lambda.titlecase}}{{paramName}}{{/lambda.titlecase}}(Promoter.listOfOne({{paramName}})); - } -{{/isArray}} -{{#vendorExtensions.x-promotions}} -{{#entrySet}} - - public {{apiName}}Updater set{{#lambda.titlecase}}{{paramName}}{{/lambda.titlecase}}(final {{#lambda.titlecase}}{{key}}{{/lambda.titlecase}} {{paramName}}){ - return set{{#lambda.titlecase}}{{paramName}}{{/lambda.titlecase}}({{value}}); - } -{{/entrySet}} -{{/vendorExtensions.x-promotions}} -{{/vendorExtensions.x-non-path-params}} - - @Override - public {{apiName}} update(final {{vendorExtensions.x-auth-attributes.x-http-class-prefix}}TwilioRestClient client){ -{{>generate_uri}} - {{vendorExtensions.x-auth-attributes.x-http-class-prefix}}Request request = new {{vendorExtensions.x-auth-attributes.x-http-class-prefix}}Request( - {{vendorExtensions.x-http-method}}, - Domains.{{#lambda.uppercase}}{{domainName}}{{/lambda.uppercase}}.toString(), - path - ); - {{#queryParams.0}} - addQueryParams(request); - {{/queryParams.0}} - {{^vendorExtensions.x-is-json}} - request.setContentType(EnumConstants.ContentType.FORM_URLENCODED); - {{/vendorExtensions.x-is-json}} - {{#vendorExtensions.x-is-json}} - request.setContentType(EnumConstants.ContentType.JSON); - {{/vendorExtensions.x-is-json}} - {{#formParams.0}} - addPostParams(request); - {{/formParams.0}} - {{#bodyParams.0}} - addPostParams(request, client); - {{/bodyParams.0}} - {{#headerParams.0}} - addHeaderParams(request); - {{/headerParams.0}} - Response response = client.request(request); - if (response == null) { - throw new ApiConnectionException("{{apiName}} update failed: Unable to connect to server"); - } else if (!{{vendorExtensions.x-auth-attributes.x-http-class-prefix}}TwilioRestClient.SUCCESS.test(response.getStatusCode())) { - RestException restException = RestException.fromJson(response.getStream(), client.getObjectMapper()); - if (restException == null) { - throw new ApiException("Server Error, no content", response.getStatusCode()); - } - throw new ApiException(restException); - } - - return {{apiName}}.fromJson(response.getStream(), client.getObjectMapper()); - } - -{{#vendorExtensions.x-has-form-params}} -{{>postParams}} -{{/vendorExtensions.x-has-form-params}} -{{#vendorExtensions.x-has-body-params}} -{{>postParams_body}} -{{/vendorExtensions.x-has-body-params}} -{{#vendorExtensions.x-has-header-params}} -{{>headerParams}} -{{/vendorExtensions.x-has-header-params}} -{{#vendorExtensions.x-has-query-params}} - private void addQueryParams(final {{vendorExtensions.x-auth-attributes.x-http-class-prefix}}Request request) { -{{>queryParams}} } -{{/vendorExtensions.x-has-query-params}} -} -{{/vendorExtensions.x-is-update-operation}} -{{/apiOperations}} -{{/resources}} +{{/vendorExtensions.x-update-operation}} +{{/operations}} +{{/resources}} \ No newline at end of file diff --git a/src/main/resources/twilio-java-modern/updater/operationMethod.mustache b/src/main/resources/twilio-java/updater/operationMethod.mustache similarity index 100% rename from src/main/resources/twilio-java-modern/updater/operationMethod.mustache rename to src/main/resources/twilio-java/updater/operationMethod.mustache diff --git a/src/main/resources/twilio-java-modern/updater/setters.mustache b/src/main/resources/twilio-java/updater/setters.mustache similarity index 100% rename from src/main/resources/twilio-java-modern/updater/setters.mustache rename to src/main/resources/twilio-java/updater/setters.mustache diff --git a/src/test/java/com/twilio/oai/TwilioGeneratorTest.java b/src/test/java/com/twilio/oai/TwilioGeneratorTest.java index 02acf94b8..b20b9fe44 100644 --- a/src/test/java/com/twilio/oai/TwilioGeneratorTest.java +++ b/src/test/java/com/twilio/oai/TwilioGeneratorTest.java @@ -28,7 +28,7 @@ public class TwilioGeneratorTest { @Parameterized.Parameters public static Collection generators() { - return Arrays.asList(Generator.TWILIO_JAVA_MODERN); + return Arrays.asList(Generator.TWILIO_JAVA); } private final Generator generator; diff --git a/src/test/resources/config/test_toggles.json b/src/test/resources/config/test_toggles.json index e0c3ec25d..89aaf1eea 100644 --- a/src/test/resources/config/test_toggles.json +++ b/src/test/resources/config/test_toggles.json @@ -1,5 +1,5 @@ { "json_ingress": { - "twilio-java": true + "twilio-java-legacy": true } } From 053a83d01963c284154e9bed11684c86c2b601a0 Mon Sep 17 00:00:00 2001 From: sbansla Date: Fri, 12 Sep 2025 17:24:16 +0530 Subject: [PATCH 22/38] keeping java tests only --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index fc7470505..611128b4a 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -14,7 +14,7 @@ jobs: strategy: fail-fast: false matrix: - language: [ 'csharp', 'go', 'java', 'node', 'php', 'python', 'ruby' ] + language: ['java' ] runs-on: ubuntu-latest timeout-minutes: 20 env: From 065c7e785e3eb04c4d97811a9baa679fb065da58 Mon Sep 17 00:00:00 2001 From: sbansla Date: Tue, 16 Sep 2025 17:14:15 +0530 Subject: [PATCH 23/38] disabled python generator and moved spec out of scripts --- scripts/generate.sh | 10 +- .../java/twilio_customfeature_v1.yaml | 2 + specs_test/test_spec/twilio_auth_v1.yaml | 10 + .../test_spec/twilio_datamodels_v1.yaml | 212 ++ specs_test/test_spec/twilio_enum_v1.yaml | 106 + specs_test/test_spec/twilio_format_v1.yaml | 0 .../test_spec/twilio_nestedmodel_v1.yaml | 2 + specs_test/test_spec/twilio_oneOf_v1.yaml | 110 + .../test_spec/twilio_parameters_v1.yaml | 78 + specs_test/test_spec/twilio_request_v1.yaml | 101 + specs_test/test_spec/twilio_response_v1.yaml | 3 + specs_test/test_spec/twilio_testenum_v1.yaml | 134 + specs_test/twilio_iam_organizations.yaml | 1392 ++++++++++ specs_test/twilio_iam_organizations_v1.yaml | 572 +++++ .../twilio_iam_organizations_versionless.yaml | 2233 +++++++++++++++++ .../com/twilio/oai/TwilioPythonGenerator.java | 15 +- .../body/InlineBodyListEnumProcessor.java | 6 +- .../body/ReusableBodyListEnumProcessor.java | 6 +- .../param/InlineListParamEnumProcessor.java | 6 +- .../param/ReusableListParamEnumProcessor.java | 6 +- .../property/InlineListPropEnumProcessor.java | 6 +- .../ReusableListPropEnumProcessor.java | 6 +- .../com/twilio/oai/TwilioGeneratorTest.java | 2 +- 23 files changed, 4976 insertions(+), 42 deletions(-) create mode 100644 specs_test/test_spec/java/twilio_customfeature_v1.yaml create mode 100644 specs_test/test_spec/twilio_auth_v1.yaml create mode 100644 specs_test/test_spec/twilio_datamodels_v1.yaml create mode 100644 specs_test/test_spec/twilio_enum_v1.yaml create mode 100644 specs_test/test_spec/twilio_format_v1.yaml create mode 100644 specs_test/test_spec/twilio_nestedmodel_v1.yaml create mode 100644 specs_test/test_spec/twilio_oneOf_v1.yaml create mode 100644 specs_test/test_spec/twilio_parameters_v1.yaml create mode 100644 specs_test/test_spec/twilio_request_v1.yaml create mode 100644 specs_test/test_spec/twilio_response_v1.yaml create mode 100644 specs_test/test_spec/twilio_testenum_v1.yaml create mode 100644 specs_test/twilio_iam_organizations.yaml create mode 100644 specs_test/twilio_iam_organizations_v1.yaml create mode 100644 specs_test/twilio_iam_organizations_versionless.yaml diff --git a/scripts/generate.sh b/scripts/generate.sh index e03b520f5..dca485392 100644 --- a/scripts/generate.sh +++ b/scripts/generate.sh @@ -82,11 +82,11 @@ if should-generate php; then generate twilio-php fi -if should-generate python; then - OUT_DIR=examples/python/twilio/rest - generate twilio-python -DskipFormModel=false - docker-run examples/python/Dockerfile-prettier -fi +#if should-generate python; then +# OUT_DIR=examples/python/twilio/rest +# generate twilio-python -DskipFormModel=false +# docker-run examples/python/Dockerfile-prettier +#fi if should-generate ruby; then OUT_DIR=examples/ruby/lib/twilio-ruby/rest diff --git a/specs_test/test_spec/java/twilio_customfeature_v1.yaml b/specs_test/test_spec/java/twilio_customfeature_v1.yaml new file mode 100644 index 000000000..4d479ff56 --- /dev/null +++ b/specs_test/test_spec/java/twilio_customfeature_v1.yaml @@ -0,0 +1,2 @@ +# This spec is twilio-java specific and Tests following +# 1. It tests custom feature for twilio-java examples: constructors, DateInequality \ No newline at end of file diff --git a/specs_test/test_spec/twilio_auth_v1.yaml b/specs_test/test_spec/twilio_auth_v1.yaml new file mode 100644 index 000000000..a6d5e7b9d --- /dev/null +++ b/specs_test/test_spec/twilio_auth_v1.yaml @@ -0,0 +1,10 @@ +components: + securitySchemes: + oAuth2ClientCredentials: + type: oauth2 + flows: + clientCredentials: + tokenUrl: https://preview-iam.twilio.com/v1/token + scopes: {} +paths: + \ No newline at end of file diff --git a/specs_test/test_spec/twilio_datamodels_v1.yaml b/specs_test/test_spec/twilio_datamodels_v1.yaml new file mode 100644 index 000000000..57eb06230 --- /dev/null +++ b/specs_test/test_spec/twilio_datamodels_v1.yaml @@ -0,0 +1,212 @@ +openapi: 3.1.0 +info: + title: OneOf API Examples + version: 1.0.0 +servers: + - url: https://api.twilio.com + +paths: + /v1/directOneOf: + post: + operationId: CreateDirectOneOf + summary: Direct oneOf in request body + requestBody: + required: true + content: + application/json: + schema: + oneOf: + - $ref: '#/components/schemas/Cat' + - $ref: '#/components/schemas/Dog' + responses: + '200': + description: Success + +# /v1/nestedOneOf: +# post: +# operationId: CreateNestedOneOf +# summary: Nested oneOf in request body +# requestBody: +# required: true +# content: +# application/json: +# schema: +# type: object +# properties: +# pet: +# oneOf: +# - $ref: '#/components/schemas/Cat' +# - $ref: '#/components/schemas/Dog' +# owner: +# type: string +# responses: +# '200': +# description: Success +# +# /v1/multipleNestedOneOf: +# post: +# operationId: CreateMultipleDirectOneOf +# summary: Multiple nested oneOf in request body +# requestBody: +# required: true +# content: +# application/json: +# schema: +# type: object +# properties: +# petDetails: +# type: object +# properties: +# pet: +# oneOf: +# - $ref: '#/components/schemas/Cat' +# - $ref: '#/components/schemas/Dog' +# additionalInfo: +# oneOf: +# - $ref: '#/components/schemas/One' +# - $ref: '#/components/schemas/Two' +# owner: +# type: string +# responses: +# '200': +# description: Success +# +# /v1/arrayOfOneOf: +# post: +# operationId: CreateArrayOfOneOf +# summary: Array of oneOf in request body +# requestBody: +# required: true +# content: +# application/json: +# schema: +# type: object +# properties: +# pets: +# type: array +# items: +# oneOf: +# - $ref: '#/components/schemas/Cat' +# - $ref: '#/components/schemas/Dog' +# responses: +# '200': +# description: Success +# /v1/parallelOneOfAndObject: +# post: +# operationId: CreateParallelOneOfAndObject +# summary: OneOf and normal object in parallel +# requestBody: +# required: true +# content: +# application/json: +# schema: +# type: object +# properties: +# pet: +# oneOf: +# - $ref: '#/components/schemas/Cat' +# - $ref: '#/components/schemas/Dog' +# owner: +# type: object +# properties: +# name: +# type: string +# age: +# type: integer +# responses: +# '200': +# description: Success +# +# /v1/oneOfWithAdditionalProperties: +# post: +# operationId: CreateOneOfWithAdditionalProperties +# summary: OneOf with additional properties +# requestBody: +# required: true +# content: +# application/json: +# schema: +# type: object +# properties: +# pet: +# oneOf: +# - $ref: '#/components/schemas/Cat' +# - $ref: '#/components/schemas/Dog' +# metadata: +# type: object +# additionalProperties: +# type: string +# responses: +# '200': +# description: Success +# +# /v1/oneOfWithRequiredFields: +# post: +# operationId: CreateOneOfWithRequiredFields +# summary: OneOf with required fields in parallel +# requestBody: +# required: true +# content: +# application/json: +# schema: +# type: object +# required: +# - pet +# - owner +# properties: +# pet: +# oneOf: +# - $ref: '#/components/schemas/Cat' +# - $ref: '#/components/schemas/Dog' +# owner: +# type: object +# properties: +# name: +# type: string +# contact: +# type: string +# responses: +# '200': +# description: Success + +components: + schemas: + Cat: + type: object + properties: + type: + type: string + enum: [cat] + name: + type: string + huntingSkill: + type: string + enum: [clueless, lazy, adventurous, aggressive] + + Dog: + type: object + properties: + type: + type: string + enum: [dog] + name: + type: string + packSize: + type: integer + minimum: 0 + + One: + type: object + properties: + param1: + type: string + param2: + type: string + + Two: + type: object + properties: + object1: + type: string + object2: + type: string \ No newline at end of file diff --git a/specs_test/test_spec/twilio_enum_v1.yaml b/specs_test/test_spec/twilio_enum_v1.yaml new file mode 100644 index 000000000..2de5aaa20 --- /dev/null +++ b/specs_test/test_spec/twilio_enum_v1.yaml @@ -0,0 +1,106 @@ +info: + contact: + email: support@twilio.com + name: Twilio Support + url: https://support.twilio.com + description: This is the public Twilio REST API. + license: + name: Apache 2.0 + url: https://www.apache.org/licenses/LICENSE-2.0.html + termsOfService: https://www.twilio.com/legal/tos + title: Twilio - CONTENT + version: 1.11.0 +openapi: 3.0.1 + +paths: + /v1/content: + servers: + - url: https://enum.twilio.com + get: + summary: Retrieve items with various filter options + parameters: + # PARAMETER_SINGLE + - name: singleParam + in: query + description: A single enum value as a query parameter + required: false + schema: + type: string + enum: + - asc + - desc + example: asc + + # PARAMETER_ARRAY + - name: arrayParam + in: query + description: Order items using an array of enums + required: false + schema: + type: array + items: + type: string + enum: + - asc + - desc + example: [asc] + + # PARAMETER_ARRAY + - name: arrayParamRef + in: query + required: false + description: An array parameter referencing a reusable schema + schema: + type: array + items: + $ref: '#/components/schemas/singleReusable' + + - name: singleParamRef + in: header + schema: + $ref: '#/components/schemas/singleReusable' + + responses: + '200': + description: A list of items + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/Item' + +components: + schemas: + Item: + type: object + properties: + # PROPERTY_SINGLE + singleProperty: + type: string + enum: [available, pending, sold] + description: A single enum value as a property in a schema + example: available + + # PROPERTY_ARRAY + arrayProperty: + type: array + items: + type: string + enum: [new, sale, featured] + description: An array of enum values in a schema property + example: [new, featured] + + # REUSABLE_ARRAY + arrayReusable: + type: array + items: + $ref: '#/components/schemas/singleReusable' + description: An array of reusable enum defined in components + example: [electronics, clothing] + + # REUSABLE_SINGLE + singleReusable: + type: string + enum: [electronics, furniture, clothing] + description: A reusable single-value enum defined in components \ No newline at end of file diff --git a/specs_test/test_spec/twilio_format_v1.yaml b/specs_test/test_spec/twilio_format_v1.yaml new file mode 100644 index 000000000..e69de29bb diff --git a/specs_test/test_spec/twilio_nestedmodel_v1.yaml b/specs_test/test_spec/twilio_nestedmodel_v1.yaml new file mode 100644 index 000000000..940719838 --- /dev/null +++ b/specs_test/test_spec/twilio_nestedmodel_v1.yaml @@ -0,0 +1,2 @@ +# This spec tests followings +# 1. Nested model in request body and component schema \ No newline at end of file diff --git a/specs_test/test_spec/twilio_oneOf_v1.yaml b/specs_test/test_spec/twilio_oneOf_v1.yaml new file mode 100644 index 000000000..831bf8a24 --- /dev/null +++ b/specs_test/test_spec/twilio_oneOf_v1.yaml @@ -0,0 +1,110 @@ +openapi: 3.1.0 +info: + title: Number Pool Service + description: |- + This service is an entry point for all Number Pool CRUD requests. + version: 1.0.0 + contact: + name: 'Number Pool Service' + url: 'https://wiki.hq.twilio.com/display/MSG/Messaging+Services' + license: + name: Apache 2.0 + url: https://www.apache.org/licenses/LICENSE-2.0.html +servers: + - url: https://oneOf.twilio.com +paths: + /v1/pets: + post: + operationId: CreatePet + summary: Add a pet (cat or dog) + requestBody: + required: true + content: + application/json: + schema: +# properties: +# RecordingStatusCallback: +# format: uri +# type: string +# RecordingStatusCallbackEvent: +# items: +# type: string +# type: array + $ref: '#/components/schemas/Cat' +# title: MyPet +# oneOf: +# - $ref: '#/components/schemas/Cat' +# - $ref: '#/components/schemas/Dog' + responses: + '200': + description: Returns the created pet (cat or dog) + content: + application/json: + schema: + $ref: '#/components/schemas/Cat' +# allOf: +# - type: object +# properties: +# account_sid: +# type: string +# nullable: true +# - title: MyPet_Response +# $ref: '#/components/schemas/MyPet_Response' +# - oneOf: +# - $ref: '#/components/schemas/Cat' +# - $ref: '#/components/schemas/Dog' + +components: + schemas: + MyPet_Response: + type: object + properties: + cat: + $ref: '#/components/schemas/Cat' + dog: + $ref: '#/components/schemas/Dog' + Cat: + allOf: + - type: object + properties: + account_sid: + type: string + - oneOf: + - $ref: '#/components/schemas/One' + - $ref: '#/components/schemas/Two' +# type: +# type: string +# enum: [cat] +# name: +# type: string +# huntingSkill: +# type: string +# enum: [clueless, lazy, adventurous, aggressive] + + Dog: + type: object + properties: + type: + type: string + enum: [dog] + name: + type: string + packSize: + type: integer + minimum: 0 + One: + type: object + properties: + param1: + type: string + param2: + type: string + dog: + $ref: '#/components/schemas/Dog' + Two: + type: object + properties: + object1: + type: string + object2: + type: string diff --git a/specs_test/test_spec/twilio_parameters_v1.yaml b/specs_test/test_spec/twilio_parameters_v1.yaml new file mode 100644 index 000000000..77ce3ab33 --- /dev/null +++ b/specs_test/test_spec/twilio_parameters_v1.yaml @@ -0,0 +1,78 @@ +# This spec tests followings +# 1. All types of parameters(query, header, path) + +info: + contact: + email: support@twilio.com + name: Twilio Support + url: https://support.twilio.com + description: This is the public Twilio REST API. + license: + name: Apache 2.0 + url: https://www.apache.org/licenses/LICENSE-2.0.html + termsOfService: https://www.twilio.com/legal/tos + title: Twilio - PARAMETERS + version: 1.11.0 +openapi: 3.0.1 + +paths: + /v1/parameter/{id}: + servers: + - url: https://testparameter.twilio.com + post: + operationId: CreateParameter + parameters: + - name: id + in: path + required: true + description: The unique identifier for the enum item + schema: + type: string + - name: queryParamDoubleRequired + in: query + description: A single enum value as a query parameter + required: required + schema: + type: string + - name: queryParamBoolean + in: query + description: A single enum value as a query parameter + required: false + schema: + type: boolean + - name: queryParamString + in: query + description: A single enum value as a query parameter + required: false + schema: + type: string + - name: queryParamInteger + in: query + description: A single enum value as a query parameter + required: false + schema: + type: integer + + + requestBody: + content: + application/x-www-form-urlencoded: + schema: + type: object + title: CreateParameterRequest + properties: + To: + type: string + format: phone-number + responses: + '201': + description: Parameter created successfully + content: + application/json: + schema: + type: object + properties: + id: + type: string + status: + type: string diff --git a/specs_test/test_spec/twilio_request_v1.yaml b/specs_test/test_spec/twilio_request_v1.yaml new file mode 100644 index 000000000..cf07b84a3 --- /dev/null +++ b/specs_test/test_spec/twilio_request_v1.yaml @@ -0,0 +1,101 @@ +# This spec tests followings +# 1. All types of request body(urlencoded, json) +# 2. Tests pagination for both type of request body. + +info: + contact: + email: support@twilio.com + name: Twilio Support + url: https://support.twilio.com + description: This is the public Twilio REST API. + license: + name: Apache 2.0 + url: https://www.apache.org/licenses/LICENSE-2.0.html + termsOfService: https://www.twilio.com/legal/tos + title: Twilio - REQUEST BODY TEST + version: 1.11.0 +openapi: 3.0.1 + +components: + schemas: + UpdateRequestBodyRequest: + type: object + properties: + username: + type: string + password: + type: string +paths: + /v1/requestbody: + servers: + - url: https://testparameter.twilio.com + post: + operationId: CreateRequestBody + parameters: + - name: queryParamStringRequired + in: query + description: A single enum value as a query parameter + required: required + schema: + type: string + requestBody: + content: + application/x-www-form-urlencoded: + schema: + # 1. Inline request body + type: object + title: CreateRequestBodyRequest + properties: + username: + type: string + password: + type: string + + responses: + '201': + description: Parameter created successfully + content: + application/json: + schema: + type: object + properties: + id: + type: string + status: + type: string + + /v1/requestbody/{id}: + servers: + - url: https://testparameter.twilio.com + post: + operationId: UpdateRequestBody + parameters: + - name: id + in: path + required: true + schema: + type: string + - name: queryParamStringRequired + in: query + required: required + schema: + type: string + requestBody: + content: + application/x-www-form-urlencoded: + schema: + # 2. Reusable request body + $ref: '#/components/schemas/UpdateRequestBodyRequest' + + responses: + '201': + description: Parameter created successfully + content: + application/json: + schema: + type: object + properties: + id: + type: string + status: + type: string \ No newline at end of file diff --git a/specs_test/test_spec/twilio_response_v1.yaml b/specs_test/test_spec/twilio_response_v1.yaml new file mode 100644 index 000000000..3188edba5 --- /dev/null +++ b/specs_test/test_spec/twilio_response_v1.yaml @@ -0,0 +1,3 @@ +# This spec tests followings +# 1. All types of response body(json) +# 2. Tests paginated response. \ No newline at end of file diff --git a/specs_test/test_spec/twilio_testenum_v1.yaml b/specs_test/test_spec/twilio_testenum_v1.yaml new file mode 100644 index 000000000..470aed46a --- /dev/null +++ b/specs_test/test_spec/twilio_testenum_v1.yaml @@ -0,0 +1,134 @@ +# This spec Tests following +# 1. All types of enums, There are 8 types of Enum to be tested +# 2. Enums as a query, header parameter +info: + contact: + email: support@twilio.com + name: Twilio Support + url: https://support.twilio.com + description: This is the public Twilio REST API. + license: + name: Apache 2.0 + url: https://www.apache.org/licenses/LICENSE-2.0.html + termsOfService: https://www.twilio.com/legal/tos + title: Twilio - CONTENT + version: 1.11.0 +openapi: 3.0.1 + +paths: + /v1/enum/{id}: + servers: + - url: https://testenum.twilio.com + get: + operationId: FetchAbc + summary: Retrieve items with various filter options + parameters: + - name: id + in: path + required: true + description: The unique identifier for the enum item + schema: + type: string + # 1. PARAMETER_SINGLE + - name: singleParam + in: query + description: A single enum value as a query parameter + required: false + schema: + type: string + enum: + - asc + - desc + example: asc + + # 2. PARAMETER_ARRAY + - name: arrayParam + in: query + description: Order items using an array of enums + required: false + schema: + type: array + items: + type: string + enum: + - asc + - desc + example: [asc] + + # 3. PARAMETER_ARRAY Referencing Reusable Schema + - name: arrayParamRef + in: query + required: false + description: An array parameter referencing a reusable schema + schema: + type: array + items: + $ref: '#/components/schemas/singleReusable' + + # 4. PARAMETER_REUSABLE_SINGLE + - name: singleParamRef + in: header + schema: + $ref: '#/components/schemas/singleReusable' + + responses: + '200': + description: A list of items + content: + application/json: + schema: + $ref: '#/components/schemas/Item' + +components: + schemas: + Item: + type: object + properties: + # 5. PROPERTY_SINGLE + singleProperty: + type: string + enum: [available, pending, sold] + description: A single enum value as a property in a schema + example: available + + # 6. PROPERTY_ARRAY + arrayProperty: + type: array + items: + type: string + enum: [new, sale, featured] + description: An array of enum values in a schema property + example: [new, featured] + + # 7. REUSABLE_ARRAY + arrayReusable: + type: array + items: + $ref: '#/components/schemas/singleReusable' + description: An array of reusable enum defined in components + example: [electronics, clothing] + status: + $ref: '#/components/schemas/message_enum_status' + + # 8. REUSABLE_SINGLE + singleReusable: + type: string + enum: [electronics, furniture, clothing] + description: A reusable single-value enum defined in components + message_enum_status: + type: string + enum: + - queued + - sending + - sent + - failed + - delivered + - undelivered + - receiving + - received + - accepted + - scheduled + - read + - partially_delivered + - canceled + description: test \ No newline at end of file diff --git a/specs_test/twilio_iam_organizations.yaml b/specs_test/twilio_iam_organizations.yaml new file mode 100644 index 000000000..a13e4e0e7 --- /dev/null +++ b/specs_test/twilio_iam_organizations.yaml @@ -0,0 +1,1392 @@ +openapi: 3.0.1 +security: + - oAuth2ClientCredentials: [] +info: + title: Organization Public API + contact: + name: Twilio Support + url: https://support.twilio.com + email: support@twilio.com + license: + name: Apache 2.0 + url: https://www.apache.org/licenses/LICENSE-2.0.html + version: 1.0.0 +tags: + - name: SCIM + description: SCIM 2.0 User endpoints + - name: OrganizationAccount + description: Organization Account operations + - name: RoleAssignments + description: Role assignment operations + - name: OauthV1Authorize + - name: OauthV1Token +paths: + /Organizations/{organizationSid}/scim/Users: + servers: + - url: https://preview-iam.twilio.com + get: + tags: + - SCIM + summary: List SCIM Users + operationId: ListOrganizationUsers + parameters: + - name: organizationSid + in: path + required: true + schema: + pattern: OR[0-9a-f]{32} + type: string + format: OrganizationSid + example: OR33f4f3aa6fffe840d000f8ef22e883db + - name: filter + in: query + schema: + type: string + responses: + '200': + description: List of users + content: + application/scim+json: + schema: + $ref: '#/components/schemas/ScimUserPage' + headers: + Access-Control-Allow-Origin: + description: Specify the origin(s) allowed to access the resource + schema: + type: string + example: '*' + Access-Control-Allow-Methods: + description: Specify the HTTP methods allowed when accessing the resource + schema: + type: string + example: POST, OPTIONS + Access-Control-Allow-Headers: + description: Specify the headers allowed when accessing the resource + schema: + type: string + example: Content-Type, Authorization + Access-Control-Allow-Credentials: + description: Indicates whether the browser should include credentials + schema: + type: boolean + Access-Control-Expose-Headers: + description: Headers exposed to the client + schema: + type: string + example: X-Custom-Header1, X-Custom-Header2 + '400': + description: Bad request or business rules violation + content: + application/scim+json: + schema: + $ref: '#/components/schemas/ScimError' + headers: + Access-Control-Allow-Origin: + description: Specify the origin(s) allowed to access the resource + schema: + type: string + example: '*' + Access-Control-Allow-Methods: + description: Specify the HTTP methods allowed when accessing the resource + schema: + type: string + example: POST, OPTIONS + Access-Control-Allow-Headers: + description: Specify the headers allowed when accessing the resource + schema: + type: string + example: Content-Type, Authorization + Access-Control-Allow-Credentials: + description: Indicates whether the browser should include credentials + schema: + type: boolean + Access-Control-Expose-Headers: + description: Headers exposed to the client + schema: + type: string + example: X-Custom-Header1, X-Custom-Header2 + '401': + description: Unauthorized + content: + application/scim+json: + schema: + $ref: '#/components/schemas/ScimError' + headers: + Access-Control-Allow-Origin: + description: Specify the origin(s) allowed to access the resource + schema: + type: string + example: '*' + Access-Control-Allow-Methods: + description: Specify the HTTP methods allowed when accessing the resource + schema: + type: string + example: POST, OPTIONS + Access-Control-Allow-Headers: + description: Specify the headers allowed when accessing the resource + schema: + type: string + example: Content-Type, Authorization + Access-Control-Allow-Credentials: + description: Indicates whether the browser should include credentials + schema: + type: boolean + Access-Control-Expose-Headers: + description: Headers exposed to the client + schema: + type: string + example: X-Custom-Header1, X-Custom-Header2 + '403': + description: Forbidden + content: + application/scim+json: + schema: + $ref: '#/components/schemas/ScimError' + headers: + Access-Control-Allow-Origin: + description: Specify the origin(s) allowed to access the resource + schema: + type: string + example: '*' + Access-Control-Allow-Methods: + description: Specify the HTTP methods allowed when accessing the resource + schema: + type: string + example: POST, OPTIONS + Access-Control-Allow-Headers: + description: Specify the headers allowed when accessing the resource + schema: + type: string + example: Content-Type, Authorization + Access-Control-Allow-Credentials: + description: Indicates whether the browser should include credentials + schema: + type: boolean + Access-Control-Expose-Headers: + description: Headers exposed to the client + schema: + type: string + example: X-Custom-Header1, X-Custom-Header2 + '429': + description: Too many requests + content: + application/scim+json: + schema: + $ref: '#/components/schemas/ScimError' + headers: + Access-Control-Allow-Origin: + description: Specify the origin(s) allowed to access the resource + schema: + type: string + example: '*' + Access-Control-Allow-Methods: + description: Specify the HTTP methods allowed when accessing the resource + schema: + type: string + example: POST, OPTIONS + Access-Control-Allow-Headers: + description: Specify the headers allowed when accessing the resource + schema: + type: string + example: Content-Type, Authorization + Access-Control-Allow-Credentials: + description: Indicates whether the browser should include credentials + schema: + type: boolean + Access-Control-Expose-Headers: + description: Headers exposed to the client + schema: + type: string + example: X-Custom-Header1, X-Custom-Header2 + post: + tags: + - SCIM + summary: Create SCIM User + operationId: CreateOrganizationUser + parameters: + - name: organizationSid + in: path + required: true + schema: + pattern: OR[0-9a-f]{32} + type: string + format: OrganizationSid + example: ORceef74a747c1ae8d837aafb5a31e475f + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/ScimUser' + application/scim+json: + schema: + $ref: '#/components/schemas/ScimUser' + required: true + responses: + '201': + description: Created User + content: + application/scim+json: + schema: + $ref: '#/components/schemas/ScimUser' + headers: + Access-Control-Allow-Origin: + description: Specify the origin(s) allowed to access the resource + schema: + type: string + example: '*' + Access-Control-Allow-Methods: + description: Specify the HTTP methods allowed when accessing the resource + schema: + type: string + example: POST, OPTIONS + Access-Control-Allow-Headers: + description: Specify the headers allowed when accessing the resource + schema: + type: string + example: Content-Type, Authorization + Access-Control-Allow-Credentials: + description: Indicates whether the browser should include credentials + schema: + type: boolean + Access-Control-Expose-Headers: + description: Headers exposed to the client + schema: + type: string + example: X-Custom-Header1, X-Custom-Header2 + '400': + description: Bad request or business rules violation + content: + application/scim+json: + schema: + $ref: '#/components/schemas/ScimError' + headers: + Access-Control-Allow-Origin: + description: Specify the origin(s) allowed to access the resource + schema: + type: string + example: '*' + Access-Control-Allow-Methods: + description: Specify the HTTP methods allowed when accessing the resource + schema: + type: string + example: POST, OPTIONS + Access-Control-Allow-Headers: + description: Specify the headers allowed when accessing the resource + schema: + type: string + example: Content-Type, Authorization + Access-Control-Allow-Credentials: + description: Indicates whether the browser should include credentials + schema: + type: boolean + Access-Control-Expose-Headers: + description: Headers exposed to the client + schema: + type: string + example: X-Custom-Header1, X-Custom-Header2 + '401': + description: Unauthorized + content: + application/scim+json: + schema: + $ref: '#/components/schemas/ScimError' + headers: + Access-Control-Allow-Origin: + description: Specify the origin(s) allowed to access the resource + schema: + type: string + example: '*' + Access-Control-Allow-Methods: + description: Specify the HTTP methods allowed when accessing the resource + schema: + type: string + example: POST, OPTIONS + Access-Control-Allow-Headers: + description: Specify the headers allowed when accessing the resource + schema: + type: string + example: Content-Type, Authorization + Access-Control-Allow-Credentials: + description: Indicates whether the browser should include credentials + schema: + type: boolean + Access-Control-Expose-Headers: + description: Headers exposed to the client + schema: + type: string + example: X-Custom-Header1, X-Custom-Header2 + '403': + description: Forbidden + content: + application/scim+json: + schema: + $ref: '#/components/schemas/ScimError' + headers: + Access-Control-Allow-Origin: + description: Specify the origin(s) allowed to access the resource + schema: + type: string + example: '*' + Access-Control-Allow-Methods: + description: Specify the HTTP methods allowed when accessing the resource + schema: + type: string + example: POST, OPTIONS + Access-Control-Allow-Headers: + description: Specify the headers allowed when accessing the resource + schema: + type: string + example: Content-Type, Authorization + Access-Control-Allow-Credentials: + description: Indicates whether the browser should include credentials + schema: + type: boolean + Access-Control-Expose-Headers: + description: Headers exposed to the client + schema: + type: string + example: X-Custom-Header1, X-Custom-Header2 + '404': + description: Not found + content: + application/scim+json: + schema: + $ref: '#/components/schemas/ScimError' + headers: + Access-Control-Allow-Origin: + description: Specify the origin(s) allowed to access the resource + schema: + type: string + example: '*' + Access-Control-Allow-Methods: + description: Specify the HTTP methods allowed when accessing the resource + schema: + type: string + example: POST, OPTIONS + Access-Control-Allow-Headers: + description: Specify the headers allowed when accessing the resource + schema: + type: string + example: Content-Type, Authorization + Access-Control-Allow-Credentials: + description: Indicates whether the browser should include credentials + schema: + type: boolean + Access-Control-Expose-Headers: + description: Headers exposed to the client + schema: + type: string + example: X-Custom-Header1, X-Custom-Header2 + '429': + description: Too many requests + content: + application/scim+json: + schema: + $ref: '#/components/schemas/ScimError' + headers: + Access-Control-Allow-Origin: + description: Specify the origin(s) allowed to access the resource + schema: + type: string + example: '*' + Access-Control-Allow-Methods: + description: Specify the HTTP methods allowed when accessing the resource + schema: + type: string + example: POST, OPTIONS + Access-Control-Allow-Headers: + description: Specify the headers allowed when accessing the resource + schema: + type: string + example: Content-Type, Authorization + Access-Control-Allow-Credentials: + description: Indicates whether the browser should include credentials + schema: + type: boolean + Access-Control-Expose-Headers: + description: Headers exposed to the client + schema: + type: string + example: X-Custom-Header1, X-Custom-Header2 + /Organizations/{organizationSid}/scim/Users/{userSid}: + servers: + - url: https://preview-iam.twilio.com + get: + tags: + - SCIM + summary: Get SCIM User + operationId: FetchOrganizationUser + parameters: + - name: organizationSid + in: path + required: true + schema: + pattern: OR[0-9a-f]{32} + type: string + format: OrganizationSid + example: OR5f3baf01a0f8273e74266afb84341766 + - name: userSid + in: path + required: true + schema: + pattern: US[0-9a-f]{32} + type: string + format: UserSid + example: USb51dccce9ac8e67b938253c7bcaa4f45 + responses: + '200': + description: User + content: + application/scim+json: + schema: + $ref: '#/components/schemas/ScimUser' + headers: + Access-Control-Allow-Origin: + description: Specify the origin(s) allowed to access the resource + schema: + type: string + example: '*' + Access-Control-Allow-Methods: + description: Specify the HTTP methods allowed when accessing the resource + schema: + type: string + example: POST, OPTIONS + Access-Control-Allow-Headers: + description: Specify the headers allowed when accessing the resource + schema: + type: string + example: Content-Type, Authorization + Access-Control-Allow-Credentials: + description: Indicates whether the browser should include credentials + schema: + type: boolean + Access-Control-Expose-Headers: + description: Headers exposed to the client + schema: + type: string + example: X-Custom-Header1, X-Custom-Header2 + '400': + description: Bad request or business rules violation + content: + application/scim+json: + schema: + $ref: '#/components/schemas/ScimError' + headers: + Access-Control-Allow-Origin: + description: Specify the origin(s) allowed to access the resource + schema: + type: string + example: '*' + Access-Control-Allow-Methods: + description: Specify the HTTP methods allowed when accessing the resource + schema: + type: string + example: POST, OPTIONS + Access-Control-Allow-Headers: + description: Specify the headers allowed when accessing the resource + schema: + type: string + example: Content-Type, Authorization + Access-Control-Allow-Credentials: + description: Indicates whether the browser should include credentials + schema: + type: boolean + Access-Control-Expose-Headers: + description: Headers exposed to the client + schema: + type: string + example: X-Custom-Header1, X-Custom-Header2 + '401': + description: Unauthorized + content: + application/scim+json: + schema: + $ref: '#/components/schemas/ScimError' + headers: + Access-Control-Allow-Origin: + description: Specify the origin(s) allowed to access the resource + schema: + type: string + example: '*' + Access-Control-Allow-Methods: + description: Specify the HTTP methods allowed when accessing the resource + schema: + type: string + example: POST, OPTIONS + Access-Control-Allow-Headers: + description: Specify the headers allowed when accessing the resource + schema: + type: string + example: Content-Type, Authorization + Access-Control-Allow-Credentials: + description: Indicates whether the browser should include credentials + schema: + type: boolean + Access-Control-Expose-Headers: + description: Headers exposed to the client + schema: + type: string + example: X-Custom-Header1, X-Custom-Header2 + '403': + description: Forbidden + content: + application/scim+json: + schema: + $ref: '#/components/schemas/ScimError' + headers: + Access-Control-Allow-Origin: + description: Specify the origin(s) allowed to access the resource + schema: + type: string + example: '*' + Access-Control-Allow-Methods: + description: Specify the HTTP methods allowed when accessing the resource + schema: + type: string + example: POST, OPTIONS + Access-Control-Allow-Headers: + description: Specify the headers allowed when accessing the resource + schema: + type: string + example: Content-Type, Authorization + Access-Control-Allow-Credentials: + description: Indicates whether the browser should include credentials + schema: + type: boolean + Access-Control-Expose-Headers: + description: Headers exposed to the client + schema: + type: string + example: X-Custom-Header1, X-Custom-Header2 + '404': + description: Not found + content: + application/scim+json: + schema: + $ref: '#/components/schemas/ScimError' + headers: + Access-Control-Allow-Origin: + description: Specify the origin(s) allowed to access the resource + schema: + type: string + example: '*' + Access-Control-Allow-Methods: + description: Specify the HTTP methods allowed when accessing the resource + schema: + type: string + example: POST, OPTIONS + Access-Control-Allow-Headers: + description: Specify the headers allowed when accessing the resource + schema: + type: string + example: Content-Type, Authorization + Access-Control-Allow-Credentials: + description: Indicates whether the browser should include credentials + schema: + type: boolean + Access-Control-Expose-Headers: + description: Headers exposed to the client + schema: + type: string + example: X-Custom-Header1, X-Custom-Header2 + '429': + description: Too many requests + content: + application/scim+json: + schema: + $ref: '#/components/schemas/ScimError' + headers: + Access-Control-Allow-Origin: + description: Specify the origin(s) allowed to access the resource + schema: + type: string + example: '*' + Access-Control-Allow-Methods: + description: Specify the HTTP methods allowed when accessing the resource + schema: + type: string + example: POST, OPTIONS + Access-Control-Allow-Headers: + description: Specify the headers allowed when accessing the resource + schema: + type: string + example: Content-Type, Authorization + Access-Control-Allow-Credentials: + description: Indicates whether the browser should include credentials + schema: + type: boolean + Access-Control-Expose-Headers: + description: Headers exposed to the client + schema: + type: string + example: X-Custom-Header1, X-Custom-Header2 + put: + tags: + - SCIM + summary: Update SCIM User + operationId: UpdateOrganizationUser + parameters: + - name: If-Match + in: header + schema: + type: string + - name: organizationSid + in: path + required: true + schema: + pattern: OR[0-9a-f]{32} + type: string + format: OrganizationSid + example: ORd3a1c06d4942d123cd8fa2a052fe110a + - name: userSid + in: path + required: true + schema: + pattern: US[0-9a-f]{32} + type: string + format: UserSid + example: US14def5586bc0799a5c7aab80247af278 + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/ScimUser' + application/scim+json: + schema: + $ref: '#/components/schemas/ScimUser' + required: true + responses: + '200': + description: User object with updated attributes + content: + application/scim+json: + schema: + $ref: '#/components/schemas/ScimUser' + headers: + Access-Control-Allow-Origin: + description: Specify the origin(s) allowed to access the resource + schema: + type: string + example: '*' + Access-Control-Allow-Methods: + description: Specify the HTTP methods allowed when accessing the resource + schema: + type: string + example: POST, OPTIONS + Access-Control-Allow-Headers: + description: Specify the headers allowed when accessing the resource + schema: + type: string + example: Content-Type, Authorization + Access-Control-Allow-Credentials: + description: Indicates whether the browser should include credentials + schema: + type: boolean + Access-Control-Expose-Headers: + description: Headers exposed to the client + schema: + type: string + example: X-Custom-Header1, X-Custom-Header2 + '400': + description: Bad request or business rules violation + content: + application/scim+json: + schema: + $ref: '#/components/schemas/ScimError' + headers: + Access-Control-Allow-Origin: + description: Specify the origin(s) allowed to access the resource + schema: + type: string + example: '*' + Access-Control-Allow-Methods: + description: Specify the HTTP methods allowed when accessing the resource + schema: + type: string + example: POST, OPTIONS + Access-Control-Allow-Headers: + description: Specify the headers allowed when accessing the resource + schema: + type: string + example: Content-Type, Authorization + Access-Control-Allow-Credentials: + description: Indicates whether the browser should include credentials + schema: + type: boolean + Access-Control-Expose-Headers: + description: Headers exposed to the client + schema: + type: string + example: X-Custom-Header1, X-Custom-Header2 + '401': + description: Unauthorized + content: + application/scim+json: + schema: + $ref: '#/components/schemas/ScimError' + headers: + Access-Control-Allow-Origin: + description: Specify the origin(s) allowed to access the resource + schema: + type: string + example: '*' + Access-Control-Allow-Methods: + description: Specify the HTTP methods allowed when accessing the resource + schema: + type: string + example: POST, OPTIONS + Access-Control-Allow-Headers: + description: Specify the headers allowed when accessing the resource + schema: + type: string + example: Content-Type, Authorization + Access-Control-Allow-Credentials: + description: Indicates whether the browser should include credentials + schema: + type: boolean + Access-Control-Expose-Headers: + description: Headers exposed to the client + schema: + type: string + example: X-Custom-Header1, X-Custom-Header2 + '403': + description: Forbidden + content: + application/scim+json: + schema: + $ref: '#/components/schemas/ScimError' + headers: + Access-Control-Allow-Origin: + description: Specify the origin(s) allowed to access the resource + schema: + type: string + example: '*' + Access-Control-Allow-Methods: + description: Specify the HTTP methods allowed when accessing the resource + schema: + type: string + example: POST, OPTIONS + Access-Control-Allow-Headers: + description: Specify the headers allowed when accessing the resource + schema: + type: string + example: Content-Type, Authorization + Access-Control-Allow-Credentials: + description: Indicates whether the browser should include credentials + schema: + type: boolean + Access-Control-Expose-Headers: + description: Headers exposed to the client + schema: + type: string + example: X-Custom-Header1, X-Custom-Header2 + '404': + description: Not found + content: + application/scim+json: + schema: + $ref: '#/components/schemas/ScimError' + headers: + Access-Control-Allow-Origin: + description: Specify the origin(s) allowed to access the resource + schema: + type: string + example: '*' + Access-Control-Allow-Methods: + description: Specify the HTTP methods allowed when accessing the resource + schema: + type: string + example: POST, OPTIONS + Access-Control-Allow-Headers: + description: Specify the headers allowed when accessing the resource + schema: + type: string + example: Content-Type, Authorization + Access-Control-Allow-Credentials: + description: Indicates whether the browser should include credentials + schema: + type: boolean + Access-Control-Expose-Headers: + description: Headers exposed to the client + schema: + type: string + example: X-Custom-Header1, X-Custom-Header2 + '409': + description: Version conflict + content: + application/scim+json: + schema: + $ref: '#/components/schemas/ScimError' + headers: + Access-Control-Allow-Origin: + description: Specify the origin(s) allowed to access the resource + schema: + type: string + example: '*' + Access-Control-Allow-Methods: + description: Specify the HTTP methods allowed when accessing the resource + schema: + type: string + example: POST, OPTIONS + Access-Control-Allow-Headers: + description: Specify the headers allowed when accessing the resource + schema: + type: string + example: Content-Type, Authorization + Access-Control-Allow-Credentials: + description: Indicates whether the browser should include credentials + schema: + type: boolean + Access-Control-Expose-Headers: + description: Headers exposed to the client + schema: + type: string + example: X-Custom-Header1, X-Custom-Header2 + '429': + description: Too many requests + content: + application/scim+json: + schema: + $ref: '#/components/schemas/ScimError' + headers: + Access-Control-Allow-Origin: + description: Specify the origin(s) allowed to access the resource + schema: + type: string + example: '*' + Access-Control-Allow-Methods: + description: Specify the HTTP methods allowed when accessing the resource + schema: + type: string + example: POST, OPTIONS + Access-Control-Allow-Headers: + description: Specify the headers allowed when accessing the resource + schema: + type: string + example: Content-Type, Authorization + Access-Control-Allow-Credentials: + description: Indicates whether the browser should include credentials + schema: + type: boolean + Access-Control-Expose-Headers: + description: Headers exposed to the client + schema: + type: string + example: X-Custom-Header1, X-Custom-Header2 + delete: + tags: + - SCIM + summary: Delete SCIM User + operationId: DeleteOrganizationUser + parameters: + - name: organizationSid + in: path + required: true + schema: + pattern: OR[0-9a-f]{32} + type: string + format: OrganizationSid + example: OR80b7392892f0a424d07c42f5b11dce2a + - name: userSid + in: path + required: true + schema: + pattern: US[0-9a-f]{32} + type: string + format: UserSid + example: US23c7d4510f1398849aaac5c543475b12 + responses: + '204': + description: No content + headers: + Access-Control-Allow-Origin: + description: Specify the origin(s) allowed to access the resource + schema: + type: string + example: '*' + Access-Control-Allow-Methods: + description: Specify the HTTP methods allowed when accessing the resource + schema: + type: string + example: POST, OPTIONS + Access-Control-Allow-Headers: + description: Specify the headers allowed when accessing the resource + schema: + type: string + example: Content-Type, Authorization + Access-Control-Allow-Credentials: + description: Indicates whether the browser should include credentials + schema: + type: boolean + Access-Control-Expose-Headers: + description: Headers exposed to the client + schema: + type: string + example: X-Custom-Header1, X-Custom-Header2 + '400': + description: Bad request or business rules violation + content: + application/scim+json: + schema: + $ref: '#/components/schemas/ScimError' + headers: + Access-Control-Allow-Origin: + description: Specify the origin(s) allowed to access the resource + schema: + type: string + example: '*' + Access-Control-Allow-Methods: + description: Specify the HTTP methods allowed when accessing the resource + schema: + type: string + example: POST, OPTIONS + Access-Control-Allow-Headers: + description: Specify the headers allowed when accessing the resource + schema: + type: string + example: Content-Type, Authorization + Access-Control-Allow-Credentials: + description: Indicates whether the browser should include credentials + schema: + type: boolean + Access-Control-Expose-Headers: + description: Headers exposed to the client + schema: + type: string + example: X-Custom-Header1, X-Custom-Header2 + '401': + description: Unauthorized + content: + application/scim+json: + schema: + $ref: '#/components/schemas/ScimError' + headers: + Access-Control-Allow-Origin: + description: Specify the origin(s) allowed to access the resource + schema: + type: string + example: '*' + Access-Control-Allow-Methods: + description: Specify the HTTP methods allowed when accessing the resource + schema: + type: string + example: POST, OPTIONS + Access-Control-Allow-Headers: + description: Specify the headers allowed when accessing the resource + schema: + type: string + example: Content-Type, Authorization + Access-Control-Allow-Credentials: + description: Indicates whether the browser should include credentials + schema: + type: boolean + Access-Control-Expose-Headers: + description: Headers exposed to the client + schema: + type: string + example: X-Custom-Header1, X-Custom-Header2 + '403': + description: Forbidden + content: + application/scim+json: + schema: + $ref: '#/components/schemas/ScimError' + headers: + Access-Control-Allow-Origin: + description: Specify the origin(s) allowed to access the resource + schema: + type: string + example: '*' + Access-Control-Allow-Methods: + description: Specify the HTTP methods allowed when accessing the resource + schema: + type: string + example: POST, OPTIONS + Access-Control-Allow-Headers: + description: Specify the headers allowed when accessing the resource + schema: + type: string + example: Content-Type, Authorization + Access-Control-Allow-Credentials: + description: Indicates whether the browser should include credentials + schema: + type: boolean + Access-Control-Expose-Headers: + description: Headers exposed to the client + schema: + type: string + example: X-Custom-Header1, X-Custom-Header2 + '404': + description: Not found + content: + application/scim+json: + schema: + $ref: '#/components/schemas/ScimError' + headers: + Access-Control-Allow-Origin: + description: Specify the origin(s) allowed to access the resource + schema: + type: string + example: '*' + Access-Control-Allow-Methods: + description: Specify the HTTP methods allowed when accessing the resource + schema: + type: string + example: POST, OPTIONS + Access-Control-Allow-Headers: + description: Specify the headers allowed when accessing the resource + schema: + type: string + example: Content-Type, Authorization + Access-Control-Allow-Credentials: + description: Indicates whether the browser should include credentials + schema: + type: boolean + Access-Control-Expose-Headers: + description: Headers exposed to the client + schema: + type: string + example: X-Custom-Header1, X-Custom-Header2 + '429': + description: Too many requests + content: + application/scim+json: + schema: + $ref: '#/components/schemas/ScimError' + headers: + Access-Control-Allow-Origin: + description: Specify the origin(s) allowed to access the resource + schema: + type: string + example: '*' + Access-Control-Allow-Methods: + description: Specify the HTTP methods allowed when accessing the resource + schema: + type: string + example: POST, OPTIONS + Access-Control-Allow-Headers: + description: Specify the headers allowed when accessing the resource + schema: + type: string + example: Content-Type, Authorization + Access-Control-Allow-Credentials: + description: Indicates whether the browser should include credentials + schema: + type: boolean + Access-Control-Expose-Headers: + description: Headers exposed to the client + schema: + type: string + example: X-Custom-Header1, X-Custom-Header2 + /v1/token: + servers: + - url: https://preview-iam.twilio.com + x-twilio: + defaultOutputProperties: [] + pathType: list + post: + security: [] + tags: + - OauthV1Token + summary: Issues a new Access token (optionally identity_token & refresh_token) + in exchange of Oauth grant + operationId: CreateToken + responses: + '201': + content: + application/json: + schema: + $ref: '#/components/schemas/oauth.v1.token' + examples: + create: + value: + access_token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c + refresh_token: ghjbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c + id_token: eyJhbdGciOiIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c + expires_in: 1438315200000 + token_type: bearer + description: Created + requestBody: + content: + application/x-www-form-urlencoded: + schema: + type: object + title: CreateTokenRequest + properties: + grant_type: + type: string + description: Grant type is a credential representing resource owner's + authorization which can be used by client to obtain access token. + client_id: + type: string + description: A 34 character string that uniquely identifies this + OAuth App. + client_secret: + type: string + description: The credential for confidential OAuth App. + code: + type: string + description: JWT token related to the authorization code grant type. + redirect_uri: + type: string + description: The redirect uri + audience: + type: string + description: The targeted audience uri + refresh_token: + type: string + description: JWT token related to refresh access token. + scope: + type: string + description: The scope of token + required: + - grant_type + - client_id + examples: + create: + value: + client_id: OQ7cda1a615f05a95634e643aaaf7081d7 + client_secret: sUWblrQ4wx_aYkdAWjHXNvHinynkYOgBoiRyEQUeEntpgDEG47qnBFD98yoEzsTh + grant_type: client_credentials + redirect_uri: '' + audience: '' + code: '' + refresh_token: refresh_token + scope: scope + required: true +components: + securitySchemes: + oAuth2ClientCredentials: + type: oauth2 + flows: + clientCredentials: + tokenUrl: https://oauth.twilio.com/v1/token + scopes: {} + schemas: + ScimUser: + required: + - userName + type: object + properties: + id: + type: string + description: Unique Twilio user sid + externalId: + maxLength: 255 + minLength: 2 + type: string + description: External unique resource id defined by provisioning client + userName: + maxLength: 255 + minLength: 2 + type: string + description: Unique username, MUST be same as primary email address + displayName: + maxLength: 255 + minLength: 0 + type: string + description: User friendly display name + name: + $ref: '#/components/schemas/ScimName' + emails: + maxItems: 2147483647 + minItems: 1 + type: array + description: Email address list of the user. Primary email must be defined + if there are more than 1 email. Primary email must match the username. + items: + $ref: '#/components/schemas/ScimEmailAddress' + active: + type: boolean + description: Indicates whether the user is active + locale: + type: string + description: User's locale + timezone: + type: string + description: User's time zone + schemas: + type: array + description: An array of URIs that indicate the schemas supported for this + user resource + items: + type: string + description: An array of URIs that indicate the schemas supported for + this user resource + meta: + $ref: '#/components/schemas/ScimMeta' + ScimUserPage: + type: object + properties: + Resources: + type: array + items: + $ref: '#/components/schemas/ScimUser' + totalResults: + type: integer + format: int32 + schemas: + type: array + items: + type: string + description: Scim ListResponse schema + ScimEmailAddress: + type: object + properties: + primary: + type: boolean + description: Indicates if this email address is the primary one + value: + maxLength: 160 + minLength: 2 + type: string + description: The actual email address value + type: + maxLength: 64 + minLength: 0 + type: string + description: The type of email address (e.g., work, home, etc.) + description: Email address list of the user. Primary email must be defined if + there are more than 1 email. Primary email must match the username. + ScimMeta: + type: object + properties: + resourceType: + type: string + description: Indicates the type of the resource + created: + type: string + description: The date and time when the resource was created in the system + format: date-time + lastModified: + type: string + description: The date and time when the resource was last modified + format: date-time + version: + type: string + description: A version identifier for the resource. This can be used to + manage resource versioning and concurrency control. + description: Meta + ScimName: + type: object + properties: + givenName: + maxLength: 255 + minLength: 0 + type: string + description: The user's first or given name + familyName: + maxLength: 255 + minLength: 0 + type: string + description: The user's last or family name + TestAnyType: + description: This is any type object + description: User's name + ScimResourceTypes: + type: object + properties: + Resources: + type: array + items: + type: object + properties: + name: + type: string + description: Name of the resource type + description: + type: string + description: Description of the resource type + endpoint: + type: string + description: HTTP-addressable endpoint relative to the Base URL of + the service provider + schema: + type: string + description: Primary/base schema URI + JsonPatch: + type: object + properties: + op: + type: string + enum: + - add + - remove + - replace + path: + type: string + value: + type: string + TwilioServiceErrorResponse: + type: object + properties: + code: + description: Twilio-specific error code + type: integer + format: int32 + message: + description: Error message + type: string + moreInfo: + description: Link to Error Code References + type: string + status: + description: HTTP response status code + type: integer + format: int32 + ScimError: + type: object + properties: + schemas: + type: array + description: Schema URIs that define the contents of the error structure + items: + type: string + description: Schema URIs that define the contents of the error structure + detail: + type: string + description: A human-readable description of the error + scimType: + type: string + description: A scimType error code as defined in RFC7644 + enum: + - invalidFilter + - uniqueness + - mutability + - invalidValue + - invalidSyntax + status: + type: string + description: Http status code + code: + description: Twilio-specific error code + type: integer + format: int32 + moreInfo: + description: Link to Error Code References + type: string + oauth.v1.token: + type: object + properties: + access_token: + type: string + nullable: true + description: Token which carries the necessary information to access a Twilio + resource directly. + refresh_token: + type: string + nullable: true + description: Token which carries the information necessary to get a new + access token. + id_token: + type: string + nullable: true + description: Token which carries the information necessary of user profile. + token_type: + type: string + nullable: true + description: Token type + expires_in: + type: integer + format: int64 + nullable: true diff --git a/specs_test/twilio_iam_organizations_v1.yaml b/specs_test/twilio_iam_organizations_v1.yaml new file mode 100644 index 000000000..65e71658c --- /dev/null +++ b/specs_test/twilio_iam_organizations_v1.yaml @@ -0,0 +1,572 @@ +openapi: 3.0.1 +security: + - oAuth2ClientCredentials: [] +info: + title: Organization Public API + contact: + name: Twilio Support + url: https://support.twilio.com + email: support@twilio.com + license: + name: Apache 2.0 + url: https://www.apache.org/licenses/LICENSE-2.0.html + version: 1.0.0 +tags: + - name: SCIM + description: SCIM 2.0 User endpoints + - name: OrganizationAccount + description: Organization Account operations + - name: RoleAssignments + description: Role assignment operations + - name: OauthV1Authorize + - name: OauthV1Token +paths: + "/v1/authorize": + servers: + - url: https://preview-iam.twilio.com + x-twilio: + defaultOutputProperties: + - redirect_to + pathType: list + get: + tags: + - OauthV1Authorize + security: [] + summary: Retrieves authorize uri + operationId: FetchAuthorize + parameters: + - name: response_type + in: query + description: Response Type + schema: + type: string + example: code + - name: client_id + in: query + description: The Client Identifier + schema: + type: string + example: OQ7cda1a615f05a95634e643aaaf7081d7 + - name: redirect_uri + in: query + description: The url to which response will be redirected to + schema: + type: string + example: www.twilio.com + - name: scope + in: query + description: The scope of the access request + schema: + type: string + example: offline_access + - name: state + in: query + description: An opaque value which can be used to maintain state between the + request and callback + schema: + type: string + example: xvz + responses: + '302': + content: + application/json: + schema: + "$ref": "#/components/schemas/oauth.v1.authorize" + examples: + fetch: + value: + redirect_to: https://www.twilio.com/authorize?response_type=code&client_id=OQ7cda1a615f05a95634e643aaaf7081d7&redirect_uri=www.twilio.com&scope=offline_access&state=xvz + description: Found + "/v1/token": + servers: + - url: https://preview-iam.twilio.com + x-twilio: + defaultOutputProperties: [] + pathType: list + post: + security: [] + tags: + - OauthV1Token + summary: Issues a new Access token (optionally identity_token & refresh_token) + in exchange of Oauth grant + operationId: CreateToken + responses: + '201': + content: + application/json: + schema: + "$ref": "#/components/schemas/oauth.v1.token" + examples: + create: + value: + access_token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c + refresh_token: ghjbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c + id_token: eyJhbdGciOiIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c + expires_in: 1438315200000 + token_type: bearer + description: Created + requestBody: + content: + application/x-www-form-urlencoded: + schema: + type: object + title: CreateTokenRequest + properties: + grant_type: + type: string + description: Grant type is a credential representing resource owner's + authorization which can be used by client to obtain access token. + client_id: + type: string + description: A 34 character string that uniquely identifies this + OAuth App. + client_secret: + type: string + description: The credential for confidential OAuth App. + code: + type: string + description: JWT token related to the authorization code grant type. + redirect_uri: + type: string + description: The redirect uri + audience: + type: string + description: The targeted audience uri + refresh_token: + type: string + description: JWT token related to refresh access token. + scope: + type: string + description: The scope of token + required: + - grant_type + - client_id + examples: + create: + value: + client_id: OQ7cda1a615f05a95634e643aaaf7081d7 + client_secret: sUWblrQ4wx_aYkdAWjHXNvHinynkYOgBoiRyEQUeEntpgDEG47qnBFD98yoEzsTh + grant_type: client_credentials + redirect_uri: '' + audience: '' + code: '' + refresh_token: refresh_token + scope: scope + required: true +components: + securitySchemes: + oAuth2ClientCredentials: + type: oauth2 + flows: + clientCredentials: + tokenUrl: https://preview-iam.twilio.com/v1/token + scopes: {} + schemas: + ScimUser: + required: + - userName + type: object + properties: + id: + type: string + description: Unique Twilio user sid + externalId: + maxLength: 255 + minLength: 2 + type: string + description: External unique resource id defined by provisioning client + userName: + maxLength: 255 + minLength: 2 + type: string + description: Unique username, MUST be same as primary email address + displayName: + maxLength: 255 + minLength: 0 + type: string + description: User friendly display name + name: + "$ref": "#/components/schemas/ScimName" + emails: + maxItems: 2147483647 + minItems: 1 + type: array + description: Email address list of the user. Primary email must be defined + if there are more than 1 email. Primary email must match the username. + items: + "$ref": "#/components/schemas/ScimEmailAddress" + active: + type: boolean + description: Indicates whether the user is active + locale: + type: string + description: User's locale + timezone: + type: string + description: User's time zone + schemas: + type: array + description: An array of URIs that indicate the schemas supported for this + user resource + items: + type: string + description: An array of URIs that indicate the schemas supported for + this user resource + meta: + "$ref": "#/components/schemas/ScimMeta" + ScimUserPage: + type: object + properties: + Resources: + type: array + items: + "$ref": "#/components/schemas/ScimUser" + totalResults: + type: integer + format: int32 + schemas: + type: array + items: + type: string + description: Scim ListResponse schema + ScimEmailAddress: + type: object + properties: + primary: + type: boolean + description: Indicates if this email address is the primary one + value: + maxLength: 160 + minLength: 2 + type: string + description: The actual email address value + type: + maxLength: 64 + minLength: 0 + type: string + description: The type of email address (e.g., work, home, etc.) + description: Email address list of the user. Primary email must be defined if + there are more than 1 email. Primary email must match the username. + ScimMeta: + type: object + properties: + resourceType: + type: string + description: Indicates the type of the resource + created: + type: string + description: The date and time when the resource was created in the system + format: date-time + lastModified: + type: string + description: The date and time when the resource was last modified + format: date-time + version: + type: string + description: A version identifier for the resource. This can be used to + manage resource versioning and concurrency control. + description: Meta + ScimName: + type: object + properties: + givenName: + maxLength: 255 + minLength: 0 + type: string + description: The user's first or given name + familyName: + maxLength: 255 + minLength: 0 + type: string + description: The user's last or family name + description: User's name + ScimResourceTypes: + type: object + properties: + Resources: + type: array + items: + type: object + properties: + name: + type: string + description: Name of the resource type + description: + type: string + description: Description of the resource type + endpoint: + type: string + description: HTTP-addressable endpoint relative to the Base URL of + the service provider + schema: + type: string + description: Primary/base schema URI + JsonPatch: + type: object + properties: + op: + type: string + enum: + - add + - remove + - replace + path: + type: string + value: + type: string + PublicApiCreateAccountRequest: + required: + - friendlyName + type: object + properties: + friendlyName: + maxLength: 255 + minLength: 1 + type: string + description: Account friendly name + ownerSid: + pattern: US[0-9a-f]{32} + type: string + description: Optional owner sid. If not provided, the owner will be the + organization owner. + format: UserSid + example: USa4faef6467378082de67039e533b515a + PublicApiCreateAccountResponse: + type: object + properties: + accountSid: + pattern: AC[0-9a-f]{32} + type: string + description: Twilio account sid for the new account, creation is asynchronous + owner. + format: AccountSid + example: ACaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + PublicApiAccountResponse: + type: object + properties: + account_sid: + pattern: AC[0-9a-f]{32} + type: string + description: Twilio account sid + format: AccountSid + example: ACaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + friendly_name: + type: string + description: Account friendly name + status: + type: string + description: Account status + example: active + enum: + - active + - suspended + - pending_closure + - closed + owner_sid: + pattern: US[0-9a-f]{32} + type: string + description: Twilio account sid + format: UserSid + example: US9a6d63d00bdbb50aa1c1889b3066bd30 + date_created: + type: string + description: The date and time when the account was created in the system + format: date-time + description: Page content + PublicApiAccountResponsePage: + type: object + properties: + content: + type: array + description: Page content + items: + "$ref": "#/components/schemas/PublicApiAccountResponse" + meta: + properties: + first_page_url: + format: uri + type: string + key: + type: string + next_page_url: + format: uri + nullable: true + type: string + page: + type: integer + page_size: + type: integer + previous_page_url: + format: uri + nullable: true + type: string + url: + format: uri + type: string + type: object + PublicApiCreateRoleAssignmentRequest: + required: + - role_sid + - scope + - identity + type: object + properties: + role_sid: + pattern: IX[0-9a-f]{32} + type: string + description: Twilio Role Sid representing assigned role + format: IamRoleSid + example: IXc4ddb9d0befdb122b0eff334e3084544 + scope: + pattern: "^[A-Z]{2}[0-9a-fA-F]{32}$" + type: string + description: Twilio Sid representing scope of this assignment + format: Sid + example: ACaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + identity: + pattern: "^[A-Z]{2}[0-9a-fA-F]{32}$" + type: string + description: Twilio Sid representing identity of this assignment + format: Sid + example: USc4ddb9d0befdb122b0eff334e3084544 + PublicApiCreateRoleAssignmentResponsePage: + type: object + properties: + content: + type: array + description: Page content + items: + "$ref": "#/components/schemas/PublicApiRoleAssignmentResponse" + meta: + properties: + first_page_url: + format: uri + type: string + key: + type: string + next_page_url: + format: uri + nullable: true + type: string + page: + type: integer + page_size: + type: integer + previous_page_url: + format: uri + nullable: true + type: string + url: + format: uri + type: string + type: object + PublicApiRoleAssignmentResponse: + type: object + properties: + sid: + pattern: IY[0-9a-f]{32} + type: string + description: Twilio Role Assignment Sid representing this role assignment + format: IamRoleAssignmentSid + example: IYc4ddb9d0befdb122b0eff334e3084544 + role_sid: + pattern: IX[0-9a-f]{32} + type: string + description: Twilio Role Sid representing assigned role + format: IamRoleSid + example: IXc4ddb9d0befdb122b0eff334e3084544 + scope: + pattern: "^[A-Z]{2}[0-9a-fA-F]{32}$" + type: string + description: Twilio Sid representing identity of this assignment + format: Sid + example: ACaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + identity: + pattern: "^[A-Z]{2}[0-9a-fA-F]{32}$" + type: string + description: Twilio Sid representing scope of this assignment + format: Sid + example: USc4ddb9d0befdb122b0eff334e3084544 + TwilioServiceErrorResponse: + type: object + properties: + code: + description: Twilio-specific error code + type: integer + format: int32 + message: + description: Error message + type: string + moreInfo: + description: Link to Error Code References + type: string + status: + description: HTTP response status code + type: integer + format: int32 + ScimError: + type: object + properties: + schemas: + type: array + description: Schema URIs that define the contents of the error structure + items: + type: string + description: Schema URIs that define the contents of the error structure + detail: + type: string + description: A human-readable description of the error + scimType: + type: string + description: A scimType error code as defined in RFC7644 + enum: + - invalidFilter + - uniqueness + - mutability + - invalidValue + - invalidSyntax + status: + type: string + description: Http status code + code: + description: Twilio-specific error code + type: integer + format: int32 + moreInfo: + description: Link to Error Code References + type: string + oauth.v1.authorize: + type: object + properties: + redirect_to: + type: string + format: uri + nullable: true + description: The callback URL + oauth.v1.token: + type: object + properties: + access_token: + type: string + nullable: true + description: Token which carries the necessary information to access a Twilio + resource directly. + refresh_token: + type: string + nullable: true + description: Token which carries the information necessary to get a new + access token. + id_token: + type: string + nullable: true + description: Token which carries the information necessary of user profile. + token_type: + type: string + nullable: true + description: Token type + expires_in: + type: integer + format: int64 + nullable: true +servers: + - url: https://preview-iam.twilio.com diff --git a/specs_test/twilio_iam_organizations_versionless.yaml b/specs_test/twilio_iam_organizations_versionless.yaml new file mode 100644 index 000000000..dfbcda84b --- /dev/null +++ b/specs_test/twilio_iam_organizations_versionless.yaml @@ -0,0 +1,2233 @@ +openapi: 3.0.1 +security: + - oAuth2ClientCredentials: [] +info: + title: Organization Public API + contact: + name: Twilio Support + url: 'https://support.twilio.com' + email: support@twilio.com + license: + name: Apache 2.0 + url: 'https://www.apache.org/licenses/LICENSE-2.0.html' + version: 1.0.0 +tags: + - name: SCIM + description: SCIM 2.0 User endpoints + - name: OrganizationAccount + description: Organization Account operations + - name: RoleAssignments + description: Role assignment operations + - name: OauthV1Authorize + - name: OauthV1Token +paths: + '/Organizations/{OrganizationSid}': + x-twilio: + dependentProperties: + users: + mapping: + organization_sid: organization_sid + resource_url: '/Organizations/{organization_sid}/scim/Users' + accounts: + mapping: + organization_sid: organization_sid + resource_url: '/Organizations/{organization_sid}/Accounts' + roleAssignments: + mapping: + organization_sid: organization_sid + resource_url: '/Organizations/{organization_sid}/RoleAssignments' + pathType: instance + mountName: organization + servers: + - url: 'https://preview-iam.twilio.com' + get: + summary: List SCIM Users + operationId: FetchOrganization + parameters: + - name: OrganizationSid + in: path + required: true + schema: + pattern: 'OR[0-9a-f]{32}' + type: string + format: OrganizationSid + example: OR33f4f3aa6fffe840d000f8ef22e883db + x-twilio: + ignoreOperation: true + responses: + '403': + description: Forbidden + content: + application/scim+json: + schema: {} + headers: + Access-Control-Allow-Origin: + description: Specify the origin(s) allowed to access the resource + schema: + type: string + example: '*' + Access-Control-Allow-Methods: + description: Specify the HTTP methods allowed when accessing the resource + schema: + type: string + example: 'POST, OPTIONS' + Access-Control-Allow-Headers: + description: Specify the headers allowed when accessing the resource + schema: + type: string + example: 'Content-Type, Authorization' + Access-Control-Allow-Credentials: + description: Indicates whether the browser should include credentials + schema: + type: boolean + Access-Control-Expose-Headers: + description: Headers exposed to the client + schema: + type: string + example: 'X-Custom-Header1, X-Custom-Header2' + '/Organizations/{OrganizationSid}/scim/ResourceTypes': + servers: + - url: 'https://preview-iam.twilio.com' + x-twilio: + pathType: list + parent: '/{OrganizationSid}' + '/Organizations/{OrganizationSid}/scim/Users': + servers: + - url: 'https://preview-iam.twilio.com' + get: + tags: + - SCIM + summary: List SCIM Users + operationId: ListOrganizationUsers + parameters: + - name: OrganizationSid + in: path + required: true + schema: + pattern: 'OR[0-9a-f]{32}' + type: string + format: OrganizationSid + example: OR33f4f3aa6fffe840d000f8ef22e883db + - name: filter + in: query + schema: + type: string + responses: + '200': + description: List of users + content: + application/scim+json: + schema: + $ref: '#/components/schemas/ScimUserPage' + headers: + Access-Control-Allow-Origin: + description: Specify the origin(s) allowed to access the resource + schema: + type: string + example: '*' + Access-Control-Allow-Methods: + description: Specify the HTTP methods allowed when accessing the resource + schema: + type: string + example: 'POST, OPTIONS' + Access-Control-Allow-Headers: + description: Specify the headers allowed when accessing the resource + schema: + type: string + example: 'Content-Type, Authorization' + Access-Control-Allow-Credentials: + description: Indicates whether the browser should include credentials + schema: + type: boolean + Access-Control-Expose-Headers: + description: Headers exposed to the client + schema: + type: string + example: 'X-Custom-Header1, X-Custom-Header2' + '400': + description: Bad request or business rules violation + content: + application/scim+json: + schema: + $ref: '#/components/schemas/ScimError' + headers: + Access-Control-Allow-Origin: + description: Specify the origin(s) allowed to access the resource + schema: + type: string + example: '*' + Access-Control-Allow-Methods: + description: Specify the HTTP methods allowed when accessing the resource + schema: + type: string + example: 'POST, OPTIONS' + Access-Control-Allow-Headers: + description: Specify the headers allowed when accessing the resource + schema: + type: string + example: 'Content-Type, Authorization' + Access-Control-Allow-Credentials: + description: Indicates whether the browser should include credentials + schema: + type: boolean + Access-Control-Expose-Headers: + description: Headers exposed to the client + schema: + type: string + example: 'X-Custom-Header1, X-Custom-Header2' + '401': + description: Unauthorized + content: + application/scim+json: + schema: + $ref: '#/components/schemas/ScimError' + headers: + Access-Control-Allow-Origin: + description: Specify the origin(s) allowed to access the resource + schema: + type: string + example: '*' + Access-Control-Allow-Methods: + description: Specify the HTTP methods allowed when accessing the resource + schema: + type: string + example: 'POST, OPTIONS' + Access-Control-Allow-Headers: + description: Specify the headers allowed when accessing the resource + schema: + type: string + example: 'Content-Type, Authorization' + Access-Control-Allow-Credentials: + description: Indicates whether the browser should include credentials + schema: + type: boolean + Access-Control-Expose-Headers: + description: Headers exposed to the client + schema: + type: string + example: 'X-Custom-Header1, X-Custom-Header2' + '403': + description: Forbidden + content: + application/scim+json: + schema: + $ref: '#/components/schemas/ScimError' + headers: + Access-Control-Allow-Origin: + description: Specify the origin(s) allowed to access the resource + schema: + type: string + example: '*' + Access-Control-Allow-Methods: + description: Specify the HTTP methods allowed when accessing the resource + schema: + type: string + example: 'POST, OPTIONS' + Access-Control-Allow-Headers: + description: Specify the headers allowed when accessing the resource + schema: + type: string + example: 'Content-Type, Authorization' + Access-Control-Allow-Credentials: + description: Indicates whether the browser should include credentials + schema: + type: boolean + Access-Control-Expose-Headers: + description: Headers exposed to the client + schema: + type: string + example: 'X-Custom-Header1, X-Custom-Header2' + '429': + description: Too many requests + content: + application/scim+json: + schema: + $ref: '#/components/schemas/ScimError' + headers: + Access-Control-Allow-Origin: + description: Specify the origin(s) allowed to access the resource + schema: + type: string + example: '*' + Access-Control-Allow-Methods: + description: Specify the HTTP methods allowed when accessing the resource + schema: + type: string + example: 'POST, OPTIONS' + Access-Control-Allow-Headers: + description: Specify the headers allowed when accessing the resource + schema: + type: string + example: 'Content-Type, Authorization' + Access-Control-Allow-Credentials: + description: Indicates whether the browser should include credentials + schema: + type: boolean + Access-Control-Expose-Headers: + description: Headers exposed to the client + schema: + type: string + example: 'X-Custom-Header1, X-Custom-Header2' + post: + tags: + - SCIM + summary: Create SCIM User + operationId: CreateOrganizationUser + parameters: + - name: OrganizationSid + in: path + required: true + schema: + pattern: 'OR[0-9a-f]{32}' + type: string + format: OrganizationSid + example: ORceef74a747c1ae8d837aafb5a31e475f + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/ScimUser' + application/scim+json: + schema: + $ref: '#/components/schemas/ScimUser' + required: true + responses: + '201': + description: Created User + content: + application/scim+json: + schema: + $ref: '#/components/schemas/ScimUser' + headers: + Access-Control-Allow-Origin: + description: Specify the origin(s) allowed to access the resource + schema: + type: string + example: '*' + Access-Control-Allow-Methods: + description: Specify the HTTP methods allowed when accessing the resource + schema: + type: string + example: 'POST, OPTIONS' + Access-Control-Allow-Headers: + description: Specify the headers allowed when accessing the resource + schema: + type: string + example: 'Content-Type, Authorization' + Access-Control-Allow-Credentials: + description: Indicates whether the browser should include credentials + schema: + type: boolean + Access-Control-Expose-Headers: + description: Headers exposed to the client + schema: + type: string + example: 'X-Custom-Header1, X-Custom-Header2' + '400': + description: Bad request or business rules violation + content: + application/scim+json: + schema: + $ref: '#/components/schemas/ScimError' + headers: + Access-Control-Allow-Origin: + description: Specify the origin(s) allowed to access the resource + schema: + type: string + example: '*' + Access-Control-Allow-Methods: + description: Specify the HTTP methods allowed when accessing the resource + schema: + type: string + example: 'POST, OPTIONS' + Access-Control-Allow-Headers: + description: Specify the headers allowed when accessing the resource + schema: + type: string + example: 'Content-Type, Authorization' + Access-Control-Allow-Credentials: + description: Indicates whether the browser should include credentials + schema: + type: boolean + Access-Control-Expose-Headers: + description: Headers exposed to the client + schema: + type: string + example: 'X-Custom-Header1, X-Custom-Header2' + '401': + description: Unauthorized + content: + application/scim+json: + schema: + $ref: '#/components/schemas/ScimError' + headers: + Access-Control-Allow-Origin: + description: Specify the origin(s) allowed to access the resource + schema: + type: string + example: '*' + Access-Control-Allow-Methods: + description: Specify the HTTP methods allowed when accessing the resource + schema: + type: string + example: 'POST, OPTIONS' + Access-Control-Allow-Headers: + description: Specify the headers allowed when accessing the resource + schema: + type: string + example: 'Content-Type, Authorization' + Access-Control-Allow-Credentials: + description: Indicates whether the browser should include credentials + schema: + type: boolean + Access-Control-Expose-Headers: + description: Headers exposed to the client + schema: + type: string + example: 'X-Custom-Header1, X-Custom-Header2' + '403': + description: Forbidden + content: + application/scim+json: + schema: + $ref: '#/components/schemas/ScimError' + headers: + Access-Control-Allow-Origin: + description: Specify the origin(s) allowed to access the resource + schema: + type: string + example: '*' + Access-Control-Allow-Methods: + description: Specify the HTTP methods allowed when accessing the resource + schema: + type: string + example: 'POST, OPTIONS' + Access-Control-Allow-Headers: + description: Specify the headers allowed when accessing the resource + schema: + type: string + example: 'Content-Type, Authorization' + Access-Control-Allow-Credentials: + description: Indicates whether the browser should include credentials + schema: + type: boolean + Access-Control-Expose-Headers: + description: Headers exposed to the client + schema: + type: string + example: 'X-Custom-Header1, X-Custom-Header2' + '404': + description: Not found + content: + application/scim+json: + schema: + $ref: '#/components/schemas/ScimError' + headers: + Access-Control-Allow-Origin: + description: Specify the origin(s) allowed to access the resource + schema: + type: string + example: '*' + Access-Control-Allow-Methods: + description: Specify the HTTP methods allowed when accessing the resource + schema: + type: string + example: 'POST, OPTIONS' + Access-Control-Allow-Headers: + description: Specify the headers allowed when accessing the resource + schema: + type: string + example: 'Content-Type, Authorization' + Access-Control-Allow-Credentials: + description: Indicates whether the browser should include credentials + schema: + type: boolean + Access-Control-Expose-Headers: + description: Headers exposed to the client + schema: + type: string + example: 'X-Custom-Header1, X-Custom-Header2' + '429': + description: Too many requests + content: + application/scim+json: + schema: + $ref: '#/components/schemas/ScimError' + headers: + Access-Control-Allow-Origin: + description: Specify the origin(s) allowed to access the resource + schema: + type: string + example: '*' + Access-Control-Allow-Methods: + description: Specify the HTTP methods allowed when accessing the resource + schema: + type: string + example: 'POST, OPTIONS' + Access-Control-Allow-Headers: + description: Specify the headers allowed when accessing the resource + schema: + type: string + example: 'Content-Type, Authorization' + Access-Control-Allow-Credentials: + description: Indicates whether the browser should include credentials + schema: + type: boolean + Access-Control-Expose-Headers: + description: Headers exposed to the client + schema: + type: string + example: 'X-Custom-Header1, X-Custom-Header2' + x-twilio: + pathType: list + parent: '/{OrganizationSid}' + '/Organizations/{OrganizationSid}/scim/Users/{Id}': + servers: + - url: 'https://preview-iam.twilio.com' + get: + tags: + - SCIM + summary: Get SCIM User + operationId: FetchOrganizationUser + parameters: + - name: OrganizationSid + in: path + required: true + schema: + pattern: 'OR[0-9a-f]{32}' + type: string + format: OrganizationSid + example: OR5f3baf01a0f8273e74266afb84341766 + - name: Id + in: path + required: true + schema: + pattern: 'US[0-9a-f]{32}' + type: string + format: Id + example: USb51dccce9ac8e67b938253c7bcaa4f45 + responses: + '200': + description: User + content: + application/scim+json: + schema: + $ref: '#/components/schemas/ScimUser' + headers: + Access-Control-Allow-Origin: + description: Specify the origin(s) allowed to access the resource + schema: + type: string + example: '*' + Access-Control-Allow-Methods: + description: Specify the HTTP methods allowed when accessing the resource + schema: + type: string + example: 'POST, OPTIONS' + Access-Control-Allow-Headers: + description: Specify the headers allowed when accessing the resource + schema: + type: string + example: 'Content-Type, Authorization' + Access-Control-Allow-Credentials: + description: Indicates whether the browser should include credentials + schema: + type: boolean + Access-Control-Expose-Headers: + description: Headers exposed to the client + schema: + type: string + example: 'X-Custom-Header1, X-Custom-Header2' + '400': + description: Bad request or business rules violation + content: + application/scim+json: + schema: + $ref: '#/components/schemas/ScimError' + headers: + Access-Control-Allow-Origin: + description: Specify the origin(s) allowed to access the resource + schema: + type: string + example: '*' + Access-Control-Allow-Methods: + description: Specify the HTTP methods allowed when accessing the resource + schema: + type: string + example: 'POST, OPTIONS' + Access-Control-Allow-Headers: + description: Specify the headers allowed when accessing the resource + schema: + type: string + example: 'Content-Type, Authorization' + Access-Control-Allow-Credentials: + description: Indicates whether the browser should include credentials + schema: + type: boolean + Access-Control-Expose-Headers: + description: Headers exposed to the client + schema: + type: string + example: 'X-Custom-Header1, X-Custom-Header2' + '401': + description: Unauthorized + content: + application/scim+json: + schema: + $ref: '#/components/schemas/ScimError' + headers: + Access-Control-Allow-Origin: + description: Specify the origin(s) allowed to access the resource + schema: + type: string + example: '*' + Access-Control-Allow-Methods: + description: Specify the HTTP methods allowed when accessing the resource + schema: + type: string + example: 'POST, OPTIONS' + Access-Control-Allow-Headers: + description: Specify the headers allowed when accessing the resource + schema: + type: string + example: 'Content-Type, Authorization' + Access-Control-Allow-Credentials: + description: Indicates whether the browser should include credentials + schema: + type: boolean + Access-Control-Expose-Headers: + description: Headers exposed to the client + schema: + type: string + example: 'X-Custom-Header1, X-Custom-Header2' + '403': + description: Forbidden + content: + application/scim+json: + schema: + $ref: '#/components/schemas/ScimError' + headers: + Access-Control-Allow-Origin: + description: Specify the origin(s) allowed to access the resource + schema: + type: string + example: '*' + Access-Control-Allow-Methods: + description: Specify the HTTP methods allowed when accessing the resource + schema: + type: string + example: 'POST, OPTIONS' + Access-Control-Allow-Headers: + description: Specify the headers allowed when accessing the resource + schema: + type: string + example: 'Content-Type, Authorization' + Access-Control-Allow-Credentials: + description: Indicates whether the browser should include credentials + schema: + type: boolean + Access-Control-Expose-Headers: + description: Headers exposed to the client + schema: + type: string + example: 'X-Custom-Header1, X-Custom-Header2' + '404': + description: Not found + content: + application/scim+json: + schema: + $ref: '#/components/schemas/ScimError' + headers: + Access-Control-Allow-Origin: + description: Specify the origin(s) allowed to access the resource + schema: + type: string + example: '*' + Access-Control-Allow-Methods: + description: Specify the HTTP methods allowed when accessing the resource + schema: + type: string + example: 'POST, OPTIONS' + Access-Control-Allow-Headers: + description: Specify the headers allowed when accessing the resource + schema: + type: string + example: 'Content-Type, Authorization' + Access-Control-Allow-Credentials: + description: Indicates whether the browser should include credentials + schema: + type: boolean + Access-Control-Expose-Headers: + description: Headers exposed to the client + schema: + type: string + example: 'X-Custom-Header1, X-Custom-Header2' + '429': + description: Too many requests + content: + application/scim+json: + schema: + $ref: '#/components/schemas/ScimError' + headers: + Access-Control-Allow-Origin: + description: Specify the origin(s) allowed to access the resource + schema: + type: string + example: '*' + Access-Control-Allow-Methods: + description: Specify the HTTP methods allowed when accessing the resource + schema: + type: string + example: 'POST, OPTIONS' + Access-Control-Allow-Headers: + description: Specify the headers allowed when accessing the resource + schema: + type: string + example: 'Content-Type, Authorization' + Access-Control-Allow-Credentials: + description: Indicates whether the browser should include credentials + schema: + type: boolean + Access-Control-Expose-Headers: + description: Headers exposed to the client + schema: + type: string + example: 'X-Custom-Header1, X-Custom-Header2' + put: + tags: + - SCIM + summary: Update SCIM User + operationId: UpdateOrganizationUser + parameters: + - name: If-Match + in: header + schema: + type: string + - name: OrganizationSid + in: path + required: true + schema: + pattern: 'OR[0-9a-f]{32}' + type: string + format: OrganizationSid + example: ORd3a1c06d4942d123cd8fa2a052fe110a + - name: Id + in: path + required: true + schema: + pattern: 'US[0-9a-f]{32}' + type: string + format: Id + example: US14def5586bc0799a5c7aab80247af278 + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/ScimUser' + application/scim+json: + schema: + $ref: '#/components/schemas/ScimUser' + required: true + responses: + '200': + description: User object with updated attributes + content: + application/scim+json: + schema: + $ref: '#/components/schemas/ScimUser' + headers: + Access-Control-Allow-Origin: + description: Specify the origin(s) allowed to access the resource + schema: + type: string + example: '*' + Access-Control-Allow-Methods: + description: Specify the HTTP methods allowed when accessing the resource + schema: + type: string + example: 'POST, OPTIONS' + Access-Control-Allow-Headers: + description: Specify the headers allowed when accessing the resource + schema: + type: string + example: 'Content-Type, Authorization' + Access-Control-Allow-Credentials: + description: Indicates whether the browser should include credentials + schema: + type: boolean + Access-Control-Expose-Headers: + description: Headers exposed to the client + schema: + type: string + example: 'X-Custom-Header1, X-Custom-Header2' + '400': + description: Bad request or business rules violation + content: + application/scim+json: + schema: + $ref: '#/components/schemas/ScimError' + headers: + Access-Control-Allow-Origin: + description: Specify the origin(s) allowed to access the resource + schema: + type: string + example: '*' + Access-Control-Allow-Methods: + description: Specify the HTTP methods allowed when accessing the resource + schema: + type: string + example: 'POST, OPTIONS' + Access-Control-Allow-Headers: + description: Specify the headers allowed when accessing the resource + schema: + type: string + example: 'Content-Type, Authorization' + Access-Control-Allow-Credentials: + description: Indicates whether the browser should include credentials + schema: + type: boolean + Access-Control-Expose-Headers: + description: Headers exposed to the client + schema: + type: string + example: 'X-Custom-Header1, X-Custom-Header2' + '401': + description: Unauthorized + content: + application/scim+json: + schema: + $ref: '#/components/schemas/ScimError' + headers: + Access-Control-Allow-Origin: + description: Specify the origin(s) allowed to access the resource + schema: + type: string + example: '*' + Access-Control-Allow-Methods: + description: Specify the HTTP methods allowed when accessing the resource + schema: + type: string + example: 'POST, OPTIONS' + Access-Control-Allow-Headers: + description: Specify the headers allowed when accessing the resource + schema: + type: string + example: 'Content-Type, Authorization' + Access-Control-Allow-Credentials: + description: Indicates whether the browser should include credentials + schema: + type: boolean + Access-Control-Expose-Headers: + description: Headers exposed to the client + schema: + type: string + example: 'X-Custom-Header1, X-Custom-Header2' + '403': + description: Forbidden + content: + application/scim+json: + schema: + $ref: '#/components/schemas/ScimError' + headers: + Access-Control-Allow-Origin: + description: Specify the origin(s) allowed to access the resource + schema: + type: string + example: '*' + Access-Control-Allow-Methods: + description: Specify the HTTP methods allowed when accessing the resource + schema: + type: string + example: 'POST, OPTIONS' + Access-Control-Allow-Headers: + description: Specify the headers allowed when accessing the resource + schema: + type: string + example: 'Content-Type, Authorization' + Access-Control-Allow-Credentials: + description: Indicates whether the browser should include credentials + schema: + type: boolean + Access-Control-Expose-Headers: + description: Headers exposed to the client + schema: + type: string + example: 'X-Custom-Header1, X-Custom-Header2' + '404': + description: Not found + content: + application/scim+json: + schema: + $ref: '#/components/schemas/ScimError' + headers: + Access-Control-Allow-Origin: + description: Specify the origin(s) allowed to access the resource + schema: + type: string + example: '*' + Access-Control-Allow-Methods: + description: Specify the HTTP methods allowed when accessing the resource + schema: + type: string + example: 'POST, OPTIONS' + Access-Control-Allow-Headers: + description: Specify the headers allowed when accessing the resource + schema: + type: string + example: 'Content-Type, Authorization' + Access-Control-Allow-Credentials: + description: Indicates whether the browser should include credentials + schema: + type: boolean + Access-Control-Expose-Headers: + description: Headers exposed to the client + schema: + type: string + example: 'X-Custom-Header1, X-Custom-Header2' + '409': + description: Version conflict + content: + application/scim+json: + schema: + $ref: '#/components/schemas/ScimError' + headers: + Access-Control-Allow-Origin: + description: Specify the origin(s) allowed to access the resource + schema: + type: string + example: '*' + Access-Control-Allow-Methods: + description: Specify the HTTP methods allowed when accessing the resource + schema: + type: string + example: 'POST, OPTIONS' + Access-Control-Allow-Headers: + description: Specify the headers allowed when accessing the resource + schema: + type: string + example: 'Content-Type, Authorization' + Access-Control-Allow-Credentials: + description: Indicates whether the browser should include credentials + schema: + type: boolean + Access-Control-Expose-Headers: + description: Headers exposed to the client + schema: + type: string + example: 'X-Custom-Header1, X-Custom-Header2' + '429': + description: Too many requests + content: + application/scim+json: + schema: + $ref: '#/components/schemas/ScimError' + headers: + Access-Control-Allow-Origin: + description: Specify the origin(s) allowed to access the resource + schema: + type: string + example: '*' + Access-Control-Allow-Methods: + description: Specify the HTTP methods allowed when accessing the resource + schema: + type: string + example: 'POST, OPTIONS' + Access-Control-Allow-Headers: + description: Specify the headers allowed when accessing the resource + schema: + type: string + example: 'Content-Type, Authorization' + Access-Control-Allow-Credentials: + description: Indicates whether the browser should include credentials + schema: + type: boolean + Access-Control-Expose-Headers: + description: Headers exposed to the client + schema: + type: string + example: 'X-Custom-Header1, X-Custom-Header2' + delete: + tags: + - SCIM + summary: Delete SCIM User + operationId: DeleteOrganizationUser + parameters: + - name: OrganizationSid + in: path + required: true + schema: + pattern: 'OR[0-9a-f]{32}' + type: string + format: OrganizationSid + example: OR80b7392892f0a424d07c42f5b11dce2a + - name: Id + in: path + required: true + schema: + pattern: 'US[0-9a-f]{32}' + type: string + format: Id + example: US23c7d4510f1398849aaac5c543475b12 + responses: + '204': + description: No content + headers: + Access-Control-Allow-Origin: + description: Specify the origin(s) allowed to access the resource + schema: + type: string + example: '*' + Access-Control-Allow-Methods: + description: Specify the HTTP methods allowed when accessing the resource + schema: + type: string + example: 'POST, OPTIONS' + Access-Control-Allow-Headers: + description: Specify the headers allowed when accessing the resource + schema: + type: string + example: 'Content-Type, Authorization' + Access-Control-Allow-Credentials: + description: Indicates whether the browser should include credentials + schema: + type: boolean + Access-Control-Expose-Headers: + description: Headers exposed to the client + schema: + type: string + example: 'X-Custom-Header1, X-Custom-Header2' + '400': + description: Bad request or business rules violation + content: + application/scim+json: + schema: + $ref: '#/components/schemas/ScimError' + headers: + Access-Control-Allow-Origin: + description: Specify the origin(s) allowed to access the resource + schema: + type: string + example: '*' + Access-Control-Allow-Methods: + description: Specify the HTTP methods allowed when accessing the resource + schema: + type: string + example: 'POST, OPTIONS' + Access-Control-Allow-Headers: + description: Specify the headers allowed when accessing the resource + schema: + type: string + example: 'Content-Type, Authorization' + Access-Control-Allow-Credentials: + description: Indicates whether the browser should include credentials + schema: + type: boolean + Access-Control-Expose-Headers: + description: Headers exposed to the client + schema: + type: string + example: 'X-Custom-Header1, X-Custom-Header2' + '401': + description: Unauthorized + content: + application/scim+json: + schema: + $ref: '#/components/schemas/ScimError' + headers: + Access-Control-Allow-Origin: + description: Specify the origin(s) allowed to access the resource + schema: + type: string + example: '*' + Access-Control-Allow-Methods: + description: Specify the HTTP methods allowed when accessing the resource + schema: + type: string + example: 'POST, OPTIONS' + Access-Control-Allow-Headers: + description: Specify the headers allowed when accessing the resource + schema: + type: string + example: 'Content-Type, Authorization' + Access-Control-Allow-Credentials: + description: Indicates whether the browser should include credentials + schema: + type: boolean + Access-Control-Expose-Headers: + description: Headers exposed to the client + schema: + type: string + example: 'X-Custom-Header1, X-Custom-Header2' + '403': + description: Forbidden + content: + application/scim+json: + schema: + $ref: '#/components/schemas/ScimError' + headers: + Access-Control-Allow-Origin: + description: Specify the origin(s) allowed to access the resource + schema: + type: string + example: '*' + Access-Control-Allow-Methods: + description: Specify the HTTP methods allowed when accessing the resource + schema: + type: string + example: 'POST, OPTIONS' + Access-Control-Allow-Headers: + description: Specify the headers allowed when accessing the resource + schema: + type: string + example: 'Content-Type, Authorization' + Access-Control-Allow-Credentials: + description: Indicates whether the browser should include credentials + schema: + type: boolean + Access-Control-Expose-Headers: + description: Headers exposed to the client + schema: + type: string + example: 'X-Custom-Header1, X-Custom-Header2' + '404': + description: Not found + content: + application/scim+json: + schema: + $ref: '#/components/schemas/ScimError' + headers: + Access-Control-Allow-Origin: + description: Specify the origin(s) allowed to access the resource + schema: + type: string + example: '*' + Access-Control-Allow-Methods: + description: Specify the HTTP methods allowed when accessing the resource + schema: + type: string + example: 'POST, OPTIONS' + Access-Control-Allow-Headers: + description: Specify the headers allowed when accessing the resource + schema: + type: string + example: 'Content-Type, Authorization' + Access-Control-Allow-Credentials: + description: Indicates whether the browser should include credentials + schema: + type: boolean + Access-Control-Expose-Headers: + description: Headers exposed to the client + schema: + type: string + example: 'X-Custom-Header1, X-Custom-Header2' + '429': + description: Too many requests + content: + application/scim+json: + schema: + $ref: '#/components/schemas/ScimError' + headers: + Access-Control-Allow-Origin: + description: Specify the origin(s) allowed to access the resource + schema: + type: string + example: '*' + Access-Control-Allow-Methods: + description: Specify the HTTP methods allowed when accessing the resource + schema: + type: string + example: 'POST, OPTIONS' + Access-Control-Allow-Headers: + description: Specify the headers allowed when accessing the resource + schema: + type: string + example: 'Content-Type, Authorization' + Access-Control-Allow-Credentials: + description: Indicates whether the browser should include credentials + schema: + type: boolean + Access-Control-Expose-Headers: + description: Headers exposed to the client + schema: + type: string + example: 'X-Custom-Header1, X-Custom-Header2' + x-twilio: + pathType: instance + parent: '/{OrganizationSid}' + '/Organizations/{OrganizationSid}/Accounts': + servers: + - url: 'https://preview-iam.twilio.com' + get: + tags: + - OrganizationAccounts + summary: List organization accounts + operationId: ListOrganizationAccounts + parameters: + - name: OrganizationSid + in: path + required: true + schema: + pattern: 'OR[0-9a-f]{32}' + type: string + format: OrganizationSid + example: ORa36de9717566c7eb6363671f54b87ba9 + - name: PageSize + in: query + schema: + maximum: 100 + minimum: 1 + type: integer + format: int32 + default: 50 + - name: PageToken + in: query + schema: + maxLength: 4096 + minLength: 1 + type: string + responses: + '200': + description: Organization account list + content: + application/json: + schema: + $ref: '#/components/schemas/PublicApiAccountResponsePage' + headers: + Access-Control-Allow-Origin: + description: Specify the origin(s) allowed to access the resource + schema: + type: string + example: '*' + Access-Control-Allow-Methods: + description: Specify the HTTP methods allowed when accessing the resource + schema: + type: string + example: 'POST, OPTIONS' + Access-Control-Allow-Headers: + description: Specify the headers allowed when accessing the resource + schema: + type: string + example: 'Content-Type, Authorization' + Access-Control-Allow-Credentials: + description: Indicates whether the browser should include credentials + schema: + type: boolean + Access-Control-Expose-Headers: + description: Headers exposed to the client + schema: + type: string + example: 'X-Custom-Header1, X-Custom-Header2' + '403': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/TwilioServiceErrorResponse' + headers: + Access-Control-Allow-Origin: + description: Specify the origin(s) allowed to access the resource + schema: + type: string + example: '*' + Access-Control-Allow-Methods: + description: Specify the HTTP methods allowed when accessing the resource + schema: + type: string + example: 'POST, OPTIONS' + Access-Control-Allow-Headers: + description: Specify the headers allowed when accessing the resource + schema: + type: string + example: 'Content-Type, Authorization' + Access-Control-Allow-Credentials: + description: Indicates whether the browser should include credentials + schema: + type: boolean + Access-Control-Expose-Headers: + description: Headers exposed to the client + schema: + type: string + example: 'X-Custom-Header1, X-Custom-Header2' + '404': + description: Account not found + content: + application/json: + schema: + $ref: '#/components/schemas/TwilioServiceErrorResponse' + headers: + Access-Control-Allow-Origin: + description: Specify the origin(s) allowed to access the resource + schema: + type: string + example: '*' + Access-Control-Allow-Methods: + description: Specify the HTTP methods allowed when accessing the resource + schema: + type: string + example: 'POST, OPTIONS' + Access-Control-Allow-Headers: + description: Specify the headers allowed when accessing the resource + schema: + type: string + example: 'Content-Type, Authorization' + Access-Control-Allow-Credentials: + description: Indicates whether the browser should include credentials + schema: + type: boolean + Access-Control-Expose-Headers: + description: Headers exposed to the client + schema: + type: string + example: 'X-Custom-Header1, X-Custom-Header2' + x-twilio: + pathType: list + parent: '/{OrganizationSid}' + '/Organizations/{OrganizationSid}/Accounts/{AccountSid}': + servers: + - url: 'https://preview-iam.twilio.com' + get: + tags: + - OrganizationAccounts + summary: Get details of organization account + operationId: FetchOrganizationAccount + parameters: + - name: OrganizationSid + in: path + required: true + schema: + pattern: 'OR[0-9a-f]{32}' + type: string + format: OrganizationSid + example: ORf9618e7f043b4bc13832e4946fde06c9 + - name: AccountSid + in: path + required: true + schema: + pattern: 'AC[0-9a-f]{32}' + type: string + format: AccountSid + example: ACaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + responses: + '200': + description: Get details of organization account + content: + application/json: + schema: + $ref: '#/components/schemas/PublicApiAccountResponse' + headers: + Access-Control-Allow-Origin: + description: Specify the origin(s) allowed to access the resource + schema: + type: string + example: '*' + Access-Control-Allow-Methods: + description: Specify the HTTP methods allowed when accessing the resource + schema: + type: string + example: 'POST, OPTIONS' + Access-Control-Allow-Headers: + description: Specify the headers allowed when accessing the resource + schema: + type: string + example: 'Content-Type, Authorization' + Access-Control-Allow-Credentials: + description: Indicates whether the browser should include credentials + schema: + type: boolean + Access-Control-Expose-Headers: + description: Headers exposed to the client + schema: + type: string + example: 'X-Custom-Header1, X-Custom-Header2' + '403': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/TwilioServiceErrorResponse' + headers: + Access-Control-Allow-Origin: + description: Specify the origin(s) allowed to access the resource + schema: + type: string + example: '*' + Access-Control-Allow-Methods: + description: Specify the HTTP methods allowed when accessing the resource + schema: + type: string + example: 'POST, OPTIONS' + Access-Control-Allow-Headers: + description: Specify the headers allowed when accessing the resource + schema: + type: string + example: 'Content-Type, Authorization' + Access-Control-Allow-Credentials: + description: Indicates whether the browser should include credentials + schema: + type: boolean + Access-Control-Expose-Headers: + description: Headers exposed to the client + schema: + type: string + example: 'X-Custom-Header1, X-Custom-Header2' + '404': + description: Account does not belong to Organization + content: + application/json: + schema: + $ref: '#/components/schemas/TwilioServiceErrorResponse' + headers: + Access-Control-Allow-Origin: + description: Specify the origin(s) allowed to access the resource + schema: + type: string + example: '*' + Access-Control-Allow-Methods: + description: Specify the HTTP methods allowed when accessing the resource + schema: + type: string + example: 'POST, OPTIONS' + Access-Control-Allow-Headers: + description: Specify the headers allowed when accessing the resource + schema: + type: string + example: 'Content-Type, Authorization' + Access-Control-Allow-Credentials: + description: Indicates whether the browser should include credentials + schema: + type: boolean + Access-Control-Expose-Headers: + description: Headers exposed to the client + schema: + type: string + example: 'X-Custom-Header1, X-Custom-Header2' + x-twilio: + pathType: instance + parent: '/{OrganizationSid}' + '/Organizations/{OrganizationSid}/RoleAssignments': + servers: + - url: 'https://preview-iam.twilio.com' + get: + tags: + - RoleAssignments + summary: List role assignments + description: List role assignments for the given organization + operationId: ListRoleAssignments + parameters: + - name: OrganizationSid + in: path + required: true + schema: + pattern: 'OR[0-9a-f]{32}' + type: string + format: OrganizationSid + example: OR33f4f3aa6fffe840d000f8ef22e883db + - name: PageSize + in: query + schema: + maximum: 100 + minimum: 1 + type: integer + format: int32 + default: 100 + - name: PageToken + in: query + schema: + maxLength: 4096 + minLength: 1 + type: string + - name: Identity + in: query + required: false + schema: + pattern: '^[A-Z]{2}[0-9a-fA-F]{32}$' + type: string + format: Sid + example: USa36de9717566c7eb6363671f54b87ba9 + - name: Scope + in: query + required: false + schema: + pattern: '^[A-Z]{2}[0-9a-fA-F]{32}$' + type: string + format: Sid + example: ACaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + responses: + '200': + description: Returned list of role assignments + content: + application/json: + schema: + $ref: '#/components/schemas/PublicApiCreateRoleAssignmentResponsePage' + headers: + Access-Control-Allow-Origin: + description: Specify the origin(s) allowed to access the resource + schema: + type: string + example: '*' + Access-Control-Allow-Methods: + description: Specify the HTTP methods allowed when accessing the resource + schema: + type: string + example: 'POST, OPTIONS' + Access-Control-Allow-Headers: + description: Specify the headers allowed when accessing the resource + schema: + type: string + example: 'Content-Type, Authorization' + Access-Control-Allow-Credentials: + description: Indicates whether the browser should include credentials + schema: + type: boolean + Access-Control-Expose-Headers: + description: Headers exposed to the client + schema: + type: string + example: 'X-Custom-Header1, X-Custom-Header2' + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/TwilioServiceErrorResponse' + headers: + Access-Control-Allow-Origin: + description: Specify the origin(s) allowed to access the resource + schema: + type: string + example: '*' + Access-Control-Allow-Methods: + description: Specify the HTTP methods allowed when accessing the resource + schema: + type: string + example: 'POST, OPTIONS' + Access-Control-Allow-Headers: + description: Specify the headers allowed when accessing the resource + schema: + type: string + example: 'Content-Type, Authorization' + Access-Control-Allow-Credentials: + description: Indicates whether the browser should include credentials + schema: + type: boolean + Access-Control-Expose-Headers: + description: Headers exposed to the client + schema: + type: string + example: 'X-Custom-Header1, X-Custom-Header2' + '403': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/TwilioServiceErrorResponse' + headers: + Access-Control-Allow-Origin: + description: Specify the origin(s) allowed to access the resource + schema: + type: string + example: '*' + Access-Control-Allow-Methods: + description: Specify the HTTP methods allowed when accessing the resource + schema: + type: string + example: 'POST, OPTIONS' + Access-Control-Allow-Headers: + description: Specify the headers allowed when accessing the resource + schema: + type: string + example: 'Content-Type, Authorization' + Access-Control-Allow-Credentials: + description: Indicates whether the browser should include credentials + schema: + type: boolean + Access-Control-Expose-Headers: + description: Headers exposed to the client + schema: + type: string + example: 'X-Custom-Header1, X-Custom-Header2' + post: + tags: + - RoleAssignments + summary: Create a role assignment + description: Create a role assignment for the given organization + operationId: CreateRoleAssignment + parameters: + - name: OrganizationSid + in: path + required: true + schema: + pattern: 'OR[0-9a-f]{32}' + type: string + format: OrganizationSid + example: ORa36de9717566c7eb6363671f54b87ba9 + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/PublicApiCreateRoleAssignmentRequest' + required: true + responses: + '201': + description: Created + content: + application/json: + schema: + $ref: '#/components/schemas/PublicApiRoleAssignmentResponse' + headers: + Access-Control-Allow-Origin: + description: Specify the origin(s) allowed to access the resource + schema: + type: string + example: '*' + Access-Control-Allow-Methods: + description: Specify the HTTP methods allowed when accessing the resource + schema: + type: string + example: 'POST, OPTIONS' + Access-Control-Allow-Headers: + description: Specify the headers allowed when accessing the resource + schema: + type: string + example: 'Content-Type, Authorization' + Access-Control-Allow-Credentials: + description: Indicates whether the browser should include credentials + schema: + type: boolean + Access-Control-Expose-Headers: + description: Headers exposed to the client + schema: + type: string + example: 'X-Custom-Header1, X-Custom-Header2' + '400': + description: Bad request or business rules violation + content: + application/scim+json: + schema: + $ref: '#/components/schemas/TwilioServiceErrorResponse' + headers: + Access-Control-Allow-Origin: + description: Specify the origin(s) allowed to access the resource + schema: + type: string + example: '*' + Access-Control-Allow-Methods: + description: Specify the HTTP methods allowed when accessing the resource + schema: + type: string + example: 'POST, OPTIONS' + Access-Control-Allow-Headers: + description: Specify the headers allowed when accessing the resource + schema: + type: string + example: 'Content-Type, Authorization' + Access-Control-Allow-Credentials: + description: Indicates whether the browser should include credentials + schema: + type: boolean + Access-Control-Expose-Headers: + description: Headers exposed to the client + schema: + type: string + example: 'X-Custom-Header1, X-Custom-Header2' + '403': + description: Unauthorized + content: + application/scim+json: + schema: + $ref: '#/components/schemas/TwilioServiceErrorResponse' + headers: + Access-Control-Allow-Origin: + description: Specify the origin(s) allowed to access the resource + schema: + type: string + example: '*' + Access-Control-Allow-Methods: + description: Specify the HTTP methods allowed when accessing the resource + schema: + type: string + example: 'POST, OPTIONS' + Access-Control-Allow-Headers: + description: Specify the headers allowed when accessing the resource + schema: + type: string + example: 'Content-Type, Authorization' + Access-Control-Allow-Credentials: + description: Indicates whether the browser should include credentials + schema: + type: boolean + Access-Control-Expose-Headers: + description: Headers exposed to the client + schema: + type: string + example: 'X-Custom-Header1, X-Custom-Header2' + x-twilio: + pathType: list + parent: '/{OrganizationSid}' + '/Organizations/{OrganizationSid}/RoleAssignments/{Sid}': + servers: + - url: 'https://preview-iam.twilio.com' + delete: + tags: + - RoleAssignments + summary: Delete a role assignment + description: Delete a role assignment for the given organization + operationId: DeleteRoleAssignment + parameters: + - name: OrganizationSid + in: path + required: true + schema: + pattern: 'OR[0-9a-f]{32}' + type: string + format: OrganizationSid + example: ORa36de9717566c7eb6363671f54b87ba9 + - name: Sid + in: path + required: true + schema: + pattern: 'IY[0-9a-f]{32}' + type: string + format: IamSid + example: IYa36de9717566c7eb6363671f54b87ba9 + responses: + '204': + description: No content + headers: + Access-Control-Allow-Origin: + description: Specify the origin(s) allowed to access the resource + schema: + type: string + example: '*' + Access-Control-Allow-Methods: + description: Specify the HTTP methods allowed when accessing the resource + schema: + type: string + example: 'POST, OPTIONS' + Access-Control-Allow-Headers: + description: Specify the headers allowed when accessing the resource + schema: + type: string + example: 'Content-Type, Authorization' + Access-Control-Allow-Credentials: + description: Indicates whether the browser should include credentials + schema: + type: boolean + Access-Control-Expose-Headers: + description: Headers exposed to the client + schema: + type: string + example: 'X-Custom-Header1, X-Custom-Header2' + '400': + description: Invalid request provided + content: + application/scim+json: + schema: + $ref: '#/components/schemas/TwilioServiceErrorResponse' + headers: + Access-Control-Allow-Origin: + description: Specify the origin(s) allowed to access the resource + schema: + type: string + example: '*' + Access-Control-Allow-Methods: + description: Specify the HTTP methods allowed when accessing the resource + schema: + type: string + example: 'POST, OPTIONS' + Access-Control-Allow-Headers: + description: Specify the headers allowed when accessing the resource + schema: + type: string + example: 'Content-Type, Authorization' + Access-Control-Allow-Credentials: + description: Indicates whether the browser should include credentials + schema: + type: boolean + Access-Control-Expose-Headers: + description: Headers exposed to the client + schema: + type: string + example: 'X-Custom-Header1, X-Custom-Header2' + '403': + description: Unauthorized + content: + application/scim+json: + schema: + $ref: '#/components/schemas/TwilioServiceErrorResponse' + headers: + Access-Control-Allow-Origin: + description: Specify the origin(s) allowed to access the resource + schema: + type: string + example: '*' + Access-Control-Allow-Methods: + description: Specify the HTTP methods allowed when accessing the resource + schema: + type: string + example: 'POST, OPTIONS' + Access-Control-Allow-Headers: + description: Specify the headers allowed when accessing the resource + schema: + type: string + example: 'Content-Type, Authorization' + Access-Control-Allow-Credentials: + description: Indicates whether the browser should include credentials + schema: + type: boolean + Access-Control-Expose-Headers: + description: Headers exposed to the client + schema: + type: string + example: 'X-Custom-Header1, X-Custom-Header2' + x-twilio: + pathType: instance + parent: '/{OrganizationSid}' +components: + securitySchemes: + oAuth2ClientCredentials: + type: oauth2 + flows: + clientCredentials: + tokenUrl: 'https://preview-iam.twilio.com/v1/token' + scopes: {} + schemas: + ScimUser: + required: + - userName + type: object + properties: + id: + type: string + description: Unique Twilio user sid + externalId: + maxLength: 255 + minLength: 2 + type: string + description: External unique resource id defined by provisioning client + userName: + maxLength: 255 + minLength: 2 + type: string + description: 'Unique username, MUST be same as primary email address' + displayName: + maxLength: 255 + minLength: 0 + type: string + description: User friendly display name + name: + $ref: '#/components/schemas/ScimName' + emails: + maxItems: 2147483647 + minItems: 1 + type: array + description: >- + Email address list of the user. Primary email must be defined if + there are more than 1 email. Primary email must match the username. + items: + $ref: '#/components/schemas/ScimEmailAddress' + active: + type: boolean + description: Indicates whether the user is active + locale: + type: string + description: User's locale + timezone: + type: string + description: User's time zone + schemas: + type: array + description: >- + An array of URIs that indicate the schemas supported for this user + resource + items: + type: string + description: >- + An array of URIs that indicate the schemas supported for this user + resource + meta: + $ref: '#/components/schemas/ScimMeta' + ScimUserPage: + type: object + properties: + Resources: + type: array + items: + $ref: '#/components/schemas/ScimUser' + totalResults: + type: integer + format: int32 + schemas: + type: array + items: + type: string + description: Scim ListResponse schema + ScimEmailAddress: + type: object + properties: + primary: + type: boolean + description: Indicates if this email address is the primary one + value: + maxLength: 160 + minLength: 2 + type: string + description: The actual email address value + type: + maxLength: 64 + minLength: 0 + type: string + description: 'The type of email address (e.g., work, home, etc.)' + description: >- + Email address list of the user. Primary email must be defined if there + are more than 1 email. Primary email must match the username. + ScimMeta: + type: object + properties: + resourceType: + type: string + description: Indicates the type of the resource + created: + type: string + description: The date and time when the resource was created in the system + format: date-time + lastModified: + type: string + description: The date and time when the resource was last modified + format: date-time + version: + type: string + description: >- + A version identifier for the resource. This can be used to manage + resource versioning and concurrency control. + description: Meta + ScimName: + type: object + properties: + givenName: + maxLength: 255 + minLength: 0 + type: string + description: The user's first or given name + familyName: + maxLength: 255 + minLength: 0 + type: string + description: The user's last or family name + description: User's name + ScimResourceTypes: + type: object + properties: + Resources: + type: array + items: + type: object + properties: + name: + type: string + description: Name of the resource type + description: + type: string + description: Description of the resource type + endpoint: + type: string + description: >- + HTTP-addressable endpoint relative to the Base URL of the + service provider + schema: + type: string + description: Primary/base schema URI + ScimPatchRequest: + type: object + properties: + schemas: + type: array + items: + type: string + Operations: + type: array + items: + $ref: '#/components/schemas/ScimPatchOperation' + ScimPatchOperation: + type: object + properties: + op: + type: string + description: The operation to perform + path: + type: string + value: + type: object + JsonPatch: + type: object + properties: + op: + type: string + enum: + - add + - remove + - replace + path: + type: string + value: + type: string + PublicApiCreateAccountRequest: + required: + - friendlyName + type: object + properties: + friendlyName: + maxLength: 255 + minLength: 1 + type: string + description: Account friendly name + ownerSid: + pattern: 'US[0-9a-f]{32}' + type: string + description: >- + Optional owner sid. If not provided, the owner will be the + organization owner. + format: Id + example: USa4faef6467378082de67039e533b515a + PublicApiCreateAccountResponse: + type: object + properties: + accountSid: + pattern: 'AC[0-9a-f]{32}' + type: string + description: >- + Twilio account sid for the new account, creation is asynchronous + owner. + format: AccountSid + example: ACaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + PublicApiAccountResponse: + type: object + properties: + account_sid: + pattern: 'AC[0-9a-f]{32}' + type: string + description: Twilio account sid + format: AccountSid + example: ACaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + friendly_name: + type: string + description: Account friendly name + status: + type: string + description: Account status + example: active + enum: + - active + - suspended + - pending_closure + - closed + owner_sid: + pattern: 'US[0-9a-f]{32}' + type: string + description: Twilio account sid + format: Id + example: US9a6d63d00bdbb50aa1c1889b3066bd30 + date_created: + type: string + description: The date and time when the account was created in the system + format: date-time + description: Page content + PublicApiAccountResponsePage: + type: object + properties: + content: + type: array + description: Page content + items: + $ref: '#/components/schemas/PublicApiAccountResponse' + meta: + properties: + first_page_url: + format: uri + type: string + key: + type: string + next_page_url: + format: uri + nullable: true + type: string + page: + type: integer + page_size: + type: integer + previous_page_url: + format: uri + nullable: true + type: string + url: + format: uri + type: string + type: object + PublicApiCreateRoleAssignmentRequest: + required: + - role_sid + - scope + - identity + type: object + properties: + role_sid: + pattern: 'IX[0-9a-f]{32}' + type: string + description: Twilio Role Sid representing assigned role + format: IamRoleSid + example: IXc4ddb9d0befdb122b0eff334e3084544 + scope: + pattern: '^[A-Z]{2}[0-9a-fA-F]{32}$' + type: string + description: Twilio Sid representing scope of this assignment + format: Sid + example: ACaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + identity: + pattern: '^[A-Z]{2}[0-9a-fA-F]{32}$' + type: string + description: Twilio Sid representing identity of this assignment + format: Sid + example: USc4ddb9d0befdb122b0eff334e3084544 + PublicApiCreateRoleAssignmentResponsePage: + type: object + properties: + content: + type: array + description: Page content + items: + $ref: '#/components/schemas/PublicApiRoleAssignmentResponse' + meta: + properties: + first_page_url: + format: uri + type: string + key: + type: string + next_page_url: + format: uri + nullable: true + type: string + page: + type: integer + page_size: + type: integer + previous_page_url: + format: uri + nullable: true + type: string + url: + format: uri + type: string + type: object + PublicApiRoleAssignmentResponse: + type: object + properties: + sid: + pattern: 'IY[0-9a-f]{32}' + type: string + description: Twilio Role Assignment Sid representing this role assignment + format: IamSid + example: IYc4ddb9d0befdb122b0eff334e3084544 + role_sid: + pattern: 'IX[0-9a-f]{32}' + type: string + description: Twilio Role Sid representing assigned role + format: IamRoleSid + example: IXc4ddb9d0befdb122b0eff334e3084544 + scope: + pattern: '^[A-Z]{2}[0-9a-fA-F]{32}$' + type: string + description: Twilio Sid representing identity of this assignment + format: Sid + example: ACaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + identity: + pattern: '^[A-Z]{2}[0-9a-fA-F]{32}$' + type: string + description: Twilio Sid representing scope of this assignment + format: Sid + example: USc4ddb9d0befdb122b0eff334e3084544 + TwilioServiceErrorResponse: + type: object + properties: + code: + description: Twilio-specific error code + type: integer + format: int32 + message: + description: Error message + type: string + moreInfo: + description: Link to Error Code References + type: string + status: + description: HTTP response status code + type: integer + format: int32 + ScimError: + type: object + properties: + schemas: + type: array + description: Schema URIs that define the contents of the error structure + items: + type: string + description: Schema URIs that define the contents of the error structure + detail: + type: string + description: A human-readable description of the error + scimType: + type: string + description: A scimType error code as defined in RFC7644 + enum: + - invalidFilter + - uniqueness + - mutability + - invalidValue + - invalidSyntax + status: + type: string + description: Http status code + code: + description: Twilio-specific error code + type: integer + format: int32 + moreInfo: + description: Link to Error Code References + type: string + oauth.v1.authorize: + type: object + properties: + redirect_to: + type: string + format: uri + nullable: true + description: The callback URL + oauth.v1.token: + type: object + properties: + access_token: + type: string + nullable: true + description: >- + Token which carries the necessary information to access a Twilio + resource directly. + refresh_token: + type: string + nullable: true + description: >- + Token which carries the information necessary to get a new access + token. + id_token: + type: string + nullable: true + description: Token which carries the information necessary of user profile. + token_type: + type: string + nullable: true + description: Token type + expires_in: + type: integer + format: int64 + nullable: true +servers: + - url: 'https://preview-iam.twilio.com' diff --git a/src/main/java/com/twilio/oai/TwilioPythonGenerator.java b/src/main/java/com/twilio/oai/TwilioPythonGenerator.java index 92c67f7a2..0087b2479 100644 --- a/src/main/java/com/twilio/oai/TwilioPythonGenerator.java +++ b/src/main/java/com/twilio/oai/TwilioPythonGenerator.java @@ -1,3 +1,6 @@ +import com.twilio.oai.common.EnumConstants; +import org.openapitools.codegen.languages.PythonClientCodegen; + //package com.twilio.oai; // //import com.twilio.oai.api.ApiResources; @@ -32,7 +35,7 @@ // //import static com.twilio.oai.common.ApplicationConstants.CONFIG_PYTHON_JSON_PATH; // -//public class TwilioPythonGenerator extends PythonClientCodegen { +public class TwilioPythonGenerator extends PythonClientCodegen { // private final TwilioCodegenAdapter twilioCodegen; // private final PythonApiActionTemplate actionTemplate = new PythonApiActionTemplate(this); // private final IResourceTree resourceTree = new ResourceMap(new Inflector()); @@ -132,10 +135,10 @@ // .build(); // } // -// @Override -// public String getName() { -// return EnumConstants.Generator.TWILIO_PYTHON.getValue(); -// } + @Override + public String getName() { + return EnumConstants.Generator.TWILIO_PYTHON.getValue(); + } // // @Override // public String toParamName(final String name) { @@ -146,4 +149,4 @@ // public String defaultTemplatingEngine() { // return "twilio-handlebars"; // } -//} +} diff --git a/src/main/java/com/twilio/oai/java/processor/enums/parameter/body/InlineBodyListEnumProcessor.java b/src/main/java/com/twilio/oai/java/processor/enums/parameter/body/InlineBodyListEnumProcessor.java index 0319a7ae3..a3aa5d4b0 100644 --- a/src/main/java/com/twilio/oai/java/processor/enums/parameter/body/InlineBodyListEnumProcessor.java +++ b/src/main/java/com/twilio/oai/java/processor/enums/parameter/body/InlineBodyListEnumProcessor.java @@ -71,11 +71,7 @@ private void datatype(CodegenParameter codegenParameter) { codegenParameter.vendorExtensions.put(X_DATATYPE, resolvedDataType); // Resolve BaseType for List as it is used in promoter as setter method. - String baseType = Utility.getEnumNameFromDatatype(codegenParameter.baseType); - if (baseType != null) { - String resolvedBaseType = ResourceCacheContext.get().getResourceName() + DOT + StringUtils.toPascalCase(baseType); - codegenParameter.baseType = resolvedBaseType; - } + codegenParameter.baseType = enumNonContainerDatatype; } private void cacheEnumClass(CodegenParameter codegenParameter) { diff --git a/src/main/java/com/twilio/oai/java/processor/enums/parameter/body/ReusableBodyListEnumProcessor.java b/src/main/java/com/twilio/oai/java/processor/enums/parameter/body/ReusableBodyListEnumProcessor.java index 017b48842..7b430e69e 100644 --- a/src/main/java/com/twilio/oai/java/processor/enums/parameter/body/ReusableBodyListEnumProcessor.java +++ b/src/main/java/com/twilio/oai/java/processor/enums/parameter/body/ReusableBodyListEnumProcessor.java @@ -76,11 +76,7 @@ private void datatype(CodegenParameter codegenParameter) { codegenParameter.vendorExtensions.put(X_DATATYPE, resolvedDataType); // Resolve BaseType for List as it is used in promoter as setter method. - String baseType = Utility.getEnumNameFromDatatype(codegenParameter.baseType); - if (baseType != null) { - String resolvedBaseType = ResourceCacheContext.get().getResourceName() + DOT + StringUtils.toPascalCase(baseType); - codegenParameter.baseType = resolvedBaseType; - } + codegenParameter.baseType = enumNonContainerDatatype; } private void cacheEnumClass(CodegenParameter codegenParameter) { diff --git a/src/main/java/com/twilio/oai/java/processor/enums/parameter/param/InlineListParamEnumProcessor.java b/src/main/java/com/twilio/oai/java/processor/enums/parameter/param/InlineListParamEnumProcessor.java index 345eb5399..e9209677e 100644 --- a/src/main/java/com/twilio/oai/java/processor/enums/parameter/param/InlineListParamEnumProcessor.java +++ b/src/main/java/com/twilio/oai/java/processor/enums/parameter/param/InlineListParamEnumProcessor.java @@ -72,11 +72,7 @@ private void datatype(CodegenParameter codegenParameter) { codegenParameter.vendorExtensions.put(X_DATATYPE, resolvedDataType); // Resolve BaseType for List as it is used in promoter as setter method. - String baseType = Utility.getEnumNameFromDatatype(codegenParameter.baseType); - if (baseType != null) { - String resolvedBaseType = ResourceCacheContext.get().getResourceName() + DOT + StringUtils.toPascalCase(baseType); - codegenParameter.baseType = resolvedBaseType; - } + codegenParameter.baseType = enumNonContainerDatatype; // enumNonContainerDatatype = Account.Status } diff --git a/src/main/java/com/twilio/oai/java/processor/enums/parameter/param/ReusableListParamEnumProcessor.java b/src/main/java/com/twilio/oai/java/processor/enums/parameter/param/ReusableListParamEnumProcessor.java index 35d106116..43022baa2 100644 --- a/src/main/java/com/twilio/oai/java/processor/enums/parameter/param/ReusableListParamEnumProcessor.java +++ b/src/main/java/com/twilio/oai/java/processor/enums/parameter/param/ReusableListParamEnumProcessor.java @@ -71,11 +71,7 @@ private void datatype(CodegenParameter codegenParameter) { codegenParameter.vendorExtensions.put(X_DATATYPE, resolvedDataType); // Resolve BaseType for List as it is used in promoter as setter method. - String baseType = Utility.getEnumNameFromDatatype(codegenParameter.baseType); - if (baseType != null) { - String resolvedBaseType = ResourceCacheContext.get().getResourceName() + DOT + StringUtils.toPascalCase(baseType); - codegenParameter.baseType = resolvedBaseType; - } + codegenParameter.baseType = enumNonContainerDatatype; } private void cacheEnumClass(CodegenParameter codegenParameter) { diff --git a/src/main/java/com/twilio/oai/java/processor/enums/property/InlineListPropEnumProcessor.java b/src/main/java/com/twilio/oai/java/processor/enums/property/InlineListPropEnumProcessor.java index 308616018..10aaa5ca3 100644 --- a/src/main/java/com/twilio/oai/java/processor/enums/property/InlineListPropEnumProcessor.java +++ b/src/main/java/com/twilio/oai/java/processor/enums/property/InlineListPropEnumProcessor.java @@ -53,11 +53,7 @@ private void datatype(CodegenProperty codegenProperty) { codegenProperty.vendorExtensions.put(X_DATATYPE, resolvedDataType); // Resolve BaseType for List as it is used in promoter as setter method. - String baseType = Utility.getEnumNameFromDatatype(codegenProperty.baseType); - if (baseType != null) { - String resolvedBaseType = ResourceCacheContext.get().getResourceName() + DOT + StringUtils.toPascalCase(baseType); - codegenProperty.baseType = resolvedBaseType; - } + codegenProperty.baseType = enumNonContainerDatatype; } private void cacheEnumClass(CodegenProperty codegenProperty) { diff --git a/src/main/java/com/twilio/oai/java/processor/enums/property/ReusableListPropEnumProcessor.java b/src/main/java/com/twilio/oai/java/processor/enums/property/ReusableListPropEnumProcessor.java index cf1da6b5a..c512376ce 100644 --- a/src/main/java/com/twilio/oai/java/processor/enums/property/ReusableListPropEnumProcessor.java +++ b/src/main/java/com/twilio/oai/java/processor/enums/property/ReusableListPropEnumProcessor.java @@ -56,11 +56,7 @@ private void datatype(CodegenProperty codegenProperty) { codegenProperty.vendorExtensions.put(X_DATATYPE, resolvedDataType); // Resolve BaseType for List as it is used in promoter as setter method. - String baseType = Utility.getEnumNameFromDatatype(codegenProperty.baseType); - if (baseType != null) { - String resolvedBaseType = ResourceCacheContext.get().getResourceName() + DOT + StringUtils.toPascalCase(baseType); - codegenProperty.baseType = resolvedBaseType; - } + codegenProperty.baseType = enumNonContainerDatatype; } private void cacheEnumClass(CodegenProperty codegenProperty) { diff --git a/src/test/java/com/twilio/oai/TwilioGeneratorTest.java b/src/test/java/com/twilio/oai/TwilioGeneratorTest.java index b20b9fe44..5f1029a37 100644 --- a/src/test/java/com/twilio/oai/TwilioGeneratorTest.java +++ b/src/test/java/com/twilio/oai/TwilioGeneratorTest.java @@ -40,7 +40,7 @@ public static void setUp() { @Test public void launchGenerator() { - final String pathname = "examples/spec/twilio_api_v2010.yaml"; + final String pathname = "examples/spec/twilio_flex_v1.yaml"; File filesList[] ; File directoryPath = new File(pathname); if (directoryPath.isDirectory()) { From 95118868234c5839f410cde524c5ec362a739860 Mon Sep 17 00:00:00 2001 From: sbansla Date: Wed, 17 Sep 2025 17:18:37 +0530 Subject: [PATCH 24/38] added scim+json support --- .../auth/{BasicAuth.java => Auth.java} | 11 +++--- .../oai/java/processor/auth/NoAuth.java | 6 +++- .../twilio/oai/java/processor/auth/OAuth.java | 19 ---------- .../oai/java/processor/auth/OrgsOAuth.java | 35 ------------------- .../processor/auth/SecuritySchemeManager.java | 3 +- .../property/InlinePropEnumProcessor.java | 2 +- .../responsebody/JsonResponseProcessor.java | 10 ++++-- 7 files changed, 20 insertions(+), 66 deletions(-) rename src/main/java/com/twilio/oai/java/processor/auth/{BasicAuth.java => Auth.java} (74%) delete mode 100644 src/main/java/com/twilio/oai/java/processor/auth/OAuth.java delete mode 100644 src/main/java/com/twilio/oai/java/processor/auth/OrgsOAuth.java diff --git a/src/main/java/com/twilio/oai/java/processor/auth/BasicAuth.java b/src/main/java/com/twilio/oai/java/processor/auth/Auth.java similarity index 74% rename from src/main/java/com/twilio/oai/java/processor/auth/BasicAuth.java rename to src/main/java/com/twilio/oai/java/processor/auth/Auth.java index 17b34197e..02c29b6da 100644 --- a/src/main/java/com/twilio/oai/java/processor/auth/BasicAuth.java +++ b/src/main/java/com/twilio/oai/java/processor/auth/Auth.java @@ -9,7 +9,7 @@ import static com.twilio.oai.resolver.java.JavaConventionResolver.AUTH_IMPORT_CLASS; import static com.twilio.oai.resolver.java.JavaConventionResolver.HTTP_CLASS_PREFIX; -public class BasicAuth implements SecuritySchemeProcessor { +public class Auth implements SecuritySchemeProcessor { @Override public void process(CodegenOperation codegenOperation) { HashMap authAttributes = new HashMap<>(); @@ -22,10 +22,9 @@ public void process(CodegenOperation codegenOperation) { public boolean shouldProcess(CodegenOperation codegenOperation) { List securities = codegenOperation.authMethods; if (securities == null || securities.isEmpty()) return false; // No Authentication - if (securities.size() > 1) { - throw new RuntimeException("Multiple auth methods are not supported. Please use only one auth method per operation."); - } - CodegenSecurity security = securities.get(0); - return security.isBasic; + return true; +// if (securities.size() > 1) { +// throw new RuntimeException("Multiple auth methods are not supported. Please use only one auth method per operation."); +// } } } diff --git a/src/main/java/com/twilio/oai/java/processor/auth/NoAuth.java b/src/main/java/com/twilio/oai/java/processor/auth/NoAuth.java index 4eef9260f..579a48292 100644 --- a/src/main/java/com/twilio/oai/java/processor/auth/NoAuth.java +++ b/src/main/java/com/twilio/oai/java/processor/auth/NoAuth.java @@ -1,8 +1,10 @@ package com.twilio.oai.java.processor.auth; import org.openapitools.codegen.CodegenOperation; +import org.openapitools.codegen.CodegenSecurity; import java.util.HashMap; +import java.util.List; import static com.twilio.oai.resolver.java.JavaConventionResolver.AUTH_IMPORT_CLASS; import static com.twilio.oai.resolver.java.JavaConventionResolver.HTTP_CLASS_PREFIX; @@ -22,6 +24,8 @@ public void process(CodegenOperation codegenOperation) { @Override public boolean shouldProcess(CodegenOperation codegenOperation) { // This processor is for operations that do not require authentication - return true; + List securities = codegenOperation.authMethods; + if (securities == null || securities.isEmpty()) return true; + return false; } } diff --git a/src/main/java/com/twilio/oai/java/processor/auth/OAuth.java b/src/main/java/com/twilio/oai/java/processor/auth/OAuth.java deleted file mode 100644 index bc442c157..000000000 --- a/src/main/java/com/twilio/oai/java/processor/auth/OAuth.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.twilio.oai.java.processor.auth; - -import org.openapitools.codegen.CodegenOperation; - -// Placeholder class, OAuth is not added to security schemes. -public class OAuth implements SecuritySchemeProcessor { - - @Override - public void process(CodegenOperation codegenOperation) { - // Implement the logic to process the CodegenOperation for OAuth - // This could include setting up OAuth-specific parameters, headers, etc. - } - - // Currently we are using same classes for OAuth and Basic Authentication, Thus no differentiation required. - @Override - public boolean shouldProcess(CodegenOperation codegenOperation) { - return false; - } -} diff --git a/src/main/java/com/twilio/oai/java/processor/auth/OrgsOAuth.java b/src/main/java/com/twilio/oai/java/processor/auth/OrgsOAuth.java deleted file mode 100644 index 2090e6eb7..000000000 --- a/src/main/java/com/twilio/oai/java/processor/auth/OrgsOAuth.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.twilio.oai.java.processor.auth; - -import org.openapitools.codegen.CodegenOperation; -import org.openapitools.codegen.CodegenSecurity; - -import java.util.HashMap; -import java.util.List; - -import static com.twilio.oai.resolver.java.JavaConventionResolver.AUTH_IMPORT_CLASS; -import static com.twilio.oai.resolver.java.JavaConventionResolver.BEARER_AUTH_HTTP_CLASS_PREFIX; -import static com.twilio.oai.resolver.java.JavaConventionResolver.BEARER_AUTH_IMPORT_CLASS; -import static com.twilio.oai.resolver.java.JavaConventionResolver.HTTP_CLASS_PREFIX; - -public class OrgsOAuth implements SecuritySchemeProcessor { - - - @Override - public void process(CodegenOperation codegenOperation) { - HashMap authAttributes = new HashMap<>(); - authAttributes.put(AUTH_IMPORT_CLASS, BEARER_AUTH_IMPORT_CLASS); - authAttributes.put(HTTP_CLASS_PREFIX, BEARER_AUTH_HTTP_CLASS_PREFIX); - codegenOperation.vendorExtensions.put(authAttributesExtension, authAttributes); - } - - @Override - public boolean shouldProcess(CodegenOperation codegenOperation) { - List securities = codegenOperation.authMethods; - if (securities == null || securities.isEmpty()) return false; // No Authentication - if (securities.size() > 1) { - throw new RuntimeException("Multiple auth methods are not supported. Please use only one auth method per operation."); - } - CodegenSecurity security = securities.get(0); - return security.isOAuth; - } -} diff --git a/src/main/java/com/twilio/oai/java/processor/auth/SecuritySchemeManager.java b/src/main/java/com/twilio/oai/java/processor/auth/SecuritySchemeManager.java index 8eaba5327..6afce19a3 100644 --- a/src/main/java/com/twilio/oai/java/processor/auth/SecuritySchemeManager.java +++ b/src/main/java/com/twilio/oai/java/processor/auth/SecuritySchemeManager.java @@ -22,8 +22,7 @@ public static synchronized SecuritySchemeManager getInstance() { private SecuritySchemeManager() { this.securitySchemeProcessors = List.of( new NoAuth(), - new BasicAuth(), - new OrgsOAuth() + new Auth() ); } diff --git a/src/main/java/com/twilio/oai/java/processor/enums/property/InlinePropEnumProcessor.java b/src/main/java/com/twilio/oai/java/processor/enums/property/InlinePropEnumProcessor.java index f9351e6a3..b75568774 100644 --- a/src/main/java/com/twilio/oai/java/processor/enums/property/InlinePropEnumProcessor.java +++ b/src/main/java/com/twilio/oai/java/processor/enums/property/InlinePropEnumProcessor.java @@ -40,7 +40,7 @@ public OpenApiEnumType getType() { @Override public boolean shouldProcess(CodegenProperty codegenProperty) { - if (codegenProperty.isEnum && codegenProperty.isEnumRef && codegenProperty.get_enum() != null) { + if (codegenProperty.isEnum && !codegenProperty.isEnumRef && codegenProperty.get_enum() != null) { return true; } return false; diff --git a/src/main/java/com/twilio/oai/java/processor/responsebody/JsonResponseProcessor.java b/src/main/java/com/twilio/oai/java/processor/responsebody/JsonResponseProcessor.java index 528ce1c32..9ab982846 100644 --- a/src/main/java/com/twilio/oai/java/processor/responsebody/JsonResponseProcessor.java +++ b/src/main/java/com/twilio/oai/java/processor/responsebody/JsonResponseProcessor.java @@ -37,6 +37,8 @@ public void process(final CodegenOperation codegenOperation) { Deserializer.addDeserializer(codegenProperty); }); responseModel.vars.stream().forEach(property -> recursiveModelProcessor.process(property)); + + // Adding responseModel vars to cache responseModel.vars.forEach(ResourceCacheContext.get().getResponse()::add); } @@ -58,7 +60,7 @@ public boolean shouldProcess(final CodegenOperation codegenOperation) { System.out.println(codegenOperation.operationId); if (codegenOperation.produces != null && !codegenOperation.produces.isEmpty()) { for (Map contentType : codegenOperation.produces) { - if (getContentType().equals(contentType.get("mediaType"))) { + if (getContentType().equals(contentType.get("mediaType")) || "application/scim+json".equals(contentType.get("mediaType"))) { return true; } } @@ -79,7 +81,11 @@ private CodegenModel getModel(final CodegenOperation codegenOperation) { if (codegenResponse.is2xx || codegenResponse.is3xx) { if (codegenResponse == null || codegenResponse.getContent() == null) return null; CodegenMediaType codegenMediaType = codegenResponse.getContent().get(getContentType()); - if (codegenMediaType == null) return null; + if (codegenMediaType == null) { + codegenMediaType = codegenResponse.getContent().get("application/scim+json"); + if (codegenMediaType == null) return null; + } + if (codegenMediaType.getSchema().isContainer) { // It covers special case in which response is list // TODO: Handle in future. From 06360373a6d7176ee50a724f70088a8abcb2bc60 Mon Sep 17 00:00:00 2001 From: sbansla Date: Thu, 18 Sep 2025 15:32:21 +0530 Subject: [PATCH 25/38] added noauth changes --- src/main/java/com/twilio/oai/java/processor/auth/NoAuth.java | 1 + .../oai/java/processor/auth/SecuritySchemeProcessor.java | 1 + src/main/resources/twilio-java/common/imports.mustache | 1 + .../resources/twilio-java/creator/operationMethod.mustache | 3 +++ .../resources/twilio-java/deleter/operationMethod.mustache | 3 +++ .../resources/twilio-java/fetcher/operationMethod.mustache | 3 +++ src/main/resources/twilio-java/reader/operationMethod.mustache | 3 +++ .../resources/twilio-java/updater/operationMethod.mustache | 3 +++ 8 files changed, 18 insertions(+) diff --git a/src/main/java/com/twilio/oai/java/processor/auth/NoAuth.java b/src/main/java/com/twilio/oai/java/processor/auth/NoAuth.java index 579a48292..ab59481c4 100644 --- a/src/main/java/com/twilio/oai/java/processor/auth/NoAuth.java +++ b/src/main/java/com/twilio/oai/java/processor/auth/NoAuth.java @@ -19,6 +19,7 @@ public void process(CodegenOperation codegenOperation) { authAttributes.put(AUTH_IMPORT_CLASS, NOAUTH_IMPORT_CLASS); authAttributes.put(HTTP_CLASS_PREFIX, NOAUTH_HTTP_CLASS_PREFIX); codegenOperation.vendorExtensions.put(authAttributesExtension, authAttributes); + codegenOperation.vendorExtensions.put(noAuth, true); } @Override diff --git a/src/main/java/com/twilio/oai/java/processor/auth/SecuritySchemeProcessor.java b/src/main/java/com/twilio/oai/java/processor/auth/SecuritySchemeProcessor.java index 8c516b628..31a57bd21 100644 --- a/src/main/java/com/twilio/oai/java/processor/auth/SecuritySchemeProcessor.java +++ b/src/main/java/com/twilio/oai/java/processor/auth/SecuritySchemeProcessor.java @@ -6,6 +6,7 @@ // Set "x-auth-attributes" for different type of authentication public interface SecuritySchemeProcessor { String authAttributesExtension = "x-auth-attributes"; + String noAuth = "x-no-auth"; void process(CodegenOperation codegenOperation); boolean shouldProcess(CodegenOperation codegenOperation); } diff --git a/src/main/resources/twilio-java/common/imports.mustache b/src/main/resources/twilio-java/common/imports.mustache index 487a9f6f5..2dce9d03f 100644 --- a/src/main/resources/twilio-java/common/imports.mustache +++ b/src/main/resources/twilio-java/common/imports.mustache @@ -5,6 +5,7 @@ import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.twilio.auth_strategy.NoAuthStrategy; import com.twilio.base.Creator; import com.twilio.base.Deleter; import com.twilio.base.Fetcher; diff --git a/src/main/resources/twilio-java/creator/operationMethod.mustache b/src/main/resources/twilio-java/creator/operationMethod.mustache index c518e5cba..32496cede 100644 --- a/src/main/resources/twilio-java/creator/operationMethod.mustache +++ b/src/main/resources/twilio-java/creator/operationMethod.mustache @@ -19,6 +19,9 @@ vendorExtensions.x-content-type: content type of the request, example: applicati {{#vendorExtensions.x-request-content-type}} request.setContentType(EnumConstants.ContentType.{{vendorExtensions.x-request-content-type}}); {{/vendorExtensions.x-request-content-type}} + {{#vendorExtensions.x-no-auth}} + request.setAuth(NoAuthStrategy.getInstance()); + {{/vendorExtensions.x-no-auth}} {{#queryParams.0}} addQueryParams(request); {{/queryParams.0}} diff --git a/src/main/resources/twilio-java/deleter/operationMethod.mustache b/src/main/resources/twilio-java/deleter/operationMethod.mustache index e8a2e85f1..ba98e2ba1 100644 --- a/src/main/resources/twilio-java/deleter/operationMethod.mustache +++ b/src/main/resources/twilio-java/deleter/operationMethod.mustache @@ -19,6 +19,9 @@ vendorExtensions.x-content-type: content type of the request, example: applicati {{#vendorExtensions.x-request-content-type}} request.setContentType(EnumConstants.ContentType.{{vendorExtensions.x-request-content-type}}); {{/vendorExtensions.x-request-content-type}} + {{#vendorExtensions.x-no-auth}} + request.setAuth(NoAuthStrategy.getInstance()); + {{/vendorExtensions.x-no-auth}} {{#queryParams.0}} addQueryParams(request); {{/queryParams.0}} diff --git a/src/main/resources/twilio-java/fetcher/operationMethod.mustache b/src/main/resources/twilio-java/fetcher/operationMethod.mustache index caaee3b13..8ead0de7b 100644 --- a/src/main/resources/twilio-java/fetcher/operationMethod.mustache +++ b/src/main/resources/twilio-java/fetcher/operationMethod.mustache @@ -19,6 +19,9 @@ vendorExtensions.x-content-type: content type of the request, example: applicati {{#vendorExtensions.x-request-content-type}} request.setContentType(EnumConstants.ContentType.{{vendorExtensions.x-request-content-type}}); {{/vendorExtensions.x-request-content-type}} + {{#vendorExtensions.x-no-auth}} + request.setAuth(NoAuthStrategy.getInstance()); + {{/vendorExtensions.x-no-auth}} {{#queryParams.0}} addQueryParams(request); {{/queryParams.0}} diff --git a/src/main/resources/twilio-java/reader/operationMethod.mustache b/src/main/resources/twilio-java/reader/operationMethod.mustache index 5acc99074..7dea9b5d8 100644 --- a/src/main/resources/twilio-java/reader/operationMethod.mustache +++ b/src/main/resources/twilio-java/reader/operationMethod.mustache @@ -16,6 +16,9 @@ domainName: example api, video, chat, etc. These can be found in Domains.java in Domains.{{#lambda.uppercase}}{{domainName}}{{/lambda.uppercase}}.toString(), path ); + {{#vendorExtensions.x-no-auth}} + request.setAuth(NoAuthStrategy.getInstance()); + {{/vendorExtensions.x-no-auth}} {{#queryParams.0}} addQueryParams(request); {{/queryParams.0}} diff --git a/src/main/resources/twilio-java/updater/operationMethod.mustache b/src/main/resources/twilio-java/updater/operationMethod.mustache index 4e9d7bfb6..6744cbbc4 100644 --- a/src/main/resources/twilio-java/updater/operationMethod.mustache +++ b/src/main/resources/twilio-java/updater/operationMethod.mustache @@ -19,6 +19,9 @@ vendorExtensions.x-content-type: content type of the request, example: applicati {{#vendorExtensions.x-request-content-type}} request.setContentType(EnumConstants.ContentType.{{vendorExtensions.x-request-content-type}}); {{/vendorExtensions.x-request-content-type}} + {{#vendorExtensions.x-no-auth}} + request.setAuth(NoAuthStrategy.getInstance()); + {{/vendorExtensions.x-no-auth}} {{#queryParams.0}} addQueryParams(request); {{/queryParams.0}} From 3f928500dc1dabe9f9fd51beda1236e8bb53c29f Mon Sep 17 00:00:00 2001 From: sbansla Date: Thu, 18 Sep 2025 18:09:54 +0530 Subject: [PATCH 26/38] removed noauth unused extensions --- src/main/java/com/twilio/oai/java/processor/auth/Auth.java | 4 ---- src/main/java/com/twilio/oai/java/processor/auth/NoAuth.java | 4 ---- 2 files changed, 8 deletions(-) diff --git a/src/main/java/com/twilio/oai/java/processor/auth/Auth.java b/src/main/java/com/twilio/oai/java/processor/auth/Auth.java index 02c29b6da..be584e029 100644 --- a/src/main/java/com/twilio/oai/java/processor/auth/Auth.java +++ b/src/main/java/com/twilio/oai/java/processor/auth/Auth.java @@ -12,10 +12,6 @@ public class Auth implements SecuritySchemeProcessor { @Override public void process(CodegenOperation codegenOperation) { - HashMap authAttributes = new HashMap<>(); - authAttributes.put(AUTH_IMPORT_CLASS, ""); - authAttributes.put(HTTP_CLASS_PREFIX, ""); - codegenOperation.vendorExtensions.put(authAttributesExtension, authAttributes); } @Override diff --git a/src/main/java/com/twilio/oai/java/processor/auth/NoAuth.java b/src/main/java/com/twilio/oai/java/processor/auth/NoAuth.java index ab59481c4..b2623af32 100644 --- a/src/main/java/com/twilio/oai/java/processor/auth/NoAuth.java +++ b/src/main/java/com/twilio/oai/java/processor/auth/NoAuth.java @@ -15,10 +15,6 @@ public class NoAuth implements SecuritySchemeProcessor { @Override public void process(CodegenOperation codegenOperation) { - HashMap authAttributes = new HashMap<>(); - authAttributes.put(AUTH_IMPORT_CLASS, NOAUTH_IMPORT_CLASS); - authAttributes.put(HTTP_CLASS_PREFIX, NOAUTH_HTTP_CLASS_PREFIX); - codegenOperation.vendorExtensions.put(authAttributesExtension, authAttributes); codegenOperation.vendorExtensions.put(noAuth, true); } From 3872c9a21cb65327682ec216397a57682cc76203 Mon Sep 17 00:00:00 2001 From: sbansla Date: Sat, 20 Sep 2025 14:44:21 +0530 Subject: [PATCH 27/38] refactored constructor generator to use path, query, header param instead of requiredParams --- specs_test/test_spec/twilio_oneOf_v1.yaml | 58 +++++ .../constructor/ConstructorGenerator.java | 45 ---- .../constructor/JsonConstructorGenerator.java | 74 +++--- .../UrlencodedBodyConstructorGenerator.java | 215 ++++++++---------- .../parameter/ParameterProcessor.java | 10 +- .../requestbody/JsonRequestProcessor.java | 34 ++- 6 files changed, 223 insertions(+), 213 deletions(-) diff --git a/specs_test/test_spec/twilio_oneOf_v1.yaml b/specs_test/test_spec/twilio_oneOf_v1.yaml index 831bf8a24..7ca5d6e85 100644 --- a/specs_test/test_spec/twilio_oneOf_v1.yaml +++ b/specs_test/test_spec/twilio_oneOf_v1.yaml @@ -13,6 +13,22 @@ info: servers: - url: https://oneOf.twilio.com paths: + /v1/owners: + post: + operationId: CreateOwner + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/Owner' + responses: + '200': + description: Returns the created pet (cat or dog) + content: + application/json: + schema: + $ref: '#/components/schemas/Cat' /v1/pets: post: operationId: CreatePet @@ -22,6 +38,38 @@ paths: content: application/json: schema: + oneOf: + - type: object + required: [ name, livesLeft ] + properties: + name: + type: string + example: "Kitty" + livesLeft: + type: integer + example: 9 + description: "Cat object (inline)" + - type: object + required: [ name, breed ] + properties: + name: + type: string + example: "Bruno" + breed: + type: string + example: "Labrador" + description: "Dog object (inline)" + - type: object + required: [ name, wingSpan ] + properties: + name: + type: string + example: "Tweety" + wingSpan: + type: number + format: float + example: 25.5 + description: "Bird object (inline)" # properties: # RecordingStatusCallback: # format: uri @@ -56,6 +104,16 @@ paths: components: schemas: + Owner: + type: object + required: [ ownerName, pet ] + properties: + ownerName: + type: string + pet: + oneOf: + - $ref: '#/components/schemas/Cat' + - $ref: '#/components/schemas/Dog' MyPet_Response: type: object properties: diff --git a/src/main/java/com/twilio/oai/java/feature/constructor/ConstructorGenerator.java b/src/main/java/com/twilio/oai/java/feature/constructor/ConstructorGenerator.java index 9947eaf26..cb79f541a 100644 --- a/src/main/java/com/twilio/oai/java/feature/constructor/ConstructorGenerator.java +++ b/src/main/java/com/twilio/oai/java/feature/constructor/ConstructorGenerator.java @@ -13,49 +13,4 @@ public abstract class ConstructorGenerator { abstract void apply(CodegenOperation codegenOperation); abstract boolean shouldApply(CodegenOperation codegenOperation); - - public List> getConditionalParameters(CodegenOperation codegenOperation) { - List> conditionalCodegenParam = new ArrayList<>(); - - if (codegenOperation.vendorExtensions.containsKey("x-twilio")) { - HashMap twilioVendorExtension = (HashMap) codegenOperation.vendorExtensions.get("x-twilio"); - if (twilioVendorExtension.containsKey("conditional")) { - List> conditionalParamDoubleList = (List>) twilioVendorExtension.get("conditional"); - - // Look for conditional parameters in body - // Add to conditionalCodegenParam from conditionalParamDoubleList - lookForConditionalParameterInBody(conditionalParamDoubleList, conditionalCodegenParam, codegenOperation); - - // Remove similar datatype parameters because they will create same constructors - List> filteredConditionalCodegenParam = new ArrayList<>(); - for (List cpList : conditionalCodegenParam) { - if (cpList.size() <= 1 || !cpList.get(0).dataType.equals(cpList.get(1).dataType)) { - filteredConditionalCodegenParam.add(cpList); - } - } - conditionalCodegenParam = filteredConditionalCodegenParam; } - } - - return conditionalCodegenParam; - } - - /* - The `conditionalParameterDoubleList` contains combinations of constructors derived solely from conditional parameters. - It is necessary to filter out constructors with similar parameter combinations to ensure uniqueness. - */ - public List> filterConditionalParametersByDatatype(List> conditionalParameterDoubleList) { - List> filteredConditionalCodegenParam = new ArrayList<>(); - HashSet> signatureHashSet = new HashSet<>(); - for (List paramList : conditionalParameterDoubleList) { - List orderedParamList = paramList.stream().map(p -> p.dataType).collect(Collectors.toList()); - if (signatureHashSet.add(orderedParamList)) { - filteredConditionalCodegenParam.add(paramList); - } - } - return filteredConditionalCodegenParam; - } - - // Look for conditional parameters in body - abstract void lookForConditionalParameterInBody(List> conditionalParamDoubleList, - List> conditionalCodegenParam, CodegenOperation codegenOperation); } diff --git a/src/main/java/com/twilio/oai/java/feature/constructor/JsonConstructorGenerator.java b/src/main/java/com/twilio/oai/java/feature/constructor/JsonConstructorGenerator.java index d9646ed7e..38761f549 100644 --- a/src/main/java/com/twilio/oai/java/feature/constructor/JsonConstructorGenerator.java +++ b/src/main/java/com/twilio/oai/java/feature/constructor/JsonConstructorGenerator.java @@ -26,7 +26,7 @@ public void apply(CodegenOperation codegenOperation) { List> constructors = generateSignatureListModern(codegenOperation); - codegenOperation.vendorExtensions.put(SIGNATURE_LIST, generateSignatureListModern(codegenOperation)); + codegenOperation.vendorExtensions.put(SIGNATURE_LIST, constructors); } @@ -41,50 +41,50 @@ public boolean shouldApply(CodegenOperation codegenOperation) { } public List> generateSignatureListModern(final CodegenOperation codegenOperation) { - List requiredParams = codegenOperation.requiredParams; - // This is required because requiredParams are not resolved. - //applyDataTypeToBodyParams(requiredParams); - CodegenParameter accountSidParam = null; - Optional optionalParam = codegenOperation.pathParams.stream() - .filter(param -> param.vendorExtensions.containsKey(ACCOUNT_SID_VEND_EXT)).findAny(); - if(optionalParam.isPresent()){ - accountSidParam = optionalParam.get(); - } + // Step 1 + List requiredParams = getRequiredParameters(codegenOperation); + // Step 2 + CodegenParameter accountSidParam = getAccountSidParameter(codegenOperation); + // Step 3 + List> listOfConstructors = combineParameters(requiredParams, accountSidParam); + return listOfConstructors; + } - List> conditionalParameterDoubleList = getConditionalParameters(codegenOperation); - conditionalParameterDoubleList = Lists.cartesianProduct(conditionalParameterDoubleList); - // conditionalParameterDoubleList contains list of constructors only from conditional parameters - // We need to filter out similar constructors. - List> filteredConditionalCodegenParam = filterConditionalParametersByDatatype(conditionalParameterDoubleList); + private List getRequiredParameters(CodegenOperation codegenOperation) { + List requiredParams; + requiredParams = codegenOperation.pathParams.stream() + .filter(param -> !param.vendorExtensions.containsKey(ACCOUNT_SID_VEND_EXT)) + .collect(Collectors.toList()); + requiredParams.addAll(codegenOperation.queryParams.stream() + .filter(param -> param.required) + .collect(Collectors.toList())); + requiredParams.addAll(codegenOperation.bodyParams.stream() + .filter(param -> param.required) + .collect(Collectors.toList())); + requiredParams.addAll(codegenOperation.headerParams.stream() + .filter(param -> param.required) + .collect(Collectors.toList())); + return requiredParams; + } - // Combine required and conditional parameters to form the signature list + private CodegenParameter getAccountSidParameter(CodegenOperation codegenOperation) { + return codegenOperation.pathParams.stream() + .filter(param -> param.vendorExtensions.containsKey(ACCOUNT_SID_VEND_EXT)) + .findAny() + .orElse(null); + } + private List> combineParameters(List requiredParams, CodegenParameter accountSidParam) { List> signatureList = new ArrayList<>(); - for(List paramList : filteredConditionalCodegenParam){ - signatureList.add(addAllToList(codegenOperation.requiredParams, paramList)); - if( accountSidParam != null) { - signatureList.add(addAllToList(List.of(accountSidParam), requiredParams, paramList)); - } + signatureList.add(addAllToList(requiredParams)); + if (accountSidParam != null) { + signatureList.add(addAllToList(List.of(accountSidParam), requiredParams)); } return signatureList; } - private void applyDataTypeToBodyParams(List requiredParams) { - requiredParams.forEach(param -> { - if (param.isBodyParam) { - param.dataType = ResourceCacheContext.get().getResourceName() + DOT + param.dataType; - } - }); - } - - public void lookForConditionalParameterInBody(List> conditionalParamDoubleList, - List> conditionalCodegenParam, CodegenOperation codegenOperation) { -// conditionalParamDoubleList.stream().map( -// paramList -> paramList.stream().map( -// cp -> codegenOperation.bodyParams.get(0).filter( -// op -> op.name.equals(StringHelper.camelize(cp, true)) -// ).findAny().get() -// ).collect(Collectors.toList())).collect(Collectors.toList()); + public List> lookForConditionalParameterInBody(List> conditionalParamDoubleList, CodegenOperation codegenOperation) { + return new ArrayList<>(); } private List addAllToList(List... lists) { diff --git a/src/main/java/com/twilio/oai/java/feature/constructor/UrlencodedBodyConstructorGenerator.java b/src/main/java/com/twilio/oai/java/feature/constructor/UrlencodedBodyConstructorGenerator.java index 28110d9bf..ef57795d8 100644 --- a/src/main/java/com/twilio/oai/java/feature/constructor/UrlencodedBodyConstructorGenerator.java +++ b/src/main/java/com/twilio/oai/java/feature/constructor/UrlencodedBodyConstructorGenerator.java @@ -2,6 +2,7 @@ import com.google.common.collect.Lists; import com.twilio.oai.StringHelper; +import org.checkerframework.checker.units.qual.A; import org.openapitools.codegen.CodegenOperation; import org.openapitools.codegen.CodegenParameter; @@ -24,7 +25,6 @@ public class UrlencodedBodyConstructorGenerator extends ConstructorGenerator { public void apply(CodegenOperation codegenOperation) { codegenOperation.vendorExtensions.put("x-java-constructor", true); codegenOperation.vendorExtensions.put(SIGNATURE_LIST, generateSignatureListModern(codegenOperation)); - System.out.println(codegenOperation.vendorExtensions.get(SIGNATURE_LIST)); } public boolean shouldApply(CodegenOperation codegenOperation) { @@ -38,11 +38,102 @@ public boolean shouldApply(CodegenOperation codegenOperation) { .anyMatch(mediaType -> mediaType.get("mediaType").equals("application/x-www-form-urlencoded")); return shouldApply; } + + /* + Steps: + 1. Get required parameters from path, query, header, body except accountSid + 2. Get accountSid parameter from path if exists + 3. Get conditional parameters from body + 4. Get cartesian product of conditional parameters + 5. Filter out similar datatype parameters because they will create same constructors + 6. Combine required and conditional parameters to form the signature list + 7. If accountSid exists, add it to the beginning of each signature + 8. Return the signature list + */ + public List> generateSignatureListModern(final CodegenOperation codegenOperation) { + // Step 1 + List requiredParams = getRequiredParameters(codegenOperation); + // Step 2 + CodegenParameter accountSidParam = getAccountSidParameter(codegenOperation); + // Step 3 + List> conditionalParameters = getConditionalParameters(codegenOperation); + // Step 4 + List> cartesianProducts = Lists.cartesianProduct(conditionalParameters); + // Step 5 + List> filteredConditionalCodegenParam = filterConditionalParameters(cartesianProducts); + // Step 6 + List> listOfConstructors = combineParameters(requiredParams, filteredConditionalCodegenParam, accountSidParam); + return listOfConstructors; + } + + private List getRequiredParameters(CodegenOperation codegenOperation) { + List requiredParams; + requiredParams = codegenOperation.pathParams.stream() + .filter(param -> !param.vendorExtensions.containsKey(ACCOUNT_SID_VEND_EXT)) + .collect(Collectors.toList()); + requiredParams.addAll(codegenOperation.queryParams.stream() + .filter(param -> param.required) + .collect(Collectors.toList())); + requiredParams.addAll(codegenOperation.formParams.stream() + .filter(param -> param.required) + .collect(Collectors.toList())); + requiredParams.addAll(codegenOperation.headerParams.stream() + .filter(param -> param.required) + .collect(Collectors.toList())); + return requiredParams; + } + private CodegenParameter getAccountSidParameter(CodegenOperation codegenOperation) { + return codegenOperation.pathParams.stream() + .filter(param -> param.vendorExtensions.containsKey(ACCOUNT_SID_VEND_EXT)) + .findAny() + .orElse(null); + } + public List> getConditionalParameters(CodegenOperation codegenOperation) { + List> conditionalParamDoubleList = new ArrayList<>(); + try { + conditionalParamDoubleList = (List>) ((HashMap) codegenOperation.vendorExtensions.get("x-twilio")).get("conditional"); + } catch (NullPointerException nullPointerException) { + // skip list do not exist. + } + if (conditionalParamDoubleList == null || conditionalParamDoubleList.isEmpty()) { + return List.of(); + } + List> conditionalCodegenParam = lookForConditionalParameterInBody(conditionalParamDoubleList, codegenOperation); + return conditionalCodegenParam; + } + + /* + * The `conditionalParameterDoubleList` contains combinations of constructors derived solely from conditional parameters. + * It is necessary to filter out constructors with similar parameter combinations to ensure uniqueness. + */ + public List> filterConditionalParameters(List> conditionalParams) { + List> filteredConditionalCodegenParam = new ArrayList<>(); + HashSet> signatureHashSet = new HashSet<>(); + for (List paramList : conditionalParams) { + List orderedParamList = paramList.stream().map(p -> p.dataType).collect(Collectors.toList()); + if (signatureHashSet.add(orderedParamList)) { + filteredConditionalCodegenParam.add(paramList); + } + } + return filteredConditionalCodegenParam; + } - public void lookForConditionalParameterInBody(List> conditionalParamDoubleList, - List> conditionalCodegenParam, CodegenOperation codegenOperation) { + private List> combineParameters(List requiredParams, + List> filteredConditionalCodegenParam, + CodegenParameter accountSidParam) { + List> signatureList = new ArrayList<>(); + for (List paramList : filteredConditionalCodegenParam) { + signatureList.add(addAllToList(requiredParams, paramList)); + if (accountSidParam != null) { + signatureList.add(addAllToList(List.of(accountSidParam), requiredParams, paramList)); + } + } + return signatureList; + } + public List> lookForConditionalParameterInBody(List> conditionalParamDoubleList, CodegenOperation codegenOperation) { + List> conditionalCodegenParam = new ArrayList<>(); for (List conditionalParamList : conditionalParamDoubleList) { List foundParameters = new ArrayList<>(); for (String cp : conditionalParamList) { @@ -62,129 +153,13 @@ public void lookForConditionalParameterInBody(List> conditionalPara } conditionalCodegenParam.add(foundParameters); } - } - - public List> generateSignatureListModern(final CodegenOperation codegenOperation) { - List requiredParams = codegenOperation.requiredParams; - - CodegenParameter accountSidParam = null; - Optional optionalParam = codegenOperation.pathParams.stream() - .filter(param -> param.vendorExtensions.containsKey(ACCOUNT_SID_VEND_EXT)).findAny(); - if(optionalParam.isPresent()){ - accountSidParam = optionalParam.get(); - } - - List> conditionalParameterDoubleList = getConditionalParameters(codegenOperation); - conditionalParameterDoubleList = Lists.cartesianProduct(conditionalParameterDoubleList); - // conditionalParameterDoubleList contains list of constructors only from conditional parameters - // We need to filter out similar constructors. - List> filteredConditionalCodegenParam = filterConditionalParametersByDatatype(conditionalParameterDoubleList); - - // Combine required and conditional parameters to form the signature list - List> signatureList = new ArrayList<>(); - for(List paramList : filteredConditionalCodegenParam){ - signatureList.add(addAllToList(codegenOperation.requiredParams, paramList)); - if( accountSidParam != null) { - signatureList.add(addAllToList(List.of(accountSidParam), requiredParams, paramList)); - } - } - return signatureList; + return conditionalCodegenParam; } @SafeVarargs private final List mergeLists(List... lists) { return Arrays.stream(lists).flatMap(List::stream).collect(Collectors.toList()); } - - - -// private List> getConditionalParameters(CodegenOperation codegenOperation) { -// List> conditionalCodegenParam = new ArrayList<>(); -// -// if (codegenOperation.vendorExtensions.containsKey("x-twilio")) { -// HashMap twilioVendorExtension = (HashMap) codegenOperation.vendorExtensions.get("x-twilio"); -// if (twilioVendorExtension.containsKey("conditional")) { -// List> conditionalParamDoubleList = (List>) twilioVendorExtension.get("conditional"); -// -// // Look for conditional parameters in body -// for (List conditionalParamList : conditionalParamDoubleList) { -// List foundParameters = new ArrayList<>(); -// for (String cp : conditionalParamList) { -// CodegenParameter matchedParam = null; -// for (CodegenParameter formParam : codegenOperation.formParams) { -// if (!formParam.required -// && StringHelper.camelize(formParam.baseName, true) -// .equals(StringHelper.camelize(cp, true))) { -// matchedParam = formParam; -// break; -// } -// } -// if (matchedParam == null) { -// throw new IllegalArgumentException("Parameter not found: " + cp); -// } -// foundParameters.add(matchedParam); -// } -// conditionalCodegenParam.add(foundParameters); -// } -// -// // Remove similar datatype parameters because they will create same constructors -// List> filteredConditionalCodegenParam = new ArrayList<>(); -// for (List cpList : conditionalCodegenParam) { -// if (cpList.size() <= 1 || !cpList.get(0).dataType.equals(cpList.get(1).dataType)) { -// filteredConditionalCodegenParam.add(cpList); -// } -// } -// conditionalCodegenParam = filteredConditionalCodegenParam; } -// } -// -// return conditionalCodegenParam; -// } - - public ArrayList> generateSignatureList(final CodegenOperation co) { - CodegenParameter accountSidParam = null; - List> conditionalCodegenParam = new ArrayList<>(); - Optional optionalParam = co.allParams.stream() - .filter(param -> param.vendorExtensions.containsKey("x-account-sid")).findAny(); - if (optionalParam.isPresent()) { - accountSidParam = optionalParam.get(); - } - - if (co.vendorExtensions.containsKey("x-twilio")) { - HashMap twilioVendorExtension = (HashMap) co.vendorExtensions.get("x-twilio"); - if (twilioVendorExtension.containsKey("conditional")) { - List> conditionalParams = (List>) twilioVendorExtension.get("conditional"); - conditionalCodegenParam = conditionalParams.stream().map( - paramList -> paramList.stream().map( - cp -> co.optionalParams.stream().filter( - op -> op.paramName.equals(cp) - ).findAny().get() - ).collect(Collectors.toList())).collect(Collectors.toList()); - conditionalCodegenParam = conditionalCodegenParam.stream() - .filter(cpList -> (cpList.size() <= 1 || !cpList.get(0).dataType.equals(cpList.get(1).dataType))) - .collect(Collectors.toList()); - } - } - - conditionalCodegenParam = Lists.cartesianProduct(conditionalCodegenParam); - List> filteredConditionalCodegenParam = new ArrayList<>(); - HashSet> signatureHashSet = new HashSet<>(); - for (List paramList : conditionalCodegenParam) { - List orderedParamList = paramList.stream().map(p -> p.dataType).collect(Collectors.toList()); - if (!signatureHashSet.contains(orderedParamList)) { - filteredConditionalCodegenParam.add(paramList); - signatureHashSet.add(orderedParamList); - } - } - - ArrayList> signatureList = new ArrayList<>(); - for (List paramList : filteredConditionalCodegenParam) { - signatureList.add(addAllToList(co.requiredParams, paramList)); - if (accountSidParam != null) { - signatureList.add(addAllToList(List.of(accountSidParam), co.requiredParams, paramList)); - } - } - return signatureList; - } private List addAllToList(List... lists) { return Arrays.stream(lists).flatMap(List::stream).collect(Collectors.toList()); diff --git a/src/main/java/com/twilio/oai/java/processor/parameter/ParameterProcessor.java b/src/main/java/com/twilio/oai/java/processor/parameter/ParameterProcessor.java index 7fadcc98a..9072f6649 100644 --- a/src/main/java/com/twilio/oai/java/processor/parameter/ParameterProcessor.java +++ b/src/main/java/com/twilio/oai/java/processor/parameter/ParameterProcessor.java @@ -1,6 +1,7 @@ package com.twilio.oai.java.processor.parameter; import com.twilio.oai.java.processor.enums.EnumProcessorFactory; +import org.apache.commons.lang3.StringUtils; import org.openapitools.codegen.CodegenOperation; /* @@ -23,15 +24,18 @@ public static synchronized ParameterProcessor getInstance() { public void process(final CodegenOperation codegenOperation) { codegenOperation.pathParams.forEach(param -> { - param.paramName = "path" + param.paramName; + String capitalized = StringUtils.capitalize(param.paramName); + param.paramName = "path" + capitalized; }); codegenOperation.allParams.stream().filter(param -> param.isPathParam).forEach(param -> { - param.paramName = "path" + param.paramName; + String capitalized = StringUtils.capitalize(param.paramName); + param.paramName = "path" + capitalized; }); codegenOperation.requiredParams.stream().filter(param -> param.isPathParam).forEach(param -> { - param.paramName = "path" + param.paramName; + String capitalized = StringUtils.capitalize(param.paramName); + param.paramName = "path" + capitalized; }); codegenOperation.queryParams.forEach(param -> enumProcessorFactory.applyProcessor(param)); diff --git a/src/main/java/com/twilio/oai/java/processor/requestbody/JsonRequestProcessor.java b/src/main/java/com/twilio/oai/java/processor/requestbody/JsonRequestProcessor.java index ed4509aa5..5015d58a0 100644 --- a/src/main/java/com/twilio/oai/java/processor/requestbody/JsonRequestProcessor.java +++ b/src/main/java/com/twilio/oai/java/processor/requestbody/JsonRequestProcessor.java @@ -2,6 +2,10 @@ import com.twilio.oai.LoggerUtil; import org.openapitools.codegen.CodegenOperation; +import org.openapitools.codegen.CodegenParameter; +import org.openapitools.codegen.CodegenProperty; + +import java.util.List; import static com.twilio.oai.common.ApplicationConstants.X_REQUEST_CONTENT_TYPE; import static com.twilio.oai.java.constants.MustacheConstants.X_REQUEST_LANGUAGE_CONTENT_TYPE_CONSTANT; @@ -28,19 +32,33 @@ public void process(CodegenOperation codegenOperation) { codegenOperation.vendorExtensions.put(X_REQUEST_CONTENT_TYPE, getContentType()); codegenOperation.vendorExtensions.put(X_REQUEST_CONTENT_TYPE, getContentType()); codegenOperation.vendorExtensions.put(X_REQUEST_LANGUAGE_CONTENT_TYPE_CONSTANT, "JSON"); - System.out.println(codegenOperation.operationId); if (!codegenOperation.getHasBodyParam()) return; - if (codegenOperation.bodyParams.size() > 1) { + List bodyParams = codegenOperation.bodyParams; + if (bodyParams.size() > 1) { LoggerUtil.logSevere(this.getClass().getName(), "Multiple request bodies found " + codegenOperation.operationId); } - - processParameter(codegenOperation); -// if (codegenOperation.bodyParam.vars != null && codegenOperation.bodyParam.vars.size() > 0) { -// processProperty(codegenOperation); -// } else { -// processParameter(codegenOperation); +// if (codegenOperation.bodyParams != null && !codegenOperation.bodyParams.isEmpty() && codegenOperation.bodyParams.get(0).isOneOf) { +// processOneOf(codegenOperation); +// return; // } + + if (bodyParams.get(0).vars != null && !bodyParams.get(0).vars.isEmpty()) { + processProperty(codegenOperation); + } else { + processOneOf(codegenOperation); + } + } + + public void processOneOf(CodegenOperation codegenOperation) { + System.out.println(codegenOperation.bodyParams); + CodegenParameter codegenParameter = codegenOperation.bodyParams.get(0); + if (codegenParameter.getContent() != null && codegenParameter.getContent().get("application/json") != null) { + CodegenProperty codegenProperty = codegenParameter.getContent().get("application/json").getSchema(); + if (codegenProperty != null) { + recursiveModelProcessor.process(codegenProperty); + } + } } @Override From 2807d6064b8d9aaae0fd29e737ddb449d568df68 Mon Sep 17 00:00:00 2001 From: sbansla Date: Wed, 24 Sep 2025 10:53:38 +0530 Subject: [PATCH 28/38] fixed Endpoint and Twiml data types --- .../java/format/OpenApiSpecFormatFeatureConstants.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/twilio/oai/java/format/OpenApiSpecFormatFeatureConstants.java b/src/main/java/com/twilio/oai/java/format/OpenApiSpecFormatFeatureConstants.java index b6ecdab36..b36283a16 100644 --- a/src/main/java/com/twilio/oai/java/format/OpenApiSpecFormatFeatureConstants.java +++ b/src/main/java/com/twilio/oai/java/format/OpenApiSpecFormatFeatureConstants.java @@ -49,17 +49,20 @@ final static Map getPredefinedTypeMappings() { predefinedTypeMappings.put("string+phone-number", "com.twilio.type.PhoneNumber"); predefinedTypeMappings.put("com.twilio.type.PhoneNumber", "com.twilio.type.PhoneNumber"); + predefinedTypeMappings.put("string+endpoint", "com.twilio.type.Endpoint"); + predefinedTypeMappings.put("com.twilio.type.Endpoint", "com.twilio.type.Endpoint"); + predefinedTypeMappings.put("string+twiml", "com.twilio.type.Twiml"); + predefinedTypeMappings.put("com.twilio.type.Twiml", "com.twilio.type.Twiml"); + + predefinedTypeMappings.put("string+uri", "URI"); predefinedTypeMappings.put("string+url", "URI"); predefinedTypeMappings.put("string+currency", "Currency"); predefinedTypeMappings.put("string+date-time", "ZonedDateTime"); predefinedTypeMappings.put("string+date", "LocalDate"); //predefinedTypeMappings.put("LocalDate", "LocalDate"); - predefinedTypeMappings.put("string+endpoint", "Endpoint"); predefinedTypeMappings.put("string+http-method", "HttpMethod"); - predefinedTypeMappings.put("string+twiml", "Twiml"); predefinedTypeMappings.put("string+date-time-rfc-2822", "ZonedDateTime"); - predefinedTypeMappings.put("object+ice-server", "IceServer"); predefinedTypeMappings.put("object+subscribe-rule", "SubscribeRule"); predefinedTypeMappings.put("object+recording-rule", "RecordingRule"); From c1abd8a2c7aa0be53c0e93fc169cfe45a8a909a3 Mon Sep 17 00:00:00 2001 From: sbansla Date: Wed, 24 Sep 2025 11:51:12 +0530 Subject: [PATCH 29/38] fixed uri promoters --- .../oai/java/format/OpenApiSpecFormatFeatureConstants.java | 6 +++--- src/main/java/com/twilio/oai/java/format/Promoter.java | 3 +++ 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/twilio/oai/java/format/OpenApiSpecFormatFeatureConstants.java b/src/main/java/com/twilio/oai/java/format/OpenApiSpecFormatFeatureConstants.java index b36283a16..044188da5 100644 --- a/src/main/java/com/twilio/oai/java/format/OpenApiSpecFormatFeatureConstants.java +++ b/src/main/java/com/twilio/oai/java/format/OpenApiSpecFormatFeatureConstants.java @@ -9,16 +9,16 @@ public class OpenApiSpecFormatFeatureConstants { /* - * inputType -> Customer will provide inputType. - * promoter -> Promoter will use this to convert the inputType to the desired type. * key (format) -> The key is the format defined in the OpenAPI Spec. + * inputType -> Customer will provide inputType. + * promoter -> Promoter will use this to convert the inputType to the desired type. * * This can be applied to setters. For example, if a query parameter is of the format "phone-number", * two setters will be created: one for `PhoneNumber` and another for `String`. * The promoter logic will be applied to the `String` setter. */ public final static Map PROMOTIONS = Map.of( - "url", new Promotion("String", "Promoter.uriFromString({})"), + "uri", new Promotion("String", "Promoter.uriFromString({})"), "phone-number", new Promotion("String", "Promoter.phoneNumberFromString({})"), "twiml", new Promotion("String", "Promoter.twimlFromString({})") ); diff --git a/src/main/java/com/twilio/oai/java/format/Promoter.java b/src/main/java/com/twilio/oai/java/format/Promoter.java index 7d6547ef7..4aa8f180e 100644 --- a/src/main/java/com/twilio/oai/java/format/Promoter.java +++ b/src/main/java/com/twilio/oai/java/format/Promoter.java @@ -32,6 +32,7 @@ public static void addPromoter(final CodegenParameter codegenParameter) { public static void addPromoter(final CodegenOperation codegenOperation) { //List setterParameters = codegenOperation.allParams.stream().filter(param -> !param.isPathParam).collect(Collectors.toList()); + // Add promoter to following input variables. List setterParameters = new ArrayList<>(codegenOperation.bodyParams); setterParameters.addAll(codegenOperation.formParams); setterParameters.addAll(codegenOperation.queryParams); @@ -39,3 +40,5 @@ public static void addPromoter(final CodegenOperation codegenOperation) { setterParameters.forEach(param -> addPromoter(param)); } } + + From 65e6d1ff5ca4c2b4226e6451d3ac85d05e0a7ea7 Mon Sep 17 00:00:00 2001 From: sbansla Date: Wed, 24 Sep 2025 15:01:50 +0530 Subject: [PATCH 30/38] fixed constructor generation due to similar data types --- .../constructor/UrlencodedBodyConstructorGenerator.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main/java/com/twilio/oai/java/feature/constructor/UrlencodedBodyConstructorGenerator.java b/src/main/java/com/twilio/oai/java/feature/constructor/UrlencodedBodyConstructorGenerator.java index ef57795d8..d8760a54e 100644 --- a/src/main/java/com/twilio/oai/java/feature/constructor/UrlencodedBodyConstructorGenerator.java +++ b/src/main/java/com/twilio/oai/java/feature/constructor/UrlencodedBodyConstructorGenerator.java @@ -100,6 +100,9 @@ public List> getConditionalParameters(CodegenOperation co return List.of(); } List> conditionalCodegenParam = lookForConditionalParameterInBody(conditionalParamDoubleList, codegenOperation); + + // added filter to prevent same signature types + conditionalCodegenParam = conditionalCodegenParam.stream().filter(cpList -> (cpList.size() <=1 || !cpList.get(0).dataType.equals(cpList.get(1).dataType))).collect(Collectors.toList()); return conditionalCodegenParam; } From 0a3db3d41d8d797a2eb56450da4c7ac13e858389 Mon Sep 17 00:00:00 2001 From: sbansla Date: Thu, 25 Sep 2025 11:30:23 +0530 Subject: [PATCH 31/38] fixed Enum datatype is getting appended by resource name multiple times --- src/main/java/com/twilio/oai/common/Utility.java | 12 ++++++++++++ .../parameter/body/ReusableBodyEnumProcessor.java | 4 ++-- .../body/ReusableBodyListEnumProcessor.java | 3 ++- .../param/ReusableListParamEnumProcessor.java | 3 ++- .../parameter/param/ReusableParamEnumProcessor.java | 3 +-- .../property/ReusableListPropEnumProcessor.java | 3 ++- .../enums/property/ReusablePropEnumProcessor.java | 4 ++-- 7 files changed, 23 insertions(+), 9 deletions(-) diff --git a/src/main/java/com/twilio/oai/common/Utility.java b/src/main/java/com/twilio/oai/common/Utility.java index 23d99fd6b..891562731 100644 --- a/src/main/java/com/twilio/oai/common/Utility.java +++ b/src/main/java/com/twilio/oai/common/Utility.java @@ -24,6 +24,7 @@ import org.openapitools.codegen.model.ModelsMap; import static com.twilio.oai.common.ApplicationConstants.ARRAY; +import static com.twilio.oai.common.ApplicationConstants.DOT; import static com.twilio.oai.common.ApplicationConstants.OBJECT; @UtilityClass @@ -191,6 +192,17 @@ public static String replaceDatatypeInContainer(String input, String replacement return input; } + public static String appendResourceNameToEnum(String name) { + if (name == null || name.isEmpty()) { + return null; + } + String prefix = ResourceCacheContext.get().getResourceName() + DOT; + if (name.startsWith(prefix)) { + return name; + } + return prefix + com.twilio.oai.common.StringUtils.toPascalCase(name); + } + public static String getEnumNameFromRef(final String ref) { String schemaName = ref.replaceFirst("#/components/schemas/", ""); String[] enumNameArray = schemaName.split("_enum_"); diff --git a/src/main/java/com/twilio/oai/java/processor/enums/parameter/body/ReusableBodyEnumProcessor.java b/src/main/java/com/twilio/oai/java/processor/enums/parameter/body/ReusableBodyEnumProcessor.java index 8d74ca741..253d31db9 100644 --- a/src/main/java/com/twilio/oai/java/processor/enums/parameter/body/ReusableBodyEnumProcessor.java +++ b/src/main/java/com/twilio/oai/java/processor/enums/parameter/body/ReusableBodyEnumProcessor.java @@ -58,8 +58,8 @@ private void variableName(CodegenParameter codegenParameter) { codegenParameter.vendorExtensions.put(X_VARIABLE_NAME, StringUtils.toCamelCase(codegenParameter.baseName)); } private void datatype(CodegenParameter codegenParameter) { - String enumDatatypeResolved = StringUtils.toPascalCase(Utility.getEnumNameFromDefaultDatatype(codegenParameter.dataType)); - codegenParameter.vendorExtensions.put(X_DATATYPE, ResourceCacheContext.get().getResourceName() + DOT + enumDatatypeResolved); + String enumName = Utility.getEnumNameFromDefaultDatatype(codegenParameter.dataType); + codegenParameter.vendorExtensions.put(X_DATATYPE, Utility.appendResourceNameToEnum(enumName)); } private void cacheEnumClass(CodegenParameter codegenParameter) { diff --git a/src/main/java/com/twilio/oai/java/processor/enums/parameter/body/ReusableBodyListEnumProcessor.java b/src/main/java/com/twilio/oai/java/processor/enums/parameter/body/ReusableBodyListEnumProcessor.java index 7b430e69e..5c224e7e1 100644 --- a/src/main/java/com/twilio/oai/java/processor/enums/parameter/body/ReusableBodyListEnumProcessor.java +++ b/src/main/java/com/twilio/oai/java/processor/enums/parameter/body/ReusableBodyListEnumProcessor.java @@ -70,7 +70,8 @@ private void datatype(CodegenParameter codegenParameter) { // enumClassName = Status String enumClassName = Utility.getEnumNameFromDatatype(enumExistingDatatype); // enumNonContainerDatatype = Account.Status - String enumNonContainerDatatype = ResourceCacheContext.get().getResourceName() + DOT + StringUtils.toPascalCase(enumClassName); + String enumNonContainerDatatype = Utility.appendResourceNameToEnum(enumClassName); + //ResourceCacheContext.get().getResourceName() + DOT + StringUtils.toPascalCase(enumClassName); // resolvedDataType = List String resolvedDataType = Utility.replaceDatatypeInContainer(codegenParameter.dataType, enumNonContainerDatatype); codegenParameter.vendorExtensions.put(X_DATATYPE, resolvedDataType); diff --git a/src/main/java/com/twilio/oai/java/processor/enums/parameter/param/ReusableListParamEnumProcessor.java b/src/main/java/com/twilio/oai/java/processor/enums/parameter/param/ReusableListParamEnumProcessor.java index 43022baa2..a0970d29d 100644 --- a/src/main/java/com/twilio/oai/java/processor/enums/parameter/param/ReusableListParamEnumProcessor.java +++ b/src/main/java/com/twilio/oai/java/processor/enums/parameter/param/ReusableListParamEnumProcessor.java @@ -65,7 +65,8 @@ private void datatype(CodegenParameter codegenParameter) { // enumRefResolved = singleReusable String enumRefResolved = Utility.getEnumNameFromRef(codegenParameter.getSchema().items.getRef()); // enumNonContainerDatatype = Content.SingleReusable - String enumNonContainerDatatype = ResourceCacheContext.get().getResourceName() + DOT + StringUtils.toPascalCase(enumRefResolved); + String enumNonContainerDatatype = Utility.appendResourceNameToEnum(enumRefResolved); + //ResourceCacheContext.get().getResourceName() + DOT + StringUtils.toPascalCase(enumRefResolved); // resolvedDataType = List String resolvedDataType = Utility.replaceDatatypeInContainer(codegenParameter.dataType, enumNonContainerDatatype); codegenParameter.vendorExtensions.put(X_DATATYPE, resolvedDataType); diff --git a/src/main/java/com/twilio/oai/java/processor/enums/parameter/param/ReusableParamEnumProcessor.java b/src/main/java/com/twilio/oai/java/processor/enums/parameter/param/ReusableParamEnumProcessor.java index 0ca681c50..e95d85a27 100644 --- a/src/main/java/com/twilio/oai/java/processor/enums/parameter/param/ReusableParamEnumProcessor.java +++ b/src/main/java/com/twilio/oai/java/processor/enums/parameter/param/ReusableParamEnumProcessor.java @@ -55,8 +55,7 @@ private void variableName(CodegenParameter codegenParameter) { } private void datatype(CodegenParameter codegenParameter) { String enumRefResolved = Utility.getEnumNameFromRef(codegenParameter.getSchema().getRef()); - codegenParameter.vendorExtensions.put(X_DATATYPE, - ResourceCacheContext.get().getResourceName() + DOT + StringUtils.toPascalCase(enumRefResolved)); + codegenParameter.vendorExtensions.put(X_DATATYPE, Utility.appendResourceNameToEnum(enumRefResolved)); } private void cacheEnumClass(CodegenParameter codegenParameter) { diff --git a/src/main/java/com/twilio/oai/java/processor/enums/property/ReusableListPropEnumProcessor.java b/src/main/java/com/twilio/oai/java/processor/enums/property/ReusableListPropEnumProcessor.java index c512376ce..c95bfaf7a 100644 --- a/src/main/java/com/twilio/oai/java/processor/enums/property/ReusableListPropEnumProcessor.java +++ b/src/main/java/com/twilio/oai/java/processor/enums/property/ReusableListPropEnumProcessor.java @@ -50,7 +50,8 @@ private void datatype(CodegenProperty codegenProperty) { // enumClassName = Status String enumClassName = Utility.getEnumNameFromDatatype(enumExistingDatatype); // enumNonContainerDatatype = Account.Status - String enumNonContainerDatatype = ResourceCacheContext.get().getResourceName() + DOT + StringUtils.toPascalCase(enumClassName); + String enumNonContainerDatatype = Utility.appendResourceNameToEnum(enumClassName); + // ResourceCacheContext.get().getResourceName() + DOT + StringUtils.toPascalCase(enumClassName); // resolvedDataType = List String resolvedDataType = Utility.replaceDatatypeInContainer(codegenProperty.dataType, enumNonContainerDatatype); codegenProperty.vendorExtensions.put(X_DATATYPE, resolvedDataType); diff --git a/src/main/java/com/twilio/oai/java/processor/enums/property/ReusablePropEnumProcessor.java b/src/main/java/com/twilio/oai/java/processor/enums/property/ReusablePropEnumProcessor.java index 190202449..21765adb7 100644 --- a/src/main/java/com/twilio/oai/java/processor/enums/property/ReusablePropEnumProcessor.java +++ b/src/main/java/com/twilio/oai/java/processor/enums/property/ReusablePropEnumProcessor.java @@ -48,8 +48,8 @@ private void variableName(CodegenProperty codegenProperty) { codegenProperty.vendorExtensions.put(X_VARIABLE_NAME, StringUtils.toCamelCase(codegenProperty.baseName)); } private void datatype(CodegenProperty codegenProperty) { - String enumDatatypeResolved = StringUtils.toPascalCase(Utility.getEnumNameFromDefaultDatatype(codegenProperty.getRef())); - codegenProperty.vendorExtensions.put(X_DATATYPE, ResourceCacheContext.get().getResourceName() + DOT + enumDatatypeResolved); + String enumName = Utility.getEnumNameFromDefaultDatatype(codegenProperty.getRef()); + codegenProperty.vendorExtensions.put(X_DATATYPE, Utility.appendResourceNameToEnum(enumName)); } private void cacheEnumClass(CodegenProperty codegenProperty) { From 487250fb414a36df8756174864052f01381c6cd2 Mon Sep 17 00:00:00 2001 From: sbansla Date: Sun, 28 Sep 2025 11:05:37 +0530 Subject: [PATCH 32/38] fixed the array items appending inner in inline schema --- scripts/build_twilio_library.py | 4 ++-- src/test/java/com/twilio/oai/TwilioGeneratorTest.java | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/scripts/build_twilio_library.py b/scripts/build_twilio_library.py index ddf0bad83..d192cc8fc 100644 --- a/scripts/build_twilio_library.py +++ b/scripts/build_twilio_library.py @@ -80,8 +80,8 @@ def generate_domain_for_language(spec_file: str, config_path: str, spec_folder: 'generatorName': 'terraform-provider-twilio' if language == 'terraform' else f'twilio-{language}', 'inputSpec': full_path, 'outputDir': output_path, - 'inlineSchemaNameDefaults': { - 'arrayItemSuffix': '' + 'inlineSchemaOptions': { + 'ARRAY_ITEM_SUFFIX': '' }, } # print(config) diff --git a/src/test/java/com/twilio/oai/TwilioGeneratorTest.java b/src/test/java/com/twilio/oai/TwilioGeneratorTest.java index 5f1029a37..f8cb7b80e 100644 --- a/src/test/java/com/twilio/oai/TwilioGeneratorTest.java +++ b/src/test/java/com/twilio/oai/TwilioGeneratorTest.java @@ -53,7 +53,8 @@ public void launchGenerator() { .setGeneratorName(generator.getValue()) .setInputSpec(file.getPath()) .setOutputDir("codegen/" + generator.getValue()) - //.setInlineSchemaNameDefaults(Map.of("arrayItemSuffix", "")) + //.setInlineSchemaNameDefaults(Map.of("arrayItemSuffix", "")) // OpenAPI Generator 6.x.x + .setInlineSchemaOptions(Map.of("ARRAY_ITEM_SUFFIX", "")) // OpenAPI Generator 7.x.x .addGlobalProperty("apiTests", "false") .addGlobalProperty("apiDocs", "false"); final ClientOptInput clientOptInput = configurator.toClientOptInput(); From 6f8795b75fd711998c693c44f251aebbf0d4f3e3 Mon Sep 17 00:00:00 2001 From: sbansla Date: Mon, 29 Sep 2025 09:31:03 +0530 Subject: [PATCH 33/38] using builder pattern for twilio-java nested model generation --- .../oai/java/nestedmodels/MustacheModel.java | 6 ++ .../modelEqualsAndHashCode.mustache | 27 ++++++++ .../resources/twilio-java/models.mustache | 63 ++++++++++++++++--- 3 files changed, 87 insertions(+), 9 deletions(-) create mode 100644 src/main/resources/twilio-java/modelEqualsAndHashCode.mustache diff --git a/src/main/java/com/twilio/oai/java/nestedmodels/MustacheModel.java b/src/main/java/com/twilio/oai/java/nestedmodels/MustacheModel.java index 9fe1585d0..a09070b61 100644 --- a/src/main/java/com/twilio/oai/java/nestedmodels/MustacheModel.java +++ b/src/main/java/com/twilio/oai/java/nestedmodels/MustacheModel.java @@ -20,6 +20,8 @@ public class MustacheModel { // Used in constructor List mandatoryProperties; + List optionalProperties; + public MustacheModel(CodegenProperty codegenProperty, CodegenModel codegenModel) { this.className = codegenModel.classname; @@ -28,6 +30,10 @@ public MustacheModel(CodegenProperty codegenProperty, CodegenModel codegenModel) this.mandatoryProperties = codegenModel.vars.stream() .filter(codegenProperty1 -> codegenProperty1.required) .collect(Collectors.toList()); + + this.optionalProperties = codegenModel.vars.stream() + .filter(codegenProperty1 -> !codegenProperty1.required) + .collect(Collectors.toList()); } public MustacheModel(CodegenParameter codegenParameter, CodegenModel codegenModel) { diff --git a/src/main/resources/twilio-java/modelEqualsAndHashCode.mustache b/src/main/resources/twilio-java/modelEqualsAndHashCode.mustache new file mode 100644 index 000000000..7a8c4d8fa --- /dev/null +++ b/src/main/resources/twilio-java/modelEqualsAndHashCode.mustache @@ -0,0 +1,27 @@ + + @Override + public boolean equals(final Object o) { + if (this == o) { + return true; + } + + if (o == null || getClass() != o.getClass()) { + return false; + } + + {{className}} other = ({{className}}) o; + return ( + {{#allProperties}} + Objects.equals({{name}}, other.{{name}}){{^-last}} && {{/-last}} + {{/allProperties}} + ); + } + + @Override + public int hashCode() { + return Objects.hash( + {{#allProperties}} + {{name}}{{^-last}}, {{/-last}} + {{/allProperties}} + ); + } diff --git a/src/main/resources/twilio-java/models.mustache b/src/main/resources/twilio-java/models.mustache index b23a58c91..86470737b 100644 --- a/src/main/resources/twilio-java/models.mustache +++ b/src/main/resources/twilio-java/models.mustache @@ -1,17 +1,10 @@ {{#mustacheModels}} - //@JsonDeserialize(builder = {{className}}.Builder.class) + @JsonDeserialize(builder = {{className}}.Builder.class) @JsonInclude(JsonInclude.Include.NON_EMPTY) @ToString {{!@Builder}} public static class {{className}} { - {{#mandatoryProperties.0}} - public {{className}}({{#mandatoryProperties}} final {{{dataType}}} {{name}}{{^-last}}, {{/-last}} {{/mandatoryProperties}}) { - {{#mandatoryProperties}} - this.{{name}} = {{name}}; - {{/mandatoryProperties}} - } - {{/mandatoryProperties.0}} {{#allProperties}} {{#vendorExtensions.x-deserializer}} @@ -19,10 +12,62 @@ {{/vendorExtensions.x-deserializer}} @JsonInclude(JsonInclude.Include.NON_EMPTY) @JsonProperty("{{{baseName}}}") - @Getter @Setter private {{{dataType}}} {{name}}; + @Getter private final {{{dataType}}} {{name}}; + + {{/allProperties}} + + private {{className}}(Builder builder) { + {{#allProperties}} + this.{{name}} = builder.{{name}}; + {{/allProperties}} + } + public static Builder builder({{#mandatoryProperties}} final {{{dataType}}} {{name}}{{^-last}}, {{/-last}} {{/mandatoryProperties}}) { + return new Builder({{#mandatoryProperties}} {{name}}{{^-last}}, {{/-last}} {{/mandatoryProperties}}); + } + + public static {{className}} fromJson(String jsonString, ObjectMapper mapper) throws IOException { + return mapper.readValue(jsonString, {{className}}.class); + } + + @JsonPOJOBuilder(withPrefix = "") + public static class Builder { + {{#allProperties}} + {{#vendorExtensions.x-deserializer}} + @JsonDeserialize(using = {{vendorExtensions.x-deserializer}}.class) + {{/vendorExtensions.x-deserializer}} + @JsonProperty("{{{baseName}}}") + private {{{dataType}}} {{name}}; {{/allProperties}} + + {{#mandatoryProperties.0}} + @JsonCreator + public Builder({{#mandatoryProperties}} @JsonProperty("{{{baseName}}}") final {{{dataType}}} {{name}}{{^-last}}, {{/-last}} {{/mandatoryProperties}}) { + {{#mandatoryProperties}} + this.{{name}} = {{name}}; + {{/mandatoryProperties}} + } + {{/mandatoryProperties.0}} + + {{#optionalProperties}} + {{#vendorExtensions.x-deserializer}} + @JsonDeserialize(using = {{vendorExtensions.x-deserializer}}.class) + {{/vendorExtensions.x-deserializer}} + @JsonInclude(JsonInclude.Include.NON_EMPTY) + @JsonProperty("{{{baseName}}}") + public Builder {{name}}({{{dataType}}} {{name}}) { + this.{{name}} = {{name}}; + return this; + } + {{/optionalProperties}} + + public {{className}} build() { + return new {{className}}(this); + } + } + {{>modelEqualsAndHashCode}} {{! @JsonPOJOBuilder(withPrefix = "") public static class Builder {}} } + {{/mustacheModels}} From 8dc540b38cb18d1dfca792ce1ee667f20fef8e89 Mon Sep 17 00:00:00 2001 From: Shubham Date: Tue, 28 Oct 2025 10:37:31 +0530 Subject: [PATCH 34/38] chore: changes in different languages for openapi-generator-cli version upgrade (#685) # Fixes # 1. In C#, for operations having json payload, there used to be a `vendorExtension`, `x-is-json` which used to be set to `true`. That is removed in MVR. Now, we are using `bodyParams` are present or not to detect if the payload is json. This is in coherence with all other helpers as well Preview PR - https://github.com/twilio/twilio-csharp/pull/805 2. In Go, certain docs files are getting updated, Preview PR - https://github.com/twilio/twilio-go/pull/303 ### Checklist - [x] I acknowledge that all my contributions will be made under the project's license - [ ] Run `make test-docker` - [ ] Verify affected language: - [ ] Generate [twilio-go](https://github.com/twilio/twilio-go) from our [OpenAPI specification](https://github.com/twilio/twilio-oai) using the [build_twilio_go.py](./examples/build_twilio_go.py) using `python examples/build_twilio_go.py path/to/twilio-oai/spec/yaml path/to/twilio-go` and inspect the diff - [ ] Run `make test` in `twilio-go` - [ ] Create a pull request in `twilio-go` - [ ] Provide a link below to the pull request - [ ] I have made a material change to the repo (functionality, testing, spelling, grammar) - [ ] I have read the [Contribution Guidelines](https://github.com/twilio/twilio-oai-generator/blob/main/CONTRIBUTING.md) and my PR follows them - [ ] I have titled the PR appropriately - [ ] I have updated my branch with the main branch - [ ] I have added tests that prove my fix is effective or that my feature works - [ ] I have added the necessary documentation about the functionality in the appropriate .md file - [ ] I have added inline documentation to the code I modified If you have questions, please create a GitHub Issue in this repository. --- .../Call/FeedbackCallSummaryResource.cs | 5 +- .../Rest/Api/V2010/Account/CallOptions.cs | 1 + .../Rest/Api/V2010/Account/CallResource.cs | 9 +- .../Twilio/Rest/Api/V2010/AccountOptions.cs | 1 + .../Twilio/Rest/Api/V2010/AccountResource.cs | 2 + .../Twilio/Rest/FlexApi/V1/CallResource.cs | 1 + .../Rest/FlexApi/V1/Credential/AwsResource.cs | 1 + .../V1/Credential/NewCredentialsOptions.cs | 5 +- .../V1/Credential/NewCredentialsResource.cs | 9 +- .../src/Twilio/Rest/Iam/V1/ApiKeyOptions.cs | 131 --- .../src/Twilio/Rest/Iam/V1/ApiKeyResource.cs | 307 ------- .../Twilio/Rest/Iam/V1/GetApiKeysOptions.cs | 64 -- .../Twilio/Rest/Iam/V1/GetApiKeysResource.cs | 217 ----- .../Twilio/Rest/Iam/V1/NewApiKeyOptions.cs | 80 -- .../Twilio/Rest/Iam/V1/NewApiKeyResource.cs | 191 ----- .../src/Twilio/Rest/Iam/V1/TokenOptions.cs | 110 --- .../src/Twilio/Rest/Iam/V1/TokenResource.cs | 192 ----- .../PreviewIam/Organizations/UserOptions.cs | 225 ------ .../PreviewIam/Organizations/UserResource.cs | 752 ------------------ .../Twilio/Rest/PreviewIam/V1/TokenOptions.cs | 110 --- .../Rest/PreviewIam/V1/TokenResource.cs | 192 ----- .../DeployedDevices/FleetOptions.cs | 1 + .../DeployedDevices/FleetResource.cs | 1 + .../oai/api/CsharpApiResourceBuilder.java | 85 +- .../org.openapitools.codegen.CodegenConfig | 1 - .../options/CreateOptions.mustache | 10 +- .../options/DeleteOptions.mustache | 5 - .../options/FetchOptions.mustache | 5 - .../twilio-csharp/options/GetBody.mustache | 4 +- .../options/ReadOptions.mustache | 5 - .../options/UpdateOptions.mustache | 8 +- .../resource/CreateResource.mustache | 10 +- .../resource/UpdateResource.mustache | 10 +- 33 files changed, 120 insertions(+), 2630 deletions(-) delete mode 100644 examples/csharp/src/Twilio/Rest/Iam/V1/ApiKeyOptions.cs delete mode 100644 examples/csharp/src/Twilio/Rest/Iam/V1/ApiKeyResource.cs delete mode 100644 examples/csharp/src/Twilio/Rest/Iam/V1/GetApiKeysOptions.cs delete mode 100644 examples/csharp/src/Twilio/Rest/Iam/V1/GetApiKeysResource.cs delete mode 100644 examples/csharp/src/Twilio/Rest/Iam/V1/NewApiKeyOptions.cs delete mode 100644 examples/csharp/src/Twilio/Rest/Iam/V1/NewApiKeyResource.cs delete mode 100644 examples/csharp/src/Twilio/Rest/Iam/V1/TokenOptions.cs delete mode 100644 examples/csharp/src/Twilio/Rest/Iam/V1/TokenResource.cs delete mode 100644 examples/csharp/src/Twilio/Rest/PreviewIam/Organizations/UserOptions.cs delete mode 100644 examples/csharp/src/Twilio/Rest/PreviewIam/Organizations/UserResource.cs delete mode 100644 examples/csharp/src/Twilio/Rest/PreviewIam/V1/TokenOptions.cs delete mode 100644 examples/csharp/src/Twilio/Rest/PreviewIam/V1/TokenResource.cs diff --git a/examples/csharp/src/Twilio/Rest/Api/V2010/Account/Call/FeedbackCallSummaryResource.cs b/examples/csharp/src/Twilio/Rest/Api/V2010/Account/Call/FeedbackCallSummaryResource.cs index d211831c7..fda3d2947 100644 --- a/examples/csharp/src/Twilio/Rest/Api/V2010/Account/Call/FeedbackCallSummaryResource.cs +++ b/examples/csharp/src/Twilio/Rest/Api/V2010/Account/Call/FeedbackCallSummaryResource.cs @@ -56,10 +56,10 @@ private static Request BuildUpdateRequest(UpdateFeedbackCallSummaryOptions optio string path = "/2010-04-01/Accounts/{AccountSid}/Calls/Feedback/Summary/{Sid}.json"; - string PathAccountSid = options.PathAccountSid ?? client.AccountSid; - path = path.Replace("{"+"AccountSid"+"}", PathAccountSid); string PathSid = options.PathSid; path = path.Replace("{"+"Sid"+"}", PathSid); + string PathAccountSid = options.PathAccountSid ?? client.AccountSid; + path = path.Replace("{"+"AccountSid"+"}", PathAccountSid); return new Request( HttpMethod.Post, @@ -137,6 +137,7 @@ public static async System.Threading.Tasks.Task Upd return await UpdateAsync(options, client); } #endif + /// /// Converts a JSON string into a FeedbackCallSummaryResource object diff --git a/examples/csharp/src/Twilio/Rest/Api/V2010/Account/CallOptions.cs b/examples/csharp/src/Twilio/Rest/Api/V2010/Account/CallOptions.cs index 473d9ab82..2c2630983 100644 --- a/examples/csharp/src/Twilio/Rest/Api/V2010/Account/CallOptions.cs +++ b/examples/csharp/src/Twilio/Rest/Api/V2010/Account/CallOptions.cs @@ -83,6 +83,7 @@ public List> GetParams() } + /// delete public class DeleteCallOptions : IOptions { diff --git a/examples/csharp/src/Twilio/Rest/Api/V2010/Account/CallResource.cs b/examples/csharp/src/Twilio/Rest/Api/V2010/Account/CallResource.cs index ad0d34fd9..f7a3f1e8d 100644 --- a/examples/csharp/src/Twilio/Rest/Api/V2010/Account/CallResource.cs +++ b/examples/csharp/src/Twilio/Rest/Api/V2010/Account/CallResource.cs @@ -134,6 +134,7 @@ public static async System.Threading.Tasks.Task CreateAsync( return await CreateAsync(options, client); } #endif + /// delete /// Delete Call parameters @@ -144,10 +145,10 @@ private static Request BuildDeleteRequest(DeleteCallOptions options, ITwilioRest string path = "/2010-04-01/Accounts/{AccountSid}/Calls/{TestInteger}.json"; - string PathAccountSid = options.PathAccountSid ?? client.AccountSid; - path = path.Replace("{"+"AccountSid"+"}", PathAccountSid); string PathTestInteger = options.PathTestInteger.ToString(); path = path.Replace("{"+"TestInteger"+"}", PathTestInteger); + string PathAccountSid = options.PathAccountSid ?? client.AccountSid; + path = path.Replace("{"+"AccountSid"+"}", PathAccountSid); return new Request( HttpMethod.Delete, @@ -212,10 +213,10 @@ private static Request BuildFetchRequest(FetchCallOptions options, ITwilioRestCl string path = "/2010-04-01/Accounts/{AccountSid}/Calls/{TestInteger}.json"; - string PathAccountSid = options.PathAccountSid ?? client.AccountSid; - path = path.Replace("{"+"AccountSid"+"}", PathAccountSid); string PathTestInteger = options.PathTestInteger.ToString(); path = path.Replace("{"+"TestInteger"+"}", PathTestInteger); + string PathAccountSid = options.PathAccountSid ?? client.AccountSid; + path = path.Replace("{"+"AccountSid"+"}", PathAccountSid); return new Request( HttpMethod.Get, diff --git a/examples/csharp/src/Twilio/Rest/Api/V2010/AccountOptions.cs b/examples/csharp/src/Twilio/Rest/Api/V2010/AccountOptions.cs index 5c85f5db3..cf70d8ec8 100644 --- a/examples/csharp/src/Twilio/Rest/Api/V2010/AccountOptions.cs +++ b/examples/csharp/src/Twilio/Rest/Api/V2010/AccountOptions.cs @@ -76,6 +76,7 @@ public List> GetHeaderParams() } } + /// delete public class DeleteAccountOptions : IOptions { diff --git a/examples/csharp/src/Twilio/Rest/Api/V2010/AccountResource.cs b/examples/csharp/src/Twilio/Rest/Api/V2010/AccountResource.cs index 2aeda8a82..0274555bc 100644 --- a/examples/csharp/src/Twilio/Rest/Api/V2010/AccountResource.cs +++ b/examples/csharp/src/Twilio/Rest/Api/V2010/AccountResource.cs @@ -140,6 +140,7 @@ public static async System.Threading.Tasks.Task CreateAsync( return await CreateAsync(options, client); } #endif + /// delete /// Delete Account parameters @@ -484,6 +485,7 @@ public static async System.Threading.Tasks.Task UpdateAsync( return await UpdateAsync(options, client); } #endif + /// /// Converts a JSON string into a AccountResource object diff --git a/examples/csharp/src/Twilio/Rest/FlexApi/V1/CallResource.cs b/examples/csharp/src/Twilio/Rest/FlexApi/V1/CallResource.cs index bbe77b31f..93dfac837 100644 --- a/examples/csharp/src/Twilio/Rest/FlexApi/V1/CallResource.cs +++ b/examples/csharp/src/Twilio/Rest/FlexApi/V1/CallResource.cs @@ -102,6 +102,7 @@ public static async System.Threading.Tasks.Task UpdateAsync( return await UpdateAsync(options, client); } #endif + /// /// Converts a JSON string into a CallResource object diff --git a/examples/csharp/src/Twilio/Rest/FlexApi/V1/Credential/AwsResource.cs b/examples/csharp/src/Twilio/Rest/FlexApi/V1/Credential/AwsResource.cs index fbbdf9632..b383fd4c6 100644 --- a/examples/csharp/src/Twilio/Rest/FlexApi/V1/Credential/AwsResource.cs +++ b/examples/csharp/src/Twilio/Rest/FlexApi/V1/Credential/AwsResource.cs @@ -361,6 +361,7 @@ public static async System.Threading.Tasks.Task UpdateAsync( return await UpdateAsync(options, client); } #endif + /// /// Converts a JSON string into a AwsResource object diff --git a/examples/csharp/src/Twilio/Rest/FlexApi/V1/Credential/NewCredentialsOptions.cs b/examples/csharp/src/Twilio/Rest/FlexApi/V1/Credential/NewCredentialsOptions.cs index 413652c42..90a3b3835 100644 --- a/examples/csharp/src/Twilio/Rest/FlexApi/V1/Credential/NewCredentialsOptions.cs +++ b/examples/csharp/src/Twilio/Rest/FlexApi/V1/Credential/NewCredentialsOptions.cs @@ -41,10 +41,10 @@ public class CreateNewCredentialsOptions : IOptions public decimal? TestNumber { get; set; } - public float? TestNumberFloat { get; set; } + public float TestNumberFloat { get; set; } - public double? TestNumberDouble { get; set; } + public double TestNumberDouble { get; set; } public decimal? TestNumberInt32 { get; set; } @@ -170,5 +170,6 @@ public List> GetParams() } + } diff --git a/examples/csharp/src/Twilio/Rest/FlexApi/V1/Credential/NewCredentialsResource.cs b/examples/csharp/src/Twilio/Rest/FlexApi/V1/Credential/NewCredentialsResource.cs index 515501877..70bd7182f 100644 --- a/examples/csharp/src/Twilio/Rest/FlexApi/V1/Credential/NewCredentialsResource.cs +++ b/examples/csharp/src/Twilio/Rest/FlexApi/V1/Credential/NewCredentialsResource.cs @@ -126,11 +126,11 @@ public static NewCredentialsResource Create( string testString, int? testInteger = null, DateTime? testDate = null, - float? testNumberFloat = null, + float testNumberFloat = null, object testObject = null, bool? testBoolean = null, decimal? testNumber = null, - double? testNumberDouble = null, + double testNumberDouble = null, decimal? testNumberInt32 = null, long? testNumberInt64 = null, DateTime? testDateTime = null, @@ -171,11 +171,11 @@ public static async System.Threading.Tasks.Task CreateAs string testString, int? testInteger = null, DateTime? testDate = null, - float? testNumberFloat = null, + float testNumberFloat = null, object testObject = null, bool? testBoolean = null, decimal? testNumber = null, - double? testNumberDouble = null, + double testNumberDouble = null, decimal? testNumberInt32 = null, long? testNumberInt64 = null, DateTime? testDateTime = null, @@ -191,6 +191,7 @@ public static async System.Threading.Tasks.Task CreateAs return await CreateAsync(options, client); } #endif + /// /// Converts a JSON string into a NewCredentialsResource object diff --git a/examples/csharp/src/Twilio/Rest/Iam/V1/ApiKeyOptions.cs b/examples/csharp/src/Twilio/Rest/Iam/V1/ApiKeyOptions.cs deleted file mode 100644 index 6ca4bfda6..000000000 --- a/examples/csharp/src/Twilio/Rest/Iam/V1/ApiKeyOptions.cs +++ /dev/null @@ -1,131 +0,0 @@ -/* - * This code was generated by - * ___ _ _ _ _ _ _ ____ ____ ____ _ ____ ____ _ _ ____ ____ ____ ___ __ __ - * | | | | | | | | | __ | | |__| | __ | __ |___ |\ | |___ |__/ |__| | | | |__/ - * | |_|_| | |___ | |__| |__| | | | |__] |___ | \| |___ | \ | | | |__| | \ - * - * Twilio - Iam - * This is the public Twilio REST API. - * - * NOTE: This class is auto generated by OpenAPI Generator. - * https://openapi-generator.tech - * Do not edit the class manually. - */ - - -using System; -using System.Collections.Generic; -using Twilio.Base; -using Twilio.Converters; - - - - -namespace Twilio.Rest.Iam.V1 -{ - /// Delete a specific Key. - public class DeleteApiKeyOptions : IOptions - { - - /// The Twilio-provided string that uniquely identifies the Key resource to delete. - public string PathSid { get; } - - - - /// Construct a new DeleteKeyOptions - /// The Twilio-provided string that uniquely identifies the Key resource to delete. - public DeleteApiKeyOptions(string pathSid) - { - PathSid = pathSid; - } - - - /// Generate the necessary parameters - public List> GetParams() - { - var p = new List>(); - - return p; - } - - - - } - - - /// Fetch a specific Key. - public class FetchApiKeyOptions : IOptions - { - - /// The Twilio-provided string that uniquely identifies the Key resource to fetch. - public string PathSid { get; } - - - - /// Construct a new FetchKeyOptions - /// The Twilio-provided string that uniquely identifies the Key resource to fetch. - public FetchApiKeyOptions(string pathSid) - { - PathSid = pathSid; - } - - - /// Generate the necessary parameters - public List> GetParams() - { - var p = new List>(); - - return p; - } - - - - } - - - /// Update a specific Key. - public class UpdateApiKeyOptions : IOptions - { - - /// The Twilio-provided string that uniquely identifies the Key resource to update. - public string PathSid { get; } - - /// A descriptive string that you create to describe the resource. It can be up to 64 characters long. - public string FriendlyName { get; set; } - - /// The \\\\`Policy\\\\` object is a collection that specifies the allowed Twilio permissions for the restricted key. For more information on the permissions available with restricted API keys, refer to the [Twilio documentation](https://www.twilio.com/docs/iam/api-keys/restricted-api-keys#permissions-available-with-restricted-api-keys). - public object Policy { get; set; } - - - - /// Construct a new UpdateKeyOptions - /// The Twilio-provided string that uniquely identifies the Key resource to update. - public UpdateApiKeyOptions(string pathSid) - { - PathSid = pathSid; - } - - - /// Generate the necessary parameters - public List> GetParams() - { - var p = new List>(); - - if (FriendlyName != null) - { - p.Add(new KeyValuePair("FriendlyName", FriendlyName)); - } - if (Policy != null) - { - p.Add(new KeyValuePair("Policy", Serializers.JsonObject(Policy))); - } - return p; - } - - - - } - - -} - diff --git a/examples/csharp/src/Twilio/Rest/Iam/V1/ApiKeyResource.cs b/examples/csharp/src/Twilio/Rest/Iam/V1/ApiKeyResource.cs deleted file mode 100644 index 1228a7d42..000000000 --- a/examples/csharp/src/Twilio/Rest/Iam/V1/ApiKeyResource.cs +++ /dev/null @@ -1,307 +0,0 @@ -/* - * This code was generated by - * ___ _ _ _ _ _ _ ____ ____ ____ _ ____ ____ _ _ ____ ____ ____ ___ __ __ - * | | | | | | | | | __ | | |__| | __ | __ |___ |\ | |___ |__/ |__| | | | |__/ - * | |_|_| | |___ | |__| |__| | | | |__] |___ | \| |___ | \ | | | |__| | \ - * - * Twilio - Iam - * This is the public Twilio REST API. - * - * NOTE: This class is auto generated by OpenAPI Generator. - * https://openapi-generator.tech - * Do not edit the class manually. - */ - - -using Newtonsoft.Json; -using System; -using System.Collections.Generic; -using Twilio.Base; -using Twilio.Clients; -using Twilio.Constant; -using Twilio.Converters; -using Twilio.Exceptions; -using Twilio.Http; - - - -namespace Twilio.Rest.Iam.V1 -{ - public class ApiKeyResource : Resource - { - - - - - - /// Delete a specific Key. - /// Delete ApiKey parameters - /// Client to make requests to Twilio - /// A single instance of ApiKey - private static Request BuildDeleteRequest(DeleteApiKeyOptions options, ITwilioRestClient client) - { - - string path = "/v1/Keys/{Sid}"; - - string PathSid = options.PathSid; - path = path.Replace("{"+"Sid"+"}", PathSid); - - return new Request( - HttpMethod.Delete, - Rest.Domain.Iam, - path, - queryParams: options.GetParams(), - headerParams: null - ); - } - - /// Delete a specific Key. - /// Delete ApiKey parameters - /// Client to make requests to Twilio - /// A single instance of ApiKey - public static bool Delete(DeleteApiKeyOptions options, ITwilioRestClient client = null) - { - client = client ?? TwilioClient.GetRestClient(); - var response = client.Request(BuildDeleteRequest(options, client)); - return response.StatusCode == System.Net.HttpStatusCode.NoContent; - } - - #if !NET35 - /// Delete a specific Key. - /// Delete ApiKey parameters - /// Client to make requests to Twilio - /// Task that resolves to A single instance of ApiKey - public static async System.Threading.Tasks.Task DeleteAsync(DeleteApiKeyOptions options, - ITwilioRestClient client = null) - { - client = client ?? TwilioClient.GetRestClient(); - var response = await client.RequestAsync(BuildDeleteRequest(options, client)); - return response.StatusCode == System.Net.HttpStatusCode.NoContent; - } - #endif - - /// Delete a specific Key. - /// The Twilio-provided string that uniquely identifies the Key resource to delete. - /// Client to make requests to Twilio - /// A single instance of ApiKey - public static bool Delete(string pathSid, ITwilioRestClient client = null) - { - var options = new DeleteApiKeyOptions(pathSid) ; - return Delete(options, client); - } - - #if !NET35 - /// Delete a specific Key. - /// The Twilio-provided string that uniquely identifies the Key resource to delete. - /// Client to make requests to Twilio - /// Task that resolves to A single instance of ApiKey - public static async System.Threading.Tasks.Task DeleteAsync(string pathSid, ITwilioRestClient client = null) - { - var options = new DeleteApiKeyOptions(pathSid) ; - return await DeleteAsync(options, client); - } - #endif - - private static Request BuildFetchRequest(FetchApiKeyOptions options, ITwilioRestClient client) - { - - string path = "/v1/Keys/{Sid}"; - - string PathSid = options.PathSid; - path = path.Replace("{"+"Sid"+"}", PathSid); - - return new Request( - HttpMethod.Get, - Rest.Domain.Iam, - path, - queryParams: options.GetParams(), - headerParams: null - ); - } - - /// Fetch a specific Key. - /// Fetch ApiKey parameters - /// Client to make requests to Twilio - /// A single instance of ApiKey - public static ApiKeyResource Fetch(FetchApiKeyOptions options, ITwilioRestClient client = null) - { - client = client ?? TwilioClient.GetRestClient(); - var response = client.Request(BuildFetchRequest(options, client)); - return FromJson(response.Content); - } - - #if !NET35 - /// Fetch a specific Key. - /// Fetch ApiKey parameters - /// Client to make requests to Twilio - /// Task that resolves to A single instance of ApiKey - public static async System.Threading.Tasks.Task FetchAsync(FetchApiKeyOptions options, ITwilioRestClient client = null) - { - client = client ?? TwilioClient.GetRestClient(); - var response = await client.RequestAsync(BuildFetchRequest(options, client)); - return FromJson(response.Content); - } - #endif - /// Fetch a specific Key. - /// The Twilio-provided string that uniquely identifies the Key resource to fetch. - /// Client to make requests to Twilio - /// A single instance of ApiKey - public static ApiKeyResource Fetch( - string pathSid, - ITwilioRestClient client = null) - { - var options = new FetchApiKeyOptions(pathSid){ }; - return Fetch(options, client); - } - - #if !NET35 - /// Fetch a specific Key. - /// The Twilio-provided string that uniquely identifies the Key resource to fetch. - /// Client to make requests to Twilio - /// Task that resolves to A single instance of ApiKey - public static async System.Threading.Tasks.Task FetchAsync(string pathSid, ITwilioRestClient client = null) - { - var options = new FetchApiKeyOptions(pathSid){ }; - return await FetchAsync(options, client); - } - #endif - - private static Request BuildUpdateRequest(UpdateApiKeyOptions options, ITwilioRestClient client) - { - - string path = "/v1/Keys/{Sid}"; - - string PathSid = options.PathSid; - path = path.Replace("{"+"Sid"+"}", PathSid); - - return new Request( - HttpMethod.Post, - Rest.Domain.Iam, - path, - contentType: EnumConstants.ContentTypeEnum.FORM_URLENCODED, - postParams: options.GetParams(), - headerParams: null - ); - } - - /// Update a specific Key. - /// Update ApiKey parameters - /// Client to make requests to Twilio - /// A single instance of ApiKey - public static ApiKeyResource Update(UpdateApiKeyOptions options, ITwilioRestClient client = null) - { - client = client ?? TwilioClient.GetRestClient(); - var response = client.Request(BuildUpdateRequest(options, client)); - return FromJson(response.Content); - } - - /// Update a specific Key. - /// Update ApiKey parameters - /// Client to make requests to Twilio - /// Task that resolves to A single instance of ApiKey - #if !NET35 - public static async System.Threading.Tasks.Task UpdateAsync(UpdateApiKeyOptions options, - ITwilioRestClient client = null) - { - client = client ?? TwilioClient.GetRestClient(); - var response = await client.RequestAsync(BuildUpdateRequest(options, client)); - return FromJson(response.Content); - } - #endif - - /// Update a specific Key. - /// The Twilio-provided string that uniquely identifies the Key resource to update. - /// A descriptive string that you create to describe the resource. It can be up to 64 characters long. - /// The \\\\`Policy\\\\` object is a collection that specifies the allowed Twilio permissions for the restricted key. For more information on the permissions available with restricted API keys, refer to the [Twilio documentation](https://www.twilio.com/docs/iam/api-keys/restricted-api-keys#permissions-available-with-restricted-api-keys). - /// Client to make requests to Twilio - /// A single instance of ApiKey - public static ApiKeyResource Update( - string pathSid, - string friendlyName = null, - object policy = null, - ITwilioRestClient client = null) - { - var options = new UpdateApiKeyOptions(pathSid){ FriendlyName = friendlyName, Policy = policy }; - return Update(options, client); - } - - #if !NET35 - /// Update a specific Key. - /// The Twilio-provided string that uniquely identifies the Key resource to update. - /// A descriptive string that you create to describe the resource. It can be up to 64 characters long. - /// The \\\\`Policy\\\\` object is a collection that specifies the allowed Twilio permissions for the restricted key. For more information on the permissions available with restricted API keys, refer to the [Twilio documentation](https://www.twilio.com/docs/iam/api-keys/restricted-api-keys#permissions-available-with-restricted-api-keys). - /// Client to make requests to Twilio - /// Task that resolves to A single instance of ApiKey - public static async System.Threading.Tasks.Task UpdateAsync( - string pathSid, - string friendlyName = null, - object policy = null, - ITwilioRestClient client = null) - { - var options = new UpdateApiKeyOptions(pathSid){ FriendlyName = friendlyName, Policy = policy }; - return await UpdateAsync(options, client); - } - #endif - - /// - /// Converts a JSON string into a ApiKeyResource object - /// - /// Raw JSON string - /// ApiKeyResource object represented by the provided JSON - public static ApiKeyResource FromJson(string json) - { - try - { - return JsonConvert.DeserializeObject(json); - } - catch (JsonException e) - { - throw new ApiException(e.Message, e); - } - } - /// - /// Converts an object into a json string - /// - /// C# model - /// JSON string - public static string ToJson(object model) - { - try - { - return JsonConvert.SerializeObject(model); - } - catch (JsonException e) - { - throw new ApiException(e.Message, e); - } - } - - - /// The unique string that we created to identify the Key resource. - [JsonProperty("sid")] - public string Sid { get; private set; } - - /// The string that you assigned to describe the resource. - [JsonProperty("friendly_name")] - public string FriendlyName { get; private set; } - - /// The date and time in GMT that the resource was created specified in [RFC 2822](https://www.ietf.org/rfc/rfc2822.txt) format. - [JsonProperty("date_created")] - public DateTime? DateCreated { get; private set; } - - /// The date and time in GMT that the resource was last updated specified in [RFC 2822](https://www.ietf.org/rfc/rfc2822.txt) format. - [JsonProperty("date_updated")] - public DateTime? DateUpdated { get; private set; } - - /// The \\`Policy\\` object is a collection that specifies the allowed Twilio permissions for the restricted key. For more information on the permissions available with restricted API keys, refer to the [Twilio documentation](https://www.twilio.com/docs/iam/api-keys/restricted-api-keys#permissions-available-with-restricted-api-keys). - [JsonProperty("policy")] - public object Policy { get; private set; } - - - - private ApiKeyResource() { - - } - } -} - diff --git a/examples/csharp/src/Twilio/Rest/Iam/V1/GetApiKeysOptions.cs b/examples/csharp/src/Twilio/Rest/Iam/V1/GetApiKeysOptions.cs deleted file mode 100644 index 5f0f52dfc..000000000 --- a/examples/csharp/src/Twilio/Rest/Iam/V1/GetApiKeysOptions.cs +++ /dev/null @@ -1,64 +0,0 @@ -/* - * This code was generated by - * ___ _ _ _ _ _ _ ____ ____ ____ _ ____ ____ _ _ ____ ____ ____ ___ __ __ - * | | | | | | | | | __ | | |__| | __ | __ |___ |\ | |___ |__/ |__| | | | |__/ - * | |_|_| | |___ | |__| |__| | | | |__] |___ | \| |___ | \ | | | |__| | \ - * - * Twilio - Iam - * This is the public Twilio REST API. - * - * NOTE: This class is auto generated by OpenAPI Generator. - * https://openapi-generator.tech - * Do not edit the class manually. - */ - - -using System; -using System.Collections.Generic; -using Twilio.Base; -using Twilio.Converters; - - - - -namespace Twilio.Rest.Iam.V1 -{ - /// Retrieve a list of all Keys for a account. - public class ReadGetApiKeysOptions : ReadOptions - { - - /// The SID of the [Account](https://www.twilio.com/docs/iam/api/account) that created the Payments resource. - public string AccountSid { get; } - - - - /// Construct a new ListGetKeysOptions - /// The SID of the [Account](https://www.twilio.com/docs/iam/api/account) that created the Payments resource. - public ReadGetApiKeysOptions(string accountSid) - { - AccountSid = accountSid; - } - - - /// Generate the necessary parameters - public List> GetParams() - { - var p = new List>(); - - if (AccountSid != null) - { - p.Add(new KeyValuePair("AccountSid", AccountSid)); - } - if (PageSize != null) - { - p.Add(new KeyValuePair("PageSize", PageSize.ToString())); - } - return p; - } - - - - } - -} - diff --git a/examples/csharp/src/Twilio/Rest/Iam/V1/GetApiKeysResource.cs b/examples/csharp/src/Twilio/Rest/Iam/V1/GetApiKeysResource.cs deleted file mode 100644 index dbaaf156a..000000000 --- a/examples/csharp/src/Twilio/Rest/Iam/V1/GetApiKeysResource.cs +++ /dev/null @@ -1,217 +0,0 @@ -/* - * This code was generated by - * ___ _ _ _ _ _ _ ____ ____ ____ _ ____ ____ _ _ ____ ____ ____ ___ __ __ - * | | | | | | | | | __ | | |__| | __ | __ |___ |\ | |___ |__/ |__| | | | |__/ - * | |_|_| | |___ | |__| |__| | | | |__] |___ | \| |___ | \ | | | |__| | \ - * - * Twilio - Iam - * This is the public Twilio REST API. - * - * NOTE: This class is auto generated by OpenAPI Generator. - * https://openapi-generator.tech - * Do not edit the class manually. - */ - - -using Newtonsoft.Json; -using System; -using System.Collections.Generic; -using Twilio.Base; -using Twilio.Clients; -using Twilio.Constant; -using Twilio.Converters; -using Twilio.Exceptions; -using Twilio.Http; - - - -namespace Twilio.Rest.Iam.V1 -{ - public class GetApiKeysResource : Resource - { - - - - - - private static Request BuildReadRequest(ReadGetApiKeysOptions options, ITwilioRestClient client) - { - - string path = "/v1/Keys"; - - - return new Request( - HttpMethod.Get, - Rest.Domain.Iam, - path, - queryParams: options.GetParams(), - headerParams: null - ); - } - /// Retrieve a list of all Keys for a account. - /// Read GetApiKeys parameters - /// Client to make requests to Twilio - /// A single instance of GetApiKeys - public static ResourceSet Read(ReadGetApiKeysOptions options, ITwilioRestClient client = null) - { - client = client ?? TwilioClient.GetRestClient(); - var response = client.Request(BuildReadRequest(options, client)); - var page = Page.FromJson("keys", response.Content); - return new ResourceSet(page, options, client); - } - - #if !NET35 - /// Retrieve a list of all Keys for a account. - /// Read GetApiKeys parameters - /// Client to make requests to Twilio - /// Task that resolves to A single instance of GetApiKeys - public static async System.Threading.Tasks.Task> ReadAsync(ReadGetApiKeysOptions options, ITwilioRestClient client = null) - { - client = client ?? TwilioClient.GetRestClient(); - var response = await client.RequestAsync(BuildReadRequest(options, client)); - - var page = Page.FromJson("keys", response.Content); - return new ResourceSet(page, options, client); - } - #endif - /// Retrieve a list of all Keys for a account. - /// The SID of the [Account](https://www.twilio.com/docs/iam/api/account) that created the Payments resource. - /// How many resources to return in each list page. The default is 50, and the maximum is 1000. - /// Record limit - /// Client to make requests to Twilio - /// A single instance of GetApiKeys - public static ResourceSet Read( - string accountSid, - long? pageSize = null, - long? limit = null, - ITwilioRestClient client = null) - { - var options = new ReadGetApiKeysOptions(accountSid){ PageSize = pageSize, Limit = limit}; - return Read(options, client); - } - - #if !NET35 - /// Retrieve a list of all Keys for a account. - /// The SID of the [Account](https://www.twilio.com/docs/iam/api/account) that created the Payments resource. - /// How many resources to return in each list page. The default is 50, and the maximum is 1000. - /// Record limit - /// Client to make requests to Twilio - /// Task that resolves to A single instance of GetApiKeys - public static async System.Threading.Tasks.Task> ReadAsync( - string accountSid, - long? pageSize = null, - long? limit = null, - ITwilioRestClient client = null) - { - var options = new ReadGetApiKeysOptions(accountSid){ PageSize = pageSize, Limit = limit}; - return await ReadAsync(options, client); - } - #endif - - - /// Fetch the target page of records - /// API-generated URL for the requested results page - /// Client to make requests to Twilio - /// The target page of records - public static Page GetPage(string targetUrl, ITwilioRestClient client) - { - client = client ?? TwilioClient.GetRestClient(); - - var request = new Request( - HttpMethod.Get, - targetUrl - ); - - var response = client.Request(request); - return Page.FromJson("keys", response.Content); - } - - /// Fetch the next page of records - /// current page of records - /// Client to make requests to Twilio - /// The next page of records - public static Page NextPage(Page page, ITwilioRestClient client) - { - var request = new Request( - HttpMethod.Get, - page.GetNextPageUrl(Rest.Domain.Api) - ); - - var response = client.Request(request); - return Page.FromJson("keys", response.Content); - } - - /// Fetch the previous page of records - /// current page of records - /// Client to make requests to Twilio - /// The previous page of records - public static Page PreviousPage(Page page, ITwilioRestClient client) - { - var request = new Request( - HttpMethod.Get, - page.GetPreviousPageUrl(Rest.Domain.Api) - ); - - var response = client.Request(request); - return Page.FromJson("keys", response.Content); - } - - - /// - /// Converts a JSON string into a GetApiKeysResource object - /// - /// Raw JSON string - /// GetApiKeysResource object represented by the provided JSON - public static GetApiKeysResource FromJson(string json) - { - try - { - return JsonConvert.DeserializeObject(json); - } - catch (JsonException e) - { - throw new ApiException(e.Message, e); - } - } - /// - /// Converts an object into a json string - /// - /// C# model - /// JSON string - public static string ToJson(object model) - { - try - { - return JsonConvert.SerializeObject(model); - } - catch (JsonException e) - { - throw new ApiException(e.Message, e); - } - } - - - /// The unique string that we created to identify the Key resource. - [JsonProperty("sid")] - public string Sid { get; private set; } - - /// The string that you assigned to describe the resource. - [JsonProperty("friendly_name")] - public string FriendlyName { get; private set; } - - /// The date and time in GMT that the resource was created specified in [RFC 2822](https://www.ietf.org/rfc/rfc2822.txt) format. - [JsonProperty("date_created")] - public DateTime? DateCreated { get; private set; } - - /// The date and time in GMT that the resource was last updated specified in [RFC 2822](https://www.ietf.org/rfc/rfc2822.txt) format. - [JsonProperty("date_updated")] - public DateTime? DateUpdated { get; private set; } - - - - private GetApiKeysResource() { - - } - } -} - diff --git a/examples/csharp/src/Twilio/Rest/Iam/V1/NewApiKeyOptions.cs b/examples/csharp/src/Twilio/Rest/Iam/V1/NewApiKeyOptions.cs deleted file mode 100644 index ce96de3bf..000000000 --- a/examples/csharp/src/Twilio/Rest/Iam/V1/NewApiKeyOptions.cs +++ /dev/null @@ -1,80 +0,0 @@ -/* - * This code was generated by - * ___ _ _ _ _ _ _ ____ ____ ____ _ ____ ____ _ _ ____ ____ ____ ___ __ __ - * | | | | | | | | | __ | | |__| | __ | __ |___ |\ | |___ |__/ |__| | | | |__/ - * | |_|_| | |___ | |__| |__| | | | |__] |___ | \| |___ | \ | | | |__| | \ - * - * Twilio - Iam - * This is the public Twilio REST API. - * - * NOTE: This class is auto generated by OpenAPI Generator. - * https://openapi-generator.tech - * Do not edit the class manually. - */ - - -using System; -using System.Collections.Generic; -using Twilio.Base; -using Twilio.Converters; - - - - -namespace Twilio.Rest.Iam.V1 -{ - - /// Create a new Signing Key for the account making the request. - public class CreateNewApiKeyOptions : IOptions - { - - /// The SID of the [Account](https://www.twilio.com/docs/iam/api/account) that created the Payments resource. - public string AccountSid { get; } - - /// A descriptive string that you create to describe the resource. It can be up to 64 characters long. - public string FriendlyName { get; set; } - - - public NewApiKeyResource.KeytypeEnum KeyType { get; set; } - - /// The \\\\`Policy\\\\` object is a collection that specifies the allowed Twilio permissions for the restricted key. For more information on the permissions available with restricted API keys, refer to the [Twilio documentation](https://www.twilio.com/docs/iam/api-keys/restricted-api-keys#permissions-available-with-restricted-api-keys). - public object Policy { get; set; } - - - /// Construct a new CreateNewKeyOptions - /// The SID of the [Account](https://www.twilio.com/docs/iam/api/account) that created the Payments resource. - public CreateNewApiKeyOptions(string accountSid) - { - AccountSid = accountSid; - } - - - /// Generate the necessary parameters - public List> GetParams() - { - var p = new List>(); - - if (AccountSid != null) - { - p.Add(new KeyValuePair("AccountSid", AccountSid)); - } - if (FriendlyName != null) - { - p.Add(new KeyValuePair("FriendlyName", FriendlyName)); - } - if (KeyType != null) - { - p.Add(new KeyValuePair("KeyType", KeyType.ToString())); - } - if (Policy != null) - { - p.Add(new KeyValuePair("Policy", Serializers.JsonObject(Policy))); - } - return p; - } - - - - } -} - diff --git a/examples/csharp/src/Twilio/Rest/Iam/V1/NewApiKeyResource.cs b/examples/csharp/src/Twilio/Rest/Iam/V1/NewApiKeyResource.cs deleted file mode 100644 index a420cb2ed..000000000 --- a/examples/csharp/src/Twilio/Rest/Iam/V1/NewApiKeyResource.cs +++ /dev/null @@ -1,191 +0,0 @@ -/* - * This code was generated by - * ___ _ _ _ _ _ _ ____ ____ ____ _ ____ ____ _ _ ____ ____ ____ ___ __ __ - * | | | | | | | | | __ | | |__| | __ | __ |___ |\ | |___ |__/ |__| | | | |__/ - * | |_|_| | |___ | |__| |__| | | | |__] |___ | \| |___ | \ | | | |__| | \ - * - * Twilio - Iam - * This is the public Twilio REST API. - * - * NOTE: This class is auto generated by OpenAPI Generator. - * https://openapi-generator.tech - * Do not edit the class manually. - */ - - -using Newtonsoft.Json; -using System; -using System.Collections.Generic; -using Twilio.Base; -using Twilio.Clients; -using Twilio.Constant; -using Twilio.Converters; -using Twilio.Exceptions; -using Twilio.Http; -using Twilio.Types; - - -namespace Twilio.Rest.Iam.V1 -{ - public class NewApiKeyResource : Resource - { - - - - public sealed class KeytypeEnum : StringEnum - { - private KeytypeEnum(string value) : base(value) {} - public KeytypeEnum() {} - public static implicit operator KeytypeEnum(string value) - { - return new KeytypeEnum(value); - } - public static readonly KeytypeEnum Restricted = new KeytypeEnum("restricted"); - - } - - - private static Request BuildCreateRequest(CreateNewApiKeyOptions options, ITwilioRestClient client) - { - - string path = "/v1/Keys"; - - - return new Request( - HttpMethod.Post, - Rest.Domain.Iam, - path, - contentType: EnumConstants.ContentTypeEnum.FORM_URLENCODED, - postParams: options.GetParams(), - headerParams: null - ); - } - - /// Create a new Signing Key for the account making the request. - /// Create NewApiKey parameters - /// Client to make requests to Twilio - /// A single instance of NewApiKey - public static NewApiKeyResource Create(CreateNewApiKeyOptions options, ITwilioRestClient client = null) - { - client = client ?? TwilioClient.GetRestClient(); - var response = client.Request(BuildCreateRequest(options, client)); - return FromJson(response.Content); - } - - #if !NET35 - /// Create a new Signing Key for the account making the request. - /// Create NewApiKey parameters - /// Client to make requests to Twilio - /// Task that resolves to A single instance of NewApiKey - public static async System.Threading.Tasks.Task CreateAsync(CreateNewApiKeyOptions options, ITwilioRestClient client = null) - { - client = client ?? TwilioClient.GetRestClient(); - var response = await client.RequestAsync(BuildCreateRequest(options, client)); - return FromJson(response.Content); - } - #endif - - /// Create a new Signing Key for the account making the request. - /// The SID of the [Account](https://www.twilio.com/docs/iam/api/account) that created the Payments resource. - /// A descriptive string that you create to describe the resource. It can be up to 64 characters long. - /// - /// The \\\\`Policy\\\\` object is a collection that specifies the allowed Twilio permissions for the restricted key. For more information on the permissions available with restricted API keys, refer to the [Twilio documentation](https://www.twilio.com/docs/iam/api-keys/restricted-api-keys#permissions-available-with-restricted-api-keys). - /// Client to make requests to Twilio - /// A single instance of NewApiKey - public static NewApiKeyResource Create( - string accountSid, - string friendlyName = null, - NewApiKeyResource.KeytypeEnum keyType = null, - object policy = null, - ITwilioRestClient client = null) - { - var options = new CreateNewApiKeyOptions(accountSid){ FriendlyName = friendlyName, KeyType = keyType, Policy = policy }; - return Create(options, client); - } - - #if !NET35 - /// Create a new Signing Key for the account making the request. - /// The SID of the [Account](https://www.twilio.com/docs/iam/api/account) that created the Payments resource. - /// A descriptive string that you create to describe the resource. It can be up to 64 characters long. - /// - /// The \\\\`Policy\\\\` object is a collection that specifies the allowed Twilio permissions for the restricted key. For more information on the permissions available with restricted API keys, refer to the [Twilio documentation](https://www.twilio.com/docs/iam/api-keys/restricted-api-keys#permissions-available-with-restricted-api-keys). - /// Client to make requests to Twilio - /// Task that resolves to A single instance of NewApiKey - public static async System.Threading.Tasks.Task CreateAsync( - string accountSid, - string friendlyName = null, - NewApiKeyResource.KeytypeEnum keyType = null, - object policy = null, - ITwilioRestClient client = null) - { - var options = new CreateNewApiKeyOptions(accountSid){ FriendlyName = friendlyName, KeyType = keyType, Policy = policy }; - return await CreateAsync(options, client); - } - #endif - - /// - /// Converts a JSON string into a NewApiKeyResource object - /// - /// Raw JSON string - /// NewApiKeyResource object represented by the provided JSON - public static NewApiKeyResource FromJson(string json) - { - try - { - return JsonConvert.DeserializeObject(json); - } - catch (JsonException e) - { - throw new ApiException(e.Message, e); - } - } - /// - /// Converts an object into a json string - /// - /// C# model - /// JSON string - public static string ToJson(object model) - { - try - { - return JsonConvert.SerializeObject(model); - } - catch (JsonException e) - { - throw new ApiException(e.Message, e); - } - } - - - /// The unique string that that we created to identify the NewKey resource. You will use this as the basic-auth `user` when authenticating to the API. - [JsonProperty("sid")] - public string Sid { get; private set; } - - /// The string that you assigned to describe the resource. - [JsonProperty("friendly_name")] - public string FriendlyName { get; private set; } - - /// The date and time in GMT that the API Key was created specified in [RFC 2822](https://www.ietf.org/rfc/rfc2822.txt) format. - [JsonProperty("date_created")] - public DateTime? DateCreated { get; private set; } - - /// The date and time in GMT that the new API Key was last updated specified in [RFC 2822](https://www.ietf.org/rfc/rfc2822.txt) format. - [JsonProperty("date_updated")] - public DateTime? DateUpdated { get; private set; } - - /// The secret your application uses to sign Access Tokens and to authenticate to the REST API (you will use this as the basic-auth `password`). **Note that for security reasons, this field is ONLY returned when the API Key is first created.** - [JsonProperty("secret")] - public string Secret { get; private set; } - - /// Collection of allow assertions. - [JsonProperty("policy")] - public object Policy { get; private set; } - - - - private NewApiKeyResource() { - - } - } -} - diff --git a/examples/csharp/src/Twilio/Rest/Iam/V1/TokenOptions.cs b/examples/csharp/src/Twilio/Rest/Iam/V1/TokenOptions.cs deleted file mode 100644 index a0eabf328..000000000 --- a/examples/csharp/src/Twilio/Rest/Iam/V1/TokenOptions.cs +++ /dev/null @@ -1,110 +0,0 @@ -/* - * This code was generated by - * ___ _ _ _ _ _ _ ____ ____ ____ _ ____ ____ _ _ ____ ____ ____ ___ __ __ - * | | | | | | | | | __ | | |__| | __ | __ |___ |\ | |___ |__/ |__| | | | |__/ - * | |_|_| | |___ | |__| |__| | | | |__] |___ | \| |___ | \ | | | |__| | \ - * - * Twilio - Iam - * This is the public Twilio REST API. - * - * NOTE: This class is auto generated by OpenAPI Generator. - * https://openapi-generator.tech - * Do not edit the class manually. - */ - - -using System; -using System.Collections.Generic; -using Twilio.Base; -using Twilio.Converters; - - - - -namespace Twilio.Rest.Iam.V1 -{ - - /// create - public class CreateTokenOptions : IOptions - { - - /// Grant type is a credential representing resource owner's authorization which can be used by client to obtain access token. - public string GrantType { get; } - - /// A 34 character string that uniquely identifies this OAuth App. - public string ClientId { get; } - - /// The credential for confidential OAuth App. - public string ClientSecret { get; set; } - - /// JWT token related to the authorization code grant type. - public string Code { get; set; } - - /// The redirect uri - public string RedirectUri { get; set; } - - /// The targeted audience uri - public string Audience { get; set; } - - /// JWT token related to refresh access token. - public string RefreshToken { get; set; } - - /// The scope of token - public string Scope { get; set; } - - - /// Construct a new CreateTokenOptions - /// Grant type is a credential representing resource owner's authorization which can be used by client to obtain access token. - /// A 34 character string that uniquely identifies this OAuth App. - public CreateTokenOptions(string grantType, string clientId) - { - GrantType = grantType; - ClientId = clientId; - } - - - /// Generate the necessary parameters - public List> GetParams() - { - var p = new List>(); - - if (GrantType != null) - { - p.Add(new KeyValuePair("grant_type", GrantType)); - } - if (ClientId != null) - { - p.Add(new KeyValuePair("client_id", ClientId)); - } - if (ClientSecret != null) - { - p.Add(new KeyValuePair("client_secret", ClientSecret)); - } - if (Code != null) - { - p.Add(new KeyValuePair("code", Code)); - } - if (RedirectUri != null) - { - p.Add(new KeyValuePair("redirect_uri", RedirectUri)); - } - if (Audience != null) - { - p.Add(new KeyValuePair("audience", Audience)); - } - if (RefreshToken != null) - { - p.Add(new KeyValuePair("refresh_token", RefreshToken)); - } - if (Scope != null) - { - p.Add(new KeyValuePair("scope", Scope)); - } - return p; - } - - - - } -} - diff --git a/examples/csharp/src/Twilio/Rest/Iam/V1/TokenResource.cs b/examples/csharp/src/Twilio/Rest/Iam/V1/TokenResource.cs deleted file mode 100644 index a26d69f53..000000000 --- a/examples/csharp/src/Twilio/Rest/Iam/V1/TokenResource.cs +++ /dev/null @@ -1,192 +0,0 @@ -/* - * This code was generated by - * ___ _ _ _ _ _ _ ____ ____ ____ _ ____ ____ _ _ ____ ____ ____ ___ __ __ - * | | | | | | | | | __ | | |__| | __ | __ |___ |\ | |___ |__/ |__| | | | |__/ - * | |_|_| | |___ | |__| |__| | | | |__] |___ | \| |___ | \ | | | |__| | \ - * - * Twilio - Iam - * This is the public Twilio REST API. - * - * NOTE: This class is auto generated by OpenAPI Generator. - * https://openapi-generator.tech - * Do not edit the class manually. - */ - - -using Newtonsoft.Json; -using System; -using System.Collections.Generic; -using Twilio.Base; -using Twilio.Clients; -using Twilio.Constant; -using Twilio.Converters; -using Twilio.Exceptions; -using Twilio.Http; - - - -namespace Twilio.Rest.Iam.V1 -{ - public class TokenResource : Resource - { - - - - - - private static Request BuildCreateRequest(CreateTokenOptions options, ITwilioRestClient client) - { - - string path = "/v1/token"; - - - return new Request( - HttpMethod.Post, - Rest.Domain.Iam, - path, - contentType: EnumConstants.ContentTypeEnum.FORM_URLENCODED, - postParams: options.GetParams(), - headerParams: null - ); - } - - /// create - /// Create Token parameters - /// Client to make requests to Twilio - /// A single instance of Token - public static TokenResource Create(CreateTokenOptions options, ITwilioRestClient client = null) - { - client = client ?? TwilioClient.GetNoAuthRestClient(); - var response = client.Request(BuildCreateRequest(options, client)); - return FromJson(response.Content); - } - - #if !NET35 - /// create - /// Create Token parameters - /// Client to make requests to Twilio - /// Task that resolves to A single instance of Token - public static async System.Threading.Tasks.Task CreateAsync(CreateTokenOptions options, ITwilioRestClient client = null) - { - client = client ?? TwilioClient.GetNoAuthRestClient(); - var response = await client.RequestAsync(BuildCreateRequest(options, client)); - return FromJson(response.Content); - } - #endif - - /// create - /// Grant type is a credential representing resource owner's authorization which can be used by client to obtain access token. - /// A 34 character string that uniquely identifies this OAuth App. - /// The credential for confidential OAuth App. - /// JWT token related to the authorization code grant type. - /// The redirect uri - /// The targeted audience uri - /// JWT token related to refresh access token. - /// The scope of token - /// Client to make requests to Twilio - /// A single instance of Token - public static TokenResource Create( - string grantType, - string clientId, - string clientSecret = null, - string code = null, - string redirectUri = null, - string audience = null, - string refreshToken = null, - string scope = null, - ITwilioRestClient client = null) - { - var options = new CreateTokenOptions(grantType, clientId){ ClientSecret = clientSecret, Code = code, RedirectUri = redirectUri, Audience = audience, RefreshToken = refreshToken, Scope = scope }; - return Create(options, client); - } - - #if !NET35 - /// create - /// Grant type is a credential representing resource owner's authorization which can be used by client to obtain access token. - /// A 34 character string that uniquely identifies this OAuth App. - /// The credential for confidential OAuth App. - /// JWT token related to the authorization code grant type. - /// The redirect uri - /// The targeted audience uri - /// JWT token related to refresh access token. - /// The scope of token - /// Client to make requests to Twilio - /// Task that resolves to A single instance of Token - public static async System.Threading.Tasks.Task CreateAsync( - string grantType, - string clientId, - string clientSecret = null, - string code = null, - string redirectUri = null, - string audience = null, - string refreshToken = null, - string scope = null, - ITwilioRestClient client = null) - { - var options = new CreateTokenOptions(grantType, clientId){ ClientSecret = clientSecret, Code = code, RedirectUri = redirectUri, Audience = audience, RefreshToken = refreshToken, Scope = scope }; - return await CreateAsync(options, client); - } - #endif - - /// - /// Converts a JSON string into a TokenResource object - /// - /// Raw JSON string - /// TokenResource object represented by the provided JSON - public static TokenResource FromJson(string json) - { - try - { - return JsonConvert.DeserializeObject(json); - } - catch (JsonException e) - { - throw new ApiException(e.Message, e); - } - } - /// - /// Converts an object into a json string - /// - /// C# model - /// JSON string - public static string ToJson(object model) - { - try - { - return JsonConvert.SerializeObject(model); - } - catch (JsonException e) - { - throw new ApiException(e.Message, e); - } - } - - - /// Token which carries the necessary information to access a Twilio resource directly. - [JsonProperty("access_token")] - public string AccessToken { get; private set; } - - /// Token which carries the information necessary to get a new access token. - [JsonProperty("refresh_token")] - public string RefreshToken { get; private set; } - - /// Token which carries the information necessary of user profile. - [JsonProperty("id_token")] - public string IdToken { get; private set; } - - /// Token type - [JsonProperty("token_type")] - public string TokenType { get; private set; } - - /// The expires_in - [JsonProperty("expires_in")] - public long? ExpiresIn { get; private set; } - - - - private TokenResource() { - - } - } -} - diff --git a/examples/csharp/src/Twilio/Rest/PreviewIam/Organizations/UserOptions.cs b/examples/csharp/src/Twilio/Rest/PreviewIam/Organizations/UserOptions.cs deleted file mode 100644 index 745105eac..000000000 --- a/examples/csharp/src/Twilio/Rest/PreviewIam/Organizations/UserOptions.cs +++ /dev/null @@ -1,225 +0,0 @@ -/* - * This code was generated by - * ___ _ _ _ _ _ _ ____ ____ ____ _ ____ ____ _ _ ____ ____ ____ ___ __ __ - * | | | | | | | | | __ | | |__| | __ | __ |___ |\ | |___ |__/ |__| | | | |__/ - * | |_|_| | |___ | |__| |__| | | | |__] |___ | \| |___ | \ | | | |__| | \ - * - * Organization Public API - * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) - * - * NOTE: This class is auto generated by OpenAPI Generator. - * https://openapi-generator.tech - * Do not edit the class manually. - */ - - -using System; -using System.Collections.Generic; -using Twilio.Base; -using Twilio.Converters; - - - - -namespace Twilio.Rest.PreviewIam.Organizations -{ - - /// create - public class CreateUserOptions : IOptions - { - - - public string PathOrganizationSid { get; } - - - public UserResource.ScimUser ScimUser { get; } - - - /// Construct a new CreateOrganizationUserOptions - /// - /// - public CreateUserOptions(string pathOrganizationSid, UserResource.ScimUser scimUser) - { - PathOrganizationSid = pathOrganizationSid; - ScimUser = scimUser; - } - - - /// Generate the request body - public string GetBody() - { - string body = ""; - - if (ScimUser != null) - { - body = UserResource.ToJson(ScimUser); - } - return body; - } - - - } - /// delete - public class DeleteUserOptions : IOptions - { - - - public string PathOrganizationSid { get; } - - - public string PathUserSid { get; } - - - - /// Construct a new DeleteOrganizationUserOptions - /// - /// - public DeleteUserOptions(string pathOrganizationSid, string pathUserSid) - { - PathOrganizationSid = pathOrganizationSid; - PathUserSid = pathUserSid; - } - - - /// Generate the necessary parameters - public List> GetParams() - { - var p = new List>(); - - return p; - } - - - - } - - - /// fetch - public class FetchUserOptions : IOptions - { - - - public string PathOrganizationSid { get; } - - - public string PathUserSid { get; } - - - - /// Construct a new FetchOrganizationUserOptions - /// - /// - public FetchUserOptions(string pathOrganizationSid, string pathUserSid) - { - PathOrganizationSid = pathOrganizationSid; - PathUserSid = pathUserSid; - } - - - /// Generate the necessary parameters - public List> GetParams() - { - var p = new List>(); - - return p; - } - - - - } - - - /// read - public class ReadUserOptions : ReadOptions - { - - - public string PathOrganizationSid { get; } - - - public string Filter { get; set; } - - - - /// Construct a new ListOrganizationUsersOptions - /// - public ReadUserOptions(string pathOrganizationSid) - { - PathOrganizationSid = pathOrganizationSid; - } - - - /// Generate the necessary parameters - public List> GetParams() - { - var p = new List>(); - - if (Filter != null) - { - p.Add(new KeyValuePair("filter", Filter)); - } - return p; - } - - - - } - - /// update - public class UpdateUserOptions : IOptions - { - - - public string PathOrganizationSid { get; } - - - public string PathUserSid { get; } - - - public UserResource.ScimUser ScimUser { get; } - - - public string IfMatch { get; set; } - - - - /// Construct a new UpdateOrganizationUserOptions - /// - /// - /// - public UpdateUserOptions(string pathOrganizationSid, string pathUserSid, UserResource.ScimUser scimUser) - { - PathOrganizationSid = pathOrganizationSid; - PathUserSid = pathUserSid; - ScimUser = scimUser; - } - - - /// Generate the request body - public string GetBody() - { - string body = ""; - - if (ScimUser != null) - { - body = UserResource.ToJson(ScimUser); - } - return body; - } - - /// Generate the necessary header parameters - public List> GetHeaderParams() - { - var p = new List>(); - if (IfMatch != null) - { - p.Add(new KeyValuePair("If-Match", IfMatch)); - } - return p; - } - - } - - -} - diff --git a/examples/csharp/src/Twilio/Rest/PreviewIam/Organizations/UserResource.cs b/examples/csharp/src/Twilio/Rest/PreviewIam/Organizations/UserResource.cs deleted file mode 100644 index dfc6671c5..000000000 --- a/examples/csharp/src/Twilio/Rest/PreviewIam/Organizations/UserResource.cs +++ /dev/null @@ -1,752 +0,0 @@ -/* - * This code was generated by - * ___ _ _ _ _ _ _ ____ ____ ____ _ ____ ____ _ _ ____ ____ ____ ___ __ __ - * | | | | | | | | | __ | | |__| | __ | __ |___ |\ | |___ |__/ |__| | | | |__/ - * | |_|_| | |___ | |__| |__| | | | |__] |___ | \| |___ | \ | | | |__| | \ - * - * Organization Public API - * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) - * - * NOTE: This class is auto generated by OpenAPI Generator. - * https://openapi-generator.tech - * Do not edit the class manually. - */ - - -using Newtonsoft.Json; -using System; -using System.Collections.Generic; -using Twilio.Base; -using Twilio.Clients; -using Twilio.Constant; -using Twilio.Converters; -using Twilio.Exceptions; -using Twilio.Http; - - - -namespace Twilio.Rest.PreviewIam.Organizations -{ - public class UserResource : Resource - { - - public class ScimName - { - [JsonProperty("givenName")] - private string GivenName {get; set;} - [JsonProperty("familyName")] - private string FamilyName {get; set;} - [JsonProperty("TestAnyType")] - private object TestAnyType {get; set;} - public ScimName() { } - public class Builder - { - private ScimName _scimName = new ScimName(); - public Builder() - { - } - public Builder WithGivenName(string givenName) - { - _scimName.GivenName= givenName; - return this; - } - public Builder WithFamilyName(string familyName) - { - _scimName.FamilyName= familyName; - return this; - } - public Builder WithTestAnyType(object testAnyType) - { - _scimName.TestAnyType= testAnyType; - return this; - } - public ScimName Build() - { - return _scimName; - } - } - } - public class ScimEmailAddress - { - [JsonProperty("primary")] - private bool? Primary {get; set;} - [JsonProperty("value")] - private string Value {get; set;} - [JsonProperty("type")] - private string Type {get; set;} - public ScimEmailAddress() { } - public class Builder - { - private ScimEmailAddress _scimEmailAddress = new ScimEmailAddress(); - public Builder() - { - } - public Builder WithPrimary(bool? primary) - { - _scimEmailAddress.Primary= primary; - return this; - } - public Builder WithValue(string value) - { - _scimEmailAddress.Value= value; - return this; - } - public Builder WithType(string type) - { - _scimEmailAddress.Type= type; - return this; - } - public ScimEmailAddress Build() - { - return _scimEmailAddress; - } - } - } - public class ScimMeta - { - [JsonProperty("resourceType")] - private string ResourceType {get; set;} - [JsonProperty("created")] - private DateTime? Created {get; set;} - [JsonProperty("lastModified")] - private DateTime? LastModified {get; set;} - [JsonProperty("version")] - private string Version {get; set;} - public ScimMeta() { } - public class Builder - { - private ScimMeta _scimMeta = new ScimMeta(); - public Builder() - { - } - public Builder WithResourceType(string resourceType) - { - _scimMeta.ResourceType= resourceType; - return this; - } - public Builder WithCreated(DateTime? created) - { - _scimMeta.Created= created; - return this; - } - public Builder WithLastModified(DateTime? lastModified) - { - _scimMeta.LastModified= lastModified; - return this; - } - public Builder WithVersion(string version) - { - _scimMeta.Version= version; - return this; - } - public ScimMeta Build() - { - return _scimMeta; - } - } - } - public class ScimUser - { - [JsonProperty("id")] - private string Id {get; set;} - [JsonProperty("externalId")] - private string ExternalId {get; set;} - [JsonProperty("userName")] - private string UserName {get; set;} - [JsonProperty("displayName")] - private string DisplayName {get; set;} - [JsonProperty("name")] - private ScimName Name {get; set;} - [JsonProperty("emails")] - private List Emails {get; set;} - [JsonProperty("active")] - private bool? Active {get; set;} - [JsonProperty("locale")] - private string Locale {get; set;} - [JsonProperty("timezone")] - private string Timezone {get; set;} - [JsonProperty("schemas")] - private List Schemas {get; set;} - [JsonProperty("meta")] - private ScimMeta Meta {get; set;} - public ScimUser() { } - public class Builder - { - private ScimUser _scimUser = new ScimUser(); - public Builder() - { - } - public Builder WithId(string id) - { - _scimUser.Id= id; - return this; - } - public Builder WithExternalId(string externalId) - { - _scimUser.ExternalId= externalId; - return this; - } - public Builder WithUserName(string userName) - { - _scimUser.UserName= userName; - return this; - } - public Builder WithDisplayName(string displayName) - { - _scimUser.DisplayName= displayName; - return this; - } - public Builder WithName(ScimName name) - { - _scimUser.Name= name; - return this; - } - public Builder WithEmails(List emails) - { - _scimUser.Emails= emails; - return this; - } - public Builder WithActive(bool? active) - { - _scimUser.Active= active; - return this; - } - public Builder WithLocale(string locale) - { - _scimUser.Locale= locale; - return this; - } - public Builder WithTimezone(string timezone) - { - _scimUser.Timezone= timezone; - return this; - } - public Builder WithSchemas(List schemas) - { - _scimUser.Schemas= schemas; - return this; - } - public Builder WithMeta(ScimMeta meta) - { - _scimUser.Meta= meta; - return this; - } - public ScimUser Build() - { - return _scimUser; - } - } - } - - - - - private static Request BuildCreateRequest(CreateUserOptions options, ITwilioRestClient client) - { - - string path = "/Organizations/{organizationSid}/scim/Users"; - - string PathOrganizationSid = options.PathOrganizationSid.ToString(); - path = path.Replace("{"+"organizationSid"+"}", PathOrganizationSid); - - return new Request( - HttpMethod.Post, - Rest.Domain.PreviewIam, - path, - - contentType: EnumConstants.ContentTypeEnum.JSON, - body: options.GetBody(), - headerParams: null - ); - } - - /// create - /// Create User parameters - /// Client to make requests to Twilio - /// A single instance of User - public static UserResource Create(CreateUserOptions options, ITwilioRestClient client = null) - { - client = client ?? TwilioClient.GetRestClient(); - var response = client.Request(BuildCreateRequest(options, client)); - return FromJson(response.Content); - } - - #if !NET35 - /// create - /// Create User parameters - /// Client to make requests to Twilio - /// Task that resolves to A single instance of User - public static async System.Threading.Tasks.Task CreateAsync(CreateUserOptions options, ITwilioRestClient client = null) - { - client = client ?? TwilioClient.GetRestClient(); - var response = await client.RequestAsync(BuildCreateRequest(options, client)); - return FromJson(response.Content); - } - #endif - - /// create - /// - /// - /// Client to make requests to Twilio - /// A single instance of User - public static UserResource Create( - string pathOrganizationSid, - UserResource.ScimUser scimUser, - ITwilioRestClient client = null) - { - var options = new CreateUserOptions(pathOrganizationSid, scimUser){ }; - return Create(options, client); - } - - #if !NET35 - /// create - /// - /// - /// Client to make requests to Twilio - /// Task that resolves to A single instance of User - public static async System.Threading.Tasks.Task CreateAsync( - string pathOrganizationSid, - UserResource.ScimUser scimUser, - ITwilioRestClient client = null) - { - var options = new CreateUserOptions(pathOrganizationSid, scimUser){ }; - return await CreateAsync(options, client); - } - #endif - - /// delete - /// Delete User parameters - /// Client to make requests to Twilio - /// A single instance of User - private static Request BuildDeleteRequest(DeleteUserOptions options, ITwilioRestClient client) - { - - string path = "/Organizations/{organizationSid}/scim/Users/{userSid}"; - - string PathOrganizationSid = options.PathOrganizationSid.ToString(); - path = path.Replace("{"+"organizationSid"+"}", PathOrganizationSid); - string PathUserSid = options.PathUserSid.ToString(); - path = path.Replace("{"+"userSid"+"}", PathUserSid); - - return new Request( - HttpMethod.Delete, - Rest.Domain.PreviewIam, - path, - queryParams: options.GetParams(), - headerParams: null - ); - } - - /// delete - /// Delete User parameters - /// Client to make requests to Twilio - /// A single instance of User - public static bool Delete(DeleteUserOptions options, ITwilioRestClient client = null) - { - client = client ?? TwilioClient.GetRestClient(); - var response = client.Request(BuildDeleteRequest(options, client)); - return response.StatusCode == System.Net.HttpStatusCode.NoContent; - } - - #if !NET35 - /// delete - /// Delete User parameters - /// Client to make requests to Twilio - /// Task that resolves to A single instance of User - public static async System.Threading.Tasks.Task DeleteAsync(DeleteUserOptions options, - ITwilioRestClient client = null) - { - client = client ?? TwilioClient.GetRestClient(); - var response = await client.RequestAsync(BuildDeleteRequest(options, client)); - return response.StatusCode == System.Net.HttpStatusCode.NoContent; - } - #endif - - /// delete - /// - /// - /// Client to make requests to Twilio - /// A single instance of User - public static bool Delete(string pathOrganizationSid, string pathUserSid, ITwilioRestClient client = null) - { - var options = new DeleteUserOptions(pathOrganizationSid, pathUserSid) ; - return Delete(options, client); - } - - #if !NET35 - /// delete - /// - /// - /// Client to make requests to Twilio - /// Task that resolves to A single instance of User - public static async System.Threading.Tasks.Task DeleteAsync(string pathOrganizationSid, string pathUserSid, ITwilioRestClient client = null) - { - var options = new DeleteUserOptions(pathOrganizationSid, pathUserSid) ; - return await DeleteAsync(options, client); - } - #endif - - private static Request BuildFetchRequest(FetchUserOptions options, ITwilioRestClient client) - { - - string path = "/Organizations/{organizationSid}/scim/Users/{userSid}"; - - string PathOrganizationSid = options.PathOrganizationSid.ToString(); - path = path.Replace("{"+"organizationSid"+"}", PathOrganizationSid); - string PathUserSid = options.PathUserSid.ToString(); - path = path.Replace("{"+"userSid"+"}", PathUserSid); - - return new Request( - HttpMethod.Get, - Rest.Domain.PreviewIam, - path, - queryParams: options.GetParams(), - headerParams: null - ); - } - - /// fetch - /// Fetch User parameters - /// Client to make requests to Twilio - /// A single instance of User - public static UserResource Fetch(FetchUserOptions options, ITwilioRestClient client = null) - { - client = client ?? TwilioClient.GetRestClient(); - var response = client.Request(BuildFetchRequest(options, client)); - return FromJson(response.Content); - } - - #if !NET35 - /// fetch - /// Fetch User parameters - /// Client to make requests to Twilio - /// Task that resolves to A single instance of User - public static async System.Threading.Tasks.Task FetchAsync(FetchUserOptions options, ITwilioRestClient client = null) - { - client = client ?? TwilioClient.GetRestClient(); - var response = await client.RequestAsync(BuildFetchRequest(options, client)); - return FromJson(response.Content); - } - #endif - /// fetch - /// - /// - /// Client to make requests to Twilio - /// A single instance of User - public static UserResource Fetch( - string pathOrganizationSid, - string pathUserSid, - ITwilioRestClient client = null) - { - var options = new FetchUserOptions(pathOrganizationSid, pathUserSid){ }; - return Fetch(options, client); - } - - #if !NET35 - /// fetch - /// - /// - /// Client to make requests to Twilio - /// Task that resolves to A single instance of User - public static async System.Threading.Tasks.Task FetchAsync(string pathOrganizationSid, string pathUserSid, ITwilioRestClient client = null) - { - var options = new FetchUserOptions(pathOrganizationSid, pathUserSid){ }; - return await FetchAsync(options, client); - } - #endif - - private static Request BuildReadRequest(ReadUserOptions options, ITwilioRestClient client) - { - - string path = "/Organizations/{organizationSid}/scim/Users"; - - string PathOrganizationSid = options.PathOrganizationSid.ToString(); - path = path.Replace("{"+"organizationSid"+"}", PathOrganizationSid); - - return new Request( - HttpMethod.Get, - Rest.Domain.PreviewIam, - path, - queryParams: options.GetParams(), - headerParams: null - ); - } - /// read - /// Read User parameters - /// Client to make requests to Twilio - /// A single instance of User - public static ResourceSet Read(ReadUserOptions options, ITwilioRestClient client = null) - { - client = client ?? TwilioClient.GetRestClient(); - var response = client.Request(BuildReadRequest(options, client)); - var page = Page.FromJson("Resources", response.Content); - return new ResourceSet(page, options, client); - } - - #if !NET35 - /// read - /// Read User parameters - /// Client to make requests to Twilio - /// Task that resolves to A single instance of User - public static async System.Threading.Tasks.Task> ReadAsync(ReadUserOptions options, ITwilioRestClient client = null) - { - client = client ?? TwilioClient.GetRestClient(); - var response = await client.RequestAsync(BuildReadRequest(options, client)); - - var page = Page.FromJson("Resources", response.Content); - return new ResourceSet(page, options, client); - } - #endif - /// read - /// - /// - /// Record limit - /// Client to make requests to Twilio - /// A single instance of User - public static ResourceSet Read( - string pathOrganizationSid, - string filter = null, - long? limit = null, - ITwilioRestClient client = null) - { - var options = new ReadUserOptions(pathOrganizationSid){ Filter = filter, Limit = limit}; - return Read(options, client); - } - - #if !NET35 - /// read - /// - /// - /// Record limit - /// Client to make requests to Twilio - /// Task that resolves to A single instance of User - public static async System.Threading.Tasks.Task> ReadAsync( - string pathOrganizationSid, - string filter = null, - long? limit = null, - ITwilioRestClient client = null) - { - var options = new ReadUserOptions(pathOrganizationSid){ Filter = filter, Limit = limit}; - return await ReadAsync(options, client); - } - #endif - - - /// Fetch the target page of records - /// API-generated URL for the requested results page - /// Client to make requests to Twilio - /// The target page of records - public static Page GetPage(string targetUrl, ITwilioRestClient client) - { - client = client ?? TwilioClient.GetRestClient(); - - var request = new Request( - HttpMethod.Get, - targetUrl - ); - - var response = client.Request(request); - return Page.FromJson("Resources", response.Content); - } - - /// Fetch the next page of records - /// current page of records - /// Client to make requests to Twilio - /// The next page of records - public static Page NextPage(Page page, ITwilioRestClient client) - { - var request = new Request( - HttpMethod.Get, - page.GetNextPageUrl(Rest.Domain.Api) - ); - - var response = client.Request(request); - return Page.FromJson("Resources", response.Content); - } - - /// Fetch the previous page of records - /// current page of records - /// Client to make requests to Twilio - /// The previous page of records - public static Page PreviousPage(Page page, ITwilioRestClient client) - { - var request = new Request( - HttpMethod.Get, - page.GetPreviousPageUrl(Rest.Domain.Api) - ); - - var response = client.Request(request); - return Page.FromJson("Resources", response.Content); - } - - - private static Request BuildUpdateRequest(UpdateUserOptions options, ITwilioRestClient client) - { - - string path = "/Organizations/{organizationSid}/scim/Users/{userSid}"; - - string PathOrganizationSid = options.PathOrganizationSid.ToString(); - path = path.Replace("{"+"organizationSid"+"}", PathOrganizationSid); - string PathUserSid = options.PathUserSid.ToString(); - path = path.Replace("{"+"userSid"+"}", PathUserSid); - - return new Request( - HttpMethod.Put, - Rest.Domain.PreviewIam, - path, - - contentType: EnumConstants.ContentTypeEnum.JSON, - body: options.GetBody(), - headerParams: options.GetHeaderParams() - ); - } - - /// update - /// Update User parameters - /// Client to make requests to Twilio - /// A single instance of User - public static UserResource Update(UpdateUserOptions options, ITwilioRestClient client = null) - { - client = client ?? TwilioClient.GetRestClient(); - var response = client.Request(BuildUpdateRequest(options, client)); - return FromJson(response.Content); - } - - /// update - /// Update User parameters - /// Client to make requests to Twilio - /// Task that resolves to A single instance of User - #if !NET35 - public static async System.Threading.Tasks.Task UpdateAsync(UpdateUserOptions options, - ITwilioRestClient client = null) - { - client = client ?? TwilioClient.GetRestClient(); - var response = await client.RequestAsync(BuildUpdateRequest(options, client)); - return FromJson(response.Content); - } - #endif - - /// update - /// - /// - /// - /// - /// Client to make requests to Twilio - /// A single instance of User - public static UserResource Update( - string pathOrganizationSid, - string pathUserSid, - UserResource.ScimUser scimUser, - string ifMatch = null, - ITwilioRestClient client = null) - { - var options = new UpdateUserOptions(pathOrganizationSid, pathUserSid, scimUser){ IfMatch = ifMatch }; - return Update(options, client); - } - - #if !NET35 - /// update - /// - /// - /// - /// - /// Client to make requests to Twilio - /// Task that resolves to A single instance of User - public static async System.Threading.Tasks.Task UpdateAsync( - string pathOrganizationSid, - string pathUserSid, - UserResource.ScimUser scimUser, - string ifMatch = null, - ITwilioRestClient client = null) - { - var options = new UpdateUserOptions(pathOrganizationSid, pathUserSid, scimUser){ IfMatch = ifMatch }; - return await UpdateAsync(options, client); - } - #endif - - /// - /// Converts a JSON string into a UserResource object - /// - /// Raw JSON string - /// UserResource object represented by the provided JSON - public static UserResource FromJson(string json) - { - try - { - return JsonConvert.DeserializeObject(json); - } - catch (JsonException e) - { - throw new ApiException(e.Message, e); - } - } - /// - /// Converts an object into a json string - /// - /// C# model - /// JSON string - public static string ToJson(object model) - { - try - { - return JsonConvert.SerializeObject(model); - } - catch (JsonException e) - { - throw new ApiException(e.Message, e); - } - } - - - /// Unique Twilio user sid - [JsonProperty("id")] - public string Id { get; private set; } - - /// External unique resource id defined by provisioning client - [JsonProperty("externalId")] - public string ExternalId { get; private set; } - - /// Unique username, MUST be same as primary email address - [JsonProperty("userName")] - public string UserName { get; } - - /// User friendly display name - [JsonProperty("displayName")] - public string DisplayName { get; private set; } - - /// The name - [JsonProperty("name")] - public ScimName Name { get; private set; } - - /// Email address list of the user. Primary email must be defined if there are more than 1 email. Primary email must match the username. - [JsonProperty("emails")] - public List Emails { get; private set; } - - /// Indicates whether the user is active - [JsonProperty("active")] - public bool? Active { get; private set; } - - /// User's locale - [JsonProperty("locale")] - public string Locale { get; private set; } - - /// User's time zone - [JsonProperty("timezone")] - public string Timezone { get; private set; } - - /// An array of URIs that indicate the schemas supported for this user resource - [JsonProperty("schemas")] - public List Schemas { get; private set; } - - /// The meta - [JsonProperty("meta")] - public ScimMeta Meta { get; private set; } - - - - private UserResource() { - - } - } -} - diff --git a/examples/csharp/src/Twilio/Rest/PreviewIam/V1/TokenOptions.cs b/examples/csharp/src/Twilio/Rest/PreviewIam/V1/TokenOptions.cs deleted file mode 100644 index 95adbbe9f..000000000 --- a/examples/csharp/src/Twilio/Rest/PreviewIam/V1/TokenOptions.cs +++ /dev/null @@ -1,110 +0,0 @@ -/* - * This code was generated by - * ___ _ _ _ _ _ _ ____ ____ ____ _ ____ ____ _ _ ____ ____ ____ ___ __ __ - * | | | | | | | | | __ | | |__| | __ | __ |___ |\ | |___ |__/ |__| | | | |__/ - * | |_|_| | |___ | |__| |__| | | | |__] |___ | \| |___ | \ | | | |__| | \ - * - * Organization Public API - * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) - * - * NOTE: This class is auto generated by OpenAPI Generator. - * https://openapi-generator.tech - * Do not edit the class manually. - */ - - -using System; -using System.Collections.Generic; -using Twilio.Base; -using Twilio.Converters; - - - - -namespace Twilio.Rest.PreviewIam.V1 -{ - - /// create - public class CreateTokenOptions : IOptions - { - - /// Grant type is a credential representing resource owner's authorization which can be used by client to obtain access token. - public string GrantType { get; } - - /// A 34 character string that uniquely identifies this OAuth App. - public string ClientId { get; } - - /// The credential for confidential OAuth App. - public string ClientSecret { get; set; } - - /// JWT token related to the authorization code grant type. - public string Code { get; set; } - - /// The redirect uri - public string RedirectUri { get; set; } - - /// The targeted audience uri - public string Audience { get; set; } - - /// JWT token related to refresh access token. - public string RefreshToken { get; set; } - - /// The scope of token - public string Scope { get; set; } - - - /// Construct a new CreateTokenOptions - /// Grant type is a credential representing resource owner's authorization which can be used by client to obtain access token. - /// A 34 character string that uniquely identifies this OAuth App. - public CreateTokenOptions(string grantType, string clientId) - { - GrantType = grantType; - ClientId = clientId; - } - - - /// Generate the necessary parameters - public List> GetParams() - { - var p = new List>(); - - if (GrantType != null) - { - p.Add(new KeyValuePair("grant_type", GrantType)); - } - if (ClientId != null) - { - p.Add(new KeyValuePair("client_id", ClientId)); - } - if (ClientSecret != null) - { - p.Add(new KeyValuePair("client_secret", ClientSecret)); - } - if (Code != null) - { - p.Add(new KeyValuePair("code", Code)); - } - if (RedirectUri != null) - { - p.Add(new KeyValuePair("redirect_uri", RedirectUri)); - } - if (Audience != null) - { - p.Add(new KeyValuePair("audience", Audience)); - } - if (RefreshToken != null) - { - p.Add(new KeyValuePair("refresh_token", RefreshToken)); - } - if (Scope != null) - { - p.Add(new KeyValuePair("scope", Scope)); - } - return p; - } - - - - } -} - diff --git a/examples/csharp/src/Twilio/Rest/PreviewIam/V1/TokenResource.cs b/examples/csharp/src/Twilio/Rest/PreviewIam/V1/TokenResource.cs deleted file mode 100644 index 311407ac9..000000000 --- a/examples/csharp/src/Twilio/Rest/PreviewIam/V1/TokenResource.cs +++ /dev/null @@ -1,192 +0,0 @@ -/* - * This code was generated by - * ___ _ _ _ _ _ _ ____ ____ ____ _ ____ ____ _ _ ____ ____ ____ ___ __ __ - * | | | | | | | | | __ | | |__| | __ | __ |___ |\ | |___ |__/ |__| | | | |__/ - * | |_|_| | |___ | |__| |__| | | | |__] |___ | \| |___ | \ | | | |__| | \ - * - * Organization Public API - * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) - * - * NOTE: This class is auto generated by OpenAPI Generator. - * https://openapi-generator.tech - * Do not edit the class manually. - */ - - -using Newtonsoft.Json; -using System; -using System.Collections.Generic; -using Twilio.Base; -using Twilio.Clients; -using Twilio.Constant; -using Twilio.Converters; -using Twilio.Exceptions; -using Twilio.Http; - - - -namespace Twilio.Rest.PreviewIam.V1 -{ - public class TokenResource : Resource - { - - - - - - private static Request BuildCreateRequest(CreateTokenOptions options, ITwilioRestClient client) - { - - string path = "/v1/token"; - - - return new Request( - HttpMethod.Post, - Rest.Domain.PreviewIam, - path, - contentType: EnumConstants.ContentTypeEnum.FORM_URLENCODED, - postParams: options.GetParams(), - headerParams: null - ); - } - - /// create - /// Create Token parameters - /// Client to make requests to Twilio - /// A single instance of Token - public static TokenResource Create(CreateTokenOptions options, ITwilioRestClient client = null) - { - client = client ?? TwilioClient.GetNoAuthRestClient(); - var response = client.Request(BuildCreateRequest(options, client)); - return FromJson(response.Content); - } - - #if !NET35 - /// create - /// Create Token parameters - /// Client to make requests to Twilio - /// Task that resolves to A single instance of Token - public static async System.Threading.Tasks.Task CreateAsync(CreateTokenOptions options, ITwilioRestClient client = null) - { - client = client ?? TwilioClient.GetNoAuthRestClient(); - var response = await client.RequestAsync(BuildCreateRequest(options, client)); - return FromJson(response.Content); - } - #endif - - /// create - /// Grant type is a credential representing resource owner's authorization which can be used by client to obtain access token. - /// A 34 character string that uniquely identifies this OAuth App. - /// The credential for confidential OAuth App. - /// JWT token related to the authorization code grant type. - /// The redirect uri - /// The targeted audience uri - /// JWT token related to refresh access token. - /// The scope of token - /// Client to make requests to Twilio - /// A single instance of Token - public static TokenResource Create( - string grantType, - string clientId, - string clientSecret = null, - string code = null, - string redirectUri = null, - string audience = null, - string refreshToken = null, - string scope = null, - ITwilioRestClient client = null) - { - var options = new CreateTokenOptions(grantType, clientId){ ClientSecret = clientSecret, Code = code, RedirectUri = redirectUri, Audience = audience, RefreshToken = refreshToken, Scope = scope }; - return Create(options, client); - } - - #if !NET35 - /// create - /// Grant type is a credential representing resource owner's authorization which can be used by client to obtain access token. - /// A 34 character string that uniquely identifies this OAuth App. - /// The credential for confidential OAuth App. - /// JWT token related to the authorization code grant type. - /// The redirect uri - /// The targeted audience uri - /// JWT token related to refresh access token. - /// The scope of token - /// Client to make requests to Twilio - /// Task that resolves to A single instance of Token - public static async System.Threading.Tasks.Task CreateAsync( - string grantType, - string clientId, - string clientSecret = null, - string code = null, - string redirectUri = null, - string audience = null, - string refreshToken = null, - string scope = null, - ITwilioRestClient client = null) - { - var options = new CreateTokenOptions(grantType, clientId){ ClientSecret = clientSecret, Code = code, RedirectUri = redirectUri, Audience = audience, RefreshToken = refreshToken, Scope = scope }; - return await CreateAsync(options, client); - } - #endif - - /// - /// Converts a JSON string into a TokenResource object - /// - /// Raw JSON string - /// TokenResource object represented by the provided JSON - public static TokenResource FromJson(string json) - { - try - { - return JsonConvert.DeserializeObject(json); - } - catch (JsonException e) - { - throw new ApiException(e.Message, e); - } - } - /// - /// Converts an object into a json string - /// - /// C# model - /// JSON string - public static string ToJson(object model) - { - try - { - return JsonConvert.SerializeObject(model); - } - catch (JsonException e) - { - throw new ApiException(e.Message, e); - } - } - - - /// Token which carries the necessary information to access a Twilio resource directly. - [JsonProperty("access_token")] - public string AccessToken { get; private set; } - - /// Token which carries the information necessary to get a new access token. - [JsonProperty("refresh_token")] - public string RefreshToken { get; private set; } - - /// Token which carries the information necessary of user profile. - [JsonProperty("id_token")] - public string IdToken { get; private set; } - - /// Token type - [JsonProperty("token_type")] - public string TokenType { get; private set; } - - /// The expires_in - [JsonProperty("expires_in")] - public long? ExpiresIn { get; private set; } - - - - private TokenResource() { - - } - } -} - diff --git a/examples/csharp/src/Twilio/Rest/Versionless/DeployedDevices/FleetOptions.cs b/examples/csharp/src/Twilio/Rest/Versionless/DeployedDevices/FleetOptions.cs index 9e36d9918..3ed78b086 100644 --- a/examples/csharp/src/Twilio/Rest/Versionless/DeployedDevices/FleetOptions.cs +++ b/examples/csharp/src/Twilio/Rest/Versionless/DeployedDevices/FleetOptions.cs @@ -49,6 +49,7 @@ public List> GetParams() } + /// fetch public class FetchFleetOptions : IOptions { diff --git a/examples/csharp/src/Twilio/Rest/Versionless/DeployedDevices/FleetResource.cs b/examples/csharp/src/Twilio/Rest/Versionless/DeployedDevices/FleetResource.cs index 3a561a96a..47ae97cd9 100644 --- a/examples/csharp/src/Twilio/Rest/Versionless/DeployedDevices/FleetResource.cs +++ b/examples/csharp/src/Twilio/Rest/Versionless/DeployedDevices/FleetResource.cs @@ -99,6 +99,7 @@ public static async System.Threading.Tasks.Task CreateAsync( return await CreateAsync(options, client); } #endif + private static Request BuildFetchRequest(FetchFleetOptions options, ITwilioRestClient client) { diff --git a/src/main/java/com/twilio/oai/api/CsharpApiResourceBuilder.java b/src/main/java/com/twilio/oai/api/CsharpApiResourceBuilder.java index c1c3f362d..54a086a6b 100644 --- a/src/main/java/com/twilio/oai/api/CsharpApiResourceBuilder.java +++ b/src/main/java/com/twilio/oai/api/CsharpApiResourceBuilder.java @@ -38,6 +38,14 @@ public class CsharpApiResourceBuilder extends ApiResourceBuilder { public String authMethod = ""; + /** + * List of C# primitive types that require a nullable marker (?) when nullable + */ + private static final Set CSHARP_PRIMITIVE_TYPES = new HashSet<>(Arrays.asList( + "int", "long", "float", "double", "decimal", "bool", "char", "byte", + "sbyte", "short", "ushort", "uint", "ulong", "DateTime" + )); + public CsharpApiResourceBuilder(IApiActionTemplate template, List codegenOperations, List allModels) { super(template, codegenOperations, allModels); @@ -92,6 +100,7 @@ public ApiResourceBuilder updateOperations(Resolver codegenPar super.updateOperations(codegenParameterIResolver); processAuthMethods(this.codegenOperationList); this.codegenOperationList.forEach(co -> { + co.allParams.forEach(this::handleNullableParameter); co.headerParams.forEach(e -> codegenParameterIResolver.resolve(e, this)); populateRequestBodyArgument(co); resolveIngressModel(co); @@ -231,28 +240,54 @@ public ApiResourceBuilder updateResponseModel(Resolver codegenP } public Set getDistinctResponseModel(List responseModels) { - HashSet modelVars = new HashSet<>(); + HashMap propertyMap = new HashMap<>(); Set distinctResponseModels = new LinkedHashSet<>(); + for (CodegenModel codegenModel: responseModels) { for (CodegenProperty property: codegenModel.vars) { property.nameInCamelCase = StringHelper.camelize(property.nameInSnakeCase); - Boolean isOverridden = property.isOverridden; - if(isOverridden != null && isOverridden == false) - property.isOverridden = null; + handleNullableProperty(property); + // Check for operation name conflicts or nested model name conflicts if (Arrays.stream(EnumConstants.Operation.values()) .anyMatch(value -> value.getValue().equals(property.nameInCamelCase)) || isNestedModelPresentWithPropertyName(property)) { property.nameInCamelCase = "_" + property.nameInCamelCase; } + + // Check if property with same name already exists, but has different metadata + // This handles cases where properties have the same name but different types or model flags + String propertyKey = property.name; + if (propertyMap.containsKey(propertyKey)) { + CodegenProperty existingProperty = propertyMap.get(propertyKey); + + // Check if the properties are functionally different enough to warrant duplication + // Only consider properties truly different if they have different data types + // Differences in isModel or isOverridden flags alone should not cause duplication + if (!Objects.equals(existingProperty.dataType, property.dataType)) { + property.nameInCamelCase = "_" + property.nameInCamelCase; + } else { + // If they're functionally the same (same data type), merge any metadata if needed + // and skip adding this property + continue; + } + } + + // Store the property in the map for future duplicate checks + propertyMap.put(propertyKey, property); distinctResponseModels.add(property); - property.isOverridden = isOverridden; } } - for(CodegenProperty s : distinctResponseModels){ - if(modelVars.contains(s.name)){ - s.nameInCamelCase = "_" + s.nameInCamelCase; - }else modelVars.add(s.nameInCamelCase); + + // Final check for name collisions in camelCase names (which are used in C# code) + HashSet modelVars = new HashSet<>(); + for (CodegenProperty property : distinctResponseModels) { + if (modelVars.contains(property.nameInCamelCase)) { + property.nameInCamelCase = "_" + property.nameInCamelCase; + } else { + modelVars.add(property.nameInCamelCase); + } } + return distinctResponseModels; } @@ -358,4 +393,36 @@ public boolean isNestedModelPresentWithPropertyName(final CodegenProperty proper .findFirst(); return foundModel.isPresent(); } + + /** + * Handle nullable property in C# by appending "?" to primitive types when nullable. + * Reference types (arrays, objects, custom classes) are already nullable in C#. + * + * @param property The CodegenProperty to process + */ + protected void handleNullableProperty(CodegenProperty property) { + if (property.isNullable && !property.dataType.endsWith("?")) { + // Only add nullable marker to primitive types + if (CSHARP_PRIMITIVE_TYPES.contains(property.dataType)) { + property.dataType = property.dataType + "?"; + } + } + } + + protected void handleNullableParameter(CodegenParameter parameter) { + CodegenModel model = getModel(parameter.dataType); + if(model != null) { + for(CodegenProperty property: model.vars) { + handleNullableProperty(property); + } + } + else { + if (parameter.isNullable && !parameter.dataType.endsWith("?")) { + // Only add nullable marker to primitive types + if (CSHARP_PRIMITIVE_TYPES.contains(parameter.dataType)) { + parameter.dataType = parameter.dataType + "?"; + } + } + } + } } diff --git a/src/main/resources/META-INF/services/org.openapitools.codegen.CodegenConfig b/src/main/resources/META-INF/services/org.openapitools.codegen.CodegenConfig index 9f3dba485..0a6a5b370 100644 --- a/src/main/resources/META-INF/services/org.openapitools.codegen.CodegenConfig +++ b/src/main/resources/META-INF/services/org.openapitools.codegen.CodegenConfig @@ -4,6 +4,5 @@ com.twilio.oai.TwilioJavaGenerator com.twilio.oai.TwilioJavaGeneratorModern com.twilio.oai.TwilioNodeGenerator com.twilio.oai.TwilioPhpGenerator -com.twilio.oai.TwilioPythonGenerator com.twilio.oai.TwilioRubyGenerator com.twilio.oai.TwilioTerraformGenerator diff --git a/src/main/resources/twilio-csharp/options/CreateOptions.mustache b/src/main/resources/twilio-csharp/options/CreateOptions.mustache index eaf5745be..953df3bb4 100644 --- a/src/main/resources/twilio-csharp/options/CreateOptions.mustache +++ b/src/main/resources/twilio-csharp/options/CreateOptions.mustache @@ -19,11 +19,11 @@ } {{/vendorExtensions.x-required-param-exists}} - {{^vendorExtensions.x-is-json}} + {{^bodyParams.0}} {{>options/GetParams}} - {{/vendorExtensions.x-is-json}} - {{#vendorExtensions.x-is-json}} + {{/bodyParams.0}} + {{#bodyParams.0}} {{>options/GetBody}} - {{/vendorExtensions.x-is-json}} + {{/bodyParams.0}} {{>options/HeaderParams}} - } \ No newline at end of file + } diff --git a/src/main/resources/twilio-csharp/options/DeleteOptions.mustache b/src/main/resources/twilio-csharp/options/DeleteOptions.mustache index 81a89826d..22e07f4d3 100644 --- a/src/main/resources/twilio-csharp/options/DeleteOptions.mustache +++ b/src/main/resources/twilio-csharp/options/DeleteOptions.mustache @@ -19,12 +19,7 @@ } {{/vendorExtensions.x-required-param-exists}} - {{^vendorExtensions.x-is-json}} {{>options/GetParams}} - {{/vendorExtensions.x-is-json}} - {{#vendorExtensions.x-is-json}} - {{>options/GetBody}} - {{/vendorExtensions.x-is-json}} {{>options/HeaderParams}} } diff --git a/src/main/resources/twilio-csharp/options/FetchOptions.mustache b/src/main/resources/twilio-csharp/options/FetchOptions.mustache index 3f37646c3..7b9034ef4 100644 --- a/src/main/resources/twilio-csharp/options/FetchOptions.mustache +++ b/src/main/resources/twilio-csharp/options/FetchOptions.mustache @@ -19,12 +19,7 @@ } {{/vendorExtensions.x-required-param-exists}} - {{^vendorExtensions.x-is-json}} {{>options/GetParams}} - {{/vendorExtensions.x-is-json}} - {{#vendorExtensions.x-is-json}} - {{>options/GetBody}} - {{/vendorExtensions.x-is-json}} {{>options/HeaderParams}} } diff --git a/src/main/resources/twilio-csharp/options/GetBody.mustache b/src/main/resources/twilio-csharp/options/GetBody.mustache index 070e3b328..6b00d461e 100644 --- a/src/main/resources/twilio-csharp/options/GetBody.mustache +++ b/src/main/resources/twilio-csharp/options/GetBody.mustache @@ -4,7 +4,6 @@ { string body = ""; - {{#vendorExtensions.x-getparams}} {{^isArray}} {{^vendorExtensions.x-parameter-map}} if ({{paramName}} != null) @@ -13,6 +12,5 @@ } {{/vendorExtensions.x-parameter-map}} {{/isArray}} - {{/vendorExtensions.x-getparams}} return body; - } \ No newline at end of file + } diff --git a/src/main/resources/twilio-csharp/options/ReadOptions.mustache b/src/main/resources/twilio-csharp/options/ReadOptions.mustache index e77a9f95e..06f74cf8b 100644 --- a/src/main/resources/twilio-csharp/options/ReadOptions.mustache +++ b/src/main/resources/twilio-csharp/options/ReadOptions.mustache @@ -19,11 +19,6 @@ } {{/vendorExtensions.x-required-param-exists}} - {{^vendorExtensions.x-is-json}} {{>options/GetParams}} - {{/vendorExtensions.x-is-json}} - {{#vendorExtensions.x-is-json}} - {{>options/GetBody}} - {{/vendorExtensions.x-is-json}} {{>options/HeaderParams}} } diff --git a/src/main/resources/twilio-csharp/options/UpdateOptions.mustache b/src/main/resources/twilio-csharp/options/UpdateOptions.mustache index 237d43f5e..a2060d929 100644 --- a/src/main/resources/twilio-csharp/options/UpdateOptions.mustache +++ b/src/main/resources/twilio-csharp/options/UpdateOptions.mustache @@ -19,12 +19,12 @@ } {{/vendorExtensions.x-required-param-exists}} - {{^vendorExtensions.x-is-json}} + {{^bodyParams.0}} {{>options/GetParams}} - {{/vendorExtensions.x-is-json}} - {{#vendorExtensions.x-is-json}} + {{/bodyParams.0}} + {{#bodyParams.0}} {{>options/GetBody}} - {{/vendorExtensions.x-is-json}} + {{/bodyParams.0}} {{>options/HeaderParams}} } diff --git a/src/main/resources/twilio-csharp/resource/CreateResource.mustache b/src/main/resources/twilio-csharp/resource/CreateResource.mustache index 7348e8e04..4b6fb8618 100644 --- a/src/main/resources/twilio-csharp/resource/CreateResource.mustache +++ b/src/main/resources/twilio-csharp/resource/CreateResource.mustache @@ -6,13 +6,13 @@ {{vendorExtensions.x-http-method}}, Rest.Domain.{{domainPackage}}, path, - {{^vendorExtensions.x-is-json}} + {{^bodyParams.0}} contentType: EnumConstants.ContentTypeEnum.FORM_URLENCODED, - postParams: options.GetParams(),{{/vendorExtensions.x-is-json}} - {{#vendorExtensions.x-is-json}} + postParams: options.GetParams(),{{/bodyParams.0}} + {{#bodyParams.0}} contentType: EnumConstants.ContentTypeEnum.JSON, body: options.GetBody(), - {{/vendorExtensions.x-is-json}} + {{/bodyParams.0}} headerParams: {{^vendorExtensions.hasOptionalHeaderParams}}null{{/vendorExtensions.hasOptionalHeaderParams}}{{#vendorExtensions.hasOptionalHeaderParams}}options.GetHeaderParams(){{/vendorExtensions.hasOptionalHeaderParams}} ); } @@ -61,4 +61,4 @@ var options = new Create{{apiName}}Options({{#requiredParams}}{{#lambda.camelcase}}{{paramName}}{{/lambda.camelcase}}{{^-last}}, {{/-last}}{{/requiredParams}}){ {{#vendorExtensions.x-request-body-param}}{{^required}} {{paramName}} = {{#lambda.camelcase}}{{paramName}}{{/lambda.camelcase}}{{^-last}},{{/-last}}{{/required}}{{/vendorExtensions.x-request-body-param}} }; return await CreateAsync(options, client); } - #endif \ No newline at end of file + #endif diff --git a/src/main/resources/twilio-csharp/resource/UpdateResource.mustache b/src/main/resources/twilio-csharp/resource/UpdateResource.mustache index 036ef5935..1584db2c0 100644 --- a/src/main/resources/twilio-csharp/resource/UpdateResource.mustache +++ b/src/main/resources/twilio-csharp/resource/UpdateResource.mustache @@ -6,13 +6,13 @@ {{vendorExtensions.x-http-method}}, Rest.Domain.{{domainPackage}}, path, - {{^vendorExtensions.x-is-json}} + {{^bodyParams.0}} contentType: EnumConstants.ContentTypeEnum.FORM_URLENCODED, - postParams: options.GetParams(),{{/vendorExtensions.x-is-json}} - {{#vendorExtensions.x-is-json}} + postParams: options.GetParams(),{{/bodyParams.0}} + {{#bodyParams.0}} contentType: EnumConstants.ContentTypeEnum.JSON, body: options.GetBody(), - {{/vendorExtensions.x-is-json}} + {{/bodyParams.0}} headerParams: {{^vendorExtensions.x-header-param-exists}}null{{/vendorExtensions.x-header-param-exists}}{{#vendorExtensions.x-header-param-exists}}options.GetHeaderParams(){{/vendorExtensions.x-header-param-exists}} ); } @@ -62,4 +62,4 @@ var options = new Update{{apiName}}Options({{#requiredParams}}{{#lambda.camelcase}}{{paramName}}{{/lambda.camelcase}}{{^-last}}, {{/-last}}{{/requiredParams}}){ {{#vendorExtensions.x-request-body-param}}{{^required}}{{paramName}} = {{#lambda.camelcase}}{{paramName}}{{/lambda.camelcase}}{{^-last}}, {{/-last}}{{/required}}{{/vendorExtensions.x-request-body-param}} }; return await UpdateAsync(options, client); } - #endif \ No newline at end of file + #endif From 63a6ffbefd36dbd3ca005e1bd2c7629c2cef8a5e Mon Sep 17 00:00:00 2001 From: sbansla Date: Wed, 5 Nov 2025 14:06:45 +0530 Subject: [PATCH 35/38] added optional properties for model --- .../java/com/twilio/oai/java/nestedmodels/MustacheModel.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/com/twilio/oai/java/nestedmodels/MustacheModel.java b/src/main/java/com/twilio/oai/java/nestedmodels/MustacheModel.java index a09070b61..e9d657c32 100644 --- a/src/main/java/com/twilio/oai/java/nestedmodels/MustacheModel.java +++ b/src/main/java/com/twilio/oai/java/nestedmodels/MustacheModel.java @@ -44,6 +44,10 @@ public MustacheModel(CodegenParameter codegenParameter, CodegenModel codegenMode this.mandatoryProperties = codegenModel.vars.stream() .filter(codegenProperty1 -> codegenProperty1.required) .collect(Collectors.toList()); + + this.optionalProperties = codegenModel.vars.stream() + .filter(codegenProperty1 -> !codegenProperty1.required) + .collect(Collectors.toList()); } public MustacheModel(String className, List mandatoryProperties, List allProperties) { From 4d03ba4f6ddbea3747b1724b17425a9760aedee9 Mon Sep 17 00:00:00 2001 From: kridai Date: Wed, 5 Nov 2025 14:56:02 +0530 Subject: [PATCH 36/38] fix: Python generator fix for 7.x open api generator (#693) FIxes : DII-2054 # Fixes # Made a few updates to support twilio-python backward compatibility with 7.x version - moved FieldValueResolver to last since that prevents reflective access, which is the safer default (prefer getters and map entries over raw field access). - Added staticReservedWords for backward compatibility twilio-python generated changes befor and after upgrade are here https://github.com/twilio/twilio-python/pull/891/files ### Checklist - [x] I acknowledge that all my contributions will be made under the project's license - [ ] Run `make test-docker` - [ ] Verify affected language: - [ ] Generate [twilio-go](https://github.com/twilio/twilio-go) from our [OpenAPI specification](https://github.com/twilio/twilio-oai) using the [build_twilio_go.py](./examples/build_twilio_go.py) using `python examples/build_twilio_go.py path/to/twilio-oai/spec/yaml path/to/twilio-go` and inspect the diff - [ ] Run `make test` in `twilio-go` - [ ] Create a pull request in `twilio-go` - [ ] Provide a link below to the pull request - [ ] I have made a material change to the repo (functionality, testing, spelling, grammar) - [ ] I have read the [Contribution Guidelines](https://github.com/twilio/twilio-oai-generator/blob/main/CONTRIBUTING.md) and my PR follows them - [ ] I have titled the PR appropriately - [ ] I have updated my branch with the main branch - [ ] I have added tests that prove my fix is effective or that my feature works - [ ] I have added the necessary documentation about the functionality in the appropriate .md file - [ ] I have added inline documentation to the code I modified If you have questions, please create a GitHub Issue in this repository. --- .../twilio/oai/DirectoryStructureService.java | 3 +- .../com/twilio/oai/TwilioPythonGenerator.java | 290 +++++++++--------- .../TwilioHandlebarsEngineAdapter.java | 4 +- .../org.openapitools.codegen.CodegenConfig | 1 + 4 files changed, 151 insertions(+), 147 deletions(-) diff --git a/src/main/java/com/twilio/oai/DirectoryStructureService.java b/src/main/java/com/twilio/oai/DirectoryStructureService.java index 339eda529..e2b3e118e 100644 --- a/src/main/java/com/twilio/oai/DirectoryStructureService.java +++ b/src/main/java/com/twilio/oai/DirectoryStructureService.java @@ -251,10 +251,9 @@ public List processOperations(final OperationsMap results) { for(CodegenOperation co : operations){ if(co.produces != null) for(Map map : co.produces){ - Map.Entry firstEntry = map.entrySet().iterator().next(); List> successProduce = new ArrayList<>(); Map successMap = new HashMap<>(); - successMap.put(firstEntry.getKey(), firstEntry.getValue()); + successMap.putAll(map); successProduce.add(successMap); co.vendorExtensions.put("successProduce", successProduce); break; diff --git a/src/main/java/com/twilio/oai/TwilioPythonGenerator.java b/src/main/java/com/twilio/oai/TwilioPythonGenerator.java index 0087b2479..70b2286d0 100644 --- a/src/main/java/com/twilio/oai/TwilioPythonGenerator.java +++ b/src/main/java/com/twilio/oai/TwilioPythonGenerator.java @@ -1,152 +1,156 @@ +package com.twilio.oai; + +import com.twilio.oai.api.ApiResources; +import com.twilio.oai.api.PythonApiResourceBuilder; import com.twilio.oai.common.EnumConstants; +import com.twilio.oai.common.Utility; +import com.twilio.oai.resolver.IConventionMapper; +import com.twilio.oai.resolver.LanguageConventionResolver; +import com.twilio.oai.resolver.python.PythonCodegenModelResolver; +import com.twilio.oai.resolver.python.PythonCaseResolver; +import com.twilio.oai.resolver.python.PythonParameterResolver; +import com.twilio.oai.resolver.python.PythonPropertyResolver; +import com.twilio.oai.resource.IResourceTree; +import com.twilio.oai.resource.ResourceMap; +import com.twilio.oai.template.PythonApiActionTemplate; + +import java.io.File; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import io.swagger.v3.oas.models.OpenAPI; +import io.swagger.v3.oas.models.PathItem; +import org.openapitools.codegen.CodegenModel; +import org.openapitools.codegen.CodegenOperation; import org.openapitools.codegen.languages.PythonClientCodegen; +import org.openapitools.codegen.model.ModelMap; +import org.openapitools.codegen.model.ModelsMap; +import org.openapitools.codegen.model.OperationsMap; + +import static com.twilio.oai.common.ApplicationConstants.CONFIG_PYTHON_JSON_PATH; -//package com.twilio.oai; -// -//import com.twilio.oai.api.ApiResources; -//import com.twilio.oai.api.PythonApiResourceBuilder; -//import com.twilio.oai.common.EnumConstants; -//import com.twilio.oai.common.Utility; -//import com.twilio.oai.resolver.IConventionMapper; -//import com.twilio.oai.resolver.LanguageConventionResolver; -//import com.twilio.oai.resolver.python.PythonCodegenModelResolver; -//import com.twilio.oai.resolver.python.PythonCaseResolver; -//import com.twilio.oai.resolver.python.PythonParameterResolver; -//import com.twilio.oai.resolver.python.PythonPropertyResolver; -//import com.twilio.oai.resource.IResourceTree; -//import com.twilio.oai.resource.ResourceMap; -//import com.twilio.oai.template.PythonApiActionTemplate; -// -//import java.io.File; -//import java.util.ArrayList; -//import java.util.HashMap; -//import java.util.List; -//import java.util.Map; -// -//import io.swagger.v3.oas.models.OpenAPI; -//import io.swagger.v3.oas.models.PathItem; -//import org.openapitools.codegen.CodegenModel; -//import org.openapitools.codegen.CodegenOperation; -//import org.openapitools.codegen.languages.PythonClientCodegen; -////import org.openapitools.codegen.languages.PythonLegacyClientCodegen; -//import org.openapitools.codegen.model.ModelMap; -//import org.openapitools.codegen.model.ModelsMap; -//import org.openapitools.codegen.model.OperationsMap; -// -//import static com.twilio.oai.common.ApplicationConstants.CONFIG_PYTHON_JSON_PATH; -// public class TwilioPythonGenerator extends PythonClientCodegen { -// private final TwilioCodegenAdapter twilioCodegen; -// private final PythonApiActionTemplate actionTemplate = new PythonApiActionTemplate(this); -// private final IResourceTree resourceTree = new ResourceMap(new Inflector()); -// private final DirectoryStructureService directoryStructureService = new DirectoryStructureService( -// additionalProperties, -// resourceTree, -// new PythonCaseResolver()); -// private final List allModels = new ArrayList<>(); -// private final Map modelFormatMap = new HashMap<>(); -// public static final String JSON_INGRESS = "json_ingress"; -// -// public TwilioPythonGenerator() { -// super(); -// twilioCodegen = new TwilioCodegenAdapter(this, getName()); -// packageName = ""; -// -// typeMapping.put("array", "List"); -// } -// -// @Override -// public void processOpts() { -// twilioCodegen.processOpts(); -// } -// -// @Override -// public void processOpenAPI(final OpenAPI openAPI) { -// String domain = StringHelper.toSnakeCase(twilioCodegen.getDomainFromOpenAPI(openAPI)); -// String version = StringHelper.toSnakeCase(twilioCodegen.getVersionFromOpenAPI(openAPI)); -// twilioCodegen.setDomain(domain); -// twilioCodegen.setVersion(version); -// twilioCodegen.setOutputDir(domain, version); -// -// openAPI.getPaths().forEach(resourceTree::addResource); -// resourceTree.getResources().forEach(resource -> resource.updateFamily(resourceTree)); -// -// directoryStructureService.configure(openAPI); -// } -// -// @Override -// public String apiFilename(final String templateName, final String tag) { -// final String initFilename = "__init__.py"; -// final String filename = actionTemplate.apiFilename(templateName, super.apiFilename(templateName, tag)); -// -// final boolean isInitFile = this.openAPI.getPaths().entrySet().stream().anyMatch(pathsEntry -> { -// final String resourcePath = pathsEntry.getKey(); -// final PathItem path = pathsEntry.getValue(); -// final boolean isMatchingPath = path -// .readOperations() -// .stream() -// .anyMatch(operation -> operation.getTags().contains(tag)); -// final boolean pathHasDependents = !resourceTree.dependents(resourcePath).isEmpty(); -// -// return isMatchingPath && pathHasDependents; -// }); -// -// if (isInitFile && !filename.endsWith(initFilename)) { -// return PathUtils.removeExtension(filename) + File.separator + initFilename; -// } -// -// return filename; -// } -// -// @Override -// public String toApiFilename(final String name) { -// return directoryStructureService.toApiFilename(name); -// } -// -// @Override -// public Map postProcessAllModels(final Map allModels) { -// final Map results = super.postProcessAllModels(allModels); -// -// Utility.addModelsToLocalModelList(results, this.allModels); -// directoryStructureService.postProcessAllModels(results, modelFormatMap); -// -// // Return an empty collection so no model files get generated. -// return new HashMap<>(); -// } -// -// @Override -// public OperationsMap postProcessOperationsWithModels(final OperationsMap objs, List allModels) { -// final List opList = directoryStructureService.processOperations(objs); -// objs.put("resources", generateResources(opList)); -// return objs; -// } -// -// private ApiResources generateResources(final List opList) { -// final IConventionMapper conventionMapper = new LanguageConventionResolver(CONFIG_PYTHON_JSON_PATH); -// final PythonCodegenModelResolver codegenModelResolver = new PythonCodegenModelResolver(conventionMapper, -// modelFormatMap, -// List.of(EnumConstants.PythonDataTypes.values())); -// -// PythonApiResourceBuilder pythonApiResourceBuilder = new PythonApiResourceBuilder(actionTemplate, opList, allModels, directoryStructureService, twilioCodegen.getToggles(JSON_INGRESS)); -// pythonApiResourceBuilder.updateApiPath() -// .updateTemplate() -// .updateOperations(new PythonParameterResolver(conventionMapper, codegenModelResolver)); -// return pythonApiResourceBuilder.updateResponseModel(new PythonPropertyResolver(conventionMapper), codegenModelResolver) -// .build(); -// } -// + private final TwilioCodegenAdapter twilioCodegen; + private final PythonApiActionTemplate actionTemplate = new PythonApiActionTemplate(this); + private final IResourceTree resourceTree = new ResourceMap(new Inflector()); + private final DirectoryStructureService directoryStructureService = new DirectoryStructureService( + additionalProperties, + resourceTree, + new PythonCaseResolver()); + private final List allModels = new ArrayList<>(); + private final Map modelFormatMap = new HashMap<>(); + public static final String JSON_INGRESS = "json_ingress"; + + public TwilioPythonGenerator() { + super(); + twilioCodegen = new TwilioCodegenAdapter(this, getName()); + packageName = ""; + + typeMapping.put("array", "List"); + } + + @Override + public void processOpts() { + twilioCodegen.processOpts(); + // setting this since oai generator is prefixing var_ for reserved words + Map staticReservedWords = Map.of( + "date", "date", + "from", "_from", + "field", "field" + ); + + staticReservedWords.forEach((key, value) -> reservedWordsMappings().put(key, value)); + } + + @Override + public void processOpenAPI(final OpenAPI openAPI) { + String domain = StringHelper.toSnakeCase(twilioCodegen.getDomainFromOpenAPI(openAPI)); + String version = StringHelper.toSnakeCase(twilioCodegen.getVersionFromOpenAPI(openAPI)); + twilioCodegen.setDomain(domain); + twilioCodegen.setVersion(version); + twilioCodegen.setOutputDir(domain, version); + + openAPI.getPaths().forEach(resourceTree::addResource); + resourceTree.getResources().forEach(resource -> resource.updateFamily(resourceTree)); + + directoryStructureService.configure(openAPI); + } + + @Override + public String apiFilename(final String templateName, final String tag) { + final String initFilename = "__init__.py"; + final String filename = actionTemplate.apiFilename(templateName, super.apiFilename(templateName, tag)); + + final boolean isInitFile = this.openAPI.getPaths().entrySet().stream().anyMatch(pathsEntry -> { + final String resourcePath = pathsEntry.getKey(); + final PathItem path = pathsEntry.getValue(); + final boolean isMatchingPath = path + .readOperations() + .stream() + .anyMatch(operation -> operation.getTags().contains(tag)); + final boolean pathHasDependents = !resourceTree.dependents(resourcePath).isEmpty(); + + return isMatchingPath && pathHasDependents; + }); + + if (isInitFile && !filename.endsWith(initFilename)) { + return PathUtils.removeExtension(filename) + File.separator + initFilename; + } + + return filename; + } + + @Override + public String toApiFilename(final String name) { + return directoryStructureService.toApiFilename(name); + } + + @Override + public Map postProcessAllModels(final Map allModels) { + final Map results = super.postProcessAllModels(allModels); + + Utility.addModelsToLocalModelList(results, this.allModels); + directoryStructureService.postProcessAllModels(results, modelFormatMap); + + // Return an empty collection so no model files get generated. + return new HashMap<>(); + } + + @Override + public OperationsMap postProcessOperationsWithModels(final OperationsMap objs, List allModels) { + final List opList = directoryStructureService.processOperations(objs); + objs.put("resources", generateResources(opList)); + return objs; + } + + private ApiResources generateResources(final List opList) { + final IConventionMapper conventionMapper = new LanguageConventionResolver(CONFIG_PYTHON_JSON_PATH); + final PythonCodegenModelResolver codegenModelResolver = new PythonCodegenModelResolver(conventionMapper, + modelFormatMap, + List.of(EnumConstants.PythonDataTypes.values())); + + PythonApiResourceBuilder pythonApiResourceBuilder = new PythonApiResourceBuilder(actionTemplate, opList, allModels, directoryStructureService, twilioCodegen.getToggles(JSON_INGRESS)); + pythonApiResourceBuilder.updateApiPath() + .updateTemplate() + .updateOperations(new PythonParameterResolver(conventionMapper, codegenModelResolver)); + return pythonApiResourceBuilder.updateResponseModel(new PythonPropertyResolver(conventionMapper), codegenModelResolver) + .build(); + } + @Override public String getName() { return EnumConstants.Generator.TWILIO_PYTHON.getValue(); } -// -// @Override -// public String toParamName(final String name) { -// return StringHelper.toSnakeCase(twilioCodegen.toParamName(name)); -// } -// -// @Override -// public String defaultTemplatingEngine() { -// return "twilio-handlebars"; -// } + + @Override + public String toParamName(final String name) { + return StringHelper.toSnakeCase(twilioCodegen.toParamName(name)); + } + + @Override + public String defaultTemplatingEngine() { + return "twilio-handlebars"; + } } diff --git a/src/main/java/com/twilio/oai/templating/TwilioHandlebarsEngineAdapter.java b/src/main/java/com/twilio/oai/templating/TwilioHandlebarsEngineAdapter.java index 8badacd90..ee6441103 100644 --- a/src/main/java/com/twilio/oai/templating/TwilioHandlebarsEngineAdapter.java +++ b/src/main/java/com/twilio/oai/templating/TwilioHandlebarsEngineAdapter.java @@ -41,8 +41,8 @@ public TemplateSource sourceAt(final String location) { .newBuilder(bundle) .resolver(MapValueResolver.INSTANCE, JavaBeanValueResolver.INSTANCE, - FieldValueResolver.INSTANCE, - MethodValueResolver.INSTANCE) + MethodValueResolver.INSTANCE, + FieldValueResolver.INSTANCE) .build(); final Handlebars handlebars = new Handlebars(loader); diff --git a/src/main/resources/META-INF/services/org.openapitools.codegen.CodegenConfig b/src/main/resources/META-INF/services/org.openapitools.codegen.CodegenConfig index 0a6a5b370..096960d4a 100644 --- a/src/main/resources/META-INF/services/org.openapitools.codegen.CodegenConfig +++ b/src/main/resources/META-INF/services/org.openapitools.codegen.CodegenConfig @@ -6,3 +6,4 @@ com.twilio.oai.TwilioNodeGenerator com.twilio.oai.TwilioPhpGenerator com.twilio.oai.TwilioRubyGenerator com.twilio.oai.TwilioTerraformGenerator +com.twilio.oai.TwilioPythonGenerator From 20f3f0779311cfe089d5690afa963ccff030de92 Mon Sep 17 00:00:00 2001 From: sbansla Date: Wed, 5 Nov 2025 16:30:30 +0530 Subject: [PATCH 37/38] chore: java added apistandard validation --- .../java/com/twilio/oai/TwilioJavaGeneratorModern.java | 10 ++++++++++ .../com/twilio/oai/common/ApplicationConstants.java | 3 +-- src/main/java/com/twilio/oai/java/JavaApiResource.java | 2 ++ .../java/com/twilio/oai/java/cache/ResourceCache2.java | 4 ++++ 4 files changed, 17 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/twilio/oai/TwilioJavaGeneratorModern.java b/src/main/java/com/twilio/oai/TwilioJavaGeneratorModern.java index 5cced9f22..20cb24a60 100644 --- a/src/main/java/com/twilio/oai/TwilioJavaGeneratorModern.java +++ b/src/main/java/com/twilio/oai/TwilioJavaGeneratorModern.java @@ -2,6 +2,7 @@ import com.google.common.collect.ImmutableMap; import com.samskivert.mustache.Mustache.Lambda; +import com.twilio.oai.common.ApplicationConstants; import com.twilio.oai.common.EnumConstants; import com.twilio.oai.common.Utility; import com.twilio.oai.java.JavaApiResource; @@ -22,6 +23,7 @@ import org.openapitools.codegen.model.OperationsMap; import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.List; import java.util.Map; @@ -64,6 +66,14 @@ public void processOpts() { // Run once per spec @Override public void processOpenAPI(final OpenAPI openAPI) { + String apiStdVersion = null; + if (openAPI.getInfo().getExtensions() != null && openAPI.getInfo().getExtensions().containsKey("x-twilio")) { + LinkedHashMap xTwilio = (LinkedHashMap)openAPI.getInfo().getExtensions().get("x-twilio"); + apiStdVersion = (String) xTwilio.get("apiStandards"); + } + boolean isV1 = ApplicationConstants.isV1.test(apiStdVersion); + ResourceCacheContext.get().setV1(isV1); + String domain = twilioCodegen.getDomainFromOpenAPI(openAPI); String version = twilioCodegen.getVersionFromOpenAPI(openAPI); twilioCodegen.setDomain(domain); diff --git a/src/main/java/com/twilio/oai/common/ApplicationConstants.java b/src/main/java/com/twilio/oai/common/ApplicationConstants.java index eee6757df..ba5c08dd5 100644 --- a/src/main/java/com/twilio/oai/common/ApplicationConstants.java +++ b/src/main/java/com/twilio/oai/common/ApplicationConstants.java @@ -65,7 +65,6 @@ public class ApplicationConstants { public static final String X_MODEL_TYPE = "x-model-type"; // EnumConstants.OpenApiEnumType public static final String X_IS_MODEL = "x-is-model"; public static final String X_REQUEST_CONTENT_TYPE = "x-request-content-type"; - - + public static final Predicate isV1 = input -> input != null && input.startsWith("v1"); // Usage: isV1.test("v1.0"); } diff --git a/src/main/java/com/twilio/oai/java/JavaApiResource.java b/src/main/java/com/twilio/oai/java/JavaApiResource.java index 392dc06e8..c37745427 100644 --- a/src/main/java/com/twilio/oai/java/JavaApiResource.java +++ b/src/main/java/com/twilio/oai/java/JavaApiResource.java @@ -20,6 +20,7 @@ public class JavaApiResource { String namespaceSubPart; Boolean responseFlag = null; // true or NUll + Boolean isApiV1 = null; // true or NUll public JavaApiResource(JavaApiResourceBuilder builder) { resourceName = ResourceCacheContext.get().getResourceName(); @@ -30,6 +31,7 @@ public JavaApiResource(JavaApiResourceBuilder builder) { this.response = ResourceCacheContext.get().getResponse(); if (response != null && !response.isEmpty()) responseFlag = true; this.namespaceSubPart = builder.namespaceSubPart; + if (ResourceCacheContext.get().isV1()) isApiV1 = true; } } diff --git a/src/main/java/com/twilio/oai/java/cache/ResourceCache2.java b/src/main/java/com/twilio/oai/java/cache/ResourceCache2.java index 5aaef466d..d8a06e1ee 100644 --- a/src/main/java/com/twilio/oai/java/cache/ResourceCache2.java +++ b/src/main/java/com/twilio/oai/java/cache/ResourceCache2.java @@ -32,6 +32,10 @@ public class ResourceCache2 { @Getter private Set enumsClassesForMustache = new HashSet<>(); + @Getter + @Setter + private boolean isV1; + public void setAllModelsByDefaultGenerator(ArrayList allModelsByDefaultGenerator) { this.allModelsByDefaultGenerator = new ArrayList<>(allModelsByDefaultGenerator); } From 0e2e3ab2866155b8fc2326c05709ce97ac72d7a6 Mon Sep 17 00:00:00 2001 From: Shubham Date: Thu, 6 Nov 2025 13:22:55 +0530 Subject: [PATCH 38/38] chore: remove openjdk 8 from java dockerfile (#701) # Fixes # Updated the base image to Eclipse Temurin 8 and added error handling for Maven installation. Also included Git installation and modified the git clone command to use HTTPS. ### Checklist - [x] I acknowledge that all my contributions will be made under the project's license - [ ] Run `make test-docker` - [ ] Verify affected language: - [ ] Generate [twilio-go](https://github.com/twilio/twilio-go) from our [OpenAPI specification](https://github.com/twilio/twilio-oai) using the [build_twilio_go.py](./examples/build_twilio_go.py) using `python examples/build_twilio_go.py path/to/twilio-oai/spec/yaml path/to/twilio-go` and inspect the diff - [ ] Run `make test` in `twilio-go` - [ ] Create a pull request in `twilio-go` - [ ] Provide a link below to the pull request - [ ] I have made a material change to the repo (functionality, testing, spelling, grammar) - [ ] I have read the [Contribution Guidelines](https://github.com/twilio/twilio-oai-generator/blob/main/CONTRIBUTING.md) and my PR follows them - [ ] I have titled the PR appropriately - [ ] I have updated my branch with the main branch - [ ] I have added tests that prove my fix is effective or that my feature works - [ ] I have added the necessary documentation about the functionality in the appropriate .md file - [ ] I have added inline documentation to the code I modified If you have questions, please create a GitHub Issue in this repository. --------- Co-authored-by: manisha1997 --- examples/java/Dockerfile | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/examples/java/Dockerfile b/examples/java/Dockerfile index 61cfaa6d7..313a202ee 100644 --- a/examples/java/Dockerfile +++ b/examples/java/Dockerfile @@ -1,8 +1,19 @@ -FROM openjdk:8 +FROM eclipse-temurin:8-jdk -RUN apt-get update && apt-get install maven -y +# Install Maven with proper error handling +RUN apt-get update && \ + apt-get install -y --no-install-recommends maven && \ + apt-get clean && \ + rm -rf /var/lib/apt/lists/* WORKDIR /app +# Install git +RUN apt-get update && \ + apt-get install -y --no-install-recommends git && \ + apt-get clean && \ + rm -rf /var/lib/apt/lists/* + +# Use HTTPS instead of SSH for git clone RUN git clone https://github.com/twilio/twilio-java.git WORKDIR /app/twilio-java/