package com.tevinjeffrey.rutgersct.rutgersapi.model;
import android.os.Parcel;
import android.os.Parcelable;
import android.support.annotation.NonNull;
import com.tevinjeffrey.rutgersct.rutgersapi.utils.SectionUtils;
import org.apache.commons.lang3.StringUtils;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
//This class is a bit complicated. It's a POJO for the GSON library to quickly serialize json data
// into java objects. It is also a parcelable object which means it allows the android system to serialize this object.
// Which in turn allows me to pss this object between Activities and Fragments.
public class Course implements Comparable, Parcelable {
private String title;
private String subject;
private double credits;
private String courseNumber;
private String subjectNotes;
private String courseNotes;
private String preReqNotes;
private String offeringUnitCode;
private int openSections;
private List<Section> sections = new ArrayList<>();
private String expandedTitle;
private Subject mEnclosingSubject;
private Request mRequest;
public Course() {
}
public Course(Course course) {
this.title = course.title;
this.subject = course.subject;
this.credits = course.credits;
this.courseNumber = course.courseNumber;
this.subjectNotes = course.subjectNotes;
this.courseNotes = course.courseNotes;
this.preReqNotes = course.preReqNotes;
this.offeringUnitCode = course.offeringUnitCode;
this.openSections = course.openSections;
this.expandedTitle = course.expandedTitle;
this.mEnclosingSubject = course.mEnclosingSubject;
this.mRequest = course.mRequest;
}
public Subject getEnclosingSubject() {
return mEnclosingSubject;
}
public void setEnclosingSubject(Subject mEnclosingSubject) {
this.mEnclosingSubject = mEnclosingSubject;
}
public void setRequest(Request mRequest) {
this.mRequest = mRequest;
}
public Request getRequest() {
return mRequest;
}
public String getSubject() {
return subject;
}
public String getCredits() {
if (credits % 1 == 0) {
return String.valueOf((int) credits);
} else {
return String.valueOf(credits);
}
}
public String getCourseNumber() {
return courseNumber;
}
public String getSubjectNotes() {
return subjectNotes;
}
public String getCourseNotes() {
return courseNotes;
}
public String getPreReqNotes() {
return preReqNotes;
}
public String getOfferingUnitCode() {
return offeringUnitCode;
}
public int getOpenSections() {
return openSections - getNumberOfOpenNoPrintSections();
}
public int getSectionsTotal() {
return getSections().size() - getNumberOfNoPrintSections();
}
String getExpandedTitle() {
if (expandedTitle != null) {
return expandedTitle.replaceAll("\\s+", " ").trim();
}
return null;
}
String getTitle() {
if (title != null) {
return title.replaceAll("\\s+", " ").trim();
}
return null;
}
public String getTrueTitle() {
return (getExpandedTitle() == null || getExpandedTitle().length() <= 0) ? getTitle() :
getExpandedTitle();
}
public int getNumberOfNoPrintSections() {
int num = 0;
for (Section s : getSections()) {
if (!s.isPrinted()) ++num;
}
return num;
}
public int getNumberOfOpenNoPrintSections() {
int num = 0;
for (Section s : getSections()) {
if (!s.isPrinted() && s.openStatus) ++num;
}
return num;
}
public List<Section> getSections() {
return sections;
}
public void setSections(List<Section> sections) {
this.sections = sections;
}
@Override
public String toString() {
return "Course" + getTrueTitle();
}
@Override
public int compareTo(@NonNull Object another) {
Course b = (Course) another;
int result;
result = new SubjectNumberComparator().compare(this.getSubject(), b.getSubject());
if (result == 0)
return new SubjectNumberComparator().compare(this.getCourseNumber(), b.getCourseNumber());
return result;
}
private class SubjectNumberComparator implements Comparator<String> {
@Override
public int compare(String lhs, String rhs) {
if (Integer.valueOf(lhs) > Integer.valueOf(rhs)) {
return 1;
} else if (Integer.valueOf(lhs) < Integer.valueOf(rhs)) {
return -1;
} else {
return 0;
}
}
}
public static class Section implements Comparable, Parcelable {
public List<Instructors> instructors = new ArrayList<>();
public List<MeetingTimes> meetingTimes = new ArrayList<>();
public List<CrossListedSections> crossListedSections = new ArrayList<>();
public List<Majors> majors = new ArrayList<>();
public List<Comments> comments = new ArrayList<>();
public String subtitle;
public String index;
public String specialPermissionAddCodeDescription;
public String specialPermissionAddCode;
public String specialPermissionDropCode;
public String offeringUnitCode;
public String synopsisUrl;
public String examCode;
public String sectionNotes;
public String number;
public String campusCode;
public String printed;
public Request request;
public Course course;
public Course getCourse() {
return course;
}
public void setCourse(Course course) {
this.course = course;
}
public Request getRequest() {
return request;
}
public void setRequest(Request mRequest) {
this.request = mRequest;
}
int stopPoint;
boolean openStatus;
public Section() {
}
public Section(Section dummy) {
this.instructors = dummy.instructors;
this.meetingTimes = dummy.meetingTimes;
this.crossListedSections = dummy.crossListedSections;
this.majors = dummy.majors;
this.comments = dummy.comments;
this.subtitle = dummy.subtitle;
this.index = dummy.index;
this.specialPermissionAddCodeDescription = dummy.specialPermissionAddCodeDescription;
this.specialPermissionAddCode = dummy.specialPermissionAddCode;
this.specialPermissionDropCode = dummy.specialPermissionDropCode;
this.offeringUnitCode = dummy.offeringUnitCode;
this.synopsisUrl = dummy.synopsisUrl;
this.examCode = dummy.examCode;
this.sectionNotes = dummy.sectionNotes;
this.number = dummy.number;
this.campusCode = dummy.campusCode;
this.printed = dummy.printed;
this.stopPoint = dummy.stopPoint;
this.openStatus = dummy.openStatus;
}
public List<MeetingTimes> getMeetingTimes() {
return meetingTimes;
}
public List<Instructors> getInstructors() {
return instructors;
}
public List<Comments> getComments() {
return comments;
}
public List<Majors> getMajors() {
return majors;
}
public List<CrossListedSections> getCrossListedSections() {
return crossListedSections;
}
public String getToStringMeetingTimes(String joiner) {
return StringUtils.join(meetingTimes, joiner);
}
public String getToStringInstructors(String joiner) {
return StringUtils.join(instructors, joiner);
}
public String getToStringComments(String joiner) {
return StringUtils.join(comments, joiner);
}
public String getToStringMajors(String joiner) {
return StringUtils.join(majors, joiner);
}
public String getToStringCrossListedSections(String joiner) {
return StringUtils.join(instructors, joiner);
}
public int getStopPoint() {
return stopPoint;
}
public String getIndex() {
return index;
}
public String getSpecialPermissionAddCodeDescription() {
return specialPermissionAddCodeDescription;
}
public String getSubtitle() {
return subtitle;
}
public String getSpecialPermissionAddCode() {
return specialPermissionAddCode;
}
public String getSpecialPermissionDropCode() {
return specialPermissionDropCode;
}
public String getOfferingUnitCode() {
return offeringUnitCode;
}
public String getSynopsisUrl() {
return synopsisUrl;
}
public String getExamCode() {
return examCode;
}
public String getSectionNotes() {
return sectionNotes;
}
public void setSectionNotes(String sectionNotes) {
this.sectionNotes = sectionNotes;
}
public String getNumber() {
return number;
}
public String getCampusCode() {
return campusCode;
}
public boolean isOpenStatus() {
return openStatus;
}
public boolean hasNotes() {
return getSectionNotes() != null;
}
public boolean hasComments() {
return getComments().size() > 0;
}
public boolean hasMajors() {
return getMajors().size() > 0;
}
public boolean hasSpecialPermission() {
return getSpecialPermissionAddCode() != null;
}
public boolean hasSubtitle() {
return getSubtitle() != null;
}
public boolean hasCrossListed() {
return getCrossListedSections().size() > 0;
}
public String getPrinted() {
return printed;
}
public boolean isPrinted() {
return getPrinted().equals("Y");
}
public boolean hasMetaData() {
return hasCrossListed() ||
hasSpecialPermission() ||
hasSubtitle() ||
hasMajors() ||
hasComments() ||
hasNotes();
}
@Override
public String toString() {
return "Section #" + getNumber();
}
@Override
public int compareTo(@NonNull Object another) {
Section anotherSection = (Section) another;
int result = 0;
if (this.getCourse() != null && anotherSection.getCourse() != null) {
result = this.getCourse().compareTo(anotherSection.getCourse());
if (result == 0) return new SectionComparator().compare(this, anotherSection);
}
return result;
}
private class SectionComparator implements Comparator<Section> {
@Override
public int compare(Section lhs, Section rhs) {
return lhs.getIndex().compareTo(rhs.getIndex());
}
}
public static class MeetingTimes implements Comparable, Parcelable {
String meetingDay;
String roomNumber;
String pmCode;
String startTime;
String endTime;
String buildingCode;
String meetingModeDesc;
String meetingModeCode;
String campusAbbrev;
String baClassHours;
public MeetingTimes() {
}
public boolean isLecture() {
return getMeetingModeCode() != null && getMeetingModeCode().equals("02");
}
public boolean isRecitation() {
return getMeetingModeCode() != null && getMeetingModeCode().equals("03");
}
public boolean isLab() {
return getMeetingModeCode() != null && getMeetingModeCode().equals("05");
}
public boolean isStudio() {
return getMeetingModeCode() != null && getMeetingModeCode().equals("07");
}
public boolean isByArrangement() {
return getBaClassHours() != null && getBaClassHours().equals("B");
}
public String getStartTime() {
return startTime;
}
public String getEndTime() {
return endTime;
}
public String getBuildingCode() {
return buildingCode;
}
public String getMeetingModeDesc() {
return meetingModeDesc;
}
public String getMeetingModeCode() {
return meetingModeCode;
}
public String getCampusAbbrev() {
return campusAbbrev;
}
public String getCampus() {
String campus;
if (getCampusAbbrev() != null) {
switch (getCampusAbbrev()) {
case "NWK":
campus = "Newark";
break;
case "CAM":
campus = "Camden";
break;
default:
campus = "New Brunswick";
}
return campus;
}
return null;
}
public String getBaClassHours() {
return baClassHours;
}
public String getMeetingDay() {
return meetingDay;
}
public String getRoomNumber() {
return roomNumber;
}
public String getPmCode() {
return pmCode;
}
@Override
public int compareTo(@NonNull Object time) {
MeetingTimes b = (MeetingTimes) time;
int result = new ClassRankComparator().compare(this, b);
if (result == 0) result = new TimeRankComparator().compare(this, b);
return result;
}
private class ClassRankComparator implements Comparator<MeetingTimes> {
@Override
public int compare(MeetingTimes lhs, MeetingTimes rhs) {
if (SectionUtils.getClassRank(lhs) < SectionUtils.getClassRank(rhs)) {
return 1;
} else if (SectionUtils.getClassRank(lhs) > SectionUtils.getClassRank(rhs)) {
return -1;
}
return 0;
}
}
private class TimeRankComparator implements Comparator<MeetingTimes> {
@Override
public int compare(MeetingTimes lhs, MeetingTimes rhs) {
if (SectionUtils.getTimeRank(lhs) < SectionUtils.getTimeRank(rhs)) {
return 1;
} else if (SectionUtils.getTimeRank(lhs) > SectionUtils.getTimeRank(rhs)) {
return -1;
} else {
return 0;
}
}
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(this.meetingDay);
dest.writeString(this.roomNumber);
dest.writeString(this.pmCode);
dest.writeString(this.startTime);
dest.writeString(this.endTime);
dest.writeString(this.buildingCode);
dest.writeString(this.meetingModeDesc);
dest.writeString(this.meetingModeCode);
dest.writeString(this.campusAbbrev);
dest.writeString(this.baClassHours);
}
protected MeetingTimes(Parcel in) {
this.meetingDay = in.readString();
this.roomNumber = in.readString();
this.pmCode = in.readString();
this.startTime = in.readString();
this.endTime = in.readString();
this.buildingCode = in.readString();
this.meetingModeDesc = in.readString();
this.meetingModeCode = in.readString();
this.campusAbbrev = in.readString();
this.baClassHours = in.readString();
}
public static final Creator<MeetingTimes> CREATOR = new Creator<MeetingTimes>() {
public MeetingTimes createFromParcel(Parcel source) {
return new MeetingTimes(source);
}
public MeetingTimes[] newArray(int size) {
return new MeetingTimes[size];
}
};
@Override
public String toString() {
return SectionUtils.getMeetingDayName(this) + " " + SectionUtils.getMeetingHours(this) + " "
+ SectionUtils.getClassLocation(this);
}
}
public static class Instructors implements Parcelable {
String name;
public Instructors(String name) {
this.name = name;
}
public String getName() {
return name.replaceAll("\\s+", " ").trim();
}
public String getFirstName() {
String firstName = StringUtils.substringAfter(name, ",");
if (name.equals(firstName)) {
return "";
} else {
return firstName.trim();
}
}
public String getLastName() {
return StringUtils.substringBefore(name, ",");
}
@Override
public String toString() {
return getName();
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(this.name);
}
protected Instructors(Parcel in) {
this.name = in.readString();
}
public static final Creator<Instructors> CREATOR = new Creator<Instructors>() {
public Instructors createFromParcel(Parcel source) {
return new Instructors(source);
}
public Instructors[] newArray(int size) {
return new Instructors[size];
}
};
}
public static class Comments implements Parcelable {
String description;
public Comments() {
}
@Override
public String toString() {
return getDescription();
}
public String getDescription() {
return description;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(this.description);
}
protected Comments(Parcel in) {
this.description = in.readString();
}
public static final Creator<Comments> CREATOR = new Creator<Comments>() {
public Comments createFromParcel(Parcel source) {
return new Comments(source);
}
public Comments[] newArray(int size) {
return new Comments[size];
}
};
}
public static class CrossListedSections implements Parcelable {
String sectionNumber;
String offeringUnitCode;
String subjectCode;
String courseNumber;
public CrossListedSections() {
}
public String getSectionNumber() {
return sectionNumber;
}
public String getOfferingUnitCode() {
return offeringUnitCode;
}
public String getSubjectCode() {
return subjectCode;
}
public String getCourseNumber() {
return courseNumber;
}
public String getFullCrossListedSection() {
return getOfferingUnitCode() + ":" + getSubjectCode() + ":"
+ getCourseNumber() + ":" + getSectionNumber();
}
@Override
public String toString() {
return getFullCrossListedSection();
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(this.sectionNumber);
dest.writeString(this.offeringUnitCode);
dest.writeString(this.subjectCode);
dest.writeString(this.courseNumber);
}
protected CrossListedSections(Parcel in) {
this.sectionNumber = in.readString();
this.offeringUnitCode = in.readString();
this.subjectCode = in.readString();
this.courseNumber = in.readString();
}
public static final Creator<CrossListedSections> CREATOR = new Creator<CrossListedSections>() {
public CrossListedSections createFromParcel(Parcel source) {
return new CrossListedSections(source);
}
public CrossListedSections[] newArray(int size) {
return new CrossListedSections[size];
}
};
}
public static class Majors implements Parcelable {
boolean isMajorCode;
boolean isUnitCode;
String code;
public Majors() {
}
public boolean isMajorCode() {
return isMajorCode;
}
public boolean isUnitCode() {
return isUnitCode;
}
public String getCode() {
return code;
}
@Override
public String toString() {
return getCode();
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeByte(isMajorCode ? (byte) 1 : (byte) 0);
dest.writeByte(isUnitCode ? (byte) 1 : (byte) 0);
dest.writeString(this.code);
}
protected Majors(Parcel in) {
this.isMajorCode = in.readByte() != 0;
this.isUnitCode = in.readByte() != 0;
this.code = in.readString();
}
public static final Creator<Majors> CREATOR = new Creator<Majors>() {
public Majors createFromParcel(Parcel source) {
return new Majors(source);
}
public Majors[] newArray(int size) {
return new Majors[size];
}
};
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeTypedList(instructors);
dest.writeTypedList(meetingTimes);
dest.writeTypedList(crossListedSections);
dest.writeTypedList(majors);
dest.writeTypedList(comments);
dest.writeString(this.subtitle);
dest.writeString(this.index);
dest.writeString(this.specialPermissionAddCodeDescription);
dest.writeString(this.specialPermissionAddCode);
dest.writeString(this.specialPermissionDropCode);
dest.writeString(this.offeringUnitCode);
dest.writeString(this.synopsisUrl);
dest.writeString(this.examCode);
dest.writeString(this.sectionNotes);
dest.writeString(this.number);
dest.writeString(this.campusCode);
dest.writeString(this.printed);
dest.writeParcelable(this.request, 0);
dest.writeParcelable(this.course, 0);
dest.writeInt(this.stopPoint);
dest.writeByte(openStatus ? (byte) 1 : (byte) 0);
}
protected Section(Parcel in) {
this.instructors = in.createTypedArrayList(Instructors.CREATOR);
this.meetingTimes = in.createTypedArrayList(MeetingTimes.CREATOR);
this.crossListedSections = in.createTypedArrayList(CrossListedSections.CREATOR);
this.majors = in.createTypedArrayList(Majors.CREATOR);
this.comments = in.createTypedArrayList(Comments.CREATOR);
this.subtitle = in.readString();
this.index = in.readString();
this.specialPermissionAddCodeDescription = in.readString();
this.specialPermissionAddCode = in.readString();
this.specialPermissionDropCode = in.readString();
this.offeringUnitCode = in.readString();
this.synopsisUrl = in.readString();
this.examCode = in.readString();
this.sectionNotes = in.readString();
this.number = in.readString();
this.campusCode = in.readString();
this.printed = in.readString();
this.request = in.readParcelable(getClass().getClassLoader());
this.course = in.readParcelable(getClass().getClassLoader());
this.stopPoint = in.readInt();
this.openStatus = in.readByte() != 0;
}
public static final Creator<Section> CREATOR = new Creator<Section>() {
public Section createFromParcel(Parcel source) {
return new Section(source);
}
public Section[] newArray(int size) {
return new Section[size];
}
};
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(this.title);
dest.writeString(this.subject);
dest.writeDouble(this.credits);
dest.writeString(this.courseNumber);
dest.writeString(this.subjectNotes);
dest.writeString(this.courseNotes);
dest.writeString(this.preReqNotes);
dest.writeString(this.offeringUnitCode);
dest.writeInt(this.openSections);
dest.writeTypedList(sections);
dest.writeString(this.expandedTitle);
dest.writeParcelable(this.mEnclosingSubject, 0);
dest.writeParcelable(this.mRequest, 0);
}
protected Course(Parcel in) {
this.title = in.readString();
this.subject = in.readString();
this.credits = in.readDouble();
this.courseNumber = in.readString();
this.subjectNotes = in.readString();
this.courseNotes = in.readString();
this.preReqNotes = in.readString();
this.offeringUnitCode = in.readString();
this.openSections = in.readInt();
this.sections = in.createTypedArrayList(Section.CREATOR);
this.expandedTitle = in.readString();
this.mEnclosingSubject = in.readParcelable(getClass().getClassLoader());
this.mRequest = in.readParcelable(getClass().getClassLoader());
}
public static final Creator<Course> CREATOR = new Creator<Course>() {
public Course createFromParcel(Parcel source) {
return new Course(source);
}
public Course[] newArray(int size) {
return new Course[size];
}
};
}