Coverage Summary for Class: CityController (dev.karlkadak.backend.controller)

Class Class, % Method, % Branch, % Line, %
CityController 100% (1/1) 100% (6/6) 100% (12/12) 100% (23/23)


 package dev.karlkadak.backend.controller;
 
 import dev.karlkadak.backend.dto.AddCityRequest;
 import dev.karlkadak.backend.dto.CityResponse;
 import dev.karlkadak.backend.dto.WeatherResponse;
 import dev.karlkadak.backend.entity.City;
 import dev.karlkadak.backend.entity.WeatherData;
 import dev.karlkadak.backend.exception.CityNotFoundException;
 import dev.karlkadak.backend.exception.MalformedCityNameException;
 import dev.karlkadak.backend.exception.WeatherDataMissingException;
 import dev.karlkadak.backend.repository.CityRepository;
 import dev.karlkadak.backend.repository.WeatherDataRepository;
 import dev.karlkadak.backend.service.CityManager;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.http.HttpStatus;
 import org.springframework.http.ResponseEntity;
 import org.springframework.web.bind.annotation.*;
 
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Optional;
 
 /**
  * REST controller for interacting with the city database
  */
 @RestController
 @RequestMapping("${api.prefix}/cities")
 public class CityController {
 
     private final CityRepository cityRepository;
     private final CityManager cityManager;
     private final WeatherDataRepository weatherDataRepository;
 
     @Autowired
     public CityController(CityRepository cityRepository, CityManager cityManager,
                           WeatherDataRepository weatherDataRepository) {
         this.cityRepository = cityRepository;
         this.cityManager = cityManager;
         this.weatherDataRepository = weatherDataRepository;
     }
 
     /**
      * API endpoint for retrieving information about all {@link City} objects for which data collection is enabled
      *
      * @return list of {@link CityResponse} objects representing all {@link City} objects for which data collection is
      * enabled
      */
     @GetMapping
     ResponseEntity<List<CityResponse>> all() {
         List<City> cities = cityRepository.findAllByImportingDataTrue();
         List<CityResponse> responseList = new ArrayList<>();
         for (City city : cities) {
             responseList.add(new CityResponse(city));
         }
         return ResponseEntity.ok(responseList);
     }
 
     /**
      * API endpoint for adding and / or enabling weather data tracking for a {@link City} object
      *
      * @param addCityRequest request body (city name)
      * @return a {@link CityResponse} object representing the added / enabled {@link City} object
      */
     @PostMapping
     ResponseEntity<CityResponse> enable(@RequestBody AddCityRequest addCityRequest) {
         if (addCityRequest.getName() == null || addCityRequest.getName().isEmpty()) {
             throw new MalformedCityNameException();
         }
 
         City city = cityManager.enableImporting(addCityRequest.getName());
 
         return ResponseEntity.status(HttpStatus.CREATED).body(new CityResponse(city));
     }
 
     /**
      * API endpoint for retrieving information about a single {@link City} object
      *
      * @param id the {@link City} object's {@link City#id id}
      * @return a {@link CityResponse} object representing the selected {@link City} object
      */
     @GetMapping("/{id}")
     ResponseEntity<CityResponse> one(@PathVariable Long id) {
         City city = cityRepository.findById(id).orElse(null);
 
         if (city == null) throw new CityNotFoundException(id);
         return ResponseEntity.ok(new CityResponse(city));
     }
 
     /**
      * API endpoint for disabling weather data tracking for a {@link City} object
      *
      * @param id the {@link City} object's {@link City#id id}
      * @return an empty {@link ResponseEntity}
      */
     @DeleteMapping("/{id}")
     ResponseEntity<Void> disable(@PathVariable Long id) {
         City city = cityManager.disableImporting(id);
         return ResponseEntity.status(HttpStatus.NO_CONTENT).build();
     }
 
     /**
      * API endpoint for requesting the most recent weather data linked to a {@link City} object
      *
      * @param id the {@link City} object's {@link City#id id}
      * @return the DTO of latest recorded {@link WeatherData} object
      */
     @GetMapping("/{id}/weather")
     ResponseEntity<WeatherResponse> weather(@PathVariable Long id) {
         City city = cityRepository.findById(id).orElse(null);
         if (city == null) throw new CityNotFoundException(id);
         Optional<WeatherData> weatherDataOptional = weatherDataRepository.findTopByCity_IdOrderByTimestampDesc(id);
         if (weatherDataOptional.isEmpty()) throw new WeatherDataMissingException();
         return ResponseEntity.ok(new WeatherResponse(weatherDataOptional.get()));
     }
 }