Capers Design Document
Classes and Data Structures
This is the entry point to our program. It takes in arguments from the command line and based on the command (the first element of the
args array) calls the corresponding command in
CapersRepository which will actually execute the logic of the command. It also validates the arguments based on the command to ensure that enough arguments were passed in.
This class has no fields and hence no associated state: it simply validates arguments and defers the execution to the
This is where the main logic of our program will live. This file will handle all of the actual capers commands by reading/writing from/to the correct file, setting up persistence, and additional error checking.
It will also be responsible for setting up all persistence within capers. This includes creating the
.capers folder as well as the folder and file where we store all
Dog objects and the current story.
This class defers all
Dog specific logic to the
Dog class: for example, instead of having the
CapersRepository class handle
Dog serialization and deserialization, we have the
Dog class contain the logic for that.
static final File CWD = new File(System.getProperty("user.dir"))The Current Working Directory. Since it has the package-private access modifier (i.e. no access modifier), other classes in the package may use this field. It is useful for the other
Fileobjects we need to use.
static final File CAPERS_FOLDER = Utils.join(CWD, ".capers")The hidden
.capersdirectory. This is where all of the state of the
CapersRepositorywill be stored, including additional things like the
Dogobjects and the current story. It is also package private as other classes will use it to store their state.
These fields are both
static since we don’t actually instantiate a
CapersRepository object: we simply use it to house functions. If we had additional non-static state (like the
Dog class), we’d need to serialize it and save it to a file.
This class represents a
Dog that will be stored in a file. Because each
Dog will have a unique name, we may simply use that as the name of the file that the object is serialized to.
Dog objects are serialized within the
DOG_FOLDER which is within the
Dog class has helpful methods that will return the
Dog object corresponding to some
String name given to it, as well as write that
Dog to a file to persist its changes.
static final File DOG_FOLDER = Utils.join(CapersRepository.CAPERS_FOLDER, "dogs")The
Fileobject that corresponds to the directory containing all the serialized
Dogobjects. This is
Dogobjects are stored within the same directory. When
private int ageThe age of this
private String breedThe breed of this
private String nameThe name of this
Dog. These names are unique and thus no two
Dogobjects can possibly have the same name (not enforced by capers, but a guarantee from the spec).
This class contains helpful utility methods to read/write objects or
String contents from/to files, as well as reporting errors when they occur.
This is a staff-provided and PNH written class, so we leave the actual implementation as magic and simply read the helpful javadoc comments above each method to give us an idea of whether or not it’ll be useful for us.
private fields to aid in the magic.
There aren’t any algorithms in this lab as we were just dipping our toes into serialization/persistence.
The directory structure looks like this:
CWD <==== Whatever the current working directory is. └── .capers <==== All persistant data is stored within here ├── story <==== Where the story is stored (a file) └── dogs <==== All dogs are stored in this directory ├── Dog1 <==== A single Dog instance stored to a file ├── Dog2 ├── ... └── DogN
CapersRepository will set up all persistence. It will:
- Create the
.capersfolder if it doesn’t already exist
- Create the
dogsfolder if it doesn’t arleady exist
story [text] command is used we will do one of two things:
- If the
.capers/storyfile doesn’t exist, we will create it and write the
textto the newly created file followed by a
\ncharacter after printinting it.
- If the
.capers/storyfile does exist, we’ll read the previous story using the
Utils.readContentsAsStringfunction, add the
text, add a
\ncharacter, and write this new story back to the
.capers/storyfile after printing it.
Dog class will handle the serialization of
Dog objects. It has two methods that are useful for this:
public static Dog fromFile(String name)- Given the name of a
Dogobject, it retrieves the serialized data from the
.capers.dogs) and uses the
Utils.readObjectmethod to convert it to an instance of
public void saveDog()- Serializes this
Dogobject to the
DOG_FOLDERin a file whose name is the same as the name of the
Dogobject (since we’re guaranteed the names are unique, there is no collision with any other
Dogobject). If this
Dogalready existed, this will also overwrite the old (now out-of-date) serialized data.