Project 4 — You've Got Mail, Round 2.5!
|
|
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.
This project comprises 4 simple parts:
search body <str>
search header {from|to|subject|sentdate} <str>
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
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
Searchable<>
and
StringSearchable
interfaces
It should be obvious from the methods given above that
Searchable
and StringSearchable
are Java interface
s, 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
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
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.
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.:
There are no extra credit options for this project.
The standard grading rules will apply to this project.
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
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.