1 | package edu.ucsb.cs156.courses.documents; | |
2 | ||
3 | import com.fasterxml.jackson.core.JsonProcessingException; | |
4 | import com.fasterxml.jackson.databind.DeserializationFeature; | |
5 | import com.fasterxml.jackson.databind.ObjectMapper; | |
6 | import java.util.ArrayList; | |
7 | import java.util.Collections; | |
8 | import java.util.List; | |
9 | import lombok.Data; | |
10 | import lombok.NoArgsConstructor; | |
11 | import lombok.extern.slf4j.Slf4j; | |
12 | ||
13 | @Data | |
14 | @NoArgsConstructor | |
15 | @Slf4j | |
16 | public class CoursePage { | |
17 | private int pageNumber; | |
18 | private int pageSize; | |
19 | private int total; | |
20 | private List<Course> classes; | |
21 | ||
22 | /** | |
23 | * Create a CoursePage object from json representation | |
24 | * | |
25 | * @param json String of json returned by API endpoint {@code /classes/search} | |
26 | * @return a new CoursePage object | |
27 | * @see <a href= | |
28 | * "https://developer.ucsb.edu/content/academic-curriculums">https://developer.ucsb.edu/content/academic-curriculums</a> | |
29 | */ | |
30 | public static CoursePage fromJSON(String json) { | |
31 | try { | |
32 | ObjectMapper objectMapper = new ObjectMapper(); | |
33 | objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); | |
34 | ||
35 | CoursePage coursePage = objectMapper.readValue(json, CoursePage.class); | |
36 |
1
1. fromJSON : replaced return value with null for edu/ucsb/cs156/courses/documents/CoursePage::fromJSON → KILLED |
return coursePage; |
37 | } catch (JsonProcessingException jpe) { | |
38 | log.error("JsonProcessingException:" + jpe); | |
39 | return null; | |
40 | } | |
41 | } | |
42 | ||
43 | /** | |
44 | * Create a List of ConvertedSections from json representation | |
45 | * | |
46 | * @return a list of converted sections | |
47 | */ | |
48 | public List<ConvertedSection> convertedSections() { | |
49 | ||
50 | List<ConvertedSection> result = new ArrayList<ConvertedSection>(); | |
51 | ||
52 | for (Course c : this.getClasses()) { | |
53 | for (Section section : c.getClassSections()) { | |
54 |
1
1. convertedSections : Replaced integer division with multiplication → KILLED |
int lectureNum = Integer.parseInt(section.getSection()) / 100; |
55 | ||
56 | CourseInfo courseInfo = | |
57 | CourseInfo.builder() | |
58 | .quarter(c.getQuarter()) | |
59 | .courseId(c.getCourseId() + "-" + Integer.toString(lectureNum)) | |
60 | .title(c.getTitle()) | |
61 | .description(c.getDescription()) | |
62 | .generalEducation(c.getGeneralEducation()) | |
63 | .build(); | |
64 | ConvertedSection cs = | |
65 | ConvertedSection.builder().courseInfo(courseInfo).section(section).build(); | |
66 | result.add(cs); | |
67 | } | |
68 | } | |
69 |
1
1. convertedSections : replaced return value with Collections.emptyList for edu/ucsb/cs156/courses/documents/CoursePage::convertedSections → KILLED |
return result; |
70 | } | |
71 | ||
72 | /** | |
73 | * Look ahead to the next section if there is one | |
74 | * | |
75 | * @param sections List of sections | |
76 | * @param sectionIndex the index of the current section | |
77 | * @return the next section if it exists, otherwise null | |
78 | */ | |
79 | public static Section nextSection(List<Section> sections, int sectionIndex) { | |
80 |
3
1. nextSection : changed conditional boundary → KILLED 2. nextSection : negated conditional → KILLED 3. nextSection : Replaced integer addition with subtraction → KILLED |
if (sectionIndex + 1 < sections.size()) { |
81 |
2
1. nextSection : Replaced integer addition with subtraction → KILLED 2. nextSection : replaced return value with null for edu/ucsb/cs156/courses/documents/CoursePage::nextSection → KILLED |
return sections.get(sectionIndex + 1); |
82 | } | |
83 | return null; // No more sections to look at | |
84 | } | |
85 | ||
86 | /** | |
87 | * Given a Course, return a list of Primary objects. | |
88 | * | |
89 | * <p>The reason this is necessary is that the UCSB API returns a course with a list of sections. | |
90 | * However, that list of sections may contain multiple primary sections, each with its own set of | |
91 | * secondary sections. | |
92 | * | |
93 | * <p>This method processes the sections of a course to create a list of Primary objects, each | |
94 | * representing a primary section and its associated secondary sections. | |
95 | * | |
96 | * @return a list of Primary objects | |
97 | */ | |
98 | public static List<Primary> getListOfPrimaries(Course course) { | |
99 | List<Primary> result = new ArrayList<>(); | |
100 | List<Section> classSections = course.getClassSections(); | |
101 | ||
102 |
1
1. getListOfPrimaries : negated conditional → KILLED |
if (classSections.isEmpty()) { |
103 | return Collections.emptyList(); // No sections to process | |
104 | } | |
105 | ||
106 | Section firstSection = classSections.get(0); | |
107 |
1
1. getListOfPrimaries : negated conditional → KILLED |
if (!firstSection.isPrimary()) { |
108 | log.error("First section is not primary: {}", firstSection); | |
109 | return Collections.emptyList(); // No sections to process | |
110 | } | |
111 | ||
112 | int sectionIndex = 0; | |
113 | Section thisSection = classSections.get(sectionIndex); | |
114 | ||
115 |
1
1. getListOfPrimaries : negated conditional → KILLED |
while (thisSection != null) { |
116 | List<Section> secondaries = new ArrayList<>(); | |
117 | Section lookAhead = nextSection(classSections, sectionIndex); | |
118 | ||
119 |
2
1. getListOfPrimaries : negated conditional → KILLED 2. getListOfPrimaries : negated conditional → KILLED |
while (lookAhead != null && !lookAhead.isPrimary()) { |
120 | secondaries.add(lookAhead); | |
121 |
1
1. getListOfPrimaries : Changed increment from 1 to -1 → TIMED_OUT |
sectionIndex++; |
122 | lookAhead = nextSection(classSections, sectionIndex); | |
123 | } | |
124 | ||
125 | Primary primary = | |
126 | Primary.builder() | |
127 | .quarter(course.getQuarter()) | |
128 | .courseId(course.getCourseId()) | |
129 | .title(course.getTitle()) | |
130 | .description(course.getDescription()) | |
131 | .primary(thisSection) | |
132 | .subRows(secondaries) | |
133 | .generalEducation(course.getGeneralEducation()) | |
134 | .build(); | |
135 | result.add(primary); | |
136 | thisSection = nextSection(classSections, sectionIndex); | |
137 |
1
1. getListOfPrimaries : Changed increment from 1 to -1 → TIMED_OUT |
sectionIndex++; // Move to the next section |
138 | } | |
139 |
1
1. getListOfPrimaries : replaced return value with Collections.emptyList for edu/ucsb/cs156/courses/documents/CoursePage::getListOfPrimaries → KILLED |
return result; |
140 | } | |
141 | ||
142 | /** Get a list of Primary objects from the CoursePage */ | |
143 | public List<Primary> getPrimaries() { | |
144 | List<Primary> result = new ArrayList<>(); | |
145 | ||
146 | for (Course c : this.getClasses()) { | |
147 | List<Primary> primaries = getListOfPrimaries(c); | |
148 | result.addAll(primaries); | |
149 | } | |
150 |
1
1. getPrimaries : replaced return value with Collections.emptyList for edu/ucsb/cs156/courses/documents/CoursePage::getPrimaries → KILLED |
return result; |
151 | } | |
152 | } | |
Mutations | ||
36 |
1.1 |
|
54 |
1.1 |
|
69 |
1.1 |
|
80 |
1.1 2.2 3.3 |
|
81 |
1.1 2.2 |
|
102 |
1.1 |
|
107 |
1.1 |
|
115 |
1.1 |
|
119 |
1.1 2.2 |
|
121 |
1.1 |
|
137 |
1.1 |
|
139 |
1.1 |
|
150 |
1.1 |