GameController.java

package io.github.cwacoderwithattitude.games.controller;

import io.github.cwacoderwithattitude.games.model.Game;
import io.github.cwacoderwithattitude.games.service.GameService;
import io.github.cwacoderwithattitude.games.service.SeedDataReader;
import io.micrometer.core.instrument.Counter;
import io.micrometer.core.instrument.MeterRegistry;
import jakarta.annotation.PostConstruct;
import org.apache.tomcat.util.json.ParseException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.Resource;
import org.springframework.dao.InvalidDataAccessResourceUsageException;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.io.IOException;
import java.util.List;

@RestController
@RequestMapping("games")
public class GameController {
    private static final int MIN_NUMBER_OF_GAMES = 10;
    @Autowired
    GameService gameService;
    @Autowired
    SeedDataReader seedDataReader;
    java.util.logging.Logger logger = java.util.logging.Logger.getLogger(GameController.class.getName());
    @Value("classpath:board_games.json")
    Resource resource; // = new ClassPathResource("rules_of_acquisiton.json");
    @Autowired
    private MeterRegistry meterRegistry;
    private Counter gameListCounter;
    private Counter gameByIdCounter;
    private Counter gamesUpdateCounter;
    private Counter newGameCounter;
    private Counter deleteGameCounter;

    @PostConstruct
    private void init() {
        try {
            gameListCounter = buildCounter(meterRegistry, "api_games_list", "a number of GET requests to /games/ endpoint");
            gameByIdCounter = buildCounter(meterRegistry, "api_games_getById", "a number of GET requests to /games/{id} endpoint");
            gamesUpdateCounter = buildCounter(meterRegistry, "api_games_update", "a number of PUT requests to /games/{id} endpoint");
            newGameCounter = buildCounter(meterRegistry, "api_games_new", "a number of POST requests to /games/new endpoint");
            deleteGameCounter = buildCounter(meterRegistry, "api_games_deleteById", "a number of DELETE requests to /games/{id} endpoint");
            if (gameService.list().size() >= MIN_NUMBER_OF_GAMES) {
                logger.info("Games already exist in the database, skipping seed data.");
            } else {
                logger.info("No games found in the database, seeding with initial data.");
                seedDataReader.readSeedData(resource);
            }
        } catch (IOException | ParseException e) {
            logger.info("Error reading seed data: " + e);
        }
    }

    private Counter buildCounter(MeterRegistry registry, String name, String description) {
        return Counter.builder(name)
                // .tag("title", StringUtils.isEmpty(title) ? "all" : title)
                .description(description)
                .register(registry);
    }

    @GetMapping(value = "/", produces = "application/json")
    public List<Game> getGames() {
        gameListCounter.increment();
        return gameService.list();
    }

    @GetMapping(value = "/{id}", produces = "application/json")
    public ResponseEntity<Game> getGameById(@PathVariable String id) {
        try {
            gameByIdCounter.increment();
            Game game = gameService.getById(Long.parseLong(id));
            if (game == null) {
                return ResponseEntity.notFound().build();
            } else {
                return ResponseEntity.ok(game);
            }
        } catch (IllegalArgumentException e) {
            return ResponseEntity.notFound().build();
        }
    }

    @PutMapping(value = "/{id}", consumes = "application/json", produces = "application/json")
    public ResponseEntity<Game> update(@PathVariable Long id, @RequestBody Game game) {
        try {
            gamesUpdateCounter.increment();
            Game updatedGame = gameService.update(id, game);
            return ResponseEntity.ok(updatedGame);
        } catch (IllegalArgumentException e) {
            return ResponseEntity.notFound().build();
        }
    }

    @PostMapping(value = "/new", consumes = "application/json", produces = "application/json")
    public ResponseEntity<Game> save(@RequestBody Game game) {
        try {
            newGameCounter.increment();
            logger.info(null == game ? "Game is null" : "Game: " + game);
            Game savedGame = gameService.save(game);
            return ResponseEntity.ok(savedGame);
        } catch (InvalidDataAccessResourceUsageException e) {
            return ResponseEntity.badRequest().build();
        } catch (Exception e) {
            return ResponseEntity.internalServerError().build();
        }
    }

    @DeleteMapping(value = "/{id}")
    public ResponseEntity<Void> deleteGameById(@PathVariable Long id) {
        try {
            deleteGameCounter.increment();
            boolean deleted = gameService.deleteById(id);
            if (deleted) {
                return ResponseEntity.noContent().build();
            } else {
                return ResponseEntity.notFound().build();
            }
        } catch (IllegalArgumentException e) {
            return ResponseEntity.notFound().build();
        }
    }

}