5.6. Students.rsl



(****
 *
 * Module StudentDB defines the database of students and associated data
 *
 *)

module StudentDB;
  
  export StudentDB;

  object StudentDB is
	components: studreclst:StudentRecord*;
	description: (*
		The Student Database is comprised of user records (which
		includes name, UID, classes taken, comments, etc, and
		StudentReport, which is a report generated from all
		student input.
	*);
  end;

  object StudentRecord is
	components: name:StudentName and id:StudentID and cdb:CourseTried* and comments:StudentComments;
	description: (*
		The UserRecord is all information pertaining to one
		student user.
	*);
  end;

  object StudentName is string;
  object StudentID is integer;

  object CourseTried is
	components: CourseName and Reason;
	description: (*
		Describes a class that a student attempted to take and
		was unsuccessful.
	*);
  end;

  object CourseName is string;

  object Reason is
	components: Reason_Full or Reason_TimeConflict or Reason_Instructor or Reason_OtherString;
	description: (*
		Reason why class was not available.
	*);
  end;

  object Reason_Full is boolean;
  object Reason_TimeConflict is boolean;
  object Reason_Instructor is boolean;
  object Reason_OtherString is
	components: string and boolean;
  end;

  object StudentComments is string;

  operation AddStudent is 
	inputs: sr:StudentRecord, sdb:StudentDB;
	outputs: sdb':StudentDB;

	precondition:
	(*
		There is no student record in the input database (StudentDB) with the
		same id as the record to be added.
	*)
	(not (exists (sr' in sdb) sr'.id = sr.id))
		and
	(*
		The id of the given student record is not empty and 32 characters or less.
	*)
	(sr.id != nil) and (#(sr.id) <= 32);

	postcondition:
	(*
		A student record is in the output database iff it is the new record to
		be added or it is in the input database
	*)
	forall (sr':StudentRecord) (sr' in sdb') iff ((sr' = sr) or (sr' in sdb));
	
	description: (*
		Adds a student record to the database if its ID is a suitable number of
		characters and a record does not already exist with the same ID.
	*);
  end AddStudent;

  operation RemoveStudent is 
	inputs: sr:StudentRecord, sdb:StudentDB;
	outputs: sdb':StudentDB;

	precondition:
	(*
		The given student record is in the given database
	*)
	sr in sdb;

	postcondition:
	(*
		A user record is in the output db iff it is not the input record
		and it is in the input db.
	*)
	(forall (sr':StudentRecord)
		(sr' in sdb') iff ((sr' != sr) and (sr' in sdb)));

	description: (*
		Removes a specific student record from the database, if it exists
		in the database.
	*);
  end RemoveStudent;

  operation ChangeStudent is
	inputs: old_sr:StudentRecord, new_sr:StudentRecord, sdb:StudentDB;
	outputs: sdb':StudentDB;
	
	precondition:
	(*
		The old and new records are not the same
	*)
	(old_sr != new_sr)
		and
	(*
		The old record is in the input database
	*)
	(old_sr in sdb)
		and
	(*
		There is no user record in the input database with the same
		id as the new record unless it is the old record
	*)
	(exists (sr' in sdb) (sr'.id = new_sr.id)) iff (exists (sr' in sdb) (sr' = old_sr))
		and
	(*
		The id of the new record is not empty and is 32 characters or less
	*)
	(new_sr.id != nil) and (#(new_sr.id) <= 32);

	postcondition:
	(*
		A student record is in the output database iff it is the new record
		to be added or it is in the input database, and it is not the old
		record
	*)
	forall (sr':StudentRecord)
		(sr' in sdb') iff (((sr' = new_sr) or (sr' in sdb)) and (sr' != old_sr));
		
	description: (*
		Finds a specific student record in the input database and replaces it with
		the new input record. The two input records must not be the same. The old
		record must be in the input database. The new record must meet the conditions
		for adding a record (AddStudent).
	*);
  end ChangeStudent;

  operation FindStudent is
	inputs: name:StudentName, sdb:StudentDB;
	outputs: srl:StudentRecord*;
	
	precondition:
	(*
		name is not empty
	*)
	(name != nil);

	postcondition:
	(*
		The output list contains all records with the input name in the input database
	*)
	(forall (sr' in srl) (sr' in sdb) and (sr'.name = name))
		and
	(*
		The output list is sorted alphabetically by id (courtesy of Dr. Gene Fisher)
	*)
	(forall (i:integer | (i >= 1) and (i < #srl))
		srl[i].id < srl[i+1].id);

	description: (*
		Searches the student database for records with matching
		student name. If more than one is found, the output list
		is sorted by id.
	*);
  end FindStudent;

  operation FindStudent is
	inputs: id:StudentID, sdb:StudentDB;
	outputs: sr':StudentRecord;

	precondition:
	(*
		id is not empty, and is 32 characters or less
	*)
	(id != nil) and (#id <= 32);

	postcondition:
	(*
		If there is a record with the given id in the input database, then the output
		record is equal to it, otherwise the output record is empty.
	*)
	(exists (sr in sdb) (sr.id = id) and (sr' = sr))
		or
	(sr' = nil);

	description: (*
		Searches the student database for a record with matching
		student ID number
	*);
  end FindStudent;

  operation ImportDatabase is
	inputs: xdb:XExternalDatabase;
	outputs: sdb':StudentDB;

	precondition:
	(*
		The input database is readable as full of student records
	*)
	xdb.conv;

	postcondition:
	(*
		All student records in the output database are also in the input
		database
	*)
	(forall (sr:StudentRecord) (sr in xdb.srl) iff (sr in sdb'));

	description: (*
		Replaces the current student database with the contents
		of an external database.
	*);
  end ImportDatabase;

  object XExternalDatabase is
	components: conv:CanBeConverted, srl:StudentRecord*;
	description: (*
		Contains student records in a format that can be read by the system.
	*);
  end;

  object CanBeConverted is boolean;

  operation GenerateReport is
	inputs: sdb:StudentDB;
	outputs: rv:ReportView;

	precondition: (* none ... works even if StudentDB is empty *)
		;
	postcondition:
	   (*
		ReportView contains all comments in the database, as well as all
		courseTried objects
	   *)
	
	forall (sr:StudentRecord | sr in sdb.studreclst) (if sr.comments != nil then (exists(com':StudentComments | com' in rv.comlst) (com' = sr.comments)))
	and
	forall (sr:StudentRecord | sr in sdb.studreclst) (if #(sdb.studreclst) != 0 then (exists(ct:CourseTried | ct in rv.cselst) ((forall(ct':CourseTried | ct' in sr.cdb) ct' = ct))));

	description: (*
		Generates a dialog to display detailed information about student
		statistics.
	*);
  end GenerateReport;


  object ReportView is
	components: comlst:StudentComments*, cselst:CourseTried*;
	description: (*
		Generate a list of comments and attempted courses from the student
		database in order to generate a report.
	*);
  end;

end StudentDB;


Prev: Room Listing | Next: File Handling | Up: Specification | Top: index