This lab will build upon studios 16-21. You should complete all studios before starting the lab.
Throughout studios 16-21 and continuing into lab 5, you will build a software simulation of a file system, some simple file types that may be stored in a file system, and a user interface similar to a command prompt or terminal that allows a user to interact with the file system and files it contains. Throughout the design and implementation of the file system, OOP design principles and patterns learned throughout the semester will be used to ensure the file system is easy to extend with new functionality in the future, easy to modify without major code refactoring, and easy to configure with different functionality as needed. Here is a quick overview of what you have done in studio already:
- Studio 16: Creating a set of related classes via interface inheritance. A file system stores files of many different types. In this studio, you created an interface that declares the basic functionality all files share (read, write, append, getSize, getName). You then defined a couple of concrete file types that inherit this interface and define it appropriately for the given file type(TextFile, ImageFile(studio 17)). This creates a set of concrete file classes that share a common interface (AbstractFile).
- Studio 17: Programming to an interface. Now that you have some concrete file types,you need a way to store and manage access to files. This is the file system’s job. This studio introduces a new interface describing the functionality all file systems share(createFile (moved in studio 18), addFile, openFile, closeFile, removeFile) and introduces an implementation of this interface (SimpleFileSystem). The SimpleFileSystem may store and manage access to many different file types. To support this, the file system is programmed to use the AbstractFile interface. A file system stores AbstractFiles and interacts with AbstractFiles. As concrete classes that inherit and define the AbstractFile interface are subclasses of AbstractFile, objects of those classes may be used freely with the file system. New file types can easily be added to the file system by creating new concrete file classes that inherit the AbstractFile interface.
- Studio 18: Single responsibility principle and the abstract factory design pattern.
This studio separates the task of creating files from the file system object. A file system should simply be responsible for storing and managing access to files, not creating them.
A new object, a file factory, will be responsible for creating files instead. The abstract factory pattern is used to support extensibility and flexibility in our design. The AbstractFileFactory interface declares an interface for creating files and concrete file factory objects define that interface to handle the creation of objects of different concrete file types. The abstract factory pattern provides extensibility by making it easy to create new concrete file factory classes (as in studio 20). Each concrete file factory may enforce restrictions on what types of files it can create, or can vary how the files are actually created. The pattern supports flexibility as a client that creates files using the AbstractFileFactory interface may be configured with any concrete factory class that inherits from AbstractFileFactory. This allows us to easily configure a client to change what types of files it may create or how those files are created.
- Studio 19: Adding new functionality to existing file types via the visitor pattern.
This studio introduces the visitor pattern. The visitor pattern allows us to add new functionality to an existing set of related classes, where each concrete class may require a different implementation. For instance, a file may be displayed in different ways.
Maybe we want to display the bytes contained in the file directly, without any special formatting; maybe we want to display metadata about the file only; or, maybe we want to display the file in a format specific to that concrete file type. Rather than adding a virtual member function to the AbstractFile interface for each of these display methods (such as readBytes(), readMetadata(), readFormatted()) and overriding those methods in an appropriate way in each derived file class, we can instead use the visitor pattern to accomplish this without cluttering the AbstractFile interface. After completion, you will now have a couple of concrete visitors. One prints the contents of a file in a format specific to that file type, the other displays the metadata of the file.
- Studio 20: Password protected files using the Proxy pattern. This studio introduces the Proxy design pattern to start to build support for password protected files. A proxy object can be stored in place of a real file in the file system. Any attempts to read, write,or visit a file will require the user to enter the correct password for the file before gaining access.
- Studio 21: Adding a user interface and the command pattern. Up to this point,testing/interacting with the file system has been done via writing code in main. This studio creates a user interface (CommandPrompt) that allows a user to interact with thefile system by issuing commands. To implement this functionality, the command pattern is used. Each action the user can request is implemented as a ConcreteCommand object. When a user provides input, the CommandPrompt object invokes the appropriate command based on the user’s input. The touch command is introduced in this studio.
Touch is a command that creates a new file and adds the file to the file system.
What you will implement in lab 5: For lab 5, you will be creating a few additional commands to increase the functionality of the program. The commands you will modify or implement are listed below, you will find further details on the specification and requirements of each command later in this document. In lab 5, you will:
- Create and implement a command called “ls” to list all of the files stored in the file system
- Create and implement a command called “remove” to remove a file from the filesystem
- Modify the “touch” command to support creating password protected files
- Create and implement a command called “cat” that concatenates or writes user input into a file
- Create and implement a command called “ds” that displays the contents of a file based on the file’s type
- Create and implement a command called “copy” that makes a copy of an existing file and stores it in the file system with a different name (prototype pattern)
- Create and implement a command called “rename” that renames an existing file in the file system (composite pattern, strategy pattern)
And finally, the details…
Modify, or create and implement the following commands as described below. All commands you add should be ConcreteCommand objects as part of the command pattern. You should name your classes exactly as they are typed below when highlighted in blue. Header and source files for your classes should already be created and linked in the solution.
Note: You should not:
- Modify any base class interfaces to include additional functions not described in this document or studio assignments. For example: you cannot add a function to AbstractFile to return the file’s concrete type. You may modify AbstractFile to support the prototype pattern as this is required.
- Modify any tests.
- Determine a file’s type in a command object by using the file’s name and extension.
Command objects should not need to understand the types of files they are interacting with.
Doing any of the above will result in deductions.