From 42236c4135194e37a7e80a942a8ea5b6a6f9cb5b Mon Sep 17 00:00:00 2001 From: Dilip Krishnan Date: Mon, 15 Jun 2020 08:51:13 -0500 Subject: [PATCH] Updated sample OAS service This is to develop the against a fixed contract that we're expecting in the end (2022) --- oas-contract-tests/build.gradle | 1 - .../test/contract/oas/OasApplication.java | 9 +- .../test/contract/oas/OpenApiTestConfig.java | 241 +- .../test/contract/oas/api/ApiUtil.java | 50 + .../contract/oas/api/ExceptionTranslator.java | 47 + .../test/contract/oas/api/HomeController.java | 40 + .../test/contract/oas/api/PetApi.java | 302 +++ .../contract/oas/api/PetApiController.java | 46 + .../test/contract/oas/api/PetApiDelegate.java | 162 ++ .../contract/oas/api/PetApiDelegateImpl.java | 282 ++ .../test/contract/oas/api/StoreApi.java | 130 + .../contract/oas/api/StoreApiController.java | 46 + .../contract/oas/api/StoreApiDelegate.java | 100 + .../oas/api/StoreApiDelegateImpl.java | 103 + .../test/contract/oas/api/UserApi.java | 201 ++ .../contract/oas/api/UserApiController.java | 46 + .../contract/oas/api/UserApiDelegate.java | 132 + .../contract/oas/api/UserApiDelegateImpl.java | 141 + .../test/contract/oas/model/Category.java | 131 + .../contract/oas/model/ModelApiResponse.java | 161 ++ .../test/contract/oas/model/Order.java | 273 ++ .../test/contract/oas/model/Pet.java | 285 ++ .../test/contract/oas/model/Tag.java | 131 + .../test/contract/oas/model/User.java | 312 +++ .../oas/repository/HashMapRepository.java | 175 ++ .../oas/repository/OrderRepository.java | 35 + .../oas/repository/PetRepository.java | 69 + .../oas/repository/UserRepository.java | 35 + .../contract/oas/FunctionContractSpec.groovy | 58 +- .../test/resources/contracts/petstore.json | 2342 +++++++++-------- 30 files changed, 4721 insertions(+), 1365 deletions(-) create mode 100644 oas-contract-tests/src/main/java/springfox/test/contract/oas/api/ApiUtil.java create mode 100644 oas-contract-tests/src/main/java/springfox/test/contract/oas/api/ExceptionTranslator.java create mode 100644 oas-contract-tests/src/main/java/springfox/test/contract/oas/api/HomeController.java create mode 100644 oas-contract-tests/src/main/java/springfox/test/contract/oas/api/PetApi.java create mode 100644 oas-contract-tests/src/main/java/springfox/test/contract/oas/api/PetApiController.java create mode 100644 oas-contract-tests/src/main/java/springfox/test/contract/oas/api/PetApiDelegate.java create mode 100644 oas-contract-tests/src/main/java/springfox/test/contract/oas/api/PetApiDelegateImpl.java create mode 100644 oas-contract-tests/src/main/java/springfox/test/contract/oas/api/StoreApi.java create mode 100644 oas-contract-tests/src/main/java/springfox/test/contract/oas/api/StoreApiController.java create mode 100644 oas-contract-tests/src/main/java/springfox/test/contract/oas/api/StoreApiDelegate.java create mode 100644 oas-contract-tests/src/main/java/springfox/test/contract/oas/api/StoreApiDelegateImpl.java create mode 100644 oas-contract-tests/src/main/java/springfox/test/contract/oas/api/UserApi.java create mode 100644 oas-contract-tests/src/main/java/springfox/test/contract/oas/api/UserApiController.java create mode 100644 oas-contract-tests/src/main/java/springfox/test/contract/oas/api/UserApiDelegate.java create mode 100644 oas-contract-tests/src/main/java/springfox/test/contract/oas/api/UserApiDelegateImpl.java create mode 100644 oas-contract-tests/src/main/java/springfox/test/contract/oas/model/Category.java create mode 100644 oas-contract-tests/src/main/java/springfox/test/contract/oas/model/ModelApiResponse.java create mode 100644 oas-contract-tests/src/main/java/springfox/test/contract/oas/model/Order.java create mode 100644 oas-contract-tests/src/main/java/springfox/test/contract/oas/model/Pet.java create mode 100644 oas-contract-tests/src/main/java/springfox/test/contract/oas/model/Tag.java create mode 100644 oas-contract-tests/src/main/java/springfox/test/contract/oas/model/User.java create mode 100644 oas-contract-tests/src/main/java/springfox/test/contract/oas/repository/HashMapRepository.java create mode 100644 oas-contract-tests/src/main/java/springfox/test/contract/oas/repository/OrderRepository.java create mode 100644 oas-contract-tests/src/main/java/springfox/test/contract/oas/repository/PetRepository.java create mode 100644 oas-contract-tests/src/main/java/springfox/test/contract/oas/repository/UserRepository.java diff --git a/oas-contract-tests/build.gradle b/oas-contract-tests/build.gradle index 1322b9de36e..6e7ba3bfedd 100644 --- a/oas-contract-tests/build.gradle +++ b/oas-contract-tests/build.gradle @@ -48,7 +48,6 @@ dependencies { compile project(':springfox-oas') compile project(':springfox-data-rest') - compile project(':springfox-petstore') compile project(':springfox-bean-validators') compile(project(path: ':springfox-swagger-ui')) { diff --git a/oas-contract-tests/src/main/java/springfox/test/contract/oas/OasApplication.java b/oas-contract-tests/src/main/java/springfox/test/contract/oas/OasApplication.java index 9a7c797d4ce..ccb98cfca91 100644 --- a/oas-contract-tests/src/main/java/springfox/test/contract/oas/OasApplication.java +++ b/oas-contract-tests/src/main/java/springfox/test/contract/oas/OasApplication.java @@ -21,23 +21,18 @@ import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Import; import org.springframework.hateoas.config.EnableHypermediaSupport; import springfox.bean.validators.configuration.BeanValidatorPluginsConfiguration; +import springfox.documentation.oas.annotations.EnableOasWebMvc; import springfox.documentation.spring.data.rest.configuration.SpringDataRestConfiguration; -import springfox.petstore.PetStoreConfiguration; @SpringBootApplication @SuppressWarnings("HideUtilityClassConstructor") @EnableHypermediaSupport(type = EnableHypermediaSupport.HypermediaType.HAL) -@ComponentScan(basePackages = { - "springfox.test.contract.oas", - "springfox.petstore.controller" -}) +@EnableOasWebMvc @Import(value = { SpringDataRestConfiguration.class, - PetStoreConfiguration.class, SecuritySupport.class, OpenApiTestConfig.class, BeanValidatorPluginsConfiguration.class }) diff --git a/oas-contract-tests/src/main/java/springfox/test/contract/oas/OpenApiTestConfig.java b/oas-contract-tests/src/main/java/springfox/test/contract/oas/OpenApiTestConfig.java index b03b10c0644..cbca77086e1 100644 --- a/oas-contract-tests/src/main/java/springfox/test/contract/oas/OpenApiTestConfig.java +++ b/oas-contract-tests/src/main/java/springfox/test/contract/oas/OpenApiTestConfig.java @@ -1,26 +1,26 @@ package springfox.test.contract.oas; -import groovy.lang.MetaClass; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import springfox.documentation.builders.PathSelectors; -import springfox.documentation.oas.annotations.EnableOasWebMvc; +import springfox.documentation.service.ApiKey; +import springfox.documentation.service.AuthorizationScope; +import springfox.documentation.service.HttpAuthenticationScheme; +import springfox.documentation.service.OAuth2Scheme; import springfox.documentation.service.SecurityScheme; import springfox.documentation.spi.DocumentationType; import springfox.documentation.spring.web.plugins.Docket; -import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; import java.util.List; @Configuration -@EnableOasWebMvc public class OpenApiTestConfig { @Bean - public Docket petstoreWithUriTemplating(List authorizationTypes) { + public Docket petStore(List authorizationTypes) { return new Docket(DocumentationType.OAS_30) - .groupName("petstoreTemplated") + .groupName("petstore") .useDefaultResponseMessages(false) .securitySchemes(authorizationTypes) .produces(new HashSet() {{ @@ -28,221 +28,26 @@ public Docket petstoreWithUriTemplating(List authorizationTypes) add("application/json"); }}) .select() - .paths(PathSelectors.regex("/api/store/search.*")) + .paths(PathSelectors.regex("/.*") + .and(PathSelectors.regex("/error").negate()) + .and(PathSelectors.regex("/profile").negate())) .build() - .enableUrlTemplating(true) + .enableUrlTemplating(false) .host("petstore.swagger.io") .protocols(new HashSet<>(Arrays.asList( "http", - "https"))); - } - - @Bean - public Docket business(List authorizationTypes) { - return new Docket(DocumentationType.OAS_30) - .groupName("businessService") - .useDefaultResponseMessages(false) - .securitySchemes(authorizationTypes) - .produces(new HashSet<>(Arrays.asList( - "application/xml", - "application/json"))) - .select() - .paths(PathSelectors.regex("/business.*")) - .build(); - } - - @Bean - public Docket concrete(List authorizationTypes) { - return new Docket(DocumentationType.OAS_30) - .groupName("concrete") - .useDefaultResponseMessages(false) - .securitySchemes(authorizationTypes) - .produces(new HashSet<>(Arrays.asList( - "application/xml", - "application/json"))) - .select() - .paths(PathSelectors.regex("/foo/.*")) - .build(); - } - - @Bean - public Docket noRequestMapping(List authorizationTypes) { - return new Docket(DocumentationType.OAS_30) - .groupName("noRequestMapping") - .useDefaultResponseMessages(false) - .securitySchemes(authorizationTypes) - .produces(new HashSet<>(Arrays.asList( - "application/xml", - "application/json"))) - .select() - .paths(PathSelectors.regex("/no-request-mapping/.*")) - .build(); - } - - @Bean - public Docket fancyPetstore(List authorizationTypes) { - return new Docket(DocumentationType.OAS_30) - .groupName("fancyPetstore") - .useDefaultResponseMessages(false) - .securitySchemes(authorizationTypes) - .produces(new HashSet<>(Arrays.asList( - "application/xml", - "application/json"))) - .select() - .paths(PathSelectors.regex("/fancypets/.*")) - .build(); - } - - @Bean - public Docket inheritedService(List authorizationTypes) { - return new Docket(DocumentationType.OAS_30) - .groupName("inheritedService") - .useDefaultResponseMessages(false) - .securitySchemes(authorizationTypes) - .produces(new HashSet<>(Arrays.asList( - "application/xml", - "application/json"))) - .select() - .paths(PathSelectors.regex("/child/.*")) - .build(); - } - - @Bean - public Docket pet(List authorizationTypes) { - return new Docket(DocumentationType.OAS_30) - .groupName("petService") - .useDefaultResponseMessages(false) - .securitySchemes(authorizationTypes) - .produces(new HashSet<>(Arrays.asList( - "application/xml", - "application/json"))) - .enableUrlTemplating(true) - .select() - .paths(PathSelectors.regex("/pets/.*")) - .build(); - } - - @Bean - public Docket petGrooming(List authorizationTypes) { - return new Docket(DocumentationType.OAS_30) - .groupName("petGroomingService") - .useDefaultResponseMessages(false) - .securitySchemes(authorizationTypes) - .produces(new HashSet<>( - Arrays.asList( - "application/xml", - "application/json"))) - .select() - .paths(PathSelectors.regex("/petgrooming/.*")) - .build(); - } - - @Bean - public Docket root(List authorizationTypes) { - return new Docket(DocumentationType.OAS_30) - .groupName("root") - .useDefaultResponseMessages(false) - .securitySchemes(authorizationTypes) - .produces(new HashSet<>( - Arrays.asList( - "application/xml", - "application/json"))) - .ignoredParameterTypes(MetaClass.class) - .select() - .paths(PathSelectors.regex("/.*")) - .build(); - } - - @Bean - public Docket groovyServiceBean(List authorizationTypes) { - return new Docket(DocumentationType.OAS_30) - .groupName("groovyService") - .useDefaultResponseMessages(false) - .securitySchemes(authorizationTypes) - .forCodeGeneration(true) - .produces(new HashSet<>( - Arrays.asList( - "application/xml", - "application/json"))) - .select() - .paths(PathSelectors.regex("/groovy/.*")) - .build() - .ignoredParameterTypes(MetaClass.class); - } - - @Bean - public Docket enumServiceBean(List authorizationTypes) { - return new Docket(DocumentationType.OAS_30) - .groupName("enumService") - .useDefaultResponseMessages(false) - .securitySchemes(authorizationTypes) - .produces(new HashSet<>( - Arrays.asList( - "application/xml", - "application/json"))) - .select() - .paths(PathSelectors.regex("/enums/.*")) - .build(); - } - - @Bean - public Docket consumesProducesNotOnDocumentContext(List authorizationTypes) { - return new Docket(DocumentationType.OAS_30) - .groupName("consumesProducesNotOnDocumentContext") - .useDefaultResponseMessages(false) - .securitySchemes(authorizationTypes) - .select() - .paths(PathSelectors.regex("/consumes-produces/.*")) - .build(); - } - - @Bean - public Docket consumesProducesOnDocumentContext(List authorizationTypes) { - return new Docket(DocumentationType.OAS_30) - .groupName("consumesProducesOnDocumentContext") - .useDefaultResponseMessages(false) - .securitySchemes(authorizationTypes) - .consumes(new HashSet() {{ - add("text/plain"); - }}) - .produces(new HashSet() {{ - add("application/json"); - }}) - .select().paths(PathSelectors.regex("/consumes-produces/.*")).build(); - } - - @Bean - public Docket springDataRest() { - return new Docket(DocumentationType.OAS_30) - .groupName("spring-data-rest") - .useDefaultResponseMessages(false) - .enableUrlTemplating(true) - .securitySchemes(new ArrayList<>()) - .forCodeGeneration(true) - .produces(new HashSet<>( - Arrays.asList( - "application/xml", - "application/json"))) - .select() - .paths(PathSelectors.regex("/rest/people.*") - .or(PathSelectors.regex("/rest/tags.*")) - .or(PathSelectors.regex("/rest/categories.*")) - .or(PathSelectors.regex("/rest/addresses.*"))) - .build(); - } - - @Bean - public Docket same(List authorizationTypes) { - return new Docket(DocumentationType.OAS_30) - .groupName("same") - .useDefaultResponseMessages(false) - .securitySchemes(authorizationTypes) - .produces(new HashSet<>( - Arrays.asList( - "application/xml", - "application/json"))) - .select() - .paths(PathSelectors.regex("/same/.*")) - .build(); + "https"))) + .securitySchemes(Arrays.asList( + new ApiKey("api_key", "api_key", "header"), + HttpAuthenticationScheme.BASIC_AUTH_BUILDER + .name("basicScheme") + .build(), + OAuth2Scheme.OAUTH2_IMPLICIT_FLOW_BUILDER + .name("petstore_auth") + .authorizationUrl("https://petstore3.swagger.io/oauth/authorize") + .scopes(Arrays.asList( + new AuthorizationScope("write:pets", "Write scope"), + new AuthorizationScope("read:pets", "Read scope"))) + .build())); } } diff --git a/oas-contract-tests/src/main/java/springfox/test/contract/oas/api/ApiUtil.java b/oas-contract-tests/src/main/java/springfox/test/contract/oas/api/ApiUtil.java new file mode 100644 index 00000000000..89649caa121 --- /dev/null +++ b/oas-contract-tests/src/main/java/springfox/test/contract/oas/api/ApiUtil.java @@ -0,0 +1,50 @@ +/* + * + * * Copyright 2019-2020 the original author or authors. + * * + * * Licensed under the Apache License, Version 2.0 (the "License"); + * * you may not use this file except in compliance with the License. + * * You may obtain a copy of the License at + * * + * * https://www.apache.org/licenses/LICENSE-2.0 + * * + * * Unless required by applicable law or agreed to in writing, software + * * distributed under the License is distributed on an "AS IS" BASIS, + * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * * See the License for the specific language governing permissions and + * * limitations under the License. + * + */ + +package springfox.test.contract.oas.api; + +import org.springframework.http.HttpStatus; +import org.springframework.web.context.request.NativeWebRequest; +import org.springframework.web.server.ResponseStatusException; + +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + +public class ApiUtil { + private ApiUtil() { + } + + public static void setExampleResponse( + NativeWebRequest req, + String contentType, + String example) { + try { + req.getNativeResponse(HttpServletResponse.class).addHeader("Content-Type", contentType); + req.getNativeResponse(HttpServletResponse.class).getOutputStream().print(example); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + public static void checkApiKey(NativeWebRequest req) { + if (!"1".equals(System.getenv("DISABLE_API_KEY")) + && !"special-key".equals(req.getHeader("api_key"))) { + throw new ResponseStatusException(HttpStatus.UNAUTHORIZED, "Missing API key!"); + } + } +} \ No newline at end of file diff --git a/oas-contract-tests/src/main/java/springfox/test/contract/oas/api/ExceptionTranslator.java b/oas-contract-tests/src/main/java/springfox/test/contract/oas/api/ExceptionTranslator.java new file mode 100644 index 00000000000..ad827f36f81 --- /dev/null +++ b/oas-contract-tests/src/main/java/springfox/test/contract/oas/api/ExceptionTranslator.java @@ -0,0 +1,47 @@ +/* + * + * * Copyright 2019-2020 the original author or authors. + * * + * * Licensed under the Apache License, Version 2.0 (the "License"); + * * you may not use this file except in compliance with the License. + * * You may obtain a copy of the License at + * * + * * https://www.apache.org/licenses/LICENSE-2.0 + * * + * * Unless required by applicable law or agreed to in writing, software + * * distributed under the License is distributed on an "AS IS" BASIS, + * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * * See the License for the specific language governing permissions and + * * limitations under the License. + * + */ + +package springfox.test.contract.oas.api; + +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.ResponseStatus; +import org.springframework.web.bind.annotation.RestControllerAdvice; +import org.springframework.web.context.request.WebRequest; + +import javax.validation.ConstraintViolationException; + +@RestControllerAdvice +public class ExceptionTranslator { + + private final org.springframework.boot.web.servlet.error.ErrorAttributes errorAttributes; + + public ExceptionTranslator(org.springframework.boot.web.servlet.error.ErrorAttributes errorAttributes) { + this.errorAttributes = errorAttributes; + } + + @ExceptionHandler(ConstraintViolationException.class) + @ResponseStatus(HttpStatus.BAD_REQUEST) + public java.util.Map processConstraintViolationException(WebRequest request) { + request.setAttribute( + "javax.servlet.error.status_code", + HttpStatus.BAD_REQUEST.value(), + org.springframework.web.context.request.RequestAttributes.SCOPE_REQUEST); + return errorAttributes.getErrorAttributes(request, false); + } +} diff --git a/oas-contract-tests/src/main/java/springfox/test/contract/oas/api/HomeController.java b/oas-contract-tests/src/main/java/springfox/test/contract/oas/api/HomeController.java new file mode 100644 index 00000000000..df8dfb2bf71 --- /dev/null +++ b/oas-contract-tests/src/main/java/springfox/test/contract/oas/api/HomeController.java @@ -0,0 +1,40 @@ +/* + * + * * Copyright 2019-2020 the original author or authors. + * * + * * Licensed under the Apache License, Version 2.0 (the "License"); + * * you may not use this file except in compliance with the License. + * * You may obtain a copy of the License at + * * + * * https://www.apache.org/licenses/LICENSE-2.0 + * * + * * Unless required by applicable law or agreed to in writing, software + * * distributed under the License is distributed on an "AS IS" BASIS, + * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * * See the License for the specific language governing permissions and + * * limitations under the License. + * + */ + +package springfox.test.contract.oas.api; + +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.GetMapping; + +import static org.springframework.util.AntPathMatcher.*; +import static org.springframework.web.servlet.view.UrlBasedViewResolver.*; + +/** + * Home redirection to swagger api documentation + */ +@Controller +public class HomeController { + + //@Value(SWAGGER_UI_PATH) + private String swaggerUiPath; + + @GetMapping(DEFAULT_PATH_SEPARATOR) + public String index() { + return REDIRECT_URL_PREFIX + swaggerUiPath; + } +} diff --git a/oas-contract-tests/src/main/java/springfox/test/contract/oas/api/PetApi.java b/oas-contract-tests/src/main/java/springfox/test/contract/oas/api/PetApi.java new file mode 100644 index 00000000000..2b3648b2c28 --- /dev/null +++ b/oas-contract-tests/src/main/java/springfox/test/contract/oas/api/PetApi.java @@ -0,0 +1,302 @@ +/* + * + * * Copyright 2019-2020 the original author or authors. + * * + * * Licensed under the Apache License, Version 2.0 (the "License"); + * * you may not use this file except in compliance with the License. + * * You may obtain a copy of the License at + * * + * * https://www.apache.org/licenses/LICENSE-2.0 + * * + * * Unless required by applicable law or agreed to in writing, software + * * distributed under the License is distributed on an "AS IS" BASIS, + * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * * See the License for the specific language governing permissions and + * * limitations under the License. + * + */ + +/** + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech) (3.0.0). + * https://openapi-generator.tech + * Do not edit the class manually. + */ +package springfox.test.contract.oas.api; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.enums.Explode; +import io.swagger.v3.oas.annotations.enums.ParameterIn; +import io.swagger.v3.oas.annotations.enums.ParameterStyle; +import io.swagger.v3.oas.annotations.enums.SecuritySchemeType; +import io.swagger.v3.oas.annotations.media.ArraySchema; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; +import io.swagger.v3.oas.annotations.security.OAuthFlow; +import io.swagger.v3.oas.annotations.security.OAuthFlows; +import io.swagger.v3.oas.annotations.security.OAuthScope; +import io.swagger.v3.oas.annotations.security.SecurityRequirement; +import io.swagger.v3.oas.annotations.security.SecurityScheme; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.data.domain.Pageable; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestHeader; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RequestPart; +import org.springframework.web.multipart.MultipartFile; +import springfox.test.contract.oas.model.ModelApiResponse; +import springfox.test.contract.oas.model.Pet; + +import javax.validation.Valid; +import javax.validation.constraints.NotNull; + +@SecurityScheme(name = "petstore_auth", + type = SecuritySchemeType.OAUTH2, + flows = @OAuthFlows(implicit = @OAuthFlow(authorizationUrl = "https://petstore3.swagger" + + ".io/oauth/authorize", + scopes = { + @OAuthScope(name = "write:pets", + description = "modify pets in your account"), + @OAuthScope(name = "read:pets", + description = "read your pets") }))) +@Tag(name = "pet", description = "the pet API") +public interface PetApi { + + default PetApiDelegate getDelegate() { + return new PetApiDelegate() { + }; + } + + @Operation(summary = "Add a new pet to the store", description = "Add a new pet to the store", security = { + @SecurityRequirement(name = "petstore_auth", + scopes = { + "write:pets", + "read:pets" }) }, tags = { "pet" }) + @ApiResponses(value = { + @ApiResponse(responseCode = "200", + description = "Successful operation", + content = { + @Content(mediaType = "application/xml", + schema = @Schema(implementation = + Pet.class)), + @Content( + mediaType = "application/json", + schema = @Schema(implementation = Pet.class)) }), + @ApiResponse(responseCode = "405", description = "Invalid input") + }) + @PostMapping(value = "/pet", + consumes = { + "application/json", + "application/xml", + "application/x-www-form-urlencoded" }) + default void addPet( + @Parameter(description = "Create a new pet in the store", + required = true) @Valid @RequestBody Pet pet) { + // return getDelegate().addPet(pet); + } + + @Operation(summary = "Deletes a pet", description = "", security = { + @SecurityRequirement(name = "petstore_auth", + scopes = { + "write:pets", + "read:pets" }) }, tags = { "pet" }) + @ApiResponses(value = { @ApiResponse(responseCode = "400", description = "Invalid pet value") }) + @DeleteMapping(value = "/pet/{petId}") + default ResponseEntity deletePet( + @Parameter(description = "Pet id to delete", required = true) @PathVariable("petId") Long petId, + @Parameter(description = "") @RequestHeader(value = "api_key", required = false) String apiKey) { + return getDelegate().deletePet(petId, apiKey); + } + + @Operation(summary = "Finds Pets by status", + description = "Multiple status values can be provided with comma separated strings", + security = { + @SecurityRequirement(name = "petstore_auth", + scopes = { + "write:pets", + "read:pets" }) }, + tags = { "pet" }) + @ApiResponses(value = { + @ApiResponse(responseCode = "200", + description = "successful operation", + content = @Content(array = @ArraySchema(schema = @Schema( + implementation = Pet.class)))), + @ApiResponse(responseCode = "400", description = "Invalid status value") }) + @GetMapping(value = "/pet/findByStatus", + produces = { + "application/xml", + "application/json" }) + default ResponseEntity> findPetsByStatus( + @Parameter(explode = Explode.TRUE, + name = "status", + in = ParameterIn.QUERY, + description = "Status values that need to be considered for filter", + style = ParameterStyle.FORM, + schema = @Schema(type = "string", + defaultValue = "available", + allowableValues = { + "available", + "pending", + "sold" })) @Valid @RequestParam( + value = "status", + required = false) java.util.List status) { + return getDelegate().findPetsByStatus(status); + } + + @Operation(summary = "Finds Pets by tags", + description = "Multiple tags can be provided with comma separated strings. Use tag1, tag2, tag3 for " + + "testing.", + security = { + @SecurityRequirement(name = "petstore_auth", + scopes = { + "write:pets", + "read:pets" }) }, + tags = { "pet" }) + @ApiResponses(value = { + @ApiResponse(responseCode = "200", + description = "successful operation", + content = @Content(array = @ArraySchema(schema = @Schema( + implementation = Pet.class)))), + @ApiResponse(responseCode = "400", description = "Invalid tag value", content = @Content) }) + @GetMapping(value = "/pet/findByTags", + produces = { + "application/xml", + "application/json" }) + default ResponseEntity> findPetsByTags( + @Parameter(description = "Tags to filter by", + explode = Explode.TRUE, + in = ParameterIn.QUERY, + name = "tags", + style = ParameterStyle.FORM) @Valid + @RequestParam(value = "tags", + required = false) java.util.List tags) { + return getDelegate().findPetsByTags(tags); + } + + @Operation(summary = "Find pet by ID", description = "Returns a single pet", security = { + @SecurityRequirement(name = "api_key"), + @SecurityRequirement(name = "petstore_auth", + scopes = { + "write:pets", + "read:pets" }) + }, tags = { "pet" }) + @ApiResponses(value = { + @ApiResponse(responseCode = "200", + description = "successful operation", + content = @Content(schema = + @Schema(implementation = Pet.class))), + @ApiResponse(responseCode = "400", description = "Invalid ID supplied", content = @Content), + @ApiResponse(responseCode = "404", description = "Pet not found", content = @Content) }) + @GetMapping(value = "/pet/{petId}", + produces = { + "application/xml", + "application/json" }) + default ResponseEntity getPetById( + @Parameter(description = "ID of pet to return", required = true) @PathVariable("petId") Long petId) { + return getDelegate().getPetById(petId); + } + + @Operation(summary = "Update an existing pet", + description = "Update an existing pet by Id", + operationId = "updatePet", + security = { + @SecurityRequirement(name = "petstore_auth", + scopes = { + "write:pets", + "read:pets" }) }, + tags = { "pet" }) + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "Successful operation", + content = + { + @Content(mediaType = "application/xml", + schema = @Schema(implementation = Pet.class)), + @Content( + mediaType = "application/json", + schema = @Schema(implementation = Pet.class)) } + ), + @ApiResponse(responseCode = "400", description = "Invalid ID supplied"), + @ApiResponse(responseCode = "404", description = "Pet not found"), + @ApiResponse(responseCode = "405", description = "Validation exception") }) + @PutMapping(value = "/pet", + consumes = { + "application/json", + "application/xml", + "application/x-www-form-urlencoded" }) + default ResponseEntity updatePet( + @Parameter(description = "Update an existent pet in the store", + required = true) @Valid @RequestBody Pet pet) { + return getDelegate().updatePet(pet); + } + + @Operation(summary = "Updates a pet in the store with form data", description = "", security = { + @SecurityRequirement(name = "petstore_auth", + scopes = { + "write:pets", + "read:pets" }) }, tags = { "pet" }) + @ApiResponses(value = { @ApiResponse(responseCode = "405", description = "Invalid input") }) + @PostMapping(value = "/pet/{petId}", consumes = { "application/x-www-form-urlencoded" }) + default ResponseEntity updatePetWithForm( + @Parameter(description = "ID of pet that needs to be updated", required = true) + @PathVariable("petId") Long petId, + @Parameter(description = "Name of pet that needs to be updated") + @RequestParam(value = "name", required = false) String name, + @Parameter(description = "Status of pet that needs to be updated") + @RequestParam(value = "status", required = false) String status) { + return getDelegate().updatePetWithForm(petId, name, status); + } + + @Operation(summary = "uploads an image", security = { + @SecurityRequirement(name = "petstore_auth", + scopes = { + "write:pets", + "read:pets" }) }, tags = { "pet" }) + @ApiResponses(value = { + @ApiResponse(responseCode = "200", + description = "successful operation", + content = @Content(schema = @Schema(implementation = + ModelApiResponse.class))) }) + @PostMapping(value = "/pet/{petId}/uploadImage", produces = { "application/json" }, consumes = { + "application/octet-stream" }) + default ResponseEntity uploadFile( + @Parameter(description = "ID of pet to update", required = true) @PathVariable("petId") Long petId, + @Parameter(description = "Additional Metadata") @RequestParam(value = "additionalMetadata", + required = false) String additionalMetadata, + @io.swagger.v3.oas.annotations.parameters.RequestBody( + content = @Content(mediaType = "application/octet-stream", + schema = + @Schema( + type = "string", + format = "binary"))) @Valid @RequestPart( + "file") MultipartFile file) { + return getDelegate().uploadFile(petId, additionalMetadata, file); + } + + @Operation(summary = "Get all Pets paged", description = "Get all Pets paged", security = { + @SecurityRequirement(name = "petstore_auth", + scopes = { + "write:pets", + "read:pets" }) }, tags = { "pet" }) + @ApiResponses(value = { + @ApiResponse(responseCode = "200", + description = "successful operation", + content = @Content(array = @ArraySchema(schema = @Schema( + implementation = Pet.class)))) + }) + @GetMapping(value = "/pet", + produces = { + "application/xml", + "application/json" }) + default ResponseEntity> getAllPets(@NotNull Pageable pageable) { + return getDelegate().getAllPets(pageable); + } + +} diff --git a/oas-contract-tests/src/main/java/springfox/test/contract/oas/api/PetApiController.java b/oas-contract-tests/src/main/java/springfox/test/contract/oas/api/PetApiController.java new file mode 100644 index 00000000000..3dce9f4f318 --- /dev/null +++ b/oas-contract-tests/src/main/java/springfox/test/contract/oas/api/PetApiController.java @@ -0,0 +1,46 @@ +/* + * + * * Copyright 2019-2020 the original author or authors. + * * + * * Licensed under the Apache License, Version 2.0 (the "License"); + * * you may not use this file except in compliance with the License. + * * You may obtain a copy of the License at + * * + * * https://www.apache.org/licenses/LICENSE-2.0 + * * + * * Unless required by applicable law or agreed to in writing, software + * * distributed under the License is distributed on an "AS IS" BASIS, + * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * * See the License for the specific language governing permissions and + * * limitations under the License. + * + */ + +package springfox.test.contract.oas.api; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.Optional; + +@javax.annotation.Generated(value = "org.springdoc.demo.app2.codegen.languages.SpringCodegen", + date = "2019-07-11T00:09:29.839+02:00[Europe/Paris]") + +@RestController +@RequestMapping("${openapi.openAPIPetstore.base-path:/}") +public class PetApiController implements PetApi { + + private final PetApiDelegate delegate; + + public PetApiController(@Autowired(required = false) PetApiDelegate delegate) { + this.delegate = Optional.ofNullable(delegate).orElse(new PetApiDelegate() { + }); + } + + @Override + public PetApiDelegate getDelegate() { + return delegate; + } + +} diff --git a/oas-contract-tests/src/main/java/springfox/test/contract/oas/api/PetApiDelegate.java b/oas-contract-tests/src/main/java/springfox/test/contract/oas/api/PetApiDelegate.java new file mode 100644 index 00000000000..812e4a01210 --- /dev/null +++ b/oas-contract-tests/src/main/java/springfox/test/contract/oas/api/PetApiDelegate.java @@ -0,0 +1,162 @@ +/* + * + * * Copyright 2019-2020 the original author or authors. + * * + * * Licensed under the Apache License, Version 2.0 (the "License"); + * * you may not use this file except in compliance with the License. + * * You may obtain a copy of the License at + * * + * * https://www.apache.org/licenses/LICENSE-2.0 + * * + * * Unless required by applicable law or agreed to in writing, software + * * distributed under the License is distributed on an "AS IS" BASIS, + * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * * See the License for the specific language governing permissions and + * * limitations under the License. + * + */ + +package springfox.test.contract.oas.api; + +import org.springframework.data.domain.Pageable; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.context.request.NativeWebRequest; +import org.springframework.web.multipart.MultipartFile; +import springfox.test.contract.oas.model.ModelApiResponse; +import springfox.test.contract.oas.model.Pet; + +import javax.validation.constraints.NotNull; +import java.util.Optional; + +/** + * A delegate to be called by the {@link PetApiController}}. + * Implement this interface with a {@link org.springframework.stereotype.Service} annotated class. + */ +@javax.annotation.Generated(value = "org.springdoc.demo.app2.codegen.languages.SpringCodegen", + date = "2019-07-11T00:09:29.839+02:00[Europe/Paris]") + +public interface PetApiDelegate { + + default Optional getRequest() { + return Optional.empty(); + } + + /** + * @see PetApi#addPet + */ + default void addPet(Pet pet) { + + } + + /** + * @see PetApi#deletePet + */ + default ResponseEntity deletePet( + Long petId, + String apiKey) { + return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED); + + } + + /** + * @see PetApi#findPetsByStatus + */ + default ResponseEntity> findPetsByStatus(java.util.List status) { + extract(); + return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED); + + } + + default void extract() { + getRequest().ifPresent(request -> { + for (org.springframework.http.MediaType mediaType : org.springframework.http.MediaType + .parseMediaTypes(request.getHeader("Accept"))) { + if (mediaType.isCompatibleWith(org.springframework.http.MediaType.valueOf("application/json"))) { + ApiUtil.setExampleResponse( + request, + "application/json", + "{ \"photoUrls\" : [ \"photoUrls\", \"photoUrls\" ], \"name\" : \"doggie\", \"id\" : 0, " + + "\"category\" : { \"name\" : \"name\", \"id\" : 6 }, \"tags\" : [ { \"name\" : " + + "\"name\", \"id\" : 1 }, { \"name\" : \"name\", \"id\" : 1 } ], \"status\" : " + + "\"available\"}"); + break; + } + if (mediaType.isCompatibleWith(org.springframework.http.MediaType.valueOf("application/xml"))) { + ApiUtil.setExampleResponse( + request, + "application/xml", + " 123456789 doggie aeiou " + + " aeiou"); + break; + } + } + }); + } + + /** + * @see PetApi#findPetsByTags + */ + default ResponseEntity> findPetsByTags(java.util.List tags) { + extract(); + return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED); + + } + + /** + * @see PetApi#getPetById + */ + default ResponseEntity getPetById(Long petId) { + extract(); + return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED); + + } + + /** + * @see PetApi#updatePet(Pet) + */ + default ResponseEntity updatePet(Pet pet) { + return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED); + + } + + /** + * @see PetApi#updatePetWithForm(Long, String, String) + */ + default ResponseEntity updatePetWithForm( + Long petId, + String name, + String status) { + return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED); + + } + + /** + * @see PetApi#uploadFile(Long, String, MultipartFile) + * + */ + default ResponseEntity uploadFile( + Long petId, + String additionalMetadata, + @javax.validation.Valid MultipartFile file) { + getRequest().ifPresent(request -> { + for (org.springframework.http.MediaType mediaType : org.springframework.http.MediaType + .parseMediaTypes(request.getHeader("Accept"))) { + if (mediaType.isCompatibleWith(org.springframework.http.MediaType.valueOf("application/json"))) { + ApiUtil.setExampleResponse( + request, + "application/json", + "{ \"code\" : 0, \"type\" : \"type\", \"message\" : \"message\"}"); + break; + } + } + }); + return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED); + + } + + default ResponseEntity> getAllPets(@NotNull Pageable pageable) { + return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED); + } + +} diff --git a/oas-contract-tests/src/main/java/springfox/test/contract/oas/api/PetApiDelegateImpl.java b/oas-contract-tests/src/main/java/springfox/test/contract/oas/api/PetApiDelegateImpl.java new file mode 100644 index 00000000000..877a93a096c --- /dev/null +++ b/oas-contract-tests/src/main/java/springfox/test/contract/oas/api/PetApiDelegateImpl.java @@ -0,0 +1,282 @@ +/* + * + * * Copyright 2019-2020 the original author or authors. + * * + * * Licensed under the Apache License, Version 2.0 (the "License"); + * * you may not use this file except in compliance with the License. + * * You may obtain a copy of the License at + * * + * * https://www.apache.org/licenses/LICENSE-2.0 + * * + * * Unless required by applicable law or agreed to in writing, software + * * distributed under the License is distributed on an "AS IS" BASIS, + * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * * See the License for the specific language governing permissions and + * * limitations under the License. + * + */ + +package springfox.test.contract.oas.api; + +import org.apache.tomcat.util.http.fileupload.IOUtils; +import org.springframework.data.domain.Pageable; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Service; +import org.springframework.util.StringUtils; +import org.springframework.web.context.request.NativeWebRequest; +import org.springframework.web.multipart.MultipartFile; +import org.springframework.web.server.ResponseStatusException; +import springfox.test.contract.oas.model.Category; +import springfox.test.contract.oas.model.ModelApiResponse; +import springfox.test.contract.oas.model.Pet; +import springfox.test.contract.oas.model.Tag; +import springfox.test.contract.oas.repository.PetRepository; + +import javax.annotation.PostConstruct; +import javax.validation.constraints.NotNull; +import java.io.FileOutputStream; +import java.util.Arrays; +import java.util.Optional; +import java.util.concurrent.atomic.AtomicLong; +import java.util.stream.Collectors; + +@Service +public class PetApiDelegateImpl implements PetApiDelegate { + + private final PetRepository petRepository; + + private final NativeWebRequest request; + + public PetApiDelegateImpl( + PetRepository petRepository, + NativeWebRequest request) { + this.petRepository = petRepository; + this.request = request; + } + + private static Pet createPet( + long id, + Category category, + String name, + String[] urls, + String[] tags, + Pet.StatusEnum status) { + Pet pet = new Pet().id(id).category(category).name(name).status(status); + + if (null != urls) { + pet.setPhotoUrls(Arrays.asList(urls)); + } + + final AtomicLong i = new AtomicLong(0); + if (null != tags && tags.length > 0) { + Arrays.stream(tags).map(tag -> new Tag().name(tag).id(i.incrementAndGet())).forEach(pet::addTagsItem); + } + return pet; + } + + @PostConstruct + private void initPets() { + Category dogs = new Category().id(1L).name("Dogs"); + Category cats = new Category().id(2L).name("Cats"); + Category rabbits = new Category().id(3L).name("Rabbits"); + Category lions = new Category().id(4L).name("Lions"); + + petRepository.save(createPet( + 1, + cats, + "Cat 1", + new String[] { + "url1", + "url2" }, + new String[] { + "tag1", + "tag2" }, + Pet.StatusEnum.AVAILABLE)); + petRepository.save(createPet( + 2, + cats, + "Cat 2", + new String[] { + "url1", + "url2" }, + new String[] { + "tag2", + "tag3" }, + Pet.StatusEnum.AVAILABLE)); + petRepository.save(createPet( + 3, + cats, + "Cat 3", + new String[] { + "url1", + "url2" }, + new String[] { + "tag3", + "tag4" }, + Pet.StatusEnum.PENDING)); + + petRepository.save(createPet( + 4, + dogs, + "Dog 1", + new String[] { + "url1", + "url2" }, + new String[] { + "tag1", + "tag2" }, + Pet.StatusEnum.AVAILABLE)); + petRepository.save(createPet( + 5, + dogs, + "Dog 2", + new String[] { + "url1", + "url2" }, + new String[] { + "tag2", + "tag3" }, + Pet.StatusEnum.SOLD)); + petRepository.save(createPet( + 6, + dogs, + "Dog 3", + new String[] { + "url1", + "url2" }, + new String[] { + "tag3", + "tag4" }, + Pet.StatusEnum.PENDING)); + + petRepository.save(createPet( + 7, + lions, + "Lion 1", + new String[] { + "url1", + "url2" }, + new String[] { + "tag1", + "tag2" }, + Pet.StatusEnum.AVAILABLE)); + petRepository.save(createPet( + 8, + lions, + "Lion 2", + new String[] { + "url1", + "url2" }, + new String[] { + "tag2", + "tag3" }, + Pet.StatusEnum.AVAILABLE)); + petRepository.save(createPet( + 9, + lions, + "Lion 3", + new String[] { + "url1", + "url2" }, + new String[] { + "tag3", + "tag4" }, + Pet.StatusEnum.AVAILABLE)); + + petRepository.save(createPet( + 10, + rabbits, + "Rabbit 1", + new String[] { + "url1", + "url2" }, + new String[] { + "tag3", + "tag4" }, + Pet.StatusEnum.AVAILABLE)); + } + + @Override + public void addPet(Pet pet) { + petRepository.save(pet); + // return ResponseEntity.ok().build(); + } + + @Override + public ResponseEntity deletePet( + Long petId, + String apiKey) { + petRepository.deleteById(petId); + return ResponseEntity.ok().build(); + } + + @Override + public ResponseEntity> findPetsByStatus(java.util.List statusList) { + java.util.List statusEnums = + statusList.stream() + .map(s -> Optional.ofNullable(Pet.StatusEnum.fromValue(s)) + .orElseThrow(() -> new ResponseStatusException( + HttpStatus.BAD_REQUEST, + "Invalid status: " + s))) + .collect(Collectors.toList()); + return ResponseEntity.ok(petRepository.findPetsByStatus(statusEnums)); + } + + @Override + public ResponseEntity> findPetsByTags(java.util.List tags) { + return ResponseEntity.ok(petRepository.findPetsByTags(tags)); + } + + @Override + public ResponseEntity getPetById(Long petId) { + ApiUtil.checkApiKey(request); + return petRepository.findById(petId).map(ResponseEntity::ok) + .orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND)); + } + + @Override + public ResponseEntity updatePet(Pet pet) { + return null; + // return addPet(pet); + } + + @Override + public ResponseEntity updatePetWithForm( + Long petId, + String name, + String status) { + Pet pet = petRepository.findById(petId).orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND)); + if (!StringUtils.isEmpty(name)) { + pet.name(name); + } + if (!StringUtils.isEmpty(name)) { + pet.setStatus(Pet.StatusEnum.fromValue(status)); + } + // return addPet(pet); + return null; + } + + @Override + public ResponseEntity uploadFile( + Long petId, + String additionalMetadata, + MultipartFile file) { + try { + String uploadedFileLocation = "./" + file.getName(); + IOUtils.copy(file.getInputStream(), new FileOutputStream(uploadedFileLocation)); + String msg = String.format("additionalMetadata: %s\nFile uploaded to %s, %d bytes", additionalMetadata, + uploadedFileLocation, (new java.io.File(uploadedFileLocation)).length()); + ModelApiResponse output = new ModelApiResponse().code(200).message(msg); + return ResponseEntity.ok(output); + } catch (Exception e) { + throw new ResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR, "Couldn't upload file", e); + } + } + + public ResponseEntity> getAllPets(@NotNull Pageable pageable) { + ApiUtil.checkApiKey(request); + return new ResponseEntity>(petRepository.findAll(pageable), HttpStatus.OK); + } + +} diff --git a/oas-contract-tests/src/main/java/springfox/test/contract/oas/api/StoreApi.java b/oas-contract-tests/src/main/java/springfox/test/contract/oas/api/StoreApi.java new file mode 100644 index 00000000000..8956700a839 --- /dev/null +++ b/oas-contract-tests/src/main/java/springfox/test/contract/oas/api/StoreApi.java @@ -0,0 +1,130 @@ +/* + * + * * Copyright 2019-2020 the original author or authors. + * * + * * Licensed under the Apache License, Version 2.0 (the "License"); + * * you may not use this file except in compliance with the License. + * * You may obtain a copy of the License at + * * + * * https://www.apache.org/licenses/LICENSE-2.0 + * * + * * Unless required by applicable law or agreed to in writing, software + * * distributed under the License is distributed on an "AS IS" BASIS, + * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * * See the License for the specific language governing permissions and + * * limitations under the License. + * + */ + +/** + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech) (3.0.0). + * https://openapi-generator.tech + * Do not edit the class manually. + */ +package springfox.test.contract.oas.api; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; +import io.swagger.v3.oas.annotations.security.SecurityRequirement; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import springfox.test.contract.oas.model.Order; + +import javax.validation.Valid; +import javax.validation.constraints.Max; + +@javax.annotation.Generated(value = "org.springdoc.demo.app2.codegen.languages.SpringCodegen", + date = "2019-07-11T00:09:29.839+02:00[Europe/Paris]") + +@Tag(name = "store", description = "the store API") +public interface StoreApi { + + default StoreApiDelegate getDelegate() { + return new StoreApiDelegate() { + }; + } + + @Operation(summary = "Delete purchase order by ID", + description = "For valid response try integer IDs with value < 1000. Anything above 1000 or nonintegers " + + "will generate API errors", + tags = { "store" }) + @ApiResponses(value = { + @ApiResponse(responseCode = "400", description = "Invalid ID supplied"), + @ApiResponse(responseCode = "404", description = "Order not found") }) + @DeleteMapping(value = "/store/order/{orderId}") + default ResponseEntity deleteOrder( + @Parameter(description = "ID of the order that needs to be deleted", + required = true, + schema = @Schema(type = "integer", + format = "int64")) @PathVariable("orderId") Long orderId) { + return getDelegate().deleteOrder(orderId); + } + + @Operation(summary = "Returns pet inventories by status", + description = "Returns a map of status codes to quantities", + security = { + @SecurityRequirement(name = "api_key") }, + tags = { "store" }) + @ApiResponses(value = { + @ApiResponse(responseCode = "200", + description = "successful operation", + content = @Content(schema = @Schema(type = "object"))) }) + @GetMapping(value = "/store/inventory", produces = { "application/json" }) + default ResponseEntity> getInventory() { + return getDelegate().getInventory(); + } + + @Operation(summary = "Find purchase order by ID", + description = "For valid response try integer IDs with value <= 5 or > 10. Other values will generated " + + "exceptions", + tags = { "store" }) + @ApiResponses(value = { + @ApiResponse(responseCode = "200", + description = "successful operation", + content = @Content(schema = @Schema(implementation = + Order.class))), + @ApiResponse(responseCode = "400", description = "Invalid ID supplied", content = @Content), + @ApiResponse(responseCode = "404", description = "Order not found", content = @Content) + }) + @GetMapping(value = "/store/order/{orderId}", + produces = { + "application/xml", + "application/json" }) + default ResponseEntity getOrderById( + @javax.validation.constraints.Min(1L) @Max(5L) + @Parameter(description = "ID of " + + "order that needs to be fetched", required = true) @PathVariable( + "orderId") Long orderId) { + return getDelegate().getOrderById(orderId); + } + + @Operation(summary = "Place an order for a pet", description = "Place a new order in the store", tags = { "store" }) + @ApiResponses(value = { + @ApiResponse(responseCode = "200", + description = "successful operation", + content = @Content(schema = @Schema(implementation = + Order.class))), + @ApiResponse(responseCode = "405", description = "Invalid input", content = @Content) + }) + @PostMapping(value = "/store/order", + produces = { "application/json" }, + consumes = { + "application/xml", + "application/json", + "application/x-www-form-urlencoded" }) + default ResponseEntity placeOrder( + @io.swagger.v3.oas.annotations.parameters.RequestBody(description = "") + @Valid @RequestBody Order order) { + return getDelegate().placeOrder(order); + } + +} diff --git a/oas-contract-tests/src/main/java/springfox/test/contract/oas/api/StoreApiController.java b/oas-contract-tests/src/main/java/springfox/test/contract/oas/api/StoreApiController.java new file mode 100644 index 00000000000..98baba7a985 --- /dev/null +++ b/oas-contract-tests/src/main/java/springfox/test/contract/oas/api/StoreApiController.java @@ -0,0 +1,46 @@ +/* + * + * * Copyright 2019-2020 the original author or authors. + * * + * * Licensed under the Apache License, Version 2.0 (the "License"); + * * you may not use this file except in compliance with the License. + * * You may obtain a copy of the License at + * * + * * https://www.apache.org/licenses/LICENSE-2.0 + * * + * * Unless required by applicable law or agreed to in writing, software + * * distributed under the License is distributed on an "AS IS" BASIS, + * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * * See the License for the specific language governing permissions and + * * limitations under the License. + * + */ + +package springfox.test.contract.oas.api; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.Optional; + +@javax.annotation.Generated(value = "org.springdoc.demo.app2.codegen.languages.SpringCodegen", + date = "2019-07-11T00:09:29.839+02:00[Europe/Paris]") + +@RestController +@RequestMapping("${openapi.openAPIPetstore.base-path:/}") +public class StoreApiController implements StoreApi { + + private final StoreApiDelegate delegate; + + public StoreApiController(@Autowired(required = false) StoreApiDelegate delegate) { + this.delegate = Optional.ofNullable(delegate).orElse(new StoreApiDelegate() { + }); + } + + @Override + public StoreApiDelegate getDelegate() { + return delegate; + } + +} diff --git a/oas-contract-tests/src/main/java/springfox/test/contract/oas/api/StoreApiDelegate.java b/oas-contract-tests/src/main/java/springfox/test/contract/oas/api/StoreApiDelegate.java new file mode 100644 index 00000000000..225fce13af4 --- /dev/null +++ b/oas-contract-tests/src/main/java/springfox/test/contract/oas/api/StoreApiDelegate.java @@ -0,0 +1,100 @@ +/* + * + * * Copyright 2019-2020 the original author or authors. + * * + * * Licensed under the Apache License, Version 2.0 (the "License"); + * * you may not use this file except in compliance with the License. + * * You may obtain a copy of the License at + * * + * * https://www.apache.org/licenses/LICENSE-2.0 + * * + * * Unless required by applicable law or agreed to in writing, software + * * distributed under the License is distributed on an "AS IS" BASIS, + * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * * See the License for the specific language governing permissions and + * * limitations under the License. + * + */ + +package springfox.test.contract.oas.api; + +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.context.request.NativeWebRequest; +import springfox.test.contract.oas.model.Order; + +import java.util.Optional; + +/** + * A delegate to be called by the {@link StoreApiController}}. + * Implement this interface with a {@link org.springframework.stereotype.Service} annotated class. + */ +@javax.annotation.Generated(value = "org.springdoc.demo.app2.codegen.languages.SpringCodegen", + date = "2019-07-11T00:09:29.839+02:00[Europe/Paris]") + +public interface StoreApiDelegate { + + default Optional getRequest() { + return Optional.empty(); + } + + /** + * @see StoreApi#deleteOrder + */ + default ResponseEntity deleteOrder(Long orderId) { + return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED); + + } + + /** + * @see StoreApi#getInventory + */ + default ResponseEntity> getInventory() { + return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED); + + } + + /** + * @see StoreApi#getOrderById + */ + default ResponseEntity getOrderById(Long orderId) { + extract(); + return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED); + + } + + default void extract() { + getRequest().ifPresent(request -> { + for (org.springframework.http.MediaType mediaType : org.springframework.http.MediaType + .parseMediaTypes(request.getHeader("Accept"))) { + if (mediaType.isCompatibleWith(org.springframework.http.MediaType.valueOf("application/json"))) { + ApiUtil.setExampleResponse( + request, + "application/json", + "{ \"petId\" : 6, \"quantity\" : 1, \"id\" : 0, \"shipDate\" : \"2000-01-23T04:56:07.000+00:00\", " + + "\"complete\" : false, \"status\" : \"placed\"}"); + break; + } + if (mediaType.isCompatibleWith(org.springframework.http.MediaType.valueOf("application/xml"))) { + ApiUtil.setExampleResponse( + request, + "application/xml", + " 123456789 123456789 123 " + + "2000-01-23T04:56:07.000Z aeiou " + + "true"); + break; + } + } + }); + } + + /** + * @see StoreApi#placeOrder + */ + default ResponseEntity placeOrder(Order order) { + extract(); + return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED); + + } + +} diff --git a/oas-contract-tests/src/main/java/springfox/test/contract/oas/api/StoreApiDelegateImpl.java b/oas-contract-tests/src/main/java/springfox/test/contract/oas/api/StoreApiDelegateImpl.java new file mode 100644 index 00000000000..a0ee957c377 --- /dev/null +++ b/oas-contract-tests/src/main/java/springfox/test/contract/oas/api/StoreApiDelegateImpl.java @@ -0,0 +1,103 @@ +/* + * + * * Copyright 2019-2020 the original author or authors. + * * + * * Licensed under the Apache License, Version 2.0 (the "License"); + * * you may not use this file except in compliance with the License. + * * You may obtain a copy of the License at + * * + * * https://www.apache.org/licenses/LICENSE-2.0 + * * + * * Unless required by applicable law or agreed to in writing, software + * * distributed under the License is distributed on an "AS IS" BASIS, + * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * * See the License for the specific language governing permissions and + * * limitations under the License. + * + */ + +package springfox.test.contract.oas.api; + +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Service; +import org.springframework.web.context.request.NativeWebRequest; +import org.springframework.web.server.ResponseStatusException; +import springfox.test.contract.oas.model.Order; +import springfox.test.contract.oas.repository.OrderRepository; +import springfox.test.contract.oas.repository.PetRepository; + +import javax.annotation.PostConstruct; +import java.util.Date; + +@Service +public class StoreApiDelegateImpl implements StoreApiDelegate { + + private final OrderRepository orderRepository; + + @SuppressWarnings("unused") + private final PetRepository petRepository; + + private final NativeWebRequest request; + + public StoreApiDelegateImpl( + OrderRepository orderRepository, + PetRepository petRepository, + NativeWebRequest request) { + this.orderRepository = orderRepository; + this.petRepository = petRepository; + this.request = request; + } + + private static Order createOrder( + long id, + long petId, + Order.StatusEnum status) { + return new Order() + .id(id) + .petId(petId) + .quantity(2) + .shipDate(new Date()) + .status(status); + } + + @PostConstruct + void initOrders() { + orderRepository.save(createOrder(1, 1, Order.StatusEnum.PLACED)); + orderRepository.save(createOrder(2, 1, Order.StatusEnum.DELIVERED)); + orderRepository.save(createOrder(3, 2, Order.StatusEnum.PLACED)); + orderRepository.save(createOrder(4, 2, Order.StatusEnum.DELIVERED)); + orderRepository.save(createOrder(5, 3, Order.StatusEnum.PLACED)); + orderRepository.save(createOrder(6, 3, Order.StatusEnum.PLACED)); + orderRepository.save(createOrder(7, 3, Order.StatusEnum.PLACED)); + orderRepository.save(createOrder(8, 3, Order.StatusEnum.PLACED)); + orderRepository.save(createOrder(9, 3, Order.StatusEnum.PLACED)); + orderRepository.save(createOrder(10, 3, Order.StatusEnum.PLACED)); + } + + @Override + public ResponseEntity deleteOrder(Long orderId) { + Order order = orderRepository.findById(orderId) + .orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND)); + orderRepository.delete(order); + return ResponseEntity.ok().build(); + } + + @Override + public ResponseEntity> getInventory() { + ApiUtil.checkApiKey(request); + return ResponseEntity.ok().build(); + } + + @Override + public ResponseEntity getOrderById(Long orderId) { + return orderRepository.findById(orderId) + .map(ResponseEntity::ok) + .orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND, "Order not found")); + } + + @Override + public ResponseEntity placeOrder(Order order) { + return ResponseEntity.ok(orderRepository.save(order)); + } +} diff --git a/oas-contract-tests/src/main/java/springfox/test/contract/oas/api/UserApi.java b/oas-contract-tests/src/main/java/springfox/test/contract/oas/api/UserApi.java new file mode 100644 index 00000000000..d062b98cdd1 --- /dev/null +++ b/oas-contract-tests/src/main/java/springfox/test/contract/oas/api/UserApi.java @@ -0,0 +1,201 @@ +/* + * + * * Copyright 2019-2020 the original author or authors. + * * + * * Licensed under the Apache License, Version 2.0 (the "License"); + * * you may not use this file except in compliance with the License. + * * You may obtain a copy of the License at + * * + * * https://www.apache.org/licenses/LICENSE-2.0 + * * + * * Unless required by applicable law or agreed to in writing, software + * * distributed under the License is distributed on an "AS IS" BASIS, + * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * * See the License for the specific language governing permissions and + * * limitations under the License. + * + */ + +/** + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech) (3.0.0). + * https://openapi-generator.tech + * Do not edit the class manually. + */ +package springfox.test.contract.oas.api; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.enums.Explode; +import io.swagger.v3.oas.annotations.enums.ParameterIn; +import io.swagger.v3.oas.annotations.enums.ParameterStyle; +import io.swagger.v3.oas.annotations.headers.Header; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestParam; +import springfox.test.contract.oas.model.User; + +import javax.validation.constraints.NotNull; + +@javax.annotation.Generated(value = "org.springdoc.demo.app2.codegen.languages.SpringCodegen", + date = "2019-07-11T00:09:29.839+02:00[Europe/Paris]") + +@Tag(name = "user", description = "the user API") +public interface UserApi { + + default UserApiDelegate getDelegate() { + return new UserApiDelegate() { + }; + } + + @Operation(summary = "Create user", description = "This can only be done by the logged in user.", tags = { "user" }) + @ApiResponses(value = { + @ApiResponse(description = "successful operation", + content = { + @Content(mediaType = "application/json", + schema = @Schema( + implementation = User.class)), + @Content(mediaType = "application/xml", + schema = + @Schema( + implementation = User.class)) }) }) + @PostMapping(value = "/user", + consumes = { + "application/json", + "application/xml", + "application/x-www-form-urlencoded" }) + default ResponseEntity createUser( + @Parameter(description = "Created user object") @javax.validation.Valid @RequestBody User user) { + return getDelegate().createUser(user); + } + + @Operation(summary = "Creates list of users with given input array", tags = { "user" }) + @ApiResponses(value = { @ApiResponse(responseCode = "200", description = "successful operation") }) + + @PostMapping(value = "/user/createWithArray", consumes = { "application/json" }) + default ResponseEntity createUsersWithArrayInput( + @Parameter(description = "List of user object", + required = true) @javax.validation.Valid @RequestBody java.util.List user) { + return getDelegate().createUsersWithArrayInput(user); + } + + @Operation(summary = "Creates list of users with given input array", + description = "Creates list of users with given input array", + tags = { "user" }) + @ApiResponses(value = { + @ApiResponse(responseCode = "200", + description = "Successful operation", + content = { + @Content(mediaType = "application/json", + schema = @Schema(implementation = + User.class)), + @Content( + mediaType = "application/xml", + schema = @Schema(implementation = User.class)) }), + @ApiResponse(description = "successful operation") + + }) + @PostMapping(value = "/user/createWithList", consumes = { "application/json" }) + default ResponseEntity createUsersWithListInput( + @Parameter @javax.validation.Valid @RequestBody java.util.List user) { + return getDelegate().createUsersWithListInput(user); + } + + @Operation(summary = "Delete user", description = "This can only be done by the logged in user.", tags = { "user" }) + @ApiResponses(value = { + @ApiResponse(responseCode = "400", description = "Invalid username supplied"), + @ApiResponse(responseCode = "404", description = "User not found") + }) + @DeleteMapping(value = "/user/{username}") + default ResponseEntity deleteUser( + @Parameter(description = "The name that needs to be deleted", + required = true) @PathVariable("username") String username) { + return getDelegate().deleteUser(username); + } + + @Operation(summary = "Get user by user name", tags = { "user" }) + @ApiResponses(value = { + @ApiResponse(responseCode = "200", + description = "successful operation", + content = { + @Content(mediaType = "application/json", + schema = @Schema(implementation = + User.class)), + @Content( + mediaType = "application/xml", + schema = @Schema(implementation = User.class)) }), + @ApiResponse(responseCode = "400", description = "Invalid username supplied", content = @Content), + @ApiResponse(responseCode = "404", description = "User not found", content = @Content) }) + + @GetMapping(value = "/user/{username}") + default ResponseEntity getUserByName( + @Parameter(description = "The name that needs to be fetched. Use user1 for testing. ", + required = true) @PathVariable("username") String username) { + return getDelegate().getUserByName(username); + } + + @Operation(summary = "Logs user into the system", tags = { "user" }) + @ApiResponses(value = { + @ApiResponse(responseCode = "200", + headers = { + @Header(name = "X-Rate-Limit", + description = "calls per hour allowed by the user", + schema = @Schema(type = "integer", + format = "int32")), + @Header(name = "X-Expires-After", + description = "date in UTC when toekn expires", + schema = @Schema(type = "string", + format = "date-time")) }, + description = "successful operation", + content = @Content(schema = @Schema(implementation = + String.class))), + @ApiResponse(responseCode = "400", description = "Invalid username/password supplied", content = @Content) }) + @GetMapping(value = "/user/login", + produces = { + "application/xml", + "application/json" }) + default ResponseEntity loginUser( + @NotNull @Parameter(description = "The user name for login", + required = false) @javax.validation.Valid @RequestParam(value = "username", + required = false) String username, + @NotNull @Parameter(description = "The password for login in clear text", + required = false) @javax.validation.Valid @RequestParam(value = "password", + required = false) String password) { + return getDelegate().loginUser(username, password); + } + + @Operation(summary = "Logs out current logged in user session", tags = { "user" }) + @ApiResponses(value = { @ApiResponse(description = "successful operation") }) + @GetMapping(value = "/user/logout") + default ResponseEntity logoutUser() { + return getDelegate().logoutUser(); + } + + @Operation(summary = "Update user", description = "This can only be done by the logged in user.", tags = { "user" }) + @ApiResponses(value = @ApiResponse(description = "successful operation")) + @PutMapping(value = "/user/{username}", consumes = { + "application/json", + "application/xml", + "application/x-www-form-urlencoded" }) + default ResponseEntity updateUser( + @Parameter(description = "name that need to be deleted", + required = true, + explode = Explode.FALSE, + in = ParameterIn.PATH, + name = "username", + style = ParameterStyle.SIMPLE, + schema = @Schema(type = "string")) @PathVariable("username") String username, + @Parameter(description = "Update an existent user in the store") @javax.validation.Valid @RequestBody User user) { + return getDelegate().updateUser(username, user); + } + +} diff --git a/oas-contract-tests/src/main/java/springfox/test/contract/oas/api/UserApiController.java b/oas-contract-tests/src/main/java/springfox/test/contract/oas/api/UserApiController.java new file mode 100644 index 00000000000..67c299a35e2 --- /dev/null +++ b/oas-contract-tests/src/main/java/springfox/test/contract/oas/api/UserApiController.java @@ -0,0 +1,46 @@ +/* + * + * * Copyright 2019-2020 the original author or authors. + * * + * * Licensed under the Apache License, Version 2.0 (the "License"); + * * you may not use this file except in compliance with the License. + * * You may obtain a copy of the License at + * * + * * https://www.apache.org/licenses/LICENSE-2.0 + * * + * * Unless required by applicable law or agreed to in writing, software + * * distributed under the License is distributed on an "AS IS" BASIS, + * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * * See the License for the specific language governing permissions and + * * limitations under the License. + * + */ + +package springfox.test.contract.oas.api; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.Optional; + +@javax.annotation.Generated(value = "org.springdoc.demo.app2.codegen.languages.SpringCodegen", + date = "2019-07-11T00:09:29.839+02:00[Europe/Paris]") + +@RestController +@RequestMapping("${openapi.openAPIPetstore.base-path:/}") +public class UserApiController implements UserApi { + + private final UserApiDelegate delegate; + + public UserApiController(@Autowired(required = false) UserApiDelegate delegate) { + this.delegate = Optional.ofNullable(delegate).orElse(new UserApiDelegate() { + }); + } + + @Override + public UserApiDelegate getDelegate() { + return delegate; + } + +} diff --git a/oas-contract-tests/src/main/java/springfox/test/contract/oas/api/UserApiDelegate.java b/oas-contract-tests/src/main/java/springfox/test/contract/oas/api/UserApiDelegate.java new file mode 100644 index 00000000000..ef7e7d5fb96 --- /dev/null +++ b/oas-contract-tests/src/main/java/springfox/test/contract/oas/api/UserApiDelegate.java @@ -0,0 +1,132 @@ +/* + * + * * Copyright 2019-2020 the original author or authors. + * * + * * Licensed under the Apache License, Version 2.0 (the "License"); + * * you may not use this file except in compliance with the License. + * * You may obtain a copy of the License at + * * + * * https://www.apache.org/licenses/LICENSE-2.0 + * * + * * Unless required by applicable law or agreed to in writing, software + * * distributed under the License is distributed on an "AS IS" BASIS, + * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * * See the License for the specific language governing permissions and + * * limitations under the License. + * + */ + +package springfox.test.contract.oas.api; + +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.context.request.NativeWebRequest; +import springfox.test.contract.oas.model.User; + +import java.util.Optional; + +/** + * A delegate to be called by the {@link UserApiController}}. + * Implement this interface with a {@link org.springframework.stereotype.Service} annotated class. + */ +@javax.annotation.Generated(value = "org.springdoc.demo.app2.codegen.languages.SpringCodegen", + date = "2019-07-11T00:09:29.839+02:00[Europe/Paris]") + +public interface UserApiDelegate { + + default Optional getRequest() { + return Optional.empty(); + } + + /** + * @see UserApi#createUser + */ + default ResponseEntity createUser(User user) { + return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED); + + } + + /** + * @see UserApi#createUsersWithArrayInput + */ + default ResponseEntity createUsersWithArrayInput(java.util.List user) { + return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED); + + } + + /** + * @see UserApi#createUsersWithListInput + */ + default ResponseEntity createUsersWithListInput(java.util.List user) { + return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED); + + } + + /** + * @see UserApi#deleteUser + */ + default ResponseEntity deleteUser(String username) { + return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED); + + } + + /** + * @see UserApi#getUserByName + */ + default ResponseEntity getUserByName(String username) { + getRequest().ifPresent(request -> { + for (org.springframework.http.MediaType mediaType : org.springframework.http.MediaType + .parseMediaTypes(request.getHeader("Accept"))) { + if (mediaType.isCompatibleWith(org.springframework.http.MediaType.valueOf("application/json"))) { + ApiUtil.setExampleResponse( + request, + "application/json", + "{ \"firstName\" : \"firstName\", \"lastName\" : \"lastName\", \"password\" : \"password\", " + + "\"userStatus\" : 6, \"phone\" : \"phone\", \"id\" : 0, \"email\" : \"email\", \"username\" :" + + " \"username\"}"); + break; + } + if (mediaType.isCompatibleWith(org.springframework.http.MediaType.valueOf("application/xml"))) { + ApiUtil.setExampleResponse( + request, + "application/xml", + " 123456789 aeiou aeiou " + + "aeiou aeiou aeiou " + + "aeiou 123"); + break; + } + } + }); + return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED); + + } + + /** + * @see UserApi#loginUser + */ + default ResponseEntity loginUser( + String username, + String password) { + return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED); + + } + + /** + * @see UserApi#logoutUser + */ + default ResponseEntity logoutUser() { + return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED); + + } + + /** + * @see UserApi#updateUser + */ + default ResponseEntity updateUser( + String username, + User user) { + return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED); + + } + +} diff --git a/oas-contract-tests/src/main/java/springfox/test/contract/oas/api/UserApiDelegateImpl.java b/oas-contract-tests/src/main/java/springfox/test/contract/oas/api/UserApiDelegateImpl.java new file mode 100644 index 00000000000..ee1312d4e54 --- /dev/null +++ b/oas-contract-tests/src/main/java/springfox/test/contract/oas/api/UserApiDelegateImpl.java @@ -0,0 +1,141 @@ +/* + * + * * Copyright 2019-2020 the original author or authors. + * * + * * Licensed under the Apache License, Version 2.0 (the "License"); + * * you may not use this file except in compliance with the License. + * * You may obtain a copy of the License at + * * + * * https://www.apache.org/licenses/LICENSE-2.0 + * * + * * Unless required by applicable law or agreed to in writing, software + * * distributed under the License is distributed on an "AS IS" BASIS, + * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * * See the License for the specific language governing permissions and + * * limitations under the License. + * + */ + +package springfox.test.contract.oas.api; + +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Service; +import org.springframework.web.server.ResponseStatusException; +import springfox.test.contract.oas.model.User; +import springfox.test.contract.oas.repository.UserRepository; + +import javax.annotation.PostConstruct; +import java.time.Instant; +import java.time.temporal.ChronoUnit; +import java.util.Date; + +@Service +public class UserApiDelegateImpl implements UserApiDelegate { + + private final UserRepository userRepository; + + public UserApiDelegateImpl(UserRepository userRepository) { + this.userRepository = userRepository; + } + + private static User createUser( + long id, + String username, + String firstName, + String lastName, + String email, + int userStatus) { + return new User() + .id(id) + .username(username) + .firstName(firstName) + .lastName(lastName) + .email(email) + .password("XXXXXXXXXXX") + .phone("123-456-7890") + .userStatus(userStatus); + } + + @PostConstruct + private void initUsers() { + userRepository.save(createUser(1, "user1", "first name 1", "last name 1", + "email1@test.com", 1)); + userRepository.save(createUser(2, "user2", "first name 2", "last name 2", + "email2@test.com", 2)); + userRepository.save(createUser(3, "user3", "first name 3", "last name 3", + "email3@test.com", 3)); + userRepository.save(createUser(4, "user4", "first name 4", "last name 4", + "email4@test.com", 1)); + userRepository.save(createUser(5, "user5", "first name 5", "last name 5", + "email5@test.com", 2)); + userRepository.save(createUser(6, "user6", "first name 6", "last name 6", + "email6@test.com", 3)); + userRepository.save(createUser(7, "user7", "first name 7", "last name 7", + "email7@test.com", 1)); + userRepository.save(createUser(8, "user8", "first name 8", "last name 8", + "email8@test.com", 2)); + userRepository.save(createUser(9, "user9", "first name 9", "last name 9", + "email9@test.com", 3)); + userRepository.save(createUser(10, "user10", "first name 10", "last name 10", + "email10@test.com", 1)); + userRepository.save(createUser(11, "user?10", "first name ?10", "last name ?10", + "email101@test.com", 1)); + } + + @Override + public ResponseEntity createUser(User user) { + userRepository.save(user); + return ResponseEntity.ok().build(); + } + + @Override + public ResponseEntity createUsersWithArrayInput(java.util.List users) { + userRepository.saveAll(users); + return ResponseEntity.ok().build(); + } + + @Override + public ResponseEntity createUsersWithListInput(java.util.List users) { + return createUsersWithArrayInput(users); + } + + @Override + public ResponseEntity deleteUser(String username) { + User user = userRepository.findById(username) + .orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND)); + userRepository.delete(user); + return ResponseEntity.ok().build(); + } + + @Override + public ResponseEntity getUserByName(String username) { + return userRepository.findById(username) + .map(ResponseEntity::ok) + .orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND)); + } + + @Override + public ResponseEntity loginUser( + String username, + String password) { + Instant now = Instant.now().plus(1, ChronoUnit.HOURS); + return ResponseEntity.ok() + .header("X-Expires-After", new Date(now.toEpochMilli()).toString()) + .header("X-Rate-Limit", "5000") + .body("logged in user session:" + now.toEpochMilli()); + } + + @Override + public ResponseEntity logoutUser() { + return ResponseEntity.ok().build(); + } + + @Override + public ResponseEntity updateUser( + String username, + User user) { + user.setUsername(username); + return createUser(user); + } +} diff --git a/oas-contract-tests/src/main/java/springfox/test/contract/oas/model/Category.java b/oas-contract-tests/src/main/java/springfox/test/contract/oas/model/Category.java new file mode 100644 index 00000000000..e38c4e39fea --- /dev/null +++ b/oas-contract-tests/src/main/java/springfox/test/contract/oas/model/Category.java @@ -0,0 +1,131 @@ +/* + * + * * Copyright 2019-2020 the original author or authors. + * * + * * Licensed under the Apache License, Version 2.0 (the "License"); + * * you may not use this file except in compliance with the License. + * * You may obtain a copy of the License at + * * + * * https://www.apache.org/licenses/LICENSE-2.0 + * * + * * Unless required by applicable law or agreed to in writing, software + * * distributed under the License is distributed on an "AS IS" BASIS, + * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * * See the License for the specific language governing permissions and + * * limitations under the License. + * + */ + +package springfox.test.contract.oas.model; + +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.Objects; + +/** + * Category + */ + +@javax.annotation.Generated(value = "org.openapitools.codegen.languages.SpringCodegen", + date = "2019-11-30T09:49:26.034469-01:00[Atlantic/Azores]") + + +public class Category { + + @JsonProperty("id") + + private Long id; + + + @JsonProperty("name") + + private String name; + + + public Category id(Long id) { + this.id = id; + return this; + } + + + /** + * Get id + * + * @return id + */ + @io.swagger.v3.oas.annotations.media.Schema(example = "1", description = "") + + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + + public Category name(String name) { + this.name = name; + return this; + } + + + /** + * Get name + * + * @return name + */ + @io.swagger.v3.oas.annotations.media.Schema(example = "Dogs", description = "") + + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + Category category = (Category) o; + return Objects.equals(this.id, category.id) && + Objects.equals(this.name, category.name); + } + + @Override + public int hashCode() { + return Objects.hash(id, name); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class Category {\n"); + + sb.append(" id: ").append(toIndentedString(id)).append("\n"); + sb.append(" name: ").append(toIndentedString(name)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } +} + diff --git a/oas-contract-tests/src/main/java/springfox/test/contract/oas/model/ModelApiResponse.java b/oas-contract-tests/src/main/java/springfox/test/contract/oas/model/ModelApiResponse.java new file mode 100644 index 00000000000..3a59473543b --- /dev/null +++ b/oas-contract-tests/src/main/java/springfox/test/contract/oas/model/ModelApiResponse.java @@ -0,0 +1,161 @@ +/* + * + * * Copyright 2019-2020 the original author or authors. + * * + * * Licensed under the Apache License, Version 2.0 (the "License"); + * * you may not use this file except in compliance with the License. + * * You may obtain a copy of the License at + * * + * * https://www.apache.org/licenses/LICENSE-2.0 + * * + * * Unless required by applicable law or agreed to in writing, software + * * distributed under the License is distributed on an "AS IS" BASIS, + * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * * See the License for the specific language governing permissions and + * * limitations under the License. + * + */ + +package springfox.test.contract.oas.model; + +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.Objects; + +/** + * ModelApiResponse + */ + +@javax.annotation.Generated(value = "org.openapitools.codegen.languages.SpringCodegen", + date = "2019-11-30T09:49:26.034469-01:00[Atlantic/Azores]") + + +public class ModelApiResponse { + + @JsonProperty("code") + + private Integer code; + + + @JsonProperty("type") + + private String type; + + + @JsonProperty("message") + + private String message; + + + public ModelApiResponse code(Integer code) { + this.code = code; + return this; + } + + + /** + * Get code + * + * @return code + */ + @io.swagger.v3.oas.annotations.media.Schema(description = "") + + + public Integer getCode() { + return code; + } + + public void setCode(Integer code) { + this.code = code; + } + + + public ModelApiResponse type(String type) { + this.type = type; + return this; + } + + + /** + * Get type + * + * @return type + */ + @io.swagger.v3.oas.annotations.media.Schema(description = "") + + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + + public ModelApiResponse message(String message) { + this.message = message; + return this; + } + + + /** + * Get message + * + * @return message + */ + @io.swagger.v3.oas.annotations.media.Schema(description = "") + + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + ModelApiResponse modelApiResponse = (ModelApiResponse) o; + return Objects.equals(this.code, modelApiResponse.code) && + Objects.equals(this.type, modelApiResponse.type) && + Objects.equals(this.message, modelApiResponse.message); + } + + @Override + public int hashCode() { + return Objects.hash(code, type, message); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class ModelApiResponse {\n"); + + sb.append(" code: ").append(toIndentedString(code)).append("\n"); + sb.append(" type: ").append(toIndentedString(type)).append("\n"); + sb.append(" message: ").append(toIndentedString(message)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } +} + diff --git a/oas-contract-tests/src/main/java/springfox/test/contract/oas/model/Order.java b/oas-contract-tests/src/main/java/springfox/test/contract/oas/model/Order.java new file mode 100644 index 00000000000..578c9f01e1b --- /dev/null +++ b/oas-contract-tests/src/main/java/springfox/test/contract/oas/model/Order.java @@ -0,0 +1,273 @@ +/* + * + * * Copyright 2019-2020 the original author or authors. + * * + * * Licensed under the Apache License, Version 2.0 (the "License"); + * * you may not use this file except in compliance with the License. + * * You may obtain a copy of the License at + * * + * * https://www.apache.org/licenses/LICENSE-2.0 + * * + * * Unless required by applicable law or agreed to in writing, software + * * distributed under the License is distributed on an "AS IS" BASIS, + * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * * See the License for the specific language governing permissions and + * * limitations under the License. + * + */ + +package springfox.test.contract.oas.model; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonValue; + +import java.util.Date; +import java.util.Objects; + +/** + * Order + */ + +@javax.annotation.Generated(value = "org.openapitools.codegen.languages.SpringCodegen", + date = "2019-11-30T09:49:26.034469-01:00[Atlantic/Azores]") + + +public class Order { + + @JsonProperty("id") + + private Long id; + + + @JsonProperty("petId") + + private Long petId; + + + @JsonProperty("quantity") + + private Integer quantity; + + + @JsonProperty("shipDate") + + private Date shipDate; + + @JsonProperty("status") + + private StatusEnum status; + + @JsonProperty("complete") + + private Boolean complete; + + public Order id(Long id) { + this.id = id; + return this; + } + + /** + * Get id + * + * @return id + */ + @io.swagger.v3.oas.annotations.media.Schema(example = "10", description = "") + + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public Order petId(Long petId) { + this.petId = petId; + return this; + } + + /** + * Get petId + * + * @return petId + */ + @io.swagger.v3.oas.annotations.media.Schema(example = "198772", description = "") + + + public Long getPetId() { + return petId; + } + + public void setPetId(Long petId) { + this.petId = petId; + } + + public Order quantity(Integer quantity) { + this.quantity = quantity; + return this; + } + + /** + * Get quantity + * + * @return quantity + */ + @io.swagger.v3.oas.annotations.media.Schema(example = "7", description = "") + + + public Integer getQuantity() { + return quantity; + } + + public void setQuantity(Integer quantity) { + this.quantity = quantity; + } + + public Order shipDate(Date shipDate) { + this.shipDate = shipDate; + return this; + } + + /** + * Get shipDate + * + * @return shipDate + */ + @io.swagger.v3.oas.annotations.media.Schema(description = "") + + @javax.validation.Valid + + public Date getShipDate() { + return shipDate; + } + + public void setShipDate(Date shipDate) { + this.shipDate = shipDate; + } + + public Order status(StatusEnum status) { + this.status = status; + return this; + } + + /** + * Order Status + * + * @return status + */ + @io.swagger.v3.oas.annotations.media.Schema(example = "approved", description = "Order Status") + + + public StatusEnum getStatus() { + return status; + } + + public void setStatus(StatusEnum status) { + this.status = status; + } + + public Order complete(Boolean complete) { + this.complete = complete; + return this; + } + + /** + * Get complete + * + * @return complete + */ + @io.swagger.v3.oas.annotations.media.Schema(description = "") + + + public Boolean getComplete() { + return complete; + } + + public void setComplete(Boolean complete) { + this.complete = complete; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + Order order = (Order) o; + return Objects.equals(this.id, order.id) && + Objects.equals(this.petId, order.petId) && + Objects.equals(this.quantity, order.quantity) && + Objects.equals(this.shipDate, order.shipDate) && + Objects.equals(this.status, order.status) && + Objects.equals(this.complete, order.complete); + } + + @Override + public int hashCode() { + return Objects.hash(id, petId, quantity, shipDate, status, complete); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class Order {\n"); + + sb.append(" id: ").append(toIndentedString(id)).append("\n"); + sb.append(" petId: ").append(toIndentedString(petId)).append("\n"); + sb.append(" quantity: ").append(toIndentedString(quantity)).append("\n"); + sb.append(" shipDate: ").append(toIndentedString(shipDate)).append("\n"); + sb.append(" status: ").append(toIndentedString(status)).append("\n"); + sb.append(" complete: ").append(toIndentedString(complete)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } + + /** + * Order Status + */ + public enum StatusEnum { + PLACED("placed"), + + APPROVED("approved"), + + DELIVERED("delivered"); + + private String value; + + StatusEnum(String value) { + this.value = value; + } + + @JsonCreator + public static StatusEnum fromValue(String value) { + for (StatusEnum b : StatusEnum.values()) { + if (b.value.equals(value)) { + return b; + } + } + throw new IllegalArgumentException("Unexpected value '" + value + "'"); + } + + @Override + @JsonValue + public String toString() { + return String.valueOf(value); + } + } +} + diff --git a/oas-contract-tests/src/main/java/springfox/test/contract/oas/model/Pet.java b/oas-contract-tests/src/main/java/springfox/test/contract/oas/model/Pet.java new file mode 100644 index 00000000000..0f381d864ab --- /dev/null +++ b/oas-contract-tests/src/main/java/springfox/test/contract/oas/model/Pet.java @@ -0,0 +1,285 @@ +/* + * + * * Copyright 2019-2020 the original author or authors. + * * + * * Licensed under the Apache License, Version 2.0 (the "License"); + * * you may not use this file except in compliance with the License. + * * You may obtain a copy of the License at + * * + * * https://www.apache.org/licenses/LICENSE-2.0 + * * + * * Unless required by applicable law or agreed to in writing, software + * * distributed under the License is distributed on an "AS IS" BASIS, + * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * * See the License for the specific language governing permissions and + * * limitations under the License. + * + */ + +package springfox.test.contract.oas.model; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonValue; + +import javax.validation.constraints.NotNull; +import java.util.ArrayList; +import java.util.Objects; + +public class Pet { + + @JsonProperty("id") + + private Long id; + + + @JsonProperty("name") + + private String name; + + + @JsonProperty("category") + + private Category category; + + + @JsonProperty("photoUrls") + + @javax.validation.Valid + private java.util.List photoUrls = new ArrayList<>(); + + + @JsonProperty("tags") + + @javax.validation.Valid + private java.util.List tags = null; + + @JsonProperty("status") + + private StatusEnum status; + + public Pet id(Long id) { + this.id = id; + return this; + } + + /** + * Get id + * + * @return id + */ + @io.swagger.v3.oas.annotations.media.Schema(example = "10", description = "") + + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public Pet name(String name) { + this.name = name; + return this; + } + + /** + * Get name + * + * @return name + */ + @io.swagger.v3.oas.annotations.media.Schema(example = "doggie", required = true, description = "") + @NotNull + + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Pet category(Category category) { + this.category = category; + return this; + } + + /** + * Get category + * + * @return category + */ + @io.swagger.v3.oas.annotations.media.Schema(description = "") + + @javax.validation.Valid + + public Category getCategory() { + return category; + } + + public void setCategory(Category category) { + this.category = category; + } + + public Pet photoUrls(java.util.List photoUrls) { + this.photoUrls = photoUrls; + return this; + } + + public Pet addPhotoUrlsItem(String photoUrlsItem) { + this.photoUrls.add(photoUrlsItem); + return this; + } + + /** + * Get photoUrls + * + * @return photoUrls + */ + @io.swagger.v3.oas.annotations.media.Schema(required = true, description = "") + @NotNull + + + public java.util.List getPhotoUrls() { + return photoUrls; + } + + public void setPhotoUrls(java.util.List photoUrls) { + this.photoUrls = photoUrls; + } + + public Pet tags(java.util.List tags) { + this.tags = tags; + return this; + } + + public Pet addTagsItem(Tag tagsItem) { + if (this.tags == null) { + this.tags = new ArrayList<>(); + } + this.tags.add(tagsItem); + return this; + } + + /** + * Get tags + * + * @return tags + */ + @io.swagger.v3.oas.annotations.media.Schema(description = "") + + @javax.validation.Valid + + public java.util.List getTags() { + return tags; + } + + public void setTags(java.util.List tags) { + this.tags = tags; + } + + public Pet status(StatusEnum status) { + this.status = status; + return this; + } + + /** + * pet status in the store + * + * @return status + */ + @io.swagger.v3.oas.annotations.media.Schema(description = "pet status in the store") + + + public StatusEnum getStatus() { + return status; + } + + public void setStatus(StatusEnum status) { + this.status = status; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + Pet pet = (Pet) o; + return Objects.equals(this.id, pet.id) && + Objects.equals(this.name, pet.name) && + Objects.equals(this.category, pet.category) && + Objects.equals(this.photoUrls, pet.photoUrls) && + Objects.equals(this.tags, pet.tags) && + Objects.equals(this.status, pet.status); + } + + @Override + public int hashCode() { + return Objects.hash(id, name, category, photoUrls, tags, status); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class Pet {\n"); + + sb.append(" id: ").append(toIndentedString(id)).append("\n"); + sb.append(" name: ").append(toIndentedString(name)).append("\n"); + sb.append(" category: ").append(toIndentedString(category)).append("\n"); + sb.append(" photoUrls: ").append(toIndentedString(photoUrls)).append("\n"); + sb.append(" tags: ").append(toIndentedString(tags)).append("\n"); + sb.append(" status: ").append(toIndentedString(status)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } + + /** + * pet status in the store + */ + public enum StatusEnum { + AVAILABLE("available"), + + PENDING("pending"), + + SOLD("sold"); + + private final String value; + + StatusEnum(String value) { + this.value = value; + } + + @JsonCreator + public static StatusEnum fromValue(String value) { + for (StatusEnum b : StatusEnum.values()) { + if (b.value.equals(value)) { + return b; + } + } + throw new IllegalArgumentException("Unexpected value '" + value + "'"); + } + + @Override + @JsonValue + public String toString() { + return String.valueOf(value); + } + } +} + diff --git a/oas-contract-tests/src/main/java/springfox/test/contract/oas/model/Tag.java b/oas-contract-tests/src/main/java/springfox/test/contract/oas/model/Tag.java new file mode 100644 index 00000000000..80371d14c0e --- /dev/null +++ b/oas-contract-tests/src/main/java/springfox/test/contract/oas/model/Tag.java @@ -0,0 +1,131 @@ +/* + * + * * Copyright 2019-2020 the original author or authors. + * * + * * Licensed under the Apache License, Version 2.0 (the "License"); + * * you may not use this file except in compliance with the License. + * * You may obtain a copy of the License at + * * + * * https://www.apache.org/licenses/LICENSE-2.0 + * * + * * Unless required by applicable law or agreed to in writing, software + * * distributed under the License is distributed on an "AS IS" BASIS, + * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * * See the License for the specific language governing permissions and + * * limitations under the License. + * + */ + +package springfox.test.contract.oas.model; + +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.Objects; + +/** + * Tag + */ + +@javax.annotation.Generated(value = "org.openapitools.codegen.languages.SpringCodegen", + date = "2019-11-30T09:49:26.034469-01:00[Atlantic/Azores]") + + +public class Tag { + + @JsonProperty("id") + + private Long id; + + + @JsonProperty("name") + + private String name; + + + public Tag id(Long id) { + this.id = id; + return this; + } + + + /** + * Get id + * + * @return id + */ + @io.swagger.v3.oas.annotations.media.Schema(description = "") + + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + + public Tag name(String name) { + this.name = name; + return this; + } + + + /** + * Get name + * + * @return name + */ + @io.swagger.v3.oas.annotations.media.Schema(description = "") + + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + Tag tag = (Tag) o; + return Objects.equals(this.id, tag.id) && + Objects.equals(this.name, tag.name); + } + + @Override + public int hashCode() { + return Objects.hash(id, name); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class Tag {\n"); + + sb.append(" id: ").append(toIndentedString(id)).append("\n"); + sb.append(" name: ").append(toIndentedString(name)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } +} + diff --git a/oas-contract-tests/src/main/java/springfox/test/contract/oas/model/User.java b/oas-contract-tests/src/main/java/springfox/test/contract/oas/model/User.java new file mode 100644 index 00000000000..f70883736ab --- /dev/null +++ b/oas-contract-tests/src/main/java/springfox/test/contract/oas/model/User.java @@ -0,0 +1,312 @@ +/* + * + * * Copyright 2019-2020 the original author or authors. + * * + * * Licensed under the Apache License, Version 2.0 (the "License"); + * * you may not use this file except in compliance with the License. + * * You may obtain a copy of the License at + * * + * * https://www.apache.org/licenses/LICENSE-2.0 + * * + * * Unless required by applicable law or agreed to in writing, software + * * distributed under the License is distributed on an "AS IS" BASIS, + * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * * See the License for the specific language governing permissions and + * * limitations under the License. + * + */ + +package springfox.test.contract.oas.model; + +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.Objects; + +/** + * User + */ + +@javax.annotation.Generated(value = "org.openapitools.codegen.languages.SpringCodegen", + date = "2019-11-30T09:49:26.034469-01:00[Atlantic/Azores]") + + +public class User { + + @JsonProperty("id") + + private Long id; + + + @JsonProperty("username") + + private String username; + + + @JsonProperty("firstName") + + private String firstName; + + + @JsonProperty("lastName") + + private String lastName; + + + @JsonProperty("email") + + private String email; + + + @JsonProperty("password") + + private String password; + + + @JsonProperty("phone") + + private String phone; + + + @JsonProperty("userStatus") + + private Integer userStatus; + + + public User id(Long id) { + this.id = id; + return this; + } + + + /** + * Get id + * + * @return id + */ + @io.swagger.v3.oas.annotations.media.Schema(example = "10", description = "") + + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + + public User username(String username) { + this.username = username; + return this; + } + + + /** + * Get username + * + * @return username + */ + @io.swagger.v3.oas.annotations.media.Schema(example = "theUser", description = "") + + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + + public User firstName(String firstName) { + this.firstName = firstName; + return this; + } + + + /** + * Get firstName + * + * @return firstName + */ + @io.swagger.v3.oas.annotations.media.Schema(example = "John", description = "") + + + public String getFirstName() { + return firstName; + } + + public void setFirstName(String firstName) { + this.firstName = firstName; + } + + + public User lastName(String lastName) { + this.lastName = lastName; + return this; + } + + + /** + * Get lastName + * + * @return lastName + */ + @io.swagger.v3.oas.annotations.media.Schema(example = "James", description = "") + + + public String getLastName() { + return lastName; + } + + public void setLastName(String lastName) { + this.lastName = lastName; + } + + + public User email(String email) { + this.email = email; + return this; + } + + + /** + * Get email + * + * @return email + */ + @io.swagger.v3.oas.annotations.media.Schema(example = "john@email.com", description = "") + + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } + + + public User password(String password) { + this.password = password; + return this; + } + + + /** + * Get password + * + * @return password + */ + @io.swagger.v3.oas.annotations.media.Schema(example = "12345", description = "") + + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + + public User phone(String phone) { + this.phone = phone; + return this; + } + + + /** + * Get phone + * + * @return phone + */ + @io.swagger.v3.oas.annotations.media.Schema(example = "12345", description = "") + + + public String getPhone() { + return phone; + } + + public void setPhone(String phone) { + this.phone = phone; + } + + + public User userStatus(Integer userStatus) { + this.userStatus = userStatus; + return this; + } + + + /** + * User Status + * + * @return userStatus + */ + @io.swagger.v3.oas.annotations.media.Schema(example = "1", description = "User Status") + + + public Integer getUserStatus() { + return userStatus; + } + + public void setUserStatus(Integer userStatus) { + this.userStatus = userStatus; + } + + + @SuppressWarnings("CyclomaticComplexity") + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + User user = (User) o; + return Objects.equals(this.id, user.id) && + Objects.equals(this.username, user.username) && + Objects.equals(this.firstName, user.firstName) && + Objects.equals(this.lastName, user.lastName) && + Objects.equals(this.email, user.email) && + Objects.equals(this.password, user.password) && + Objects.equals(this.phone, user.phone) && + Objects.equals(this.userStatus, user.userStatus); + } + + @Override + public int hashCode() { + return Objects.hash(id, username, firstName, lastName, email, password, phone, userStatus); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class User {\n"); + + sb.append(" id: ").append(toIndentedString(id)).append("\n"); + sb.append(" username: ").append(toIndentedString(username)).append("\n"); + sb.append(" firstName: ").append(toIndentedString(firstName)).append("\n"); + sb.append(" lastName: ").append(toIndentedString(lastName)).append("\n"); + sb.append(" email: ").append(toIndentedString(email)).append("\n"); + sb.append(" password: ").append(toIndentedString(password)).append("\n"); + sb.append(" phone: ").append(toIndentedString(phone)).append("\n"); + sb.append(" userStatus: ").append(toIndentedString(userStatus)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } +} + diff --git a/oas-contract-tests/src/main/java/springfox/test/contract/oas/repository/HashMapRepository.java b/oas-contract-tests/src/main/java/springfox/test/contract/oas/repository/HashMapRepository.java new file mode 100644 index 00000000000..f15a553b87d --- /dev/null +++ b/oas-contract-tests/src/main/java/springfox/test/contract/oas/repository/HashMapRepository.java @@ -0,0 +1,175 @@ +/* + * + * * Copyright 2019-2020 the original author or authors. + * * + * * Licensed under the Apache License, Version 2.0 (the "License"); + * * you may not use this file except in compliance with the License. + * * You may obtain a copy of the License at + * * + * * https://www.apache.org/licenses/LICENSE-2.0 + * * + * * Unless required by applicable law or agreed to in writing, software + * * distributed under the License is distributed on an "AS IS" BASIS, + * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * * See the License for the specific language governing permissions and + * * limitations under the License. + * + */ + +package springfox.test.contract.oas.repository; + +import org.springframework.beans.BeanWrapper; +import org.springframework.beans.BeanWrapperImpl; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Sort; +import org.springframework.data.repository.CrudRepository; +import org.springframework.data.repository.NoRepositoryBean; +import org.springframework.util.Assert; + +import java.util.ArrayList; +import java.util.Comparator; +import java.util.HashMap; +import java.util.Optional; +import java.util.TreeSet; + +@NoRepositoryBean +public abstract class HashMapRepository implements CrudRepository { + + private final BeanWrapper entityBeanInfo; + + @SuppressWarnings("VisibilityModifier") + protected final java.util.Map entities = new HashMap<>(); + + protected HashMapRepository(Class clazz) { + entityBeanInfo = new BeanWrapperImpl(clazz); + } + + abstract ID getEntityId(S entity); + + @Override + public S save(S entity) { + Assert.notNull(entity, "entity cannot be null"); + Assert.notNull(getEntityId(entity), "entity ID cannot be null"); + entities.put(getEntityId(entity), entity); + return entity; + } + + @Override + public java.util.List saveAll(Iterable entities) { + Assert.notNull(entities, "entities cannot be null"); + java.util.List result = new ArrayList<>(); + entities.forEach(entity -> result.add(save(entity))); + return result; + } + + @Override + public java.util.Collection findAll() { + return entities.values(); + } + + public java.util.List findAll(Pageable pageable) { + final java.util.List result; + final Sort sort = pageable.getSort(); + Comparator comp = new Comparator() { + @Override + public int compare( + T t1, + T t2) { + int result = 0; + for (Sort.Order o : sort) { + final String prop = o.getProperty(); + java.beans.PropertyDescriptor propDesc = entityBeanInfo.getPropertyDescriptor(prop); + result = ((Comparable) propDesc.createPropertyEditor(t1).getValue()) + .compareTo((T) propDesc.createPropertyEditor(t2).getValue()); + if (o.isDescending()) { + result = -result; + } + if (result != 0) { + break; + } + } + return result; + } + }; + final java.util.Set set = new TreeSet<>(comp); + set.addAll(entities.values()); + result = getPageSlice(pageable, set); + return result; + } + + private java.util.List getPageSlice( + Pageable pageable, + java.util.Collection col) { + final ArrayList all = new ArrayList<>(col); + final int size = all.size(); + final int psize = pageable.getPageSize(); + final int pnum = pageable.getPageNumber(); + if (pnum < 1) { + throw new IllegalArgumentException("page number must be 1 or more"); + } + if (psize < 1) { + throw new IllegalArgumentException("page size must be 1 or more"); + } + // inclusive + final int begin = (pnum - 1) * psize; + // exclusive + final int end = Math.min(begin + psize, size); + if (size < begin) { + return new ArrayList<>(); + } + // return of slice is valid because all is local to this method + return all.subList(begin, end); + } + + @Override + public long count() { + return entities.keySet().size(); + } + + @Override + public void delete(T entity) { + Assert.notNull(entity, "entity cannot be null"); + deleteById(getEntityId(entity)); + } + + @Override + public void deleteAll(Iterable entitiesToDelete) { + Assert.notNull(entitiesToDelete, "entities cannot be null"); + entitiesToDelete.forEach(entity -> entities.remove(getEntityId(entity))); + } + + @Override + public void deleteAll() { + entities.clear(); + } + + @Override + public void deleteById(ID id) { + Assert.notNull(id, "Id cannot be null"); + entities.remove(id); + } + + @Override + public java.util.List findAllById(Iterable ids) { + Assert.notNull(ids, "Ids cannot be null"); + java.util.List result = new ArrayList<>(); + ids.forEach(id -> findById(id).ifPresent(result::add)); + return result; + } + + @Override + public boolean existsById(ID id) { + Assert.notNull(id, "Id cannot be null"); + return entities.containsKey(id); + } + + public T findOne(ID id) { + Assert.notNull(id, "Id cannot be null"); + return entities.get(id); + } + + @Override + public Optional findById(ID id) { + return Optional.ofNullable(findOne(id)); + } +} diff --git a/oas-contract-tests/src/main/java/springfox/test/contract/oas/repository/OrderRepository.java b/oas-contract-tests/src/main/java/springfox/test/contract/oas/repository/OrderRepository.java new file mode 100644 index 00000000000..c0aa299ba25 --- /dev/null +++ b/oas-contract-tests/src/main/java/springfox/test/contract/oas/repository/OrderRepository.java @@ -0,0 +1,35 @@ +/* + * + * * Copyright 2019-2020 the original author or authors. + * * + * * Licensed under the Apache License, Version 2.0 (the "License"); + * * you may not use this file except in compliance with the License. + * * You may obtain a copy of the License at + * * + * * https://www.apache.org/licenses/LICENSE-2.0 + * * + * * Unless required by applicable law or agreed to in writing, software + * * distributed under the License is distributed on an "AS IS" BASIS, + * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * * See the License for the specific language governing permissions and + * * limitations under the License. + * + */ + +package springfox.test.contract.oas.repository; + +import org.springframework.stereotype.Repository; +import springfox.test.contract.oas.model.Order; + +@Repository +public class OrderRepository extends HashMapRepository { + + public OrderRepository() { + super(Order.class); + } + + @Override + Long getEntityId(S order) { + return order.getId(); + } +} diff --git a/oas-contract-tests/src/main/java/springfox/test/contract/oas/repository/PetRepository.java b/oas-contract-tests/src/main/java/springfox/test/contract/oas/repository/PetRepository.java new file mode 100644 index 00000000000..20997ea6648 --- /dev/null +++ b/oas-contract-tests/src/main/java/springfox/test/contract/oas/repository/PetRepository.java @@ -0,0 +1,69 @@ +/* + * + * * Copyright 2019-2020 the original author or authors. + * * + * * Licensed under the Apache License, Version 2.0 (the "License"); + * * you may not use this file except in compliance with the License. + * * You may obtain a copy of the License at + * * + * * https://www.apache.org/licenses/LICENSE-2.0 + * * + * * Unless required by applicable law or agreed to in writing, software + * * distributed under the License is distributed on an "AS IS" BASIS, + * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * * See the License for the specific language governing permissions and + * * limitations under the License. + * + */ + +package springfox.test.contract.oas.repository; + +import org.springframework.stereotype.Repository; +import springfox.test.contract.oas.model.Pet; +import springfox.test.contract.oas.model.Tag; + +import java.util.stream.Collectors; + +@Repository +public class PetRepository extends HashMapRepository { + + private Long sequenceId = 1L; + + public PetRepository() { + super(Pet.class); + } + + @Override + Long getEntityId(S pet) { + return pet.getId(); + } + + @Override + public S save(S pet) { + if (pet.getId() != null && pet.getId() > sequenceId) { + sequenceId = pet.getId() + 1; + } + if (pet.getId() == null) { + pet.setId(sequenceId); + sequenceId += 1; + } + return super.save(pet); + } + + public java.util.List findPetsByStatus(java.util.List statusList) { + return entities.values().stream() + .filter(entity -> entity.getStatus() != null) + .filter(entity -> statusList.contains(entity.getStatus())) + .collect(Collectors.toList()); + } + + public java.util.List findPetsByTags(java.util.List tags) { + return entities.values().stream() + .filter(entity -> entity.getTags() != null) + .filter(entity -> entity.getTags().stream() + .map(Tag::getName) + .anyMatch(tags::contains) + ) + .collect(Collectors.toList()); + } +} diff --git a/oas-contract-tests/src/main/java/springfox/test/contract/oas/repository/UserRepository.java b/oas-contract-tests/src/main/java/springfox/test/contract/oas/repository/UserRepository.java new file mode 100644 index 00000000000..c9e4164c59c --- /dev/null +++ b/oas-contract-tests/src/main/java/springfox/test/contract/oas/repository/UserRepository.java @@ -0,0 +1,35 @@ +/* + * + * * Copyright 2019-2020 the original author or authors. + * * + * * Licensed under the Apache License, Version 2.0 (the "License"); + * * you may not use this file except in compliance with the License. + * * You may obtain a copy of the License at + * * + * * https://www.apache.org/licenses/LICENSE-2.0 + * * + * * Unless required by applicable law or agreed to in writing, software + * * distributed under the License is distributed on an "AS IS" BASIS, + * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * * See the License for the specific language governing permissions and + * * limitations under the License. + * + */ + +package springfox.test.contract.oas.repository; + +import org.springframework.stereotype.Repository; +import springfox.test.contract.oas.model.User; + +@Repository +public class UserRepository extends HashMapRepository { + + public UserRepository() { + super(User.class); + } + + @Override + String getEntityId(S user) { + return user.getUsername(); + } +} diff --git a/oas-contract-tests/src/test/groovy/springfox/test/contract/oas/FunctionContractSpec.groovy b/oas-contract-tests/src/test/groovy/springfox/test/contract/oas/FunctionContractSpec.groovy index 32df27927dd..861ca80091e 100644 --- a/oas-contract-tests/src/test/groovy/springfox/test/contract/oas/FunctionContractSpec.groovy +++ b/oas-contract-tests/src/test/groovy/springfox/test/contract/oas/FunctionContractSpec.groovy @@ -44,7 +44,6 @@ import static org.skyscreamer.jsonassert.JSONCompareMode.* import static org.springframework.boot.test.context.SpringBootTest.* @SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT, classes = OasApplication) -@Ignore class FunctionContractSpec extends Specification implements FileAccess { @Shared @@ -93,20 +92,6 @@ class FunctionContractSpec extends Specification implements FileAccess { where: contractFile | groupName 'petstore.json' | 'petstore' -// 'petstoreTemplated.json' | 'petstoreTemplated' -// 'declaration-business-service.json' | 'businessService' -// 'declaration-concrete-controller.json' | 'concrete' -// 'declaration-controller-with-no-request-mapping-service.json' | 'noRequestMapping' -// 'declaration-fancy-pet-service.json' | 'fancyPetstore' -// 'declaration-inherited-service-impl.json' | 'inheritedService' -// 'declaration-pet-grooming-service.json' | 'petGroomingService' -// 'declaration-pet-service.json' | 'petService' -// 'declaration-groovy-service.json' | 'groovyService' -// 'declaration-enum-service.json' | 'enumService' -// 'declaration-spring-data-rest.json' | 'spring-data-rest' -// 'declaration-consumes-produces-not-on-document-context.json' | 'consumesProducesNotOnDocumentContext' -// 'declaration-consumes-produces-on-document-context.json' | 'consumesProducesOnDocumentContext' -// 'declaration-same-controller.json' | 'same' } def "should list swagger resources for open api 3.0"() { @@ -127,48 +112,13 @@ class FunctionContractSpec extends Specification implements FileAccess { result.find { it.name == 'petstore' && it.url == '/v3/api-docs?group=petstore' && - it.swaggerVersion == '2.0' + it.swaggerVersion == '3.0.1' } result.find { - it.name == 'businessService' && - it.url == '/v3/api-docs?group=businessService' && - it.swaggerVersion == '2.0' + it.name == 'default' && + it.url == '/v3/api-docs' && + it.swaggerVersion == '3.0.1' } - result.find { - it.name == 'concrete' && - it.url == '/v3/api-docs?group=concrete' && - it.swaggerVersion == '2.0' - } - } - - @Ignore - def 'should honor swagger resource listing'() { - given: - RequestEntity request = RequestEntity.get(new URI("http://localhost:$port/api-docs")) - .accept(MediaType.APPLICATION_JSON) - .build() - String contract = fileContents('/contract/swagger/resource-listing.json') - - when: - def response = http. - exchange( - request, - String) - - then: - response.statusCode == HttpStatus.OK - - def bodyWithLFOnly = response. - body. - replaceAll( - "\\\\r\\\\n", - "\\\\n") //Make sure if we're running on windows the line endings which are double-escaped match up with - // the resource file above. - JSONAssert. - assertEquals( - contract, - bodyWithLFOnly, - NON_EXTENSIBLE) } @TestConfiguration diff --git a/oas-contract-tests/src/test/resources/contracts/petstore.json b/oas-contract-tests/src/test/resources/contracts/petstore.json index a17de6196bd..bf839576332 100644 --- a/oas-contract-tests/src/test/resources/contracts/petstore.json +++ b/oas-contract-tests/src/test/resources/contracts/petstore.json @@ -1,1136 +1,1308 @@ { - "openapi": "3.0.0", - "info": { - "description": "Api Documentation", - "version": "1.0", - "title": "Api Documentation", - "termsOfService": "urn:tos", - "contact": {}, - "license": { - "name": "Apache 2.0", - "url": "http://www.apache.org/licenses/LICENSE-2.0" - } - }, - "tags": [ - { - "name": "pet-controller", - "description": "Operations about pets" - }, - { - "name": "pet-store-resource", - "description": "Operations about store" + "openapi": "3.0.1", + "info": { + "title": "Api Documentation", + "description": "Api Documentation", + "termsOfService": "urn:tos", + "contact": { + + }, + "license": { + "name": "Apache 2.0", + "url": "http://www.apache.org/licenses/LICENSE-2.0" + }, + "version": "1.0" }, - { - "name": "user-controller", - "description": "Operations about user" - } - ], - "paths": { - "/api/pet": { - "post": { - "tags": [ - "pet-controller" - ], - "summary": "Add a new pet to the store", - "operationId": "addPetUsingPOST", - "requestBody": { - "$ref": "#/components/requestBodies/Pet" + "servers": [ + { + "url": "http://localhost:__PORT__", + "description": "Inferred Url" + } + ], + "tags": [ + { + "name": "home-controller", + "description": "Home Controller" }, - "responses": { - "200": { - "description": "OK", - "content": { - "application/json": { - "schema": { - "type": "string" - } - }, - "application/xml": { - "schema": { - "type": "string" - } - } - } - }, - "405": { - "description": "Invalid input" - } + { + "name": "pet", + "description": "the pet API" }, - "security": [ - { - "petstore_auth": [ - "write:pets", - "read:pets" - ] - } - ], - "deprecated": false - }, - "put": { - "tags": [ - "pet-controller" - ], - "summary": "Update an existing pet", - "operationId": "updatePetUsingPUT", - "requestBody": { - "$ref": "#/components/requestBodies/Pet" + { + "name": "store", + "description": "the store API" }, - "responses": { - "200": { - "description": "OK", - "content": { - "application/json": { - "schema": { - "type": "string" - } - }, - "application/xml": { - "schema": { - "type": "string" + { + "name": "user", + "description": "the user API" + } + ], + "paths": { + "/": { + "get": { + "tags": [ + "home-controller" + ], + "summary": "index", + "operationId": "indexUsingGET", + "responses": { + "200": { + "description": "OK", + "content": { + "*/*": { + "schema": { + "type": "string" + } + } + } + } } - } } - }, - "400": { - "description": "Invalid ID supplied" - }, - "404": { - "description": "Pet not found" - }, - "405": { - "description": "Validation exception" - } }, - "security": [ - { - "petstore_auth": [ - "write:pets", - "read:pets" - ] - } - ], - "deprecated": false - } - }, - "/api/pet/findByStatus": { - "get": { - "tags": [ - "pet-controller" - ], - "summary": "Finds Pets by status", - "description": "Multiple status values can be provided with comma-separated strings", - "operationId": "findPetsByStatusUsingGET_1", - "parameters": [ - { - "name": "status", - "in": "query", - "description": "Status values that need to be considered for filter", - "required": true, - "allowEmptyValue": false, - "schema": { - "type": "string", - "enum": [ - "available", - "pending", - "sold" - ], - "default": "available" + "/pet": { + "get": { + "tags": [ + "pet" + ], + "summary": "Get all Pets paged", + "description": "Get all Pets paged", + "operationId": "getAllPetsUsingGET", + "parameters": [ + { + "name": "page", + "in": "query", + "required": false, + "style": "form", + "schema": { + "type": "integer", + "format": "int32" + } + }, + { + "name": "size", + "in": "query", + "required": false, + "style": "form", + "schema": { + "type": "integer", + "format": "int32" + } + }, + { + "name": "sort", + "in": "query", + "required": false, + "style": "form", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/xml": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Pet" + } + } + }, + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + }, + "security": [ + { + "petstore_auth": [ + "write:pets", + "read:pets" + ] + } + ] + }, + "put": { + "tags": [ + "pet" + ], + "summary": "Update an existing pet", + "description": "Update an existing pet by Id", + "operationId": "updatePetUsingPUT", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + }, + "application/x-www-form-urlencoded": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + }, + "application/xml": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + }, + "responses": { + "200": { + "description": "Successful operation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + }, + "application/xml": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + }, + "400": { + "description": "Invalid ID supplied" + }, + "404": { + "description": "Pet not found" + }, + "405": { + "description": "Validation exception" + } + }, + "security": [ + { + "petstore_auth": [ + "write:pets", + "read:pets" + ] + } + ] + }, + "post": { + "tags": [ + "pet" + ], + "summary": "Add a new pet to the store", + "description": "Add a new pet to the store", + "operationId": "addPetUsingPOST", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + }, + "application/x-www-form-urlencoded": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + }, + "application/xml": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + }, + "responses": { + "200": { + "description": "Successful operation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + }, + "application/xml": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + }, + "405": { + "description": "Invalid input" + } + }, + "security": [ + { + "petstore_auth": [ + "write:pets", + "read:pets" + ] + } + ] } - } - ], - "responses": { - "200": { - "description": "OK", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/Pet_1" - } - } - }, - "application/xml": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/Pet_1" - } - } - } + }, + "/pet/findByStatus": { + "get": { + "tags": [ + "pet" + ], + "summary": "Finds Pets by status", + "description": "Multiple status values can be provided with comma separated strings", + "operationId": "findPetsByStatusUsingGET", + "parameters": [ + { + "name": "status", + "in": "query", + "description": "Status values that need to be considered for filter", + "required": false, + "style": "form", + "explode": true, + "schema": { + "type": "string", + "enum": [ + "available", + "pending", + "sold" + ] + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/xml": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Pet" + } + } + }, + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + }, + "400": { + "description": "Invalid status value" + } + }, + "security": [ + { + "petstore_auth": [ + "write:pets", + "read:pets" + ] + } + ] } - }, - "400": { - "description": "Invalid status value" - } }, - "security": [ - { - "petstore_auth": [ - "write:pets", - "read:pets" - ] - } - ], - "deprecated": false - } - }, - "/api/pet/findByTags": { - "get": { - "tags": [ - "pet-controller" - ], - "summary": "Finds Pets by tags", - "description": "Multiple tags can be provided with comma-separated strings. Use tag1, tag2, tag3 for testing.", - "operationId": "findPetsByTagsUsingGET_1", - "parameters": [ - { - "name": "tags", - "in": "query", - "description": "Tags to filter by", - "required": true, - "allowEmptyValue": false, - "schema": { - "type": "string" + "/pet/findByTags": { + "get": { + "tags": [ + "pet" + ], + "summary": "Finds Pets by tags", + "description": "Multiple tags can be provided with comma separated strings. Use tag1, tag2, tag3 for testing.", + "operationId": "findPetsByTagsUsingGET", + "parameters": [ + { + "name": "tags", + "in": "query", + "description": "Tags to filter by", + "required": false, + "style": "form", + "explode": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/xml": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Pet" + } + } + }, + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + }, + "400": { + "description": "Invalid tag value" + } + }, + "security": [ + { + "petstore_auth": [ + "write:pets", + "read:pets" + ] + } + ] } - } - ], - "responses": { - "200": { - "description": "OK", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/Pet_1" - } - } - }, - "application/xml": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/Pet_1" - } - } - } + }, + "/pet/{petId}": { + "get": { + "tags": [ + "pet" + ], + "summary": "Find pet by ID", + "description": "Returns a single pet", + "operationId": "getPetByIdUsingGET", + "parameters": [ + { + "name": "petId", + "in": "path", + "description": "ID of pet to return", + "required": true, + "style": "simple", + "schema": { + "type": "integer", + "format": "int64" + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + }, + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + }, + "application/xml": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + }, + "400": { + "description": "Invalid ID supplied" + }, + "404": { + "description": "Pet not found" + } + }, + "security": [ + { + "petstore_auth": [ + "write:pets", + "read:pets" + ] + }, + { + "api_key": [ + + ] + } + ] + }, + "post": { + "tags": [ + "pet" + ], + "summary": "Updates a pet in the store with form data", + "operationId": "updatePetWithFormUsingPOST", + "parameters": [ + { + "name": "petId", + "in": "path", + "description": "ID of pet that needs to be updated", + "required": true, + "style": "simple", + "schema": { + "type": "integer", + "format": "int64" + } + } + ], + "requestBody": { + "content": { + "application/x-www-form-urlencoded": { + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Name of pet that needs to be updated" + }, + "status": { + "type": "string", + "description": "Status of pet that needs to be updated" + } + } + } + } + } + }, + "responses": { + "200": { + "description": "OK" + }, + "405": { + "description": "Invalid input" + } + }, + "security": [ + { + "petstore_auth": [ + "write:pets", + "read:pets" + ] + } + ] + }, + "delete": { + "tags": [ + "pet" + ], + "summary": "Deletes a pet", + "operationId": "deletePetUsingDELETE", + "parameters": [ + { + "name": "api_key", + "in": "header", + "description": "api_key", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "petId", + "in": "path", + "description": "Pet id to delete", + "required": true, + "style": "simple", + "schema": { + "type": "integer", + "format": "int64" + } + } + ], + "responses": { + "200": { + "description": "OK" + }, + "400": { + "description": "Invalid pet value" + } + }, + "security": [ + { + "petstore_auth": [ + "write:pets", + "read:pets" + ] + } + ] } - }, - "400": { - "description": "Invalid tag value" - } }, - "security": [ - { - "petstore_auth": [ - "write:pets", - "read:pets" - ] - } - ], - "deprecated": true - } - }, - "/api/pet/{petId}": { - "get": { - "tags": [ - "pet-controller" - ], - "summary": "Find pet by ID", - "description": "Returns a pet when ID < 10. ID > 10 or non-integers will simulate API error conditions", - "operationId": "getPetByIdUsingGET_3", - "parameters": [ - { - "name": "petId", - "in": "path", - "description": "ID of pet that needs to be fetched", - "required": true, - "schema": { - "type": "string", - "minLength": 1, - "maxLength": 5 + "/pet/{petId}/uploadImage": { + "post": { + "tags": [ + "pet" + ], + "summary": "uploads an image", + "operationId": "uploadFileUsingPOST", + "parameters": [ + { + "name": "additionalMetadata", + "in": "query", + "description": "Additional Metadata", + "required": false, + "style": "form", + "schema": { + "type": "string" + } + }, + { + "name": "petId", + "in": "path", + "description": "ID of pet to update", + "required": true, + "style": "simple", + "schema": { + "type": "integer", + "format": "int64" + } + } + ], + "requestBody": { + "content": { + "multipart/form-data": { + "schema": { + "required": [ + "file" + ], + "type": "object", + "properties": { + "file": { + "type": "string", + "description": "file", + "format": "binary" + } + } + } + } + } + }, + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ModelApiResponse" + } + }, + "*/*": { + "schema": { + "$ref": "#/components/schemas/ModelApiResponse" + } + } + } + } + }, + "security": [ + { + "petstore_auth": [ + "write:pets", + "read:pets" + ] + } + ] } - } - ], - "responses": { - "200": { - "description": "OK", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Pet_1" - } - }, - "application/xml": { - "schema": { - "$ref": "#/components/schemas/Pet_1" - } - } + }, + "/store/inventory": { + "get": { + "tags": [ + "store" + ], + "summary": "Returns pet inventories by status", + "description": "Returns a map of status codes to quantities", + "operationId": "getInventoryUsingGET", + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": { + "type": "integer", + "format": "int32" + } + } + } + } + } + }, + "security": [ + { + "api_key": [ + + ] + } + ] } - }, - "400": { - "description": "Invalid ID supplied", - "headers": { - "header4": { - "schema": { - "type": "string" - } - }, - "header3": { - "schema": { - "type": "string" - } - }, - "header2": { - "schema": { - "type": "string" - } - }, - "header1": { - "schema": { - "type": "string" + }, + "/store/order": { + "post": { + "tags": [ + "store" + ], + "summary": "Place an order for a pet", + "description": "Place a new order in the store", + "operationId": "placeOrderUsingPOST", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Order" + } + }, + "application/x-www-form-urlencoded": { + "schema": { + "$ref": "#/components/schemas/Order" + } + }, + "application/xml": { + "schema": { + "$ref": "#/components/schemas/Order" + } + } + } + }, + "responses": { + "200": { + "description": "successful operation", + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/Order" + } + }, + "application/json": { + "schema": { + "$ref": "#/components/schemas/Order" + } + } + } + }, + "405": { + "description": "Invalid input" + } } - } } - }, - "404": { - "description": "Pet not found", - "headers": { - "header4": { - "schema": { - "type": "string" + }, + "/store/order/{orderId}": { + "get": { + "tags": [ + "store" + ], + "summary": "Find purchase order by ID", + "description": "For valid response try integer IDs with value <= 5 or > 10. Other values will generated exceptions", + "operationId": "getOrderByIdUsingGET", + "parameters": [ + { + "name": "orderId", + "in": "path", + "description": "ID of order that needs to be fetched", + "required": true, + "style": "simple", + "schema": { + "maximum": 5, + "exclusiveMaximum": false, + "minimum": 1, + "exclusiveMinimum": false, + "type": "integer", + "format": "int64" + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/xml": { + "schema": { + "$ref": "#/components/schemas/Order" + } + }, + "*/*": { + "schema": { + "$ref": "#/components/schemas/Order" + } + }, + "application/json": { + "schema": { + "$ref": "#/components/schemas/Order" + } + } + } + }, + "400": { + "description": "Invalid ID supplied" + }, + "404": { + "description": "Order not found" + } } - }, - "header3": { - "schema": { - "type": "string" + }, + "delete": { + "tags": [ + "store" + ], + "summary": "Delete purchase order by ID", + "description": "For valid response try integer IDs with value < 1000. Anything above 1000 or nonintegers will generate API errors", + "operationId": "deleteOrderUsingDELETE", + "parameters": [ + { + "name": "orderId", + "in": "path", + "description": "ID of the order that needs to be deleted", + "required": true, + "style": "simple", + "schema": { + "type": "integer", + "format": "int64" + } + } + ], + "responses": { + "200": { + "description": "OK" + }, + "400": { + "description": "Invalid ID supplied" + }, + "404": { + "description": "Order not found" + } } - } } - } }, - "security": [ - { - "petstore_auth": [ - "write:pets", - "read:pets" - ] - }, - { - "api_key": [] - } - ], - "deprecated": false - } - }, - "/api/store/order": { - "post": { - "tags": [ - "pet-store-resource" - ], - "summary": "Place an order for a pet", - "operationId": "placeOrderUsingPOST", - "parameters": [ - { - "name": "status", - "in": "query", - "description": "Order Status", - "required": false, - "schema": { - "type": "string", - "enum": [ - "placed", - "approved", - "delivered" - ] - } - }, - { - "name": "complete", - "in": "query", - "required": false, - "schema": { - "type": "boolean" - } - }, - { - "name": "id", - "in": "query", - "required": false, - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "name": "identifier", - "in": "query", - "required": false, - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "name": "petId", - "in": "query", - "required": false, - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "name": "quantity", - "in": "query", - "required": false, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "shipDate", - "in": "query", - "required": false, - "schema": { - "type": "string", - "format": "date-time" - } - } - ], - "responses": { - "200": { - "description": "OK", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Order" + "/user": { + "post": { + "tags": [ + "user" + ], + "summary": "Create user", + "description": "This can only be done by the logged in user.", + "operationId": "createUserUsingPOST", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/User" + } + }, + "application/x-www-form-urlencoded": { + "schema": { + "$ref": "#/components/schemas/User" + } + }, + "application/xml": { + "schema": { + "$ref": "#/components/schemas/User" + } + } + } + }, + "responses": { + "200": { + "description": "OK" + }, + "default": { + "description": "successful operation", + "content": { + "application/xml": { + "schema": { + "$ref": "#/components/schemas/User" + } + }, + "application/json": { + "schema": { + "$ref": "#/components/schemas/User" + } + } + } + } } - } } - }, - "400": { - "description": "Invalid Order" - } }, - "deprecated": false - } - }, - "/api/store/order/{orderId}": { - "get": { - "tags": [ - "Pet Store" - ], - "summary": "Find purchase order by ID", - "description": "For valid response try integer IDs with value <= 5 or > 10. Other values will generated exceptions", - "operationId": "getOrderByIdUsingGET", - "parameters": [ - { - "name": "orderId", - "in": "path", - "description": "ID of pet that needs to be fetched", - "required": true, - "schema": { - "type": "string", - "minLength": 1, - "maxLength": 5 - } - } - ], - "responses": { - "200": { - "description": "OK", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Order" + "/user/createWithArray": { + "post": { + "tags": [ + "user" + ], + "summary": "Creates list of users with given input array", + "operationId": "createUsersWithArrayInputUsingPOST", + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/User" + } + } + } + } + }, + "responses": { + "200": { + "description": "successful operation" + } } - } } - }, - "400": { - "description": "Invalid ID supplied" - }, - "404": { - "description": "Order not found" - } }, - "deprecated": false - }, - "delete": { - "tags": [ - "pet-store-resource" - ], - "summary": "Delete purchase order by ID", - "description": "For valid response try integer IDs with value < 1000. Anything above 1000 or non-integers will generate API errors", - "operationId": "deleteOrderUsingDELETE", - "parameters": [ - { - "name": "orderId", - "in": "path", - "description": "ID of the order that needs to be deleted", - "required": true, - "schema": { - "type": "string", - "minLength": 1 - } - } - ], - "responses": { - "200": { - "description": "OK", - "content": { - "application/json": { - "schema": { - "type": "string" + "/user/createWithList": { + "post": { + "tags": [ + "user" + ], + "summary": "Creates list of users with given input array", + "description": "Creates list of users with given input array", + "operationId": "createUsersWithListInputUsingPOST", + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/User" + } + } + } + } + }, + "responses": { + "200": { + "description": "Successful operation", + "content": { + "application/xml": { + "schema": { + "$ref": "#/components/schemas/User" + } + }, + "application/json": { + "schema": { + "$ref": "#/components/schemas/User" + } + } + } + }, + "default": { + "description": "successful operation" + } } - } - } - }, - "400": { - "description": "Invalid ID supplied" - }, - "404": { - "description": "Order not found" - } - }, - "deprecated": false - } - }, - "/api/user": { - "post": { - "tags": [ - "user-controller" - ], - "summary": "Create user", - "description": "This can only be done by the logged in user.", - "operationId": "createUserUsingPOST", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/User" - } } - }, - "description": "Created user object", - "required": true }, - "responses": { - "200": { - "description": "OK", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/User" + "/user/login": { + "get": { + "tags": [ + "user" + ], + "summary": "Logs user into the system", + "operationId": "loginUserUsingGET", + "parameters": [ + { + "name": "password", + "in": "query", + "description": "The password for login in clear text", + "required": true, + "style": "form", + "schema": { + "type": "string" + } + }, + { + "name": "username", + "in": "query", + "description": "The user name for login", + "required": true, + "style": "form", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "headers": { + "X-Rate-Limit": { + "description": "calls per hour allowed by the user", + "required": false, + "schema": { + "type": "integer", + "format": "int32" + } + }, + "X-Expires-After": { + "description": "date in UTC when toekn expires", + "required": false, + "schema": { + "type": "string", + "format": "date-time" + } + } + }, + "content": { + "application/xml": { + "schema": { + "type": "string" + } + }, + "*/*": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "Invalid username/password supplied" + } } - } } - } - }, - "deprecated": false - } - }, - "/api/user/createWithArray": { - "post": { - "tags": [ - "user-controller" - ], - "summary": "Creates list of users with given input array", - "operationId": "createUsersWithArrayInputUsingPOST", - "requestBody": { - "$ref": "#/components/requestBodies/UserArray" }, - "responses": { - "200": { - "description": "OK", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/User" + "/user/logout": { + "get": { + "tags": [ + "user" + ], + "summary": "Logs out current logged in user session", + "operationId": "logoutUserUsingGET", + "responses": { + "200": { + "description": "OK" + }, + "default": { + "description": "successful operation" + } } - } } - } - }, - "deprecated": false - } - }, - "/api/user/createWithList": { - "post": { - "tags": [ - "user-controller" - ], - "summary": "Creates list of users with given input array", - "operationId": "createUsersWithListInputUsingPOST", - "requestBody": { - "$ref": "#/components/requestBodies/UserArray" }, - "responses": { - "200": { - "description": "OK", - "content": { - "application/json": { - "schema": { - "type": "string" + "/user/{username}": { + "get": { + "tags": [ + "user" + ], + "summary": "Get user by user name", + "operationId": "getUserByNameUsingGET", + "parameters": [ + { + "name": "username", + "in": "path", + "description": "The name that needs to be fetched. Use user1 for testing. ", + "required": true, + "style": "simple", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/xml": { + "schema": { + "$ref": "#/components/schemas/User" + } + }, + "application/json": { + "schema": { + "$ref": "#/components/schemas/User" + } + }, + "*/*": { + "schema": { + "$ref": "#/components/schemas/User" + } + } + } + }, + "400": { + "description": "Invalid username supplied" + }, + "404": { + "description": "User not found" + } } - } - } - } - }, - "deprecated": false - } - }, - "/api/user/login": { - "get": { - "tags": [ - "user-controller" - ], - "summary": "Logs user into the system", - "operationId": "loginUserUsingGET", - "parameters": [ - { - "name": "password", - "in": "query", - "description": "The password for login in clear text", - "required": true, - "allowEmptyValue": false, - "schema": { - "type": "string" - } - }, - { - "name": "username", - "in": "query", - "description": "The user name for login", - "required": true, - "allowEmptyValue": false, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK", - "content": { - "application/json": { - "schema": { - "type": "string" + }, + "put": { + "tags": [ + "user" + ], + "summary": "Update user", + "description": "This can only be done by the logged in user.", + "operationId": "updateUserUsingPUT", + "parameters": [ + { + "name": "username", + "in": "path", + "description": "name that need to be deleted", + "required": true, + "style": "simple", + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/User" + } + }, + "application/x-www-form-urlencoded": { + "schema": { + "$ref": "#/components/schemas/User" + } + }, + "application/xml": { + "schema": { + "$ref": "#/components/schemas/User" + } + } + } + }, + "responses": { + "200": { + "description": "OK" + }, + "default": { + "description": "successful operation" + } } - } - } - }, - "400": { - "description": "Invalid username/password supplied" - } - }, - "deprecated": false - } - }, - "/api/user/logout": { - "get": { - "tags": [ - "user-controller" - ], - "summary": "Logs out current logged in user session", - "operationId": "logoutUserUsingGET", - "responses": { - "200": { - "description": "OK", - "content": { - "application/json": { - "schema": { - "type": "string" + }, + "delete": { + "tags": [ + "user" + ], + "summary": "Delete user", + "description": "This can only be done by the logged in user.", + "operationId": "deleteUserUsingDELETE", + "parameters": [ + { + "name": "username", + "in": "path", + "description": "The name that needs to be deleted", + "required": true, + "style": "simple", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "OK" + }, + "400": { + "description": "Invalid username supplied" + }, + "404": { + "description": "User not found" + } } - } } - } - }, - "deprecated": false - } + } }, - "/api/user/{username}": { - "get": { - "tags": [ - "user-controller" - ], - "summary": "Get user by user name", - "operationId": "getUserByNameUsingGET", - "parameters": [ - { - "name": "username", - "in": "path", - "description": "The name that needs to be fetched. Use user1 for testing. ", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/User" + "components": { + "schemas": { + "Category": { + "title": "Category", + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int64", + "example": 1 + }, + "name": { + "type": "string", + "example": "Dogs" + } } - } - } - }, - "400": { - "description": "Invalid username supplied" - }, - "404": { - "description": "User not found" - } - }, - "deprecated": false - }, - "put": { - "tags": [ - "user-controller" - ], - "summary": "Updated user", - "description": "This can only be done by the logged in user.", - "operationId": "updateUserUsingPUT", - "parameters": [ - { - "name": "userStatus", - "in": "query", - "description": "User Status", - "required": false, - "schema": { - "type": "integer", - "format": "int32", - "enum": [ - "1-registered", - "2-active", - "3-closed" - ] - } - }, - { - "name": "username", - "in": "path", - "description": "name that need to be deleted", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "email", - "in": "query", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "firstName", - "in": "query", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "id", - "in": "query", - "required": false, - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "name": "identifier", - "in": "query", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "lastName", - "in": "query", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "password", - "in": "query", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "phone", - "in": "query", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "username", - "in": "query", - "required": false, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK", - "content": { - "application/json": { - "schema": { - "type": "string" + }, + "ModelApiResponse": { + "title": "ModelApiResponse", + "type": "object", + "properties": { + "code": { + "type": "integer", + "format": "int32" + }, + "message": { + "type": "string" + }, + "type": { + "type": "string" + } } - } - } - }, - "400": { - "description": "Invalid user supplied" - }, - "404": { - "description": "User not found" - } - }, - "deprecated": false - }, - "delete": { - "tags": [ - "user-controller" - ], - "summary": "Delete user", - "description": "This can only be done by the logged in user.", - "operationId": "deleteUserUsingDELETE", - "parameters": [ - { - "name": "username", - "in": "path", - "description": "The name that needs to be deleted", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK", - "content": { - "application/json": { - "schema": { - "type": "string" + }, + "Order": { + "title": "Order", + "type": "object", + "properties": { + "complete": { + "type": "boolean", + "example": false + }, + "id": { + "type": "integer", + "format": "int64", + "example": 10 + }, + "petId": { + "type": "integer", + "format": "int64", + "example": 198772 + }, + "quantity": { + "type": "integer", + "format": "int32", + "example": 7 + }, + "shipDate": { + "type": "string", + "format": "date-time" + }, + "status": { + "type": "string", + "description": "Order Status", + "example": "approved", + "enum": [ + "approved", + "delivered", + "placed" + ] + } + } + }, + "Pet": { + "title": "Pet", + "required": [ + "name", + "photoUrls" + ], + "type": "object", + "properties": { + "category": { + "$ref": "#/components/schemas/Category" + }, + "id": { + "type": "integer", + "format": "int64", + "example": 10 + }, + "name": { + "type": "string", + "example": "doggie" + }, + "photoUrls": { + "type": "array", + "items": { + "type": "string" + } + }, + "status": { + "type": "string", + "description": "pet status in the store", + "enum": [ + "available", + "pending", + "sold" + ] + }, + "tags": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Tag" + } + } + } + }, + "Tag": { + "title": "Tag", + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int64" + }, + "name": { + "type": "string" + } + } + }, + "User": { + "title": "User", + "type": "object", + "properties": { + "email": { + "type": "string", + "example": "john@email.com" + }, + "firstName": { + "type": "string", + "example": "John" + }, + "id": { + "type": "integer", + "format": "int64", + "example": 10 + }, + "lastName": { + "type": "string", + "example": "James" + }, + "password": { + "type": "string", + "example": "12345" + }, + "phone": { + "type": "string", + "example": "12345" + }, + "userStatus": { + "type": "integer", + "description": "User Status", + "format": "int32", + "example": 1 + }, + "username": { + "type": "string", + "example": "theUser" + } } - } - } - }, - "400": { - "description": "Invalid username supplied" - }, - "404": { - "description": "User not found" - } - }, - "deprecated": false - } - } - }, - "servers": [ - { - "url": "http://petstore.swagger.io/" - }, - { - "url": "https://petstore.swagger.io/" - } - ], - "components": { - "requestBodies": { - "UserArray": { - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/User" - } - } - } - }, - "description": "List of user object", - "required": true - }, - "Pet": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Pet" } - } }, - "description": "Pet object that needs to be added to the store", - "required": true - } - }, - "securitySchemes": { - "api_key": { - "type": "apiKey", - "name": "api_key", - "in": "header" - }, - "petstore_auth": { - "type": "oauth2", - "flows": { - "implicit": { - "authorizationUrl": "http://petstore.swagger.io/api/oauth/dialog", - "scopes": { - "write:pets": "modify pets in your account", - "read:pets": "read your pets" + "securitySchemes": { + "petstore_auth": { + "type": "oauth2", + "flows": { + "implicit": { + "authorizationUrl": "https://petstore3.swagger.io/oauth/authorize", + "scopes": { + "write:pets": "Write scope", + "read:pets": "Read scope" + } + } + } + }, + "api_key": { + "type": "apiKey", + "name": "api_key", + "in": "header" + }, + "basicScheme": { + "type": "http", + "scheme": "basic" } - } } - } - }, - "schemas": { - "Category": { - "type": "object", - "required": [ - "id" - ], - "properties": { - "id": { - "type": "integer", - "format": "int64" - }, - "name": { - "type": "string" - } - }, - "title": "Category" - }, - "Category_1": { - "type": "object", - "properties": { - "id": { - "type": "integer", - "format": "int64" - }, - "name": { - "type": "string" - } - }, - "title": "Category_1" - }, - "Order": { - "type": "object", - "properties": { - "complete": { - "type": "boolean" - }, - "id": { - "type": "integer", - "format": "int64" - }, - "identifier": { - "type": "integer", - "format": "int64" - }, - "petId": { - "type": "integer", - "format": "int64" - }, - "quantity": { - "type": "integer", - "format": "int32" - }, - "shipDate": { - "type": "string", - "format": "date-time" - }, - "status": { - "type": "string", - "description": "Order Status", - "enum": [ - "placed", - "approved", - "delivered" - ] - } - }, - "title": "Order" - }, - "Pet": { - "type": "object", - "properties": { - "category": { - "$ref": "#/components/schemas/Category" - }, - "id": { - "type": "integer", - "format": "int64" - }, - "name": { - "type": "string" - }, - "photoUrls": { - "type": "array", - "items": { - "type": "string" - } - }, - "status": { - "type": "string", - "description": "pet status in the store", - "enum": [ - "available", - "pending", - "sold" - ] - }, - "tags": { - "type": "array", - "items": { - "$ref": "#/components/schemas/Tag" - } - } - }, - "title": "Pet" - }, - "Pet_1": { - "type": "object", - "properties": { - "category": { - "$ref": "#/components/schemas/Category_1" - }, - "id": { - "type": "integer", - "format": "int64" - }, - "identifier": { - "type": "integer", - "format": "int64" - }, - "name": { - "type": "string" - }, - "photoUrls": { - "type": "array", - "items": { - "type": "string" - } - }, - "status": { - "type": "string", - "description": "pet status in the store", - "enum": [ - "available", - "pending", - "sold" - ] - }, - "tags": { - "type": "array", - "items": { - "$ref": "#/components/schemas/Tag" - } - } - }, - "title": "Pet_1" - }, - "Tag": { - "type": "object", - "properties": { - "id": { - "type": "integer", - "format": "int64" - }, - "name": { - "type": "string" - } - }, - "title": "Tag" - }, - "User": { - "type": "object", - "properties": { - "email": { - "type": "string" - }, - "firstName": { - "type": "string" - }, - "id": { - "type": "integer", - "format": "int64" - }, - "identifier": { - "type": "string" - }, - "lastName": { - "type": "string" - }, - "password": { - "type": "string" - }, - "phone": { - "type": "string" - }, - "userStatus": { - "type": "integer", - "format": "int32", - "description": "User Status" - }, - "username": { - "type": "string" - } - }, - "title": "User" - }, - "User_1": { - "type": "object", - "properties": { - "email": { - "type": "string" - }, - "firstName": { - "type": "string" - }, - "id": { - "type": "integer", - "format": "int64" - }, - "lastName": { - "type": "string" - }, - "password": { - "type": "string" - }, - "phone": { - "type": "string" - }, - "userStatus": { - "type": "integer", - "format": "int32", - "description": "User Status" - }, - "username": { - "type": "string" - } - }, - "title": "User_1" - } } - } } \ No newline at end of file