Apologetics Catalog (MIDTERM)
Apologetic question: "How do we organize the knowledge of the church?"
Project 8 — MIDTERM: Apologetics Catalog
“…always being prepared to make a defense to anyone who asks you for a reason for the hope that is in you; yet do it with gentleness and respect.” — 1 Peter 3:15
Chapter: 8 — Collections, Generics, and Midterm Review
When: In class, 60 minutes (your instructor may adjust to 75)
Submit: A link to your code — an OnlineGDB project URL or a public GitHub repo URL — with Catalog.java and supporting files. See Coding 1’s online-coding workflow appendix for the full workflow. (No installs, no admin rights — everything runs in the browser.)
Allowed during the exam:
- The textbook (printed or non-interactive PDF — no clickable links, no AI chat).
- Your own past project files, if you brought a printout or a USB drive copy.
- The compiler, JUnit, and your editor’s non-AI features.
NOT allowed:
- The internet.
- ChatGPT, Claude, Copilot, Cursor, JetBrains AI Assistant, any AI of any kind.
- Anyone else’s code.
- Communication with another person during the exam window.
The Setup
A small Christian college library has digitized its apologetics collection. The librarian — practical, harried, doesn’t want a fancy database — has handed you a CSV file with every resource: title, author, year, and tradition (Lutheran, Reformed, Roman, Anglican, or Evangelical). She wants a small Java program that loads the CSV, lets her look up resources by author or tradition, list all unique authors alphabetically, and save changes back to the file when she adds or removes a resource. Robust to malformed lines. Built tonight. Used tomorrow.
That’s the midterm. The catalog you build is small. The point is that you can build it under exam conditions, drawing on seven chapters of Phase 1 skills, in 60 minutes.
The thematic frame (apologetics) doesn’t change the technical content. If “apologetics resources” isn’t your idiom, mentally substitute “ministry resources,” “Sunday school materials,” or “your church’s small library.” The code is the same. The records are the same.
What You’re Building (Normal Tier)
A complete program that:
-
Defines a
Resourcerecord with these fields:String titleString authorint yearString tradition(one of:"Lutheran","Reformed","Roman","Anglican","Evangelical")
The record must validate at construction: title non-blank, author non-blank, year ≥ 0, tradition one of the five allowed values. Throw
IllegalArgumentExceptionwith a descriptive message on any violation. -
Defines a
Catalogclass that:- Loads from a CSV file at construction time (
new Catalog(Path csv)). - Stores resources in appropriate
java.utilcollections — at minimum aList<Resource>for the master list, aMap<String, List<Resource>>keyed by author for fast lookup, and aMap<String, List<Resource>>keyed by tradition. - Skips and reports any malformed line (don’t crash on bad input; log to stderr and continue).
- Exposes:
List<Resource> findByAuthor(String author)— empty list if none.List<Resource> findByTradition(String tradition)— empty list if none.Set<String> uniqueAuthors()— returned sorted alphabetically (useTreeSet).int size().void add(Resource r)— adds to all indices.void saveCsv(Path csv)— writes the current catalog back to the file atomically (write-then-rename, per Chapter 6).
- Persists on shutdown —
mainregisters a shutdown hook or simply callssaveCsvbefore exiting.
- Loads from a CSV file at construction time (
-
A
mainmethod that:- Loads a hardcoded CSV path (
data/apologetics.csv— the provided input file; downloadapologetics.csvand drop it into your project’sdata/folder). - Prints the count loaded.
- Demos at least one query — e.g., prints all Lutheran resources, then prints
uniqueAuthors(). - Adds one new
Resourceprogrammatically. - Calls
saveCsvto persist.
- Loads a hardcoded CSV path (
-
Compiles cleanly with no warnings.
-
Robust to malformed input — at least these cases handled without crashing:
- Empty fields → line is skipped with a stderr message naming the line number.
- Non-numeric
year→ line is skipped with a useful message. - Unknown
tradition→ line is skipped with a useful message. - Missing field count (≠ 4 fields) → line is skipped with a useful message.
CSV format
title,author,year,tradition
"Mere Christianity","C. S. Lewis",1952,Anglican
"Orthodoxy","G. K. Chesterton",1908,Roman
"The Bondage of the Will","Martin Luther",1525,Lutheran
"Institutes of the Christian Religion","John Calvin",1559,Reformed
"Knowing God","J. I. Packer",1973,Reformed
The first row is a header. Skip it. Quoted fields may contain commas (use the careful CSV parsing from Chapter 6).
Example demo output
Loaded 24 resources.
Lutheran resources:
The Bondage of the Will — Martin Luther (1525)
The Freedom of a Christian — Martin Luther (1520)
...
Unique authors (sorted):
Augustine of Hippo
C. S. Lewis
G. K. Chesterton
John Calvin
...
Added: "Surprised by Joy" — C. S. Lewis (1955) [Anglican]
Saved 25 resources.
Normal-tier rubric (out of 100)
| Criterion | Points |
|---|---|
| Compiles cleanly | 4 |
Resource record correctly defined with all four fields | 6 |
Resource validates each field in compact constructor with useful messages | 10 |
| Catalog loads from CSV with careful parsing (quoted fields handled) | 10 |
Catalog uses appropriate collections (Map<String, List<Resource>> for indices, TreeSet for sorted authors, etc.) | 10 |
findByAuthor and findByTradition return correct results | 10 |
uniqueAuthors returns sorted set | 6 |
add updates all indices consistently | 6 |
saveCsv writes catalog back to file, including quoting any field containing a comma | 10 |
saveCsv uses the atomic write pattern (temp + rename) | 8 |
| Malformed lines reported (line number + reason) and skipped — program continues | 8 |
main demos at least one query and one add+save | 6 |
Reflection comment block at top of Catalog.java (tier, AI honesty) | 6 |
Medium Tier (+up to 25% extra credit)
M1. JUnit tests
Write at least 6 JUnit tests covering:
- Loading a known-good CSV produces the expected count and contents.
findByAuthorandfindByTraditionreturn the right resources.uniqueAuthorsis sorted.addadds to all indices correctly.- Round-trip:
load → add → save → load againyields the expected resources. - A test that uses a malformed CSV and asserts the malformed lines are skipped (not crashed on).
M2. Remove operation
Add boolean remove(Resource r) to Catalog that returns true if the resource was removed (and updates all indices), false if it wasn’t present. Add tests for both branches.
Hard Tier (+up to 25% additional extra credit)
H1. CLI with subcommands
Add a small command-line interface that exercises every feature. Examples:
java Catalog list
java Catalog list --tradition Lutheran
java Catalog authors
java Catalog add "Surprised by Joy" "C. S. Lewis" 1955 Anglican
java Catalog remove "Mere Christianity"
java Catalog save
Document the CLI in your README.txt.
H2. --export-json flag with round-trip
Add java Catalog export --format json --out catalog.json that produces a well-formed JSON array of resources (using the JSON-writing discipline from Chapter 6).
Then add java Catalog import --format json --in catalog.json that reads it back. Assert via test:
csv → catalog → json → catalog → csvround-trips to byte-identical (modulo documented normalizations).
Submission
Submit one URL via the course portal:
- OnlineGDB project link (recommended).
- GitHub repo link (optional).
What the linked project must contain
Catalog.java(and supporting source files:Resource.javaif you split it out,SimpleCsv.java, etc.).data/apologetics.csv— the provided input file, unchanged. (downloadapologetics.csv)data/apologetics.bad.csv— for the malformed-input demo (optional but helpful).- Test class (Medium and Hard tiers).
- Reflection comment block at the top of
Catalog.java:
/*
* Tier targeted: Normal / Medium / Hard
* Features done: (list each tier feature you completed)
* Time spent: (approximately, in minutes)
* What I learned: (one short paragraph, no bullets)
* What I'd change: (one sentence)
* AI usage: NONE — this is the midterm. Signed: <your name>
*/
- The program left in a “demonstrable” state — when the grader presses Run, your
mainexercises the features for your targeted tier. Hard-code the CSV path or pre-fill OnlineGDB’s Stdin panel so the grader doesn’t have to guess.
That’s it. No separate demo.txt. No screenshots. The instructor opens your link, reads the comment block, runs the program, and grades against the rubric.
Coach’s Note — Coding 1 and Coding 2 focus on writing code, not managing development environments. If something behaves oddly, you and the grader are looking at the exact same browser-hosted environment — there are no “works on my machine” defenses by design. Coding 3 will introduce a local toolchain properly.
Hints (Read These Before the Exam, Not During)
-
Start with the record. Get
Resourceon the page, with validation, before you touchCatalog. Compile it. Run a tinymainthat constructs one valid and one invalid Resource. You now have a confirmed foundation. -
Then the load. Write
Catalog(Path csv)that just parses and counts — don’t build the indices yet. Get the file open, parse the lines, construct Resources, count. Print the count frommain. Compile, run. Now you have data flowing. -
Then the indices. Add the two
Map<String, List<Resource>>fields and populate them inside the load loop. AddfindByAuthorandfindByTradition. Test frommain. -
Then the sorted authors. One method, four lines. Use
TreeSet. -
Then save. The hardest part is the atomic-write detail and properly quoting any field that contains a comma. Get save working first; add the atomic-rename last (the move is three lines).
-
Then the bad-input handling. Wrap your parse loop’s body in
try/catch; on catch, print the line number and reason toSystem.err;continue. The catalog should report what it skipped at the end. -
“I’m running out of time.” Submit what you have. A working Normal that doesn’t attempt Medium beats a half-finished Hard. The rubric rewards completion of lower tiers over partial completion of higher ones.
-
“I’m panicking.” Stop. Re-read the prompt out loud once. Then write the record. Then write
main. Then the load. Each compiled output is a victory. String victories together until time runs out.
Coach’s Note on Exam Day
The students who pass this exam have done two things: (1) the reps before the exam, and (2) one full timed practice run from the sample midterm prompt.
If you haven’t done the timed practice, do Rep 11 (mock midterm light) from the exercises right now, even if you’re reading this two hours before the exam. The discipline of writing the same shape of program under a clock changes how your fingers move in the actual room.
In the exam room: start with the Resource record. Get it on the page. Then main with a hardcoded load. Then the indices. Then the queries. Then save. Then bad-input handling. Compile early. Compile often. The compiler is on your side. Use it as a tight feedback loop.
The midterm is a project. Treat it like one.
See you on the other side. Chapter 9 begins the second half of the course — and AI joins the workflow.
A theological footnote (LCMS confessional Lutheran framing). This midterm is not a verdict about who you are. In confessional Lutheran terms, our standing before God is established by Christ — not by what we can do under the lights. What the midterm measures is the stewardship of the time and attention you have given to the craft so far: how well your training has taken root, where the gaps are, and what to keep practicing.
The apologetics frame is not a coincidence. The library you are cataloging tonight represents two thousand years of careful thinkers articulating the Christian faith into the questions of their times — Augustine answering the Manicheans, Luther answering Rome, Lewis answering the modern skeptic, Chesterton answering the lazy atheist. The discipline of cataloging their work in a small Java program is, in a small way, a continuation of their discipline of cataloging the faith itself.
Submit honest work. Receive an honest grade. Both are stewardship.
See you in the exam room.