(* Chris Noe *) (* describe file formats *) module File; from Edit import UserWorkSpace; from Question import QuestionDB; from Test import Test; export FileSpace, File, RequiresSaving, FileType, TakenTestType, GradedTestType; object FileSpace is File* description: (* A FileSpace is an abstract model of a file space in the operating environment in which the TestTool is run. The FileSpace is simply a collection of zero or more Files, with no other properties modeled here. *); end; object File is components: name:FileName and permissions:FilePermissions and file_type:FileType and data:FileData; description: (* A File is an abstraction of a file stored in the file space. It has a name, permissions, type, and data. These are the components sufficient to specify the behavior of Question Tool file operations. *); end File; object FileName is string description: (* The name of a file. The string representation here is an abstraction of file names used in specific operating environments. Implementations may obey any syntactic or semantic constraints imposed by a particular environment. *); end; object FilePermissions is is_readable:IsReadable and is_writable:IsWritable description: (* FilePermissions indicate whether a file is readable and/or writable. *); end; object IsReadable is boolean description: (* Flag indicating whether a file is readable, which is required to be true by the FileOpen operation. *); end; object IsWritable is boolean description: (* Flag indicating whether a file is writable, which is required to be true by the FileSave operation. *); end; object FileType is test_type:TestType or taken_test_type:TakenTestType or graded_test_type:GradedTestType or other_type:OtherType description: (* The type of file data is either TestType data (which we care about) or any other type of data that can be stored in a file, which we don't care about. *); end FileType; object TestType description: (* File data typing tag indicating that a file contains test data created by the Question Tool. *); end TestType; object TakenTestType description: (* File data typing tag indicating that a file contains taken test data created by the Question Tool. *); end TakenTestType; object GradedTestType description: (* File data typing tag indicating that a file contains graded test data created by the Question Tool. *); end GradedTestType; object OtherType description: (* File data typing tag indicating that a file contains data other than test data created by the Question Tool. *); end OtherType; object FileData is Test description: (* The abstract representation of test-type FileData is a Test object. Question Tool implementors may use any concrete file data representation that accurately holds all Test components. *); end FileData; object RequiresSaving is boolean description: (* True if a test requires saving, which is the case if one or more successful edit operations has been performed since the most recent save. *); end RequiresSaving; operation FileNew is inputs: uws:UserWorkSpace; outputs: uws':UserWorkSpace; description: (* Add a new empty test to the workspace and make it current. *); precondition: (* none *); postcondition: (* * The output workspace has a new empty test and that test is * current. We are using a single document model, so the logic * here is fairly simple. *) (exists (test:Test) (test = uws'.test) and (not test.requires_saving) ); end FileNew; operation FileOpen is inputs: fs:FileSpace, fn:FileName, uws:UserWorkSpace; outputs: uws':UserWorkSpace; description: (* Open an existing test file of the given name and put the data from that file in the workspace. *); precondition: (* * A file of the given name exists in the given file space, the file * is readable, and the file's data are of type test. *) exists (file in fs) (file.name = fn) and file.permissions.is_readable and file.file_type?test_type; postcondition: (* * The output workspace has a new test containing the file data of * the input file. We are using a single document model. *) (exists (test:Test) (test = uws'.test) and (exists (file in fs) (file.name = fn) and (test = file.data) ) and (not test.requires_saving) ); end FileOpen; operation FileClose is inputs: fs:FileSpace, uws:UserWorkSpace; outputs: uws':UserWorkSpace; description: (* Close the current test if it does not require saving. *); precondition: (* * The test does not require saving. *) not (uws.test.requires_saving); postcondition: (* * The current test is deleted from the workspace. *) (uws.test = nil); end FileClose; operation FileSave is inputs: fs:FileSpace, uws:UserWorkSpace; outputs: fs':FileSpace, uws':UserWorkSpace; description: (* If the test in the given workspace requires saving, save it in the given file space. *); precondition: (* * The given workspace requires saving. Also, there is a writable * file of the current workspace filename in the given FileSpace. Note * that the only way the current file could be unwritable is through an * external change to the file space since the file was opened by the * Question Tool. Note further that this precondition disallows the * case where the current test file has been externally deleted * since it was opened by the test tool. That is, the file must * both exist and be writable at the time the save is attempted. *) (uws.test.requires_saving) and (exists (file in fs) (file.name = uws.test.file.name) and (file.permissions.is_writable)); postcondition: (* * There is a test-type file in the resulting FileSpace containing * the current workspace test as its file data. In the resulting * workspace, the requires saving indicator is false. *) (exists (file in fs') (file.name = uws'.test.file.name) and (file.data = uws'.test) and (file.permissions.is_writable) and (file.file_type?test_type) and (not uws'.test.requires_saving) ); end FileSave; end File;