Project 2 — You've Got Mail!
|
|
To establish your proficiency with:
This project is considered an OPEN project. Please review the open project policy before beginning your project.
Code from this project will be reviewed in class as noted on the schedule as “Project 2 Analysis.” If you would like your code to be reviewed in class, please contact your instructor. Your name will be held in strict confidence. This practice has worked extremely well in the past. It is a wonderful way to compare and contrast the different designs that people have used.
The goal of the remaining projects for the term is to lead you through the process of designing a large-scale, practical Java application, in an incremental, layered fashion. The end product will be a Java program and class library that should provice hours of amusement, and maybe even act as the seed for the first application release for your Android-centered startup!
We are going to be building a mail client program: an application that a user can run to read and manage a mailbox with a bunch of emails in it. (It is a client program to distinguish it from a mail server, which is a program that runs on server hosts maintaining a large collection of e-mailboxes.) The client app will be able to perform a variety of tasks, including displaying a listing of all email headers, printing out the full contents of a specific email, and even deleting some mail. Nice!
However, you have to learn to walk before you can run. To that end, I will be providing a library of utility classes that will do some of the low-level work for you. If we want to strain another metaphor, you can think of Project 2 as the cycling stage of a triathlon: someone is providing a nice bike for you, with multiple gears and maybe even working brakes, but you will still have to figure out how to use it skillfully to complete this leg of the challenge.
For Project 2, you will be building the upper layer of the mail-reading application. You will be provided with a set of utility class libraries that will provide simple primitives to manage an on-disk mail file that contains multiple email items. You will use these provided classes to create an executable program that can both read existing mail and create new mail.
To test that you know how to create classes as well as use them,
your main task will be to build a specific class--
EmailClient
--
that performs most or all of the work. It will have three public methods:
First, it will have a constructor that accepts as an argument the name of
the mail file to be opened.
(Not to worry: you do not have to be familiar with file I/O yet; you
will simply pass this filename through to one of the utility class
methods.)
On an instance of the EmailClient
class,
we will invoke the second public method--
execute()
--that will implement
a continuous loop prompting the user for the next command, collecting any
additional input necessary for the specific command, and then
executing the command through the necessary logic and calls to the
utility classes.
Lastly, you will write a main()
method
that you can use to test your class. At a minimum, it will instantiate
an EmailClient
object with a test mail file, and then invoke its
execute()
method.
A more rigorous, detailed description of these methods and what they must do is given in the "Requirements and Specification" section below.
To make the program a little more relevant, the input file will be structured as a real IMAP mail file (in fact, I will be creating it by sending myself test emails from several other accounts, and then just giving you a copy of that file as it is maintained on the CS mail server). While the utility classes will be parsing the file for you, I think it is still neat that the combination of your application and the provided library can work on real mail files.
Specific requirements for your program are:
EmailClient
; in fact, this will likely be the only class
you will create.
EmailClient
class is required to have at least the
three public methods listed below.
You must not change the method header for any of these specific methods
listed above. That means you cannot change the method
name, parameter names or types, nor method return value type.
public EmailClient(String emailFolder)
The parameter emailFolder
is the name of the disk file
that we wish to use as our mail folder (we will hereafter call it
a "mail folder", even though it is a single physical file, because
it contains a sequence of multiple email items).
Internally, this constructor will then invoke the proper method(s) from the
provided library to actually open up that file as the email folder.
EmailClient
must also define
the public method:
public boolean execute()
This method will manage the main command loop of the email client. For each turn of the loop, it will prompt the user for, and read in, a command request using the console I/O you learned about in Lab 2. Some commands will have additional arguments beyond just the command name (e.g., the "print" command requires an item#); these should be parsed from the rest of that command line. (Additionally, the "send" command has special I/O requirement; see below.)
The execute()
method must return a boolean indicating
whether there were any errors or not, including errors triggered by
bad requests from the user. (A return value of true
indicates there were errors.)
EmailClient
must define
the public method:
public static void main(String[] args)
This is for you to use to test your class, and consist, at a minimum, of
an instantiation of a EmailClient
object, followed by an
invocation of its execute()
method. You might want to
elaborate on that to do other things, like reading the filename from
the console, but that is completely up to you, and will not enhance your
grade.
execute()
method is the heart of the control structure
of your program. It will iteratively read from the console, and execute,
a sequence of commands until the user requests an exit.
The commands to be implemented are (along with required arguments):
list
print <item#>
delete <item#>
send <username@somehost>
exit
execute()
to return "false" if all went okay, "true" if there were one or more
errors, including any illegal requests by the user (e.g., asking to
print out a non-existent message.
Note that some of the commands take an "<item#>" argument, specifying which message to operate on; messages are numberd from "1", not "0" As they are internally numbered.
EmailClient
,
but only if it really makes
your code "better", by which I mean "clearer" or "easier to understand"
or "more logical". Recall what I said in lecture: performance is
definitely a lesser consideration than clarity for any application
that we will assign in this course, and even in the real world,
it is rare that sacrificing clarity for efficiency is a Good Thing.
Also note that trying to show off by making your code unnecessarily
clever/complex just annoys and antagonizes the graders.
The MailRepository class: No public instance variables. Public constructors: /** * returns an instance with the file param bound as the input mailbox MailRepository(String mailboxFile); /* 2-arg constructor for the Extra Credit option: */ MailRepository(String mailboxFile, boolean delayedCommit); Public methods: int getNumMessages(); MailHeader getMessageHeader(int msgIndex); String getMessageBody(int msgIndex); boolean deleteMessage(int msgIndex); boolean sendMessage(MailHeader header, String body); String getMessageStatus(int msgIndex); // For Extra Credit option boolean commitChanges(); // For Extra Credit option The MailHeader class: No public instance variables. Public constructors: MailHeader(); MailHeader(String fromAddr, String toAddr, String sentDate, String subject); Public methods: String getFromAddr(); String getToAddr(); String getSentDate(); String getSubject(); }
We have provided two files for you to download: a JAR file containing the library classes described above, and a sample mail file to use as input to test your program. Download them from these links:
Once you've downloaded these two files, copy theem to the top-level directory for your project in Eclipse. Do no put them down into the src or bin subdirectories. (Unix "directory" == Windows "folder")
Now, you have to configure Eclipse to see and use the library of classes inside the .jar file you just downloaded. Launch Eclipse, go into your Proj2 project, then follow these steps:
Two things about the file argument:
First, you will be using the 2-arg version of the constructor for MailRepository:
MailRepository(String mailboxFile, boolean delayedCommit);The delayedCommit argument should be "true" -- this will cause the MailRepository instance to be created in a special, delayed-delete mode.
Now, when you use the MailRepository.deleteMessage() method, it will not actually remove the message from the list; instead, it will be marked for later deletion. You can spot this by using the method:
String getMessageStatus(int msgIndex);This method currently returns one of two values: either the String "D", meaning "Deleted", or the empty String "", which means it is a plain, not-deleted message. You should augment your "LIST" command to add a column displaying a "D" for those messages marked for deletion. You should also print out a "Status:" line in the output of the "PRINT" command, right after the header, that indicates what the status is (just output the String returned by getMessageStatus()).
Next, you should add an "expunge" command that calls invokes the MailRepository method:
boolean commitChanges();This will cause the MailRepository to actually remove the messages marked for deletion, which will cause the remaining messages to be renumbered.
Here's a brief example of how the extra credit version should work:
Important Note:
When I provide any .jar files for the project, unless you
are an expert with JREs and classpaths, the easiest process is to
unpack the class files into your tree. To do this, from the same directory
as above, just type:
jar xf proj2UtilLib.jar
where you would replace "proj2UtilLib.jar" with whatever jar file you
are using.
To submit your project, type the command
Do not submit the provided library or test input file--we have those already :-)
More complete documentation for submit and related commands can be found here.
Remember -- if you make any change to your program, no matter how insignificant it may seem, you should recompile and retest your program before submitting it. Even the smallest typo can cause errors and a reduction in your grade.