StudentsController.java

1
package edu.ucsb.cs156.happiercows.controllers;
2
3
import edu.ucsb.cs156.happiercows.entities.Course;
4
import edu.ucsb.cs156.happiercows.entities.Student;
5
import edu.ucsb.cs156.happiercows.repositories.CourseRepository;
6
import edu.ucsb.cs156.happiercows.repositories.StudentRepository;
7
import edu.ucsb.cs156.happiercows.repositories.UserRepository;
8
9
import io.swagger.v3.oas.annotations.Operation;
10
import io.swagger.v3.oas.annotations.Parameter;
11
import io.swagger.v3.oas.annotations.tags.Tag;
12
import lombok.extern.slf4j.Slf4j;
13
14
import com.fasterxml.jackson.core.JsonProcessingException;
15
import com.opencsv.CSVReader;
16
import com.opencsv.exceptions.CsvException;
17
18
import org.springframework.beans.factory.annotation.Autowired;
19
import org.springframework.security.access.prepost.PreAuthorize;
20
import org.springframework.web.bind.annotation.GetMapping;
21
import org.springframework.web.bind.annotation.PostMapping;
22
import org.springframework.web.bind.annotation.RequestMapping;
23
import org.springframework.web.bind.annotation.RequestParam;
24
import org.springframework.web.bind.annotation.RestController;
25
import org.springframework.web.multipart.MultipartFile;
26
27
import edu.ucsb.cs156.happiercows.errors.EntityNotFoundException;
28
29
import java.io.BufferedInputStream;
30
import java.io.BufferedReader;
31
import java.io.FileReader;
32
import java.io.IOException;
33
import java.io.InputStream;
34
import java.io.InputStreamReader;
35
import java.util.List;
36
import java.util.Map;
37
import java.util.Optional;
38
39
@Tag(name = "Students")
40
@RequestMapping("/api/students")
41
@RestController
42
@Slf4j
43
public class StudentsController extends ApiController {
44
45
        public enum Status {
46
                INSERTED, UPDATED
47
        };
48
49
        @Autowired
50
        CourseRepository courseRepository;
51
52
        @Autowired
53
        StudentRepository studentRepository;
54
55
        @Autowired
56
        UserRepository userRepository;
57
58
        @Operation(summary = "Get Students for course")
59
        @PreAuthorize("hasRole('ROLE_ADMIN')")
60
        @GetMapping("/all")
61
        public Iterable<Student> getStaff(
62
                        @Parameter(name = "courseId") @RequestParam Long courseId)
63
                        throws JsonProcessingException {
64
65
                Course course = courseRepository.findById(courseId)
66 1 1. lambda$getStaff$0 : replaced return value with null for edu/ucsb/cs156/happiercows/controllers/StudentsController::lambda$getStaff$0 → KILLED
                                .orElseThrow(() -> new EntityNotFoundException(Course.class, courseId.toString()));
67
68
                Iterable<Student> students = studentRepository.findByCourseId(course.getId());
69 1 1. getStaff : replaced return value with null for edu/ucsb/cs156/happiercows/controllers/StudentsController::getStaff → KILLED
                return students;
70
        }
71
72
        @Operation(summary = "Upload Students for Course in UCSB Egrades Format")
73
        @PreAuthorize("hasRole('ROLE_ADMIN')")
74
        @PostMapping(value = "/upload/egrades", consumes = { "multipart/form-data" })
75
        public Map<String, String> getStaff(
76
                        @Parameter(name = "courseId") @RequestParam Long courseId,
77
                        @Parameter(name = "file") @RequestParam("file") MultipartFile file)
78
                        throws JsonProcessingException, IOException, CsvException {
79
80
                Course course = courseRepository.findById(courseId)
81 1 1. lambda$getStaff$1 : replaced return value with null for edu/ucsb/cs156/happiercows/controllers/StudentsController::lambda$getStaff$1 → KILLED
                                .orElseThrow(() -> new EntityNotFoundException(Course.class, courseId.toString()));
82
83
                int counts[] = { 0, 0 };
84
85
                try (InputStream inputStream = new BufferedInputStream(file.getInputStream());
86
                                InputStreamReader reader = new InputStreamReader(inputStream);
87
                                CSVReader csvReader = new CSVReader(reader);) {
88 1 1. getStaff : removed call to com/opencsv/CSVReader::skip → KILLED
                        csvReader.skip(2);
89
                        List<String[]> myEntries = csvReader.readAll();
90
                        for (String[] row : myEntries) {
91
                                Student student = fromEgradesCSVRow(row);
92 1 1. getStaff : removed call to edu/ucsb/cs156/happiercows/entities/Student::setCourseId → KILLED
                                student.setCourseId(course.getId());
93
                                Status s = upsertStudent(student, course);
94 1 1. getStaff : Replaced integer addition with subtraction → KILLED
                                counts[s.ordinal()]++;
95
                        }
96
                }
97 1 1. getStaff : replaced return value with Collections.emptyMap for edu/ucsb/cs156/happiercows/controllers/StudentsController::getStaff → KILLED
                return Map.of(
98
                                "filename", file.getOriginalFilename(),
99
                                "message", String.format("Inserted %d new students, Updated %d students",
100
                                                counts[Status.INSERTED.ordinal()], counts[Status.UPDATED.ordinal()]));
101
102
        }
103
104
        public Student fromEgradesCSVRow(String[] row) {
105 1 1. fromEgradesCSVRow : replaced return value with null for edu/ucsb/cs156/happiercows/controllers/StudentsController::fromEgradesCSVRow → KILLED
                return Student.builder()
106
                                .fname(row[5])
107
                                .lname(row[4])
108
                                .studentId(row[1])
109
                                .email(row[10])
110
                                .build();
111
        }
112
113
        public Status upsertStudent(Student student, Course course) {
114
                Optional<Student> existingStudent = studentRepository.findByCourseIdAndStudentId(course.getId(),
115
                                student.getStudentId());
116 1 1. upsertStudent : negated conditional → KILLED
                if (existingStudent.isPresent()) {
117
                        Student existingStudentObj = existingStudent.get();
118 1 1. upsertStudent : removed call to edu/ucsb/cs156/happiercows/entities/Student::setFname → KILLED
                        existingStudentObj.setFname(student.getFname());
119 1 1. upsertStudent : removed call to edu/ucsb/cs156/happiercows/entities/Student::setLname → KILLED
                        existingStudentObj.setLname(student.getLname());
120 1 1. upsertStudent : removed call to edu/ucsb/cs156/happiercows/entities/Student::setEmail → KILLED
                        existingStudentObj.setEmail(student.getEmail());
121
                        studentRepository.save(existingStudentObj);
122 1 1. upsertStudent : replaced return value with null for edu/ucsb/cs156/happiercows/controllers/StudentsController::upsertStudent → KILLED
                        return Status.UPDATED;
123
                } else {
124
                        studentRepository.save(student);
125 1 1. upsertStudent : replaced return value with null for edu/ucsb/cs156/happiercows/controllers/StudentsController::upsertStudent → KILLED
                        return Status.INSERTED;
126
                }
127
128
        }
129
130
}

Mutations

66

1.1
Location : lambda$getStaff$0
Killed by : edu.ucsb.cs156.happiercows.controllers.StudentsControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.happiercows.controllers.StudentsControllerTests]/[method:admin_cannot_get_all_students_for_a_non_existing_course()]
replaced return value with null for edu/ucsb/cs156/happiercows/controllers/StudentsController::lambda$getStaff$0 → KILLED

69

1.1
Location : getStaff
Killed by : edu.ucsb.cs156.happiercows.controllers.StudentsControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.happiercows.controllers.StudentsControllerTests]/[method:admin_can_get_all_students_for_a_course()]
replaced return value with null for edu/ucsb/cs156/happiercows/controllers/StudentsController::getStaff → KILLED

81

1.1
Location : lambda$getStaff$1
Killed by : edu.ucsb.cs156.happiercows.controllers.StudentsControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.happiercows.controllers.StudentsControllerTests]/[method:admin_cannot_upload_students_for_a_non_existing_course()]
replaced return value with null for edu/ucsb/cs156/happiercows/controllers/StudentsController::lambda$getStaff$1 → KILLED

88

1.1
Location : getStaff
Killed by : edu.ucsb.cs156.happiercows.controllers.StudentsControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.happiercows.controllers.StudentsControllerTests]/[method:admin_can_upload_students_for_an_existing_course()]
removed call to com/opencsv/CSVReader::skip → KILLED

92

1.1
Location : getStaff
Killed by : edu.ucsb.cs156.happiercows.controllers.StudentsControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.happiercows.controllers.StudentsControllerTests]/[method:admin_can_upload_students_for_an_existing_course()]
removed call to edu/ucsb/cs156/happiercows/entities/Student::setCourseId → KILLED

94

1.1
Location : getStaff
Killed by : edu.ucsb.cs156.happiercows.controllers.StudentsControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.happiercows.controllers.StudentsControllerTests]/[method:admin_can_upload_students_for_an_existing_course()]
Replaced integer addition with subtraction → KILLED

97

1.1
Location : getStaff
Killed by : edu.ucsb.cs156.happiercows.controllers.StudentsControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.happiercows.controllers.StudentsControllerTests]/[method:admin_can_upload_students_for_an_existing_course()]
replaced return value with Collections.emptyMap for edu/ucsb/cs156/happiercows/controllers/StudentsController::getStaff → KILLED

105

1.1
Location : fromEgradesCSVRow
Killed by : edu.ucsb.cs156.happiercows.controllers.StudentsControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.happiercows.controllers.StudentsControllerTests]/[method:admin_can_upload_students_for_an_existing_course()]
replaced return value with null for edu/ucsb/cs156/happiercows/controllers/StudentsController::fromEgradesCSVRow → KILLED

116

1.1
Location : upsertStudent
Killed by : edu.ucsb.cs156.happiercows.controllers.StudentsControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.happiercows.controllers.StudentsControllerTests]/[method:admin_can_upload_students_for_an_existing_course()]
negated conditional → KILLED

118

1.1
Location : upsertStudent
Killed by : edu.ucsb.cs156.happiercows.controllers.StudentsControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.happiercows.controllers.StudentsControllerTests]/[method:admin_can_upload_students_for_an_existing_course()]
removed call to edu/ucsb/cs156/happiercows/entities/Student::setFname → KILLED

119

1.1
Location : upsertStudent
Killed by : edu.ucsb.cs156.happiercows.controllers.StudentsControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.happiercows.controllers.StudentsControllerTests]/[method:admin_can_upload_students_for_an_existing_course()]
removed call to edu/ucsb/cs156/happiercows/entities/Student::setLname → KILLED

120

1.1
Location : upsertStudent
Killed by : edu.ucsb.cs156.happiercows.controllers.StudentsControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.happiercows.controllers.StudentsControllerTests]/[method:admin_can_upload_students_for_an_existing_course()]
removed call to edu/ucsb/cs156/happiercows/entities/Student::setEmail → KILLED

122

1.1
Location : upsertStudent
Killed by : edu.ucsb.cs156.happiercows.controllers.StudentsControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.happiercows.controllers.StudentsControllerTests]/[method:admin_can_upload_students_for_an_existing_course()]
replaced return value with null for edu/ucsb/cs156/happiercows/controllers/StudentsController::upsertStudent → KILLED

125

1.1
Location : upsertStudent
Killed by : edu.ucsb.cs156.happiercows.controllers.StudentsControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.happiercows.controllers.StudentsControllerTests]/[method:admin_can_upload_students_for_an_existing_course()]
replaced return value with null for edu/ucsb/cs156/happiercows/controllers/StudentsController::upsertStudent → KILLED

Active mutators

Tests examined


Report generated by PIT 1.7.3