MenuItemService.java

1
package edu.ucsb.cs156.dining.services;
2
3
import edu.ucsb.cs156.dining.dto.MenuItemDTO;
4
import edu.ucsb.cs156.dining.entities.MenuItem;
5
import edu.ucsb.cs156.dining.repositories.MenuItemRepository;
6
import org.springframework.beans.factory.annotation.Value;
7
import org.springframework.boot.web.client.RestTemplateBuilder;
8
import org.springframework.http.HttpEntity;
9
import org.springframework.http.HttpHeaders;
10
import org.springframework.http.HttpMethod;
11
import org.springframework.http.ResponseEntity;
12
import org.springframework.stereotype.Service;
13
import org.springframework.web.client.RestTemplate;
14
import org.springframework.web.server.ResponseStatusException;
15
import org.springframework.web.client.HttpClientErrorException;
16
17
import java.time.LocalDateTime;
18
import java.time.format.DateTimeFormatter;
19
import java.util.Arrays;
20
import java.util.List;
21
import java.util.stream.Collectors;
22
23
/**
24
 * Service for interacting with the Dining Menu API and saving menu items.
25
 */
26
@Service
27
public class MenuItemService {
28
29
  @Value("${app.ucsb.api.consumer_key}")
30
  private String apiKey;
31
32
  private final RestTemplate restTemplate;
33
  private final MenuItemRepository menuItemRepository;
34
35
  private static final String MENU_ITEM_ENDPOINT = "https://api.ucsb.edu/dining/menu/v1/";
36
  private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd");
37
38
  public MenuItemService(RestTemplateBuilder restTemplateBuilder, MenuItemRepository menuItemRepository) {
39
    this.restTemplate = restTemplateBuilder.build();
40
    this.menuItemRepository = menuItemRepository;
41
  }
42
43
  /**
44
   * Fetches all menu items for a specific dining commons, meal, and date.
45
   * Saves each unique menu item to the database.
46
   *
47
   * @param dateTime          the date as LocalDateTime
48
   * @param diningCommonsCode the code for the dining commons
49
   * @param mealCode          the meal code (e.g., "breakfast", "lunch", "dinner")
50
   * @return a list of MenuItemDTO containing name, station, and id
51
   */
52
  public List<MenuItemDTO> getMenuItems(LocalDateTime dateTime, String diningCommonsCode, String mealCode) {
53
    String formattedDate = dateTime.format(DATE_FORMATTER);
54
    String url = String.format("%s%s/%s/%s", MENU_ITEM_ENDPOINT, formattedDate, diningCommonsCode, mealCode);
55
56
    HttpHeaders headers = new HttpHeaders();
57 1 1. getMenuItems : removed call to org/springframework/http/HttpHeaders::set → KILLED
    headers.set("ucsb-api-key", this.apiKey);
58 1 1. getMenuItems : removed call to org/springframework/http/HttpHeaders::set → KILLED
    headers.set("accept", "application/json");
59
60
    HttpEntity<String> entity = new HttpEntity<>("body", headers);
61
62
    try {
63
      ResponseEntity<MenuItem[]> response = restTemplate.exchange(
64
          url, HttpMethod.GET, entity, MenuItem[].class);
65
66
      MenuItem[] menuItemsArray = response.getBody();
67
68
      // Save unique menu items to the database and return DTOs
69
      List<MenuItemDTO> result = Arrays.stream(menuItemsArray)
70 1 1. lambda$getMenuItems$0 : replaced return value with null for edu/ucsb/cs156/dining/services/MenuItemService::lambda$getMenuItems$0 → KILLED
            .map(menuItem -> saveOrUpdateMenuItem(menuItem, diningCommonsCode, mealCode))
71 1 1. lambda$getMenuItems$1 : replaced return value with null for edu/ucsb/cs156/dining/services/MenuItemService::lambda$getMenuItems$1 → KILLED
            .map(menuItem -> new MenuItemDTO(menuItem.getId(), menuItem.getName(), menuItem.getStation()))
72
            .collect(Collectors.toList());
73 1 1. getMenuItems : replaced return value with Collections.emptyList for edu/ucsb/cs156/dining/services/MenuItemService::getMenuItems → KILLED
      return result;
74
    } catch (HttpClientErrorException.NotFound e) {
75
        // Handle 404 error from external API
76
        throw new ResponseStatusException(
77
            org.springframework.http.HttpStatus.NOT_FOUND,
78
            String.format("No menu items found for dining commons: %s, meal: %s, date: %s",
79
                diningCommonsCode, mealCode, formattedDate));
80
    } catch (Exception e) {
81
      throw new ResponseStatusException(
82
          org.springframework.http.HttpStatus.INTERNAL_SERVER_ERROR,
83
          "Error fetching menu items from the API", e);
84
    }
85
  }
86
87
  /**
88
   * Saves the menu item to the database if it does not already exist.
89
   *
90
   * @param menuItem          the menu item retrieved from the API
91
   * @param diningCommonsCode the dining commons code
92
   * @param mealCode          the meal code
93
   * @return the saved or existing MenuItem
94
   */
95
  public MenuItem saveOrUpdateMenuItem(MenuItem menuItem, String diningCommonsCode, String mealCode) {
96
    // Check if the menu item already exists
97 1 1. saveOrUpdateMenuItem : replaced return value with null for edu/ucsb/cs156/dining/services/MenuItemService::saveOrUpdateMenuItem → KILLED
    return menuItemRepository.findByUniqueFields(diningCommonsCode, mealCode, menuItem.getName(), menuItem.getStation())
98
        .orElseGet(() -> {
99
          // Log the new menu item to be saved
100 1 1. lambda$saveOrUpdateMenuItem$2 : removed call to edu/ucsb/cs156/dining/entities/MenuItem::setDiningCommonsCode → KILLED
            menuItem.setDiningCommonsCode(diningCommonsCode);
101 1 1. lambda$saveOrUpdateMenuItem$2 : removed call to edu/ucsb/cs156/dining/entities/MenuItem::setMealCode → KILLED
            menuItem.setMealCode(mealCode);
102
            MenuItem savedItem = menuItemRepository.save(menuItem);
103 1 1. lambda$saveOrUpdateMenuItem$2 : replaced return value with null for edu/ucsb/cs156/dining/services/MenuItemService::lambda$saveOrUpdateMenuItem$2 → KILLED
            return savedItem;
104
        });
105
  }
106
}

Mutations

57

1.1
Location : getMenuItems
Killed by : edu.ucsb.cs156.dining.services.MenuItemServiceTest.[engine:junit-jupiter]/[class:edu.ucsb.cs156.dining.services.MenuItemServiceTest]/[method:testGetMenuItems_NotFound()]
removed call to org/springframework/http/HttpHeaders::set → KILLED

58

1.1
Location : getMenuItems
Killed by : edu.ucsb.cs156.dining.services.MenuItemServiceTest.[engine:junit-jupiter]/[class:edu.ucsb.cs156.dining.services.MenuItemServiceTest]/[method:testGetMenuItems_Success()]
removed call to org/springframework/http/HttpHeaders::set → KILLED

70

1.1
Location : lambda$getMenuItems$0
Killed by : edu.ucsb.cs156.dining.services.MenuItemServiceTest.[engine:junit-jupiter]/[class:edu.ucsb.cs156.dining.services.MenuItemServiceTest]/[method:testGetMenuItems_Success()]
replaced return value with null for edu/ucsb/cs156/dining/services/MenuItemService::lambda$getMenuItems$0 → KILLED

71

1.1
Location : lambda$getMenuItems$1
Killed by : edu.ucsb.cs156.dining.services.MenuItemServiceTest.[engine:junit-jupiter]/[class:edu.ucsb.cs156.dining.services.MenuItemServiceTest]/[method:testGetMenuItems_Success()]
replaced return value with null for edu/ucsb/cs156/dining/services/MenuItemService::lambda$getMenuItems$1 → KILLED

73

1.1
Location : getMenuItems
Killed by : edu.ucsb.cs156.dining.services.MenuItemServiceTest.[engine:junit-jupiter]/[class:edu.ucsb.cs156.dining.services.MenuItemServiceTest]/[method:testGetMenuItems_Success()]
replaced return value with Collections.emptyList for edu/ucsb/cs156/dining/services/MenuItemService::getMenuItems → KILLED

97

1.1
Location : saveOrUpdateMenuItem
Killed by : edu.ucsb.cs156.dining.services.MenuItemServiceTest.[engine:junit-jupiter]/[class:edu.ucsb.cs156.dining.services.MenuItemServiceTest]/[method:testSaveOrUpdateMenuItem_ExistingItem()]
replaced return value with null for edu/ucsb/cs156/dining/services/MenuItemService::saveOrUpdateMenuItem → KILLED

100

1.1
Location : lambda$saveOrUpdateMenuItem$2
Killed by : edu.ucsb.cs156.dining.services.MenuItemServiceTest.[engine:junit-jupiter]/[class:edu.ucsb.cs156.dining.services.MenuItemServiceTest]/[method:testSaveOrUpdateMenuItem_NewItem_FieldSetting()]
removed call to edu/ucsb/cs156/dining/entities/MenuItem::setDiningCommonsCode → KILLED

101

1.1
Location : lambda$saveOrUpdateMenuItem$2
Killed by : edu.ucsb.cs156.dining.services.MenuItemServiceTest.[engine:junit-jupiter]/[class:edu.ucsb.cs156.dining.services.MenuItemServiceTest]/[method:testSaveOrUpdateMenuItem_NewItem_FieldSetting()]
removed call to edu/ucsb/cs156/dining/entities/MenuItem::setMealCode → KILLED

103

1.1
Location : lambda$saveOrUpdateMenuItem$2
Killed by : edu.ucsb.cs156.dining.services.MenuItemServiceTest.[engine:junit-jupiter]/[class:edu.ucsb.cs156.dining.services.MenuItemServiceTest]/[method:testSaveOrUpdateMenuItem_NewItem()]
replaced return value with null for edu/ucsb/cs156/dining/services/MenuItemService::lambda$saveOrUpdateMenuItem$2 → KILLED

Active mutators

Tests examined


Report generated by PIT 1.17.0