Skip to main content

CSE 331 Homework Library

Due Wednesday, Aug 19 at 11:59pm.

In this homework, you'll extend your inventory ADT from previous assignments into a generic borrowing library. You'll use this as the backend for a library management app with a JavaScript frontend.

Getting started

Get the starter code via gitlab as before (download directory as zip, then unpack it).

Most of the files are similar to HWInventory++. The differences are:

  • library/: a new package replacing inventory/. The interface (Library.java) is an enhanced, generic version of the Inventory interface from previous homeworks. It is parameterized by a type T that extends LibraryItem (see LibraryItems.java).
  • libraryManagement/LibraryManagementApp.java: a new starter file for your web app. Unlike the Inventory web app, it serves a JSON API rather than rendering HTML pages.
  • static/: a new directory containing the HTML, JavaScript, and CSS files that the browser loads. Replaces the HWInventory++ templates/ directory. (There are no JTE templates in this assignment).

After unpacking the hwLibrary starter code, you should copy the contents of your InventoryImpl.java into LibraryImpl.java. Be careful when copying, because hwLibrary uses a different package name. The starter code has the correct package declaration (package library;), so be careful not to overwrite it when pasting in your code. Then rename your class to LibraryImpl to agree with the new filename.

Your copied code will not compile immediately because the interface has been renamed and generic-ified. You will need to make the changes described in Task 1 below.

If you are using VS Code, be sure to open the hwLibrary folder as the "root" folder in your editor, or else it will not be able to find the dependencies in lib/.

Task 1: Implement Library

A Library<T> stores items of some type T. The starter code provides several library item types in LibraryItems.java, including Book, BoardGame, Laptop, and Tool. For example, a Library<Book> stores books, while a Library<Laptop> stores laptops.

Library transactions

Like Inventory, Library maintains an append-only transaction history. However, library transactions can now have three different types:

  • ADD records newly owned copies of an item. Both the number of copies the library owns and the item's available quantity increase.
  • BORROW records copies borrowed by a particular username. The item's available quantity decreases, but the number of copies owned does not change.
  • RETURN records copies returned by a particular username. The item's available quantity increases, but the number of copies owned does not change.

At every point in the history, the available quantity of an item must be between 0 and the total number of copies added so far, inclusive. A user also cannot return more copies of an item than that user currently has borrowed.

Read the specifications for all methods in Library.java carefully before implementing them.

The interface includes operations for modifying the library, looking up item quantities, querying the items borrowed by a user, and inspecting transaction history.

Also pay close attention to the runtime requirements stated in Library.java. Depending on the representation you used for InventoryImpl, you may need to redesign your representation rather than scanning the complete transaction history for every operation.

When you change your code, be sure to update your abstraction function (AF) and representation invariant (RI) comments, and update your checkRep() method to check the new invariants.

Task 2: Test your library

As in the Inventory homework, your tests are split across two files:

  • LibrarySpecTest.java contains specification-based tests that rely only on behavior guaranteed by the Library specification.
  • LibraryImplTest.java contains any additional implementation-based tests that rely on choices specific to your implementation or behavior left unspecified by the interface.

Copy and adapt your specification tests from InventorySpecTest.java into LibrarySpecTest.java, then add tests for the new functionality introduced by Library. If you changed your representation or method implementations in Task 1, make sure your tests thoroughly exercise the updated behavior.

Because Library is generic, your specification tests should exercise the library with at least two different types of LibraryItem provided in LibraryItems.java (e.g., Book and Laptop). This helps verify that your implementation works generically rather than depending on a particular item type.

As in previous homeworks, only your specification tests in LibrarySpecTest.java will be graded. We will run them against your implementation, the staff implementation, and possibly deliberately buggy implementations. Your specification tests must pass on any correct implementation while still being thorough enough to detect incorrect ones.

LibraryImplTest.java will not be graded and may be left blank if you wish.

Task 3: Library Management App

In this task, you will build a browser-based frontend for your library management application. We have provided substantial starter code, and part of your task is to understand the code well enough that you can extend it as described below. The Java backend is in libraryManagement/LibraryManagementApp.java. It uses your Library implementation from Task 1 to store the library's items and keep track of which items each user has borrowed.

The frontend is contained in static/index.html, static/index.js, and static/index.css. The starter code frontend implements part of the required functionality for you: logging in, browsing the catalog, and logging out. It will be your job to finish the rest.

Architecture

In HWInventory++, the server generated complete HTML pages using JTE templates. Every user action submitted an HTML form, the server processed it and rendered a new page, and the browser loaded that new page.

In this assignment, the architecture is different:

  • The backend (still Java/Javalin, but no JTE) exposes a set of JSON API routes. Each route receives a request, processes it using your Library implementation, and returns a JSON response rather than an HTML page.
  • The frontend is written as a separate HTML file and JavaScript file (and an optional CSS file for styling). The JavaScript sends requests to the backend using fetch, receives JSON responses, and dynamically updates the page.
  • The HTML page itself is loaded once. Moving between different views of the application should be handled by JavaScript rather than by asking the server to render a new page.

The backend exposes five API routes. The first four are written for you. One of your tasks is to implement the /api/add route.

  • GET /api/items returns all items in the library. For each item it reports available, the number of copies currently on the shelf, and owned, the total number of copies the library has. Note that these two quantities may differ because some copies are checked out.
  • GET /api/rentals?name=... returns the items currently borrowed by the given user.
  • POST /api/checkout attempts to check out one or more selected items for a user.
  • POST /api/return attempts to return one or more borrowed items for a user.
  • POST /api/add records new copies the library now owns, increasing owned and available together. It is also possible to add copies of items that were not previously owned by the library.

All three POST routes expect the same JSON request body: a username and a map from item names to quantities. For example:

{
  "name": "alice",
  "items": {
    "Kung Fu Panda": 1,
    "Chainsaw": 2
  }
}

You should study LibraryManagementApp.java, index.html, and index.js together to understand how the frontend and backend fit together.

Required functionality

Your library management app must allow a user to:

  • Log in by entering a username.
  • Browse all items in the library and see the currently available quantity of each item.
  • Select a quantity of one or more available items and proceed to checkout.
  • Review the selected items before completing the checkout.
  • Check out the selected items.
  • View My Rentals, which displays the items currently borrowed by the logged-in user and the quantity of each item they have borrowed.
  • Select a quantity of one or more borrowed items and return them.
  • Open a Librarian view listing every item and how many copies the library owns.
  • Add copies of one or more existing items from the Librarian view, and add an item the library does not own yet by entering a name and a quantity.
  • Navigate between the Browse, My Rentals, and Librarian views while logged in.
  • Log out and return to the login view.
  • Display useful feedback when an operation succeeds or cannot be completed.

Your application does not need to match the exact style or wording of the staff solution, but all of the functionality described above must be present.

Working with the frontend

The provided starter code demonstrates many of the JS web development techniques you will need to use. See the guide on Web Development with JavaScript for more information about how to build this style of web application.

Your application should handle inputs and API errors reasonably. An invalid operation should not cause the frontend to stop working. Instead, display a useful message to the user when an operation cannot be completed.

Note that the backend applies each item in a request on its own, so a checkout or a return can partly succeed. In that case, the items that succeeded and failed are recorded and returned to the caller. Failed items also come with a message. Your app should make clear which items went through and which did not.

A checkout of 2 Chainsaws and 3 copies of Kung Fu Panda, of which only one copy exists. The Chainsaws are checked out and the rest is reported back, so the user can see exactly what happened.

Example scenario

The following scenario demonstrates the required functionality. Your application does not need to look exactly like the staff solution, but it should support the same logical behavior.

Logging in and browsing the library

A user begins on the login page and enters their username. After logging in, they are taken to the Browse view, which displays the items in the library and the number of copies currently available.

Library login page with Kyle entered as the user’s name.
The Browse view after logging in as Kyle, showing each item’s available count and a quantity field.

Checking out an item

The user selects the quantity of one or more items they would like to borrow and proceeds to checkout.

Quantities entered for Chainsaw, Kung Fu Panda, and Types and Programming Languages, ready to proceed to checkout.

The checkout page displays the items and quantities the user selected, so they can review them.

The checkout view summarising the selected items before the user confirms.

After the user completes the checkout, the library records the borrowed items and the Browse view updates to show the new available quantities.

After a successful checkout: a confirmation message, updated availability counts, and the quantity fields reset.

Viewing rentals

The user can select My Rentals to see each item they currently have borrowed and the outstanding quantity of that item.

My Rentals, showing each item Kyle currently has borrowed and how many copies of it.

Returning an item

From My Rentals, the user selects how many copies of an item they would like to return. After the return succeeds, the rentals view updates to show the user's remaining borrowed items.

If the user returns all copies they had borrowed, that item no longer appears in My Rentals.

A quantity of 1 entered for Kung Fu Panda, ready to be returned.
After returning the only borrowed copy of Kung Fu Panda, it drops out of My Rentals entirely.

Adding items as a librarian

The Librarian view lists the current items owned by the library, together with their quantities.

The Librarian view, listing how many copies of each item the library owns.

The librarian can add copies of items already in the catalog, or add an item the library has never owned by typing its name and a quantity, or do both at once.

After adding 5 more copies of Kung Fu Panda and 3 copies of a Soldering Iron, which the library did not own at all before.

Logging out

The user can select Log out at any time while logged in. Logging out returns the application to the login view.

Submission

Submit the following files to the Homework Library assignment on Gradescope:

  • LibraryImpl.java
  • LibrarySpecTest.java
  • LibraryImplTest.java
  • LibraryManagementApp.java
  • index.html
  • index.js
  • index.css

You can either upload these files individually on Gradescope, or run make submission to bundle them into a submission.zip and upload that.

You should not modify or submit Library.java, LibraryItem.java, or LibraryItems.java.

We have set up a Gradescope autograder that will compile and run your code. It will run your tests on your own code and show you the results. Passing all the autograder tests does not guarantee your code is correct or high quality.