This is an automated email from the ASF dual-hosted git repository. davsclaus pushed a commit to branch rest-out in repository https://gitbox.apache.org/repos/asf/camel.git
commit f1868c73fcce6a58a2b6b93b574cdbe7f5d748ef Author: Claus Ibsen <[email protected]> AuthorDate: Mon Mar 11 11:13:46 2024 +0100 CAMEL-19284: restdsl-openapi-generator - Add type and outType to Rest DSL --- .../apache/camel/model/rest/RestDefinition.java | 22 ++ .../dsl/jbang/core/commands/CodeRestGenerator.java | 24 +- .../camel/generator/openapi/OperationVisitor.java | 66 +++++- .../camel/generator/openapi/PathVisitor.java | 10 +- .../openapi/RestDslDefinitionGenerator.java | 2 +- .../camel/generator/openapi/RestDslGenerator.java | 35 +-- .../openapi/RestDslSourceCodeGenerator.java | 2 +- .../generator/openapi/RestDslXmlGenerator.java | 3 +- .../generator/openapi/RestDslYamlGenerator.java | 3 +- .../generator/openapi/OperationVisitorTest.java | 5 +- .../openapi/RestDslYamlGeneratorV3Test.java | 20 +- .../resources/OpenApiV3PetstoreWithModelYaml.txt | 255 +++++++++++++++++++++ 12 files changed, 386 insertions(+), 61 deletions(-) diff --git a/core/camel-core-model/src/main/java/org/apache/camel/model/rest/RestDefinition.java b/core/camel-core-model/src/main/java/org/apache/camel/model/rest/RestDefinition.java index a2ebaa6404e..cb17ab754f9 100644 --- a/core/camel-core-model/src/main/java/org/apache/camel/model/rest/RestDefinition.java +++ b/core/camel-core-model/src/main/java/org/apache/camel/model/rest/RestDefinition.java @@ -564,6 +564,17 @@ public class RestDefinition extends OptionalIdentifiedDefinition<RestDefinition> return this; } + public RestDefinition type(String classType) { + // add to last verb + if (getVerbs().isEmpty()) { + throw new IllegalArgumentException(MISSING_VERB); + } + + VerbDefinition verb = getVerbs().get(getVerbs().size() - 1); + verb.setType(classType); + return this; + } + public RestDefinition type(Class<?> classType) { // add to last verb if (getVerbs().isEmpty()) { @@ -576,6 +587,17 @@ public class RestDefinition extends OptionalIdentifiedDefinition<RestDefinition> return this; } + public RestDefinition outType(String classType) { + // add to last verb + if (getVerbs().isEmpty()) { + throw new IllegalArgumentException(MISSING_VERB); + } + + VerbDefinition verb = getVerbs().get(getVerbs().size() - 1); + verb.setOutType(classType); + return this; + } + public RestDefinition outType(Class<?> classType) { // add to last verb if (getVerbs().isEmpty()) { diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/CodeRestGenerator.java b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/CodeRestGenerator.java index f92682ac6d2..12df871ed08 100644 --- a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/CodeRestGenerator.java +++ b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/CodeRestGenerator.java @@ -49,23 +49,23 @@ import static org.openapitools.codegen.CodegenConstants.SERIALIZABLE_MODEL; @CommandLine.Command(name = "rest", description = "Generate REST DSL source code from OpenApi specification") public class CodeRestGenerator extends CamelCommand { - @CommandLine.Option(names = { "-i", "--input" }, required = true, description = "OpenApi specification file name") + @CommandLine.Option(names = { "--input" }, required = true, description = "OpenApi specification file name") private String input; - @CommandLine.Option(names = { "-o", "--output" }, description = "Output REST DSL file name") + @CommandLine.Option(names = { "--output" }, description = "Output REST DSL file name") private String output; - @CommandLine.Option(names = { "-t", "--type" }, description = "REST DSL type (YAML or XML)", defaultValue = "yaml") + @CommandLine.Option(names = { "--type" }, description = "REST DSL type (YAML or XML)", defaultValue = "yaml") private String type; - @CommandLine.Option(names = { "-r", "--routes" }, description = "Generate routes (only in YAML)") + @CommandLine.Option(names = { "--routes" }, description = "Generate routes (only in YAML)") private boolean generateRoutes; - @CommandLine.Option(names = { "-d", "--dto" }, description = "Generate Java Data Objects") + @CommandLine.Option(names = { "--dto" }, description = "Generate Java Data Objects") private boolean generateDataObjects; - @CommandLine.Option(names = { "-run", "--runtime" }, description = "Runtime (quarkus, or spring-boot)", + @CommandLine.Option(names = { "--runtime" }, description = "Runtime (quarkus, or spring-boot)", defaultValue = "quarkus") private String runtime; - @CommandLine.Option(names = { "-p", "--package" }, description = "Package for generated Java models", + @CommandLine.Option(names = { "--package" }, description = "Package for generated Java models", defaultValue = "model") private String packageName; - @CommandLine.Option(names = { "-v", "--openapi-version" }, description = "Openapi specification 3.0 or 3.1", + @CommandLine.Option(names = { "--openapi-version" }, description = "Openapi specification 3.0 or 3.1", defaultValue = "3.0") private String openApiVersion = "3.0"; @@ -93,9 +93,13 @@ public class CodeRestGenerator extends CamelCommand { try (CamelContext context = new DefaultCamelContext()) { String text = null; if ("yaml".equalsIgnoreCase(type)) { - text = RestDslGenerator.toYaml(doc).generate(context, generateRoutes); + text = RestDslGenerator.toYaml(doc) + .withDtoPackageName(generateDataObjects ? packageName : null) + .generate(context, generateRoutes); } else if ("xml".equalsIgnoreCase(type)) { - text = RestDslGenerator.toXml(doc).generate(context); + text = RestDslGenerator.toXml(doc) + .withDtoPackageName(generateDataObjects ? packageName : null) + .generate(context); } if (text != null) { if (output == null) { diff --git a/tooling/openapi-rest-dsl-generator/src/main/java/org/apache/camel/generator/openapi/OperationVisitor.java b/tooling/openapi-rest-dsl-generator/src/main/java/org/apache/camel/generator/openapi/OperationVisitor.java index 0dbd063d88f..6c6cbd14c12 100644 --- a/tooling/openapi-rest-dsl-generator/src/main/java/org/apache/camel/generator/openapi/OperationVisitor.java +++ b/tooling/openapi-rest-dsl-generator/src/main/java/org/apache/camel/generator/openapi/OperationVisitor.java @@ -24,6 +24,7 @@ import java.util.List; import java.util.Map.Entry; import java.util.Set; +import io.apicurio.datamodels.models.Referenceable; import io.apicurio.datamodels.models.Schema; import io.apicurio.datamodels.models.openapi.OpenApiMediaType; import io.apicurio.datamodels.models.openapi.OpenApiOperation; @@ -48,19 +49,18 @@ import org.apache.camel.util.StringHelper; class OperationVisitor<T> { private final DestinationGenerator destinationGenerator; - private final CodeEmitter<T> emitter; - private final OperationFilter filter; - private final String path; + private final String dtoPackageName; OperationVisitor(final CodeEmitter<T> emitter, final OperationFilter filter, final String path, - final DestinationGenerator destinationGenerator) { + final DestinationGenerator destinationGenerator, final String dtoPackageName) { this.emitter = emitter; this.filter = filter; this.path = path; this.destinationGenerator = destinationGenerator; + this.dtoPackageName = dtoPackageName; } List<String> asStringList(final List<?> values) { @@ -238,18 +238,18 @@ class OperationVisitor<T> { emitter.emit("to", destinationGenerator.generateDestinationFor(operation)); } - } private CodeEmitter<T> emitOas30Operation(final OpenApi30Operation operation) { if (operation.getRequestBody() != null) { + String dto = null; boolean foundForm = false; final OpenApi30RequestBody requestBody = operation.getRequestBody(); for (final Entry<String, OpenApiMediaType> entry : requestBody.getContent().entrySet()) { final String ct = entry.getKey(); - final OpenApi30MediaType mediaType = (OpenApi30MediaType) entry.getValue(); - if (ct.contains("form") && mediaType.getSchema().getProperties() != null) { - for (final Entry<String, Schema> entrySchema : mediaType.getSchema().getProperties().entrySet()) { + OpenApi30MediaType mt = (OpenApi30MediaType) entry.getValue(); + if (ct.contains("form") && mt.getSchema().getProperties() != null) { + for (final Entry<String, Schema> entrySchema : mt.getSchema().getProperties().entrySet()) { OpenApi30Schema openApi30Schema = (OpenApi30Schema) entrySchema.getValue(); foundForm = true; emitter.emit("param"); @@ -261,6 +261,20 @@ class OperationVisitor<T> { emitter.emit("endParam"); } } + if (dto == null && mt.getSchema() instanceof Referenceable ref) { + OpenApi30Schema schema = (OpenApi30Schema) mt.getSchema(); + boolean array = "array".equals(schema.getType()); + if (array) { + ref = schema.getItems(); + } + String r = ref.get$ref(); + if (r != null && r.startsWith("#/components/schemas/")) { + dto = r.substring(21); + if (array) { + dto += "[]"; + } + } + } } if (!foundForm) { emitter.emit("param"); @@ -270,9 +284,43 @@ class OperationVisitor<T> { emit("description", requestBody.getDescription()); emitter.emit("endParam"); } + if (dtoPackageName != null && dto != null) { + emit("type", dtoPackageName + "." + dto); + } } - return emitter; + if (operation.getResponses() != null) { + String dto = null; + for (String key : operation.getResponses().getItemNames()) { + if ("200".equals(key)) { + var response = operation.getResponses().getItem(key); + if (response instanceof OpenApi30Response res30) { + for (final Entry<String, OpenApi30MediaType> entry : res30.getContent().entrySet()) { + final OpenApi30MediaType mediaType = entry.getValue(); + if (dto == null && mediaType.getSchema() instanceof Referenceable ref) { + OpenApi30Schema schema = (OpenApi30Schema) mediaType.getSchema(); + boolean array = "array".equals(schema.getType()); + if (array) { + ref = schema.getItems(); + } + String r = ref.get$ref(); + if (r != null && r.startsWith("#/components/schemas/")) { + dto = r.substring(21); + if (array) { + dto += "[]"; + } + } + } + } + } + } + } + if (dtoPackageName != null && dto != null) { + emit("outType", dtoPackageName + "." + dto); + } + } + return emitter; } + } diff --git a/tooling/openapi-rest-dsl-generator/src/main/java/org/apache/camel/generator/openapi/PathVisitor.java b/tooling/openapi-rest-dsl-generator/src/main/java/org/apache/camel/generator/openapi/PathVisitor.java index ff0f2f01cf6..de47790c72f 100644 --- a/tooling/openapi-rest-dsl-generator/src/main/java/org/apache/camel/generator/openapi/PathVisitor.java +++ b/tooling/openapi-rest-dsl-generator/src/main/java/org/apache/camel/generator/openapi/PathVisitor.java @@ -26,10 +26,9 @@ import org.apache.camel.util.ObjectHelper; class PathVisitor<T> { private final DestinationGenerator destinationGenerator; - private final CodeEmitter<T> emitter; - private final OperationFilter filter; + private final String dtoPackageName; public enum HttpMethod { DELETE, @@ -42,10 +41,11 @@ class PathVisitor<T> { } PathVisitor(final String basePath, final CodeEmitter<T> emitter, final OperationFilter filter, - final DestinationGenerator destinationGenerator) { + final DestinationGenerator destinationGenerator, final String dtoPackageName) { this.emitter = emitter; this.filter = filter; this.destinationGenerator = destinationGenerator; + this.dtoPackageName = dtoPackageName; if (ObjectHelper.isEmpty(basePath)) { emitter.emit("rest"); @@ -55,8 +55,8 @@ class PathVisitor<T> { } void visit(final String path, final OpenApiPathItem definition) { - final OperationVisitor<T> restDslOperation = new OperationVisitor<>(emitter, filter, path, destinationGenerator); - + final OperationVisitor<T> restDslOperation + = new OperationVisitor<>(emitter, filter, path, destinationGenerator, dtoPackageName); operationMapFrom(definition).forEach(restDslOperation::visit); } diff --git a/tooling/openapi-rest-dsl-generator/src/main/java/org/apache/camel/generator/openapi/RestDslDefinitionGenerator.java b/tooling/openapi-rest-dsl-generator/src/main/java/org/apache/camel/generator/openapi/RestDslDefinitionGenerator.java index 033cbb581db..814fc1e9926 100644 --- a/tooling/openapi-rest-dsl-generator/src/main/java/org/apache/camel/generator/openapi/RestDslDefinitionGenerator.java +++ b/tooling/openapi-rest-dsl-generator/src/main/java/org/apache/camel/generator/openapi/RestDslDefinitionGenerator.java @@ -30,7 +30,7 @@ public final class RestDslDefinitionGenerator extends RestDslGenerator<RestDslDe final RestDefinitionEmitter emitter = new RestDefinitionEmitter(); final String basePath = RestDslGenerator.determineBasePathFrom(this.basePath, document); final PathVisitor<RestsDefinition> restDslStatement - = new PathVisitor<>(basePath, emitter, filter, destinationGenerator()); + = new PathVisitor<>(basePath, emitter, filter, destinationGenerator(), dtoPackageName); for (String name : document.getPaths().getItemNames()) { OpenApiPathItem item = document.getPaths().getItem(name); diff --git a/tooling/openapi-rest-dsl-generator/src/main/java/org/apache/camel/generator/openapi/RestDslGenerator.java b/tooling/openapi-rest-dsl-generator/src/main/java/org/apache/camel/generator/openapi/RestDslGenerator.java index c7b8722fab2..4d8ee1cb123 100644 --- a/tooling/openapi-rest-dsl-generator/src/main/java/org/apache/camel/generator/openapi/RestDslGenerator.java +++ b/tooling/openapi-rest-dsl-generator/src/main/java/org/apache/camel/generator/openapi/RestDslGenerator.java @@ -50,6 +50,7 @@ public abstract class RestDslGenerator<G> { boolean springBootProject; boolean springComponent; String basePath; + String dtoPackageName; RestDslGenerator(final OpenApiDocument document) { this.document = notNull(document, "document"); @@ -57,55 +58,43 @@ public abstract class RestDslGenerator<G> { public G asSpringBootProject() { this.springBootProject = true; - @SuppressWarnings("unchecked") final G that = (G) this; - return that; } public G asSpringComponent() { this.springComponent = true; - @SuppressWarnings("unchecked") final G that = (G) this; - return that; } public G withApiContextPath(final String contextPath) { this.apiContextPath = contextPath; - @SuppressWarnings("unchecked") final G that = (G) this; - return that; } public G withClientRequestValidation() { this.clientRequestValidation = true; - @SuppressWarnings("unchecked") final G that = (G) this; - return that; } public G withBasePath(final String basePath) { this.basePath = basePath; - @SuppressWarnings("unchecked") final G that = (G) this; - return that; } public G withDestinationGenerator(final DestinationGenerator destinationGenerator) { this.destinationGenerator = destinationGenerator; - @SuppressWarnings("unchecked") final G that = (G) this; - return that; } @@ -116,46 +105,43 @@ public abstract class RestDslGenerator<G> { */ public G withDestinationToSyntax(final String destinationToSyntax) { this.destinationToSyntax = destinationToSyntax; - @SuppressWarnings("unchecked") final G that = (G) this; - return that; } public G withOperationFilter(final OperationFilter filter) { this.filter = filter; - @SuppressWarnings("unchecked") final G that = (G) this; - return that; } public G withOperationFilter(final String include) { this.filter.setIncludes(include); - @SuppressWarnings("unchecked") final G that = (G) this; - return that; } public G withRestComponent(final String restComponent) { this.restComponent = restComponent; - @SuppressWarnings("unchecked") final G that = (G) this; - return that; } public G withRestContextPath(final String contextPath) { this.restContextPath = contextPath; - @SuppressWarnings("unchecked") final G that = (G) this; + return that; + } + public G withDtoPackageName(final String dtoPackageName) { + this.dtoPackageName = dtoPackageName; + @SuppressWarnings("unchecked") + final G that = (G) this; return that; } @@ -174,7 +160,6 @@ public abstract class RestDslGenerator<G> { public static String determineBasePathFrom(final String parameter) { Objects.requireNonNull(parameter, "parameter"); - return prepareBasePath(parameter.trim()); } @@ -207,12 +192,10 @@ public abstract class RestDslGenerator<G> { if (basePath.charAt(0) != '/') { basePath = "/" + basePath; } - if (basePath.indexOf("//") == 0) { // strip off the first "/" if double "/" exists basePath = basePath.substring(1); } - if ("/".equals(basePath)) { basePath = ""; } @@ -230,11 +213,8 @@ public abstract class RestDslGenerator<G> { if (servers == null || servers.get(0) == null) { return ""; } - final OpenApi30Server firstServer = servers.get(0); - final URI serverUrl = URI.create(resolveVariablesIn(firstServer.getUrl(), firstServer)); - return serverUrl.getHost(); } @@ -250,7 +230,6 @@ public abstract class RestDslGenerator<G> { withoutPlaceholders = withoutPlaceholders.replace(name, entry.getValue().getDefault()); } } - return withoutPlaceholders; } diff --git a/tooling/openapi-rest-dsl-generator/src/main/java/org/apache/camel/generator/openapi/RestDslSourceCodeGenerator.java b/tooling/openapi-rest-dsl-generator/src/main/java/org/apache/camel/generator/openapi/RestDslSourceCodeGenerator.java index 4388a464f3b..52a2aeda281 100644 --- a/tooling/openapi-rest-dsl-generator/src/main/java/org/apache/camel/generator/openapi/RestDslSourceCodeGenerator.java +++ b/tooling/openapi-rest-dsl-generator/src/main/java/org/apache/camel/generator/openapi/RestDslSourceCodeGenerator.java @@ -138,7 +138,7 @@ public abstract class RestDslSourceCodeGenerator<T> extends RestDslGenerator<Res if (anyAccepted) { // create new rest statement per path to avoid a giant chained single method PathVisitor<MethodSpec> restDslStatement - = new PathVisitor<>(basePath, emitter, filter, destinationGenerator()); + = new PathVisitor<>(basePath, emitter, filter, destinationGenerator(), dtoPackageName); restDslStatement.visit(name, s); emitter.endEmit(); } diff --git a/tooling/openapi-rest-dsl-generator/src/main/java/org/apache/camel/generator/openapi/RestDslXmlGenerator.java b/tooling/openapi-rest-dsl-generator/src/main/java/org/apache/camel/generator/openapi/RestDslXmlGenerator.java index 36f20c2c821..a1ebe22e705 100644 --- a/tooling/openapi-rest-dsl-generator/src/main/java/org/apache/camel/generator/openapi/RestDslXmlGenerator.java +++ b/tooling/openapi-rest-dsl-generator/src/main/java/org/apache/camel/generator/openapi/RestDslXmlGenerator.java @@ -53,7 +53,8 @@ public class RestDslXmlGenerator extends RestDslGenerator<RestDslXmlGenerator> { final String basePath = RestDslGenerator.determineBasePathFrom(this.basePath, document); final PathVisitor<RestsDefinition> restDslStatement = new PathVisitor<>( basePath, emitter, filter, - destinationGenerator()); + destinationGenerator(), + dtoPackageName); for (String name : document.getPaths().getItemNames()) { OpenApiPathItem item = document.getPaths().getItem(name); diff --git a/tooling/openapi-rest-dsl-generator/src/main/java/org/apache/camel/generator/openapi/RestDslYamlGenerator.java b/tooling/openapi-rest-dsl-generator/src/main/java/org/apache/camel/generator/openapi/RestDslYamlGenerator.java index 8a3636c1577..9303c3553e7 100644 --- a/tooling/openapi-rest-dsl-generator/src/main/java/org/apache/camel/generator/openapi/RestDslYamlGenerator.java +++ b/tooling/openapi-rest-dsl-generator/src/main/java/org/apache/camel/generator/openapi/RestDslYamlGenerator.java @@ -74,7 +74,8 @@ public class RestDslYamlGenerator extends RestDslGenerator<RestDslYamlGenerator> final String basePath = RestDslGenerator.determineBasePathFrom(this.basePath, document); final PathVisitor<RestsDefinition> restDslStatement = new PathVisitor<>( basePath, emitter, filter, - destinationGenerator()); + destinationGenerator(), + dtoPackageName); for (String name : document.getPaths().getItemNames()) { OpenApiPathItem item = document.getPaths().getItem(name); diff --git a/tooling/openapi-rest-dsl-generator/src/test/java/org/apache/camel/generator/openapi/OperationVisitorTest.java b/tooling/openapi-rest-dsl-generator/src/test/java/org/apache/camel/generator/openapi/OperationVisitorTest.java index d98ea155b27..774a160659b 100644 --- a/tooling/openapi-rest-dsl-generator/src/test/java/org/apache/camel/generator/openapi/OperationVisitorTest.java +++ b/tooling/openapi-rest-dsl-generator/src/test/java/org/apache/camel/generator/openapi/OperationVisitorTest.java @@ -37,7 +37,7 @@ public class OperationVisitorTest { public void shouldEmitCodeForOas2ParameterInQuery() { final Builder method = MethodSpec.methodBuilder("configure"); final MethodBodySourceCodeEmitter emitter = new MethodBodySourceCodeEmitter(method); - final OperationVisitor<?> visitor = new OperationVisitor<>(emitter, null, null, null); + final OperationVisitor<?> visitor = new OperationVisitor<>(emitter, null, null, null, null); final OpenApi20Parameter parameter = new OpenApi20ParameterImpl(); parameter.setName("param"); @@ -59,7 +59,8 @@ public class OperationVisitorTest { final Builder method = MethodSpec.methodBuilder("configure"); final MethodBodySourceCodeEmitter emitter = new MethodBodySourceCodeEmitter(method); final OperationVisitor<?> visitor - = new OperationVisitor<>(emitter, new OperationFilter(), "/path/{param}", new DefaultDestinationGenerator()); + = new OperationVisitor<>( + emitter, new OperationFilter(), "/path/{param}", new DefaultDestinationGenerator(), null); final OpenApi20Document document = new OpenApi20DocumentImpl(); final OpenApiPaths paths = document.createPaths(); diff --git a/tooling/openapi-rest-dsl-generator/src/test/java/org/apache/camel/generator/openapi/RestDslYamlGeneratorV3Test.java b/tooling/openapi-rest-dsl-generator/src/test/java/org/apache/camel/generator/openapi/RestDslYamlGeneratorV3Test.java index c3774382335..97d5beb24d5 100644 --- a/tooling/openapi-rest-dsl-generator/src/test/java/org/apache/camel/generator/openapi/RestDslYamlGeneratorV3Test.java +++ b/tooling/openapi-rest-dsl-generator/src/test/java/org/apache/camel/generator/openapi/RestDslYamlGeneratorV3Test.java @@ -41,7 +41,7 @@ public class RestDslYamlGeneratorV3Test { try (CamelContext context = new DefaultCamelContext()) { final String yaml = RestDslGenerator.toYaml(document).generate(context); - final URI file = RestDslXmlGeneratorV3Test.class.getResource("/OpenApiV3PetstoreYaml.txt").toURI(); + final URI file = RestDslYamlGeneratorV3Test.class.getResource("/OpenApiV3PetstoreYaml.txt").toURI(); final String expectedContent = new String(Files.readAllBytes(Paths.get(file)), StandardCharsets.UTF_8); assertThat(yaml).isEqualTo(expectedContent); @@ -49,14 +49,28 @@ public class RestDslYamlGeneratorV3Test { } @Test - public void shouldGenerateXmlWithRestComponent() throws Exception { + public void shouldGenerateYamlWithRestComponent() throws Exception { try (CamelContext context = new DefaultCamelContext()) { final String yaml = RestDslGenerator.toYaml(document) .withRestComponent("servlet") .withRestContextPath("/foo") .generate(context); - final URI file = RestDslXmlGeneratorV3Test.class.getResource("/OpenApiV3PetstoreWithRestComponentYaml.txt").toURI(); + final URI file + = RestDslYamlGeneratorV3Test.class.getResource("/OpenApiV3PetstoreWithRestComponentYaml.txt").toURI(); + final String expectedContent = new String(Files.readAllBytes(Paths.get(file)), StandardCharsets.UTF_8); + assertThat(yaml).isEqualTo(expectedContent); + } + } + + @Test + public void shouldGenerateYamlWithModel() throws Exception { + try (CamelContext context = new DefaultCamelContext()) { + final String yaml = RestDslGenerator.toYaml(document) + .withDtoPackageName("model") + .generate(context); + + final URI file = RestDslYamlGeneratorV3Test.class.getResource("/OpenApiV3PetstoreWithModelYaml.txt").toURI(); final String expectedContent = new String(Files.readAllBytes(Paths.get(file)), StandardCharsets.UTF_8); assertThat(yaml).isEqualTo(expectedContent); } diff --git a/tooling/openapi-rest-dsl-generator/src/test/resources/OpenApiV3PetstoreWithModelYaml.txt b/tooling/openapi-rest-dsl-generator/src/test/resources/OpenApiV3PetstoreWithModelYaml.txt new file mode 100644 index 00000000000..8c3052f2cf1 --- /dev/null +++ b/tooling/openapi-rest-dsl-generator/src/test/resources/OpenApiV3PetstoreWithModelYaml.txt @@ -0,0 +1,255 @@ +- rest: + path: "/api/v3" + put: + - id: "updatePet" + path: "/pet" + consumes: "application/json,application/xml" + type: "model.Pet" + param: + - description: "Pet object that needs to be added to the store" + name: "body" + required: true + type: "body" + to: "direct:updatePet" + - id: "updateUser" + path: "/user/{username}" + description: "This can only be done by the logged in user." + consumes: "*/*" + type: "model.User" + param: + - dataType: "string" + description: "name that need to be updated" + name: "username" + required: true + type: "path" + - description: "Updated user object" + name: "body" + required: true + type: "body" + to: "direct:updateUser" + post: + - id: "addPet" + path: "/pet" + consumes: "application/json,application/xml" + type: "model.Pet" + param: + - dataType: "boolean" + defaultValue: "false" + description: "Verbose data" + name: "verbose" + required: false + type: "query" + - description: "Pet object that needs to be added to the store" + name: "body" + required: true + type: "body" + to: "direct:addPet" + - id: "updatePetWithForm" + path: "/pet/{petId}" + consumes: "application/x-www-form-urlencoded" + param: + - dataType: "integer" + description: "ID of pet that needs to be updated" + name: "petId" + required: true + type: "path" + - dataType: "string" + description: "Updated name of the pet" + name: "name" + required: true + type: "formData" + - dataType: "string" + description: "Updated status of the pet" + name: "status" + required: true + type: "formData" + to: "direct:updatePetWithForm" + - id: "uploadFile" + path: "/pet/{petId}/uploadImage" + consumes: "multipart/form-data" + produces: "application/json" + outType: "model.ApiResponse" + param: + - dataType: "integer" + description: "ID of pet to update" + name: "petId" + required: true + type: "path" + - dataType: "string" + description: "Additional data to pass to server" + name: "additionalMetadata" + required: true + type: "formData" + - dataType: "string" + description: "file to upload" + name: "file" + required: true + type: "formData" + to: "direct:uploadFile" + - id: "placeOrder" + path: "/store/order" + consumes: "*/*" + produces: "application/xml,application/json" + type: "model.Order" + outType: "model.Order" + param: + - description: "order placed for purchasing the pet" + name: "body" + required: true + type: "body" + to: "direct:placeOrder" + - id: "createUser" + path: "/user" + description: "This can only be done by the logged in user." + consumes: "*/*" + type: "model.User" + param: + - description: "Created user object" + name: "body" + required: true + type: "body" + to: "direct:createUser" + - id: "createUsersWithArrayInput" + path: "/user/createWithArray" + consumes: "*/*" + type: "model.User[]" + param: + - description: "List of user object" + name: "body" + required: true + type: "body" + to: "direct:createUsersWithArrayInput" + - id: "createUsersWithListInput" + path: "/user/createWithList" + consumes: "*/*" + type: "model.User[]" + param: + - description: "List of user object" + name: "body" + required: true + type: "body" + to: "direct:createUsersWithListInput" + get: + - id: "findPetsByStatus" + path: "/pet/findByStatus" + description: "Multiple status values can be provided with comma separated strings" + produces: "application/xml,application/json" + outType: "model.Pet[]" + param: + - arrayType: "string" + collectionFormat: "multi" + dataType: "array" + description: "Status values that need to be considered for filter" + name: "status" + required: true + type: "query" + to: "direct:findPetsByStatus" + - id: "findPetsByTags" + path: "/pet/findByTags" + description: "Muliple tags can be provided with comma separated strings. Use\ + \ tag1, tag2, tag3 for testing." + produces: "application/xml,application/json" + outType: "model.Pet[]" + param: + - arrayType: "string" + collectionFormat: "multi" + dataType: "array" + description: "Tags to filter by" + name: "tags" + required: true + type: "query" + to: "direct:findPetsByTags" + - id: "getPetById" + path: "/pet/{petId}" + description: "Returns a single pet" + produces: "application/xml,application/json" + outType: "model.Pet" + param: + - dataType: "integer" + description: "ID of pet to return" + name: "petId" + required: true + type: "path" + to: "direct:getPetById" + - id: "getInventory" + path: "/store/inventory" + description: "Returns a map of status codes to quantities" + produces: "application/json" + to: "direct:getInventory" + - id: "getOrderById" + path: "/store/order/{orderId}" + description: "For valid response try integer IDs with value >= 1 and <= 10.\ + \ Other values will generated exceptions" + produces: "application/xml,application/json" + outType: "model.Order" + param: + - dataType: "integer" + description: "ID of pet that needs to be fetched" + name: "orderId" + required: true + type: "path" + to: "direct:getOrderById" + - id: "loginUser" + path: "/user/login" + produces: "application/xml,application/json" + param: + - dataType: "string" + description: "The user name for login" + name: "username" + required: true + type: "query" + - dataType: "string" + description: "The password for login in clear text" + name: "password" + required: true + type: "query" + to: "direct:loginUser" + - id: "logoutUser" + path: "/user/logout" + to: "direct:logoutUser" + - id: "getUserByName" + path: "/user/{username}" + produces: "application/xml,application/json" + outType: "model.User" + param: + - dataType: "string" + description: "The name that needs to be fetched. Use user1 for testing. " + name: "username" + required: true + type: "path" + to: "direct:getUserByName" + delete: + - id: "deletePet" + path: "/pet/{petId}" + param: + - dataType: "string" + name: "api_key" + required: false + type: "header" + - dataType: "integer" + description: "Pet id to delete" + name: "petId" + required: true + type: "path" + to: "direct:deletePet" + - id: "deleteOrder" + path: "/store/order/{orderId}" + description: "For valid response try integer IDs with positive integer value.\ + \ Negative or non-integer values will generate API errors" + param: + - dataType: "integer" + description: "ID of the order that needs to be deleted" + name: "orderId" + required: true + type: "path" + to: "direct:deleteOrder" + - id: "deleteUser" + path: "/user/{username}" + description: "This can only be done by the logged in user." + param: + - dataType: "string" + description: "The name that needs to be deleted" + name: "username" + required: true + type: "path" + to: "direct:deleteUser"
