From 05b6bb2717047c16703eac873024bfbaf90c3efc Mon Sep 17 00:00:00 2001 From: Dennis Melzer Date: Fri, 2 Aug 2024 08:41:54 +0200 Subject: [PATCH] Allow Customization of Error Responses --- .../openapi/AspectModelOpenApiGenerator.java | 2 + .../OpenApiSchemaGenerationConfig.java | 26 ++++++------ .../AspectModelOpenApiGeneratorTest.java | 40 ++++++++++++++++--- .../openapi/open-api-error-template.yaml | 10 +++++ 4 files changed, 58 insertions(+), 20 deletions(-) create mode 100644 core/esmf-aspect-model-document-generators/src/test/resources/openapi/open-api-error-template.yaml diff --git a/core/esmf-aspect-model-document-generators/src/main/java/org/eclipse/esmf/aspectmodel/generator/openapi/AspectModelOpenApiGenerator.java b/core/esmf-aspect-model-document-generators/src/main/java/org/eclipse/esmf/aspectmodel/generator/openapi/AspectModelOpenApiGenerator.java index cf5c9daf2..d2f512930 100644 --- a/core/esmf-aspect-model-document-generators/src/main/java/org/eclipse/esmf/aspectmodel/generator/openapi/AspectModelOpenApiGenerator.java +++ b/core/esmf-aspect-model-document-generators/src/main/java/org/eclipse/esmf/aspectmodel/generator/openapi/AspectModelOpenApiGenerator.java @@ -617,6 +617,8 @@ private static ObjectNode mergeObjectNode( final ObjectNode node, final ObjectNo node.set( key, mergeObjectNode( (ObjectNode) resultValue, (ObjectNode) value ) ); } else if ( resultValue.isArray() && value.isArray() ) { node.set( key, mergeArrayNode( (ArrayNode) resultValue, (ArrayNode) value ) ); + } else { + node.set( key, value ); } } else { node.set( key, value ); diff --git a/core/esmf-aspect-model-document-generators/src/main/java/org/eclipse/esmf/aspectmodel/generator/openapi/OpenApiSchemaGenerationConfig.java b/core/esmf-aspect-model-document-generators/src/main/java/org/eclipse/esmf/aspectmodel/generator/openapi/OpenApiSchemaGenerationConfig.java index 3df6774f1..39863277b 100644 --- a/core/esmf-aspect-model-document-generators/src/main/java/org/eclipse/esmf/aspectmodel/generator/openapi/OpenApiSchemaGenerationConfig.java +++ b/core/esmf-aspect-model-document-generators/src/main/java/org/eclipse/esmf/aspectmodel/generator/openapi/OpenApiSchemaGenerationConfig.java @@ -16,7 +16,6 @@ import static org.eclipse.esmf.aspectmodel.generator.openapi.AspectModelOpenApiGenerator.ObjectNodeExtension.getter; import java.util.Locale; -import java.util.Optional; import org.eclipse.esmf.aspectmodel.generator.GenerationConfig; @@ -67,21 +66,20 @@ public record OpenApiSchemaGenerationConfig( } public ObjectNode queriesTemplate() { - return Optional.ofNullable( template ) - .map( getter( "paths" ) ) - .map( getter( QUERIES_TEMPLATE_PATH ) ) - .orElse( null ); + if ( template == null ) { + return null; + } + + final ObjectNode objectNode = getter( "paths" ).apply( template ); + return getter( QUERIES_TEMPLATE_PATH ).apply( objectNode ); } public ObjectNode documentTemplate() { - return Optional.ofNullable( template ) - .map( ObjectNode::deepCopy ) - .map( doc -> { - Optional.of( doc ).map( getter( "paths" ) ).ifPresent( - paths -> paths.remove( QUERIES_TEMPLATE_PATH ) - ); - return doc; - } ) - .orElse( null ); + if ( template == null ) { + return null; + } + final ObjectNode objectNode = template.deepCopy(); + getter( "paths" ).apply( objectNode ).remove( QUERIES_TEMPLATE_PATH ); + return objectNode; } } diff --git a/core/esmf-aspect-model-document-generators/src/test/java/org/eclipse/esmf/aspectmodel/generator/openapi/AspectModelOpenApiGeneratorTest.java b/core/esmf-aspect-model-document-generators/src/test/java/org/eclipse/esmf/aspectmodel/generator/openapi/AspectModelOpenApiGeneratorTest.java index c898731d9..45f945434 100644 --- a/core/esmf-aspect-model-document-generators/src/test/java/org/eclipse/esmf/aspectmodel/generator/openapi/AspectModelOpenApiGeneratorTest.java +++ b/core/esmf-aspect-model-document-generators/src/test/java/org/eclipse/esmf/aspectmodel/generator/openapi/AspectModelOpenApiGeneratorTest.java @@ -254,6 +254,28 @@ void testValidParameter() throws IOException { } ); } + @Test + void testValidTemplate() throws IOException { + final Aspect aspect = TestResources.load( TestAspect.ASPECT_WITHOUT_SEE_ATTRIBUTE ).aspect(); + final OpenApiSchemaGenerationConfig config = OpenApiSchemaGenerationConfigBuilder.builder() + .useSemanticVersion( true ) + .baseUrl( TEST_BASE_URL ) + .resourcePath( TEST_RESOURCE_PATH ) + .template( getTemplateParameter() ) + .build(); + final JsonNode json = apiJsonGenerator.apply( aspect, config ).getContent(); + final SwaggerParseResult result = new OpenAPIParser().readContents( json.toString(), null, null ); + assertThat( result.getMessages() ).isEmpty(); + + final OpenAPI openApi = result.getOpenAPI(); + assertThat( openApi.getPaths().values().stream().findFirst().get().getGet().getResponses().get( "400" ).get$ref() ) + .isEqualTo( "./core-api.yaml#/components/responses/ClientError" ); + assertThat( openApi.getPaths().values().stream().findFirst().get().getGet().getResponses().get( "401" ).get$ref() ) + .isEqualTo( "./core-api.yaml#/components/responses/Unauthorized" ); + assertThat( openApi.getPaths().values().stream().findFirst().get().getGet().getResponses().get( "403" ).get$ref() ) + .isEqualTo( "./core-api.yaml#/components/responses/Forbidden" ); + } + @Test void testInValidParameterName() throws IOException { final ListAppender logAppender = new ListAppender<>(); @@ -495,11 +517,11 @@ void testAspectWithOperationWithSeeAttribute() { final SwaggerParseResult result = new OpenAPIParser().readContents( json.toString(), null, null ); final OpenAPI openApi = result.getOpenAPI(); assertThat( - ((Schema) openApi.getComponents().getSchemas().get( "testOperation" ).getAllOf() - .get( 1 )).getProperties() ).doesNotContainKey( + ( (Schema) openApi.getComponents().getSchemas().get( "testOperation" ).getAllOf() + .get( 1 ) ).getProperties() ).doesNotContainKey( "params" ); - assertThat( ((Schema) openApi.getComponents().getSchemas().get( "testOperationTwo" ).getAllOf() - .get( 1 )).getProperties() ).doesNotContainKey( "params" ); + assertThat( ( (Schema) openApi.getComponents().getSchemas().get( "testOperationTwo" ).getAllOf() + .get( 1 ) ).getProperties() ).doesNotContainKey( "params" ); } @Test @@ -635,8 +657,8 @@ void testAspectWithCommentForSeeAttributes() { assertThat( openApi.getSpecVersion() ).isEqualTo( SpecVersion.V31 ); assertThat( openApi.getComponents().getSchemas().get( "AspectWithCollection" ).get$comment() ).isEqualTo( "See: http://example.com/" ); - assertThat( ((Schema) openApi.getComponents().getSchemas().get( "AspectWithCollection" ).getProperties() - .get( "testProperty" )).get$comment() ) + assertThat( ( (Schema) openApi.getComponents().getSchemas().get( "AspectWithCollection" ).getProperties() + .get( "testProperty" ) ).get$comment() ) .isEqualTo( "See: http://example.com/, http://example.com/me" ); assertThat( openApi.getComponents().getSchemas().get( "TestCollection" ).get$comment() ) .isEqualTo( "See: http://example.com/" ); @@ -766,4 +788,10 @@ private ObjectNode getTestParameter() throws IOException { final String inputString = IOUtils.toString( inputStream, StandardCharsets.UTF_8 ); return (ObjectNode) OBJECT_MAPPER.readTree( inputString ); } + + private ObjectNode getTemplateParameter() throws IOException { + final InputStream inputStream = getClass().getResourceAsStream( "/openapi/open-api-error-template.yaml" ); + final String inputString = IOUtils.toString( inputStream, StandardCharsets.UTF_8 ); + return (ObjectNode) new YAMLMapper().readTree( inputString ); + } } diff --git a/core/esmf-aspect-model-document-generators/src/test/resources/openapi/open-api-error-template.yaml b/core/esmf-aspect-model-document-generators/src/test/resources/openapi/open-api-error-template.yaml new file mode 100644 index 000000000..e1f91e666 --- /dev/null +++ b/core/esmf-aspect-model-document-generators/src/test/resources/openapi/open-api-error-template.yaml @@ -0,0 +1,10 @@ +paths: + __DEFAULT_QUERIES_TEMPLATE__: + get: + responses: + '400': + $ref: "core-api.yaml#/components/responses/ClientError" + '401': + $ref: "core-api.yaml#/components/responses/Unauthorized" + '403': + $ref: "core-api.yaml#/components/responses/Forbidden" \ No newline at end of file