Assignment 1: Java refresher and representation
1 Purpose
2 Getting started
3 Representing simple file systems
4 Creating examples to guide implementations
5 Correct the bugs
6 Adding a method
7 Adding a class
8 Pretty printing
9 Grading standards
9.1 The style guide
10 Submission
10.1 Deliverables
10.2 Instructions
8.9

Assignment 1: Java refresher and representation

Due dates:

Starter files: code.zip

1 Purpose

The primary goal of this assignment is to get you writing Java (again or for the first time). A secondary goal is to understand that data representations should make behaviors easier to implement. As a tertiary goal, completing this assignment will help you ensure that you have a properly configured and working Java development environment and IDE, and that you can use the submission system.

2 Getting started

Before you start this assignment, please ensure that you have all the necessary tools to complete an assignment. They include:

Please review the directions on the course page if you need help setting up any of this, or talk to the course staff.

3 Representing simple file systems

In this assignment, we’ll think about file systems and some possible data representations for them. For now, we will make the system read-only (i.e. cannot add or change files once the file system is created) and we will be using the Mac style file separator (i.e., we use the / as a file separator), and expect only three behaviors:

The starter code contains three classes that are all parts of the file system:

The Javadoc in those classes should explain what they are intended to represent.

4 Creating examples to guide implementations

A key task in understanding the meaning of a data definition is creating sufficient examples to illustrate its intended behavior in a representative variety of settings. In this assignment, you have been given starter code that contains mostly working implementations. There are several bugs that have been deliberately left in the starter code.

Your initial task is to write a collection of test methods in an ExampleFileSystem class (in the default package, not in the same package as the FileSystem starter code) that demonstrate how these classes are supposed to work. These tests will function as examples of file systems. This means that when you write your examples and run them on the starter code, they should not yet all pass.

Hints for this assignment:

5 Correct the bugs

Repair the starter code we give you and correct the bugs in it. You should now be able to run your examples against your own code, and they should all pass. You should also pass the first Java autograder on the Handins assignment as well.

6 Adding a method

We will expand the power of our file system by dding a new method to ReadOnlyFileSystem and ExtDirectory,

String path(ExtFile file);

Do not modify the interfaces given beyond adding these methods for this task.

The intent of this method is to find the location of a file.

When called on the filesystem, the method returns an absolute path. An absolute path is a path from the root directory of the file system down to the actual file itself.

When called on a directory, the method returns a path starting from that directory.

As an example, consider the following file system

+-root/
| +-data/
| | +-experiment/
| | | +-filesystem/
| | | | +-data.log
| | | +-exp-name.log
| +-lib/
| | +-cool-thing.txt

The result of calling path on the filesystem with the file object for data.log will be "root/data/experiment/filesystem/data.log". Similarly, the result of calling path with the file object for lib will be "root/lib". Notice the lack of "/" at the end of the lib directory. Both are absolute paths as they start from the root directory.

The result of calling path on the directory data with the file object for data.log will be "data/experiment/filesystem/data.log". The result of calling path on the same directory with the file object for data will be data.

Finally, if there happen to be two or more of the same file object in the file system, the first one found alphabetically is the one you want. Consider the following file system

+-root/
| +-data/
| | +-experiment/
| | | +-data.log
| +-lib/
| | +-data.log

Say both data.log files are represented by the exact same object. If we call path on the file system, then we should get the path "root/data/experiment/data.log".

In all cases, if you call path onwith a file object that has the same name and contents of another file (directory or content file) in the system, but the object itself is not in the system, path should throw an IllegalArgumentException. In other words, path only works with objects already in the file system.

Your method may need to throw exceptions: if so, they must be documented in your Javadoc for the method.

Hint: You will want to refresh yourselves on try-catch blocks and exception for throwing and catching exceptions.

You may choose to change the implementation of the classes in starter code given to you, if you think the existing representation is inconvenient for implementing this method. If you do so, leave a comment within the Javadoc of the class, as follows:

/**
 * ... existing Javadoc ...
 * @implNote ...explain what you changed about the representation, and why...
 */

Write a JUnit 4 test class, FileSystemTests, that include the new tests you add for this method — keep your existing examples in the existing ExampleFileSystem class.

7 Adding a class

In lecture, we discussed designing an interface for a data definition to allow us to add new implementations of that interface that made different design tradeoffs. You will repeat this process here for a different data definition.

As we did in class, you will create a new class CompressedFile (in package cs3500.hw1.filesystem) that implements the ContentFile interface. A compressed file consists of the name of the file and a list of files that will be contained within. It must define a public constructor with two arguments as described above.

The size and total size of the file are the same: it is the total size of all files given to create the CompressedFile reduced by a factor of 8 (i.e. divided by 8). If you are left with a decimal value, we always drop the decimal (e.g. 5.9 becomes 5). (Hint: What is the behavior of division with integers in Java? Longs have the same behavior.)

Of note, you are not actually compressing any files here but simulating the existence of one. Compression algorithms are beyond the scope of the assignment.

The contents of a compressed file are the names of every file given to you to create the CompressedFile. To clarify, if one of the files is a directory, you only give the name of the directory.

This has more to do with the limitations of the design. See the instructor if you want to dive further into this limitation. The definition of contents in this assignment gets around that cheaply.

In the FileSystemTests class, include new tests you add for this class to ensure the above behavior works as intended. Note that the path method must also work for these kind of files.

8 Pretty printing

Finally, you will add one last method to the ReadOnlyFileSystem and ExtFile

String prettyPrint();

Do not modify the interfaces given beyond adding the methods mentioned for this task.

This method will produce an easy to understand visual of the file system in a string for debugging purposes. An example of a pretty printed filesystem appears below.

+-root/
| +-data/
| | +-experiment/
| | | +-compressed.zip
| | | +-exp-name.log
| | | +-filesystem/
| | | | +-data.log
| +-lib/
| | +-cool-thing.txt

Hint: You may find the methods split and join helpful in the String class You may also find the methods in the List interface helpful as well.

Again, you may choose to change the implementation of the classes in the starter code given to you, if you think the existing representation is inconvenient for implementing this method. If you do so, leave a comment within the Javadoc of the class, as follows:

/**
 * ... existing Javadoc ...
 * @implNote ...explain what you changed about the representation, and why...
 */

Finally, in the FileSystemTests class, include new tests you add for this method.

9 Grading standards

For this assignment, you will be graded on

9.1 The style guide

Coding style is important. For this class we follow Google’s Java style guide. It’s comprehensive but not very long, so I suggest reading the whole thing and then referring to it as needed.

While it can’t yet take on full responsibility for formatting code—much less for programming style more broadly—your IDE may be able to help you follow the code formatting portion of the style guide:

10 Submission

Ready to submit? Look at the Design Principles Master List first! (Not all items there may apply to this assignment)

10.1 Deliverables

10.2 Instructions

You will submit the assignment on the Handins server. Follow these instructions:

  1. Log in to the server using the link above, using your Khoury account (not your Northeastern account). Follow directions on the course page if you do not have a Khoury account or have forgotten your password.

  2. You must be registered as a student to CS 3500 for Fall 2023 on the handin server. Follow directions on the course page if you have not applied for registration.

  3. Submit the zip file you made above to the relevant assignment (“Hw 1”) on the submission server. Note that for the autograded portions, it may take some time to see feedback. This time increases as we get closer to the deadline, because many more students tend to submit. Please be patient!

  4. You have two submissions for this assignment: the implementation submission, and the self-eval. Make sure to submit to each of them by their respective deadlines.