interface Course {
        extent courses;
        keys name,number;

        attribute string name;
        attribute string number;
        relationship List<Section> has_sections
                inverse Section::is_section_of
                {order_by Section::number};
        relationship Set<Course> has_prerequisites
                inverse Course::is_prerequisite_for;
        relationship Set<Course> is_prerequisite_for
                inverse Course::has_prerequisites;

        offer(in Semester) raises(already_offered);
        drop(in Semester) raises(not_offered);
                  }
interface Section {
        extent sections;
        keys is_section_of, number;

        attribute string number;
        relationship Professor is_taught_by inverse Professor::teaches;
        relationship TA has_TA inverse TA::assists;
        relationship Course is_section_of inverse Course::has_sections;
        relationship Set<Student> is_taken_by inverse Student::takes;
}
interface Employee {
        extent employees;
        keys name, id;

        attribute string name;
        attribute int id;
        attribute int annual_salary;

        hire(in Person);

        fire(in Employee) raises(no_such_employee);

}
interface Professor:Employee {
        extent professors;
        attribute string rank;

        relationship Set<Section> teaches inverse Section::is_taught_by;
        grant_tenure() raises (ineligible_for_tenure);
}

interface TA:Employee, Student{
        relationship Section assists inverse Section::has_TA;
}

interface Student{
        extent students;
        keys name,student_id;

        attribute string name;
        attribute string student_id;
        attribute string dorm_address;

        relationship Set<Section> takes inverse Section::is_taken_by;
        register_for_course(in Course, in Section) 
           raises (unsatisfied_prerequisites, section_full, course_full);

        drop_course(in Course) raises(not_registered_for_that_course);
        assign_mayor(in Department);
        transfer(in from:Section, in to:Section)
           raises (section_full, not_registered_for_section);
}