// Path: src/main/java/com/oskopek/studyguide/constraint/Constraint.java
// @JsonTypeInfo(include = JsonTypeInfo.As.WRAPPER_OBJECT, use = JsonTypeInfo.Id.NAME)
// @JsonSubTypes({@JsonSubTypes.Type(value = CourseEnrollmentCorequisiteConstraint.class,
//         name = "CourseEnrollmentCorequisiteConstraint"),
//         @JsonSubTypes.Type(value = CourseEnrollmentEnrolledInConstraint.class,
//                 name = "CourseEnrollmentEnrolledInConstraint"),
//         @JsonSubTypes.Type(value = CourseEnrollmentPrerequisiteConstraint.class,
//                 name = "CourseEnrollmentPrerequisiteConstraint"),
//         @JsonSubTypes.Type(value = CourseGroupCreditsPercentageConstraint.class,
//                 name = "CourseGroupCreditsPercentageConstraint"),
//         @JsonSubTypes.Type(value = CourseGroupCreditsSumConstraint.class,
//                 name = "CourseGroupCreditsSumConstraint"),
//         @JsonSubTypes.Type(value = CourseGroupFulfilledAllConstraint.class,
//                 name = "CourseGroupFulfilledAllConstraint"),
//         @JsonSubTypes.Type(value = GlobalCourseMaxFulfilledConstraint.class,
//                 name = "GlobalCourseMaxFulfilledConstraint"),
//         @JsonSubTypes.Type(value = GlobalCourseRepeatedEnrollmentConstraint.class,
//                 name = "GlobalCourseRepeatedEnrollmentConstraint"),
//         @JsonSubTypes.Type(value = GlobalCreditsSumConstraint.class,
//                 name = "GlobalCreditsSumConstraint"),
//         @JsonSubTypes.Type(value = GlobalCreditsSumUntilSemesterConstraint.class,
//                 name = "GlobalCreditsSumUntilSemesterConstraint"),
//         @JsonSubTypes.Type(value = GlobalLongStudyFeeConstraint.class,
//                 name = "GlobalLongStudyFeeConstraint")})
// public interface Constraint {
// 
//     /**
//      * The method should verify if the given constraint was broken, and if so,
//      * call the {@link #fireBrokenEvent(String, Course)} with the specific reason.
//      */
//     void validate();
// 
//     /**
//      * Used for firing a broken constraint event if the constraint is broken.
//      *
//      * @param message the reason why the constraint is broken
//      * @param changed the course that triggered the constraint breakage
//      */
//     void fireBrokenEvent(String message, Course changed);
// 
//     /**
//      * Used for firing a broken constraint event if the constraint is broken.
//      *
//      * @param message the reason why the constraint is broken
//      * @param changed the course enrollment that triggered the constraint breakage
//      */
//     void fireBrokenEvent(String message, CourseEnrollment changed);
// 
//     /**
//      * Used for firing a fixed constraint event if the constraint is fixed.
//      *
//      * @param originallyBroken the originally broken (now fixed) constraint
//      */
//     void fireFixedEvent(Constraint originallyBroken);
// }
// 
// Path: src/main/java/com/oskopek/studyguide/model/constraints/CourseGroup.java
// public class CourseGroup {
// 
//     private final ListProperty<Course> courseList;
// 
//     /**
//      * Private default constructor, needed by CDI.
//      */
//     protected CourseGroup() {
//         // needed by CDI
//         this.courseList = new SimpleListProperty<>();
//     }
// 
//     /**
//      * Builds a new, non-empty course group.
//      *
//      * @param courseList non-empty list of courses
//      * @throws IllegalArgumentException if any parameter is null or any list is empty
//      */
//     public CourseGroup(Collection<Course> courseList) throws IllegalArgumentException {
//         if (courseList == null || courseList.isEmpty()) {
//             throw new IllegalArgumentException("The parameters cannot be null and the lists cannot be empty.");
//         }
//         this.courseList = new SimpleListProperty<>(FXCollections.observableArrayList(courseList));
//     }
// 
//     /**
//      * The list property of courses in this group.
//      *
//      * @return non-null, not empty
//      */
//     public ReadOnlyListProperty<Course> courseListProperty() {
//         return courseList;
//     }
// 
//     /**
//      * The internal course list.
//      *
//      * @return non-null list of {@link Course}s
//      */
//     @JsonGetter
//     private List<Course> getCourseList() {
//         return courseList.get();
//     }
// 
//     /**
//      * Private setter for Jackson persistence.
//      *
//      * @param courseList the list of {@link Course}s to set
//      */
//     @JsonSetter
//     private void setCourseList(List<Course> courseList) {
//         this.courseList.set(FXCollections.observableArrayList(courseList));
//     }
// 
//     @Override
//     public int hashCode() {
//         return new HashCodeBuilder(17, 37).append(getCourseList()).toHashCode();
//     }
// 
//     @Override
//     public boolean equals(Object o) {
//         if (this == o) {
//             return true;
//         }
//         if (!(o instanceof CourseGroup)) {
//             return false;
//         }
//         CourseGroup group = (CourseGroup) o;
//         return new EqualsBuilder().append(getCourseList(), group.getCourseList()).isEquals();
//     }
// 
//     @Override
//     public String toString() {
//         return "CourseGroup[" + courseList.size() + ']';
//     }
// }


import com.oskopek.studyguide.constraint.Constraint;
import com.oskopek.studyguide.model.constraints.CourseGroup;
import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.HashCodeBuilder;
import java.util.ResourceBundle;
package com.oskopek.studyguide.constraint.event;



/**
 * The event used for reporting broken course group constraints.
 */
public class BrokenCourseGroupConstraintEvent extends StringMessageEvent {

    private final CourseGroup courseGroup;

    /**
     * Default constructor.
     *
     * @param messages the resource bundle used for resolving messages to their localized versions
     * @param message the message to use as a reason why the constraint is broken
     * @param broken the constraint that was broken and generated this event
     * @param courseGroup the course group that the constraint broke on
     */
// Path: src/main/java/com/oskopek/studyguide/constraint/Constraint.java
// @JsonTypeInfo(include = JsonTypeInfo.As.WRAPPER_OBJECT, use = JsonTypeInfo.Id.NAME)
// @JsonSubTypes({@JsonSubTypes.Type(value = CourseEnrollmentCorequisiteConstraint.class,
//         name = "CourseEnrollmentCorequisiteConstraint"),
//         @JsonSubTypes.Type(value = CourseEnrollmentEnrolledInConstraint.class,
//                 name = "CourseEnrollmentEnrolledInConstraint"),
//         @JsonSubTypes.Type(value = CourseEnrollmentPrerequisiteConstraint.class,
//                 name = "CourseEnrollmentPrerequisiteConstraint"),
//         @JsonSubTypes.Type(value = CourseGroupCreditsPercentageConstraint.class,
//                 name = "CourseGroupCreditsPercentageConstraint"),
//         @JsonSubTypes.Type(value = CourseGroupCreditsSumConstraint.class,
//                 name = "CourseGroupCreditsSumConstraint"),
//         @JsonSubTypes.Type(value = CourseGroupFulfilledAllConstraint.class,
//                 name = "CourseGroupFulfilledAllConstraint"),
//         @JsonSubTypes.Type(value = GlobalCourseMaxFulfilledConstraint.class,
//                 name = "GlobalCourseMaxFulfilledConstraint"),
//         @JsonSubTypes.Type(value = GlobalCourseRepeatedEnrollmentConstraint.class,
//                 name = "GlobalCourseRepeatedEnrollmentConstraint"),
//         @JsonSubTypes.Type(value = GlobalCreditsSumConstraint.class,
//                 name = "GlobalCreditsSumConstraint"),
//         @JsonSubTypes.Type(value = GlobalCreditsSumUntilSemesterConstraint.class,
//                 name = "GlobalCreditsSumUntilSemesterConstraint"),
//         @JsonSubTypes.Type(value = GlobalLongStudyFeeConstraint.class,
//                 name = "GlobalLongStudyFeeConstraint")})
// public interface Constraint {
// 
//     /**
//      * The method should verify if the given constraint was broken, and if so,
//      * call the {@link #fireBrokenEvent(String, Course)} with the specific reason.
//      */
//     void validate();
// 
//     /**
//      * Used for firing a broken constraint event if the constraint is broken.
//      *
//      * @param message the reason why the constraint is broken
//      * @param changed the course that triggered the constraint breakage
//      */
//     void fireBrokenEvent(String message, Course changed);
// 
//     /**
//      * Used for firing a broken constraint event if the constraint is broken.
//      *
//      * @param message the reason why the constraint is broken
//      * @param changed the course enrollment that triggered the constraint breakage
//      */
//     void fireBrokenEvent(String message, CourseEnrollment changed);
// 
//     /**
//      * Used for firing a fixed constraint event if the constraint is fixed.
//      *
//      * @param originallyBroken the originally broken (now fixed) constraint
//      */
//     void fireFixedEvent(Constraint originallyBroken);
// }
// 
// Path: src/main/java/com/oskopek/studyguide/model/constraints/CourseGroup.java
// public class CourseGroup {
// 
//     private final ListProperty<Course> courseList;
// 
//     /**
//      * Private default constructor, needed by CDI.
//      */
//     protected CourseGroup() {
//         // needed by CDI
//         this.courseList = new SimpleListProperty<>();
//     }
// 
//     /**
//      * Builds a new, non-empty course group.
//      *
//      * @param courseList non-empty list of courses
//      * @throws IllegalArgumentException if any parameter is null or any list is empty
//      */
//     public CourseGroup(Collection<Course> courseList) throws IllegalArgumentException {
//         if (courseList == null || courseList.isEmpty()) {
//             throw new IllegalArgumentException("The parameters cannot be null and the lists cannot be empty.");
//         }
//         this.courseList = new SimpleListProperty<>(FXCollections.observableArrayList(courseList));
//     }
// 
//     /**
//      * The list property of courses in this group.
//      *
//      * @return non-null, not empty
//      */
//     public ReadOnlyListProperty<Course> courseListProperty() {
//         return courseList;
//     }
// 
//     /**
//      * The internal course list.
//      *
//      * @return non-null list of {@link Course}s
//      */
//     @JsonGetter
//     private List<Course> getCourseList() {
//         return courseList.get();
//     }
// 
//     /**
//      * Private setter for Jackson persistence.
//      *
//      * @param courseList the list of {@link Course}s to set
//      */
//     @JsonSetter
//     private void setCourseList(List<Course> courseList) {
//         this.courseList.set(FXCollections.observableArrayList(courseList));
//     }
// 
//     @Override
//     public int hashCode() {
//         return new HashCodeBuilder(17, 37).append(getCourseList()).toHashCode();
//     }
// 
//     @Override
//     public boolean equals(Object o) {
//         if (this == o) {
//             return true;
//         }
//         if (!(o instanceof CourseGroup)) {
//             return false;
//         }
//         CourseGroup group = (CourseGroup) o;
//         return new EqualsBuilder().append(getCourseList(), group.getCourseList()).isEquals();
//     }
// 
//     @Override
//     public String toString() {
//         return "CourseGroup[" + courseList.size() + ']';
//     }
// }


// Path: src/main/java/com/oskopek/studyguide/constraint/event/BrokenCourseGroupConstraintEvent.java
import com.oskopek.studyguide.constraint.Constraint;
import com.oskopek.studyguide.model.constraints.CourseGroup;
import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.HashCodeBuilder;
import java.util.ResourceBundle;

package com.oskopek.studyguide.constraint.event;



/**
 * The event used for reporting broken course group constraints.
 */
public class BrokenCourseGroupConstraintEvent extends StringMessageEvent {

    private final CourseGroup courseGroup;

    /**
     * Default constructor.
     *
     * @param messages the resource bundle used for resolving messages to their localized versions
     * @param message the message to use as a reason why the constraint is broken
     * @param broken the constraint that was broken and generated this event
     * @param courseGroup the course group that the constraint broke on
     */
    public BrokenCourseGroupConstraintEvent(ResourceBundle messages, String message, Constraint broken,