CoursePage.java

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
Location : fromJSON
Killed by : edu.ucsb.cs156.courses.documents.CoursePageTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.courses.documents.CoursePageTests]/[method:test_getPrimaries_error_no_sections()]
replaced return value with null for edu/ucsb/cs156/courses/documents/CoursePage::fromJSON → KILLED

54

1.1
Location : convertedSections
Killed by : edu.ucsb.cs156.courses.services.UCSBCurriculumServiceTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.courses.services.UCSBCurriculumServiceTests]/[method:test_getConvertedSections()]
Replaced integer division with multiplication → KILLED

69

1.1
Location : convertedSections
Killed by : edu.ucsb.cs156.courses.jobs.UpdateCourseDataJobTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.courses.jobs.UpdateCourseDataJobTests]/[method:test_log_output_success()]
replaced return value with Collections.emptyList for edu/ucsb/cs156/courses/documents/CoursePage::convertedSections → KILLED

80

1.1
Location : nextSection
Killed by : edu.ucsb.cs156.courses.documents.CoursePageTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.courses.documents.CoursePageTests]/[method:nextSectionReturnsNextSection()]
changed conditional boundary → KILLED

2.2
Location : nextSection
Killed by : edu.ucsb.cs156.courses.documents.CoursePageTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.courses.documents.CoursePageTests]/[method:nextSectionReturnsNextSection()]
negated conditional → KILLED

3.3
Location : nextSection
Killed by : edu.ucsb.cs156.courses.documents.CoursePageTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.courses.documents.CoursePageTests]/[method:nextSectionReturnsNextSection()]
Replaced integer addition with subtraction → KILLED

81

1.1
Location : nextSection
Killed by : edu.ucsb.cs156.courses.documents.CoursePageTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.courses.documents.CoursePageTests]/[method:nextSectionReturnsNextSection()]
Replaced integer addition with subtraction → KILLED

2.2
Location : nextSection
Killed by : edu.ucsb.cs156.courses.documents.CoursePageTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.courses.documents.CoursePageTests]/[method:nextSectionReturnsNextSection()]
replaced return value with null for edu/ucsb/cs156/courses/documents/CoursePage::nextSection → KILLED

102

1.1
Location : getListOfPrimaries
Killed by : edu.ucsb.cs156.courses.documents.CoursePageTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.courses.documents.CoursePageTests]/[method:test_getListOfPrimaries_error_no_sections()]
negated conditional → KILLED

107

1.1
Location : getListOfPrimaries
Killed by : edu.ucsb.cs156.courses.documents.CoursePageTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.courses.documents.CoursePageTests]/[method:test_getListOfPrimaries()]
negated conditional → KILLED

115

1.1
Location : getListOfPrimaries
Killed by : edu.ucsb.cs156.courses.documents.CoursePageTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.courses.documents.CoursePageTests]/[method:test_getListOfPrimaries()]
negated conditional → KILLED

119

1.1
Location : getListOfPrimaries
Killed by : edu.ucsb.cs156.courses.documents.CoursePageTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.courses.documents.CoursePageTests]/[method:test_getListOfPrimaries()]
negated conditional → KILLED

2.2
Location : getListOfPrimaries
Killed by : edu.ucsb.cs156.courses.documents.CoursePageTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.courses.documents.CoursePageTests]/[method:test_getListOfPrimaries()]
negated conditional → KILLED

121

1.1
Location : getListOfPrimaries
Killed by : none
Changed increment from 1 to -1 → TIMED_OUT

137

1.1
Location : getListOfPrimaries
Killed by : none
Changed increment from 1 to -1 → TIMED_OUT

139

1.1
Location : getListOfPrimaries
Killed by : edu.ucsb.cs156.courses.documents.CoursePageTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.courses.documents.CoursePageTests]/[method:test_getListOfPrimaries()]
replaced return value with Collections.emptyList for edu/ucsb/cs156/courses/documents/CoursePage::getListOfPrimaries → KILLED

150

1.1
Location : getPrimaries
Killed by : edu.ucsb.cs156.courses.documents.CoursePageTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.courses.documents.CoursePageTests]/[method:test_getPrimaries()]
replaced return value with Collections.emptyList for edu/ucsb/cs156/courses/documents/CoursePage::getPrimaries → KILLED

Active mutators

Tests examined


Report generated by PIT 1.17.0