Project 4 — You've Got Mail, Round 2.5!

Assigned Tuesday, November 22th
Program Due Wednesday, November 30th at 11:59pm
Weight 7%
Updates

Objectives

  1. To gain experience handling exceptions
  2. To gain experience creating interfaces
  3. To gain experience with Java generics

Project Overview

In this augmentation of your mail client application, you will add searching capabilities to your system. Furthermore, you will do it in a way that will exercise your knowledge of interfaces, generics, and exceptions. You will:

This is a relatively simple, tightly-scoped project, and should take only a modicum of time to complete. Also, we will not be providing any utility code, so that is one less thing to deal with.

Project Requirements and Specification

This project comprises 4 simple parts:

Part 1: Adding a SEARCH command to your program

You can start by adding a SEARCH command to your main command parsing loop in EmailClient.execute(). It will have two "modes", so I will describe the two separately:

To implement this in your updated execute() method and its helper methods, you must add code to parse the arguments, package it up as either: a String for body text searches; or a MessageHeader object for header searches; and eventually call one of the two overloaded search methods described in Part 2 below. Note that although the method definitions below declare their first parameter as type Searchable<> or StringSearchable, you will be calling them with your MailRepository reference variable as the actual argument. Parts 3 and 4 below will explain the other changes that will make this work. (Note: in Proj3, you were supposed to declare your reference variable to be of type MailRepository, even though you actually constructed an instance of FileMailRepository-- not only is this good style, but important for Proj4, so correct this if you didn't do it that way in Proj3)

For the header search option, look ahead to Part 4 below to see what the semantics of the mail search methods are, so that you can figure out what your parser must do in terms of initializing the MailHeader object.

Methods in the MailRepository hierarchy will return an array of ints, indicating the indices of any matching items. Both versions of SEARCH should use this returned list of mail item numbers to generate a header listing, much like what the LIST command outputs (hint: modularize and reuse!). Note: It is especially important to include the index numbers in the output is important here!

Don't worry: other than the parsing, there is little other new code here: the MailRepository changes in Part 4 do most of the work for the actual searching. likely (hint, hint!)) will then use to fetch and display header listings for.

Line count: 20 new lines + minor changes to old code

Part 2: Adding search methods to EmailClient()

This part is easy--really! All you have to do is cut-and-paste the following two method definitions and add them into your EmailClient class definition:

    private int[] searchMailFolder(Searchable<MailHeader> mailFolder,
                            MailHeader header) {
        return mailFolder.searchFor(header);
    }

    private int[] searchMailFolder(StringSearchable mailFolder, String pattern) {
        return mailFolder.searchFor(pattern);
    }

That's it for Part 2!

The purpose is to force you to use interfaces and generics, in an only slightly-contrived setting. The above code will force certain constraints on your design and implementation in Parts 3 and 4.

Line count: 0 new lines to write, since I provide the new code

Part 3: Creating the Searchable<> and StringSearchable interfaces

It should be obvious from the methods given above that Searchable and StringSearchable are Java interfaces, Searchable being a generic one, at that. (The reason for creating these two similar interfaces will be explained in class—incentive to show up.)

Each interface definition will consist of a single method declaration, for a method named searchFor() that takes one parameter; let's call it "item". For the declaration of searchFor() in the StringSearchable interface, the parameter "item" should be declared to be of type String. For the generic StringSearchable<> interface, searchFor()'s "item" parameter should be declared using the generic type paramter.

Line count: 2 new interface files, 2 lines each

Part 4: Adding searching to the MailRepository class hierarchy

In Project 3, you created an abstract class MailRepository, and you declared your reference variables in the EmailClient to be of this type (even though you actually constructed a FileMailRepository object). The way you are now treating this reference in your implementation of Parts 2 and 3 above means that the declaration of the class MailRepository will now need to be modified to indicate that it implements some interfaces.

This, in turn, implies that either MailRepository, or any of its concrete subclasses (like FileMailRepository), must implement the methods declared by the interfaces. Looking into my crystal ball, I would recommend implementing the methods in the concrete subclass FileMailRepository, since you have no idea how network mail repositories might work.

To implement this, then, you will add two overloaded searchFor() methods to FileMailRepository, one to search the body for a string, and another to search the headers. The header search will receive a MailHeader as a parameter, and will match any non-empty (i.e., not null or "") String field. So, you should check each of the four header fields, and if there is a real search string in there, you should scan for it in the corresponding header field for each mail item. Your code can assume only one of these fields will be non-empty.

In both cases, search boils down to calling the appropriate String method to see if the search string is found in the actual header or body string.

For your searchFor() method(s), we are adding one more restriction to make the project a better learning experience:
In your searchFor() method implementation(s), you are not allowed—for this project—to use any class reflection operators or methods.
That means you cannot use instanceof, or getClass(), or in any other way take an instance and try to figure out the actual object class and do conditional logic. Why will become clear later.

Line count: 20 lines of code for searching bodies, 30 lines for searching headers

Part X: Practice good programming habits

As always, also pay attention to good procedural programming principles! You should still write clear, modular code. This means breaking up oversized, monolithic methods into smaller, logically divided submethods, abstracting out common, repeated chunks of logic into private helper methods, giving your variables meaningful names, etc.--you know the drill.

You are not to use any classes other than those in the standard Java libraries, and those specifically provided by me, without first checking with me.

Provided Classes and Sample Files

You may use the libraries and sample files provided with Project 3. There are no additional classes or sample files necessary.

Project Hints and Notes

  1. No hints or notes yet. Stay tuned...

Sample Output

Since your EmailClient class will not have changed much, the output should be much as it was in Project 3. The only new output is for the SEARCH command, which will be almost identical to the LIST command; e.g.:

Command: list "test_mail_folder": 3 messages. 1 jdoe1@umbc.edu Sep 26 22:38 "Hello, how are you?" 2 prince@natlbank.co.ni Sep 27 01:15 "Offer to share unclaimed account" 3 reallylongname@trun... Sep 28 10:15 "I tend to blather on and on and on a"... Command: search body Red Bull 1 matches 3 reallylongname@trun... Sep 28 10:15 "I tend to blather on and on and on a"... Command: print 3 From: reallylongname@truncatedsitename.somedomainthatdoesntmatter.com Date: Tue, 28 Sep 2010 10:15:02 -0400 Subject: I used to blather on and on and on and on and on! Hello, there! How are you??? I just did my twenty-third hit of Red Bull, and I don't feel a thing!!??!!??!! Yahhhh!!!!!! Don't remember why I started writing this. Bye! Command: search header subject to 2 matches 2 prince@natlbank.co.ni Sep 27 01:15 "Offer to share unclaimed account" 3 reallylongname@trun... Sep 28 10:15 "I tend to blather on and on and on a"... Commmand: exit

Extra Credit Option

There are no extra credit options for this project.


Grading

The standard grading rules will apply to this project.


Project Submission

Before submitting your project, be sure to compile and test your code on the GL system. See the Project Compiling section of the course projects page for details on how to run and execute your project on GL.

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 proj3UtilLib.jar

where you would replace "proj3UtilLib.jar" with whatever jar file you are using.

To submit your project, type the command

submit cs202 Proj4a MailRepository.java FileMailRepository.java <any other .java files you created> See the Project Submission page for detailed instructions.

You may resubmit your files as often as you like, but only the last submittal will be graded and will be used to determine if your project is late. For more information, see the projects page on the course web site.

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.