From 5e838816d663c17694b219f9a1c2c4b248932806 Mon Sep 17 00:00:00 2001 From: Yauhenikapl Date: Fri, 10 May 2024 15:16:05 +0300 Subject: [PATCH 1/8] Create PUT/PATCH/POST methods for OpenApi Changes: - update OpenAPI generator; - add new flag for OpenAPI generation to commands; - update tests. --- .../openapi/AspectModelOpenApiGenerator.java | 32 +++++++++++++++++-- .../OpenApiSchemaGenerationConfig.java | 3 +- .../AspectModelOpenApiGeneratorTest.java | 8 +++-- .../aspect/to/AspectToOpenapiCommand.java | 5 +++ 4 files changed, 42 insertions(+), 6 deletions(-) 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 2e8bc5588..3f148e8aa 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 @@ -63,13 +63,15 @@ public class AspectModelOpenApiGenerator private static final String FIELD_DESCRIPTION = "description"; private static final String FIELD_FILTER = "Filter"; private static final String FIELD_GET = "get"; + private static final String FIELD_POST = "post"; + private static final String FIELD_PUT = "put"; + private static final String FIELD_PATCH = "patch"; private static final String FIELD_OBJECT = "object"; private static final String FIELD_OPERATION = "Operation"; private static final String FIELD_OPERATION_ID = "operationId"; private static final String FIELD_OPERATION_RESPONSE = "OperationResponse"; protected static final String FIELD_PAGING_SCHEMA = "PagingSchema"; private static final String FIELD_PARAMETERS = "parameters"; - private static final String FIELD_POST = "post"; private static final String FIELD_PROPERTIES = "properties"; private static final String FIELD_RPC = "JsonRpc"; private static final String FIELD_REQUEST_BODIES = "requestBodies"; @@ -506,9 +508,17 @@ private ObjectNode getPathsNode( final Aspect aspect, final OpenApiSchemaGenerat pathNode.set( FIELD_GET, getRequestEndpointsRead( aspect, propertiesNode, config.resourcePath() ) ); + if ( config.includeCrud() ) { + pathNode.set( FIELD_POST, getRequestEndpointsCreate( aspect, propertiesNode, config.resourcePath() ) ); + pathNode.set( FIELD_PUT, getRequestEndpointsUpdate( aspect, propertiesNode, config.resourcePath(), true ) ); + pathNode.set( FIELD_PATCH, getRequestEndpointsUpdate( aspect, propertiesNode, config.resourcePath(), false ) ); + } + if ( config.includeQueryApi() ) { - pathNode.set( FIELD_POST, + final ObjectNode includeQueryPathNode = FACTORY.objectNode(); + includeQueryPathNode.set( FIELD_POST, getRequestEndpointFilter( aspect, propertiesNode, config.baseUrl(), apiVersion, config.resourcePath() ) ); + endpointPathsNode.set( config.baseUrl() + String.format( QUERY_SERVER_PATH, apiVersion ), includeQueryPathNode ); } final Optional operationsNode = getRequestEndpointOperations( aspect, propertiesNode, config.baseUrl(), apiVersion, @@ -621,6 +631,24 @@ private ObjectNode getRequestEndpointsRead( final Aspect aspect, final ObjectNod return objectNode; } + private ObjectNode getRequestEndpointsCreate( final Aspect aspect, final ObjectNode parameterNode, final String resourcePath ) { + final ObjectNode objectNode = FACTORY.objectNode(); + objectNode.set( "tags", FACTORY.arrayNode().add( aspect.getName() ) ); + objectNode.put( FIELD_OPERATION_ID, FIELD_POST + aspect.getName() ); + objectNode.set( FIELD_PARAMETERS, getRequiredParameters( parameterNode, isEmpty( resourcePath ) ) ); + objectNode.set( FIELD_RESPONSES, getResponsesForGet( aspect ) ); + return objectNode; + } + + private ObjectNode getRequestEndpointsUpdate( final Aspect aspect, final ObjectNode parameterNode, final String resourcePath, final boolean isPut ) { + final ObjectNode objectNode = FACTORY.objectNode(); + objectNode.set( "tags", FACTORY.arrayNode().add( aspect.getName() ) ); + objectNode.put( FIELD_OPERATION_ID, isPut ? FIELD_PUT : FIELD_PATCH + aspect.getName() ); + objectNode.set( FIELD_PARAMETERS, getRequiredParameters( parameterNode, isEmpty( resourcePath ) ) ); + objectNode.set( FIELD_RESPONSES, getResponsesForGet( aspect ) ); + return objectNode; + } + private ObjectNode getResponsesForGet( final Aspect aspect ) { final ObjectNode responses = FACTORY.objectNode(); responses.set( "200", getSuccessfulNode( aspect ) ); 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 35fa48a11..23b74bd80 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 @@ -44,7 +44,8 @@ public record OpenApiSchemaGenerationConfig( String resourcePath, ObjectNode properties, PagingOption pagingOption, - boolean includeQueryApi + boolean includeQueryApi, + boolean includeCrud ) implements GenerationConfig { public OpenApiSchemaGenerationConfig { if ( locale == null ) { 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 dfbff4569..30f478895 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 @@ -168,7 +168,7 @@ public void testIncludeQueryApiWithSemanticVersion( final KnownVersion metaModel final JsonNode json = apiJsonGenerator.apply( aspect, config ).getContent(); final SwaggerParseResult result = new OpenAPIParser().readContents( json.toString(), null, null ); final OpenAPI openApi = result.getOpenAPI(); - assertThat( openApi.getPaths().get( "/" + TEST_RESOURCE_PATH ).getPost().getServers().get( 0 ).getUrl() ) + assertThat( openApi.getPaths().get( "https://test-aspect.example.com/query-api/v1.0.0" ).getPost().getServers().get( 0 ).getUrl() ) .isEqualTo( "https://test-aspect.example.com/query-api/v1.0.0" ); } @@ -185,7 +185,8 @@ public void testDefaultResourcePath( final KnownVersion metaModelVersion ) { final SwaggerParseResult result = new OpenAPIParser().readContents( json.toString(), null, null ); final OpenAPI openApi = result.getOpenAPI(); - assertThat( openApi.getPaths().keySet() ).allMatch( path -> path.equals( "/{tenant-id}/aspect-without-see-attribute" ) ); + assertThat( openApi.getPaths().keySet() ).anyMatch( path -> path.equals( "/{tenant-id}/aspect-without-see-attribute" ) ); + assertThat( openApi.getPaths().keySet() ).anyMatch( path -> path.equals( "https://test-aspect.example.com/query-api/v1.0.0" ) ); } @ParameterizedTest @@ -216,7 +217,8 @@ public void testWithValidResourcePath( final KnownVersion metaModelVersion ) { final SwaggerParseResult result = new OpenAPIParser().readContents( json.toString(), null, null ); final OpenAPI openApi = result.getOpenAPI(); - assertThat( openApi.getPaths().keySet() ).allMatch( path -> path.equals( "/" + TEST_RESOURCE_PATH ) ); + assertThat( openApi.getPaths().keySet() ).anyMatch( path -> path.equals( "/" + TEST_RESOURCE_PATH ) ); + assertThat( openApi.getPaths().keySet() ).anyMatch( path -> path.equals( "https://test-aspect.example.com/query-api/v1.0.0" ) ); } @ParameterizedTest diff --git a/tools/samm-cli/src/main/java/org/eclipse/esmf/aspect/to/AspectToOpenapiCommand.java b/tools/samm-cli/src/main/java/org/eclipse/esmf/aspect/to/AspectToOpenapiCommand.java index 978d865e9..5d9385018 100644 --- a/tools/samm-cli/src/main/java/org/eclipse/esmf/aspect/to/AspectToOpenapiCommand.java +++ b/tools/samm-cli/src/main/java/org/eclipse/esmf/aspect/to/AspectToOpenapiCommand.java @@ -90,6 +90,10 @@ public class AspectToOpenapiCommand extends AbstractCommand { description = "Include the path for the Query Aspect API Endpoint in the OpenAPI specification." ) private boolean includeQueryApi = false; + @CommandLine.Option( names = { "--include-crud", "-cr" }, + description = "Include all CRUD operations in the OpenAPI specification." ) + private boolean includeFullCrud = false; + @CommandLine.Option( names = { "--paging-none", "-pn" }, description = "Exclude paging information for the Aspect API Endpoint in the OpenAPI specification." ) private boolean excludePaging = false; @@ -138,6 +142,7 @@ public void run() { .resourcePath( aspectResourcePath ) .properties( readAspectParameterFile() ) .includeQueryApi( includeQueryApi ) + .includeCrud( includeFullCrud ) .pagingOption( getPaging() ) .locale( locale ) .generateCommentForSeeAttributes( generateCommentForSeeAttributes ) From e39ac100924178b7d56e13c15088626668d9279b Mon Sep 17 00:00:00 2001 From: Yauhenikapl Date: Fri, 10 May 2024 15:24:21 +0300 Subject: [PATCH 2/8] Fix styles and linter errors --- .../openapi/AspectModelOpenApiGenerator.java | 13 +-- .../AspectModelOpenApiGeneratorTest.java | 94 +++++++++---------- 2 files changed, 54 insertions(+), 53 deletions(-) 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 3f148e8aa..f6e87eb5d 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 @@ -120,9 +120,9 @@ public OpenApiSchemaArtifact apply( final Aspect aspect, final OpenApiSchemaGene final ObjectNode rootNode = getRootJsonNode( config.generateCommentForSeeAttributes() ); final String apiVersion = getApiVersion( aspect, config.useSemanticVersion() ); - ( (ObjectNode) rootNode.get( "info" ) ).put( "title", aspect.getPreferredName( config.locale() ) ); - ( (ObjectNode) rootNode.get( "info" ) ).put( "version", apiVersion ); - ( (ObjectNode) rootNode.get( "info" ) ).put( AspectModelJsonSchemaVisitor.SAMM_EXTENSION, + ((ObjectNode) rootNode.get( "info" )).put( "title", aspect.getPreferredName( config.locale() ) ); + ((ObjectNode) rootNode.get( "info" )).put( "version", apiVersion ); + ((ObjectNode) rootNode.get( "info" )).put( AspectModelJsonSchemaVisitor.SAMM_EXTENSION, aspect.getAspectModelUrn().map( Object::toString ).orElse( "" ) ); setServers( rootNode, config.baseUrl(), apiVersion, READ_SERVER_PATH ); final boolean includePaging = includePaging( aspect, config.pagingOption() ); @@ -334,7 +334,7 @@ private String getApiVersion( final Aspect aspect, final boolean useSemanticVers private void setResponseBodies( final Aspect aspect, final ObjectNode jsonNode, final boolean includePaging ) { final ObjectNode componentsResponseNode = (ObjectNode) jsonNode.get( FIELD_COMPONENTS ).get( FIELD_RESPONSES ); final ObjectNode referenceNode = FACTORY.objectNode() - .put( REF, COMPONENTS_SCHEMAS + ( includePaging ? FIELD_PAGING_SCHEMA : aspect.getName() ) ); + .put( REF, COMPONENTS_SCHEMAS + (includePaging ? FIELD_PAGING_SCHEMA : aspect.getName()) ); final ObjectNode contentNode = getApplicationNode( referenceNode ); componentsResponseNode.set( aspect.getName(), contentNode ); contentNode.put( FIELD_DESCRIPTION, "The request was successful." ); @@ -518,7 +518,7 @@ private ObjectNode getPathsNode( final Aspect aspect, final OpenApiSchemaGenerat final ObjectNode includeQueryPathNode = FACTORY.objectNode(); includeQueryPathNode.set( FIELD_POST, getRequestEndpointFilter( aspect, propertiesNode, config.baseUrl(), apiVersion, config.resourcePath() ) ); - endpointPathsNode.set( config.baseUrl() + String.format( QUERY_SERVER_PATH, apiVersion ), includeQueryPathNode ); + endpointPathsNode.set( config.baseUrl() + String.format( QUERY_SERVER_PATH, apiVersion ), includeQueryPathNode ); } final Optional operationsNode = getRequestEndpointOperations( aspect, propertiesNode, config.baseUrl(), apiVersion, @@ -640,7 +640,8 @@ private ObjectNode getRequestEndpointsCreate( final Aspect aspect, final ObjectN return objectNode; } - private ObjectNode getRequestEndpointsUpdate( final Aspect aspect, final ObjectNode parameterNode, final String resourcePath, final boolean isPut ) { + private ObjectNode getRequestEndpointsUpdate( final Aspect aspect, final ObjectNode parameterNode, final String resourcePath, + final boolean isPut ) { final ObjectNode objectNode = FACTORY.objectNode(); objectNode.set( "tags", FACTORY.arrayNode().add( aspect.getName() ) ); objectNode.put( FIELD_OPERATION_ID, isPut ? FIELD_PUT : FIELD_PATCH + aspect.getName() ); 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 30f478895..d0ce5234c 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 @@ -87,7 +87,7 @@ public class AspectModelOpenApiGeneratorTest extends MetaModelVersions { @ParameterizedTest @EnumSource( value = TestAspect.class ) - public void testGeneration( final TestAspect testAspect ) throws IOException { + void testGeneration( final TestAspect testAspect ) throws IOException { final Aspect aspect = loadAspect( testAspect, KnownVersion.getLatest() ); final OpenApiSchemaGenerationConfig config = OpenApiSchemaGenerationConfigBuilder.builder() .useSemanticVersion( false ) @@ -108,7 +108,7 @@ public void testGeneration( final TestAspect testAspect ) throws IOException { for ( final Iterator> it = json.get( "components" ).get( "schemas" ).fields(); it.hasNext(); ) { final Map.Entry schema = it.next(); final Path keyForSchemaName = Path.of( schema.getKey() + ".json" ); - assertThat( jsonMap.keySet() ).contains( keyForSchemaName ); + assertThat( jsonMap ).containsKey( keyForSchemaName ); } final JsonNode rootDocument = jsonMap.get( Path.of( aspect.getName() + ".oai.json" ) ); assertThat( Streams.stream( rootDocument.get( "components" ).fieldNames() ).toList() ).doesNotContain( "schemas" ); @@ -119,7 +119,7 @@ public void testGeneration( final TestAspect testAspect ) throws IOException { for ( final Iterator> it = json.get( "components" ).get( "schemas" ).fields(); it.hasNext(); ) { final Map.Entry schema = it.next(); final Path keyForSchemaName = Path.of( schema.getKey() + ".yaml" ); - assertThat( yamlMap.keySet() ).contains( keyForSchemaName ); + assertThat( yamlMap ).containsKey( keyForSchemaName ); } } @@ -136,7 +136,7 @@ private void showJson( final JsonNode node ) { @ParameterizedTest @MethodSource( value = "allVersions" ) - public void testUseSemanticVersion( final KnownVersion metaModelVersion ) { + void testUseSemanticVersion( final KnownVersion metaModelVersion ) { final Aspect aspect = loadAspect( TestAspect.ASPECT_WITH_PROPERTY, metaModelVersion ); final OpenApiSchemaGenerationConfig config = OpenApiSchemaGenerationConfigBuilder.builder() .useSemanticVersion( true ) @@ -157,7 +157,7 @@ public void testUseSemanticVersion( final KnownVersion metaModelVersion ) { @ParameterizedTest @MethodSource( value = "allVersions" ) - public void testIncludeQueryApiWithSemanticVersion( final KnownVersion metaModelVersion ) { + void testIncludeQueryApiWithSemanticVersion( final KnownVersion metaModelVersion ) { final Aspect aspect = loadAspect( TestAspect.ASPECT, metaModelVersion ); final OpenApiSchemaGenerationConfig config = OpenApiSchemaGenerationConfigBuilder.builder() .useSemanticVersion( true ) @@ -174,7 +174,7 @@ public void testIncludeQueryApiWithSemanticVersion( final KnownVersion metaModel @ParameterizedTest @MethodSource( value = "allVersions" ) - public void testDefaultResourcePath( final KnownVersion metaModelVersion ) { + void testDefaultResourcePath( final KnownVersion metaModelVersion ) { final Aspect aspect = loadAspect( TestAspect.ASPECT_WITHOUT_SEE_ATTRIBUTE, metaModelVersion ); final OpenApiSchemaGenerationConfig config = OpenApiSchemaGenerationConfigBuilder.builder() .useSemanticVersion( true ) @@ -191,7 +191,7 @@ public void testDefaultResourcePath( final KnownVersion metaModelVersion ) { @ParameterizedTest @MethodSource( value = "allVersions" ) - public void testInvalidResourcePath( final KnownVersion metaModelVersion ) { + void testInvalidResourcePath( final KnownVersion metaModelVersion ) { final Aspect aspect = loadAspect( TestAspect.ASPECT_WITHOUT_SEE_ATTRIBUTE, metaModelVersion ); final OpenApiSchemaGenerationConfig config = OpenApiSchemaGenerationConfigBuilder.builder() .useSemanticVersion( true ) @@ -205,7 +205,7 @@ public void testInvalidResourcePath( final KnownVersion metaModelVersion ) { @ParameterizedTest @MethodSource( value = "allVersions" ) - public void testWithValidResourcePath( final KnownVersion metaModelVersion ) { + void testWithValidResourcePath( final KnownVersion metaModelVersion ) { final Aspect aspect = loadAspect( TestAspect.ASPECT_WITHOUT_SEE_ATTRIBUTE, metaModelVersion ); final OpenApiSchemaGenerationConfig config = OpenApiSchemaGenerationConfigBuilder.builder() .useSemanticVersion( true ) @@ -223,7 +223,7 @@ public void testWithValidResourcePath( final KnownVersion metaModelVersion ) { @ParameterizedTest @MethodSource( value = "allVersions" ) - public void testInvalidJsonParameter( final KnownVersion metaModelVersion ) { + void testInvalidJsonParameter( final KnownVersion metaModelVersion ) { final Aspect aspect = loadAspect( TestAspect.ASPECT_WITHOUT_SEE_ATTRIBUTE, metaModelVersion ); final OpenApiSchemaGenerationConfig config = OpenApiSchemaGenerationConfigBuilder.builder() .useSemanticVersion( true ) @@ -238,7 +238,7 @@ public void testInvalidJsonParameter( final KnownVersion metaModelVersion ) { @ParameterizedTest @MethodSource( value = "allVersions" ) - public void testValidParameter( final KnownVersion metaModelVersion ) throws IOException { + void testValidParameter( final KnownVersion metaModelVersion ) throws IOException { final Aspect aspect = loadAspect( TestAspect.ASPECT_WITHOUT_SEE_ATTRIBUTE, metaModelVersion ); final OpenApiSchemaGenerationConfig config = OpenApiSchemaGenerationConfigBuilder.builder() .useSemanticVersion( true ) @@ -248,11 +248,11 @@ public void testValidParameter( final KnownVersion metaModelVersion ) throws IOE .build(); final JsonNode json = apiJsonGenerator.apply( aspect, config ).getContent(); final SwaggerParseResult result = new OpenAPIParser().readContents( json.toString(), null, null ); - assertThat( result.getMessages().size() ).isZero(); + assertThat( result.getMessages() ).isEmpty(); final OpenAPI openApi = result.getOpenAPI(); assertThat( openApi.getPaths() ).hasSize( 1 ); - assertThat( openApi.getPaths().keySet() ).contains( "/my-test-aspect/{test-Id}" ); + assertThat( openApi.getPaths() ).containsKey( "/my-test-aspect/{test-Id}" ); openApi.getPaths().forEach( ( key, value ) -> { final List params = value.getGet().getParameters().stream().map( Parameter::getName ) .collect( Collectors.toList() ); @@ -263,7 +263,7 @@ public void testValidParameter( final KnownVersion metaModelVersion ) throws IOE @ParameterizedTest @MethodSource( value = "allVersions" ) - public void testInValidParameterName( final KnownVersion metaModelVersion ) throws IOException { + void testInValidParameterName( final KnownVersion metaModelVersion ) throws IOException { final ListAppender logAppender = new ListAppender<>(); final Logger logger = (Logger) LoggerFactory.getLogger( AspectModelOpenApiGenerator.class ); logger.addAppender( logAppender ); @@ -288,7 +288,7 @@ public void testInValidParameterName( final KnownVersion metaModelVersion ) thro @ParameterizedTest @MethodSource( value = "allVersions" ) - public void testYamlGenerator( final KnownVersion metaModelVersion ) throws IOException { + void testYamlGenerator( final KnownVersion metaModelVersion ) throws IOException { final Aspect aspect = loadAspect( TestAspect.ASPECT_WITHOUT_SEE_ATTRIBUTE, metaModelVersion ); final YAMLMapper yamlMapper = new YAMLMapper().enable( YAMLGenerator.Feature.MINIMIZE_QUOTES ); final OpenApiSchemaGenerationConfig yamlConfig = OpenApiSchemaGenerationConfigBuilder.builder() @@ -312,7 +312,7 @@ public void testYamlGenerator( final KnownVersion metaModelVersion ) throws IOEx @ParameterizedTest @MethodSource( value = "allVersions" ) - public void testHasQuerySchema( final KnownVersion metaModelVersion ) { + void testHasQuerySchema( final KnownVersion metaModelVersion ) { final Aspect aspect = loadAspect( TestAspect.ASPECT_WITHOUT_SEE_ATTRIBUTE, metaModelVersion ); final OpenApiSchemaGenerationConfig config = OpenApiSchemaGenerationConfigBuilder.builder() .useSemanticVersion( true ) @@ -323,13 +323,13 @@ public void testHasQuerySchema( final KnownVersion metaModelVersion ) { final SwaggerParseResult result = new OpenAPIParser().readContents( json.toString(), null, null ); final OpenAPI openApi = result.getOpenAPI(); - assertThat( openApi.getComponents().getSchemas().keySet() ).contains( "Filter" ); - assertThat( openApi.getComponents().getRequestBodies().keySet() ).contains( "Filter" ); + assertThat( openApi.getComponents().getSchemas() ).containsKey( "Filter" ); + assertThat( openApi.getComponents().getRequestBodies() ).containsKey( "Filter" ); } @ParameterizedTest @MethodSource( value = "allVersions" ) - public void testHasNoQuerySchema( final KnownVersion metaModelVersion ) { + void testHasNoQuerySchema( final KnownVersion metaModelVersion ) { final Aspect aspect = loadAspect( TestAspect.ASPECT_WITHOUT_SEE_ATTRIBUTE, metaModelVersion ); final OpenApiSchemaGenerationConfig config = OpenApiSchemaGenerationConfigBuilder.builder() .useSemanticVersion( true ) @@ -345,7 +345,7 @@ public void testHasNoQuerySchema( final KnownVersion metaModelVersion ) { @ParameterizedTest @MethodSource( value = "allVersions" ) - public void testHasPagingWithChosenPaging( final KnownVersion metaModelVersion ) { + void testHasPagingWithChosenPaging( final KnownVersion metaModelVersion ) { final Aspect aspect = loadAspect( TestAspect.ASPECT_WITH_COLLECTION, metaModelVersion ); final OpenApiSchemaGenerationConfig config = OpenApiSchemaGenerationConfigBuilder.builder() .useSemanticVersion( true ) @@ -355,7 +355,7 @@ public void testHasPagingWithChosenPaging( final KnownVersion metaModelVersion ) final JsonNode json = apiJsonGenerator.apply( aspect, config ).getContent(); final SwaggerParseResult result = new OpenAPIParser().readContents( json.toString(), null, null ); final OpenAPI openApi = result.getOpenAPI(); - assertThat( openApi.getPaths().keySet() ).contains( "/{tenant-id}/aspect-with-collection" ); + assertThat( openApi.getPaths() ).containsKey( "/{tenant-id}/aspect-with-collection" ); assertThat( openApi.getPaths().values().stream().findFirst().get().getGet().getParameters().get( 0 ).getName() ).isEqualTo( "tenant-id" ); assertThat( openApi.getPaths().values().stream().findFirst().get().getGet().getParameters().get( 1 ).getName() ).isEqualTo( "start" ); @@ -371,7 +371,7 @@ public void testHasPagingWithChosenPaging( final KnownVersion metaModelVersion ) @ParameterizedTest @MethodSource( value = "allVersions" ) - public void testHasPagingWithoutChosenPaging( final KnownVersion metaModelVersion ) { + void testHasPagingWithoutChosenPaging( final KnownVersion metaModelVersion ) { final Aspect aspect = loadAspect( TestAspect.ASPECT_WITH_TIME_SERIES, metaModelVersion ); final OpenApiSchemaGenerationConfig config = OpenApiSchemaGenerationConfigBuilder.builder() .useSemanticVersion( true ) @@ -380,7 +380,7 @@ public void testHasPagingWithoutChosenPaging( final KnownVersion metaModelVersio final JsonNode json = apiJsonGenerator.apply( aspect, config ).getContent(); final SwaggerParseResult result = new OpenAPIParser().readContents( json.toString(), null, null ); final OpenAPI openApi = result.getOpenAPI(); - assertThat( openApi.getPaths().keySet() ).contains( "/{tenant-id}/aspect-with-time-series" ); + assertThat( openApi.getPaths() ).containsKey( "/{tenant-id}/aspect-with-time-series" ); assertThat( openApi.getPaths().values().stream().findFirst().get().getGet().getParameters().get( 0 ).getName() ).isEqualTo( "tenant-id" ); assertThat( openApi.getPaths().values().stream().findFirst().get().getGet().getParameters().get( 1 ).getName() ).isEqualTo( "since" ); @@ -394,7 +394,7 @@ public void testHasPagingWithoutChosenPaging( final KnownVersion metaModelVersio @ParameterizedTest @MethodSource( value = "allVersions" ) - public void testHasPagingWitChosenCursorBasedPaging( final KnownVersion metaModelVersion ) { + void testHasPagingWitChosenCursorBasedPaging( final KnownVersion metaModelVersion ) { final Aspect aspect = loadAspect( TestAspect.ASPECT_WITH_COLLECTION, metaModelVersion ); final OpenApiSchemaGenerationConfig config = OpenApiSchemaGenerationConfigBuilder.builder() .useSemanticVersion( true ) @@ -404,7 +404,7 @@ public void testHasPagingWitChosenCursorBasedPaging( final KnownVersion metaMode final JsonNode json = apiJsonGenerator.apply( aspect, config ).getContent(); final SwaggerParseResult result = new OpenAPIParser().readContents( json.toString(), null, null ); final OpenAPI openApi = result.getOpenAPI(); - assertThat( openApi.getPaths().keySet() ).contains( "/{tenant-id}/aspect-with-collection" ); + assertThat( openApi.getPaths() ).containsKey( "/{tenant-id}/aspect-with-collection" ); assertThat( openApi.getPaths().values().stream().findFirst().get().getGet().getParameters().get( 0 ).getName() ).isEqualTo( "tenant-id" ); assertThat( openApi.getPaths().values().stream().findFirst().get().getGet().getParameters().get( 1 ).getName() ).isEqualTo( @@ -425,7 +425,7 @@ public void testHasPagingWitChosenCursorBasedPaging( final KnownVersion metaMode @ParameterizedTest @MethodSource( value = "allVersions" ) - public void testHasPagingWithWithDefaultChosenPaging( final KnownVersion metaModelVersion ) { + void testHasPagingWithWithDefaultChosenPaging( final KnownVersion metaModelVersion ) { final Aspect aspect = loadAspect( TestAspect.ASPECT_WITH_COLLECTION, metaModelVersion ); final OpenApiSchemaGenerationConfig config = OpenApiSchemaGenerationConfigBuilder.builder() .useSemanticVersion( true ) @@ -434,7 +434,7 @@ public void testHasPagingWithWithDefaultChosenPaging( final KnownVersion metaMod final JsonNode json = apiJsonGenerator.apply( aspect, config ).getContent(); final SwaggerParseResult result = new OpenAPIParser().readContents( json.toString(), null, null ); final OpenAPI openApi = result.getOpenAPI(); - assertThat( openApi.getPaths().keySet() ).contains( "/{tenant-id}/aspect-with-collection" ); + assertThat( openApi.getPaths() ).containsKey( "/{tenant-id}/aspect-with-collection" ); assertThat( openApi.getPaths().values().stream().findFirst().get().getGet().getParameters().get( 0 ).getName() ).isEqualTo( "tenant-id" ); assertThat( openApi.getPaths().values().stream().findFirst().get().getGet().getParameters().get( 1 ).getName() ).isEqualTo( "start" ); @@ -449,7 +449,7 @@ public void testHasPagingWithWithDefaultChosenPaging( final KnownVersion metaMod @ParameterizedTest @MethodSource( value = "allVersions" ) - public void testHasNoPagination( final KnownVersion metaModelVersion ) throws ProcessingException { + void testHasNoPagination( final KnownVersion metaModelVersion ) throws ProcessingException { final Aspect aspect = loadAspect( TestAspect.ASPECT_WITH_COLLECTION, metaModelVersion ); final OpenApiSchemaGenerationConfig config = OpenApiSchemaGenerationConfigBuilder.builder() .useSemanticVersion( true ) @@ -459,7 +459,7 @@ public void testHasNoPagination( final KnownVersion metaModelVersion ) throws Pr final JsonNode json = apiJsonGenerator.apply( aspect, config ).getContent(); final SwaggerParseResult result = new OpenAPIParser().readContents( json.toString(), null, null ); final OpenAPI openApi = result.getOpenAPI(); - assertThat( openApi.getPaths().keySet() ).contains( "/{tenant-id}/aspect-with-collection" ); + assertThat( openApi.getPaths() ).containsKey( "/{tenant-id}/aspect-with-collection" ); assertThat( openApi.getPaths().values().stream().findFirst().get().getGet().getResponses() .get( "200" ).get$ref() ).isEqualTo( "#/components/responses/AspectWithCollection" ); assertThat( openApi.getComponents().getResponses().get( "AspectWithCollection" ).getContent() @@ -468,7 +468,7 @@ public void testHasNoPagination( final KnownVersion metaModelVersion ) throws Pr @ParameterizedTest @MethodSource( value = "allVersions" ) - public void testAspectWithOperation( final KnownVersion metaModelVersion ) throws ProcessingException { + void testAspectWithOperation( final KnownVersion metaModelVersion ) throws ProcessingException { final Aspect aspect = loadAspect( TestAspect.ASPECT_WITH_OPERATION, metaModelVersion ); final OpenApiSchemaGenerationConfig config = OpenApiSchemaGenerationConfigBuilder.builder() .useSemanticVersion( true ) @@ -485,13 +485,13 @@ public void testAspectWithOperation( final KnownVersion metaModelVersion ) throw assertThat( openApi.getComponents().getSchemas() ).containsKey( "testOperationResponse" ); assertThat( openApi.getComponents().getSchemas() ).containsKey( "testOperationTwo" ); assertThat( openApi.getComponents().getSchemas() ).containsKey( "testOperationTwoResponse" ); - assertThat( openApi.getComponents().getSchemas().get( "Operation" ).getOneOf().size() ).isEqualTo( 2 ); - assertThat( openApi.getComponents().getSchemas().get( "OperationResponse" ).getOneOf().size() ).isEqualTo( 2 ); + assertThat( openApi.getComponents().getSchemas().get( "Operation" ).getOneOf() ).hasSize( 2 ); + assertThat( openApi.getComponents().getSchemas().get( "OperationResponse" ).getOneOf() ).hasSize( 2 ); } @ParameterizedTest @MethodSource( value = "allVersions" ) - public void testAspectWithOperationWithSeeAttribute( final KnownVersion metaModelVersion ) { + void testAspectWithOperationWithSeeAttribute( final KnownVersion metaModelVersion ) { final Aspect aspect = loadAspect( TestAspect.ASPECT_WITH_OPERATION_WITH_SEE_ATTRIBUTE, metaModelVersion ); final OpenApiSchemaGenerationConfig config = OpenApiSchemaGenerationConfigBuilder.builder() .useSemanticVersion( true ) @@ -502,16 +502,16 @@ public void testAspectWithOperationWithSeeAttribute( final KnownVersion metaMode 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" ); } @ParameterizedTest @MethodSource( value = "allVersions" ) - public void testAspectWithCommentForSeeAttributes( final KnownVersion metaModelVersion ) { + void testAspectWithCommentForSeeAttributes( final KnownVersion metaModelVersion ) { final Aspect aspect = loadAspect( TestAspect.ASPECT_WITH_COLLECTION, metaModelVersion ); final OpenApiSchemaGenerationConfig config = OpenApiSchemaGenerationConfigBuilder.builder() .useSemanticVersion( true ) @@ -527,8 +527,8 @@ public void testAspectWithCommentForSeeAttributes( final KnownVersion metaModelV 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/" ); @@ -593,9 +593,9 @@ private void validateOpenApiSpec( final JsonNode node, final OpenAPI openApi, fi .forEach( operation -> validateSuccessfulResponse( aspect.getName(), operation ) ); } ); - assertThat( openApi.getComponents().getSchemas().keySet() ).contains( aspect.getName() ); - assertThat( openApi.getComponents().getResponses().keySet() ).contains( aspect.getName() ); - assertThat( openApi.getComponents().getRequestBodies().keySet() ).contains( aspect.getName() ); + assertThat( openApi.getComponents().getSchemas() ).containsKey( aspect.getName() ); + assertThat( openApi.getComponents().getResponses() ).containsKey( aspect.getName() ); + assertThat( openApi.getComponents().getRequestBodies() ).containsKey( aspect.getName() ); assertThat( openApi.getComponents().getSchemas().get( aspect.getName() ).getExtensions() .get( AspectModelJsonSchemaVisitor.SAMM_EXTENSION ) ).isNotNull(); assertThat( @@ -641,11 +641,11 @@ private void validateUnsupportedKeywords( final JsonNode jsonNode ) throws IOExc } private void validateOperation( final OpenAPI openApi ) { - assertThat( openApi.getComponents().getSchemas().keySet() ).contains( "JsonRpc" ); - assertThat( openApi.getComponents().getSchemas().keySet() ).contains( "Operation" ); - assertThat( openApi.getComponents().getSchemas().keySet() ).contains( "OperationResponse" ); - assertThat( openApi.getComponents().getResponses().keySet() ).contains( "OperationResponse" ); - assertThat( openApi.getComponents().getRequestBodies().keySet() ).contains( "Operation" ); + assertThat( openApi.getComponents().getSchemas() ).containsKey( "JsonRpc" ); + assertThat( openApi.getComponents().getSchemas() ).containsKey( "Operation" ); + assertThat( openApi.getComponents().getSchemas() ).containsKey( "OperationResponse" ); + assertThat( openApi.getComponents().getResponses() ).containsKey( "OperationResponse" ); + assertThat( openApi.getComponents().getRequestBodies() ).containsKey( "Operation" ); } private void validateYaml( final Aspect aspect ) { From a99b51ac691e61157cd820a0423dfd7458fc1d0f Mon Sep 17 00:00:00 2001 From: Yauhenikapl Date: Mon, 13 May 2024 16:12:38 +0300 Subject: [PATCH 3/8] Add CRUD tests of AspectModelOpenApiGenerator --- .../openapi/AspectModelOpenApiGenerator.java | 7 ++++-- .../AspectModelOpenApiGeneratorTest.java | 24 +++++++++++++++++++ 2 files changed, 29 insertions(+), 2 deletions(-) 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 f6e87eb5d..c56c0806d 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 @@ -75,6 +75,7 @@ public class AspectModelOpenApiGenerator private static final String FIELD_PROPERTIES = "properties"; private static final String FIELD_RPC = "JsonRpc"; private static final String FIELD_REQUEST_BODIES = "requestBodies"; + private static final String FIELD_REQUEST_BODY = "requestBody"; private static final String FIELD_REQUIRED = "required"; private static final String FIELD_RESPONSES = "responses"; private static final String FIELD_SCHEMA = "schema"; @@ -542,7 +543,7 @@ private Optional getRequestEndpointOperations( final Aspect aspect, objectNode.set( "tags", FACTORY.arrayNode().add( aspect.getName() ) ); objectNode.put( FIELD_OPERATION_ID, FIELD_POST + FIELD_OPERATION + aspect.getName() ); objectNode.set( FIELD_PARAMETERS, getRequiredParameters( parameterNode, isEmpty( resourcePath ) ) ); - objectNode.set( "requestBody", FACTORY.objectNode().put( REF, COMPONENTS_REQUESTS + FIELD_OPERATION ) ); + objectNode.set( FIELD_REQUEST_BODY, FACTORY.objectNode().put( REF, COMPONENTS_REQUESTS + FIELD_OPERATION ) ); final ObjectNode responseNode = FACTORY.objectNode(); objectNode.set( FIELD_RESPONSES, responseNode ); responseNode.set( "200", FACTORY.objectNode().put( REF, COMPONENTS_RESPONSES + FIELD_OPERATION_RESPONSE ) ); @@ -613,7 +614,7 @@ private ObjectNode getRequestEndpointFilter( final Aspect aspect, final ObjectNo objectNode.set( "tags", FACTORY.arrayNode().add( aspect.getName() ) ); objectNode.put( FIELD_OPERATION_ID, FIELD_POST + aspect.getName() ); objectNode.set( FIELD_PARAMETERS, getRequiredParameters( parameterNode, isEmpty( resourcePath ) ) ); - objectNode.set( "requestBody", getRequestBodyForFilter() ); + objectNode.set( FIELD_REQUEST_BODY, getRequestBodyForFilter() ); objectNode.set( FIELD_RESPONSES, getResponsesForGet( aspect ) ); return objectNode; } @@ -636,6 +637,7 @@ private ObjectNode getRequestEndpointsCreate( final Aspect aspect, final ObjectN objectNode.set( "tags", FACTORY.arrayNode().add( aspect.getName() ) ); objectNode.put( FIELD_OPERATION_ID, FIELD_POST + aspect.getName() ); objectNode.set( FIELD_PARAMETERS, getRequiredParameters( parameterNode, isEmpty( resourcePath ) ) ); + objectNode.set( FIELD_REQUEST_BODY, FACTORY.objectNode() ); objectNode.set( FIELD_RESPONSES, getResponsesForGet( aspect ) ); return objectNode; } @@ -646,6 +648,7 @@ private ObjectNode getRequestEndpointsUpdate( final Aspect aspect, final ObjectN objectNode.set( "tags", FACTORY.arrayNode().add( aspect.getName() ) ); objectNode.put( FIELD_OPERATION_ID, isPut ? FIELD_PUT : FIELD_PATCH + aspect.getName() ); objectNode.set( FIELD_PARAMETERS, getRequiredParameters( parameterNode, isEmpty( resourcePath ) ) ); + objectNode.set( FIELD_REQUEST_BODY, FACTORY.objectNode() ); objectNode.set( FIELD_RESPONSES, getResponsesForGet( aspect ) ); 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 d0ce5234c..b82d56f1b 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 @@ -185,6 +185,9 @@ void testDefaultResourcePath( final KnownVersion metaModelVersion ) { final SwaggerParseResult result = new OpenAPIParser().readContents( json.toString(), null, null ); final OpenAPI openApi = result.getOpenAPI(); + assertThat( openApi.getPaths().get( "/{tenant-id}/aspect-without-see-attribute" ).getPost() ).isNull(); + assertThat( openApi.getPaths().get( "/{tenant-id}/aspect-without-see-attribute" ).getPut() ).isNull(); + assertThat( openApi.getPaths().get( "/{tenant-id}/aspect-without-see-attribute" ).getPatch() ).isNull(); assertThat( openApi.getPaths().keySet() ).anyMatch( path -> path.equals( "/{tenant-id}/aspect-without-see-attribute" ) ); assertThat( openApi.getPaths().keySet() ).anyMatch( path -> path.equals( "https://test-aspect.example.com/query-api/v1.0.0" ) ); } @@ -509,6 +512,27 @@ void testAspectWithOperationWithSeeAttribute( final KnownVersion metaModelVersio .get( 1 )).getProperties() ).doesNotContainKey( "params" ); } + @ParameterizedTest + @MethodSource( value = "allVersions" ) + void testAspectWithAllCrud( final KnownVersion metaModelVersion ) { + final Aspect aspect = loadAspect( TestAspect.ASPECT_WITHOUT_SEE_ATTRIBUTE, metaModelVersion ); + final OpenApiSchemaGenerationConfig config = OpenApiSchemaGenerationConfigBuilder.builder() + .useSemanticVersion( true ) + .baseUrl( TEST_BASE_URL ) + .includeQueryApi( true ) + .includeCrud( true ) + .build(); + final JsonNode json = apiJsonGenerator.apply( aspect, config ).getContent(); + final SwaggerParseResult result = new OpenAPIParser().readContents( json.toString(), null, null ); + final OpenAPI openApi = result.getOpenAPI(); + + assertThat( openApi.getPaths().get( "/{tenant-id}/aspect-without-see-attribute" ).getGet() ).isNotNull(); + assertThat( openApi.getPaths().get( "/{tenant-id}/aspect-without-see-attribute" ).getPost() ).isNotNull(); + assertThat( openApi.getPaths().get( "/{tenant-id}/aspect-without-see-attribute" ).getPut() ).isNotNull(); + assertThat( openApi.getPaths().get( "/{tenant-id}/aspect-without-see-attribute" ).getPatch() ).isNotNull(); + assertThat( openApi.getPaths().keySet() ).anyMatch( path -> path.equals( "https://test-aspect.example.com/query-api/v1.0.0" ) ); + } + @ParameterizedTest @MethodSource( value = "allVersions" ) void testAspectWithCommentForSeeAttributes( final KnownVersion metaModelVersion ) { From 7025fb288f65cc3a00d1ae390cd5996d1924bd5d Mon Sep 17 00:00:00 2001 From: Yauhenikapl Date: Tue, 14 May 2024 09:48:32 +0300 Subject: [PATCH 4/8] Add CRUD functionality to Maven Plugin --- .../org/eclipse/esmf/aspectmodel/GenerateOpenApiSpec.java | 4 ++++ .../generate-openapi-spec-json-pom-valid-aspect-model.xml | 1 + 2 files changed, 5 insertions(+) diff --git a/tools/esmf-aspect-model-maven-plugin/src/main/java/org/eclipse/esmf/aspectmodel/GenerateOpenApiSpec.java b/tools/esmf-aspect-model-maven-plugin/src/main/java/org/eclipse/esmf/aspectmodel/GenerateOpenApiSpec.java index efdc91ab1..314148b51 100644 --- a/tools/esmf-aspect-model-maven-plugin/src/main/java/org/eclipse/esmf/aspectmodel/GenerateOpenApiSpec.java +++ b/tools/esmf-aspect-model-maven-plugin/src/main/java/org/eclipse/esmf/aspectmodel/GenerateOpenApiSpec.java @@ -75,6 +75,9 @@ public class GenerateOpenApiSpec extends AspectModelMojo { @Parameter( defaultValue = "false" ) private boolean includeQueryApi; + @Parameter( defaultValue = "false" ) + private boolean includeFullCrud; + @Parameter( defaultValue = "false" ) private boolean excludePaging; @@ -112,6 +115,7 @@ public void execute() throws MojoExecutionException, MojoFailureException { .resourcePath( aspectResourcePath ) .properties( readAspectParameterFile() ) .includeQueryApi( includeQueryApi ) + .includeCrud( includeFullCrud ) .pagingOption( getPagingFromArgs() ) .locale( locale ) .build(); diff --git a/tools/esmf-aspect-model-maven-plugin/src/test/resources/generate-openapi-spec-json-pom-valid-aspect-model.xml b/tools/esmf-aspect-model-maven-plugin/src/test/resources/generate-openapi-spec-json-pom-valid-aspect-model.xml index f03fd975c..02857b1e7 100644 --- a/tools/esmf-aspect-model-maven-plugin/src/test/resources/generate-openapi-spec-json-pom-valid-aspect-model.xml +++ b/tools/esmf-aspect-model-maven-plugin/src/test/resources/generate-openapi-spec-json-pom-valid-aspect-model.xml @@ -33,6 +33,7 @@ http://example.com ${basedir}/target/test-artifacts + true json From b65d95cca0561be9d0b8b2afe3cbc6a0fbdb6442 Mon Sep 17 00:00:00 2001 From: Yauhenikapl Date: Tue, 14 May 2024 17:23:57 +0300 Subject: [PATCH 5/8] Update docs for all CRUD methods for OpenAPI Specification. --- .../modules/tooling-guide/pages/maven-plugin.adoc | 1 + .../developer-guide/modules/tooling-guide/pages/samm-cli.adoc | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/documentation/developer-guide/modules/tooling-guide/pages/maven-plugin.adoc b/documentation/developer-guide/modules/tooling-guide/pages/maven-plugin.adoc index 937ae1dec..e0a6beb5e 100644 --- a/documentation/developer-guide/modules/tooling-guide/pages/maven-plugin.adoc +++ b/documentation/developer-guide/modules/tooling-guide/pages/maven-plugin.adoc @@ -267,6 +267,7 @@ Configuration Properties: | `useSemanticApiVersion` | Use the complete semantic version of the Aspect Model as the version of the Aspect API. | `Boolean` | `false` | {nok} | `aspectResourcePath` | The resource-path` for the Aspect API endpoints. | `String` | none | {nok} | `includeQueryApi` | Include the path for the Query Aspect API Endpoint in the OpenAPI specification. | `Boolean` | `false` | {nok} +| `includeFullCrud` | Include the POST/PUT/PATCH methods in the OpenAPI specification. | `Boolean` | `false` | {nok} | `excludePaging` | Exclude paging information for the Aspect API Endpoint in the OpenAPI specification. | `Boolean` | `false` | {nok} | `aspectCursorBasedPaging` | Set the used paging strategy as cursor-based paging. | `Boolean` | `false` | {nok} | `aspectOffsetBasedPaging` | Set the used paging strategy as offset-based paging. | `Boolean` | `false` | {nok} diff --git a/documentation/developer-guide/modules/tooling-guide/pages/samm-cli.adoc b/documentation/developer-guide/modules/tooling-guide/pages/samm-cli.adoc index f1c7ffe75..26627c1a8 100644 --- a/documentation/developer-guide/modules/tooling-guide/pages/samm-cli.adoc +++ b/documentation/developer-guide/modules/tooling-guide/pages/samm-cli.adoc @@ -96,7 +96,7 @@ The available options and their meaning can also be seen in the help text of the https://velocity.apache.org/[Velocity] macro library | | _--static, -s_ : generate Java domain classes for a Static Meta Model | | _--custom-resolver_ : use an external resolver for the resolution of the model elements | -.16+| aspect to openapi | Generate https://spec.openapis.org/oas/v3.0.3[OpenAPI] specification for an Aspect Model| `samm aspect AspectModel.ttl to openapi -j` +.17+| aspect to openapi | Generate https://spec.openapis.org/oas/v3.0.3[OpenAPI] specification for an Aspect Model| `samm aspect AspectModel.ttl to openapi -j` | _--output, -o_ : output file path (default: stdout) | | _--api-base-url, -b_ : the base url for the Aspect API used in the https://spec.openapis.org/oas/v3.0.3[OpenAPI] specification | `samm aspect AspectModel.ttl to openapi -j -b \http://mysite.de` @@ -111,6 +111,7 @@ The available options and their meaning can also be seen in the help text of the | _--resource-path, -r_ : the resource path for the Aspect API endpoints | For detailed description, see the section bellow | _--include-query-api, -q_ : include the path for the Query Aspect API Endpoint in the https://spec.openapis.org/oas/v3.0.3[OpenAPI] specification | + | _--include-crud, -cr_ : include the POST/PUT/PATCH methods in the OpenAPI specification | | _--paging-none, -pn_ : exclude paging information for the Aspect API Endpoint in the https://spec.openapis.org/oas/v3.0.3[OpenAPI] specification | | _--paging-cursor-based, -pc_ : in case there is more than one paging possibility, From 77820469f73c1c284b23d67ea5b7935474bc3cab Mon Sep 17 00:00:00 2001 From: Yauhenikapl Date: Tue, 21 May 2024 11:48:54 +0300 Subject: [PATCH 6/8] Update PR for need changes. --- .../openapi/AspectModelOpenApiGenerator.java | 12 +- .../OpenApiSchemaGenerationConfig.java | 8 +- .../AspectModelOpenApiGeneratorTest.java | 103 ++++++- .../tooling-guide/pages/maven-plugin.adoc | 3 + .../modules/tooling-guide/pages/samm-cli.adoc | 5 +- .../esmf/aspectmodel/GenerateOpenApiSpec.java | 12 + .../aspectmodel/GenerateOpenApiSpecTest.java | 13 +- .../aspect/to/AspectToOpenapiCommand.java | 17 +- .../java/org/eclipse/esmf/SammCliTest.java | 288 +++++++++++++----- 9 files changed, 374 insertions(+), 87 deletions(-) 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 c56c0806d..8f64dc6b0 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 @@ -509,9 +509,17 @@ private ObjectNode getPathsNode( final Aspect aspect, final OpenApiSchemaGenerat pathNode.set( FIELD_GET, getRequestEndpointsRead( aspect, propertiesNode, config.resourcePath() ) ); - if ( config.includeCrud() ) { + boolean includeCrud = config.includeCrud(); + + if ( includeCrud || config.includePost() ) { pathNode.set( FIELD_POST, getRequestEndpointsCreate( aspect, propertiesNode, config.resourcePath() ) ); + } + + if ( includeCrud || config.includePut() ) { pathNode.set( FIELD_PUT, getRequestEndpointsUpdate( aspect, propertiesNode, config.resourcePath(), true ) ); + } + + if ( includeCrud || config.includePatch() ) { pathNode.set( FIELD_PATCH, getRequestEndpointsUpdate( aspect, propertiesNode, config.resourcePath(), false ) ); } @@ -646,7 +654,7 @@ private ObjectNode getRequestEndpointsUpdate( final Aspect aspect, final ObjectN final boolean isPut ) { final ObjectNode objectNode = FACTORY.objectNode(); objectNode.set( "tags", FACTORY.arrayNode().add( aspect.getName() ) ); - objectNode.put( FIELD_OPERATION_ID, isPut ? FIELD_PUT : FIELD_PATCH + aspect.getName() ); + objectNode.put( FIELD_OPERATION_ID, (isPut ? FIELD_PUT : FIELD_PATCH) + aspect.getName() ); objectNode.set( FIELD_PARAMETERS, getRequiredParameters( parameterNode, isEmpty( resourcePath ) ) ); objectNode.set( FIELD_REQUEST_BODY, FACTORY.objectNode() ); objectNode.set( FIELD_RESPONSES, getResponsesForGet( aspect ) ); 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 23b74bd80..7dd6fd060 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 @@ -45,7 +45,13 @@ public record OpenApiSchemaGenerationConfig( ObjectNode properties, PagingOption pagingOption, boolean includeQueryApi, - boolean includeCrud + boolean includeCrud, + + boolean includePost, + + boolean includePut, + + boolean includePatch ) implements GenerationConfig { public OpenApiSchemaGenerationConfig { if ( locale == null ) { 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 b82d56f1b..bbd7c9e56 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 @@ -526,10 +526,105 @@ void testAspectWithAllCrud( final KnownVersion metaModelVersion ) { final SwaggerParseResult result = new OpenAPIParser().readContents( json.toString(), null, null ); final OpenAPI openApi = result.getOpenAPI(); - assertThat( openApi.getPaths().get( "/{tenant-id}/aspect-without-see-attribute" ).getGet() ).isNotNull(); - assertThat( openApi.getPaths().get( "/{tenant-id}/aspect-without-see-attribute" ).getPost() ).isNotNull(); - assertThat( openApi.getPaths().get( "/{tenant-id}/aspect-without-see-attribute" ).getPut() ).isNotNull(); - assertThat( openApi.getPaths().get( "/{tenant-id}/aspect-without-see-attribute" ).getPatch() ).isNotNull(); + final String apiEndpoint = "/{tenant-id}/aspect-without-see-attribute"; + + assertThat( openApi.getPaths().get( apiEndpoint ).getGet() ).isNotNull(); + assertThat( openApi.getPaths().get( apiEndpoint ).getPost() ).isNotNull(); + assertThat( openApi.getPaths().get( apiEndpoint ).getPut() ).isNotNull(); + assertThat( openApi.getPaths().get( apiEndpoint ).getPatch() ).isNotNull(); + assertThat( openApi.getPaths().keySet() ).anyMatch( path -> path.equals( "https://test-aspect.example.com/query-api/v1.0.0" ) ); + } + + @ParameterizedTest + @MethodSource( value = "allVersions" ) + void testAspectWithPostOperation( final KnownVersion metaModelVersion ) { + final Aspect aspect = loadAspect( TestAspect.ASPECT_WITHOUT_SEE_ATTRIBUTE, metaModelVersion ); + final OpenApiSchemaGenerationConfig config = OpenApiSchemaGenerationConfigBuilder.builder() + .useSemanticVersion( true ) + .baseUrl( TEST_BASE_URL ) + .includeQueryApi( true ) + .includePost( true ) + .build(); + final JsonNode json = apiJsonGenerator.apply( aspect, config ).getContent(); + final SwaggerParseResult result = new OpenAPIParser().readContents( json.toString(), null, null ); + final OpenAPI openApi = result.getOpenAPI(); + + final String apiEndpoint = "/{tenant-id}/aspect-without-see-attribute"; + + assertThat( openApi.getPaths().get( apiEndpoint ).getGet() ).isNotNull(); + assertThat( openApi.getPaths().get( apiEndpoint ).getPost() ).isNotNull(); + assertThat( openApi.getPaths().get( apiEndpoint ).getPut() ).isNull(); + assertThat( openApi.getPaths().get( apiEndpoint ).getPatch() ).isNull(); + assertThat( openApi.getPaths().keySet() ).anyMatch( path -> path.equals( "https://test-aspect.example.com/query-api/v1.0.0" ) ); + } + + @ParameterizedTest + @MethodSource( value = "allVersions" ) + void testAspectWithPutOperation( final KnownVersion metaModelVersion ) { + final Aspect aspect = loadAspect( TestAspect.ASPECT_WITHOUT_SEE_ATTRIBUTE, metaModelVersion ); + final OpenApiSchemaGenerationConfig config = OpenApiSchemaGenerationConfigBuilder.builder() + .useSemanticVersion( true ) + .baseUrl( TEST_BASE_URL ) + .includeQueryApi( true ) + .includePut( true ) + .build(); + final JsonNode json = apiJsonGenerator.apply( aspect, config ).getContent(); + final SwaggerParseResult result = new OpenAPIParser().readContents( json.toString(), null, null ); + final OpenAPI openApi = result.getOpenAPI(); + + final String apiEndpoint = "/{tenant-id}/aspect-without-see-attribute"; + + assertThat( openApi.getPaths().get( apiEndpoint ).getGet() ).isNotNull(); + assertThat( openApi.getPaths().get( apiEndpoint ).getPost() ).isNull(); + assertThat( openApi.getPaths().get( apiEndpoint ).getPut() ).isNotNull(); + assertThat( openApi.getPaths().get( apiEndpoint ).getPatch() ).isNull(); + assertThat( openApi.getPaths().keySet() ).anyMatch( path -> path.equals( "https://test-aspect.example.com/query-api/v1.0.0" ) ); + } + + @ParameterizedTest + @MethodSource( value = "allVersions" ) + void testAspectWithPatchOperation( final KnownVersion metaModelVersion ) { + final Aspect aspect = loadAspect( TestAspect.ASPECT_WITHOUT_SEE_ATTRIBUTE, metaModelVersion ); + final OpenApiSchemaGenerationConfig config = OpenApiSchemaGenerationConfigBuilder.builder() + .useSemanticVersion( true ) + .baseUrl( TEST_BASE_URL ) + .includeQueryApi( true ) + .includePatch( true ) + .build(); + final JsonNode json = apiJsonGenerator.apply( aspect, config ).getContent(); + final SwaggerParseResult result = new OpenAPIParser().readContents( json.toString(), null, null ); + final OpenAPI openApi = result.getOpenAPI(); + + final String apiEndpoint = "/{tenant-id}/aspect-without-see-attribute"; + + assertThat( openApi.getPaths().get( apiEndpoint ).getGet() ).isNotNull(); + assertThat( openApi.getPaths().get( apiEndpoint ).getPost() ).isNull(); + assertThat( openApi.getPaths().get( apiEndpoint ).getPut() ).isNull(); + assertThat( openApi.getPaths().get( apiEndpoint ).getPatch() ).isNotNull(); + assertThat( openApi.getPaths().keySet() ).anyMatch( path -> path.equals( "https://test-aspect.example.com/query-api/v1.0.0" ) ); + } + + @ParameterizedTest + @MethodSource( value = "allVersions" ) + void testAspectWithPatchAndPostOperation( final KnownVersion metaModelVersion ) { + final Aspect aspect = loadAspect( TestAspect.ASPECT_WITHOUT_SEE_ATTRIBUTE, metaModelVersion ); + final OpenApiSchemaGenerationConfig config = OpenApiSchemaGenerationConfigBuilder.builder() + .useSemanticVersion( true ) + .baseUrl( TEST_BASE_URL ) + .includeQueryApi( true ) + .includePatch( true ) + .includePost( true ) + .build(); + final JsonNode json = apiJsonGenerator.apply( aspect, config ).getContent(); + final SwaggerParseResult result = new OpenAPIParser().readContents( json.toString(), null, null ); + final OpenAPI openApi = result.getOpenAPI(); + + final String apiEndpoint = "/{tenant-id}/aspect-without-see-attribute"; + + assertThat( openApi.getPaths().get( apiEndpoint ).getGet() ).isNotNull(); + assertThat( openApi.getPaths().get( apiEndpoint ).getPost() ).isNotNull(); + assertThat( openApi.getPaths().get( apiEndpoint ).getPut() ).isNull(); + assertThat( openApi.getPaths().get( apiEndpoint ).getPatch() ).isNotNull(); assertThat( openApi.getPaths().keySet() ).anyMatch( path -> path.equals( "https://test-aspect.example.com/query-api/v1.0.0" ) ); } diff --git a/documentation/developer-guide/modules/tooling-guide/pages/maven-plugin.adoc b/documentation/developer-guide/modules/tooling-guide/pages/maven-plugin.adoc index e0a6beb5e..3bd9cd110 100644 --- a/documentation/developer-guide/modules/tooling-guide/pages/maven-plugin.adoc +++ b/documentation/developer-guide/modules/tooling-guide/pages/maven-plugin.adoc @@ -268,6 +268,9 @@ Configuration Properties: | `aspectResourcePath` | The resource-path` for the Aspect API endpoints. | `String` | none | {nok} | `includeQueryApi` | Include the path for the Query Aspect API Endpoint in the OpenAPI specification. | `Boolean` | `false` | {nok} | `includeFullCrud` | Include the POST/PUT/PATCH methods in the OpenAPI specification. | `Boolean` | `false` | {nok} +| `includePost` | Include the POST method in the OpenAPI specification. | `Boolean` | `false` | {nok} +| `includePut` | Include the PUT method in the OpenAPI specification. | `Boolean` | `false` | {nok} +| `includePatch` | Include the PATCH method in the OpenAPI specification. | `Boolean` | `false` | {nok} | `excludePaging` | Exclude paging information for the Aspect API Endpoint in the OpenAPI specification. | `Boolean` | `false` | {nok} | `aspectCursorBasedPaging` | Set the used paging strategy as cursor-based paging. | `Boolean` | `false` | {nok} | `aspectOffsetBasedPaging` | Set the used paging strategy as offset-based paging. | `Boolean` | `false` | {nok} diff --git a/documentation/developer-guide/modules/tooling-guide/pages/samm-cli.adoc b/documentation/developer-guide/modules/tooling-guide/pages/samm-cli.adoc index 26627c1a8..051a84f7a 100644 --- a/documentation/developer-guide/modules/tooling-guide/pages/samm-cli.adoc +++ b/documentation/developer-guide/modules/tooling-guide/pages/samm-cli.adoc @@ -96,7 +96,7 @@ The available options and their meaning can also be seen in the help text of the https://velocity.apache.org/[Velocity] macro library | | _--static, -s_ : generate Java domain classes for a Static Meta Model | | _--custom-resolver_ : use an external resolver for the resolution of the model elements | -.17+| aspect to openapi | Generate https://spec.openapis.org/oas/v3.0.3[OpenAPI] specification for an Aspect Model| `samm aspect AspectModel.ttl to openapi -j` +.20+| aspect to openapi | Generate https://spec.openapis.org/oas/v3.0.3[OpenAPI] specification for an Aspect Model| `samm aspect AspectModel.ttl to openapi -j` | _--output, -o_ : output file path (default: stdout) | | _--api-base-url, -b_ : the base url for the Aspect API used in the https://spec.openapis.org/oas/v3.0.3[OpenAPI] specification | `samm aspect AspectModel.ttl to openapi -j -b \http://mysite.de` @@ -112,6 +112,9 @@ The available options and their meaning can also be seen in the help text of the | _--include-query-api, -q_ : include the path for the Query Aspect API Endpoint in the https://spec.openapis.org/oas/v3.0.3[OpenAPI] specification | | _--include-crud, -cr_ : include the POST/PUT/PATCH methods in the OpenAPI specification | + | _--include-post, -post_ : include the POST method in the OpenAPI specification | + | _--include-put, -put_ : include the PUT method in the OpenAPI specification | + | _--include-patch, -patch_ : include the PATCH method in the OpenAPI specification | | _--paging-none, -pn_ : exclude paging information for the Aspect API Endpoint in the https://spec.openapis.org/oas/v3.0.3[OpenAPI] specification | | _--paging-cursor-based, -pc_ : in case there is more than one paging possibility, diff --git a/tools/esmf-aspect-model-maven-plugin/src/main/java/org/eclipse/esmf/aspectmodel/GenerateOpenApiSpec.java b/tools/esmf-aspect-model-maven-plugin/src/main/java/org/eclipse/esmf/aspectmodel/GenerateOpenApiSpec.java index 314148b51..cd965b5f7 100644 --- a/tools/esmf-aspect-model-maven-plugin/src/main/java/org/eclipse/esmf/aspectmodel/GenerateOpenApiSpec.java +++ b/tools/esmf-aspect-model-maven-plugin/src/main/java/org/eclipse/esmf/aspectmodel/GenerateOpenApiSpec.java @@ -78,6 +78,15 @@ public class GenerateOpenApiSpec extends AspectModelMojo { @Parameter( defaultValue = "false" ) private boolean includeFullCrud; + @Parameter( defaultValue = "false" ) + private boolean includePost; + + @Parameter( defaultValue = "false" ) + private boolean includePut; + + @Parameter( defaultValue = "false" ) + private boolean includePatch; + @Parameter( defaultValue = "false" ) private boolean excludePaging; @@ -116,6 +125,9 @@ public void execute() throws MojoExecutionException, MojoFailureException { .properties( readAspectParameterFile() ) .includeQueryApi( includeQueryApi ) .includeCrud( includeFullCrud ) + .includePost( includePost ) + .includePut( includePut ) + .includePatch( includePatch ) .pagingOption( getPagingFromArgs() ) .locale( locale ) .build(); diff --git a/tools/esmf-aspect-model-maven-plugin/src/test/java/org/eclipse/esmf/aspectmodel/GenerateOpenApiSpecTest.java b/tools/esmf-aspect-model-maven-plugin/src/test/java/org/eclipse/esmf/aspectmodel/GenerateOpenApiSpecTest.java index 1322724cc..9eb637ae8 100644 --- a/tools/esmf-aspect-model-maven-plugin/src/test/java/org/eclipse/esmf/aspectmodel/GenerateOpenApiSpecTest.java +++ b/tools/esmf-aspect-model-maven-plugin/src/test/java/org/eclipse/esmf/aspectmodel/GenerateOpenApiSpecTest.java @@ -17,6 +17,8 @@ import static org.assertj.core.api.Assertions.assertThatCode; import java.io.File; +import java.nio.file.Files; +import java.nio.file.Path; import org.apache.maven.plugin.Mojo; import org.apache.maven.plugin.MojoExecutionException; @@ -49,7 +51,16 @@ public void testGenerateOpenApiSpecYamlValidAspectModel() throws Exception { final File testPom = getTestFile( "src/test/resources/generate-openapi-spec-yaml-pom-valid-aspect-model.xml" ); final Mojo generateOpenApiSpec = lookupMojo( "generateOpenApiSpec", testPom ); assertThatCode( generateOpenApiSpec::execute ).doesNotThrowAnyException(); - assertThat( generatedFilePath( "Aspect.oai.yaml" ) ).exists(); + + final Path generatedFile = generatedFilePath( "Aspect.oai.yaml" ); + assertThat( generatedFile ).exists(); + + final String yamlContent = new String( Files.readAllBytes( generatedFile ) ); + + assertThat( yamlContent ).isNotEmpty(); + assertThat( yamlContent ).contains("\"post\":"); + assertThat( yamlContent ).contains("\"put\":"); + assertThat( yamlContent ).contains("\"patch\":"); } @Test diff --git a/tools/samm-cli/src/main/java/org/eclipse/esmf/aspect/to/AspectToOpenapiCommand.java b/tools/samm-cli/src/main/java/org/eclipse/esmf/aspect/to/AspectToOpenapiCommand.java index 5d9385018..637e33c26 100644 --- a/tools/samm-cli/src/main/java/org/eclipse/esmf/aspect/to/AspectToOpenapiCommand.java +++ b/tools/samm-cli/src/main/java/org/eclipse/esmf/aspect/to/AspectToOpenapiCommand.java @@ -91,9 +91,21 @@ public class AspectToOpenapiCommand extends AbstractCommand { private boolean includeQueryApi = false; @CommandLine.Option( names = { "--include-crud", "-cr" }, - description = "Include all CRUD operations in the OpenAPI specification." ) + description = "Include all CRUD operations (POST/PUT/PATCH) in the OpenAPI specification." ) private boolean includeFullCrud = false; + @CommandLine.Option( names = { "--include-post", "-post" }, + description = "Include POST operation in the OpenAPI specification." ) + private boolean includePost = false; + + @CommandLine.Option( names = { "--include-put", "-put" }, + description = "Include PUT operation in the OpenAPI specification." ) + private boolean includePut = false; + + @CommandLine.Option( names = { "--include-patch", "-patch" }, + description = "Include PATCH operation in the OpenAPI specification." ) + private boolean includePatch = false; + @CommandLine.Option( names = { "--paging-none", "-pn" }, description = "Exclude paging information for the Aspect API Endpoint in the OpenAPI specification." ) private boolean excludePaging = false; @@ -143,6 +155,9 @@ public void run() { .properties( readAspectParameterFile() ) .includeQueryApi( includeQueryApi ) .includeCrud( includeFullCrud ) + .includePost( includePost ) + .includePut( includePut ) + .includePatch( includePatch ) .pagingOption( getPaging() ) .locale( locale ) .generateCommentForSeeAttributes( generateCommentForSeeAttributes ) diff --git a/tools/samm-cli/src/test/java/org/eclipse/esmf/SammCliTest.java b/tools/samm-cli/src/test/java/org/eclipse/esmf/SammCliTest.java index b994ed037..2da21d621 100644 --- a/tools/samm-cli/src/test/java/org/eclipse/esmf/SammCliTest.java +++ b/tools/samm-cli/src/test/java/org/eclipse/esmf/SammCliTest.java @@ -61,7 +61,7 @@ */ @ExtendWith( LogExtension.class ) @TestInstance( TestInstance.Lifecycle.PER_CLASS ) -public class SammCliTest extends MetaModelVersions { +class SammCliTest extends MetaModelVersions { protected ProcessLauncher sammCli; private final TestModel testModel = TestAspect.ASPECT_WITH_ENTITY; private final String defaultInputFile = inputFile( testModel ).getAbsolutePath(); @@ -69,13 +69,13 @@ public class SammCliTest extends MetaModelVersions { Path outputDirectory = null; @BeforeEach - public void beforeEach() throws IOException { + void beforeEach() throws IOException { sammCli = new MainClassProcessLauncher( SammCli.class ); outputDirectory = Files.createTempDirectory( "junit" ); } @AfterEach - public void afterEach() { + void afterEach() { if ( outputDirectory != null ) { final File outputDir = outputDirectory.toFile(); if ( outputDir.exists() && outputDir.isDirectory() ) { @@ -96,14 +96,14 @@ public void afterEach() { } @Test - public void testNoArgs() { + void testNoArgs() { final ExecutionResult result = sammCli.runAndExpectSuccess( "--disable-color" ); assertThat( result.stdout() ).contains( "Usage:" ); assertThat( result.stderr() ).isEmpty(); } @Test - public void testAspectWithoutSubcommand() { + void testAspectWithoutSubcommand() { final ExecutionResult result = sammCli.apply( "--disable-color", "aspect" ); assertThat( result.exitStatus() ).isEqualTo( 2 ); assertThat( result.stdout() ).isEmpty(); @@ -111,7 +111,7 @@ public void testAspectWithoutSubcommand() { } @Test - public void testWrongArgs() { + void testWrongArgs() { final ExecutionResult result = sammCli.apply( "--disable-color", "-i", "doesnotexist" ); assertThat( result.exitStatus() ).isEqualTo( 2 ); assertThat( result.stdout() ).isEmpty(); @@ -119,21 +119,21 @@ public void testWrongArgs() { } @Test - public void testHelp() { + void testHelp() { final ExecutionResult result = sammCli.runAndExpectSuccess( "--disable-color", "help" ); assertThat( result.stdout() ).contains( "Usage:" ); assertThat( result.stderr() ).isEmpty(); } @Test - public void testVerboseOutput() { + void testVerboseOutput() { final ExecutionResult result = sammCli.runAndExpectSuccess( "--disable-color", "aspect", defaultInputFile, "validate", "-vvv" ); assertThat( result.stdout() ).contains( "Input model is valid" ); assertThat( result.stderr() ).contains( "DEBUG " + AspectValidateCommand.class.getName() ); } @Test - public void testAspectMigrateToFile() { + void testAspectMigrateToFile() { final File targetFile = outputFile( "output.ttl" ); final ExecutionResult result = sammCli.runAndExpectSuccess( "--disable-color", "aspect", defaultInputFile, "migrate", "-o", targetFile.getAbsolutePath() ); @@ -144,14 +144,14 @@ public void testAspectMigrateToFile() { } @Test - public void testAspectMigrateToStdout() { + void testAspectMigrateToStdout() { final ExecutionResult result = sammCli.runAndExpectSuccess( "--disable-color", "aspect", defaultInputFile, "migrate" ); assertThat( result.stdout() ).contains( "@prefix" ); assertThat( result.stderr() ).isEmpty(); } @Test - public void testAspectPrettyPrintToFile() { + void testAspectPrettyPrintToFile() { final File targetFile = outputFile( "output.ttl" ); final ExecutionResult result = sammCli.runAndExpectSuccess( "--disable-color", "aspect", defaultInputFile, "prettyprint", "-o", targetFile.getAbsolutePath() ); @@ -162,14 +162,14 @@ public void testAspectPrettyPrintToFile() { } @Test - public void testAspectPrettyPrintToStdout() { + void testAspectPrettyPrintToStdout() { final ExecutionResult result = sammCli.runAndExpectSuccess( "--disable-color", "aspect", defaultInputFile, "prettyprint" ); assertThat( result.stdout() ).contains( "@prefix" ); assertThat( result.stderr() ).isEmpty(); } @Test - public void testAspectValidateValidModel() { + void testAspectValidateValidModel() { final ExecutionResult result = sammCli.runAndExpectSuccess( "--disable-color", "aspect", defaultInputFile, "validate" ); assertThat( result.stdout() ).contains( "Input model is valid" ); assertThat( result.stderr() ).isEmpty(); @@ -178,7 +178,7 @@ public void testAspectValidateValidModel() { @ParameterizedTest @EnumSource( TestAspect.class ) @EnabledIfSystemProperty( named = "packaging-type", matches = "native" ) - public void testAspectValidateValidModelAllTestFiles( final TestModel aspect ) { + void testAspectValidateValidModelAllTestFiles( final TestModel aspect ) { final String input = inputFile( aspect ).getAbsolutePath(); final ExecutionResult result = sammCli.runAndExpectSuccess( "--disable-color", "aspect", input, "validate" ); assertThat( result.stdout() ).contains( "Input model is valid" ); @@ -186,7 +186,7 @@ public void testAspectValidateValidModelAllTestFiles( final TestModel aspect ) { } @Test - public void testAspectValidateWithRelativePath() { + void testAspectValidateWithRelativePath() { final File workingDirectory = new File( defaultInputFile ).getParentFile(); final String relativeFileName = "." + File.separator + new File( defaultInputFile ).getName(); final ProcessLauncher.ExecutionContext executionContext = new ProcessLauncher.ExecutionContext( @@ -199,7 +199,7 @@ public void testAspectValidateWithRelativePath() { @Test @DisabledOnOs( OS.WINDOWS ) - public void testAspectValidateInvalidModel() { + void testAspectValidateInvalidModel() { final File invalidModel = inputFile( InvalidTestAspect.INVALID_SYNTAX ); final ExecutionResult result = sammCli.apply( "--disable-color", "aspect", invalidModel.getAbsolutePath(), "validate" ); assertThat( result.exitStatus() ).isEqualTo( 1 ); @@ -208,7 +208,7 @@ public void testAspectValidateInvalidModel() { } @Test - public void testAspectValidateWithDetails() { + void testAspectValidateWithDetails() { final ExecutionResult result = sammCli.runAndExpectSuccess( "--disable-color", "aspect", defaultInputFile, "validate", "--details" ); assertThat( result.stdout() ).contains( "Input model is valid" ); assertThat( result.stderr() ).isEmpty(); @@ -221,7 +221,7 @@ public void testAspectValidateWithDetails() { } @Test - public void testAspectValidateWithCustomResolver() { + void testAspectValidateWithCustomResolver() { final ExecutionResult result = sammCli.runAndExpectSuccess( "--disable-color", "aspect", defaultInputFile, "validate", "--custom-resolver", resolverCommand() ); assertThat( result.stdout() ).contains( "Input model is valid" ); @@ -229,7 +229,7 @@ public void testAspectValidateWithCustomResolver() { } @Test - public void testAspectToAasXmlToFile() { + void testAspectToAasXmlToFile() { final File targetFile = outputFile( "output.xml" ); final ExecutionResult result = sammCli.runAndExpectSuccess( "--disable-color", "aspect", defaultInputFile, "to", "aas", "--format", "xml", "-o", targetFile.getAbsolutePath() ); @@ -242,7 +242,7 @@ public void testAspectToAasXmlToFile() { @ParameterizedTest @EnumSource( TestAspect.class ) @EnabledIfSystemProperty( named = "packaging-type", matches = "native" ) - public void testAspectToAasXmlToFileAllTestFiles( final TestModel aspect ) { + void testAspectToAasXmlToFileAllTestFiles( final TestModel aspect ) { final String input = inputFile( aspect ).getAbsolutePath(); final File targetFile = outputFile( "output.xml" ); assertThat( targetFile ).doesNotExist(); @@ -255,7 +255,7 @@ public void testAspectToAasXmlToFileAllTestFiles( final TestModel aspect ) { } @Test - public void testAspectToAasXmlToStdout() { + void testAspectToAasXmlToStdout() { final ExecutionResult result = sammCli.runAndExpectSuccess( "--disable-color", "aspect", defaultInputFile, "to", "aas", "--format", "xml" ); assertThat( result.stdout() ).startsWith( " Date: Tue, 21 May 2024 11:51:13 +0300 Subject: [PATCH 7/8] Fix ckeckStyle --- .../eclipse/esmf/aspectmodel/GenerateOpenApiSpecTest.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/esmf-aspect-model-maven-plugin/src/test/java/org/eclipse/esmf/aspectmodel/GenerateOpenApiSpecTest.java b/tools/esmf-aspect-model-maven-plugin/src/test/java/org/eclipse/esmf/aspectmodel/GenerateOpenApiSpecTest.java index 9eb637ae8..d39027337 100644 --- a/tools/esmf-aspect-model-maven-plugin/src/test/java/org/eclipse/esmf/aspectmodel/GenerateOpenApiSpecTest.java +++ b/tools/esmf-aspect-model-maven-plugin/src/test/java/org/eclipse/esmf/aspectmodel/GenerateOpenApiSpecTest.java @@ -58,9 +58,9 @@ public void testGenerateOpenApiSpecYamlValidAspectModel() throws Exception { final String yamlContent = new String( Files.readAllBytes( generatedFile ) ); assertThat( yamlContent ).isNotEmpty(); - assertThat( yamlContent ).contains("\"post\":"); - assertThat( yamlContent ).contains("\"put\":"); - assertThat( yamlContent ).contains("\"patch\":"); + assertThat( yamlContent ).contains( "\"post\":" ); + assertThat( yamlContent ).contains( "\"put\":" ); + assertThat( yamlContent ).contains( "\"patch\":" ); } @Test From 96137fb748a0ff038f0c74730e933e16597d5ab1 Mon Sep 17 00:00:00 2001 From: Yauhenikapl Date: Tue, 21 May 2024 12:12:52 +0300 Subject: [PATCH 8/8] Fix MavenPlugin tests --- .../aspectmodel/GenerateOpenApiSpecTest.java | 37 +++++++++++----- ...alid-aspect-model-with-crud-parameters.xml | 44 +++++++++++++++++++ 2 files changed, 70 insertions(+), 11 deletions(-) create mode 100644 tools/esmf-aspect-model-maven-plugin/src/test/resources/generate-openapi-spec-json-pom-valid-aspect-model-with-crud-parameters.xml diff --git a/tools/esmf-aspect-model-maven-plugin/src/test/java/org/eclipse/esmf/aspectmodel/GenerateOpenApiSpecTest.java b/tools/esmf-aspect-model-maven-plugin/src/test/java/org/eclipse/esmf/aspectmodel/GenerateOpenApiSpecTest.java index d39027337..4d7592040 100644 --- a/tools/esmf-aspect-model-maven-plugin/src/test/java/org/eclipse/esmf/aspectmodel/GenerateOpenApiSpecTest.java +++ b/tools/esmf-aspect-model-maven-plugin/src/test/java/org/eclipse/esmf/aspectmodel/GenerateOpenApiSpecTest.java @@ -30,7 +30,31 @@ public void testGenerateOpenApiSpecJsonValidAspectModel() throws Exception { final File testPom = getTestFile( "src/test/resources/generate-openapi-spec-json-pom-valid-aspect-model.xml" ); final Mojo generateOpenApiSpec = lookupMojo( "generateOpenApiSpec", testPom ); assertThatCode( generateOpenApiSpec::execute ).doesNotThrowAnyException(); - assertThat( generatedFilePath( "Aspect.oai.json" ) ).exists(); + + final Path generatedFile = generatedFilePath( "Aspect.oai.json" ); + assertThat( generatedFile ).exists(); + + final String yamlContent = new String( Files.readAllBytes( generatedFile ) ); + + assertThat( yamlContent ).contains( "postAspect" ); + assertThat( yamlContent ).contains( "putAspect" ); + assertThat( yamlContent ).contains( "patchAspect" ); + } + + @Test + public void testGenerateOpenApiSpecJsonValidAspectModelWithCrudParameters() throws Exception { + final File testPom = getTestFile( "src/test/resources/generate-openapi-spec-json-pom-valid-aspect-model-with-crud-parameters.xml" ); + final Mojo generateOpenApiSpec = lookupMojo( "generateOpenApiSpec", testPom ); + assertThatCode( generateOpenApiSpec::execute ).doesNotThrowAnyException(); + + final Path generatedFile = generatedFilePath( "Aspect.oai.json" ); + assertThat( generatedFile ).exists(); + + final String yamlContent = new String( Files.readAllBytes( generatedFile ) ); + + assertThat( yamlContent ).contains( "postAspect" ); + assertThat( yamlContent ).contains( "putAspect" ); + assertThat( yamlContent ).contains( "patchAspect" ); } /** @@ -51,16 +75,7 @@ public void testGenerateOpenApiSpecYamlValidAspectModel() throws Exception { final File testPom = getTestFile( "src/test/resources/generate-openapi-spec-yaml-pom-valid-aspect-model.xml" ); final Mojo generateOpenApiSpec = lookupMojo( "generateOpenApiSpec", testPom ); assertThatCode( generateOpenApiSpec::execute ).doesNotThrowAnyException(); - - final Path generatedFile = generatedFilePath( "Aspect.oai.yaml" ); - assertThat( generatedFile ).exists(); - - final String yamlContent = new String( Files.readAllBytes( generatedFile ) ); - - assertThat( yamlContent ).isNotEmpty(); - assertThat( yamlContent ).contains( "\"post\":" ); - assertThat( yamlContent ).contains( "\"put\":" ); - assertThat( yamlContent ).contains( "\"patch\":" ); + assertThat( generatedFilePath( "Aspect.oai.yaml" ) ).exists(); } @Test diff --git a/tools/esmf-aspect-model-maven-plugin/src/test/resources/generate-openapi-spec-json-pom-valid-aspect-model-with-crud-parameters.xml b/tools/esmf-aspect-model-maven-plugin/src/test/resources/generate-openapi-spec-json-pom-valid-aspect-model-with-crud-parameters.xml new file mode 100644 index 000000000..9950cf67b --- /dev/null +++ b/tools/esmf-aspect-model-maven-plugin/src/test/resources/generate-openapi-spec-json-pom-valid-aspect-model-with-crud-parameters.xml @@ -0,0 +1,44 @@ + + + + + 4.0.0 + + org.eclipse.esmf + test-generate-openapi-spec-mojo + 1.0 + jar + Test Generate OpenApi Spec Mojo + + + + + esmf-aspect-model-maven-plugin + + ${basedir}/../../core/esmf-test-aspect-models/src/main/resources/valid/samm_2_0_0 + + urn:samm:org.eclipse.esmf.test:1.0.0#Aspect + + http://example.com + ${basedir}/target/test-artifacts + true + true + true + json + + + + +