AE1ISO Coursework 03 Command based mail client (25%)

AE1ISO Coursework 03
Command based mail client (25%)

1. LearningObjectives

This coursework is designed to give you further experience with object oriented programming. This coursework will allow you to gain some experience working with:

Exception Handling Inheritance
Containers
JUnit testing

2. Question

You are working for a company which needs to develop a command-based email client. Although you have created your own specification and requirements in groups (for CW02), the company has received many suggestions, and has decided on a different solution. The email client is to be operated by entering the commands detailed in Section 3.2 of this document. The company is aware that some users do not like command-based systems, and have a team working in parallel on a graphical user interface (GUI). Note that you are not to implement or design anything regarding the GUI. To ensure that your client has the methods required for the user interface, a set of java interfaces have been provided to work with. This allows the team working on the GUI to know which methods they can call, allowing each team to work independently of each other (these interfaces form the contract between your objects and the user interface).

3. GeneralRequirements

Your client should be able to receive emails. When an email is received, it is placed in the “inbox” folder. It is a requirement that the inbox folder always exists and cannot be deleted or renamed. Similarly, emails sent should be placed in the “sent” folder, and this folder cannot be deleted or renamed. There are commands for creating new folders (see Section 3.2), renaming, listing, and deleting folders. A folder contains many messages – there should be no limit on how many messages may exist within a folder (see lecture slides on containers: OOP.09). It should be possible to sort the emails within a folder by the date sent, or by subject. The folder structure may only be one level deep, meaning folders do not need to be able to store other folders, and folder names must be unique. A message should not exist in two folders at the same time (moving a message from one folder to another does not duplicate it). By default a received message is marked as “unread”, until the view command is issued, this marks the message as “read”. All sent messages are read, and cannot be marked as unread. The default selected folder when the application starts is “inbox”, any commands issued before changing folder will be relative to inbox (e.g., by default the command “list” will list emails in the “inbox” folder).

If a command fails due to an IOException, you should print “Failed: could not connect to server”, and should not terminate the program.

3.1 Retrieving Emails

In a real system, the communication between a client and a server follows a specific protocol (the language they speak to each other in), such as POP3 or IMAP. For this coursework, you are provided with ‘EmailConnector.jar’, which is responsible for handling any communication with a server (this is done for you). Inside this jar are three classes of interest:

  •  InterfaceConnector – This is the interface you should use, which acts as a contract to the provided connectors. There are two different connector implementations.
  •  StandardConnector – This connector will simulate retrieving emails from a POP3 server. The emails will not change: each time you run the application, the same list of emails will be given.
  •  WikiConnector – This connector will simulate retrieving a range of random emails from a different server. The emails produced are random, which may create some difficulties with unit testing. It is not a requirement that you use the WikiConnector, but it may be useful for your testing and it illustrates the reason for Interfaces (You can swap one connector for another and your email client will should still function properly).

    The Javadoc for the InterfaceConnector is provided. An example usage is below:

    InterfaceConnector connector = StandardConnector.getInstance(); String messageIds = connector.listMessages(); System.out.println(messageIds);

    This example gets an instance of the “StandardConnector”. It then uses the interface to call the retrieveIds(); method on it, and print out a list of messageIds. As the interface is used, it is possible to easily swap the connector for the WikiConnector provided, for example:

    InterfaceConnector connector = WikiConnector.getInstance(); String messageIds = connector. listMessages(); System.out.println(messageIds);

    You can then retrieve a specific message known by its ID, in this example we retrieve a message with an id of 1:

          connector.retrMessage(1);
    

    Or you may mark a message for deletion using, e.g:

    connector.markMessageForDeleting(1);

    3.2 Commands

    Commands and folder names are case sensitive. For any invalid commands, or if invalid arguments are provided, print “Invalid command!” and return to the prompt.

    cf [name]

    Changes the active folder to the specified folder. For example “cf inbox” will change to the folder named inbox.

    listfolders

    Takes no arguments, lists all of the folders available. See the expected output for the format.

    list

    Lists the messages in the selected folder, see the expected output for the format.

rename [original name] [new name]

Renames the folder specified by the first argument to the name provided in the second argument. For example, “rename old archive” will rename the folder named “old” to “archive”.

sort [-d | -s]

Sorts the selected folder by the date or subject field. The field may be either “-d” or “-s”. Any other argument is invalid. The argument “-d” specifies to sort by date (new to old). The argument “-s” specified to sort by subject alphabetically in ascending order (a to z). Only one argument may be passed in, we do not need to sort on more than one field.

mkf [name]

Creates a new folder with the name specified in [name]. For example, “mkf todo” creates a folder named “todo”.

move [message ID] [folder name]

Moves a message from the selected folder to the folder named in the second argument. For example, “move 3 spam” moves message 3 (if it exists) to the folder “spam” (if it exists).

compose

This command allows the user to compose a message. It will prompt for all of the details required, see expected output for formatting. By default, messages which are sent should appear in the “sent” folder and should be marked as read.

delete [messageid]

If the message with ID [messageid] exists within the selected folder, marks it for deletion. This removes it from the folder, and also calls the “mark for deletion” method on the connector with the appropriate message ID. After a message is marked for deletion, it will not be listed by the server when calls are made to listMessages(). If a folder name is given, do not delete the folder unless the first argument “-r” exists.

delete –r [foldername]

Deletes the folder named [foldername]. The –r flag is required for deleting a folder. This will mark all messages within the folder for deletion (calling markMessageForDeleting for each message), and will remove the folder locally. If the folder is currently the active folder, the active folder should default to “inbox” which cannot be deleted.

view [messageid]

If the message is in the active folder, view the message with ID [messageid]. See expected output for formatting.

reply [messageid]

If the message is in the active folder, reply to the message. This is similar to the compose command but the “to” and “subject” fields are already known and so are not prompted for. Any message sent should be placed in the “sent” folder and should be marked as read.

mark [-r | -u] [messageid]

If the message with the id [messageid] exists within the active folder, marks it as read or unread. “-r” marks a message as read, “-u” marks a message as unread. For example “mark –u 4” marks message 4 as unread.

receive

Retrieves any messages from the connector, which have not already been retrieved. These messages should be added to the folder named “inbox”.

quit

Terminates the program.

3.3 Additional Requirements

You work should not use packages and should run in the lab machines using JDK 1.7. The main method, as provided, should not be moved from “MailClient.java” and should not need modifying other than to change the connector (if you wish). You should have a class named “View”. This class is responsible for handling the user input and all output using System.out, as such this class should not be responsible for retrieving mail from the connector or composing mails. You should have a “ClientModel”, which is responsible for storing the folders, active folder and current state of the client, as well as calling relevant methods on the connector when needed. It is a requirement that this class implements “InterfaceClientModel”. Each method described in this interface may be called directly (perhaps from your unit tests) and this class should work without relying on the View (eg if a GUI is created by another team in the company, it will have a “ClientModel” and will directly use the methods rather than using the “View”). Therefore, it is important that you carefully unit test the ClientModel. The ClientModel must have a constructor which takes in the connector as an argument, it should only require this one argument. It is strongly recommended that you consider where the parsing of the commands takes place, it is not the responsibility of the view to handle these commands (Consider a Command factory, and having different types of command objects).

You should use the Scanner provided and should not create additional instances of this Scanner. You should read input using the “nextLine()” method.

You must add some short comments at the start of your test classes describing which conditions your tests are testing. You should mention why you have chosen your particular tests. This should be no longer than 10 lines at 80 characters each.

3.4 Provided Files

EmailConnector.jar. See Section 3.1 detailing the usage of this jar file. To add this file to eclipse, right click on your project, go to “build path”, then “add external archives”. Browse for the .jar and press “ok”.

Interfaces are provided, please see Section 3.3 for their usage. You should not remove any methods or alter the existing method signatures in the interfaces: it is a requirement that all of the methods in the interfaces be implemented, and that they should work regardless of the order in which they are called. You may create as many private methods as you need, and if required you may add additional public methods to the interface (although the existing ones should remain unchanged and should be fully implemented).

4. Suggested Methodology

It is strongly recommended that you adopt test driven development to complete this coursework. The unit tests created are part of the assessment criteria, and it is essential that each of the methods defined in the interfaces work on their own and fulfil the requirements set out in the Javadoc (within the interfaces). It is recommended that you create several tests for each method, and then implement the code to make those tests pass. It would make sense to start off with some easy-to-test classes,

such as a Message class (implements InterfaceMessage) and a Folder class (Implements InterfaceFolder). If you are unsure how to create unit tests, please ask in the Computer Lab Session.

5. ErrorConditions&Successmessages

Please also see the expected output for error conditions and success messages. For an invalid command, the error message should read:

      Error: Not a valid command.

For invalid arguments (e.g the wrong number of arguments), the message should read:

      Error: Invalid arguments.

For a command which has possibly valid arguments but cannot be executed (e.g creating a folder which already exists), the error should start with “Error:”, and have a sensible message. These are detailed in the expected output, e.g:

      Error: Folder TestFolder exists already.

Or:

Only the error messages detailed in the specification, or shown in the expected output will be tested. If there are other error conditions which you wish to report, please think of a sensible error message and follow the same format “Error: [message]”

6. Expected Output

See expected output document available on Moodle.

7. Submission and Assessment

You are required to submit a .zip file containing all of your source code within one directory (not using packages) to TMA. It would be sensible to include your username in the zip’s filename, for example “AE1ISO-CW03-zy123456.zip”. Do not submit duplicates of your code, inside your directory there should be only one instance of each .java file. You should submit all files required to compile your work, including the provided jar file. You will be allowed one pre-submission, and one final submission for this coursework. The pre-submission will assess style, adherence to coding conventions and functionality. This will be assessed instantly. The final submission will assess the same conventions and functionality, but will include manual assessment of your JUnit tests. The final submission counts towards the grade, the pre-submission is only there to allow some guidance and instant feedback. If a submission is made to the pre-submission area but not the final submission area, no grade will be awarded. There is only one attempt allowed at the final submission area and feedback will not be instant due to the manual assessment of your unit tests. Heavy penalties will apply for work which does not compile or requires fixing: it is your responsibility to test your work thoroughly before submission.

7.1 Marking criteria:

Error: Message does not exist.

Pre-submission

Final submission

Functionality

60%

50%

Conventions

40%

30%

Your Unit Testing

0%

20%

Weight of final grade for CW03:

0%

100%