View Javadoc
1   package fr.tiogars.chat.domains.task.controllers;
2   
3   import java.nio.charset.StandardCharsets;
4   import java.util.List;
5   
6   import org.springframework.http.ContentDisposition;
7   import org.springframework.http.HttpHeaders;
8   import org.springframework.http.HttpStatus;
9   import org.springframework.http.MediaType;
10  import org.springframework.http.ResponseEntity;
11  import org.springframework.web.bind.annotation.GetMapping;
12  import org.springframework.web.bind.annotation.PostMapping;
13  import org.springframework.web.bind.annotation.RequestBody;
14  import org.springframework.web.bind.annotation.RequestMapping;
15  import org.springframework.web.bind.annotation.ResponseStatus;
16  import org.springframework.web.bind.annotation.RestController;
17  import org.springframework.web.server.ResponseStatusException;
18  
19  import fr.tiogars.chat.domains.task.models.CreateTaskRequest;
20  import fr.tiogars.chat.domains.task.models.Task;
21  import fr.tiogars.chat.domains.task.services.TaskCsvCodec;
22  import fr.tiogars.chat.domains.task.services.TaskFindAllService;
23  import fr.tiogars.chat.domains.task.services.TaskSeedService;
24  import io.swagger.v3.oas.annotations.Operation;
25  import io.swagger.v3.oas.annotations.responses.ApiResponse;
26  import io.swagger.v3.oas.annotations.responses.ApiResponses;
27  import io.swagger.v3.oas.annotations.tags.Tag;
28  import jakarta.validation.Valid;
29  
30  /**
31   * Exposes JSON and CSV import/export endpoints for Tasks.
32   *
33   * @since 0.1.0
34   */
35  @Tag(name = "Tasks", description = "CRUD operations for the Task business object.")
36  @RestController
37  @RequestMapping("/api/v1/task")
38  public class TaskImportExportController {
39  
40      private final TaskFindAllService findAllService;
41      private final TaskSeedService seedService;
42      private final TaskCsvCodec csvCodec;
43  
44      /**
45       * Creates the import/export controller.
46       *
47       * @param findAllService domain record listing service
48       * @param seedService    domain record seed service
49       * @param csvCodec       CSV codec
50       */
51      public TaskImportExportController(
52              TaskFindAllService findAllService,
53              TaskSeedService seedService,
54              TaskCsvCodec csvCodec) {
55          this.findAllService = findAllService;
56          this.seedService = seedService;
57          this.csvCodec = csvCodec;
58      }
59  
60      /**
61       * Exports records as JSON.
62       *
63       * @return domain records
64       */
65      @Operation(summary = "Export domain records as JSON")
66      @ApiResponse(responseCode = "200", description = "Domain records were exported.")
67      @GetMapping(value = "/export.json", produces = MediaType.APPLICATION_JSON_VALUE)
68      public List<Task> exportJsonTask() {
69          return findAllService.findAll();
70      }
71  
72      /**
73       * Exports records as CSV.
74       *
75       * @return CSV response
76       */
77      @Operation(summary = "Export domain records as CSV")
78      @ApiResponse(responseCode = "200", description = "Domain records were exported.")
79      @GetMapping(value = "/export.csv", produces = "text/csv")
80      public ResponseEntity<String> exportCsvTask() {
81          String filename = "tasks.csv";
82          return ResponseEntity.ok()
83                  .contentType(new MediaType("text", "csv", StandardCharsets.UTF_8))
84                  .header(HttpHeaders.CONTENT_DISPOSITION,
85                          ContentDisposition.attachment().filename(filename).build().toString())
86                  .body(csvCodec.serialize(findAllService.findAll()));
87      }
88  
89      /**
90       * Imports JSON records.
91       *
92       * @param records records to import
93       * @return stored records
94       */
95      @Operation(summary = "Import domain records from JSON")
96      @ApiResponses(value = {
97              @ApiResponse(responseCode = "201", description = "Records were imported."),
98              @ApiResponse(responseCode = "400", description = "The import document is invalid.")
99      })
100     @PostMapping(value = "/import.json", consumes = MediaType.APPLICATION_JSON_VALUE)
101     @ResponseStatus(HttpStatus.CREATED)
102     public List<Task> importJsonTask(
103             @RequestBody List<@Valid CreateTaskRequest> records) {
104         return seedService.seed(records);
105     }
106 
107     /**
108      * Imports CSV records.
109      *
110      * @param csv CSV document
111      * @return stored records
112      */
113     @Operation(summary = "Import domain records from CSV")
114     @ApiResponses(value = {
115             @ApiResponse(responseCode = "201", description = "Records were imported."),
116             @ApiResponse(responseCode = "400", description = "The import document is invalid.")
117     })
118     @PostMapping(value = "/import.csv", consumes = "text/csv")
119     @ResponseStatus(HttpStatus.CREATED)
120     public List<Task> importCsvTask(@RequestBody String csv) {
121         try {
122             return seedService.seed(csvCodec.parse(csv));
123         } catch (IllegalArgumentException exception) {
124             throw new ResponseStatusException(HttpStatus.BAD_REQUEST, exception.getMessage(), exception);
125         }
126     }
127 }