Skip to content

Commit

Permalink
Merge branch 'refactor/dto'
Browse files Browse the repository at this point in the history
  • Loading branch information
dlg1206 committed May 13, 2024
2 parents 1a0b63d + c0783d2 commit 85ed467
Show file tree
Hide file tree
Showing 11 changed files with 476 additions and 362 deletions.
61 changes: 9 additions & 52 deletions src/main/java/com/uh/rainbow/controller/RainbowController.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
import com.uh.rainbow.dto.course.CourseDTO;
import com.uh.rainbow.dto.identifier.IdentifierDTO;
import com.uh.rainbow.dto.response.*;
import com.uh.rainbow.entities.Section;
import com.uh.rainbow.services.DTOMapperService;
import com.uh.rainbow.services.HTMLParserService;
import com.uh.rainbow.util.SourceURL;
import com.uh.rainbow.util.filter.CourseFilter;
Expand Down Expand Up @@ -34,6 +36,7 @@ public class RainbowController {

private final static Logger LOGGER = new Logger(RainbowController.class);
private final HTMLParserService htmlParserService = new HTMLParserService();
private final DTOMapperService dtoMapperService = new DTOMapperService();

/**
* Util logging method for reporting HTTP failures
Expand Down Expand Up @@ -176,7 +179,8 @@ public ResponseEntity<ResponseDTO> getCourses(
.setKeywords(keyword)
.build();
// Get all courses for subject
List<CourseDTO> courseDTOs = this.htmlParserService.parseCourses(cf, instID, termID, subjectID);
List<Section> sections = this.htmlParserService.parseSections(cf, instID, termID, subjectID);
List<CourseDTO> courseDTOs = this.dtoMapperService.toCourseDTOs(sections);
return new ResponseEntity<>(
new CourseResponseDTO(courseDTOs),
HttpStatus.OK
Expand Down Expand Up @@ -226,10 +230,6 @@ public ResponseEntity<ResponseDTO> getCourses(
@RequestParam(required = false) List<String> instructor,
@RequestParam(required = false) List<String> keyword) {
try {
// Get all available subjects
Instant start = Instant.now();
List<IdentifierDTO> subjects = this.htmlParserService.parseSubjects(instID, termID);

// Build filter
CourseFilter cf = new CourseFilter.Builder()
.setCRNs(crn)
Expand All @@ -244,54 +244,11 @@ public ResponseEntity<ResponseDTO> getCourses(
.setKeywords(keyword)
.build();

// Parse each subject for courses
List<String> failedSources = new ArrayList<>();
List<CompletableFuture<List<CourseDTO>>> futures = new ArrayList<>();
for (IdentifierDTO s : subjects) {

// skip if not in filter
if (!cf.validSubject(s.id()))
continue;

// Add async job to queue
SourceURL source = new SourceURL(instID, termID, s.id());
futures.add(CompletableFuture
.supplyAsync(() -> {
try {
// Attempt to parse
return this.htmlParserService.parseCourses(cf, instID, termID, s.id());
} catch (HttpStatusException e) {
// Report html access failure, add to failed sources and continue
reportHTTPAccessError(MessageBuilder.Type.COURSE, e);
LOGGER.warn(new MessageBuilder(MessageBuilder.Type.COURSE).addDetails("Skipping %s".formatted(source)));
failedSources.add(source.toString());
} catch (IOException e) {
// Internal server error, add to failed sources and continue
LOGGER.error(new MessageBuilder(MessageBuilder.Type.COURSE).addDetails(e));
failedSources.add(source.toString());
}
return new ArrayList<>(); // empty results
}));
}
// Join each thread / wait for each to finish
futures.forEach(CompletableFuture::join);

// Get all results
List<CourseDTO> courseDTOs = new ArrayList<>();
for (CompletableFuture<List<CourseDTO>> result : futures) {
try {
courseDTOs.addAll(result.get());
} catch (ExecutionException | InterruptedException e) {
LOGGER.error(new MessageBuilder(MessageBuilder.Type.COURSE).addDetails(e));
}
}
// Parse Sections
List<Section> sections = this.htmlParserService.parseSections(cf, instID, termID);
List<CourseDTO> courseDTOs = this.dtoMapperService.toCourseDTOs(sections);

// Report Success and return results
int numSites = futures.size();
LOGGER.info(new MessageBuilder(MessageBuilder.Type.COURSE)
.addDetails("Parsed %s site%s".formatted(numSites, numSites == 1 ? "" : "s"))
.setDuration(start));
return new ResponseEntity<>(new CourseResponseDTO(courseDTOs, failedSources), HttpStatus.OK);
return new ResponseEntity<>(new CourseResponseDTO(courseDTOs), HttpStatus.OK);
} catch (HttpStatusException e) {
// Report and return html access failure
reportHTTPAccessError(MessageBuilder.Type.COURSE, e);
Expand Down
8 changes: 3 additions & 5 deletions src/main/java/com/uh/rainbow/dto/course/CourseDTO.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package com.uh.rainbow.dto.course;

import com.uh.rainbow.dto.section.SectionDTO;
import com.uh.rainbow.entities.Course;
import com.uh.rainbow.util.SourceURL;

import java.util.ArrayList;
Expand All @@ -14,15 +13,14 @@
*
* @author Derek Garcia
*/
public record CourseDTO(String source, String cid, String name, String credits, List<SectionDTO> sections) {
public record CourseDTO(String cid, String name, String source, String credits, List<SectionDTO> sections) {

/**
* Create new course without any sections
*
* @param source Source URL of course data
* @param course Course
*/
public CourseDTO(SourceURL source, Course course) {
this(source.toString(), course.cid(), course.name(), course.credits(), new ArrayList<>());
public CourseDTO(SourceURL source, String cid, String name, String credits) {
this(cid, name, source.toString(), credits, new ArrayList<>());
}
}
12 changes: 0 additions & 12 deletions src/main/java/com/uh/rainbow/dto/response/CourseResponseDTO.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
*/
public class CourseResponseDTO extends ResponseDTO {
public final List<CourseDTO> courses;
public List<String> failed_sources;

/**
* Create new list of course DTOs
Expand All @@ -24,15 +23,4 @@ public CourseResponseDTO(List<CourseDTO> courseDTOS) {
this.courses = courseDTOS;
}

/**
* Create new list of course DTOs
*
* @param courseDTOS list of course DTOs
* @param failed_sources list of urls that were failed to access
*/
public CourseResponseDTO(List<CourseDTO> courseDTOS, List<String> failed_sources) {
this.courses = courseDTOS;
if (!failed_sources.isEmpty())
this.failed_sources = failed_sources;
}
}
18 changes: 2 additions & 16 deletions src/main/java/com/uh/rainbow/dto/section/SectionDTO.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,31 +2,17 @@

import com.uh.rainbow.dto.meeting.MeetingDTO;

import java.util.ArrayList;
import java.util.List;

/**
* <b>File:</b> SectionDTO.java
* <p>
* <b>Description:</b> SectionDTO
* <p>
* TODO: v2 replace 'sid' with 'section_number'
*
* @author Derek Garcia
*/
public record SectionDTO(String url, String sid, int crn, String instructor, int curr_enrolled, int seats_available,
int failed_meetings, List<String> additional_details, List<MeetingDTO> meetings) {
/**
* Create new Section DTO with no meetings
*
* @param url URL with additional section details
* @param sid Section ID
* @param crn Course Reference Number
* @param instructor Section instructor
* @param curr_enrolled Number of students currently enrolled
* @param seats_available Number of seats available
* @param failed_meetings Number of meetings failed to parse
* @param additional_details additional details for the section
*/
public SectionDTO(String url, String sid, int crn, String instructor, int curr_enrolled, int seats_available, int failed_meetings, List<String> additional_details) {
this(url, sid, crn, instructor, curr_enrolled, seats_available, failed_meetings, additional_details, new ArrayList<>());
}
}
11 changes: 0 additions & 11 deletions src/main/java/com/uh/rainbow/entities/Course.java

This file was deleted.

55 changes: 26 additions & 29 deletions src/main/java/com/uh/rainbow/entities/Meeting.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package com.uh.rainbow.entities;


import com.uh.rainbow.dto.meeting.MeetingDTO;
import com.uh.rainbow.entities.time.TimeBlock;
import com.uh.rainbow.entities.time.simple.SimpleDate;
import com.uh.rainbow.entities.time.simple.SimpleTime;
Expand Down Expand Up @@ -44,19 +43,26 @@ private Meeting(Day day, SimpleTime startTime, SimpleTime endTime, SimpleDate st
}

/**
* Convert meeting into DTO
* Create new meetings parsed from UH style input parameters
*
* @return MeetingDTO
* @param dayString Day string formatted D*
* @param timeString Time formatted HHmm-HHmm(?:a|p)
* @param roomString Room name
* @param dateString Date formatted DD/MM(?:|-DD/MM)
* @return List of parsed meetings
* @throws ParseException Fail to parse time or day block
*/
public MeetingDTO toDTO() {
return new MeetingDTO(
this.day.toString(),
this.room,
this.startTime.toString(),
this.endTime.toString(),
this.startDate.toString(),
this.endDate.toString()
public static List<Meeting> createMeetings(String dayString, String timeString, String roomString, String dateString) throws ParseException {
List<Meeting> meetings = new ArrayList<>();

List<Day> days = Day.toDays(dayString);

TimeBlock tb = new TimeBlock(timeString, dateString);
days.forEach((day) -> meetings.add(
new Meeting(day, tb.getStartTime(), tb.getEndTime(), tb.getStartDate(), tb.getEndDate(), roomString))
);

return meetings;
}

/**
Expand Down Expand Up @@ -95,26 +101,17 @@ public String getRoom() {
}

/**
* Create new meetings parsed from UH style input parameters
*
* @param dayString Day string formatted D*
* @param timeString Time formatted HHmm-HHmm(?:a|p)
* @param roomString Room name
* @param dateString Date formatted DD/MM(?:|-DD/MM)
* @return List of parsed meetings
* @throws ParseException Fail to parse time or day block
* @return Start Date of recurring meeting
*/
public static List<Meeting> createMeetings(String dayString, String timeString, String roomString, String dateString) throws ParseException {
List<Meeting> meetings = new ArrayList<>();

List<Day> days = Day.toDays(dayString);

TimeBlock tb = new TimeBlock(timeString, dateString);
days.forEach((day) -> meetings.add(
new Meeting(day, tb.getStartTime(), tb.getEndTime(), tb.getStartDate(), tb.getEndDate(), roomString))
);
public SimpleDate getStartDate() {
return this.startDate;
}

return meetings;
/**
* @return End Date of recurring meeting
*/
public SimpleDate getEndDate() {
return this.endDate;
}

}
Loading

0 comments on commit 85ed467

Please sign in to comment.