ReviewController.java

1
package edu.ucsb.cs156.dining.controllers;
2
3
import edu.ucsb.cs156.dining.entities.Review;
4
import edu.ucsb.cs156.dining.entities.User;
5
import edu.ucsb.cs156.dining.errors.EntityNotFoundException;
6
import edu.ucsb.cs156.dining.models.CurrentUser;
7
import edu.ucsb.cs156.dining.models.Entree;
8
import edu.ucsb.cs156.dining.repositories.MenuItemRepository;
9
import edu.ucsb.cs156.dining.repositories.ReviewRepository;
10
import io.swagger.v3.oas.annotations.Operation;
11
import io.swagger.v3.oas.annotations.Parameter;
12
import io.swagger.v3.oas.annotations.tags.Tag;
13
import lombok.extern.slf4j.Slf4j;
14
import com.fasterxml.jackson.core.JsonProcessingException;
15
16
import java.time.LocalDateTime;
17
import java.util.HashMap;
18
import java.util.Map;
19
20
import org.springframework.beans.factory.annotation.Autowired;
21
import org.springframework.format.annotation.DateTimeFormat;
22
import org.springframework.http.HttpStatus;
23
import org.springframework.http.ResponseEntity;
24
import org.springframework.security.access.prepost.PreAuthorize;
25
import org.springframework.web.bind.annotation.DeleteMapping;
26
import org.springframework.web.bind.annotation.ExceptionHandler;
27
import org.springframework.web.bind.annotation.GetMapping;
28
import org.springframework.web.bind.annotation.PostMapping;
29
import org.springframework.web.bind.annotation.PutMapping;
30
import org.springframework.web.bind.annotation.RequestBody;
31
import org.springframework.web.bind.annotation.RequestMapping;
32
import org.springframework.web.bind.annotation.RequestParam;
33
import org.springframework.web.bind.annotation.RestController;
34
import org.springframework.web.server.ResponseStatusException;
35
36
import com.nimbusds.openid.connect.sdk.claims.UserInfo;
37
38
import jakarta.validation.Valid;
39
40
/**
41
 * This is a REST controller for Reviews
42
 */
43
44
@Tag(name = "Review")
45
@RequestMapping("/api/reviews")
46
@RestController
47
@Slf4j
48
public class ReviewController extends ApiController {
49
50
    @ExceptionHandler(IllegalArgumentException.class)
51
    public ResponseEntity<Map<String, String>> handleValidationExceptions(IllegalArgumentException ex) {
52
        Map<String, String> errors = new HashMap<>();
53
        errors.put("error", ex.getMessage());
54 1 1. handleValidationExceptions : replaced return value with null for edu/ucsb/cs156/dining/controllers/ReviewController::handleValidationExceptions → KILLED
        return ResponseEntity.badRequest().body(errors);
55
    }
56
57
    @Autowired
58
    ReviewRepository reviewRepository;
59
60
    @Autowired
61
    MenuItemRepository menuItemRepository;
62
63
    /**
64
     * This method returns a list of all Reviews.
65
     * 
66
     * @return a list of all Reviews
67
     */
68
    @Operation(summary = "List all Reviews")
69
    @PreAuthorize("hasRole('ROLE_ADMIN')")
70
    @GetMapping("/all")
71
    public Iterable<Review> allReviews() {
72
        log.info("Attempting to log all reviews");
73
        Iterable<Review> reviews = reviewRepository.findAll();
74
        log.info("all reviews found, ", reviews);
75 1 1. allReviews : replaced return value with Collections.emptyList for edu/ucsb/cs156/dining/controllers/ReviewController::allReviews → KILLED
        return reviews;
76
    }
77
78
    /**
79
     * This method allows a user to submit a review
80
     * 
81
     * @return message that says an review was added to the database
82
     * @param itemId         id of the item
83
     * @param dateItemServed localDataTime
84
     *                       All others params must not be parameters and instead
85
     *                       derived from data sources that are dynamic (Date), or
86
     *                       set to be null or some other signifier
87
     */
88
    @Operation(summary = "Create a new review")
89
    @PreAuthorize("hasRole('ROLE_USER')")
90
    @PostMapping("/post")
91
    public Review postReview(
92
            @Parameter(name = "itemId") @RequestParam long itemId,
93
            @Parameter(description = "Comments by the reviewer, can be blank") @RequestParam(required = false) String reviewerComments,
94
            @Parameter(name = "itemsStars") @RequestParam Long itemsStars,
95
            @Parameter(name = "dateItemServed", description = "date (in iso format, e.g. YYYY-mm-ddTHH:MM:SS; see https://en.wikipedia.org/wiki/ISO_8601)") @RequestParam("dateItemServed") @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) LocalDateTime dateItemServed) // For
96
            throws JsonProcessingException {
97
        LocalDateTime now = LocalDateTime.now();
98
        Review review = new Review();
99 1 1. postReview : removed call to edu/ucsb/cs156/dining/entities/Review::setDateItemServed → KILLED
        review.setDateItemServed(dateItemServed);
100 1 1. postReview : removed call to edu/ucsb/cs156/dining/entities/Review::setDateCreated → KILLED
        review.setDateCreated(now);
101
102
        // Ensures content of truly empty and sets to null if so
103 1 1. postReview : negated conditional → KILLED
        if ((!reviewerComments.trim().isEmpty())) {
104 1 1. postReview : removed call to edu/ucsb/cs156/dining/entities/Review::setReviewerComments → KILLED
            review.setReviewerComments(reviewerComments);
105
        }
106
107
        // Ensure user inputs rating 1-5
108 4 1. postReview : negated conditional → KILLED
2. postReview : changed conditional boundary → KILLED
3. postReview : negated conditional → KILLED
4. postReview : changed conditional boundary → KILLED
        if (itemsStars < 1 || itemsStars > 5) {
109
            throw new IllegalArgumentException("Items stars must be between 1 and 5.");
110
        }
111
112 1 1. postReview : removed call to edu/ucsb/cs156/dining/entities/Review::setItemsStars → KILLED
        review.setItemsStars(itemsStars);
113
114
        // Check if the menu item exists
115 1 1. postReview : negated conditional → KILLED
        if (!menuItemRepository.existsById(itemId)) {
116
            throw new ResponseStatusException(HttpStatus.NOT_FOUND, "MenuItem with id " + itemId + " not found");
117
        }
118
119 1 1. postReview : removed call to edu/ucsb/cs156/dining/entities/Review::setItemId → KILLED
        review.setItemId(itemId);
120
        CurrentUser user = getCurrentUser();
121 1 1. postReview : removed call to edu/ucsb/cs156/dining/entities/Review::setStudentId → KILLED
        review.setStudentId(user.getUser().getId());
122 1 1. postReview : removed call to edu/ucsb/cs156/dining/entities/Review::setDateEdited → KILLED
        review.setDateEdited(now);
123
        log.info("reviews={}", review);
124
        reviewRepository.save(review);
125 1 1. postReview : replaced return value with null for edu/ucsb/cs156/dining/controllers/ReviewController::postReview → KILLED
        return review;
126
    }
127
128
    /**
129
     * This method allows a user to get a list of reviews that they have previously made.
130
     * Only user can only get a list of their own reviews, and you cant request another persons reviews
131
     * @return a list of reviews sent by a given user
132
     */
133
    @Operation(summary = "Get all reviews a user has sent: only callable by the user")
134
    @PreAuthorize("hasRole('ROLE_USER')")
135
    @GetMapping("/userReviews")
136
    public Iterable<Review> get_all_review_by_user_id(){
137
        CurrentUser user = getCurrentUser();
138
        long userId = user.getUser().getId();
139
        Iterable<Review> reviews = reviewRepository.findAllByStudentId(userId);
140 1 1. get_all_review_by_user_id : replaced return value with Collections.emptyList for edu/ucsb/cs156/dining/controllers/ReviewController::get_all_review_by_user_id → KILLED
        return reviews;
141
    }
142
}

Mutations

54

1.1
Location : handleValidationExceptions
Killed by : edu.ucsb.cs156.dining.controllers.ReviewControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.dining.controllers.ReviewControllerTests]/[method:test_rating_below_1_throws_exception()]
replaced return value with null for edu/ucsb/cs156/dining/controllers/ReviewController::handleValidationExceptions → KILLED

75

1.1
Location : allReviews
Killed by : edu.ucsb.cs156.dining.controllers.ReviewControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.dining.controllers.ReviewControllerTests]/[method:a_logged_in_admin_can_get_all()]
replaced return value with Collections.emptyList for edu/ucsb/cs156/dining/controllers/ReviewController::allReviews → KILLED

99

1.1
Location : postReview
Killed by : edu.ucsb.cs156.dining.controllers.ReviewControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.dining.controllers.ReviewControllerTests]/[method:a_user_can_post_a_new_review()]
removed call to edu/ucsb/cs156/dining/entities/Review::setDateItemServed → KILLED

100

1.1
Location : postReview
Killed by : edu.ucsb.cs156.dining.controllers.ReviewControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.dining.controllers.ReviewControllerTests]/[method:a_user_can_post_a_new_review()]
removed call to edu/ucsb/cs156/dining/entities/Review::setDateCreated → KILLED

103

1.1
Location : postReview
Killed by : edu.ucsb.cs156.dining.controllers.ReviewControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.dining.controllers.ReviewControllerTests]/[method:test_emptyString_on_creating_new_review()]
negated conditional → KILLED

104

1.1
Location : postReview
Killed by : edu.ucsb.cs156.dining.controllers.ReviewControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.dining.controllers.ReviewControllerTests]/[method:a_user_can_post_a_new_review()]
removed call to edu/ucsb/cs156/dining/entities/Review::setReviewerComments → KILLED

108

1.1
Location : postReview
Killed by : edu.ucsb.cs156.dining.controllers.ReviewControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.dining.controllers.ReviewControllerTests]/[method:test_rating_below_1_throws_exception()]
negated conditional → KILLED

2.2
Location : postReview
Killed by : edu.ucsb.cs156.dining.controllers.ReviewControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.dining.controllers.ReviewControllerTests]/[method:postReview_ShouldAcceptRatingAtBoundaries()]
changed conditional boundary → KILLED

3.3
Location : postReview
Killed by : edu.ucsb.cs156.dining.controllers.ReviewControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.dining.controllers.ReviewControllerTests]/[method:test_rating_above_5_throws_exception()]
negated conditional → KILLED

4.4
Location : postReview
Killed by : edu.ucsb.cs156.dining.controllers.ReviewControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.dining.controllers.ReviewControllerTests]/[method:testItemIdIsInvalid_NotFound()]
changed conditional boundary → KILLED

112

1.1
Location : postReview
Killed by : edu.ucsb.cs156.dining.controllers.ReviewControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.dining.controllers.ReviewControllerTests]/[method:a_user_can_post_a_new_review()]
removed call to edu/ucsb/cs156/dining/entities/Review::setItemsStars → KILLED

115

1.1
Location : postReview
Killed by : edu.ucsb.cs156.dining.controllers.ReviewControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.dining.controllers.ReviewControllerTests]/[method:testItemIdIsInvalid_NotFound()]
negated conditional → KILLED

119

1.1
Location : postReview
Killed by : edu.ucsb.cs156.dining.controllers.ReviewControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.dining.controllers.ReviewControllerTests]/[method:a_user_can_post_a_new_review()]
removed call to edu/ucsb/cs156/dining/entities/Review::setItemId → KILLED

121

1.1
Location : postReview
Killed by : edu.ucsb.cs156.dining.controllers.ReviewControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.dining.controllers.ReviewControllerTests]/[method:a_user_can_post_a_new_review()]
removed call to edu/ucsb/cs156/dining/entities/Review::setStudentId → KILLED

122

1.1
Location : postReview
Killed by : edu.ucsb.cs156.dining.controllers.ReviewControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.dining.controllers.ReviewControllerTests]/[method:a_user_can_post_a_new_review()]
removed call to edu/ucsb/cs156/dining/entities/Review::setDateEdited → KILLED

125

1.1
Location : postReview
Killed by : edu.ucsb.cs156.dining.controllers.ReviewControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.dining.controllers.ReviewControllerTests]/[method:test_emptyString_on_creating_new_review()]
replaced return value with null for edu/ucsb/cs156/dining/controllers/ReviewController::postReview → KILLED

140

1.1
Location : get_all_review_by_user_id
Killed by : edu.ucsb.cs156.dining.controllers.ReviewControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.dining.controllers.ReviewControllerTests]/[method:a_logged_in_user_can_get_own_reviews_list()]
replaced return value with Collections.emptyList for edu/ucsb/cs156/dining/controllers/ReviewController::get_all_review_by_user_id → KILLED

Active mutators

Tests examined


Report generated by PIT 1.17.0