In this problem you will implement a film information system inspired by the Internet Movie Database http://www.imdb.com. Your program will allow a user to create a database interactively---by entering films one by one at the keyboard---or in "batch" mode---by reading a bunch of films in from a file. It will also allow the user to retrieve information along different dimensions. For instance, list all the films in the database from the year 2000. Or, list all of the films in the database with "Rings" in the title.
A film's definition has multiple aspects: title, director, year, etc. To handle this aggregate information, you'll implement a Film class as specified below. Similarly, you'll create a Director class to handle various data stored for a given director. You'll implement a FilmDB class to manage the collection of films you've added to your database. Similarly, you'll implement a DirectorDB class to manage the collection of directors that have been (implicitly) added to your database (each time a film is entered with a new director, the director database incorporates a new Director object).
One interesting, fun challenge in this problem is the intertwined nature of the
classes you'll be defining. For instance, in addition to a director's first and
last name, a Director object contains a film database, FilmDB,
whose sole purpose is to make it easier to identify films on a per-director
basis. This feature leads to circular data in that FilmDB contains
Film objects, each which contains a Director object, which in
turn contains a FilmDB. These classes and their relationships to one
another are displayed in the following figure:
In general, you'd like your database to be able to adapt in size as more information is added (this is more efficient because you only allocate more resources when they are needed). However, to simplify the problem, you're allowed to assume each database you create has a fixed (suitably large, e.g. 100) size capacity. What this means is that, underneath the hood, your FilmDB and DirectorDB classes can simply create appropriate arrays of this length in their constructors. Should you then wish add more objects than this capacity supports, your program will inform the user they can't do this. In this scenario, it is important to keep some extra state around---for an array can tell you how long it is, but it doesn't know how many of its objects are currently used. For this reason, your database classes will also maintain a count field. Moreover, before any array element is assigned to a specific object instance, it will contain Java's all-purpose null value.
Extra Credit: If you wish to do extra credit on this problem, you could create your database arrays in such a way that they resize themselves as needed (they could thus start out with a size of 1 as opposed to 100!). Although this is a bit more involved because of the intertwined nature of the databases, it is definitely doable! If you'd like to try and implement this feature, only do so after you've already gotten the required version working robustly. Then you could extend that code (keep a copy of your original in case you don't get this working). It turns out a very efficient way to grow an array is to always double its size (and then copy the old items into the larger array). If you take this approach, you might consider adding a resize method to each of your database classes. Another viable option would be to use existing Java libraries (e.g. a grow-able array).
Submission: Place each of these classes in the
CS5App.java file and submit the CS5App.java file under
Homework 14, Problem 1. If you do the extra credit, submit that as Homework
14, Problem 2.
What's next: The rest of this document details the functionality of the classes you should build, followed by some documentation regarding some string methods you'll find useful and a sample run.
private String titleprivate int yearprivate String ratingprivate double reviewprivate Director dirpublic Film(String title, int year, String rating, double
review, Director dir) constructor initializes a new Film
object by setting its data members equal to the constructor's inputs.public String getTitle() returns the film's title.public Director getDirector() returns the film's
Director object.public int getYear() returns the film's year.public String getRating() returns the film's MPAA rating.public double getReview() returns a number between 1 and
10 that quantifies your assessment of the film (higher is better).public void display() should simply print the film's
data as follows:
Title: Unforgiven
Director: Eastwood, Clint
Year: 1992
Rating: R
Review: 8.0
Aside: printing the director's name requires calling the Director
object's getFullName().public void save() writes data out to a file in
a pre-specified format. (This pre-specified format allows the file to be
understandable to your program, so that it can read in the contents and use it
to initialize its database). In this, members should be printed out
in the same order as display, except that the human-readable descriptors
(e.g. "Title:", "Director:", etc.) are omitted. Additionally, the director's
last name and first name should appear on separate lines.
For example, the above film would appear as:
Unforgiven
Eastwood
Clint
1992
R
8.0
private String fnameprivate String lnameprivate FilmDB filmDBpublic Director(String fname, String lname,
int capacity) constructor initializes a new Director object
by setting its data members appropriately given the constructor's inputs.public String getFullName() returns the concatenation of
the last name, a comma, a space, and the first name. That is, if fname =
"Clint" and lname = "Eastwood" then this method should return a
String that contains the value "Eastwood, Clint". This concatenated
String is useful both for printing out the directors name and when putting
directors in alphabetical order.public String getFName() returns the director's first
name.public String getLName() returns the director's last
name.public FilmDB getFilmDB() returns the director's film
database (this will useful when adding new films).Required data members:
private Film[] filmsprivate int countpublic FilmDB(int capacity) initializes FilmDB
object by creating Films array to hold capacity elements in
total. Initially, no films are in the database, so count should be zero
(and each Film element should be null).public boolean isFull() returns true when all
element in films are not null Film entries.public boolean checkForFilm(String fulltitle) returns
true when a film with title fulltitle is found in the
array. When considering if a film is "found", use case insensitive criteria. For
example, if a film with the title unFORGivEn resides in the database
and fulltitle contains Unforgiven, this function should return
true. This method will be useful for enforcing that all film titles in
the database are unique, i.e. the user can not add two different films with the
same (case-insensitive) title.public int getCapacity() returns the size of the
Film array.public int getCount() returns the number of
non-null film entries currently in the array.public void addFilm(Film f) should add film f
to the database. Recommendations:
public void displayAllFilms() should print all the films
in the database in alphabetical order. Recommendations:
public void saveAllFilms() is similar to the
displayAllFilms except that if no films exist, that result is
be suppressed (you don't want to write that to the file). Also, instead of
display, here you'll use a Film's save method.public void displayFilmsByTitle(String titlepiece)
matches any film whose title (ignoring case) contains substring
titlepiece in it.public void displayFilmsByRating(String rating) matches
any films with the specified MPAA rating (ignoring case).public void displayFilmsByYear(int year) matches any
films with the specified year.public void displayFilmsByReview(double minreview)
matches any films with a review at least as high as minreview.private Director[] dirsprivate int countpublic DirectorDB(int capacity) is similar to the
FilmDB constructorpublic boolean isFull()public int getCount()public int getCapacity()public void displayAllDirectors()public Director findDirectorByName(String lname, String
fname) is like checkForFilm except that it identifies a
director using two pieces of information (last and first name). As with
checkForFilm this search should not be case-sensitive. Unlike
checkForFilm, however, this function returns the Director
object that was found (or null if the director isn't found). This
return value makes it easy to add a new film into an existing director's database.public void addDirector(Director dir) should add
director dir to the database by inserting it into the dirs
array in alphabetical order (sort first on last name; use first name to
break ties). Similar recommendations to those described in addFilms
apply here.public void displayFilmsByDirector(String lname, String
fname) displays all the films by a given director. The match for a
film's director should be case insensitive and employ both last and first name
(in writing this function there's a lot more opportunity for code reuse!). If
no film by this director is found, the user should be informed that this is why
no films could be displayed.private static FilmDB myFilmsprivate static DirectorDB myDirectorspublic static void printMenu() should first
print a status line indicating the database's capacity and how many
movies are currently entered. It should then display the following list of
options.
0 Display All Directors
1 Display All Films
2 Display Films by Title
3 Display Films by Director
4 Display Films by Year
5 Display Films by Rating
6 Display Films by Review
7 Add a New Film
8 Save database to file
9 Load database from file
42 Quit
public static void saveDB(String fileName) is provided
in the Hw14Pr1 download. Provide you properly implement the
FilmDB class's saveAllFilms method, this function will just
work! (That two classes can so effortlessly integrate to produce working
code is one reason why object-oriented programming is popular.) With this
function in place, you can first enter multiple films by hand (using option
7) and then save them to a file for later use (via option 8).
public static void readDB(String fileName) is also
provided for you, and again, provided you properly implement
readFilmEntry, this function will also just work! This function
provides an easy way to "bootstrap" your database (via option
9)---replacing the current contents of myFilms (which is
initially empty when the program starts up) with the database stored in file
fileName (typically, created in a prior run of your software, via
option 8).public static void readFilmEntry(), which is called by
readDB, should read in the next film entry and add that film into the
database. Because the order in which a film's entries are read in from the
keyboard (option 7) is identical to the order in which they are saved
(via Film's save method), this function can be used to service
both options 7 and 9. (Notice how good design can lead to code
reuse!). With keyboard input, users can make mistakes, and so this code should
insist that a valid MPAA rating is given before proceeding (refer to the
recommendations in the Film class); a similar requirement applies to
getting review input from the user. Aside: as long as input comes from a file that
has been written via other correctly implemented methods discussed here, what is
read in should always contain valid values.FilmDB.
If not, an error is printed and the method should return.
Director object,
prompt the user for the film's year.Film object
and add it to the film database.public static void main(String[] args) drives the rest
of the program, via an interface like the ones
you've built in previous assignments. At the top of main, initialize
your database to contain 100 Films and Directors. Then, repeatedly
present the user with the above menu of options, accept their request, and
process it (use option 42 to quit the loop).
Java provides String methods that will be useful to you in this assignment:
toLowerCase will allow you to perform case-insensitive matches.compareTo will allow you to perform alphabetic sorting.indexOf will allow you to determine if one string is a substring of another.
if (s.indexOf(t) >= 0) {
H.pl("t occurs as a substring in s");
} else {
H.pl("t does not occur as a substring in s");
}
prints out the latter message because the "U" in t is capitalized.
if (s.toLowerCase().indexOf(t.toLowerCase())) {
H.pl("if we ingore case, t occurs as a substring in s");
} else {
H.pl("if we ingore case, t does not occur as a substring in s");
}
prints out the former message (because now the "U" in t has been
transformed in to a new string that contains the corresponding "u"
instead).
if (s.compareTo(t) < 0)
H.pl("s is before t alphabetically");
else if (s.compareTo(t) > 0)
H.pl("s is after t alphabetically");
else
H.pl("s and t are identical strings");
Here is a sample run that displays how your code should function. This section only contains a small subset of the possible things we might try when testing your code. Be sure to test your code carefully before submitting it!
If you'd like to use the files I've used for testing (twofilms.txt and init.txt) these can be downloaded from http://www.cs.hmc.edu/~bthom. Another more extensive database file, which can be used for more exhaustive testing, as also available there (hardcore.txt).
Welcome to CS5's movie database!
There are 0 films in our database (max: 100)
Please choose an option from the following list:
0 Display all directors
1 Display all films
2 Display all films by Title
3 Display films by Director
4 Display films by Year
5 Display films by Rating (G, PG, ...)
6 Display films by Review (0-10)
7 Add a new film
8 Save database to file
9 Read database from file
42 Quit
Which option would you like? 9
Enter a file name: twofilms
Loading database contents from file ../twofilms.txt
100
2
Enter the title: Lord of the Rings: Return of
Enter the director's last name: Jackson
Enter the director's first name: Peter
Enter the movie's year: 2003
Enter the movie's MPAA rating: PG-13
Enter a review score: 9.0
Enter the title: Gigli
Enter the director's last name: Brest
Enter the director's first name: Martin
Enter the movie's year: 2003
Enter the movie's MPAA rating: R
Enter a review score: 2.2
There are 2 films in our database (max: 100)
< menu snipped to save trees >
Which option would you like? 0
Director #0 is Brest, Martin
Director #1 is Jackson, Peter
There are 2 films in our database (max: 100)
< menu snipped to save trees >
Which would you like? 7
Enter the title: King Kong
Enter the director's last name: jackson
Enter the director's first name: peter
Enter the movie's year: 2005
Enter the movie's MPAA rating: x
That is not a valid rating. Enter another: PG-13
Enter a review score: 6.0
There are 3 films in our database (max: 100)
< menu snipped to save trees >
Which option would you like? 1
Title: Gigli
Director: Brest, Martin
Year: 2003
Rating: R
Review: 2.2
Title: King Kong
Director: Jackson, Peter
Year: 2005
Rating: PG-13
Review: 6.0
Title: Lord of the Rings: Return of the King
Director: Jackson, Peter
Year: 2003
Rating: PG-13
Review: 9.0
There are 3 films in our database (max: 100)
< menu snipped to save trees >
Which option would you like? 2
Enter a titlepiece: king
Title: King Kong
Director: Jackson, Peter
Year: 2005
Rating: PG-13
Review: 6.0
Title: Lord of the Rings: Return of the King
Director: Jackson, Peter
Year: 2003
Rating: PG-13
Review: 9.0
There are 3 films in our database (max: 100)
< menu snipped to save trees >
Which option would you like? 3
Enter last name: Peter
Enter first name: Jackson
No films by director "Peter,Jackson"
There are 3 films in our database (max: 100)
< menu snipped to save trees >
Which option would you like? 3
Enter last name: bREst
Enter first name: MaRtIn
Title: Gigli
Director: Brest, Martin
Year: 2003
Rating: R
Review: 2.2
There are 3 films in our database (max: 100)
< menu snipped to save trees >
Which option would you like? 8
Enter a file name: threefilms
Saving the database's contents to the file ../threefilms.txt
There are 3 films in our database (max: 100)
< menu snipped to save trees >
Which option would you like? 5
Enter MPAA rating: santa
That is not a valid rating. Enter another: r
Title: Gigli
Director: Brest, Martin
Year: 2003
Rating: R
Review: 2.2
There are 3 films in our database (max: 100)
< menu snipped to save trees >
Which option would you like? 9
Enter a file name: init
Loading database contents from file ../init.txt
There are 0 films in our database (max: 100)
< menu snipped to save trees >
Which option would you like? 1
No films in database to display
There are 0 films in our database (max: 100)
< menu snipped to save trees >
Which option would you like? 9
Enter a file name: threefilms
Loading database contents from file ../threefilms.txt
Enter title: Gigli
Enter director's last name: Brest
Enter the director's first name: Martin
Enter the movie's year: 2003
Enter the movie's MPAA rating: R
Enter a review score: 2.2
Enter title: King Kong
Enter director's last name: Jackson
Enter the director's first name: Peter
Enter the movie's year: 2005
Enter the movie's MPAA rating: PG-13
Enter a review score: 6.0
Enter title: Lord of the Rings: Return of the King
Enter director's last name: Jackson
Enter the director's first name: Peter
Enter the movie's year: 2003
Enter the movie's MPAA rating: PG-13
Enter a review score: 9.0
There are 3 films in our database (max: 100)
< menu snipped to save trees >
Which option would you like? 6
Enter a review: 8
Title: Lord of the Rings: Return of the King
Director: Jackson, Peter
Year: 2003
Rating: PG-13
Review: 9.0
There are 3 films in our database (max: 100)
< menu snipped to save trees >
Which option would you like? 42
Until next time, your movie is up!