# Repository

## Overview

The `repository` package provides simple in-memory persistence for books and members. It appears to exist as a lightweight data access layer that stores domain objects in process-local lists and exposes query methods for looking them up, enumerating them, and filtering them. Because the repositories do not depend on a database or external service, they are easy to use in small applications, demos, or tests.

At a high level, this module owns the collection state for `model.Book` and `model.Member` objects and offers a narrow API for adding and retrieving them. The design is intentionally minimal: the repositories encapsulate the mutable lists so other parts of the system can work with domain objects without managing storage details directly.

## Key Classes and Interfaces

### `BookRepository`

Source: [repository/BookRepository.java](repository/BookRepository.java:8)

`BookRepository` is an in-memory repository for `Book` objects. It maintains a private `List<Book>` and exposes methods to add books, fetch a book by id, return all books, list only available books, and search books by title. This class is the main access point for book data within the package.

Its responsibilities are straightforward but important:
- it owns the book collection state
- it hides the underlying list implementation from callers
- it provides small query helpers that express common book lookups directly

Because the repository returns copies for some operations, it reduces the chance that callers accidentally mutate the internal collection.

#### Methods

- `add(Book book)` — Adds a `Book` to the repository's internal list. It returns `void` and has the side effect of mutating repository state.
- `findById(String id)` — Searches for the first book whose `getId()` matches the supplied `id`. Returns `Optional<Book>` so callers must handle the case where no match exists.
- `findAll()` — Returns a new `ArrayList` containing all stored books. This is a snapshot-style read and avoids exposing the internal list directly.
- `findAvailable()` — Filters the stored books using `Book::isAvailable` and returns the matching books as a list.
- `searchByTitle(String keyword)` — Performs a case-insensitive substring search against each book title by comparing lowercase title text to lowercase keyword text, then returns all matches.

### `MemberRepository`

Source: [repository/MemberRepository.java](repository/MemberRepository.java:8)

`MemberRepository` mirrors the book repository pattern for `Member` objects. It stores members in an internal list and provides methods for adding members, finding a member by id, and retrieving all members.

This class appears to exist so member-related code can use the same repository style as books without knowing how members are stored. Compared with `BookRepository`, it is simpler because it does not define filtered search helpers.

#### Methods

- `add(Member member)` — Appends a `Member` to the internal list.
- `findById(String id)` — Searches the list for the first member whose `getId()` equals the supplied `id` and returns it as an `Optional<Member>`.
- `findAll()` — Returns a new `ArrayList` containing all stored members.

## How It Works

Both repositories follow the same pattern:

1. A private `ArrayList` holds the current in-memory state.
2. `add(...)` mutates that state by appending a new domain object.
3. Lookup methods use the Java Stream API to search or filter the list.
4. `findById(...)` returns `Optional` rather than `null`, which pushes absence handling to the caller.
5. `findAll()` returns a new list rather than the backing collection, which helps keep repository internals encapsulated.

### Typical book flow

1. A caller creates a `Book` in the `model` package.
2. The caller passes the `Book` to `BookRepository.add(...)`.
3. Later, the caller can retrieve that book with `findById(...)`, inspect all books with `findAll()`, or ask for subsets such as `findAvailable()`.
4. If the caller needs title matching, `searchByTitle(...)` performs a case-insensitive search across the current repository contents.

### Filtering and matching behavior

`BookRepository` uses two different query styles:

- `findAvailable()` delegates the availability check to the `Book` model by calling `Book::isAvailable`.
- `searchByTitle(...)` normalizes both the stored title and the search keyword to lowercase before applying `contains(...)`, so matching is case-insensitive.

That means search results depend on the current in-memory state only; there is no indexing, sorting, paging, or persistence layer involved.

## Data Model

The repositories work with two model types:

- `model.Book` — used by `BookRepository`
- `model.Member` — used by `MemberRepository`

From the repository code, both models appear to expose at least an `getId()` method. `Book` also appears to expose `getTitle()` and `isAvailable()`, since those methods are used directly by `BookRepository`.

The repository package does not define its own DTOs or entity wrappers. It stores the domain objects themselves and returns them directly to callers.

## Dependencies and Integration

### Direct dependencies

- `model.Book` — imported by `BookRepository`
- `model.Member` — imported by `MemberRepository`
- Java collection classes — `ArrayList`, `List`, and `Optional`
- Java Stream API — used for `findById`, `findAvailable`, and `searchByTitle`

### Integration style

This module is a leaf-style package: it depends on the `model` package, but no cross-module relationships were detected in the index. In practice, that suggests other layers in the application likely call into these repositories, while the repositories themselves remain unaware of higher-level services or UI code.

## Notes for Developers

- These repositories are in-memory only. Data will be lost when the process exits unless another layer persists it elsewhere.
- `findAll()` returns a copy, so modifying the returned list does not change repository state.
- `findById(...)` returns `Optional`, so callers should handle empty results explicitly instead of assuming a value exists.
- `searchByTitle(...)` is case-insensitive, but it performs a simple substring match rather than tokenized or fuzzy search.
- `BookRepository` uses `toList()` for filtered results, which returns an unmodifiable list in modern Java runtimes. Callers should treat that result as read-only.
- The package is small and consistent, so it should be easy to extend with additional repository methods if future features need more queries.

## Relationships

```mermaid
flowchart LR
RepoModule["repository package"] --> BookRepo["BookRepository"]
RepoModule["repository package"] --> MemberRepo["MemberRepository"]
BookRepo["BookRepository"] --> BookModel["model.Book"]
MemberRepo["MemberRepository"] --> MemberModel["model.Member"]
```
