From 332dd10f421262c9fda1b97c9c3663aebcee3a4e Mon Sep 17 00:00:00 2001
From: Alexandre Touret <alexandre.touret@free.fr>
Date: Tue, 15 Feb 2022 12:59:36 +0100
Subject: [PATCH] feat: Fix and update specialty controller

---
 .../controller/SpecialtyRestController.java   |  53 ++--
 src/main/resources/openapi.yml                | 259 +++++++++++++++++-
 .../SpecialtyRestControllerTests.java         |   8 +-
 3 files changed, 283 insertions(+), 37 deletions(-)

diff --git a/src/main/java/org/springframework/samples/petclinic/rest/controller/SpecialtyRestController.java b/src/main/java/org/springframework/samples/petclinic/rest/controller/SpecialtyRestController.java
index 08c3eda2..6ebf9896 100644
--- a/src/main/java/org/springframework/samples/petclinic/rest/controller/SpecialtyRestController.java
+++ b/src/main/java/org/springframework/samples/petclinic/rest/controller/SpecialtyRestController.java
@@ -16,22 +16,24 @@
 
 package org.springframework.samples.petclinic.rest.controller;
 
+import io.swagger.annotations.ApiParam;
 import org.springframework.http.HttpHeaders;
 import org.springframework.http.HttpStatus;
 import org.springframework.http.ResponseEntity;
-import org.springframework.samples.petclinic.rest.dto.SpecialtyDto;
 import org.springframework.samples.petclinic.mapper.SpecialtyMapper;
 import org.springframework.samples.petclinic.model.Specialty;
+import org.springframework.samples.petclinic.rest.api.SpecialtiesApi;
+import org.springframework.samples.petclinic.rest.dto.SpecialtyDto;
 import org.springframework.samples.petclinic.service.ClinicService;
 import org.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.validation.BindingResult;
 import org.springframework.web.bind.annotation.*;
 import org.springframework.web.util.UriComponentsBuilder;
 
 import javax.transaction.Transactional;
 import javax.validation.Valid;
+import javax.validation.constraints.Min;
 import java.util.ArrayList;
-import java.util.Collection;
+import java.util.List;
 
 /**
  * @author Vitaliy Fedoriv
@@ -40,7 +42,7 @@ import java.util.Collection;
 @RestController
 @CrossOrigin(exposedHeaders = "errors, content-type")
 @RequestMapping("api/specialties")
-public class SpecialtyRestController {
+public class SpecialtyRestController implements SpecialtiesApi {
 
     private final ClinicService clinicService;
 
@@ -53,18 +55,20 @@ public class SpecialtyRestController {
 
     @PreAuthorize("hasRole(@roles.VET_ADMIN)")
     @RequestMapping(value = "", method = RequestMethod.GET, produces = "application/json")
-    public ResponseEntity<Collection<SpecialtyDto>> getAllSpecialtys() {
-        Collection<SpecialtyDto> specialties = new ArrayList<SpecialtyDto>();
+    @Override
+    public ResponseEntity<List<SpecialtyDto>> listSpecialties() {
+        List<SpecialtyDto> specialties = new ArrayList<SpecialtyDto>();
         specialties.addAll(specialtyMapper.toSpecialtyDtos(this.clinicService.findAllSpecialties()));
         if (specialties.isEmpty()) {
-            return new ResponseEntity<Collection<SpecialtyDto>>(HttpStatus.NOT_FOUND);
+            return new ResponseEntity<>(HttpStatus.NOT_FOUND);
         }
-        return new ResponseEntity<Collection<SpecialtyDto>>(specialties, HttpStatus.OK);
+        return new ResponseEntity<>(specialties, HttpStatus.OK);
     }
 
     @PreAuthorize("hasRole(@roles.VET_ADMIN)")
     @RequestMapping(value = "/{specialtyId}", method = RequestMethod.GET, produces = "application/json")
-    public ResponseEntity<SpecialtyDto> getSpecialty(@PathVariable("specialtyId") int specialtyId) {
+    @Override
+    public ResponseEntity<SpecialtyDto> getSpecialty(@Min(0) @ApiParam(value = "The ID of the pet.", required = true) @PathVariable("specialtyId") Integer specialtyId) {
         Specialty specialty = this.clinicService.findSpecialtyById(specialtyId);
         if (specialty == null) {
             return new ResponseEntity<SpecialtyDto>(HttpStatus.NOT_FOUND);
@@ -74,49 +78,40 @@ public class SpecialtyRestController {
 
     @PreAuthorize("hasRole(@roles.VET_ADMIN)")
     @RequestMapping(value = "", method = RequestMethod.POST, produces = "application/json")
-    public ResponseEntity<SpecialtyDto> addSpecialty(@RequestBody @Valid SpecialtyDto specialtyDto, BindingResult bindingResult, UriComponentsBuilder ucBuilder) {
+    @Override
+    public ResponseEntity<SpecialtyDto> addSpecialty(@ApiParam(value = "The specialty", required = true) @Valid @RequestBody SpecialtyDto specialtyDto) {
         BindingErrorsResponse errors = new BindingErrorsResponse();
         HttpHeaders headers = new HttpHeaders();
-        if (bindingResult.hasErrors() || (specialtyDto == null)) {
-            errors.addAllErrors(bindingResult);
-            headers.add("errors", errors.toJSON());
-            return new ResponseEntity<SpecialtyDto>(headers, HttpStatus.BAD_REQUEST);
-        }
         Specialty specialty = specialtyMapper.toSpecialty(specialtyDto);
         this.clinicService.saveSpecialty(specialty);
-        headers.setLocation(ucBuilder.path("/api/specialtys/{id}").buildAndExpand(specialty.getId()).toUri());
+        headers.setLocation(UriComponentsBuilder.newInstance().path("/api/specialtys/{id}").buildAndExpand(specialty.getId()).toUri());
         return new ResponseEntity<SpecialtyDto>(specialtyMapper.toSpecialtyDto(specialty), headers, HttpStatus.CREATED);
     }
 
     @PreAuthorize("hasRole(@roles.VET_ADMIN)")
     @RequestMapping(value = "/{specialtyId}", method = RequestMethod.PUT, produces = "application/json")
-    public ResponseEntity<SpecialtyDto> updateSpecialty(@PathVariable("specialtyId") int specialtyId, @RequestBody @Valid SpecialtyDto specialtyDto, BindingResult bindingResult) {
-        BindingErrorsResponse errors = new BindingErrorsResponse();
-        HttpHeaders headers = new HttpHeaders();
-        if (bindingResult.hasErrors() || (specialtyDto == null)) {
-            errors.addAllErrors(bindingResult);
-            headers.add("errors", errors.toJSON());
-            return new ResponseEntity<SpecialtyDto>(headers, HttpStatus.BAD_REQUEST);
-        }
+    @Override
+    public ResponseEntity<SpecialtyDto> updateSpecialty(@Min(0) @ApiParam(value = "The ID of the specialty.", required = true) @PathVariable("specialtyId") Integer specialtyId, @ApiParam(value = "The pet", required = true) @Valid @RequestBody SpecialtyDto specialtyDto) {
         Specialty currentSpecialty = this.clinicService.findSpecialtyById(specialtyId);
         if (currentSpecialty == null) {
-            return new ResponseEntity<SpecialtyDto>(HttpStatus.NOT_FOUND);
+            return new ResponseEntity<>(HttpStatus.NOT_FOUND);
         }
         currentSpecialty.setName(specialtyDto.getName());
         this.clinicService.saveSpecialty(currentSpecialty);
-        return new ResponseEntity<SpecialtyDto>(specialtyMapper.toSpecialtyDto(currentSpecialty), HttpStatus.NO_CONTENT);
+        return new ResponseEntity<>(specialtyMapper.toSpecialtyDto(currentSpecialty), HttpStatus.NO_CONTENT);
     }
 
     @PreAuthorize("hasRole(@roles.VET_ADMIN)")
     @RequestMapping(value = "/{specialtyId}", method = RequestMethod.DELETE, produces = "application/json")
     @Transactional
-    public ResponseEntity<Void> deleteSpecialty(@PathVariable("specialtyId") int specialtyId) {
+    @Override
+    public ResponseEntity<SpecialtyDto> deleteSpecialty(@Min(0) @ApiParam(value = "The ID of the specialty.", required = true) @PathVariable("specialtyId") Integer specialtyId) {
         Specialty specialty = this.clinicService.findSpecialtyById(specialtyId);
         if (specialty == null) {
-            return new ResponseEntity<Void>(HttpStatus.NOT_FOUND);
+            return new ResponseEntity<>(HttpStatus.NOT_FOUND);
         }
         this.clinicService.deleteSpecialty(specialty);
-        return new ResponseEntity<Void>(HttpStatus.NO_CONTENT);
+        return new ResponseEntity<>(HttpStatus.NO_CONTENT);
     }
 
 }
diff --git a/src/main/resources/openapi.yml b/src/main/resources/openapi.yml
index a5a5cf17..310ad8bc 100755
--- a/src/main/resources/openapi.yml
+++ b/src/main/resources/openapi.yml
@@ -525,7 +525,7 @@ paths:
               schema:
                 $ref: '#/components/schemas/RestError'
         404:
-          description: Owner not found.
+          description: Pet Type not found.
           content:
             application/json:
               schema:
@@ -579,7 +579,7 @@ paths:
               schema:
                 $ref: '#/components/schemas/RestError'
         404:
-          description: Owner not found.
+          description: Pet Type not found.
           content:
             application/json:
               schema:
@@ -639,7 +639,7 @@ paths:
               schema:
                 $ref: '#/components/schemas/RestError'
         404:
-          description: Owner not found.
+          description: Pet Type not found.
           content:
             application/json:
               schema:
@@ -740,7 +740,7 @@ paths:
                 $ref: '#/components/schemas/RestError'
     post:
       tags:
-        - petw
+        - pet
       operationId: addPet
       summary: Create a pet
       description: Creates a pet .
@@ -955,6 +955,257 @@ paths:
             application/json:
               schema:
                 $ref: '#/components/schemas/RestError'
+  /specialties:
+    get:
+      tags:
+        - specialty
+      operationId: listSpecialties
+      summary: Lists specialties
+      description: Returns an array of specialty .
+      responses:
+        200:
+          description: Specialties found and returned.
+          headers:
+            ETag:
+              description: An ID for this version of the response.
+              schema:
+                type: string
+          content:
+            application/json:
+              schema:
+                type: array
+                items:
+                  $ref: '#/components/schemas/Specialty'
+        304:
+          description: Not modified.
+          headers:
+            ETag:
+              description: An ID for this version of the response.
+              schema:
+                type: string
+        500:
+          description: Server error.
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/RestError'
+    post:
+      tags:
+        - specialty
+      operationId: addSpecialty
+      summary: Create a specialty
+      description: Creates a specialty .
+      requestBody:
+        description: The specialty
+        content:
+          application/json:
+            schema:
+              $ref: '#/components/schemas/Specialty'
+        required: true
+      responses:
+        200:
+          description: Specialty created successfully.
+          headers:
+            ETag:
+              description: An ID for this version of the response.
+              schema:
+                type: string
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/Specialty'
+        304:
+          description: Not modified.
+          headers:
+            ETag:
+              description: An ID for this version of the response.
+              schema:
+                type: string
+        400:
+          description: Bad request.
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/RestError'
+        404:
+          description: Owner not found.
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/RestError'
+        500:
+          description: Server error.
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/RestError'
+  /specialties/{specialtyId}:
+    get:
+      tags:
+        - specialty
+      operationId: getSpecialty
+      summary: Get a specialty by ID
+      description: Returns the specialty or a 404 error.
+      parameters:
+        - name: specialtyId
+          in: path
+          description: The ID of the pet.
+          required: true
+          schema:
+            type: integer
+            format: int32
+            minimum: 0
+            example: 1
+      responses:
+        200:
+          description: Specialty details found and returned.
+          headers:
+            ETag:
+              description: An ID for this version of the response.
+              schema:
+                type: string
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/Specialty'
+        304:
+          description: Not modified.
+          headers:
+            ETag:
+              description: An ID for this version of the response.
+              schema:
+                type: string
+        400:
+          description: Bad request.
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/RestError'
+        404:
+          description: Specialty not found.
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/RestError'
+        500:
+          description: Server error.
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/RestError'
+    put:
+      tags:
+        - specialty
+      operationId: updateSpecialty
+      summary: Update a specialty by ID
+      description: Returns the specialty or a 404 error.
+      parameters:
+        - name: specialtyId
+          in: path
+          description: The ID of the specialty.
+          required: true
+          schema:
+            type: integer
+            format: int32
+            minimum: 0
+            example: 1
+      requestBody:
+        description: The pet
+        content:
+          application/json:
+            schema:
+              $ref: '#/components/schemas/Specialty'
+        required: true
+      responses:
+        200:
+          description: Specialty details found and returned.
+          headers:
+            ETag:
+              description: An ID for this version of the response.
+              schema:
+                type: string
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/Specialty'
+        304:
+          description: Not modified.
+          headers:
+            ETag:
+              description: An ID for this version of the response.
+              schema:
+                type: string
+        400:
+          description: Bad request.
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/RestError'
+        404:
+          description: Specialty not found.
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/RestError'
+        500:
+          description: Server error.
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/RestError'
+    delete:
+      tags:
+        - specialty
+      operationId: deleteSpecialty
+      summary: Delete a specialty by ID
+      description: Returns the specialty or a 404 error.
+      parameters:
+        - name: specialtyId
+          in: path
+          description: The ID of the specialty.
+          required: true
+          schema:
+            type: integer
+            format: int32
+            minimum: 0
+            example: 1
+      responses:
+        200:
+          description: Specialty details found and returned.
+          headers:
+            ETag:
+              description: An ID for this version of the response.
+              schema:
+                type: string
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/Specialty'
+        304:
+          description: Not modified.
+          headers:
+            ETag:
+              description: An ID for this version of the response.
+              schema:
+                type: string
+        400:
+          description: Bad request.
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/RestError'
+        404:
+          description: Specialty not found.
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/RestError'
+        500:
+          description: Server error.
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/RestError'
   /vets:
     get:
       tags:
diff --git a/src/test/java/org/springframework/samples/petclinic/rest/controller/SpecialtyRestControllerTests.java b/src/test/java/org/springframework/samples/petclinic/rest/controller/SpecialtyRestControllerTests.java
index 4ec68cc8..7f1ea114 100644
--- a/src/test/java/org/springframework/samples/petclinic/rest/controller/SpecialtyRestControllerTests.java
+++ b/src/test/java/org/springframework/samples/petclinic/rest/controller/SpecialtyRestControllerTests.java
@@ -104,8 +104,8 @@ class SpecialtyRestControllerTests {
     @Test
     @WithMockUser(roles="VET_ADMIN")
     void testGetSpecialtyNotFound() throws Exception {
-    	given(this.clinicService.findSpecialtyById(-1)).willReturn(null);
-        this.mockMvc.perform(get("/api/specialties/-1")
+    	given(this.clinicService.findSpecialtyById(999)).willReturn(null);
+        this.mockMvc.perform(get("/api/specialties/999")
         	.accept(MediaType.APPLICATION_JSON))
             .andExpect(status().isNotFound());
     }
@@ -211,8 +211,8 @@ class SpecialtyRestControllerTests {
     	Specialty newSpecialty = specialties.get(0);
     	ObjectMapper mapper = new ObjectMapper();
         String newSpecialtyAsJSON = mapper.writeValueAsString(specialtyMapper.toSpecialtyDto(newSpecialty));
-    	given(this.clinicService.findSpecialtyById(-1)).willReturn(null);
-    	this.mockMvc.perform(delete("/api/specialties/-1")
+    	given(this.clinicService.findSpecialtyById(999)).willReturn(null);
+    	this.mockMvc.perform(delete("/api/specialties/999")
     		.content(newSpecialtyAsJSON).accept(MediaType.APPLICATION_JSON_VALUE).contentType(MediaType.APPLICATION_JSON_VALUE))
         	.andExpect(status().isNotFound());
     }
-- 
GitLab