Core library domain model for a simple library system: Books, Shelves, and Readers — with operations for inventory, checkout/returns, and listing. JUnit 5 tests codify expected behavior. Error handling is centralized in an enum (Utilities.Code
) with explicit numeric codes and human-readable messages.
For sample I/O traces and additional information, visit the project page: https://www.rsiddiq.com/software-design.html
- Project Name:
LibraTrack
- Modules: single-module Gradle project (root)
- Gradle: wrapper 8.5 (
gradle/wrapper/gradle-wrapper.properties
) - Java Toolchain: not pinned in Gradle (use a modern JDK; 17+ recommended)
- Testing: JUnit Jupiter 5.10.0 (
useJUnitPlatform()
) - Entry Point: none (library / domain model); call APIs from your own
main
or tests - Key Package(s): default package;
Utilities
(forCode
enum) - Example Data: badBooks0.csv, badBooks1.csv, badReader0.csv, badReader1.csv, badShelves0.csv, badShelves1.csv
LibraTrack/
├── gradle/
│ └── wrapper/
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── src/
│ ├── main/
│ │ └── java/
│ │ ├── Utilities/
│ │ │ └── Code.java
│ │ ├── Book.java
│ │ ├── Library.java
│ │ ├── Reader.java
│ │ └── Shelf.java
│ └── test/
│ └── java/
│ ├── BookTest.java
│ ├── LibraryTest.java
│ ├── ReaderTest.java
│ └── ShelfTest.java
├── .gitignore
├── badBooks0.csv
├── badBooks1.csv
├── badReader0.csv
├── badReader1.csv
├── badShelves0.csv
├── badShelves1.csv
├── build.gradle
├── gradlew
├── gradlew.bat
├── Library00.csv
├── Library01.csv
├── Library02.csv
├── README.md
└── settings.gradle
./gradlew clean build
./gradlew test
The project does not configure a
mainClass
or theapplication
plugin. To run a demo program, add your ownMain
class that uses the API (see Usage).
- Domain entities:
Book
,Reader
,Shelf
- Library orchestration:
Library
manages collections, shelves, and readers - Checkouts/Returns: move a
Book
between shelf and reader lists, enforce limits & existence - Listings: pretty printers for books on a shelf, all readers, all shelves
- CSV-friendly: constants in
Reader
suggest a stable CSV layout for bulk initialization - Deterministic error model:
Utilities.Code
enum returns structured codes/messages
Represents a single title (ISBN, title, subject, page count, author, optional dueDate
). Implements equality/hash on identity and provides a human-readable toString()
.
Key API: getISBN
, getTitle
, getAuthor
, getSubject
, getPageCount
, getDueDate
, set*
, toString
Represents a patron with cardNumber
, name
, phone
, and a list of checked-out Book
s. Includes index constants for CSV parsing: CARD_NUMBER_
, NAME_
, PHONE_
, BOOK_COUNT_
, BOOK_START_
.
Key API: addBook(Book)
, removeBook(Book)
, getBookCount(Book)
, getBooks()
, getCardNumber()
, getName()
, getPhone()
, set*
, toString()
Holds books for a single subject
at a numbered shelfNumber
. Maintains counts per Book
and supports inventory operations.
Key API: addBook(Book)
, removeBook(Book)
, getBookCount(Book)
, listBooks()
, getSubject()
, getShelfNumber()
, set*
listBooks()
format (example):0 books on shelf: 1 : sci-fi
When one book is present:1 book on shelf: 1 : sci-fi
followed by<Book.toString()> 1
per line.
Coordinates the whole system: initialization, lookups, list formatting, and state transitions.
Notable methods: addBook
, addShelf
, addReader
, removeReader
, checkOutBook
, returnBook
, listBooks
, listShelves
, listReaders
, getBookByISBN
, getReaderByCard
, getShelf
, convertInt
, convertDate
, errorCode
, init
Centralized error signaling with integer codes and messages. Useful for programmatic checks and UX surfaced errors.
Code | Value | Meaning |
---|---|---|
SUCCESS |
0 |
Transaction was a success |
FILE_NOT_FOUND_ERROR |
-1 |
Could not the file |
LIBRARY_ERROR |
-3 |
problem with the library |
READER_COUNT_ERROR |
-4 |
Reader Count Error |
SHELF_COUNT_ERROR |
-6 |
Shelf count error |
PAGE_COUNT_ERROR |
-8 |
Page count error |
DATE_CONVERSION_ERROR |
-101 |
Date conversion Error |
BOOK_ALREADY_CHECKED_OUT_ERROR |
-21 |
Book already checked out error |
BOOK_LIMIT_REACHED_ERROR |
-22 |
Book limit reached |
BOOK_NOT_IN_INVENTORY_ERROR |
-23 |
book not in stacks or library |
READER_NOT_IN_LIBRARY_ERROR |
-44 |
Reader Does not exists in library |
READER_STILL_HAS_BOOKS_ERROR |
-48 |
Must return all books. |
Full list in
src/main/java/Utilities/Code.java
.
Below is a minimal example showing how you might wire the library in a Main
class:
// Main.java (example)
public class Main {{
public static void main(String[] args) {{
Library lib = new Library();
lib.init(); // if available; else add shelves, readers, and books manually
Shelf s = new Shelf();
s.setShelfNumber(1);
s.setSubject("sci-fi");
lib.addShelf(s);
Book dune = new Book();
dune.setISBN("34-w-34");
dune.setTitle("Dune");
dune.setAuthor("Frank Herbert");
dune.setSubject("sci-fi");
dune.setPageCount(412);
lib.addBook(dune);
Reader r = new Reader(1001, "Ada Lovelace", "555-0100");
lib.addReader(r);
// Checkout + list
lib.checkOutBook("34-w-34", 1001, Library.convertDate("2025-10-01"));
System.out.println(lib.listReaders());
System.out.println(s.listBooks());
}}
}}
Compile & run (if you add Main.java
and a matching main
method):
./gradlew build
java -cp build/classes/java/main Main
Sample/validation CSVs are present at repo root:
- Books (e.g.,
badBooks0.csv
,badBooks1.csv
) — malformed or edge-case rows for negative testing - Readers (e.g.,
badReader0.csv
,badReader1.csv
) — checks card/phone parsing and counts - Shelves (e.g.,
badShelves0.csv
,badShelves1.csv
) — checks number/subject alignment
Implied schemas (based on parsing constants & method usage):
- Reader:
cardNumber,name,phone,bookCount,(isbn1,dueDate1, isbn2,dueDate2, ...)
- Book:
isbn,title,subject,pageCount,author
- Shelf:
shelfNumber,subject[, ...]
Refer to Library.convertInt/convertDate
and error codes for validation rules.
- JUnit 5 tests under
src/test/java
:BookTest
,ReaderTest
,ShelfTest
,LibraryTest
- Run:
./gradlew test