From c797d7a434a048b2059c22ef3a3212326bedeb9f Mon Sep 17 00:00:00 2001 From: sbansla Date: Tue, 28 Oct 2025 14:37:43 +0530 Subject: [PATCH 1/5] created constant to check api standard version --- .../twilio/oai/TwilioJavaGeneratorModern.java | 5 ++ .../oai/common/ApplicationConstants.java | 3 +- .../com/twilio/oai/java/JavaApiResource.java | 3 +- .../twilio/oai/java/cache/ResourceCache2.java | 4 ++ .../JsonMultipleResponseProcessor.java | 52 +++++++++++++++++++ .../responsebody/JsonResponseProcessor.java | 3 +- .../ResponseProcessorFactory.java | 1 + 7 files changed, 67 insertions(+), 4 deletions(-) create mode 100644 src/main/java/com/twilio/oai/java/processor/responsebody/JsonMultipleResponseProcessor.java diff --git a/src/main/java/com/twilio/oai/TwilioJavaGeneratorModern.java b/src/main/java/com/twilio/oai/TwilioJavaGeneratorModern.java index 5cced9f22..3fad82dea 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,9 @@ public void processOpts() { // Run once per spec @Override public void processOpenAPI(final OpenAPI openAPI) { + String apiStdVersion = (String)((LinkedHashMap)openAPI.getInfo().getExtensions().get("x-twilio")).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..c4ff979f3 100644 --- a/src/main/java/com/twilio/oai/java/JavaApiResource.java +++ b/src/main/java/com/twilio/oai/java/JavaApiResource.java @@ -18,8 +18,8 @@ public class JavaApiResource { List operations; Set response; String namespaceSubPart; - Boolean responseFlag = null; // true or NUll + Boolean isApiV1 = null; // true or NUll public JavaApiResource(JavaApiResourceBuilder builder) { resourceName = ResourceCacheContext.get().getResourceName(); @@ -30,6 +30,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..3cb86ecb5 100644 --- a/src/main/java/com/twilio/oai/java/cache/ResourceCache2.java +++ b/src/main/java/com/twilio/oai/java/cache/ResourceCache2.java @@ -31,6 +31,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); diff --git a/src/main/java/com/twilio/oai/java/processor/responsebody/JsonMultipleResponseProcessor.java b/src/main/java/com/twilio/oai/java/processor/responsebody/JsonMultipleResponseProcessor.java new file mode 100644 index 000000000..279819287 --- /dev/null +++ b/src/main/java/com/twilio/oai/java/processor/responsebody/JsonMultipleResponseProcessor.java @@ -0,0 +1,52 @@ +package com.twilio.oai.java.processor.responsebody; + +import com.twilio.oai.common.ApplicationConstants; +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.requestbody.RecursiveModelProcessor; +import org.openapitools.codegen.CodegenModel; +import org.openapitools.codegen.CodegenOperation; + +import java.util.Map; + +public class JsonMultipleResponseProcessor implements ResponseProcessor { + EnumProcessorFactory enumProcessorFactory = EnumProcessorFactory.getInstance(); + RecursiveModelProcessor recursiveModelProcessor = new RecursiveModelProcessor(); + @Override + public void process(final CodegenOperation codegenOperation) { + /* There are 5 types of operation we are supporting. + * delete -- does not have response body + * fetch, create, update --> have body + * list --> has pagination and body + */ + if (codegenOperation.operationId.toLowerCase().startsWith("delete")) return; + + } + + public boolean shouldProcess(final CodegenOperation codegenOperation) { + if (!ResourceCacheContext.get().isV1()) return false; + + if (codegenOperation.produces != null && !codegenOperation.produces.isEmpty()) { + for (Map contentType : codegenOperation.produces) { + if (getContentType().equals(contentType.get("mediaType")) || "application/scim+json".equals(contentType.get("mediaType"))) { + return true; + } + } + } + return false; + } + + private void processResponseWithoutPagination() { + + } + + private void processResponseWithPagination() { + + } + + @Override + public String getContentType() { + return "application/json"; + } +} 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 9ab982846..ccad09ece 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 @@ -57,7 +57,8 @@ private CodegenModel getModelFromListOperation(CodegenModel codegenModel) { } public boolean shouldProcess(final CodegenOperation codegenOperation) { - System.out.println(codegenOperation.operationId); + if (ResourceCacheContext.get().isV1()) return false; + if (codegenOperation.produces != null && !codegenOperation.produces.isEmpty()) { for (Map contentType : codegenOperation.produces) { if (getContentType().equals(contentType.get("mediaType")) || "application/scim+json".equals(contentType.get("mediaType"))) { 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 index d67553649..3f02b2b06 100644 --- a/src/main/java/com/twilio/oai/java/processor/responsebody/ResponseProcessorFactory.java +++ b/src/main/java/com/twilio/oai/java/processor/responsebody/ResponseProcessorFactory.java @@ -11,6 +11,7 @@ public class ResponseProcessorFactory { private ResponseProcessorFactory() { processors.add(new JsonResponseProcessor()); + processors.add(new JsonMultipleResponseProcessor()); } public static ResponseProcessorFactory getInstance() { From 7451bda60a60a2b15379d3825ad402177ca53153 Mon Sep 17 00:00:00 2001 From: sbansla Date: Wed, 5 Nov 2025 10:12:50 +0530 Subject: [PATCH 2/5] reading resource and getting model --- .../twilio/oai/TwilioJavaGeneratorModern.java | 10 +++-- .../twilio/oai/java/cache/ResourceCache2.java | 7 ++++ .../JsonMultipleResponseProcessor.java | 35 ++++++++++++++--- .../JsonResponseAbstractProcessor.java | 39 +++++++++++++++++++ .../responsebody/JsonResponseProcessor.java | 26 +------------ .../org.openapitools.codegen.CodegenConfig | 2 +- .../com/twilio/oai/TwilioGeneratorTest.java | 5 ++- 7 files changed, 88 insertions(+), 36 deletions(-) create mode 100644 src/main/java/com/twilio/oai/java/processor/responsebody/JsonResponseAbstractProcessor.java diff --git a/src/main/java/com/twilio/oai/TwilioJavaGeneratorModern.java b/src/main/java/com/twilio/oai/TwilioJavaGeneratorModern.java index 3fad82dea..8f1beaece 100644 --- a/src/main/java/com/twilio/oai/TwilioJavaGeneratorModern.java +++ b/src/main/java/com/twilio/oai/TwilioJavaGeneratorModern.java @@ -66,9 +66,13 @@ public void processOpts() { // Run once per spec @Override public void processOpenAPI(final OpenAPI openAPI) { - String apiStdVersion = (String)((LinkedHashMap)openAPI.getInfo().getExtensions().get("x-twilio")).get("apiStandards"); - boolean isV1 = ApplicationConstants.isV1.test(apiStdVersion); - ResourceCacheContext.get().setV1(isV1); + try { + String apiStdVersion = (String)((LinkedHashMap)openAPI.getInfo().getExtensions().get("x-twilio")).get("apiStandards"); + boolean isV1 = ApplicationConstants.isV1.test(apiStdVersion); + ResourceCacheContext.get().setV1(isV1); + } catch (Exception exception) { + ResourceCacheContext.get().setV1(false); + } String domain = twilioCodegen.getDomainFromOpenAPI(openAPI); String version = twilioCodegen.getVersionFromOpenAPI(openAPI); twilioCodegen.setDomain(domain); 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 3cb86ecb5..4dbe5ee31 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,9 @@ public class ResourceCache2 { @Getter private Set enumsClassesForMustache = new HashSet<>(); + @Getter + private Set responses = new HashSet<>(); + @Getter @Setter private boolean isV1; @@ -55,6 +58,10 @@ public void addToOneOfInterfaces(MustacheOneOfIface oneOfIFace) { this.oneOfInterfaces.add(oneOfIFace); } + public void addToResponse(MustacheModel mustacheModel) { + this.responses.add(mustacheModel); + } + // Clear at group of operation level, at method: postProcessOperationsWithModels public void clear() { resourceName = ""; diff --git a/src/main/java/com/twilio/oai/java/processor/responsebody/JsonMultipleResponseProcessor.java b/src/main/java/com/twilio/oai/java/processor/responsebody/JsonMultipleResponseProcessor.java index 279819287..7397c6609 100644 --- a/src/main/java/com/twilio/oai/java/processor/responsebody/JsonMultipleResponseProcessor.java +++ b/src/main/java/com/twilio/oai/java/processor/responsebody/JsonMultipleResponseProcessor.java @@ -1,16 +1,18 @@ package com.twilio.oai.java.processor.responsebody; import com.twilio.oai.common.ApplicationConstants; +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.processor.enums.EnumProcessorFactory; import com.twilio.oai.java.processor.requestbody.RecursiveModelProcessor; import org.openapitools.codegen.CodegenModel; import org.openapitools.codegen.CodegenOperation; +import org.openapitools.codegen.CodegenProperty; import java.util.Map; -public class JsonMultipleResponseProcessor implements ResponseProcessor { +public class JsonMultipleResponseProcessor extends JsonResponseAbstractProcessor implements ResponseProcessor { EnumProcessorFactory enumProcessorFactory = EnumProcessorFactory.getInstance(); RecursiveModelProcessor recursiveModelProcessor = new RecursiveModelProcessor(); @Override @@ -22,6 +24,12 @@ public void process(final CodegenOperation codegenOperation) { */ if (codegenOperation.operationId.toLowerCase().startsWith("delete")) return; + if (codegenOperation.operationId.toLowerCase().startsWith("list")) { + processResponseWithPagination(codegenOperation); + } else { + processResponseWithoutPagination(codegenOperation); + } + } public boolean shouldProcess(final CodegenOperation codegenOperation) { @@ -37,16 +45,33 @@ public boolean shouldProcess(final CodegenOperation codegenOperation) { return false; } - private void processResponseWithoutPagination() { - + private void processResponseWithoutPagination(CodegenOperation codegenOperation) { + System.out.println(codegenOperation.operationId); + CodegenModel codegenModel = getModel(codegenOperation); + System.out.println(codegenModel); } - private void processResponseWithPagination() { - + private void processResponseWithPagination(CodegenOperation codegenOperation) { + System.out.println(codegenOperation.operationId); + CodegenModel codegenModel = getModel(codegenOperation); + System.out.println(codegenModel); + int size = codegenModel.vars.size(); + for (int i=0; i generators() { - return Arrays.asList(Generator.TWILIO_JAVA); + return Arrays.asList(Generator.TWILIO_RUBY); } private final Generator generator; @@ -40,7 +40,8 @@ public static void setUp() { @Test public void launchGenerator() { - final String pathname = "examples/spec/twilio_flex_v1.yaml"; + //final String pathname = "/Users/sbansla/Documents/code/twilio-oai/spec/yaml/twilio_content_v1.yaml"; + final String pathname = "/Users/sbansla/Documents/code/twilio-oai/spec/yaml/twilio_api_v2010.yaml"; File filesList[] ; File directoryPath = new File(pathname); if (directoryPath.isDirectory()) { From d9211d361fd87ce7562a5d545088758e04304573 Mon Sep 17 00:00:00 2001 From: sbansla Date: Wed, 5 Nov 2025 16:27:34 +0530 Subject: [PATCH 3/5] created response model for cudf operations --- .../twilio/oai/TwilioJavaGeneratorModern.java | 13 +++---- .../java/com/twilio/oai/common/Utility.java | 5 +++ .../oai/java/constants/MustacheConstants.java | 1 + .../JsonMultipleResponseProcessor.java | 17 ++++++--- .../JsonResponseAbstractProcessor.java | 23 ++++++++++++ .../responsebody/paginationremover/Meta.java | 36 +++++++++++++++++++ .../ResponsePaginationRemover.java | 11 ++++++ .../responsebody/paginationremover/Root.java | 17 +++++++++ .../creator/operationMethod.mustache | 5 ++- .../fetcher/operationMethod.mustache | 5 ++- .../updater/operationMethod.mustache | 5 ++- .../com/twilio/oai/TwilioGeneratorTest.java | 5 ++- 12 files changed, 127 insertions(+), 16 deletions(-) create mode 100644 src/main/java/com/twilio/oai/java/processor/responsebody/paginationremover/Meta.java create mode 100644 src/main/java/com/twilio/oai/java/processor/responsebody/paginationremover/ResponsePaginationRemover.java create mode 100644 src/main/java/com/twilio/oai/java/processor/responsebody/paginationremover/Root.java diff --git a/src/main/java/com/twilio/oai/TwilioJavaGeneratorModern.java b/src/main/java/com/twilio/oai/TwilioJavaGeneratorModern.java index 8f1beaece..20cb24a60 100644 --- a/src/main/java/com/twilio/oai/TwilioJavaGeneratorModern.java +++ b/src/main/java/com/twilio/oai/TwilioJavaGeneratorModern.java @@ -66,13 +66,14 @@ public void processOpts() { // Run once per spec @Override public void processOpenAPI(final OpenAPI openAPI) { - try { - String apiStdVersion = (String)((LinkedHashMap)openAPI.getInfo().getExtensions().get("x-twilio")).get("apiStandards"); - boolean isV1 = ApplicationConstants.isV1.test(apiStdVersion); - ResourceCacheContext.get().setV1(isV1); - } catch (Exception exception) { - ResourceCacheContext.get().setV1(false); + 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/Utility.java b/src/main/java/com/twilio/oai/common/Utility.java index 891562731..863faa4db 100644 --- a/src/main/java/com/twilio/oai/common/Utility.java +++ b/src/main/java/com/twilio/oai/common/Utility.java @@ -17,6 +17,7 @@ import com.twilio.oai.java.cache.ResourceCacheContext; import lombok.experimental.UtilityClass; import org.apache.commons.lang3.StringUtils; +import org.openapitools.codegen.CodegenMediaType; import org.openapitools.codegen.CodegenModel; import org.openapitools.codegen.CodegenOperation; import org.openapitools.codegen.CodegenProperty; @@ -274,4 +275,8 @@ public static CodegenModel getModelFromRef(String ref) { } return null; } + + public static CodegenProperty getPropertyFromMediaType(CodegenMediaType codegenMediaType) { + return codegenMediaType.getSchema(); + } } diff --git a/src/main/java/com/twilio/oai/java/constants/MustacheConstants.java b/src/main/java/com/twilio/oai/java/constants/MustacheConstants.java index 6dce31699..a3532b50f 100644 --- a/src/main/java/com/twilio/oai/java/constants/MustacheConstants.java +++ b/src/main/java/com/twilio/oai/java/constants/MustacheConstants.java @@ -18,6 +18,7 @@ public class MustacheConstants { 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 String X_RESPONSE_DATATYPE = "x-response-datatype"; public static final Map serializaationMapping = Map.of( "application/x-www-form-urlencoded", "if ($paramName != null) { request.addPostParam($stringCapParamName, $paramName.toString())}", diff --git a/src/main/java/com/twilio/oai/java/processor/responsebody/JsonMultipleResponseProcessor.java b/src/main/java/com/twilio/oai/java/processor/responsebody/JsonMultipleResponseProcessor.java index 7397c6609..068478d26 100644 --- a/src/main/java/com/twilio/oai/java/processor/responsebody/JsonMultipleResponseProcessor.java +++ b/src/main/java/com/twilio/oai/java/processor/responsebody/JsonMultipleResponseProcessor.java @@ -3,18 +3,23 @@ import com.twilio.oai.common.ApplicationConstants; import com.twilio.oai.common.Utility; import com.twilio.oai.java.cache.ResourceCacheContext; +import com.twilio.oai.java.constants.MustacheConstants; import com.twilio.oai.java.format.Deserializer; import com.twilio.oai.java.processor.enums.EnumProcessorFactory; import com.twilio.oai.java.processor.requestbody.RecursiveModelProcessor; +import com.twilio.oai.java.processor.responsebody.paginationremover.Meta; import org.openapitools.codegen.CodegenModel; import org.openapitools.codegen.CodegenOperation; import org.openapitools.codegen.CodegenProperty; +import org.openapitools.codegen.Constants; import java.util.Map; public class JsonMultipleResponseProcessor extends JsonResponseAbstractProcessor implements ResponseProcessor { EnumProcessorFactory enumProcessorFactory = EnumProcessorFactory.getInstance(); RecursiveModelProcessor recursiveModelProcessor = new RecursiveModelProcessor(); + Meta meta = new Meta(); + @Override public void process(final CodegenOperation codegenOperation) { /* There are 5 types of operation we are supporting. @@ -47,11 +52,17 @@ public boolean shouldProcess(final CodegenOperation codegenOperation) { private void processResponseWithoutPagination(CodegenOperation codegenOperation) { System.out.println(codegenOperation.operationId); - CodegenModel codegenModel = getModel(codegenOperation); - System.out.println(codegenModel); + CodegenProperty codegenProperty = getCodegenProperty(codegenOperation); + recursiveModelProcessor.process(codegenProperty); + System.out.println(codegenProperty); + codegenOperation.vendorExtensions.put(MustacheConstants.X_RESPONSE_DATATYPE, codegenProperty.vendorExtensions.get(ApplicationConstants.X_DATATYPE)); } private void processResponseWithPagination(CodegenOperation codegenOperation) { + // check if pagination exists, if no, go to processResponseWithoutPagination + + meta.shouldProcess(codegenOperation); + meta.removePagination(codegenOperation); System.out.println(codegenOperation.operationId); CodegenModel codegenModel = getModel(codegenOperation); System.out.println(codegenModel); @@ -60,8 +71,6 @@ private void processResponseWithPagination(CodegenOperation codegenOperation) { CodegenProperty codegenProperty = codegenModel.vars.get(i); if (codegenProperty.getRef() == null) continue; CodegenModel model = Utility.getModelFromRef(codegenProperty.getRef()); - - } } diff --git a/src/main/java/com/twilio/oai/java/processor/responsebody/JsonResponseAbstractProcessor.java b/src/main/java/com/twilio/oai/java/processor/responsebody/JsonResponseAbstractProcessor.java index 977fe2fc6..cd8f30aed 100644 --- a/src/main/java/com/twilio/oai/java/processor/responsebody/JsonResponseAbstractProcessor.java +++ b/src/main/java/com/twilio/oai/java/processor/responsebody/JsonResponseAbstractProcessor.java @@ -4,6 +4,7 @@ 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; public abstract class JsonResponseAbstractProcessor { @@ -33,6 +34,28 @@ protected CodegenModel getModel(final CodegenOperation codegenOperation) { return null; } + protected CodegenProperty getCodegenProperty(final CodegenOperation codegenOperation) { + if (codegenOperation.responses != null && !codegenOperation.responses.isEmpty()) { + for (CodegenResponse codegenResponse: codegenOperation.responses) { + if (codegenResponse.is2xx || codegenResponse.is3xx) { + if (codegenResponse == null || codegenResponse.getContent() == null) return null; + CodegenMediaType codegenMediaType = codegenResponse.getContent().get(getContentType()); + if (codegenMediaType == null) { + codegenMediaType = codegenResponse.getContent().get("application/scim+json"); // special case for Orgs API + if (codegenMediaType == null) return null; + } + + if (codegenMediaType.getSchema().isContainer) { + // It covers special case in which response is list + // TODO: Handle in future. + } + return codegenMediaType.getSchema(); + } + } + } + return null; + } + public String getContentType() { return "application/json"; } diff --git a/src/main/java/com/twilio/oai/java/processor/responsebody/paginationremover/Meta.java b/src/main/java/com/twilio/oai/java/processor/responsebody/paginationremover/Meta.java new file mode 100644 index 000000000..df66e07e9 --- /dev/null +++ b/src/main/java/com/twilio/oai/java/processor/responsebody/paginationremover/Meta.java @@ -0,0 +1,36 @@ +package com.twilio.oai.java.processor.responsebody.paginationremover; + +import com.twilio.oai.common.Utility; +import org.openapitools.codegen.CodegenOperation; +import org.openapitools.codegen.CodegenProperty; +import org.openapitools.codegen.CodegenResponse; + +public class Meta extends ResponsePaginationRemover { + @Override + public boolean shouldProcess(CodegenOperation codegenOperation) { + // Check if in the response body there is a "meta" property + System.out.println(codegenOperation); + for (CodegenResponse response: codegenOperation.responses) { + // choose only that response which is application/json + response.getContent().forEach((contentType, mediaType) -> { + System.out.println("Content Type: " + contentType); + System.out.println("Media Type: " + mediaType); + CodegenProperty codegenProperty = Utility.getPropertyFromMediaType(mediaType); +// if (mediaType.getSchema() != null && mediaType.getSchema().getProperties() != null) { +// mediaType.getSchema().getProperties().forEach((propertyName, propertySchema) -> { +// if ("meta".equals(propertyName)) { +// // found meta property +// return; +// } +// }); +// } + }); + } + return false; + } + + @Override + public void removePagination(CodegenOperation codegenOperation) { + + } +} diff --git a/src/main/java/com/twilio/oai/java/processor/responsebody/paginationremover/ResponsePaginationRemover.java b/src/main/java/com/twilio/oai/java/processor/responsebody/paginationremover/ResponsePaginationRemover.java new file mode 100644 index 000000000..6d37a9142 --- /dev/null +++ b/src/main/java/com/twilio/oai/java/processor/responsebody/paginationremover/ResponsePaginationRemover.java @@ -0,0 +1,11 @@ +package com.twilio.oai.java.processor.responsebody.paginationremover; + +import org.openapitools.codegen.CodegenOperation; + +public abstract class ResponsePaginationRemover { + abstract boolean shouldProcess(final CodegenOperation codegenOperation); + + void removePagination(final CodegenOperation codegenOperation) { + + } +} diff --git a/src/main/java/com/twilio/oai/java/processor/responsebody/paginationremover/Root.java b/src/main/java/com/twilio/oai/java/processor/responsebody/paginationremover/Root.java new file mode 100644 index 000000000..e5aa6e51e --- /dev/null +++ b/src/main/java/com/twilio/oai/java/processor/responsebody/paginationremover/Root.java @@ -0,0 +1,17 @@ +package com.twilio.oai.java.processor.responsebody.paginationremover; + +import org.openapitools.codegen.CodegenOperation; + +public class Root extends ResponsePaginationRemover { + @Override + public boolean shouldProcess(CodegenOperation codegenOperation) { + // check if the response body is the pagination model itself + System.out.println(codegenOperation); + return true; + } + + @Override + public void removePagination(final CodegenOperation codegenOperation) { + // No-op + } +} diff --git a/src/main/resources/twilio-java/creator/operationMethod.mustache b/src/main/resources/twilio-java/creator/operationMethod.mustache index 32496cede..8a0994670 100644 --- a/src/main/resources/twilio-java/creator/operationMethod.mustache +++ b/src/main/resources/twilio-java/creator/operationMethod.mustache @@ -8,7 +8,10 @@ domainName: example api, video, chat, etc. These can be found in Domains.java in 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) { + public + {{#vendorExtensions.x-response-datatype}} {{{vendorExtensions.x-response-datatype}}} {{/vendorExtensions.x-response-datatype}} + {{^vendorExtensions.x-response-datatype}} {{resourceName}} {{/vendorExtensions.x-response-datatype}} + {{vendorExtensions.x-common-action-method}}(final TwilioRestClient client) { {{>common/generateUri}} Request request = new Request( diff --git a/src/main/resources/twilio-java/fetcher/operationMethod.mustache b/src/main/resources/twilio-java/fetcher/operationMethod.mustache index 8ead0de7b..6e820481b 100644 --- a/src/main/resources/twilio-java/fetcher/operationMethod.mustache +++ b/src/main/resources/twilio-java/fetcher/operationMethod.mustache @@ -8,7 +8,10 @@ domainName: example api, video, chat, etc. These can be found in Domains.java in vendorExtensions.x-content-type: content type of the request, example: application/json, application/x-www-form-urlencoded }} @Override - public {{resourceName}} fetch(final TwilioRestClient client) { + public + {{#vendorExtensions.x-response-datatype}} {{{vendorExtensions.x-response-datatype}}} {{/vendorExtensions.x-response-datatype}} + {{^vendorExtensions.x-response-datatype}} {{resourceName}} {{/vendorExtensions.x-response-datatype}} + fetch(final TwilioRestClient client) { {{>common/generateUri}} Request request = new Request( diff --git a/src/main/resources/twilio-java/updater/operationMethod.mustache b/src/main/resources/twilio-java/updater/operationMethod.mustache index 6744cbbc4..fe0d298ab 100644 --- a/src/main/resources/twilio-java/updater/operationMethod.mustache +++ b/src/main/resources/twilio-java/updater/operationMethod.mustache @@ -8,7 +8,10 @@ domainName: example api, video, chat, etc. These can be found in Domains.java in 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) { + public + {{#vendorExtensions.x-response-datatype}} {{{vendorExtensions.x-response-datatype}}} {{/vendorExtensions.x-response-datatype}} + {{^vendorExtensions.x-response-datatype}} {{resourceName}} {{/vendorExtensions.x-response-datatype}} + {{vendorExtensions.x-common-action-method}}(final TwilioRestClient client) { {{>common/generateUri}} Request request = new Request( diff --git a/src/test/java/com/twilio/oai/TwilioGeneratorTest.java b/src/test/java/com/twilio/oai/TwilioGeneratorTest.java index b3aa80bb3..f8cb7b80e 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_RUBY); + return Arrays.asList(Generator.TWILIO_JAVA); } private final Generator generator; @@ -40,8 +40,7 @@ public static void setUp() { @Test public void launchGenerator() { - //final String pathname = "/Users/sbansla/Documents/code/twilio-oai/spec/yaml/twilio_content_v1.yaml"; - final String pathname = "/Users/sbansla/Documents/code/twilio-oai/spec/yaml/twilio_api_v2010.yaml"; + final String pathname = "examples/spec/twilio_flex_v1.yaml"; File filesList[] ; File directoryPath = new File(pathname); if (directoryPath.isDirectory()) { From a3b37408fea8cbf2bdd56e7015b167ffc8e56832 Mon Sep 17 00:00:00 2001 From: sbansla Date: Thu, 6 Nov 2025 15:43:34 +0530 Subject: [PATCH 4/5] added response for meta pagination list ops --- .../twilio/oai/TwilioJavaGeneratorModern.java | 1 + .../java/com/twilio/oai/common/Utility.java | 23 +++++++++- .../twilio/oai/java/cache/ResourceCache2.java | 8 ++++ .../JsonMultipleResponseProcessor.java | 16 ++----- .../JsonResponseAbstractProcessor.java | 7 ++- .../responsebody/paginationremover/Meta.java | 46 ++++++++++++------- .../ResponsePaginationRemover.java | 6 +-- .../responsebody/paginationremover/Root.java | 7 +-- .../reader/operationMethod.mustache | 5 +- 9 files changed, 81 insertions(+), 38 deletions(-) diff --git a/src/main/java/com/twilio/oai/TwilioJavaGeneratorModern.java b/src/main/java/com/twilio/oai/TwilioJavaGeneratorModern.java index 20cb24a60..4cc64fb4c 100644 --- a/src/main/java/com/twilio/oai/TwilioJavaGeneratorModern.java +++ b/src/main/java/com/twilio/oai/TwilioJavaGeneratorModern.java @@ -104,6 +104,7 @@ public Map postProcessAllModels(final Map //ResourceCache.clearAllModelsByDefaultGenerator(); // Update allModels from Default generator in ResourceCache. Utility.addModelsToLocalModelList(results, cache2.getAllModelsByDefaultGenerator()); + Utility.addModelsToLocalCodegenModelMap(results, cache2.getAllModelsMapByDefaultGenerator()); directoryStructureService.postProcessAllModels(results, modelFormatMap); // Return an empty collection so no model files get generated. diff --git a/src/main/java/com/twilio/oai/common/Utility.java b/src/main/java/com/twilio/oai/common/Utility.java index 863faa4db..500bab6f5 100644 --- a/src/main/java/com/twilio/oai/common/Utility.java +++ b/src/main/java/com/twilio/oai/common/Utility.java @@ -5,6 +5,7 @@ import java.security.NoSuchAlgorithmException; import java.util.Arrays; import java.util.Collection; +import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; @@ -54,6 +55,16 @@ public void addModelsToLocalModelList(final Map modelMap, Lis } } + public void addModelsToLocalCodegenModelMap(final Map modelMap, Map localModelMap){ + for (final ModelsMap mods : modelMap.values()) { + final List modList = mods.getModels(); + modList.stream() + .map(ModelMap::getModel) + .map(CodegenModel.class::cast) + .forEach(model -> localModelMap.put(com.twilio.oai.common.StringUtils.toPascalCase(model.name), model)); + } + } + public String removeEnumName(final String dataType) { return dataType == null ? null @@ -266,6 +277,7 @@ public static void main(String[] args) { System.out.println(getModelFromRef(ref)); } public static CodegenModel getModelFromRef(String ref) { + if (ref == null) throw new RuntimeException("Ref can not be null for fetching Model"); String schemaName = ref.replaceFirst("#/components/schemas/", ""); List allModels = ResourceCacheContext.get().getAllModelsByDefaultGenerator(); for (CodegenModel model: allModels) { @@ -276,7 +288,14 @@ public static CodegenModel getModelFromRef(String ref) { return null; } - public static CodegenProperty getPropertyFromMediaType(CodegenMediaType codegenMediaType) { - return codegenMediaType.getSchema(); + public static CodegenModel getPropertyFromMediaType(CodegenMediaType codegenMediaType) { + CodegenProperty codegenProperty = codegenMediaType.getSchema(); + + String ref = codegenProperty.getRef(); + if (ref == null) { + throw new RuntimeException("Ref is null in Response schema"); + } + CodegenModel responseModel = Utility.getModelFromRef(ref); + return responseModel; } } 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 4dbe5ee31..1f7668c1d 100644 --- a/src/main/java/com/twilio/oai/java/cache/ResourceCache2.java +++ b/src/main/java/com/twilio/oai/java/cache/ResourceCache2.java @@ -35,6 +35,10 @@ public class ResourceCache2 { @Getter private Set responses = new HashSet<>(); + // Note: Key is stored in PascalCase using com.twilio.oai.common.StringUtils.toPascalCase(string_val) + @Getter + private Map allModelsMapByDefaultGenerator = new HashMap<>(); + @Getter @Setter private boolean isV1; @@ -46,6 +50,10 @@ public void setAllModelsByDefaultGenerator(ArrayList allModelsByDe public ArrayList getAllModelsByDefaultGenerator() { return this.allModelsByDefaultGenerator; } + + public Map getAllModelsMapByDefaultGenerator() { + return this.allModelsMapByDefaultGenerator; + } public void addToModelClasses(MustacheModel mustacheModel) { this.modelClassesForMustache.add(mustacheModel); } diff --git a/src/main/java/com/twilio/oai/java/processor/responsebody/JsonMultipleResponseProcessor.java b/src/main/java/com/twilio/oai/java/processor/responsebody/JsonMultipleResponseProcessor.java index 068478d26..d1e265ed6 100644 --- a/src/main/java/com/twilio/oai/java/processor/responsebody/JsonMultipleResponseProcessor.java +++ b/src/main/java/com/twilio/oai/java/processor/responsebody/JsonMultipleResponseProcessor.java @@ -54,7 +54,6 @@ private void processResponseWithoutPagination(CodegenOperation codegenOperation) System.out.println(codegenOperation.operationId); CodegenProperty codegenProperty = getCodegenProperty(codegenOperation); recursiveModelProcessor.process(codegenProperty); - System.out.println(codegenProperty); codegenOperation.vendorExtensions.put(MustacheConstants.X_RESPONSE_DATATYPE, codegenProperty.vendorExtensions.get(ApplicationConstants.X_DATATYPE)); } @@ -62,16 +61,11 @@ private void processResponseWithPagination(CodegenOperation codegenOperation) { // check if pagination exists, if no, go to processResponseWithoutPagination meta.shouldProcess(codegenOperation); - meta.removePagination(codegenOperation); - System.out.println(codegenOperation.operationId); - CodegenModel codegenModel = getModel(codegenOperation); - System.out.println(codegenModel); - int size = codegenModel.vars.size(); - for (int i=0; i codegenModelMap = ResourceCacheContext.get().getAllModelsMapByDefaultGenerator(); if (codegenOperation.responses != null && !codegenOperation.responses.isEmpty()) { for (CodegenResponse codegenResponse: codegenOperation.responses) { if (codegenResponse.is2xx || codegenResponse.is3xx) { diff --git a/src/main/java/com/twilio/oai/java/processor/responsebody/paginationremover/Meta.java b/src/main/java/com/twilio/oai/java/processor/responsebody/paginationremover/Meta.java index df66e07e9..175257c71 100644 --- a/src/main/java/com/twilio/oai/java/processor/responsebody/paginationremover/Meta.java +++ b/src/main/java/com/twilio/oai/java/processor/responsebody/paginationremover/Meta.java @@ -1,36 +1,48 @@ package com.twilio.oai.java.processor.responsebody.paginationremover; +import com.intuit.commons.traverser.Traverser; +import com.intuit.commons.traverser.TraversingIterator; +import com.twilio.oai.common.StringUtils; import com.twilio.oai.common.Utility; +import com.twilio.oai.java.cache.ResourceCache2; +import com.twilio.oai.java.cache.ResourceCacheContext; +import com.twilio.oai.java.processor.traverser.CustomTraverser; +import org.checkerframework.checker.units.qual.C; +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 Meta extends ResponsePaginationRemover { @Override public boolean shouldProcess(CodegenOperation codegenOperation) { + + Map codegenModelMap = ResourceCacheContext.get().getAllModelsMapByDefaultGenerator(); // Check if in the response body there is a "meta" property - System.out.println(codegenOperation); for (CodegenResponse response: codegenOperation.responses) { - // choose only that response which is application/json - response.getContent().forEach((contentType, mediaType) -> { - System.out.println("Content Type: " + contentType); - System.out.println("Media Type: " + mediaType); - CodegenProperty codegenProperty = Utility.getPropertyFromMediaType(mediaType); -// if (mediaType.getSchema() != null && mediaType.getSchema().getProperties() != null) { -// mediaType.getSchema().getProperties().forEach((propertyName, propertySchema) -> { -// if ("meta".equals(propertyName)) { -// // found meta property -// return; -// } -// }); -// } - }); + CodegenModel codegenModel = codegenModelMap.get(StringUtils.toPascalCase(response.baseType)); + for (CodegenProperty codegenProperty: codegenModel.vars) { + if (codegenProperty.name.equals("meta")) { + return true; + } + } } return false; } @Override - public void removePagination(CodegenOperation codegenOperation) { - + public CodegenProperty getResponse(CodegenOperation codegenOperation) { + Map codegenModelMap = ResourceCacheContext.get().getAllModelsMapByDefaultGenerator(); + for (CodegenResponse response: codegenOperation.responses) { + CodegenModel codegenModel = codegenModelMap.get(StringUtils.toPascalCase(response.baseType)); + for (CodegenProperty codegenProperty: codegenModel.vars) { + if (!codegenProperty.name.equals("meta")) { + return codegenProperty; + } + } + } + return null; } } diff --git a/src/main/java/com/twilio/oai/java/processor/responsebody/paginationremover/ResponsePaginationRemover.java b/src/main/java/com/twilio/oai/java/processor/responsebody/paginationremover/ResponsePaginationRemover.java index 6d37a9142..c85c0ba66 100644 --- a/src/main/java/com/twilio/oai/java/processor/responsebody/paginationremover/ResponsePaginationRemover.java +++ b/src/main/java/com/twilio/oai/java/processor/responsebody/paginationremover/ResponsePaginationRemover.java @@ -1,11 +1,11 @@ package com.twilio.oai.java.processor.responsebody.paginationremover; +import org.openapitools.codegen.CodegenModel; import org.openapitools.codegen.CodegenOperation; +import org.openapitools.codegen.CodegenProperty; public abstract class ResponsePaginationRemover { abstract boolean shouldProcess(final CodegenOperation codegenOperation); - void removePagination(final CodegenOperation codegenOperation) { - - } + abstract CodegenProperty getResponse(final CodegenOperation codegenOperation); } diff --git a/src/main/java/com/twilio/oai/java/processor/responsebody/paginationremover/Root.java b/src/main/java/com/twilio/oai/java/processor/responsebody/paginationremover/Root.java index e5aa6e51e..252ac3658 100644 --- a/src/main/java/com/twilio/oai/java/processor/responsebody/paginationremover/Root.java +++ b/src/main/java/com/twilio/oai/java/processor/responsebody/paginationremover/Root.java @@ -1,17 +1,18 @@ package com.twilio.oai.java.processor.responsebody.paginationremover; import org.openapitools.codegen.CodegenOperation; +import org.openapitools.codegen.CodegenProperty; public class Root extends ResponsePaginationRemover { @Override public boolean shouldProcess(CodegenOperation codegenOperation) { // check if the response body is the pagination model itself System.out.println(codegenOperation); - return true; + return false; } @Override - public void removePagination(final CodegenOperation codegenOperation) { - // No-op + CodegenProperty getResponse(CodegenOperation codegenOperation) { + return null; } } diff --git a/src/main/resources/twilio-java/reader/operationMethod.mustache b/src/main/resources/twilio-java/reader/operationMethod.mustache index 7dea9b5d8..6b456c806 100644 --- a/src/main/resources/twilio-java/reader/operationMethod.mustache +++ b/src/main/resources/twilio-java/reader/operationMethod.mustache @@ -5,7 +5,10 @@ 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) { + public + {{#vendorExtensions.x-response-datatype}} {{{vendorExtensions.x-response-datatype}}} {{/vendorExtensions.x-response-datatype}} + {{^vendorExtensions.x-response-datatype}} ResourceSet<{{resourceName}}> {{/vendorExtensions.x-response-datatype}} + read(final TwilioRestClient client) { return new ResourceSet<>(this, client, firstPage(client)); } From 1d512a0921e7996d763004049ee77dde121b1a55 Mon Sep 17 00:00:00 2001 From: sbansla Date: Thu, 6 Nov 2025 17:06:11 +0530 Subject: [PATCH 5/5] fetching paginated models using record key --- .../test_spec/twilio_multiresponse_v1.yaml | 1456 +++++++++++++++++ .../oai/java/JavaApiResourceBuilder.java | 1 + .../twilio/oai/java/cache/ResourceCache2.java | 8 +- .../JsonMultipleResponseProcessor.java | 31 +- .../responsebody/paginationremover/Meta.java | 48 - .../ResponsePaginationRemover.java | 11 - .../responsebody/paginationremover/Root.java | 18 - 7 files changed, 1483 insertions(+), 90 deletions(-) create mode 100644 specs_test/test_spec/twilio_multiresponse_v1.yaml delete mode 100644 src/main/java/com/twilio/oai/java/processor/responsebody/paginationremover/Meta.java delete mode 100644 src/main/java/com/twilio/oai/java/processor/responsebody/paginationremover/ResponsePaginationRemover.java delete mode 100644 src/main/java/com/twilio/oai/java/processor/responsebody/paginationremover/Root.java diff --git a/specs_test/test_spec/twilio_multiresponse_v1.yaml b/specs_test/test_spec/twilio_multiresponse_v1.yaml new file mode 100644 index 000000000..d18c2f411 --- /dev/null +++ b/specs_test/test_spec/twilio_multiresponse_v1.yaml @@ -0,0 +1,1456 @@ +security: + - accountSid_authToken: [] +components: + securitySchemes: + accountSid_authToken: + scheme: basic + type: http + schemas: + listItems: + type: array + items: + $ref: '#/components/schemas/listItem' + listItem: + type: object + additionalProperties: false + properties: + id: + type: string + item: + type: string + description: + type: string + required: + - id + - item + callToActionActions: + type: array + items: + $ref: '#/components/schemas/callToActionAction' + callToActionActionType: + type: string + enum: + - URL + - PHONE_NUMBER + - COPY_CODE + - VOICE_CALL + - VOICE_CALL_REQUEST + callToActionAction: + type: object + additionalProperties: false + properties: + type: + $ref: '#/components/schemas/callToActionActionType' + title: + type: string + url: + type: string + phone: + type: string + code: + type: string + id: + type: string + required: + - type + - title + quickReplyActions: + type: array + items: + $ref: '#/components/schemas/quickReplyAction' + quickReplyActionType: + type: string + enum: + - QUICK_REPLY + quickReplyAction: + type: object + additionalProperties: false + properties: + type: + $ref: '#/components/schemas/quickReplyActionType' + title: + type: string + id: + type: string + required: + - type + - title + cardActions: + type: array + items: + $ref: '#/components/schemas/cardAction' + cardActionType: + type: string + enum: + - URL + - PHONE_NUMBER + - QUICK_REPLY + - COPY_CODE + - VOICE_CALL + webviewSizeType: + type: string + enum: + - TALL + - FULL + - HALF + - NONE + cardAction: + type: object + additionalProperties: false + properties: + type: + $ref: '#/components/schemas/cardActionType' + title: + type: string + url: + type: string + phone: + type: string + id: + type: string + code: + type: string + webview_size: + $ref: '#/components/schemas/webviewSizeType' + required: + - type + - title + carouselActions: + type: array + items: + $ref: '#/components/schemas/carouselAction' + carouselActionType: + type: string + enum: + - URL + - PHONE_NUMBER + - QUICK_REPLY + carouselAction: + type: object + additionalProperties: false + properties: + type: + $ref: '#/components/schemas/carouselActionType' + title: + type: string + url: + type: string + phone: + type: string + id: + type: string + required: + - type + - title + authenticationActions: + type: array + items: + $ref: '#/components/schemas/authenticationAction' + authenticationActionType: + type: string + enum: + - COPY_CODE + authenticationAction: + type: object + additionalProperties: false + properties: + type: + $ref: '#/components/schemas/authenticationActionType' + copy_code_text: + type: string + required: + - type + - copy_code_text + catalogItems: + type: array + items: + $ref: '#/components/schemas/catalogItem' + catalogItem: + type: object + additionalProperties: false + properties: + id: + type: string + section_title: + type: string + name: + type: string + media_url: + type: string + price: + type: number + description: + type: string + carouselCards: + type: array + items: + $ref: '#/components/schemas/carouselCard' + carouselCard: + type: object + additionalProperties: false + properties: + title: + type: string + body: + type: string + media: + type: string + actions: + $ref: '#/components/schemas/carouselActions' + twilioText: + type: object + description: Type containing only plain text-based content + nullable: true + additionalProperties: false + properties: + body: + type: string + required: + - body + twilioMedia: + type: object + description: twilio/media is used to send file attachments, or to send long + text via MMS in the US and Canada. As such, the twilio/media type must contain + at least ONE of text or media content. + nullable: true + additionalProperties: false + properties: + body: + type: string + media: + type: array + items: + type: string + required: + - media + twilioLocation: + type: object + description: twilio/location type contains a location pin and an optional label, + which can be used to enhance delivery notifications or connect recipients + to physical experiences you offer. + nullable: true + additionalProperties: false + properties: + latitude: + type: number + longitude: + type: number + label: + type: string + id: + type: string + address: + type: string + required: + - latitude + - longitude + twilioListPicker: + type: object + description: twilio/list-picker includes a menu of up to 10 options, which offers + a simple way for users to make a selection. + nullable: true + additionalProperties: false + properties: + body: + type: string + button: + type: string + items: + $ref: '#/components/schemas/listItems' + required: + - body + - button + - items + twilioCallToAction: + type: object + description: twilio/call-to-action buttons let recipients tap to trigger actions + such as launching a website or making a phone call. + nullable: true + additionalProperties: false + properties: + body: + type: string + actions: + $ref: '#/components/schemas/callToActionActions' + twilioQuickReply: + type: object + description: twilio/quick-reply templates let recipients tap, rather than type, + to respond to the message. + nullable: true + additionalProperties: false + properties: + body: + type: string + actions: + $ref: '#/components/schemas/quickReplyActions' + required: + - body + - actions + twilioCard: + type: object + description: twilio/card is a structured template which can be used to send + a series of related information. It must include a title and at least one + additional field. + nullable: true + additionalProperties: false + properties: + title: + type: string + subtitle: + type: string + media: + type: array + items: + type: string + actions: + $ref: '#/components/schemas/cardActions' + required: + - title + whatsappCard: + type: object + description: whatsapp/card is a structured template which can be used to send + a series of related information. It must include a body and at least one additional + field. + nullable: true + additionalProperties: false + properties: + body: + type: string + footer: + type: string + media: + type: array + items: + type: string + header_text: + type: string + actions: + $ref: '#/components/schemas/cardActions' + required: + - body + whatsappAuthentication: + type: object + description: whatsApp/authentication templates let companies deliver WA approved + one-time-password button. + nullable: true + additionalProperties: false + properties: + add_security_recommendation: + type: boolean + code_expiration_minutes: + type: number + actions: + $ref: '#/components/schemas/authenticationActions' + required: + - actions + twilioCatalog: + type: object + description: twilio/catalog type lets recipients view list of catalog products, + ask questions about products, order products. + nullable: true + additionalProperties: false + properties: + title: + type: string + body: + type: string + subtitle: + type: string + id: + type: string + items: + $ref: '#/components/schemas/catalogItems' + dynamic_items: + type: string + required: + - body + twilioCarousel: + type: object + description: twilio/carousel templates allow you to send a single text message + accompanied by a set of up to 10 carousel cards in a horizontally scrollable + view + nullable: true + additionalProperties: false + properties: + body: + type: string + cards: + $ref: '#/components/schemas/carouselCards' + required: + - body + - cards + twilioSchedule: + type: object + description: twilio/schedule templates allow us to send a message with a schedule + with different time slots + nullable: true + additionalProperties: false + properties: + id: + type: string + title: + type: string + timeSlots: + type: string + required: + - id + - title + - timeSlots + whatsappFlows: + type: object + description: whatsapp/flows templates allow you to send multiple messages in + a set order with text or select options + nullable: true + additionalProperties: false + properties: + body: + type: string + button_text: + type: string + subtitle: + type: string + media_url: + type: string + flow_id: + type: string + flow_token: + type: string + flow_first_page_id: + type: string + is_flow_first_page_endpoint: + type: boolean + required: + - body + - button_text + - flow_id + twilioFlows: + type: object + description: twilio/flows templates allow you to send multiple messages in a + set order with text or select options + nullable: true + additionalProperties: false + properties: + body: + type: string + button_text: + type: string + subtitle: + type: string + media_url: + type: string + pages: + $ref: '#/components/schemas/flowsPages' + type: + type: string + required: + - body + - button_text + - subtitle + - media_url + - pages + - type + flowsPages: + type: array + items: + $ref: '#/components/schemas/flowsPage' + flowsPage: + type: object + additionalProperties: false + properties: + id: + type: string + next_page_id: + type: string + title: + type: string + subtitle: + type: string + layout: + $ref: '#/components/schemas/flowsPageComponents' + required: + - id + - layout + flowsPageComponents: + type: array + items: + $ref: '#/components/schemas/flowsPageComponent' + flowsPageComponent: + type: object + additionalProperties: false + properties: + label: + type: string + type: + type: string + required: + - label + - type + ContentApprovalRequest: + type: object + description: Content approval request body + required: + - name + - category + properties: + name: + description: Name of the template. + type: string + category: + description: A WhatsApp recognized template category. + type: string + ContentCreateRequest: + type: object + description: Content creation request body + properties: + friendly_name: + description: User defined name of the content + type: string + variables: + description: Key value pairs of variable name to value + type: object + additionalProperties: + type: string + language: + description: Language code for the content + type: string + types: + $ref: '#/components/schemas/types' + required: + - language + - types + types: + description: Content types + type: object + properties: + twilio/text: + $ref: '#/components/schemas/twilioText' + twilio/media: + $ref: '#/components/schemas/twilioMedia' + twilio/location: + $ref: '#/components/schemas/twilioLocation' + twilio/list-picker: + $ref: '#/components/schemas/twilioListPicker' + twilio/call-to-action: + $ref: '#/components/schemas/twilioCallToAction' + twilio/quick-reply: + $ref: '#/components/schemas/twilioQuickReply' + twilio/card: + $ref: '#/components/schemas/twilioCard' + twilio/catalog: + $ref: '#/components/schemas/twilioCatalog' + twilio/carousel: + $ref: '#/components/schemas/twilioCarousel' + twilio/flows: + $ref: '#/components/schemas/twilioFlows' + twilio/schedule: + $ref: '#/components/schemas/twilioSchedule' + whatsapp/card: + $ref: '#/components/schemas/whatsappCard' + whatsapp/authentication: + $ref: '#/components/schemas/whatsappAuthentication' + whatsapp/flows: + $ref: '#/components/schemas/whatsappFlows' + content.v1.content.approval_create: + type: object + properties: + name: + type: string + nullable: true + category: + type: string + nullable: true + content_type: + type: string + nullable: true + status: + type: string + nullable: true + rejection_reason: + type: string + nullable: true + allow_category_change: + type: boolean + nullable: true + content.v1.content.approval_fetch: + type: object + properties: + sid: + type: string + minLength: 34 + maxLength: 34 + pattern: ^HX[0-9a-fA-F]{32}$ + nullable: true + description: The unique string that that we created to identify the Content + resource. + account_sid: + type: string + minLength: 34 + maxLength: 34 + pattern: ^AC[0-9a-fA-F]{32}$ + nullable: true + description: The SID of the [Account](https://www.twilio.com/docs/usage/api/account) + that created Content resource. + whatsapp: + type: object + nullable: true + description: Contains the whatsapp approval information for the Content + resource, with fields such as approval status, rejection reason, and category, + amongst others. + url: + type: string + format: uri + nullable: true + description: The URL of the resource, relative to `https://content.twilio.com`. + content.v1.content.fetch: + type: object + properties: + date_created: + type: string + format: date-time + nullable: true + description: The date and time in GMT that the resource was created specified + in [RFC 2822](https://www.ietf.org/rfc/rfc2822.txt) format. + date_updated: + type: string + format: date-time + nullable: true + description: The date and time in GMT that the resource was last updated + specified in [RFC 2822](https://www.ietf.org/rfc/rfc2822.txt) format. + sid: + type: string + minLength: 34 + maxLength: 34 + pattern: ^HX[0-9a-fA-F]{32}$ + nullable: true + description: The unique string that that we created to identify the Content + resource. + account_sid: + type: string + minLength: 34 + maxLength: 34 + pattern: ^AC[0-9a-fA-F]{32}$ + nullable: true + description: The SID of the [Account](https://www.twilio.com/docs/usage/api/account) + that created Content resource. + friendly_name: + type: string + nullable: true + description: A string name used to describe the Content resource. Not visible + to the end recipient. + language: + type: string + nullable: true + description: Two-letter (ISO 639-1) language code (e.g., en) identifying + the language the Content resource is in. + variables: + type: object + nullable: true + description: 'Defines the default placeholder values for variables included + in the Content resource. e.g. {"1": "Customer_Name"}.' + content.v1.content.list: + type: object + properties: + account_sid: + type: string + minLength: 34 + maxLength: 34 + pattern: ^AC[0-9a-fA-F]{32}$ + nullable: true + description: The SID of the [Account](https://www.twilio.com/docs/usage/api/account) + that created Content resource. + friendly_name: + type: string + nullable: true + description: A string name used to describe the Content resource. Not visible + to the end recipient. + language: + type: string + nullable: true + description: Two-letter (ISO 639-1) language code (e.g., en) identifying + the language the Content resource is in. + content.v1.content: + type: object + properties: + date_created: + type: string + format: date-time + nullable: true + description: The date and time in GMT that the resource was created specified + in [RFC 2822](https://www.ietf.org/rfc/rfc2822.txt) format. + date_updated: + type: string + format: date-time + nullable: true + description: The date and time in GMT that the resource was last updated + specified in [RFC 2822](https://www.ietf.org/rfc/rfc2822.txt) format. + sid: + type: string + minLength: 34 + maxLength: 34 + pattern: ^HX[0-9a-fA-F]{32}$ + nullable: true + description: The unique string that that we created to identify the Content + resource. + account_sid: + type: string + minLength: 34 + maxLength: 34 + pattern: ^AC[0-9a-fA-F]{32}$ + nullable: true + description: The SID of the [Account](https://www.twilio.com/docs/usage/api/account) + that created Content resource. + friendly_name: + type: string + nullable: true + description: A string name used to describe the Content resource. Not visible + to the end recipient. + language: + type: string + nullable: true + description: Two-letter (ISO 639-1) language code (e.g., en) identifying + the language the Content resource is in. + variables: + type: object + nullable: true + description: 'Defines the default placeholder values for variables included + in the Content resource. e.g. {"1": "Customer_Name"}.' + types: + type: object + nullable: true + description: The [Content types](https://www.twilio.com/docs/content-api/content-types-overview) + (e.g. twilio/text) for this Content resource. + url: + type: string + format: uri + nullable: true + description: The URL of the resource, relative to `https://content.twilio.com`. + links: + type: object + format: uri-map + nullable: true + description: A list of links related to the Content resource, such as approval_fetch + and approval_create + content.v1.content_and_approvals: + type: object + properties: + date_created: + type: string + format: date-time + nullable: true + description: The date and time in GMT that the resource was created specified + in [RFC 2822](https://www.ietf.org/rfc/rfc2822.txt) format. + date_updated: + type: string + format: date-time + nullable: true + description: The date and time in GMT that the resource was last updated + specified in [RFC 2822](https://www.ietf.org/rfc/rfc2822.txt) format. + sid: + type: string + minLength: 34 + maxLength: 34 + pattern: ^HX[0-9a-fA-F]{32}$ + nullable: true + description: The unique string that that we created to identify the Content + resource. + account_sid: + type: string + minLength: 34 + maxLength: 34 + pattern: ^AC[0-9a-fA-F]{32}$ + nullable: true + description: The SID of the [Account](https://www.twilio.com/docs/usage/api/account) + that created Content resource. + friendly_name: + type: string + nullable: true + description: A string name used to describe the Content resource. Not visible + to the end recipient. + language: + type: string + nullable: true + description: Two-letter (ISO 639-1) language code (e.g., en) identifying + the language the Content resource is in. + variables: + type: object + nullable: true + description: 'Defines the default placeholder values for variables included + in the Content resource. e.g. {"1": "Customer_Name"}.' + types: + type: object + nullable: true + description: The [Content types](https://www.twilio.com/docs/content-api/content-types-overview) + (e.g. twilio/text) for this Content resource. + approval_requests: + type: object + nullable: true + description: The submitted information and approval request status of the + Content resource. + content.v1.legacy_content: + type: object + properties: + date_created: + type: string + format: date-time + nullable: true + description: The date and time in GMT that the resource was created specified + in [RFC 2822](https://www.ietf.org/rfc/rfc2822.txt) format. + date_updated: + type: string + format: date-time + nullable: true + description: The date and time in GMT that the resource was last updated + specified in [RFC 2822](https://www.ietf.org/rfc/rfc2822.txt) format. + sid: + type: string + minLength: 34 + maxLength: 34 + pattern: ^HX[0-9a-fA-F]{32}$ + nullable: true + description: The unique string that that we created to identify the Content + resource. + account_sid: + type: string + minLength: 34 + maxLength: 34 + pattern: ^AC[0-9a-fA-F]{32}$ + nullable: true + description: The SID of the [Account](https://www.twilio.com/docs/usage/api/account) + that created Content resource. + friendly_name: + type: string + nullable: true + description: A string name used to describe the Content resource. Not visible + to the end recipient. + language: + type: string + nullable: true + description: Two-letter (ISO 639-1) language code (e.g., en) identifying + the language the Content resource is in. + variables: + type: object + nullable: true + description: 'Defines the default placeholder values for variables included + in the Content resource. e.g. {"1": "Customer_Name"}.' + types: + type: object + nullable: true + description: The [Content types](https://www.twilio.com/docs/content-api/content-types-overview) + (e.g. twilio/text) for this Content resource. + legacy_template_name: + type: string + nullable: true + description: The string name of the legacy content template associated with + this Content resource, unique across all template names for its account. Only + lowercase letters, numbers and underscores are allowed + legacy_body: + type: string + nullable: true + description: The string body field of the legacy content template associated + with this Content resource + url: + type: string + format: uri + nullable: true + description: The URL of the resource, relative to `https://content.twilio.com`. +info: + title: Twilio - Content + description: This is the public Twilio REST API. + termsOfService: https://www.twilio.com/legal/tos + 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.1.0 + x-twilio: + apiStandards: v1.0 +openapi: 3.0.1 +paths: + /v1/Content/{Sid}: + servers: + - url: https://multiresponse.twilio.com + description: A Content resource represents rich messaging content. + x-twilio: + defaultOutputProperties: + - date_created + - date_updated + - sid + - account_sid + - friendly_name + - language + - variables + - types + dependentProperties: + approval_create: + mapping: + content_sid: sid + resource_url: /v1/Content/{content_sid}/ApprovalRequests/whatsapp + approval_fetch: + mapping: + content_sid: sid + resource_url: /v1/Content/{content_sid}/ApprovalRequests + mountName: contents + pathType: instance + get: + description: Fetch a Content resource by its unique Content Sid + summary: Fetch Content + tags: + - Contentv1Content + parameters: + - name: Sid + in: path + description: The Twilio-provided string that uniquely identifies the Content + resource to fetch. + schema: + type: string + minLength: 34 + maxLength: 34 + pattern: ^HX[0-9a-fA-F]{32}$ + required: true + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/content.v1.content.fetch' + examples: + fetch: + value: + sid: HXaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + account_sid: ACaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + friendly_name: Some content + language: en + variables: + name: foo + types: + twilio/text: + body: Foo Bar Co is located at 39.7392, 104.9903 + twilio/location: + longitude: 104.9903 + latitude: 39.7392 + label: Foo Bar Co + url: https://content.twilio.com/v1/Content/HXaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + date_created: '2015-07-30T19:00:00Z' + date_updated: '2015-07-30T19:00:00Z' + links: + approval_create: https://content.twilio.com/v1/Content/HXaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/ApprovalRequests/whatsapp + approval_fetch: https://content.twilio.com/v1/Content/HXaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/ApprovalRequests + 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 + description: OK + security: + - accountSid_authToken: [] + operationId: FetchContent + delete: + description: Deletes a Content resource + summary: Delete Content + tags: + - Contentv1Content + parameters: + - name: Sid + in: path + description: The Twilio-provided string that uniquely identifies the Content + resource to fetch. + schema: + type: string + minLength: 34 + maxLength: 34 + pattern: ^HX[0-9a-fA-F]{32}$ + required: true + responses: + '204': + description: The resource was deleted successfully. + security: + - accountSid_authToken: [] + operationId: DeleteContent + /v1/Content: + servers: + - url: https://multiresponse.twilio.com + description: A Content resource represents rich messaging content. + x-twilio: + defaultOutputProperties: + - date_created + - date_updated + - sid + - account_sid + - friendly_name + - language + - variables + - types + dependentProperties: + approval_create: + mapping: + content_sid: sid + resource_url: /v1/Content/{content_sid}/ApprovalRequests/whatsapp + approval_fetch: + mapping: + content_sid: sid + resource_url: /v1/Content/{content_sid}/ApprovalRequests + mountName: contents + pathType: list + post: + description: Create a Content resource + summary: Create Content + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/ContentCreateRequest' + tags: + - Contentv1Content + responses: + '201': + content: + application/json: + schema: + $ref: '#/components/schemas/content.v1.content' + examples: + create: + value: + sid: HXaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + account_sid: ACaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + friendly_name: '' + language: en + variables: + name: foo + types: + twilio/text: + body: Foo Bar Co is located at 39.7392, 104.9903 + twilio/location: + longitude: 104.9903 + latitude: 39.7392 + label: Foo Bar Co + url: https://content.twilio.com/v1/Content/HXaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + date_created: '2015-07-30T19:00:00Z' + date_updated: '2015-07-30T19:00:00Z' + links: + approval_create: https://content.twilio.com/v1/Content/HXaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/ApprovalRequests/whatsapp + approval_fetch: https://content.twilio.com/v1/Content/HXaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/ApprovalRequests + 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 + description: Created + security: + - accountSid_authToken: [] + operationId: CreateContent + get: + description: Retrieve a list of Contents belonging to the account used to make + the request + summary: List Contents + tags: + - Contentv1Content + parameters: + - name: PageSize + in: query + description: How many resources to return in each list page. The default is + 50, and the maximum is 1000. + schema: + type: integer + minimum: 1 + maximum: 1000 + - name: Page + in: query + description: The page index. This value is simply for client state. + schema: + type: integer + minimum: 0 + - name: PageToken + in: query + description: The page token. This is provided by the API. + schema: + type: string + responses: + '200': + content: + application/json: + schema: + type: object + title: ListContentResponse + properties: + contents: + type: array + items: + $ref: '#/components/schemas/content.v1.content.list' + 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 + examples: + readEmpty: + value: + contents: [] + meta: + page: 0 + page_size: 10 + first_page_url: https://content.twilio.com/v1/Content?PageSize=10&Page=0 + previous_page_url: null + url: https://content.twilio.com/v1/Content?PageSize=10&Page=0 + next_page_url: null + key: contents + readResults: + value: + contents: + - sid: HXaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + account_sid: ACaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + friendly_name: Some content + language: en + variables: + name: foo + types: + twilio/text: + body: Foo Bar Co is located at 39.7392, 104.9903 + twilio/location: + longitude: 104.9903 + latitude: 39.7392 + label: Foo Bar Co + url: https://content.twilio.com/v1/Content/HXaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + date_created: '2015-07-30T19:00:00Z' + date_updated: '2015-07-30T19:00:00Z' + links: + approval_create: https://content.twilio.com/v1/Content/HXaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/ApprovalRequests/whatsapp + approval_fetch: https://content.twilio.com/v1/Content/HXaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/ApprovalRequests + - sid: HXaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + account_sid: ACaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + friendly_name: Anotha content + language: en + variables: + name: foo + types: + twilio/text: + body: Foo Bar Co is located at 39.7392, 104.9903 + twilio/location: + longitude: 104.9903 + latitude: 39.7392 + label: Foo Bar Co + url: https://content.twilio.com/v1/Content/HXaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + date_created: '2015-07-30T19:00:00Z' + date_updated: '2015-07-30T19:00:00Z' + links: + approval_create: https://content.twilio.com/v1/Content/HXaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/ApprovalRequests/whatsapp + approval_fetch: https://content.twilio.com/v1/Content/HXaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/ApprovalRequests + - sid: HXaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + account_sid: ACaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + friendly_name: Third content + language: en + variables: + name: foo + types: + twilio/text: + body: Foo Bar Co is located at 39.7392, 104.9903 + twilio/location: + longitude: 104.9903 + latitude: 39.7392 + label: Foo Bar Co + url: https://content.twilio.com/v1/Content/HXaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + date_created: '2015-07-30T19:00:00Z' + date_updated: '2015-07-30T19:00:00Z' + links: + approval_create: https://content.twilio.com/v1/Content/HXaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/ApprovalRequests/whatsapp + approval_fetch: https://content.twilio.com/v1/Content/HXaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/ApprovalRequests + meta: + page: 0 + page_size: 20 + first_page_url: https://content.twilio.com/v1/Content?PageSize=20&Page=0 + previous_page_url: null + url: https://content.twilio.com/v1/Content?PageSize=20&Page=0 + next_page_url: null + key: contents + 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 + description: OK + security: + - accountSid_authToken: [] + operationId: ListContent + /v1/Multi: + servers: + - url: https://multiresponse.twilio.com + description: A Content resource represents rich messaging content. + x-twilio: + defaultOutputProperties: + - date_created + - date_updated + - sid + - account_sid + - friendly_name + - language + - variables + - types + dependentProperties: + approval_create: + mapping: + content_sid: sid + resource_url: /v1/Content/{content_sid}/ApprovalRequests/whatsapp + approval_fetch: + mapping: + content_sid: sid + resource_url: /v1/Content/{content_sid}/ApprovalRequests + mountName: multi + pathType: list + get: + description: Retrieve a list of Contents belonging to the account used to make + the request + summary: List Contents + tags: + - MultiV1Content + parameters: + - name: PageSize + in: query + description: How many resources to return in each list page. The default is + 50, and the maximum is 1000. + schema: + type: integer + minimum: 1 + maximum: 1000 + - name: Page + in: query + description: The page index. This value is simply for client state. + schema: + type: integer + minimum: 0 + - name: PageToken + in: query + description: The page token. This is provided by the API. + schema: + type: string + responses: + '200': + content: + application/json: + schema: + type: object + title: ListContentResponse + properties: + contents: + type: array + items: + $ref: '#/components/schemas/content.v1.content.list' + end: + type: integer + first_page_uri: + format: uri + type: string + next_page_uri: + format: uri + nullable: true + type: string + page: + type: integer + page_size: + type: integer + previous_page_uri: + format: uri + nullable: true + type: string + start: + type: integer + uri: + format: uri + type: string + examples: + readEmpty: + value: + contents: [ ] + meta: + page: 0 + page_size: 10 + first_page_url: https://content.twilio.com/v1/Content?PageSize=10&Page=0 + previous_page_url: null + url: https://content.twilio.com/v1/Content?PageSize=10&Page=0 + next_page_url: null + key: contents + readResults: + value: + contents: + - sid: HXaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + account_sid: ACaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + friendly_name: Some content + language: en + variables: + name: foo + types: + twilio/text: + body: Foo Bar Co is located at 39.7392, 104.9903 + twilio/location: + longitude: 104.9903 + latitude: 39.7392 + label: Foo Bar Co + url: https://content.twilio.com/v1/Content/HXaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + date_created: '2015-07-30T19:00:00Z' + date_updated: '2015-07-30T19:00:00Z' + links: + approval_create: https://content.twilio.com/v1/Content/HXaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/ApprovalRequests/whatsapp + approval_fetch: https://content.twilio.com/v1/Content/HXaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/ApprovalRequests + - sid: HXaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + account_sid: ACaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + friendly_name: Anotha content + language: en + variables: + name: foo + types: + twilio/text: + body: Foo Bar Co is located at 39.7392, 104.9903 + twilio/location: + longitude: 104.9903 + latitude: 39.7392 + label: Foo Bar Co + url: https://content.twilio.com/v1/Content/HXaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + date_created: '2015-07-30T19:00:00Z' + date_updated: '2015-07-30T19:00:00Z' + links: + approval_create: https://content.twilio.com/v1/Content/HXaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/ApprovalRequests/whatsapp + approval_fetch: https://content.twilio.com/v1/Content/HXaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/ApprovalRequests + - sid: HXaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + account_sid: ACaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + friendly_name: Third content + language: en + variables: + name: foo + types: + twilio/text: + body: Foo Bar Co is located at 39.7392, 104.9903 + twilio/location: + longitude: 104.9903 + latitude: 39.7392 + label: Foo Bar Co + url: https://content.twilio.com/v1/Content/HXaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + date_created: '2015-07-30T19:00:00Z' + date_updated: '2015-07-30T19:00:00Z' + links: + approval_create: https://content.twilio.com/v1/Content/HXaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/ApprovalRequests/whatsapp + approval_fetch: https://content.twilio.com/v1/Content/HXaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/ApprovalRequests + meta: + page: 0 + page_size: 20 + first_page_url: https://content.twilio.com/v1/Content?PageSize=20&Page=0 + previous_page_url: null + url: https://content.twilio.com/v1/Content?PageSize=20&Page=0 + next_page_url: null + key: contents + 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 + description: OK + security: + - accountSid_authToken: [ ] + operationId: ListMulti +servers: + - url: https://multiresponse.twilio.com +tags: + - name: Contentv1ApprovalCreate + - name: Contentv1ApprovalFetch + - name: Contentv1Content + - name: Contentv1ContentAndApprovals + - name: Contentv1LegacyContent diff --git a/src/main/java/com/twilio/oai/java/JavaApiResourceBuilder.java b/src/main/java/com/twilio/oai/java/JavaApiResourceBuilder.java index 3f06f3f71..c60315c6e 100644 --- a/src/main/java/com/twilio/oai/java/JavaApiResourceBuilder.java +++ b/src/main/java/com/twilio/oai/java/JavaApiResourceBuilder.java @@ -45,6 +45,7 @@ public JavaApiResourceBuilder resourceName() { public JavaApiResourceBuilder recordKey() { this.recordKey = Utility.getRecordKey(ResourceCacheContext.get().getAllModelsByDefaultGenerator(), operations); + ResourceCacheContext.get().setRecordKey(this.recordKey); return this; } 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 a0920316c..4a5ba3e3b 100644 --- a/src/main/java/com/twilio/oai/java/cache/ResourceCache2.java +++ b/src/main/java/com/twilio/oai/java/cache/ResourceCache2.java @@ -17,6 +17,10 @@ public class ResourceCache2 { @Setter private String resourceName; + @Getter + @Setter + private String recordKey; + @Getter @Setter private Set response = new TreeSet<>((p1, p2) -> p1.baseName.compareTo(p2.baseName)); @@ -43,10 +47,6 @@ public class ResourceCache2 { @Setter private boolean isV1; - @Getter - @Setter - private boolean isV1; - public void setAllModelsByDefaultGenerator(ArrayList allModelsByDefaultGenerator) { this.allModelsByDefaultGenerator = new ArrayList<>(allModelsByDefaultGenerator); } diff --git a/src/main/java/com/twilio/oai/java/processor/responsebody/JsonMultipleResponseProcessor.java b/src/main/java/com/twilio/oai/java/processor/responsebody/JsonMultipleResponseProcessor.java index d1e265ed6..21d5336e2 100644 --- a/src/main/java/com/twilio/oai/java/processor/responsebody/JsonMultipleResponseProcessor.java +++ b/src/main/java/com/twilio/oai/java/processor/responsebody/JsonMultipleResponseProcessor.java @@ -1,24 +1,21 @@ package com.twilio.oai.java.processor.responsebody; import com.twilio.oai.common.ApplicationConstants; -import com.twilio.oai.common.Utility; +import com.twilio.oai.common.StringUtils; import com.twilio.oai.java.cache.ResourceCacheContext; import com.twilio.oai.java.constants.MustacheConstants; -import com.twilio.oai.java.format.Deserializer; import com.twilio.oai.java.processor.enums.EnumProcessorFactory; import com.twilio.oai.java.processor.requestbody.RecursiveModelProcessor; -import com.twilio.oai.java.processor.responsebody.paginationremover.Meta; import org.openapitools.codegen.CodegenModel; import org.openapitools.codegen.CodegenOperation; import org.openapitools.codegen.CodegenProperty; -import org.openapitools.codegen.Constants; +import org.openapitools.codegen.CodegenResponse; import java.util.Map; public class JsonMultipleResponseProcessor extends JsonResponseAbstractProcessor implements ResponseProcessor { EnumProcessorFactory enumProcessorFactory = EnumProcessorFactory.getInstance(); RecursiveModelProcessor recursiveModelProcessor = new RecursiveModelProcessor(); - Meta meta = new Meta(); @Override public void process(final CodegenOperation codegenOperation) { @@ -53,17 +50,33 @@ public boolean shouldProcess(final CodegenOperation codegenOperation) { private void processResponseWithoutPagination(CodegenOperation codegenOperation) { System.out.println(codegenOperation.operationId); CodegenProperty codegenProperty = getCodegenProperty(codegenOperation); + if (codegenProperty == null) { + codegenOperation.vendorExtensions.put(MustacheConstants.X_RESPONSE_DATATYPE, "void"); + return; + } recursiveModelProcessor.process(codegenProperty); codegenOperation.vendorExtensions.put(MustacheConstants.X_RESPONSE_DATATYPE, codegenProperty.vendorExtensions.get(ApplicationConstants.X_DATATYPE)); } private void processResponseWithPagination(CodegenOperation codegenOperation) { // check if pagination exists, if no, go to processResponseWithoutPagination + Map codegenModelMap = ResourceCacheContext.get().getAllModelsMapByDefaultGenerator(); + CodegenProperty responseProperty = null; + for (CodegenResponse response: codegenOperation.responses) { + CodegenModel codegenModel = codegenModelMap.get(StringUtils.toPascalCase(response.baseType)); + for (CodegenProperty codegenProperty: codegenModel.vars) { + if (codegenProperty.name.equals(ResourceCacheContext.get().getRecordKey())) { + responseProperty = codegenProperty; + } + } + } - meta.shouldProcess(codegenOperation); - CodegenProperty codegenProperty = meta.getResponse(codegenOperation); - recursiveModelProcessor.process(codegenProperty); - String listResponseDatatype = (String)codegenProperty.vendorExtensions.get(ApplicationConstants.X_DATATYPE); + if (responseProperty == null) { + codegenOperation.vendorExtensions.put(MustacheConstants.X_RESPONSE_DATATYPE, "void"); + return; + } + recursiveModelProcessor.process(responseProperty); + String listResponseDatatype = (String)responseProperty.vendorExtensions.get(ApplicationConstants.X_DATATYPE); listResponseDatatype = listResponseDatatype.replaceFirst("^List(?=<)", "ResourceSet"); codegenOperation.vendorExtensions.put(MustacheConstants.X_RESPONSE_DATATYPE, listResponseDatatype); } diff --git a/src/main/java/com/twilio/oai/java/processor/responsebody/paginationremover/Meta.java b/src/main/java/com/twilio/oai/java/processor/responsebody/paginationremover/Meta.java deleted file mode 100644 index 175257c71..000000000 --- a/src/main/java/com/twilio/oai/java/processor/responsebody/paginationremover/Meta.java +++ /dev/null @@ -1,48 +0,0 @@ -package com.twilio.oai.java.processor.responsebody.paginationremover; - -import com.intuit.commons.traverser.Traverser; -import com.intuit.commons.traverser.TraversingIterator; -import com.twilio.oai.common.StringUtils; -import com.twilio.oai.common.Utility; -import com.twilio.oai.java.cache.ResourceCache2; -import com.twilio.oai.java.cache.ResourceCacheContext; -import com.twilio.oai.java.processor.traverser.CustomTraverser; -import org.checkerframework.checker.units.qual.C; -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 Meta extends ResponsePaginationRemover { - @Override - public boolean shouldProcess(CodegenOperation codegenOperation) { - - Map codegenModelMap = ResourceCacheContext.get().getAllModelsMapByDefaultGenerator(); - // Check if in the response body there is a "meta" property - for (CodegenResponse response: codegenOperation.responses) { - CodegenModel codegenModel = codegenModelMap.get(StringUtils.toPascalCase(response.baseType)); - for (CodegenProperty codegenProperty: codegenModel.vars) { - if (codegenProperty.name.equals("meta")) { - return true; - } - } - } - return false; - } - - @Override - public CodegenProperty getResponse(CodegenOperation codegenOperation) { - Map codegenModelMap = ResourceCacheContext.get().getAllModelsMapByDefaultGenerator(); - for (CodegenResponse response: codegenOperation.responses) { - CodegenModel codegenModel = codegenModelMap.get(StringUtils.toPascalCase(response.baseType)); - for (CodegenProperty codegenProperty: codegenModel.vars) { - if (!codegenProperty.name.equals("meta")) { - return codegenProperty; - } - } - } - return null; - } -} diff --git a/src/main/java/com/twilio/oai/java/processor/responsebody/paginationremover/ResponsePaginationRemover.java b/src/main/java/com/twilio/oai/java/processor/responsebody/paginationremover/ResponsePaginationRemover.java deleted file mode 100644 index c85c0ba66..000000000 --- a/src/main/java/com/twilio/oai/java/processor/responsebody/paginationremover/ResponsePaginationRemover.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.twilio.oai.java.processor.responsebody.paginationremover; - -import org.openapitools.codegen.CodegenModel; -import org.openapitools.codegen.CodegenOperation; -import org.openapitools.codegen.CodegenProperty; - -public abstract class ResponsePaginationRemover { - abstract boolean shouldProcess(final CodegenOperation codegenOperation); - - abstract CodegenProperty getResponse(final CodegenOperation codegenOperation); -} diff --git a/src/main/java/com/twilio/oai/java/processor/responsebody/paginationremover/Root.java b/src/main/java/com/twilio/oai/java/processor/responsebody/paginationremover/Root.java deleted file mode 100644 index 252ac3658..000000000 --- a/src/main/java/com/twilio/oai/java/processor/responsebody/paginationremover/Root.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.twilio.oai.java.processor.responsebody.paginationremover; - -import org.openapitools.codegen.CodegenOperation; -import org.openapitools.codegen.CodegenProperty; - -public class Root extends ResponsePaginationRemover { - @Override - public boolean shouldProcess(CodegenOperation codegenOperation) { - // check if the response body is the pagination model itself - System.out.println(codegenOperation); - return false; - } - - @Override - CodegenProperty getResponse(CodegenOperation codegenOperation) { - return null; - } -}