diff --git a/src/main/java/net/onelitefeather/vulpes/backend/controller/ItemController.java b/src/main/java/net/onelitefeather/vulpes/backend/controller/ItemController.java deleted file mode 100644 index b6b7b0b..0000000 --- a/src/main/java/net/onelitefeather/vulpes/backend/controller/ItemController.java +++ /dev/null @@ -1,724 +0,0 @@ -package net.onelitefeather.vulpes.backend.controller; - -import io.micronaut.data.model.Page; -import io.micronaut.data.model.Pageable; -import io.micronaut.http.HttpResponse; -import io.micronaut.http.MediaType; -import io.micronaut.http.annotation.Body; -import io.micronaut.http.annotation.Controller; -import io.micronaut.http.annotation.Delete; -import io.micronaut.http.annotation.Get; -import io.micronaut.http.annotation.PathVariable; -import io.micronaut.http.annotation.Post; -import io.micronaut.http.annotation.Produces; -import io.micronaut.http.annotation.Put; -import io.micronaut.validation.Validated; -import io.swagger.v3.oas.annotations.Operation; -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 jakarta.inject.Inject; -import net.onelitefeather.vulpes.api.model.ItemEntity; -import net.onelitefeather.vulpes.backend.domain.item.ItemEnchantmentDTO; -import net.onelitefeather.vulpes.backend.domain.item.ItemEnchantmentResponseDTO; -import net.onelitefeather.vulpes.backend.domain.item.ItemFlagDTO; -import net.onelitefeather.vulpes.backend.domain.item.ItemFlagResponseDTO; -import net.onelitefeather.vulpes.backend.domain.item.ItemLoreDTO; -import net.onelitefeather.vulpes.backend.domain.item.ItemLoreResponseDTO; -import net.onelitefeather.vulpes.backend.domain.item.ItemModelDTO; -import net.onelitefeather.vulpes.backend.domain.item.ItemModelResponseDTO; -import net.onelitefeather.vulpes.backend.service.ItemService; -import net.onelitefeather.vulpes.backend.validation.ValidationGroup; - -import java.util.List; -import java.util.Optional; -import java.util.UUID; - -/** - * REST controller for item resources. - * Provides CRUD operations and nested resource management (enchantments, lore, flags). - */ -@Controller("/item") -public class ItemController { - - private final ItemService itemService; - - @Inject - public ItemController(ItemService itemService) { - this.itemService = itemService; - } - - @Operation( - summary = "Create a new item", - operationId = "addItem", - description = "Creates a new item with the provided properties and stores it in the database.", - tags = {"Item"} - ) - @ApiResponse( - responseCode = "200", - description = "Item successfully created.", - content = @Content( - mediaType = MediaType.APPLICATION_JSON, - schema = @Schema(implementation = ItemModelResponseDTO.ItemModelDTO.class) - ) - ) - @ApiResponse( - responseCode = "500", - description = "Item could not be created due to an internal error.", - content = @Content( - mediaType = MediaType.APPLICATION_JSON, - schema = @Schema(implementation = ItemModelResponseDTO.ItemModelErrorDTO.class) - ) - ) - @Post - @Produces(MediaType.APPLICATION_JSON) - @Validated(groups = ValidationGroup.Create.class) - public HttpResponse add( - @Body ItemModelDTO itemModel - ) { - ItemModelResponseDTO.ItemModelDTO createdItem = itemService.createItem(itemModel); - return HttpResponse.ok(createdItem); - } - - @Operation( - summary = "Get an item by ID", - operationId = "getItemById", - description = "Retrieves a single item from the database by its unique ID (itemId).", - tags = {"Item"} - ) - @ApiResponse( - responseCode = "200", - description = "Item successfully retrieved.", - content = @Content( - mediaType = MediaType.APPLICATION_JSON, - schema = @Schema(implementation = ItemModelResponseDTO.ItemModelDTO.class) - ) - ) - @ApiResponse( - responseCode = "404", - description = "Item with the given ID was not found.", - content = @Content( - mediaType = MediaType.APPLICATION_JSON, - schema = @Schema(implementation = ItemModelResponseDTO.ItemModelErrorDTO.class) - ) - ) - @Get("/{itemId}") - @Produces(MediaType.APPLICATION_JSON) - public HttpResponse getById( - @PathVariable("itemId") UUID itemId - ) { - Optional foundItemOpt = itemService.findItemById(itemId); - if (foundItemOpt.isPresent()) { - var foundItem = foundItemOpt.get(); - return HttpResponse.ok(ItemModelResponseDTO.ItemModelDTO.createDTO(foundItem)); - } - return HttpResponse.notFound(new ItemModelResponseDTO.ItemModelErrorDTO("Item not found")); - } - - @Operation( - summary = "Remove an item by ID", - operationId = "removeItemById", - description = "Deletes an item from the database by its unique ID (itemId).", - tags = {"Item"} - ) - @ApiResponse( - responseCode = "200", - description = "Item successfully deleted.", - content = @Content( - mediaType = MediaType.APPLICATION_JSON, - schema = @Schema(implementation = ItemModelResponseDTO.ItemModelDTO.class) - ) - ) - @ApiResponse( - responseCode = "404", - description = "Item with the given ID was not found.", - content = @Content( - mediaType = MediaType.APPLICATION_JSON, - schema = @Schema(implementation = ItemModelResponseDTO.ItemModelErrorDTO.class) - ) - ) - @Delete("/delete/{itemId}") - @Produces(MediaType.APPLICATION_JSON) - public HttpResponse remove(@PathVariable("itemId") UUID itemId) { - ItemModelResponseDTO deleteResult = itemService.deleteItem(itemId); - if (deleteResult instanceof ItemModelResponseDTO.ItemModelErrorDTO) { - return HttpResponse.notFound(deleteResult); - } - return HttpResponse.ok(deleteResult); - } - - @Operation( - summary = "Get all items", - operationId = "getAllItems", - description = "Retrieves a pageable list of all items. Supports standard Micronaut pagination (page, size, sort).", - tags = {"Item"} - ) - @ApiResponse( - responseCode = "200", - description = "Items successfully retrieved.", - content = @Content( - mediaType = MediaType.APPLICATION_JSON, - array = @ArraySchema( - schema = @Schema(implementation = ItemModelResponseDTO.ItemModelDTO.class), - arraySchema = @Schema(implementation = Page.class) - ) - ) - ) - @Get - @Produces(MediaType.APPLICATION_JSON) - public HttpResponse> getAll(Pageable pageable) { - Page itemsPage = itemService.getAllItems(pageable); - return HttpResponse.ok(itemsPage); - } - - @Operation( - summary = "Delete all items", - description = "Deletes all items from the database.", - tags = {"Item"} - ) - @ApiResponse( - responseCode = "200", - description = "All items were successfully deleted.", - content = @Content( - mediaType = MediaType.APPLICATION_JSON, - array = @ArraySchema( - schema = @Schema(implementation = ItemModelResponseDTO.ItemModelDTO.class) - ) - ) - ) - @Delete("/deleteAll") - @Produces(MediaType.APPLICATION_JSON) - public HttpResponse> deleteAll() { - List deleteResults = itemService.deleteAllItems(); - return HttpResponse.ok(deleteResults); - } - - @Operation( - summary = "Update an item", - operationId = "updateItem", - description = "Updates an existing item in the database.", - tags = {"Item"} - ) - @ApiResponse( - responseCode = "200", - description = "Item successfully updated.", - content = @Content( - mediaType = MediaType.APPLICATION_JSON, - schema = @Schema(implementation = ItemModelResponseDTO.ItemModelDTO.class) - ) - ) - @ApiResponse( - responseCode = "404", - description = "Item was not found and could not be updated.", - content = @Content( - mediaType = MediaType.APPLICATION_JSON, - schema = @Schema(implementation = ItemModelResponseDTO.ItemModelErrorDTO.class) - ) - ) - @Post("/update") - @Produces(MediaType.APPLICATION_JSON) - @Validated(groups = ValidationGroup.Update.class) - public HttpResponse update( - @Body ItemModelDTO itemModel - ) { - ItemModelResponseDTO updateResult = itemService.updateItem(itemModel); - if (updateResult instanceof ItemModelResponseDTO.ItemModelErrorDTO) { - return HttpResponse.notFound(updateResult); - } - return HttpResponse.ok(updateResult); - } - - @Operation( - summary = "Get enchantments of an item", - operationId = "getEnchantments", - description = "Retrieves a pageable list of enchantments for the item identified by itemId.", - tags = {"Item"} - ) - @ApiResponse( - responseCode = "200", - description = "Enchantments successfully retrieved.", - content = @Content( - mediaType = MediaType.APPLICATION_JSON, - array = @ArraySchema( - schema = @Schema(implementation = ItemEnchantmentResponseDTO.class), - arraySchema = @Schema(implementation = Page.class) - ) - ) - ) - @Get(uris = { - "/enchantments/{itemId}", - "/{itemId}/enchantments" - }) - @Produces(MediaType.APPLICATION_JSON) - public HttpResponse> getEnchantmentsById(@PathVariable("itemId") UUID itemId, Pageable pageable) { - Page enchantmentsPage = itemService.findEnchantmentsById(itemId, pageable); - return HttpResponse.ok(enchantmentsPage); - } - - @Operation( - summary = "Update an enchantment of an item", - operationId = "updateEnchantment", - description = "Updates a specific enchantment of the item identified by itemId.", - tags = {"Item"} - ) - @ApiResponse( - responseCode = "200", - description = "Enchantment successfully updated.", - content = @Content( - mediaType = MediaType.APPLICATION_JSON, - schema = @Schema(implementation = ItemEnchantmentResponseDTO.ItemEnchantmentDTO.class) - ) - ) - @ApiResponse( - responseCode = "404", - description = "Item for the given ID was not found.", - content = @Content( - mediaType = MediaType.APPLICATION_JSON, - schema = @Schema(implementation = ItemEnchantmentResponseDTO.ItemEnchantmentErrorDTO.class) - ) - ) - @Post(uris = { - "/enchantment/{itemId}", - "/{itemId}/enchantment" - }) - @Validated(groups = ValidationGroup.Update.class) - public HttpResponse updateEnchantment(@PathVariable("itemId") UUID itemId, @Body ItemEnchantmentDTO enchantment) { - var updateResult = itemService.updateEnchantmentById(itemId, enchantment); - if (updateResult instanceof ItemEnchantmentResponseDTO.ItemEnchantmentErrorDTO) { - return HttpResponse.notFound(updateResult); - } - return HttpResponse.ok(updateResult); - } - - @Operation( - summary = "Create an enchantment for an item", - operationId = "createEnchantment", - description = "Creates a new enchantment entry for the item identified by itemId.", - tags = {"Item"} - ) - @ApiResponse( - responseCode = "200", - description = "Enchantment successfully created.", - content = @Content( - mediaType = MediaType.APPLICATION_JSON, - schema = @Schema(implementation = ItemEnchantmentResponseDTO.ItemEnchantmentDTO.class) - ) - ) - @ApiResponse( - responseCode = "404", - description = "Item for the given ID was not found.", - content = @Content( - mediaType = MediaType.APPLICATION_JSON, - schema = @Schema(implementation = ItemEnchantmentResponseDTO.ItemEnchantmentErrorDTO.class) - ) - ) - @Put(uris = { - "/enchantment/{itemId}", - "/{itemId}/enchantment" - }) - @Validated(groups = ValidationGroup.Create.class) - public HttpResponse createEnchantment(@PathVariable("itemId") UUID itemId, @Body ItemEnchantmentDTO enchantment) { - var createResult = itemService.createEnchantmentById(itemId, enchantment); - return HttpResponse.ok(createResult); - } - - @Operation( - summary = "Delete an enchantment of an item", - operationId = "deleteEnchantment", - description = "Deletes a specific enchantment (enchantmentId) of the item identified by itemId.", - tags = {"Item"} - ) - @ApiResponse( - responseCode = "200", - description = "Enchantment successfully deleted.", - content = @Content( - mediaType = MediaType.APPLICATION_JSON, - schema = @Schema(implementation = ItemEnchantmentResponseDTO.ItemEnchantmentDTO.class) - ) - ) - @ApiResponse( - responseCode = "404", - description = "Item for the given ID was not found.", - content = @Content( - mediaType = MediaType.APPLICATION_JSON, - schema = @Schema(implementation = ItemEnchantmentResponseDTO.ItemEnchantmentErrorDTO.class) - ) - ) - @Delete(uris = { - "/enchantment/{itemId}/{enchantmentId}", - "/{itemId}/enchantment/{enchantmentId}" - }) - public HttpResponse deleteEnchantment(@PathVariable("itemId") UUID itemId, @PathVariable("enchantmentId") UUID enchantmentId) { - var deleteResult = itemService.deleteEnchantmentById(itemId, enchantmentId); - if (deleteResult instanceof ItemEnchantmentResponseDTO.ItemEnchantmentErrorDTO) { - return HttpResponse.notFound(deleteResult); - } - return HttpResponse.ok(deleteResult); - } - - @Operation( - summary = "Delete all enchantments of an item", - operationId = "deleteEnchantments", - description = "Deletes all enchantments of the item identified by itemId.", - tags = {"Item"} - ) - @ApiResponse( - responseCode = "200", - description = "Enchantments successfully deleted.", - content = @Content( - mediaType = MediaType.APPLICATION_JSON, - array = @ArraySchema( - schema = @Schema(implementation = ItemEnchantmentResponseDTO.ItemEnchantmentDTO.class) - ) - ) - ) - @ApiResponse( - responseCode = "404", - description = "Item for the given ID was not found.", - content = @Content( - mediaType = MediaType.APPLICATION_JSON, - schema = @Schema(implementation = ItemEnchantmentResponseDTO.ItemEnchantmentErrorDTO.class) - ) - ) - @Delete(uris = { - "/enchantment/{itemId}/", - "/{itemId}/enchantment/" - }) - public HttpResponse> deleteEnchantments(@PathVariable("itemId") UUID itemId) { - var deletedEnchantments = itemService.deleteAllEnchantmentsById(itemId); - return HttpResponse.ok(deletedEnchantments); - } - - @Operation( - summary = "Get all lore of an item", - operationId = "getLore", - description = "Retrieves a pageable list of lore entries for the item identified by itemId.", - tags = {"Item"} - ) - @ApiResponse( - responseCode = "200", - description = "Lore successfully retrieved.", - content = @Content( - mediaType = MediaType.APPLICATION_JSON, - array = @ArraySchema( - schema = @Schema(implementation = ItemLoreResponseDTO.class), - arraySchema = @Schema(implementation = Page.class) - ) - ) - ) - @Get(uris = { - "/lore/{itemId}", - "/{itemId}/lore" - }) - @Produces(MediaType.APPLICATION_JSON) - public HttpResponse> getLoreById(@PathVariable("itemId") UUID itemId, Pageable pageable) { - Page lorePage = itemService.findLoreById(itemId, pageable); - return HttpResponse.ok(lorePage); - } - - @Operation( - summary = "Update lore of an item", - operationId = "updateLore", - description = "Updates a specific lore entry of the item identified by itemId.", - tags = {"Item"} - ) - @ApiResponse( - responseCode = "200", - description = "Lore successfully updated.", - content = @Content( - mediaType = MediaType.APPLICATION_JSON, - schema = @Schema(implementation = ItemLoreResponseDTO.ItemLoreDTO.class) - ) - ) - @ApiResponse( - responseCode = "404", - description = "Item for the given ID was not found.", - content = @Content( - mediaType = MediaType.APPLICATION_JSON, - schema = @Schema(implementation = ItemLoreResponseDTO.ItemLoreErrorDTO.class) - ) - ) - @Post(uris = { - "/lore/{itemId}", - "/{itemId}/lore" - }) - @Validated(groups = ValidationGroup.Update.class) - public HttpResponse updateLore(@PathVariable("itemId") UUID itemId, @Body ItemLoreDTO lore) { - ItemLoreResponseDTO updateResult = itemService.updateLoreById(itemId, lore); - if (updateResult instanceof ItemLoreResponseDTO.ItemLoreErrorDTO) { - return HttpResponse.notFound(updateResult); - } - return HttpResponse.ok(updateResult); - } - - @Operation( - summary = "Create lore of an item", - operationId = "createLore", - description = "Creates a new lore entry for the item identified by itemId.", - tags = {"Item"} - ) - @ApiResponse( - responseCode = "200", - description = "Lore successfully created.", - content = @Content( - mediaType = MediaType.APPLICATION_JSON, - schema = @Schema(implementation = ItemLoreResponseDTO.ItemLoreDTO.class) - ) - ) - @ApiResponse( - responseCode = "404", - description = "Item for the given ID was not found.", - content = @Content( - mediaType = MediaType.APPLICATION_JSON, - schema = @Schema(implementation = ItemLoreResponseDTO.ItemLoreErrorDTO.class) - ) - ) - @Put(uris = { - "/lore/{itemId}", - "/{itemId}/lore" - }) - @Validated(groups = ValidationGroup.Create.class) - public HttpResponse createLore(@PathVariable("itemId") UUID itemId, @Body ItemLoreDTO lore) { - ItemLoreResponseDTO createResult = itemService.createLoreById(itemId, lore); - if (createResult instanceof ItemLoreResponseDTO.ItemLoreErrorDTO) { - return HttpResponse.notFound(createResult); - } - return HttpResponse.ok(createResult); - } - - - @Operation( - summary = "Delete lore of an item", - operationId = "deleteLore", - description = "Deletes a specific lore entry (loreId) of the item identified by itemId.", - tags = {"Item"} - ) - @ApiResponse( - responseCode = "200", - description = "Lore successfully deleted.", - content = @Content( - mediaType = MediaType.APPLICATION_JSON, - schema = @Schema(implementation = ItemLoreResponseDTO.ItemLoreDTO.class) - ) - ) - @ApiResponse( - responseCode = "404", - description = "Item for the given ID was not found.", - content = @Content( - mediaType = MediaType.APPLICATION_JSON, - schema = @Schema(implementation = ItemLoreResponseDTO.ItemLoreErrorDTO.class) - ) - ) - @Delete(uris = { - "/lore/{itemId}/{loreId}", - "/{itemId}/lore/{loreId}" - }) - public HttpResponse deleteLore(@PathVariable("itemId") UUID itemId, @PathVariable("loreId") UUID loreId) { - var deleteResult = itemService.deleteLoreById(itemId, loreId); - if (deleteResult instanceof ItemLoreResponseDTO.ItemLoreErrorDTO) { - return HttpResponse.notFound(deleteResult); - } - return HttpResponse.ok(deleteResult); - } - - @Operation( - summary = "Delete all lore of an item", - operationId = "deleteAllLore", - description = "Deletes all lore entries of the item identified by itemId.", - tags = {"Item"} - ) - @ApiResponse( - responseCode = "200", - description = "All lore entries were successfully deleted.", - content = @Content( - mediaType = MediaType.APPLICATION_JSON, - array = @ArraySchema( - schema = @Schema(implementation = ItemLoreResponseDTO.ItemLoreDTO.class) - ) - ) - ) - @ApiResponse( - responseCode = "404", - description = "Item for the given ID was not found.", - content = @Content( - mediaType = MediaType.APPLICATION_JSON, - schema = @Schema(implementation = ItemLoreResponseDTO.ItemLoreErrorDTO.class) - ) - ) - @Delete(uris = { - "/lore/{itemId}/", - "/{itemId}/lore/" - }) - public HttpResponse> deleteLores(@PathVariable("itemId") UUID itemId) { - var deletedLores = itemService.deleteAllLoreById(itemId); - return HttpResponse.ok(deletedLores); - } - - - @Operation( - summary = "Get all flags of an item", - operationId = "getFlags", - description = "Retrieves a pageable list of flags for the item identified by itemId.", - tags = {"Item"} - ) - @ApiResponse( - responseCode = "200", - description = "Flags successfully retrieved.", - content = @Content( - mediaType = MediaType.APPLICATION_JSON, - array = @ArraySchema( - schema = @Schema(implementation = ItemFlagResponseDTO.ItemFlagDTO.class), - arraySchema = @Schema(implementation = Page.class) - ) - ) - ) - @Get(uris = { - "/flags/{itemId}", - "/{itemId}/flags" - }) - @Produces(MediaType.APPLICATION_JSON) - public HttpResponse> getFlagsById(@PathVariable("itemId") UUID itemId, Pageable pageable) { - Page flagsPage = itemService.findFlagsById(itemId, pageable); - return HttpResponse.ok(flagsPage); - } - - @Operation( - summary = "Update flag of an item", - operationId = "updateFlag", - description = "Updates a specific flag of the item identified by itemId.", - tags = {"Item"} - ) - @ApiResponse( - responseCode = "200", - description = "Flag successfully updated.", - content = @Content( - mediaType = MediaType.APPLICATION_JSON, - schema = @Schema(implementation = ItemFlagResponseDTO.ItemFlagDTO.class) - ) - ) - @ApiResponse( - responseCode = "404", - description = "Item for the given ID was not found.", - content = @Content( - mediaType = MediaType.APPLICATION_JSON, - schema = @Schema(implementation = ItemFlagResponseDTO.ItemFlagErrorDTO.class) - ) - ) - @Post(uris = { - "/flag/{itemId}", - "/{itemId}/flag" - }) - @Validated(groups = ValidationGroup.Update.class) - public HttpResponse updateFlags(@PathVariable("itemId") UUID itemId, @Body ItemFlagDTO flag) { - ItemFlagResponseDTO updateResult = itemService.updateFlagById(itemId, flag); - if (updateResult instanceof ItemFlagResponseDTO.ItemFlagErrorDTO) { - return HttpResponse.notFound(updateResult); - } - return HttpResponse.ok(updateResult); - } - - @Operation( - summary = "Create flag of an item", - operationId = "createFlag", - description = "Creates a new flag entry for the item identified by itemId.", - tags = {"Item"} - ) - @ApiResponse( - responseCode = "200", - description = "Flag successfully created.", - content = @Content( - mediaType = MediaType.APPLICATION_JSON, - schema = @Schema(implementation = ItemFlagResponseDTO.ItemFlagDTO.class) - ) - ) - @ApiResponse( - responseCode = "404", - description = "Item for the given ID was not found.", - content = @Content( - mediaType = MediaType.APPLICATION_JSON, - schema = @Schema(implementation = ItemFlagResponseDTO.ItemFlagErrorDTO.class) - ) - ) - @Put(uris = { - "/flag/{itemId}", - "/{itemId}/flag" - }) - @Validated(groups = ValidationGroup.Create.class) - public HttpResponse createFlag(@PathVariable("itemId") UUID itemId, @Body ItemFlagDTO flag) { - ItemFlagResponseDTO createResult = itemService.createFlagById(itemId, flag); - if (createResult instanceof ItemFlagResponseDTO.ItemFlagErrorDTO) { - return HttpResponse.notFound(createResult); - } - return HttpResponse.ok(createResult); - } - - - @Operation( - summary = "Delete flag of an item", - operationId = "deleteFlag", - description = "Deletes a specific flag (flagId) of the item identified by itemId.", - tags = {"Item"} - ) - @ApiResponse( - responseCode = "200", - description = "Flag successfully deleted.", - content = @Content( - mediaType = MediaType.APPLICATION_JSON, - schema = @Schema(implementation = ItemFlagResponseDTO.ItemFlagDTO.class) - ) - ) - @ApiResponse( - responseCode = "404", - description = "Item for the given ID was not found.", - content = @Content( - mediaType = MediaType.APPLICATION_JSON, - schema = @Schema(implementation = ItemFlagResponseDTO.ItemFlagErrorDTO.class) - ) - ) - @Delete(uris = { - "/flag/{itemId}/{flagId}", - "/{itemId}/flag/{flagId}" - }) - public HttpResponse deleteFlag(@PathVariable("itemId") UUID itemId, @PathVariable("flagId") UUID flagId) { - var deleteResult = itemService.deleteFlagById(itemId, flagId); - if (deleteResult instanceof ItemFlagResponseDTO.ItemFlagErrorDTO) { - return HttpResponse.notFound(deleteResult); - } - return HttpResponse.ok(deleteResult); - } - - @Operation( - summary = "Delete all flags of an item", - operationId = "deleteFlags", - description = "Deletes all flags of the item identified by itemId.", - tags = {"Item"} - ) - @ApiResponse( - responseCode = "200", - description = "All flags were successfully deleted.", - content = @Content( - mediaType = MediaType.APPLICATION_JSON, - array = @ArraySchema( - schema = @Schema(implementation = ItemFlagResponseDTO.ItemFlagDTO.class) - ) - ) - ) - @ApiResponse( - responseCode = "404", - description = "Item for the given ID was not found.", - content = @Content( - mediaType = MediaType.APPLICATION_JSON, - schema = @Schema(implementation = ItemFlagResponseDTO.ItemFlagErrorDTO.class) - ) - ) - @Delete(uris = { - "/flag/{itemId}/", - "/{itemId}/flag/" - }) - public HttpResponse> deleteFlags(@PathVariable("itemId") UUID itemId) { - var deletedFlags = itemService.deleteAllFlagsById(itemId); - return HttpResponse.ok(deletedFlags); - } - -} diff --git a/src/main/java/net/onelitefeather/vulpes/backend/controller/font/FontCharController.java b/src/main/java/net/onelitefeather/vulpes/backend/controller/font/FontCharController.java new file mode 100644 index 0000000..921d153 --- /dev/null +++ b/src/main/java/net/onelitefeather/vulpes/backend/controller/font/FontCharController.java @@ -0,0 +1,170 @@ +package net.onelitefeather.vulpes.backend.controller.font; + +import io.micronaut.data.model.Page; +import io.micronaut.data.model.Pageable; +import io.micronaut.http.HttpResponse; +import io.micronaut.http.MediaType; +import io.micronaut.http.annotation.Body; +import io.micronaut.http.annotation.Controller; +import io.micronaut.http.annotation.Delete; +import io.micronaut.http.annotation.Get; +import io.micronaut.http.annotation.PathVariable; +import io.micronaut.http.annotation.Post; +import io.micronaut.http.annotation.Produces; +import io.micronaut.http.annotation.Put; +import io.micronaut.validation.Validated; +import io.swagger.v3.oas.annotations.Operation; +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 jakarta.inject.Inject; +import net.onelitefeather.vulpes.backend.domain.font.FontModelResponseDTO; +import net.onelitefeather.vulpes.backend.domain.font.FontStringDTO; +import net.onelitefeather.vulpes.backend.domain.font.FontStringResponseDTO; +import net.onelitefeather.vulpes.backend.service.FontService; +import net.onelitefeather.vulpes.backend.validation.ValidationGroup; + +import java.util.List; +import java.util.UUID; + +@Controller("/font/chars") +public class FontCharController { + + private final FontService fontService; + + @Inject + public FontCharController(FontService fontService) { + this.fontService = fontService; + } + + @Operation( + summary = "Create character of a font", + operationId = "createChar", + description = "Create the character of a font in the database.", + tags = {"Font"} + ) + @ApiResponse( + responseCode = "200", + description = "The characters of the font were successfully created in the database.", + content = @Content( + mediaType = MediaType.APPLICATION_JSON, + schema = @Schema(implementation = FontStringResponseDTO.class) + ) + ) + @Put("/{id}") + @Produces(MediaType.APPLICATION_JSON) + @Validated(groups = ValidationGroup.Create.class) + public HttpResponse createChar(@PathVariable UUID id, @Body FontStringDTO charModel) { + FontStringResponseDTO model = fontService.createCharByFontId(id, charModel); + return HttpResponse.ok(model); + } + + @Operation( + summary = "Get characters by font ID", + operationId = "getCharsById", + description = "Gets the characters of a font by its ID from the database.", + tags = {"Font"} + ) + @ApiResponse( + responseCode = "200", + description = "The characters of the font were successfully retrieved from the database.", + content = @Content( + mediaType = MediaType.APPLICATION_JSON, + schema = @Schema(implementation = FontStringResponseDTO.class) + ) + ) + @ApiResponse( + responseCode = "404", + description = "The font was not found in the database.", + content = @Content( + mediaType = MediaType.APPLICATION_JSON, + schema = @Schema(implementation = FontModelResponseDTO.FontModelErrorDTO.class) + ) + ) + @Get("/{id}") + @Produces(MediaType.APPLICATION_JSON) + public HttpResponse> readCharsById(@PathVariable UUID id, Pageable pageable) { + Page models = fontService.findCharsByFontId(id, pageable); + return HttpResponse.ok(models); + } + + @Operation( + summary = "Update character of a font", + operationId = "updateChar", + description = "Updates the character of a font in the database.", + tags = {"Font"} + ) + @ApiResponse( + responseCode = "200", + description = "The characters of the font were successfully updated in the database.", + content = @Content( + mediaType = MediaType.APPLICATION_JSON, + array = @ArraySchema( + schema = @Schema(implementation = FontStringResponseDTO.class) + ) + ) + ) + @Post("/{id}") + @Produces(MediaType.APPLICATION_JSON) + @Validated(groups = ValidationGroup.Update.class) + public HttpResponse updateChar(@PathVariable UUID id, @Body FontStringDTO charModel) { + FontStringResponseDTO model = fontService.updateCharByFontId(id, charModel); + return HttpResponse.ok(model); + } + + @Operation( + summary = "Delete character of a font", + operationId = "deleteChar", + description = "Delete the character of a font in the database.", + tags = {"Font"} + ) + @ApiResponse( + responseCode = "200", + description = "The characters of the font were successfully updated in the database.", + content = @Content( + mediaType = MediaType.APPLICATION_JSON, + schema = @Schema(implementation = FontStringResponseDTO.FontStringDTO.class) + ) + ) + @ApiResponse( + responseCode = "404", + description = "The character was not found in the database.", + content = @Content( + mediaType = MediaType.APPLICATION_JSON, + schema = @Schema(implementation = FontStringResponseDTO.FontStringErrorDTO.class) + ) + ) + @Delete("/{fontId}/{charId}") + @Produces(MediaType.APPLICATION_JSON) + public HttpResponse deleteChar(@PathVariable UUID fontId, @PathVariable UUID charId) { + FontStringResponseDTO model = fontService.deleteCharByFontId(fontId, charId); + if (model instanceof FontStringResponseDTO.FontStringErrorDTO) { + return HttpResponse.notFound(model); + } + return HttpResponse.ok(model); + } + + @Operation( + summary = "Delete character of a font", + operationId = "deleteChar", + description = "Delete the character of a font in the database.", + tags = {"Font"} + ) + @ApiResponse( + responseCode = "200", + description = "The characters of the font were successfully deleted in the database.", + content = @Content( + mediaType = MediaType.APPLICATION_JSON, + array = @ArraySchema( + schema = @Schema(implementation = FontStringResponseDTO.class) + ) + ) + ) + @Delete("/{fontId}/") + @Produces(MediaType.APPLICATION_JSON) + public HttpResponse> deleteAllChars(@PathVariable UUID fontId) { + List model = fontService.deleteAllCharByFontId(fontId); + return HttpResponse.ok(model); + } +} diff --git a/src/main/java/net/onelitefeather/vulpes/backend/controller/FontController.java b/src/main/java/net/onelitefeather/vulpes/backend/controller/font/FontController.java similarity index 50% rename from src/main/java/net/onelitefeather/vulpes/backend/controller/FontController.java rename to src/main/java/net/onelitefeather/vulpes/backend/controller/font/FontController.java index cc13316..eb335d9 100644 --- a/src/main/java/net/onelitefeather/vulpes/backend/controller/FontController.java +++ b/src/main/java/net/onelitefeather/vulpes/backend/controller/font/FontController.java @@ -1,4 +1,4 @@ -package net.onelitefeather.vulpes.backend.controller; +package net.onelitefeather.vulpes.backend.controller.font; import io.micronaut.data.model.Page; import io.micronaut.data.model.Pageable; @@ -11,7 +11,6 @@ import io.micronaut.http.annotation.PathVariable; import io.micronaut.http.annotation.Post; import io.micronaut.http.annotation.Produces; -import io.micronaut.http.annotation.Put; import io.micronaut.validation.Validated; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.ArraySchema; @@ -22,8 +21,6 @@ import net.onelitefeather.vulpes.api.model.FontEntity; import net.onelitefeather.vulpes.backend.domain.font.FontModelDTO; import net.onelitefeather.vulpes.backend.domain.font.FontModelResponseDTO; -import net.onelitefeather.vulpes.backend.domain.font.FontStringDTO; -import net.onelitefeather.vulpes.backend.domain.font.FontStringResponseDTO; import net.onelitefeather.vulpes.backend.service.FontService; import net.onelitefeather.vulpes.backend.validation.ValidationGroup; @@ -109,9 +106,6 @@ public HttpResponse getById(@PathVariable UUID id) { return HttpResponse.notFound(new FontModelErrorDTO("Font not found")); } - - - @Operation( summary = "Remove a font by ID", operationId = "deleteFont", @@ -188,170 +182,4 @@ public HttpResponse> deleteAll() { List result = fontService.deleteAllFonts(); return HttpResponse.ok(result); } - - @Operation( - summary = "Update a font", - operationId = "updateFont", - description = "Updates a font in the database.", - tags = {"Font"} - ) - @ApiResponse( - responseCode = "200", - description = "The font was successfully updated in the database.", - content = @Content( - mediaType = MediaType.APPLICATION_JSON, - schema = @Schema(implementation = FontModelResponseDTO.FontModelDTO.class) - ) - ) - @ApiResponse( - responseCode = "404", - description = "The font was not found in the database.", - content = @Content( - mediaType = MediaType.APPLICATION_JSON, - schema = @Schema(implementation = FontModelErrorDTO.class) - ) - ) - @Post("/update") - @Produces(MediaType.APPLICATION_JSON) - @Validated(groups = ValidationGroup.Update.class) - public HttpResponse update( - @Body FontModelDTO model - ) { - FontModelResponseDTO result = fontService.updateFont(model); - if (result instanceof FontModelResponseDTO.FontModelErrorDTO) { - return HttpResponse.notFound(result); - } - return HttpResponse.ok(result); - } - - @Operation( - summary = "Create character of a font", - operationId = "createChar", - description = "Create the character of a font in the database.", - tags = {"Font"} - ) - @ApiResponse( - responseCode = "200", - description = "The characters of the font were successfully created in the database.", - content = @Content( - mediaType = MediaType.APPLICATION_JSON, - schema = @Schema(implementation = FontStringResponseDTO.class) - ) - ) - @Put("/chars/{id}") - @Produces(MediaType.APPLICATION_JSON) - @Validated(groups = ValidationGroup.Create.class) - public HttpResponse createChar(@PathVariable UUID id, @Body FontStringDTO charModel) { - FontStringResponseDTO model = fontService.createCharByFontId(id, charModel); - return HttpResponse.ok(model); - } - - @Operation( - summary = "Get characters by font ID", - operationId = "getCharsById", - description = "Gets the characters of a font by its ID from the database.", - tags = {"Font"} - ) - @ApiResponse( - responseCode = "200", - description = "The characters of the font were successfully retrieved from the database.", - content = @Content( - mediaType = MediaType.APPLICATION_JSON, - schema = @Schema(implementation = FontStringResponseDTO.class) - ) - ) - @ApiResponse( - responseCode = "404", - description = "The font was not found in the database.", - content = @Content( - mediaType = MediaType.APPLICATION_JSON, - schema = @Schema(implementation = FontModelErrorDTO.class) - ) - ) - @Get("/chars/{id}") - @Produces(MediaType.APPLICATION_JSON) - public HttpResponse> readCharsById(@PathVariable UUID id, Pageable pageable) { - Page models = fontService.findCharsByFontId(id, pageable); - return HttpResponse.ok(models); - } - - @Operation( - summary = "Update character of a font", - operationId = "updateChar", - description = "Updates the character of a font in the database.", - tags = {"Font"} - ) - @ApiResponse( - responseCode = "200", - description = "The characters of the font were successfully updated in the database.", - content = @Content( - mediaType = MediaType.APPLICATION_JSON, - array = @ArraySchema( - schema = @Schema(implementation = FontStringResponseDTO.class) - ) - ) - ) - @Post("/chars/{id}") - @Produces(MediaType.APPLICATION_JSON) - @Validated(groups = ValidationGroup.Update.class) - public HttpResponse updateChar(@PathVariable UUID id, @Body FontStringDTO charModel) { - FontStringResponseDTO model = fontService.updateCharByFontId(id, charModel); - return HttpResponse.ok(model); - } - - - @Operation( - summary = "Delete character of a font", - operationId = "deleteChar", - description = "Delete the character of a font in the database.", - tags = {"Font"} - ) - @ApiResponse( - responseCode = "200", - description = "The characters of the font were successfully updated in the database.", - content = @Content( - mediaType = MediaType.APPLICATION_JSON, - schema = @Schema(implementation = FontStringResponseDTO.FontStringDTO.class) - ) - ) - @ApiResponse( - responseCode = "404", - description = "The character was not found in the database.", - content = @Content( - mediaType = MediaType.APPLICATION_JSON, - schema = @Schema(implementation = FontStringResponseDTO.FontStringErrorDTO.class) - ) - ) - @Delete("/chars/{fontId}/{charId}") - @Produces(MediaType.APPLICATION_JSON) - public HttpResponse deleteChar(@PathVariable UUID fontId, @PathVariable UUID charId) { - FontStringResponseDTO model = fontService.deleteCharByFontId(fontId, charId); - if (model instanceof FontStringResponseDTO.FontStringErrorDTO) { - return HttpResponse.notFound(model); - } - return HttpResponse.ok(model); - } - - @Operation( - summary = "Delete character of a font", - operationId = "deleteChar", - description = "Delete the character of a font in the database.", - tags = {"Font"} - ) - @ApiResponse( - responseCode = "200", - description = "The characters of the font were successfully deleted in the database.", - content = @Content( - mediaType = MediaType.APPLICATION_JSON, - array = @ArraySchema( - schema = @Schema(implementation = FontStringResponseDTO.class) - ) - ) - ) - @Delete("/chars/{fontId}/") - @Produces(MediaType.APPLICATION_JSON) - public HttpResponse> deleteAllChars(@PathVariable UUID fontId) { - List model = fontService.deleteAllCharByFontId(fontId); - return HttpResponse.ok(model); - } } diff --git a/src/main/java/net/onelitefeather/vulpes/backend/controller/item/ItemController.java b/src/main/java/net/onelitefeather/vulpes/backend/controller/item/ItemController.java new file mode 100644 index 0000000..2b7932f --- /dev/null +++ b/src/main/java/net/onelitefeather/vulpes/backend/controller/item/ItemController.java @@ -0,0 +1,224 @@ +package net.onelitefeather.vulpes.backend.controller.item; + +import io.micronaut.data.model.Page; +import io.micronaut.data.model.Pageable; +import io.micronaut.http.HttpResponse; +import io.micronaut.http.MediaType; +import io.micronaut.http.annotation.Body; +import io.micronaut.http.annotation.Controller; +import io.micronaut.http.annotation.Delete; +import io.micronaut.http.annotation.Get; +import io.micronaut.http.annotation.PathVariable; +import io.micronaut.http.annotation.Post; +import io.micronaut.http.annotation.Produces; +import io.micronaut.validation.Validated; +import io.swagger.v3.oas.annotations.Operation; +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 jakarta.inject.Inject; +import net.onelitefeather.vulpes.api.model.ItemEntity; +import net.onelitefeather.vulpes.backend.domain.item.ItemModelDTO; +import net.onelitefeather.vulpes.backend.domain.item.ItemModelResponseDTO; +import net.onelitefeather.vulpes.backend.service.ItemService; +import net.onelitefeather.vulpes.backend.validation.ValidationGroup; + +import java.util.List; +import java.util.Optional; +import java.util.UUID; + +/** + * REST controller for item resources. + * Provides CRUD operations and nested resource management (enchantments, lore, flags). + */ +@Controller("/item") +public class ItemController { + + private final ItemService itemService; + + @Inject + public ItemController(ItemService itemService) { + this.itemService = itemService; + } + + @Operation( + summary = "Create a new item", + operationId = "addItem", + description = "Creates a new item with the provided properties and stores it in the database.", + tags = {"Item"} + ) + @ApiResponse( + responseCode = "200", + description = "Item successfully created.", + content = @Content( + mediaType = MediaType.APPLICATION_JSON, + schema = @Schema(implementation = ItemModelResponseDTO.ItemModelDTO.class) + ) + ) + @ApiResponse( + responseCode = "500", + description = "Item could not be created due to an internal error.", + content = @Content( + mediaType = MediaType.APPLICATION_JSON, + schema = @Schema(implementation = ItemModelResponseDTO.ItemModelErrorDTO.class) + ) + ) + @Post + @Produces(MediaType.APPLICATION_JSON) + @Validated(groups = ValidationGroup.Create.class) + public HttpResponse add( + @Body ItemModelDTO itemModel + ) { + ItemModelResponseDTO.ItemModelDTO createdItem = itemService.createItem(itemModel); + return HttpResponse.ok(createdItem); + } + + @Operation( + summary = "Get an item by ID", + operationId = "getItemById", + description = "Retrieves a single item from the database by its unique ID (itemId).", + tags = {"Item"} + ) + @ApiResponse( + responseCode = "200", + description = "Item successfully retrieved.", + content = @Content( + mediaType = MediaType.APPLICATION_JSON, + schema = @Schema(implementation = ItemModelResponseDTO.ItemModelDTO.class) + ) + ) + @ApiResponse( + responseCode = "404", + description = "Item with the given ID was not found.", + content = @Content( + mediaType = MediaType.APPLICATION_JSON, + schema = @Schema(implementation = ItemModelResponseDTO.ItemModelErrorDTO.class) + ) + ) + @Get("/{itemId}") + @Produces(MediaType.APPLICATION_JSON) + public HttpResponse getById( + @PathVariable("itemId") UUID itemId + ) { + Optional foundItemOpt = itemService.findItemById(itemId); + if (foundItemOpt.isPresent()) { + var foundItem = foundItemOpt.get(); + return HttpResponse.ok(ItemModelResponseDTO.ItemModelDTO.createDTO(foundItem)); + } + return HttpResponse.notFound(new ItemModelResponseDTO.ItemModelErrorDTO("Item not found")); + } + + @Operation( + summary = "Get all items", + operationId = "getAllItems", + description = "Retrieves a pageable list of all items. Supports standard Micronaut pagination (page, size, sort).", + tags = {"Item"} + ) + @ApiResponse( + responseCode = "200", + description = "Items successfully retrieved.", + content = @Content( + mediaType = MediaType.APPLICATION_JSON, + array = @ArraySchema( + schema = @Schema(implementation = ItemModelResponseDTO.ItemModelDTO.class), + arraySchema = @Schema(implementation = Page.class) + ) + ) + ) + @Get + @Produces(MediaType.APPLICATION_JSON) + public HttpResponse> getAll(Pageable pageable) { + Page itemsPage = itemService.getAllItems(pageable); + return HttpResponse.ok(itemsPage); + } + + @Operation( + summary = "Update an item", + operationId = "updateItem", + description = "Updates an existing item in the database.", + tags = {"Item"} + ) + @ApiResponse( + responseCode = "200", + description = "Item successfully updated.", + content = @Content( + mediaType = MediaType.APPLICATION_JSON, + schema = @Schema(implementation = ItemModelResponseDTO.ItemModelDTO.class) + ) + ) + @ApiResponse( + responseCode = "404", + description = "Item was not found and could not be updated.", + content = @Content( + mediaType = MediaType.APPLICATION_JSON, + schema = @Schema(implementation = ItemModelResponseDTO.ItemModelErrorDTO.class) + ) + ) + @Post("/update") + @Produces(MediaType.APPLICATION_JSON) + @Validated(groups = ValidationGroup.Update.class) + public HttpResponse update( + @Body ItemModelDTO itemModel + ) { + ItemModelResponseDTO updateResult = itemService.updateItem(itemModel); + if (updateResult instanceof ItemModelResponseDTO.ItemModelErrorDTO) { + return HttpResponse.notFound(updateResult); + } + return HttpResponse.ok(updateResult); + } + + @Operation( + summary = "Remove an item by ID", + operationId = "removeItemById", + description = "Deletes an item from the database by its unique ID (itemId).", + tags = {"Item"} + ) + @ApiResponse( + responseCode = "200", + description = "Item successfully deleted.", + content = @Content( + mediaType = MediaType.APPLICATION_JSON, + schema = @Schema(implementation = ItemModelResponseDTO.ItemModelDTO.class) + ) + ) + @ApiResponse( + responseCode = "404", + description = "Item with the given ID was not found.", + content = @Content( + mediaType = MediaType.APPLICATION_JSON, + schema = @Schema(implementation = ItemModelResponseDTO.ItemModelErrorDTO.class) + ) + ) + @Delete("/delete/{itemId}") + @Produces(MediaType.APPLICATION_JSON) + public HttpResponse delete(@PathVariable("itemId") UUID itemId) { + ItemModelResponseDTO deleteResult = itemService.deleteItem(itemId); + if (deleteResult instanceof ItemModelResponseDTO.ItemModelErrorDTO) { + return HttpResponse.notFound(deleteResult); + } + return HttpResponse.ok(deleteResult); + } + + @Operation( + summary = "Delete all items", + description = "Deletes all items from the database.", + tags = {"Item"} + ) + @ApiResponse( + responseCode = "200", + description = "All items were successfully deleted.", + content = @Content( + mediaType = MediaType.APPLICATION_JSON, + array = @ArraySchema( + schema = @Schema(implementation = ItemModelResponseDTO.ItemModelDTO.class) + ) + ) + ) + @Delete("/deleteAll") + @Produces(MediaType.APPLICATION_JSON) + public HttpResponse> deleteAll() { + List deleteResults = itemService.deleteAllItems(); + return HttpResponse.ok(deleteResults); + } +} diff --git a/src/main/java/net/onelitefeather/vulpes/backend/controller/item/ItemEnchantmentController.java b/src/main/java/net/onelitefeather/vulpes/backend/controller/item/ItemEnchantmentController.java new file mode 100644 index 0000000..eefb1e9 --- /dev/null +++ b/src/main/java/net/onelitefeather/vulpes/backend/controller/item/ItemEnchantmentController.java @@ -0,0 +1,201 @@ +package net.onelitefeather.vulpes.backend.controller.item; + +import io.micronaut.data.model.Page; +import io.micronaut.data.model.Pageable; +import io.micronaut.http.HttpResponse; +import io.micronaut.http.MediaType; +import io.micronaut.http.annotation.Body; +import io.micronaut.http.annotation.Controller; +import io.micronaut.http.annotation.Delete; +import io.micronaut.http.annotation.Get; +import io.micronaut.http.annotation.PathVariable; +import io.micronaut.http.annotation.Post; +import io.micronaut.http.annotation.Produces; +import io.micronaut.http.annotation.Put; +import io.micronaut.validation.Validated; +import io.swagger.v3.oas.annotations.Operation; +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 jakarta.inject.Inject; +import net.onelitefeather.vulpes.backend.domain.item.ItemEnchantmentDTO; +import net.onelitefeather.vulpes.backend.domain.item.ItemEnchantmentResponseDTO; +import net.onelitefeather.vulpes.backend.service.ItemService; +import net.onelitefeather.vulpes.backend.validation.ValidationGroup; + +import java.util.List; +import java.util.UUID; + +@Controller("/item") +public class ItemEnchantmentController { + + private final ItemService itemService; + + @Inject + public ItemEnchantmentController(ItemService itemService) { + this.itemService = itemService; + } + + @Operation( + summary = "Create an enchantment for an item", + operationId = "createEnchantment", + description = "Creates a new enchantment entry for the item identified by itemId.", + tags = {"Item"} + ) + @ApiResponse( + responseCode = "200", + description = "Enchantment successfully created.", + content = @Content( + mediaType = MediaType.APPLICATION_JSON, + schema = @Schema(implementation = ItemEnchantmentResponseDTO.ItemEnchantmentDTO.class) + ) + ) + @ApiResponse( + responseCode = "404", + description = "Item for the given ID was not found.", + content = @Content( + mediaType = MediaType.APPLICATION_JSON, + schema = @Schema(implementation = ItemEnchantmentResponseDTO.ItemEnchantmentErrorDTO.class) + ) + ) + @Put(uris = { + "/enchantment/{itemId}", + "/{itemId}/enchantment" + }) + @Validated(groups = ValidationGroup.Create.class) + public HttpResponse createEnchantment(@PathVariable("itemId") UUID itemId, @Body ItemEnchantmentDTO enchantment) { + var createResult = itemService.createEnchantmentById(itemId, enchantment); + return HttpResponse.ok(createResult); + } + + @Operation( + summary = "Get enchantments of an item", + operationId = "getEnchantments", + description = "Retrieves a pageable list of enchantments for the item identified by itemId.", + tags = {"Item"} + ) + @ApiResponse( + responseCode = "200", + description = "Enchantments successfully retrieved.", + content = @Content( + mediaType = MediaType.APPLICATION_JSON, + array = @ArraySchema( + schema = @Schema(implementation = ItemEnchantmentResponseDTO.class), + arraySchema = @Schema(implementation = Page.class) + ) + ) + ) + @Get(uris = { + "/enchantments/{itemId}", + "/{itemId}/enchantments" + }) + @Produces(MediaType.APPLICATION_JSON) + public HttpResponse> getEnchantmentsById(@PathVariable("itemId") UUID itemId, Pageable pageable) { + Page enchantmentsPage = itemService.findEnchantmentsById(itemId, pageable); + return HttpResponse.ok(enchantmentsPage); + } + + @Operation( + summary = "Update an enchantment of an item", + operationId = "updateEnchantment", + description = "Updates a specific enchantment of the item identified by itemId.", + tags = {"Item"} + ) + @ApiResponse( + responseCode = "200", + description = "Enchantment successfully updated.", + content = @Content( + mediaType = MediaType.APPLICATION_JSON, + schema = @Schema(implementation = ItemEnchantmentResponseDTO.ItemEnchantmentDTO.class) + ) + ) + @ApiResponse( + responseCode = "404", + description = "Item for the given ID was not found.", + content = @Content( + mediaType = MediaType.APPLICATION_JSON, + schema = @Schema(implementation = ItemEnchantmentResponseDTO.ItemEnchantmentErrorDTO.class) + ) + ) + @Post(uris = { + "/enchantment/{itemId}", + "/{itemId}/enchantment" + }) + @Validated(groups = ValidationGroup.Update.class) + public HttpResponse updateEnchantment(@PathVariable("itemId") UUID itemId, @Body ItemEnchantmentDTO enchantment) { + var updateResult = itemService.updateEnchantmentById(itemId, enchantment); + if (updateResult instanceof ItemEnchantmentResponseDTO.ItemEnchantmentErrorDTO) { + return HttpResponse.notFound(updateResult); + } + return HttpResponse.ok(updateResult); + } + + @Operation( + summary = "Delete an enchantment of an item", + operationId = "deleteEnchantment", + description = "Deletes a specific enchantment (enchantmentId) of the item identified by itemId.", + tags = {"Item"} + ) + @ApiResponse( + responseCode = "200", + description = "Enchantment successfully deleted.", + content = @Content( + mediaType = MediaType.APPLICATION_JSON, + schema = @Schema(implementation = ItemEnchantmentResponseDTO.ItemEnchantmentDTO.class) + ) + ) + @ApiResponse( + responseCode = "404", + description = "Item for the given ID was not found.", + content = @Content( + mediaType = MediaType.APPLICATION_JSON, + schema = @Schema(implementation = ItemEnchantmentResponseDTO.ItemEnchantmentErrorDTO.class) + ) + ) + @Delete(uris = { + "/enchantment/{itemId}/{enchantmentId}", + "/{itemId}/enchantment/{enchantmentId}" + }) + public HttpResponse deleteEnchantment(@PathVariable("itemId") UUID itemId, @PathVariable("enchantmentId") UUID enchantmentId) { + var deleteResult = itemService.deleteEnchantmentById(itemId, enchantmentId); + if (deleteResult instanceof ItemEnchantmentResponseDTO.ItemEnchantmentErrorDTO) { + return HttpResponse.notFound(deleteResult); + } + return HttpResponse.ok(deleteResult); + } + + @Operation( + summary = "Delete all enchantments of an item", + operationId = "deleteEnchantments", + description = "Deletes all enchantments of the item identified by itemId.", + tags = {"Item"} + ) + @ApiResponse( + responseCode = "200", + description = "Enchantments successfully deleted.", + content = @Content( + mediaType = MediaType.APPLICATION_JSON, + array = @ArraySchema( + schema = @Schema(implementation = ItemEnchantmentResponseDTO.ItemEnchantmentDTO.class) + ) + ) + ) + @ApiResponse( + responseCode = "404", + description = "Item for the given ID was not found.", + content = @Content( + mediaType = MediaType.APPLICATION_JSON, + schema = @Schema(implementation = ItemEnchantmentResponseDTO.ItemEnchantmentErrorDTO.class) + ) + ) + @Delete(uris = { + "/enchantment/{itemId}", + "/{itemId}/enchantment" + }) + public HttpResponse> deleteEnchantments(@PathVariable("itemId") UUID itemId) { + var deletedEnchantments = itemService.deleteAllEnchantmentsById(itemId); + return HttpResponse.ok(deletedEnchantments); + } +} + diff --git a/src/main/java/net/onelitefeather/vulpes/backend/controller/item/ItemFlagController.java b/src/main/java/net/onelitefeather/vulpes/backend/controller/item/ItemFlagController.java new file mode 100644 index 0000000..0f0e131 --- /dev/null +++ b/src/main/java/net/onelitefeather/vulpes/backend/controller/item/ItemFlagController.java @@ -0,0 +1,204 @@ +package net.onelitefeather.vulpes.backend.controller.item; + +import io.micronaut.data.model.Page; +import io.micronaut.data.model.Pageable; +import io.micronaut.http.HttpResponse; +import io.micronaut.http.MediaType; +import io.micronaut.http.annotation.Body; +import io.micronaut.http.annotation.Controller; +import io.micronaut.http.annotation.Delete; +import io.micronaut.http.annotation.Get; +import io.micronaut.http.annotation.PathVariable; +import io.micronaut.http.annotation.Post; +import io.micronaut.http.annotation.Produces; +import io.micronaut.http.annotation.Put; +import io.micronaut.validation.Validated; +import io.swagger.v3.oas.annotations.Operation; +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 jakarta.inject.Inject; +import net.onelitefeather.vulpes.backend.domain.item.ItemFlagDTO; +import net.onelitefeather.vulpes.backend.domain.item.ItemFlagResponseDTO; +import net.onelitefeather.vulpes.backend.service.ItemService; +import net.onelitefeather.vulpes.backend.validation.ValidationGroup; + +import java.util.List; +import java.util.UUID; + +@Controller("/item/") +public class ItemFlagController { + + private final ItemService itemService; + + @Inject + public ItemFlagController(ItemService itemService) { + this.itemService = itemService; + } + + @Operation( + summary = "Get all flags of an item", + operationId = "getFlags", + description = "Retrieves a pageable list of flags for the item identified by itemId.", + tags = {"Item"} + ) + @ApiResponse( + responseCode = "200", + description = "Flags successfully retrieved.", + content = @Content( + mediaType = MediaType.APPLICATION_JSON, + array = @ArraySchema( + schema = @Schema(implementation = ItemFlagResponseDTO.ItemFlagDTO.class), + arraySchema = @Schema(implementation = Page.class) + ) + ) + ) + @Get(uris = { + "/flags/{itemId}", + "/{itemId}/flags" + }) + @Produces(MediaType.APPLICATION_JSON) + public HttpResponse> getFlagsById(@PathVariable("itemId") UUID itemId, Pageable pageable) { + Page flagsPage = itemService.findFlagsById(itemId, pageable); + return HttpResponse.ok(flagsPage); + } + + @Operation( + summary = "Update flag of an item", + operationId = "updateFlag", + description = "Updates a specific flag of the item identified by itemId.", + tags = {"Item"} + ) + @ApiResponse( + responseCode = "200", + description = "Flag successfully updated.", + content = @Content( + mediaType = MediaType.APPLICATION_JSON, + schema = @Schema(implementation = ItemFlagResponseDTO.ItemFlagDTO.class) + ) + ) + @ApiResponse( + responseCode = "404", + description = "Item for the given ID was not found.", + content = @Content( + mediaType = MediaType.APPLICATION_JSON, + schema = @Schema(implementation = ItemFlagResponseDTO.ItemFlagErrorDTO.class) + ) + ) + @Post(uris = { + "/flag/{itemId}", + "/{itemId}/flag" + }) + @Validated(groups = ValidationGroup.Update.class) + public HttpResponse updateFlags(@PathVariable("itemId") UUID itemId, @Body ItemFlagDTO flag) { + ItemFlagResponseDTO updateResult = itemService.updateFlagById(itemId, flag); + if (updateResult instanceof ItemFlagResponseDTO.ItemFlagErrorDTO) { + return HttpResponse.notFound(updateResult); + } + return HttpResponse.ok(updateResult); + } + + @Operation( + summary = "Create flag of an item", + operationId = "createFlag", + description = "Creates a new flag entry for the item identified by itemId.", + tags = {"Item"} + ) + @ApiResponse( + responseCode = "200", + description = "Flag successfully created.", + content = @Content( + mediaType = MediaType.APPLICATION_JSON, + schema = @Schema(implementation = ItemFlagResponseDTO.ItemFlagDTO.class) + ) + ) + @ApiResponse( + responseCode = "404", + description = "Item for the given ID was not found.", + content = @Content( + mediaType = MediaType.APPLICATION_JSON, + schema = @Schema(implementation = ItemFlagResponseDTO.ItemFlagErrorDTO.class) + ) + ) + @Put(uris = { + "/flag/{itemId}", + "/{itemId}/flag" + }) + @Validated(groups = ValidationGroup.Create.class) + public HttpResponse createFlag(@PathVariable("itemId") UUID itemId, @Body ItemFlagDTO flag) { + ItemFlagResponseDTO createResult = itemService.createFlagById(itemId, flag); + if (createResult instanceof ItemFlagResponseDTO.ItemFlagErrorDTO) { + return HttpResponse.notFound(createResult); + } + return HttpResponse.ok(createResult); + } + + + @Operation( + summary = "Delete flag of an item", + operationId = "deleteFlag", + description = "Deletes a specific flag (flagId) of the item identified by itemId.", + tags = {"Item"} + ) + @ApiResponse( + responseCode = "200", + description = "Flag successfully deleted.", + content = @Content( + mediaType = MediaType.APPLICATION_JSON, + schema = @Schema(implementation = ItemFlagResponseDTO.ItemFlagDTO.class) + ) + ) + @ApiResponse( + responseCode = "404", + description = "Item for the given ID was not found.", + content = @Content( + mediaType = MediaType.APPLICATION_JSON, + schema = @Schema(implementation = ItemFlagResponseDTO.ItemFlagErrorDTO.class) + ) + ) + @Delete(uris = { + "/flag/{itemId}/{flagId}", + "/{itemId}/flag/{flagId}" + }) + public HttpResponse deleteFlag(@PathVariable("itemId") UUID itemId, @PathVariable("flagId") UUID flagId) { + var deleteResult = itemService.deleteFlagById(itemId, flagId); + if (deleteResult instanceof ItemFlagResponseDTO.ItemFlagErrorDTO) { + return HttpResponse.notFound(deleteResult); + } + return HttpResponse.ok(deleteResult); + } + + @Operation( + summary = "Delete all flags of an item", + operationId = "deleteFlags", + description = "Deletes all flags of the item identified by itemId.", + tags = {"Item"} + ) + @ApiResponse( + responseCode = "200", + description = "All flags were successfully deleted.", + content = @Content( + mediaType = MediaType.APPLICATION_JSON, + array = @ArraySchema( + schema = @Schema(implementation = ItemFlagResponseDTO.ItemFlagDTO.class) + ) + ) + ) + @ApiResponse( + responseCode = "404", + description = "Item for the given ID was not found.", + content = @Content( + mediaType = MediaType.APPLICATION_JSON, + schema = @Schema(implementation = ItemFlagResponseDTO.ItemFlagErrorDTO.class) + ) + ) + @Delete(uris = { + "/flag/{itemId}", + "/{itemId}/flag" + }) + public HttpResponse> deleteFlags(@PathVariable("itemId") UUID itemId) { + var deletedFlags = itemService.deleteAllFlagsById(itemId); + return HttpResponse.ok(deletedFlags); + } +} diff --git a/src/main/java/net/onelitefeather/vulpes/backend/controller/item/ItemLoreController.java b/src/main/java/net/onelitefeather/vulpes/backend/controller/item/ItemLoreController.java new file mode 100644 index 0000000..62ac9f8 --- /dev/null +++ b/src/main/java/net/onelitefeather/vulpes/backend/controller/item/ItemLoreController.java @@ -0,0 +1,204 @@ +package net.onelitefeather.vulpes.backend.controller.item; + +import io.micronaut.data.model.Page; +import io.micronaut.data.model.Pageable; +import io.micronaut.http.HttpResponse; +import io.micronaut.http.MediaType; +import io.micronaut.http.annotation.Body; +import io.micronaut.http.annotation.Controller; +import io.micronaut.http.annotation.Delete; +import io.micronaut.http.annotation.Get; +import io.micronaut.http.annotation.PathVariable; +import io.micronaut.http.annotation.Post; +import io.micronaut.http.annotation.Produces; +import io.micronaut.http.annotation.Put; +import io.micronaut.validation.Validated; +import io.swagger.v3.oas.annotations.Operation; +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 jakarta.inject.Inject; +import net.onelitefeather.vulpes.backend.domain.item.ItemLoreDTO; +import net.onelitefeather.vulpes.backend.domain.item.ItemLoreResponseDTO; +import net.onelitefeather.vulpes.backend.service.ItemService; +import net.onelitefeather.vulpes.backend.validation.ValidationGroup; + +import java.util.List; +import java.util.UUID; + +@Controller("/item") +public class ItemLoreController { + + private final ItemService itemService; + + @Inject + public ItemLoreController(ItemService itemService) { + this.itemService = itemService; + } + + @Operation( + summary = "Get all lore of an item", + operationId = "getLore", + description = "Retrieves a pageable list of lore entries for the item identified by itemId.", + tags = {"Item"} + ) + @ApiResponse( + responseCode = "200", + description = "Lore successfully retrieved.", + content = @Content( + mediaType = MediaType.APPLICATION_JSON, + array = @ArraySchema( + schema = @Schema(implementation = ItemLoreResponseDTO.class), + arraySchema = @Schema(implementation = Page.class) + ) + ) + ) + @Get(uris = { + "/lore/{itemId}", + "/{itemId}/lore" + }) + @Produces(MediaType.APPLICATION_JSON) + public HttpResponse> getLoreById(@PathVariable("itemId") UUID itemId, Pageable pageable) { + Page lorePage = itemService.findLoreById(itemId, pageable); + return HttpResponse.ok(lorePage); + } + + @Operation( + summary = "Update lore of an item", + operationId = "updateLore", + description = "Updates a specific lore entry of the item identified by itemId.", + tags = {"Item"} + ) + @ApiResponse( + responseCode = "200", + description = "Lore successfully updated.", + content = @Content( + mediaType = MediaType.APPLICATION_JSON, + schema = @Schema(implementation = ItemLoreResponseDTO.ItemLoreDTO.class) + ) + ) + @ApiResponse( + responseCode = "404", + description = "Item for the given ID was not found.", + content = @Content( + mediaType = MediaType.APPLICATION_JSON, + schema = @Schema(implementation = ItemLoreResponseDTO.ItemLoreErrorDTO.class) + ) + ) + @Post(uris = { + "/lore/{itemId}", + "/{itemId}/lore" + }) + @Validated(groups = ValidationGroup.Update.class) + public HttpResponse updateLore(@PathVariable("itemId") UUID itemId, @Body ItemLoreDTO lore) { + ItemLoreResponseDTO updateResult = itemService.updateLoreById(itemId, lore); + if (updateResult instanceof ItemLoreResponseDTO.ItemLoreErrorDTO) { + return HttpResponse.notFound(updateResult); + } + return HttpResponse.ok(updateResult); + } + + @Operation( + summary = "Create lore of an item", + operationId = "createLore", + description = "Creates a new lore entry for the item identified by itemId.", + tags = {"Item"} + ) + @ApiResponse( + responseCode = "200", + description = "Lore successfully created.", + content = @Content( + mediaType = MediaType.APPLICATION_JSON, + schema = @Schema(implementation = ItemLoreResponseDTO.ItemLoreDTO.class) + ) + ) + @ApiResponse( + responseCode = "404", + description = "Item for the given ID was not found.", + content = @Content( + mediaType = MediaType.APPLICATION_JSON, + schema = @Schema(implementation = ItemLoreResponseDTO.ItemLoreErrorDTO.class) + ) + ) + @Put(uris = { + "/lore/{itemId}", + "/{itemId}/lore" + }) + @Validated(groups = ValidationGroup.Create.class) + public HttpResponse createLore(@PathVariable("itemId") UUID itemId, @Body ItemLoreDTO lore) { + ItemLoreResponseDTO createResult = itemService.createLoreById(itemId, lore); + if (createResult instanceof ItemLoreResponseDTO.ItemLoreErrorDTO) { + return HttpResponse.notFound(createResult); + } + return HttpResponse.ok(createResult); + } + + + @Operation( + summary = "Delete lore of an item", + operationId = "deleteLore", + description = "Deletes a specific lore entry (loreId) of the item identified by itemId.", + tags = {"Item"} + ) + @ApiResponse( + responseCode = "200", + description = "Lore successfully deleted.", + content = @Content( + mediaType = MediaType.APPLICATION_JSON, + schema = @Schema(implementation = ItemLoreResponseDTO.ItemLoreDTO.class) + ) + ) + @ApiResponse( + responseCode = "404", + description = "Item for the given ID was not found.", + content = @Content( + mediaType = MediaType.APPLICATION_JSON, + schema = @Schema(implementation = ItemLoreResponseDTO.ItemLoreErrorDTO.class) + ) + ) + @Delete(uris = { + "/lore/{itemId}/{loreId}", + "/{itemId}/lore/{loreId}" + }) + public HttpResponse deleteLore(@PathVariable("itemId") UUID itemId, @PathVariable("loreId") UUID loreId) { + var deleteResult = itemService.deleteLoreById(itemId, loreId); + if (deleteResult instanceof ItemLoreResponseDTO.ItemLoreErrorDTO) { + return HttpResponse.notFound(deleteResult); + } + return HttpResponse.ok(deleteResult); + } + + @Operation( + summary = "Delete all lore of an item", + operationId = "deleteAllLore", + description = "Deletes all lore entries of the item identified by itemId.", + tags = {"Item"} + ) + @ApiResponse( + responseCode = "200", + description = "All lore entries were successfully deleted.", + content = @Content( + mediaType = MediaType.APPLICATION_JSON, + array = @ArraySchema( + schema = @Schema(implementation = ItemLoreResponseDTO.ItemLoreDTO.class) + ) + ) + ) + @ApiResponse( + responseCode = "404", + description = "Item for the given ID was not found.", + content = @Content( + mediaType = MediaType.APPLICATION_JSON, + schema = @Schema(implementation = ItemLoreResponseDTO.ItemLoreErrorDTO.class) + ) + ) + @Delete(uris = { + "/lore/{itemId}", + "/{itemId}/lore" + }) + public HttpResponse> deleteLores(@PathVariable("itemId") UUID itemId) { + var deletedLores = itemService.deleteAllLoreById(itemId); + return HttpResponse.ok(deletedLores); + } +} diff --git a/src/main/java/net/onelitefeather/vulpes/backend/controller/SoundController.java b/src/main/java/net/onelitefeather/vulpes/backend/controller/sound/SoundController.java similarity index 57% rename from src/main/java/net/onelitefeather/vulpes/backend/controller/SoundController.java rename to src/main/java/net/onelitefeather/vulpes/backend/controller/sound/SoundController.java index ba46338..5ddc533 100644 --- a/src/main/java/net/onelitefeather/vulpes/backend/controller/SoundController.java +++ b/src/main/java/net/onelitefeather/vulpes/backend/controller/sound/SoundController.java @@ -1,4 +1,4 @@ -package net.onelitefeather.vulpes.backend.controller; +package net.onelitefeather.vulpes.backend.controller.sound; import io.micronaut.data.model.Page; import io.micronaut.data.model.Pageable; @@ -13,16 +13,12 @@ import io.micronaut.http.annotation.Produces; import io.micronaut.validation.Validated; import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.enums.ParameterIn; 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 jakarta.inject.Inject; -import jakarta.validation.Valid; import net.onelitefeather.vulpes.backend.domain.sound.SoundEventDTO; -import net.onelitefeather.vulpes.backend.domain.sound.SoundFileSourceDTO; import net.onelitefeather.vulpes.backend.domain.sound.SoundResponseDTO; import net.onelitefeather.vulpes.backend.service.SoundService; import net.onelitefeather.vulpes.backend.validation.ValidationGroup; @@ -237,159 +233,4 @@ public HttpResponse update(@Body SoundEventDTO model) { } return HttpResponse.ok(result); } - - @Operation( - summary = "Get all sound file sources by an id", - operationId = "getSoundSourcesById", - description = "Get all sound file sources by a given sound event ID.", - tags = {"Sound"}, - responses = { - @ApiResponse( - responseCode = "200", - description = "The sound file sources were successfully retrieved.", - content = @Content( - mediaType = MediaType.APPLICATION_JSON, - schema = @Schema(implementation = SoundResponseDTO.SoundFileSourceDTO.class) - ) - ), - @ApiResponse( - responseCode = "404", - description = "No sound file sources were found for the given sound event ID.", - content = @Content( - mediaType = MediaType.APPLICATION_JSON, - schema = @Schema(implementation = SoundResponseDTO.SoundErrorDTO.class) - ) - ) - } - ) - @Get("{id}/sources") - @Produces(MediaType.APPLICATION_JSON) - public HttpResponse> get(@PathVariable UUID id, Pageable pageable) { - Page result = soundService.getSoundSourcesById(id, pageable); - return HttpResponse.ok(result); - } - - /** - * Creates a new SoundFileSource and links it to a SoundEventEntity by ID. - * - * @param soundEventId the ID of the SoundEventEntity - * @param sourceDTO the DTO containing source data - * @return the created SoundFileSourceDTO - */ - @Operation( - summary = "Create and link a SoundFileSource", - operationId = "createAndLinkSoundFileSource", - description = "Creates a new SoundFileSource and links it to a SoundEventEntity by its ID.", - tags = {"Sound"} - ) - @ApiResponse( - responseCode = "200", - description = "The SoundFileSource was successfully created and linked.", - content = @Content( - mediaType = MediaType.APPLICATION_JSON, - schema = @Schema(implementation = SoundResponseDTO.SoundFileSourceDTO.class) - ) - ) - @ApiResponse( - responseCode = "404", - description = "The SoundEventEntity was not found.", - content = @Content( - mediaType = MediaType.APPLICATION_JSON, - schema = @Schema(implementation = SoundResponseDTO.SoundFileSourceDTO.class) - ) - ) - @Post("{id}/sources") - @Produces(MediaType.APPLICATION_JSON) - @Validated(groups = ValidationGroup.Create.class) - public HttpResponse createSource( - @PathVariable("id") UUID soundEventId, - @Body SoundFileSourceDTO sourceDTO - ) { - SoundResponseDTO result = soundService.createAndLinkSource(soundEventId, sourceDTO); - return HttpResponse.ok(result); - } - - /** - * Updates an existing SoundFileSource linked to a SoundEventEntity by ID. - * - * @param soundEventId the ID of the SoundEventEntity - * @param sourceDTO the DTO containing updated source data - * @return the updated SoundFileSourceDTO - */ - @Operation( - summary = "Update a linked SoundFileSource", - operationId = "updateLinkedSoundFileSource", - description = "Updates an existing SoundFileSource linked to a SoundEventEntity by its ID.", - tags = {"Sound"} - ) - @ApiResponse( - responseCode = "200", - description = "The SoundFileSource was successfully updated.", - content = @Content( - mediaType = MediaType.APPLICATION_JSON, - schema = @Schema(implementation = SoundResponseDTO.SoundFileSourceDTO.class) - ) - ) - @ApiResponse( - responseCode = "404", - description = "The SoundFileSource or SoundEventEntity was not found.", - content = @Content( - mediaType = MediaType.APPLICATION_JSON, - schema = @Schema(implementation = SoundResponseDTO.SoundFileSourceDTO.class) - ) - ) - @Post("{id}/sources/update") - @Produces(MediaType.APPLICATION_JSON) - @Validated(groups = ValidationGroup.Update.class) - public HttpResponse updateSource( - @PathVariable("id") UUID soundEventId, - @Body SoundFileSourceDTO sourceDTO - ) { - SoundResponseDTO result = soundService.updateLinkedSource(soundEventId, sourceDTO); - return HttpResponse.ok(result); - } - - - /** - * Deletes an existing SoundFileSource linked to a SoundEventEntity by ID. - * - * @param soundEventId the ID of the SoundEventEntity - * @param soundId the DTO containing source data to delete - * @return the deleted SoundFileSourceDTO - */ - @Operation( - summary = "Delete a linked SoundFileSource", - operationId = "deleteLinkedSoundFileSource", - description = "Deletes an existing SoundFileSource linked to a SoundEventEntity by its ID.", - tags = {"Sound"} - ) - @ApiResponse( - responseCode = "200", - description = "The SoundFileSource was successfully deleted.", - content = @Content( - mediaType = MediaType.APPLICATION_JSON, - schema = @Schema(implementation = SoundResponseDTO.SoundFileSourceDTO.class) - ) - ) - @ApiResponse( - responseCode = "404", - description = "The SoundFileSource or SoundEventEntity was not found.", - content = @Content( - mediaType = MediaType.APPLICATION_JSON, - schema = @Schema(implementation = SoundResponseDTO.SoundFileSourceDTO.class) - ) - ) - @Delete("{id}/sources/delete/{soundId}") - @Produces(MediaType.APPLICATION_JSON) - public HttpResponse deleteSource( - @Parameter(name = "id", description = "The id of the sound event", in = ParameterIn.PATH, required = true) - @PathVariable("id") UUID soundEventId, - @Parameter(name = "soundID", description = "The id of the sound file", in = ParameterIn.PATH, required = true) - @PathVariable("soundId") UUID soundId - ) { - SoundResponseDTO result = soundService.deleteLinkedSource(soundEventId, soundId); - return HttpResponse.ok(result); - } - - } diff --git a/src/main/java/net/onelitefeather/vulpes/backend/controller/sound/SoundSourceController.java b/src/main/java/net/onelitefeather/vulpes/backend/controller/sound/SoundSourceController.java new file mode 100644 index 0000000..f24cd31 --- /dev/null +++ b/src/main/java/net/onelitefeather/vulpes/backend/controller/sound/SoundSourceController.java @@ -0,0 +1,191 @@ +package net.onelitefeather.vulpes.backend.controller.sound; + +import io.micronaut.data.model.Page; +import io.micronaut.data.model.Pageable; +import io.micronaut.http.HttpResponse; +import io.micronaut.http.MediaType; +import io.micronaut.http.annotation.Body; +import io.micronaut.http.annotation.Controller; +import io.micronaut.http.annotation.Delete; +import io.micronaut.http.annotation.Get; +import io.micronaut.http.annotation.PathVariable; +import io.micronaut.http.annotation.Post; +import io.micronaut.http.annotation.Produces; +import io.micronaut.validation.Validated; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.enums.ParameterIn; +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 jakarta.inject.Inject; +import net.onelitefeather.vulpes.backend.domain.sound.SoundFileSourceDTO; +import net.onelitefeather.vulpes.backend.domain.sound.SoundResponseDTO; +import net.onelitefeather.vulpes.backend.service.SoundService; +import net.onelitefeather.vulpes.backend.validation.ValidationGroup; + +import java.util.UUID; + +@Controller("/sound") +public class SoundSourceController { + + private final SoundService soundService; + + @Inject + public SoundSourceController(SoundService soundService) { + this.soundService = soundService; + } + + @Operation( + summary = "Get all sound file sources by an id", + operationId = "getSoundSourcesById", + description = "Get all sound file sources by a given sound event ID.", + tags = {"Sound"}, + responses = { + @ApiResponse( + responseCode = "200", + description = "The sound file sources were successfully retrieved.", + content = @Content( + mediaType = MediaType.APPLICATION_JSON, + schema = @Schema(implementation = SoundResponseDTO.SoundFileSourceDTO.class) + ) + ), + @ApiResponse( + responseCode = "404", + description = "No sound file sources were found for the given sound event ID.", + content = @Content( + mediaType = MediaType.APPLICATION_JSON, + schema = @Schema(implementation = SoundResponseDTO.SoundErrorDTO.class) + ) + ) + } + ) + @Get("/{id}/sources") + @Produces(MediaType.APPLICATION_JSON) + public HttpResponse> get(@PathVariable UUID id, Pageable pageable) { + Page result = soundService.getSoundSourcesById(id, pageable); + return HttpResponse.ok(result); + } + + /** + * Creates a new SoundFileSource and links it to a SoundEventEntity by ID. + * + * @param soundEventId the ID of the SoundEventEntity + * @param sourceDTO the DTO containing source data + * @return the created SoundFileSourceDTO + */ + @Operation( + summary = "Create and link a SoundFileSource", + operationId = "createAndLinkSoundFileSource", + description = "Creates a new SoundFileSource and links it to a SoundEventEntity by its ID.", + tags = {"Sound"} + ) + @ApiResponse( + responseCode = "200", + description = "The SoundFileSource was successfully created and linked.", + content = @Content( + mediaType = MediaType.APPLICATION_JSON, + schema = @Schema(implementation = SoundResponseDTO.SoundFileSourceDTO.class) + ) + ) + @ApiResponse( + responseCode = "404", + description = "The SoundEventEntity was not found.", + content = @Content( + mediaType = MediaType.APPLICATION_JSON, + schema = @Schema(implementation = SoundResponseDTO.SoundFileSourceDTO.class) + ) + ) + @Post("/{id}/sources") + @Produces(MediaType.APPLICATION_JSON) + @Validated(groups = ValidationGroup.Create.class) + public HttpResponse createSource( + @PathVariable("id") UUID soundEventId, + @Body SoundFileSourceDTO sourceDTO + ) { + SoundResponseDTO result = soundService.createAndLinkSource(soundEventId, sourceDTO); + return HttpResponse.ok(result); + } + + /** + * Updates an existing SoundFileSource linked to a SoundEventEntity by ID. + * + * @param soundEventId the ID of the SoundEventEntity + * @param sourceDTO the DTO containing updated source data + * @return the updated SoundFileSourceDTO + */ + @Operation( + summary = "Update a linked SoundFileSource", + operationId = "updateLinkedSoundFileSource", + description = "Updates an existing SoundFileSource linked to a SoundEventEntity by its ID.", + tags = {"Sound"} + ) + @ApiResponse( + responseCode = "200", + description = "The SoundFileSource was successfully updated.", + content = @Content( + mediaType = MediaType.APPLICATION_JSON, + schema = @Schema(implementation = SoundResponseDTO.SoundFileSourceDTO.class) + ) + ) + @ApiResponse( + responseCode = "404", + description = "The SoundFileSource or SoundEventEntity was not found.", + content = @Content( + mediaType = MediaType.APPLICATION_JSON, + schema = @Schema(implementation = SoundResponseDTO.SoundFileSourceDTO.class) + ) + ) + @Post("/{id}/sources/update") + @Produces(MediaType.APPLICATION_JSON) + @Validated(groups = ValidationGroup.Update.class) + public HttpResponse updateSource( + @PathVariable("id") UUID soundEventId, + @Body SoundFileSourceDTO sourceDTO + ) { + SoundResponseDTO result = soundService.updateLinkedSource(soundEventId, sourceDTO); + return HttpResponse.ok(result); + } + + + /** + * Deletes an existing SoundFileSource linked to a SoundEventEntity by ID. + * + * @param soundEventId the ID of the SoundEventEntity + * @param soundId the DTO containing source data to delete + * @return the deleted SoundFileSourceDTO + */ + @Operation( + summary = "Delete a linked SoundFileSource", + operationId = "deleteLinkedSoundFileSource", + description = "Deletes an existing SoundFileSource linked to a SoundEventEntity by its ID.", + tags = {"Sound"} + ) + @ApiResponse( + responseCode = "200", + description = "The SoundFileSource was successfully deleted.", + content = @Content( + mediaType = MediaType.APPLICATION_JSON, + schema = @Schema(implementation = SoundResponseDTO.SoundFileSourceDTO.class) + ) + ) + @ApiResponse( + responseCode = "404", + description = "The SoundFileSource or SoundEventEntity was not found.", + content = @Content( + mediaType = MediaType.APPLICATION_JSON, + schema = @Schema(implementation = SoundResponseDTO.SoundFileSourceDTO.class) + ) + ) + @Delete("/{id}/sources/delete/{soundId}") + @Produces(MediaType.APPLICATION_JSON) + public HttpResponse deleteSource( + @Parameter(name = "id", description = "The id of the sound event", in = ParameterIn.PATH, required = true) + @PathVariable("id") UUID soundEventId, + @Parameter(name = "soundID", description = "The id of the sound file", in = ParameterIn.PATH, required = true) + @PathVariable("soundId") UUID soundId + ) { + SoundResponseDTO result = soundService.deleteLinkedSource(soundEventId, soundId); + return HttpResponse.ok(result); + } +} diff --git a/src/test/java/net/onelitefeather/vulpes/backend/controller/SoundControllerTest.java b/src/test/java/net/onelitefeather/vulpes/backend/controller/SoundControllerTest.java index 705c512..1147db0 100644 --- a/src/test/java/net/onelitefeather/vulpes/backend/controller/SoundControllerTest.java +++ b/src/test/java/net/onelitefeather/vulpes/backend/controller/SoundControllerTest.java @@ -5,6 +5,8 @@ import io.micronaut.http.HttpResponse; import net.datafaker.Faker; import net.onelitefeather.vulpes.api.model.sound.SoundEventEntity; +import net.onelitefeather.vulpes.backend.controller.sound.SoundController; +import net.onelitefeather.vulpes.backend.controller.sound.SoundSourceController; import net.onelitefeather.vulpes.backend.domain.sound.SoundEventDTO; import net.onelitefeather.vulpes.backend.domain.sound.SoundFileSourceDTO; import net.onelitefeather.vulpes.backend.domain.sound.SoundResponseDTO; @@ -151,7 +153,7 @@ void testCreateSource_delegatesAndReturnsOk() { SoundFileSourceDTO requestDTO = new SoundFileSourceDTO(null, fileName, 1.0f, 1.0f, 1, false, 16, false, "file"); SoundResponseDTO.SoundFileSourceDTO expected = new SoundResponseDTO.SoundFileSourceDTO(UUID.randomUUID(), requestDTO.name(), requestDTO.volume(), requestDTO.pitch(), requestDTO.weight(), requestDTO.stream(), requestDTO.attenuationDistance(), requestDTO.preload(), requestDTO.type()); stub.sourceResponse = expected; - SoundController controller = new SoundController(stub); + SoundSourceController controller = new SoundSourceController(stub); HttpResponse resp = controller.createSource(id, requestDTO); assertEquals(200, resp.getStatus().getCode()); @@ -170,7 +172,7 @@ void testUpdateSource_delegatesAndReturnsOk() { SoundFileSourceDTO requestDTO = new SoundFileSourceDTO(UUID.randomUUID(), updateName, 0.8f, 1.1f, 2, true, 32, true, "file"); SoundResponseDTO.SoundFileSourceDTO expected = new SoundResponseDTO.SoundFileSourceDTO(requestDTO.id(), requestDTO.name(), requestDTO.volume(), requestDTO.pitch(), requestDTO.weight(), requestDTO.stream(), requestDTO.attenuationDistance(), requestDTO.preload(), requestDTO.type()); stub.sourceResponse = expected; - SoundController controller = new SoundController(stub); + SoundSourceController controller = new SoundSourceController(stub); HttpResponse resp = controller.updateSource(id, requestDTO); assertNotNull(resp); @@ -190,7 +192,7 @@ void testGetSources_returnsPageOk() { String listName = FAKER.internet().slug() + ".ogg"; SoundResponseDTO.SoundFileSourceDTO s = new SoundResponseDTO.SoundFileSourceDTO(UUID.randomUUID(), listName, 1.0f, 1.0f, 1, false, 16, false, "file"); stub.sourcesPage = Page.of(List.of(s), Pageable.from(0, 10), 1L); - SoundController controller = new SoundController(stub); + SoundSourceController controller = new SoundSourceController(stub); HttpResponse> resp = controller.get(id, Pageable.from(0, 10)); assertEquals(200, resp.getStatus().getCode());