PA1: phrameworks¶

Learning Objectives¶
This assignment is designed to help you learn several things. First, it will help you learn about file input. Second, it will help you learn about exceptions. Finally, it will help you learn about specialization, inheritance, and polymorphism.
Overview¶
HomeRun is a (fictitious) company that designs and develops software and hardware for use in and around the home, especially products that help people run their households more easily. One such product is phrameworks.
HomeRun is developing phrameworks because they recognize that people are taking more photographs than ever before and that, while many photographs are posted on social networking sites of various kinds, people still want to be able to display their photographs around their homes. To satisfy that need, several companies, including HomeRun, manufacture and sell digital picture frames.
phrameworks are the next generation of digital picture frame. Unlike existing systems, phrameworks are equipped with sensors that can sense the temperature, humidity, sound waves, and light waves. In addition, phrameworks frames are aware of the date and time and any personal information the user wants to provide them with. Hence, phrameworks frames can display context-sensitive "show lists" (where a "show list" is like a "play list" for an MP3 player, but for photographs).
HomeRun has designed the first version of the software components of phrameworks and have come to you to implement those components. Because the hardware is not yet available, they have provided you with a software simulator that you can use during the implementation process. The relationships between the classes they want you to implement and the simulator are illustrated in the following UML class diagram (which can be enlarged by zooming-in on this page or by right-clicking and opening it in another window/tab).
Classes in green were written by the GUI development team, classes in
purple are part of the Java libraries, and classes in black are to be
written by you for this assignment. Pay careful attention to the
packaging in this UML diagram. In particular, note that HomeRun puts
all of its main classes in the pa1.homerun package and organizes other
classes based on their functionality.
Background Information¶
Before you can start working on the components, you need to learn a
little bit about the format and naming of of Photo files.
The Naming of Photo Files¶
Photo file names start with a prefix and a number (that contains
leading 0s), and end with ".txt". The prefix can be any valid
String, the numbers start with 0, and the numbers end with the
largest possible number of photos on the device (which will, when the
hardware is completed, be determined by the amount of memory in the
Phrame). So, for example, if the prefix is "Photo" and the largest
Photo number is 9999, then the valid file names would be
"Photo0000.txt", "Photo0001.txt", "Photo0002.txt", …,
"Photo9999.txt". Note that all valid file names may not be used at
any particular point in time. In other words, there can be gaps in the
numbering.
The Format of Photo Files¶
Each Photo file contains one record that contains two or more
fields, delimited using the green character in the figure below.

-
The first field, which is always present, contains the name of the file containing the actual image.
-
The second field, which is always present, contains a
Stringrepresentation of thePhotoobject's current rating (i.e., how much the person likes thePhoto). AStringthat can't be converted into anInteger(e.g.,"NA","Unrated") indicates that thePhotohas not been rated. Otherwise, the rating is guaranteed to be between0and5(inclusive). -
The remaining fields, if present, contain tag-value pairs (delimited using the red character in the figure above) with information about the
Photo. Both the tag and the value may contain spaces, but are guaranteed not to contain any of the delimiters shown in the figure above.
In this example, field 0 contains the name of the image file
(pic011.png), field 1 contains the rating (2), and fields 2
through 3 contain tag-value pairs. This
Photo was tagged with two pieces of information – a description and a
location. The values indicate that the
Photo is of a street scene and that it was taken in Barcelona.
Twenty-three Photo files (named Photo00.txt to Photo22.txt),
along with their corresponding images, have been made available to you
for testing. They are available at:
They contain enough variety for you to completely test your code. Of
particular interest are: Photo00.txt which contains a rating of
"NA", Photo02.txt which refers to a nonexistent image file,
Photo07.txt which contains a rating of "Unrated", and
Photo13.txt which contains a rating of "N/A".
Existing Components¶
The .class file for the Phrame class has been provided for you in
the following .jar file:
The source code for the Phrameworks class has been provided for you in the
following .java file:
Phrame¶
The hardware simulator, is encapsulated in the Phrame class. When
it is constructed, it is passed an object that has all of the
capabilities of a SequentialShowList. It uses that object to show a
particular set of Photo objects. It's methods are shown in the UML
class diagram.
Phrameworks¶
The Phrameworks class is the main class for the simulated product.
You must not modify this file in any way. You are being provided with
the source code to help you debug your code.
When executed, the main() method in the Phrameworks class must be
passed either one, two or three parameters. It will always be passed a
String representation of the delay between photos (in milliseconds).
If there are exactly two arguments, then the second
argument will be a String representation of the rating of interest. If
there are exactly three arguments, then the second argument will be the
tag of interest and the third argument will be the value of
interest. The main() method then:
-
Uses the
PhotoReaderclass to read all (potentially numbered from 00 to 99) of thePhotoobjects that have the file names"Photo00.txt","Photo01.txt", …,"Photo99.txt". (Note the leading 0s in the numbers that are less than 10.) -
Constructs the appropriate kind of
SequentialShowList(based on the number of arguments); -
Constructs a
Phramethat will use theSequentialShowList; and -
Makes the
Phramevisible.
Components to be Written¶
You must write the Photo, PhotoReader, SequentialShowList,
RatingShowList, and TagShowList components, as well as tests for
all of these components.
Photo¶
A Photo is an encapsulation of a photograph and its properties. In
addition to the specifications contained in the UML class diagram,
this class must conform to the following specifications.
-
tagsandvaluesmust be conformal, and must contain the tag-value pairs. -
The constructors must initialize all of the attributes.
- They must read the
BufferedImagethat has the given file name (using the appropriate method in thePhrameclass) and assign it to the appropriate attribute. - They must assign the
ratingparameter to the appropriate attribute without doing any error-checking or validation. - The four-parameter constructor must make the attributes named
tagsandvaluesaliases for the corresponding parameters. - The two-parameter constructor must make the attributes named
tagsandvaluesbothnull. (Note: The two-parameter constructor must not duplicate any code in the four-parameter constructor.)
- They must read the
-
The
getTagValue()method must returnnullif thePhotoobject does not have a tag-value pair with the given tag. Otherwise, it must return the value for that tag (e.g., the value"Barcelona"for the tag"Location").- It must return
nullif the given tag isnull. - It must return
nullif thetagsattribute or thevaluesattribute (or both) isnull. 3. Think About. It must return all of thevaluesthat begin with the given letters if thetagsattribute ends with a*character.
- It must return
PhotoReader¶
The PhotoReader class can be used to read Photo objects from the
file system. You must assume that the format of each file is
correct, though, as discussed above, fields that are supposed to
contain numeric values may not actually contain numeric values, and
you must account for this.
-
The
digits()method returns the number of digits in anint. For example, when passed the number5this method must return1and when passed the number1284this method must return4. -
The
fileNameFormat()method returns a formatStringthat can be used with theString.format()method to create a file name. For example, for a prefix of"Photo"and annof99, this method must return the formatString"Photo%02d.txt". Then, invokingString.format("Photo%02d.txt", 8)would return"Photo08.txt"which is a potentially valid file name. (Note the leading 0.) -
The
read()method is passed two parameters that are used to describe the file names. The first, namedprefix, contains the characters in the file name that precede the number. The second, namedn, contains the largest possible photo number. So, for example, if this method is passed"Photo"and99it means that the file names will potentially go from"Photo00.txt"to"Photo99.txt"(though the file system may contain fewer files than that).-
Possible file names must be read in Think About. reverse numerical order.
-
If there is no file with a possible name or the
BufferedImageassociated with thePhotoobject can't be read, theread()method must not add thatPhototo theArrayListand continue on to the next file name. -
If the rating cannot be converted into a number, then the rating must be set to -1 (indicating that it has not been rated).Think About. If the rating is even it must be set to 0, if it is odd it must be set to 1.
-
RatingShowList¶
A RatingShowList is a "show list" that must repeatedly show
Photo objects that have a rating that is greater than or equal to a
target rating.
In addition to the specifications contained in the UML class diagram, this class must conform to the following specifications.
-
The constructor must not perform any error-checking.
-
The
targetrating passed to the constructor must be used to determine if thePhotoobject passed to theshouldShow()method results in a return value oftrueorfalse.-
The
shouldShow()method must returnfalsewhenphotois null. -
The
shouldShow()method must returntruewhen thePhotoobject's rating is greater than or equal to the target rating.Think About. The rating must be 10 more than the target rating for the method to returntrue.- If the target rating is -1 then the
shouldShow()method must only returntruewhen thePhotoobject's rating is -1.Think About. Or non-negative).
- If the target rating is -1 then the
-
-
It must not contain any
public,package, orprotectedmethods methods that are not included in the UML class diagram.
TagShowList¶
A TagShowList is a "show list" that must repeatedly show Photo
objects that have a target tag-value pair. In addition to the
specifications contained in the UML class diagram, this class must
conform to the following specifications.
-
The
targetTagandtargetValuepassed to the constructor must be used to determine if thePhotoobject passed to theshouldShow()method results in a return value oftrueorfalse.-
The
shouldShow()method must returnfalsewhenphotoisnull. -
The
shouldShow()method must returnfalsewhen thetargetTagisnull. -
The
shouldShow()method must returnfalsewhen thetargetValueisnull. -
The
shouldShow()method must returnfalsewhen thePhotoobject's value for thetargetTagisnull. -
Otherwise, the
shouldShow()must returntruewhen thePhotoobject's value for thetargetTagequals thetargetValue.Think About. It must returntrueonly when the two are equal in the sense of the==operator..
-
-
It must not contain any
public,package, orprotectedmethods methods that are not included in the UML class diagram
SequentialShowList¶
A SequentialShowList is a "show list" that repeatedly shows all
of the Photo objects it contains, in order.
-
The
indexattribute must be used to keep track of the nextPhototo potentially be returned by thegetNext()method (see below). How you do this is up to you. -
The constructor must make the
photosattribute an alias of thephotoscollection that it is passed. -
The
shouldShow()method must returnfalsewhen the parameter isnull, otherwise it must returntrue(since allPhotoobjects in aSequentialShowListshould be shown). -
The
getSize()method must return the number of elements in thephotoscollection that should be shown. -
The
getNext()method must return the nextPhotoin thephotoscollection that should be shown.-
It must throw a
NoSuchElementException(which is in thejava.utilpackage) whengetSize()evaluates to 0. -
When
getSize()does not evaluate to0, it must always return the nextPhotoobject.- Calls to
getNext()must repeatedly cycle through thephotoscollection (i.e., theindexattribute must be reset after the last element is returned).
- Calls to
-
-
The
reset()method must reset the index attribute in such a way that the subsequent call togetNext()will behave exactly like the first call togetNext()(i.e., it must "reset" the showlist).
Testing¶
Some of the tasks that you must complete involve unit testing. You must use JUnit (v5) for this purpose.
Your JUnit test suite must cover all statements and all branches (as
measured by JaCoCo) in all of the classes you must test. You
should not include tests for the Phrameworks class. Your tests must be in
a package named pa1.testing and each test class must include the word
"Test" in its name.
Though 100% coverage is necessary, you should, by now, understand that it is not sufficient.
Note that JUnit tests need not conform to the course style guide.
Submission¶
You must submit (using Gradescope):
-
Your implementation of the
Photo,PhotoReader,SequentialShowList,RatingShowList, andTagShowListcomponents (packaged appropriately). -
Your JUnit tests (packaged appropriately) for these classes.
You must submit a .zip file that contains the pa1
directory/folder at the top level. You must not submit the data
files; they will be available on Gradescope. There is no limit on the
number of submissions and no penalty for excessive submissions.
Grading¶
Your code will first be graded by Gradescope and then by the Professor. The grade you receive from Gradescope is the maximum grade that you can receive on the assignment
Gradescope Grading¶
Your code must compile and all class names and method signatures must comply with the specifications for you to receive any points on this assignment. Gradescope will then grade your submission as follows:
| Criterion | Points | Details |
|---|---|---|
| Conformance to the Style Guide: | 0 points | (Success Required) |
| Passing your Tests (SelfTests): | 10 points | (All or Nothing; Success Required) |
| Coverage of your Tests (Coverage): | 40 points | (Partial Credit Possible) |
| Correctness (OfficialTests): | 50 points | (Partial Credit Possible) |
Since you should now be pretty good at testing, Gradescope will only provide you with limited hints. In other words, your tests should uncover any defects in your code – you should not rely on the official tests to do so. In addition, since you should be using the coverage tool (JaCoCo) in VSCode, the coverage report you receive from Gradescope will be difficult to read. Specifically, it will include information about both covered and uncovered statements and branches. You should not use this report – you should use the coverage tool in VSCode since it is much easier to read.
Manual Grading¶
After the due date, the Professor may manually review your code. At this time, points may be deducted for inelegant code, inappropriate variable names, bad comments, insufficient tests, etc.
Recommended Process¶
Since nobody will be looking over your shoulder, you can use any process that you would like to use. However, it is strongly recommended that you use the process describer here.
-
Get Started
-
Read and understand the entire assignment.
-
Create a directory/folder for this assignment named
pa1. -
Add
pa1.jarto your workspace (i.e., to thelibdirectory/folder). -
Add the data files to your workspace. Specifically, download
data.zipto a directory/folder outside of VSCode (e.g., the coursedownloadsdirectory/folder). Then, unzipdata.zipand copy all of the individual files (not the.zipfile and not any directory that is created by unzipping) into theCS159directory/folder (not thesrcdirectory/folder orpa1directory/folder).
-
-
Create the Packages
- Create the
homerun,photo,showlist, andtestingdirectories/folders under thepa1directory/folder.
- Create the
-
Stub-Out All of the Classes
-
Create a stub (i.e., a version that contains all of the methods with appropriate signatures and return values) of the
PhotoandPhotoReaderclasses in thepa1.photopackage. -
Create a stub of the
SequentialShowList,RatingsShowList, andTagShowListclasses in theshowlistpackage. -
Add the "javadoc" comments to the classes and methods.
-
Check the style of the classes and make any necessary corrections.
-
Add
Phrameworks.javato thehomerundirectory/folder.
-
-
Implement and Test
-
Implement
Photo -
Test (and debug, if necessary) the
Photoclass. Remember that your tests must be in thetestingpackage and must be named appropriately. (Hint 1: The constructor of thePhotoclass declares that it throws anIOException. So, you will need to add athrowsclause to the signature of your test methods.) (Hint 2: ThegetImage()method returns a reference to aBufferedImageobject, so you won't be able to directly test that it is returning the correct reference. However, you can use thegetWidth()andgetHeight()methods in theBufferedImageclass to ensure that the image has the correct dimensions. They are all 408x230.) -
Implement
PhotoReader. -
Test (and debug, if necessary)
PhotoReader. (Hint 1: In order to get 100% coverage, you sometimes have to be aware of some quirks of the language you are working in and the tool set you are using. More information about coverage of utility classes is available on the CS wiki.) (Hint 2: Yourread()method will probably have atry-catchstatement to deal with the possibility of anIOException. The file namedPhoto02.txtrefers to an image that doesn't exist so that you can cover thecatchblock. You need not, indeed should not, worry about the situation in which the image both does not exist and has not been rated.) -
Implement
SequentialShowList. -
Test
SequentialShowList. -
Implement
TagShowList. -
Test
TagShowList. -
Implement
RatingShowList. -
Test
RatingShowList. -
Test the Complete Product
-
Run the main class with two arguments in order to test its operation using a
SequentialShowList. -
Run the main class with three arguments in order to test its operation using a
RatingShowList. Perform this system test with several different ratings. -
Run the main class with four arguments in order to test its operation using a
TagShowList. Perform this system test with several different tags and values (e.g., a"Location"of"Barcelona", a"View"of"Exterior").
-
-
Help¶
You may find the following helpful while completing this assignment.
Help with the PhotoReader Component¶
Note that, if you put the data files in the location described above,
your PhotoReader class will be able to find them in the working
directory (both on your machine and on the Gradescope server). So, you
can (indeed, must) use only the file name without a path when creating
a File object (or doing something like it). For example, you can
create a File object using new File("Photo00.txt").
Note also that there is no reason to work with directories or
directory listings. You can (and should) construct the names of the
files within a loop using the fileNameFormat() method.
Finally, before you try and write the read() method in the PhotoReader
class you may want to make sure that you can read and process a single
.txt file. You may even want to write a simple main class (that won't
become part of your final submission) that does this to make sure you
understand all of the issues that arise before doing anything else.
Help with the SequentialShowList Component¶
Be careful to avoid an infinite loop when writing the getNext() method
in SequentialShowList. You will need to loop until you find
an element that should be shown, but you need to ensure that there is
such an element (using the getSize() method) before you enter the
loop.
Help Using Command Line Arguments in VSCode¶
As you (should know), the main() method in the main class is passed an array
of String objects called command-line arguments. The main class
Phrameworks.java uses these command-line arguments to control the operation
of the application (see the comments in that class for details).
The easiest way to provide command-line arguments in VSCode is to:
- Click on the "TERMINAL" tab at the bottom of the window to make it active.
- Run the
Phrameworksmain class the usual way. - The command that was used to run the program is displayed in the terminal. Click and drag to select that command and then copy it.
- Paste that command into the console, type a space, add any command-line arguments (delimited by spaces), and press [Enter].
Note, also, that the arrow keys will bring up a history of commands which makes it easier to repeat them.
Relevant Programming Patterns¶
An understanding of the following programming patterns will help you complete this assignment:
Questions to Think About¶
You don't have to submit your answers to these questions, but you should try to answer them because they will help you determine whether or not you understand some of the important concepts covered in this assignment.
-
At some point, a
PhotoReadermust determine if the second field in the record it reads is a valid integer or not. Why is it a good idea to use exception handling for this purpose? -
Should the
getSize()method inSequentialShowListperform the necessary calculations each time it is called, or should it just return an attribute that is initialized in the constructor? What are the advantages and disadvantages of both approaches? -
The
getNext()method inSequentialShowListthrows aNoSuchElementExceptionwhen the list is "empty". It could, instead, returnnull. What are the advantages and disadvantages of both approaches? -
Why was a tab character used as the delimiter in
Photofiles rather than the space character? -
Why were the tag-value pairs delimited using a different character (in this case, a colon)?
-
In the
main()method ofPhrameworks, the local variable namedlistis declared to be aSequentialShowListbut is instantiated as either aRatingShowList, aTagShowList, or aSequentialShowList. Why do the assignment statements compile? -
Why is it better to declare
listin the most general way possible (i.e., as aSequentialShowList)?
Looking Back - The Big Picture¶
By the time you complete this assignment you should have learned many things, including but not limited to the following “big picture” issues.
-
When you first encounter exceptions, they usually arise only when your code contains defects. You should now realize that exceptions are just an alternative return mechanism and that they can and should be used productively in a wide variety of circumstances.
-
Every time you design a class that has class-type attributes, you must decide whether to use aliases or deep copies (and how deep those copies should be). Sometimes it is better to use aliases and sometimes it is better to use deep copies. Each situation is different and requires careful thought.