# Service

## Overview

The `service` package contains the application-layer logic for managing books, members, and loans. It sits between the UI and the repositories, coordinating object creation, validation, and state changes so the rest of the system can work with higher-level operations instead of manipulating repositories directly.

This appears to be the main orchestration layer for the library domain. `LibraryService` focuses on catalog and member registration tasks, while `LoanService` handles borrowing and returning books and keeps track of active loans in memory.

## Key Classes and Interfaces

### `LibraryService`

Source: [service/LibraryService.java](service/LibraryService.java:10)

`LibraryService` is a small façade over the book and member repositories. Its job is to create new domain objects with generated IDs, persist them through the repositories, and expose simple query methods for listing and searching library data.

Key responsibilities:

- Creates `Book` instances with generated identifiers in `addBook(...)`
- Creates `Member` instances with generated identifiers in `registerMember(...)`
- Delegates read operations directly to the repositories for listing and searching
- Keeps repository access centralized so callers do not need to know about persistence details

Methods:

- `LibraryService(BookRepository bookRepo, MemberRepository memberRepo)` — constructor that injects the repositories the service needs. This makes the service easy to wire up from the UI layer and keeps it independent of concrete storage implementations.
- `addBook(String title, String author, String isbn)` — creates a new `Book` with an ID prefixed by `B`, stores it through `bookRepo.add(...)`, and returns the created object.
- `registerMember(String name, String email)` — creates a new `Member` with an ID prefixed by `M`, stores it through `memberRepo.add(...)`, and returns the created object.
- `listAllBooks()` — returns `bookRepo.findAll()`.
- `listAvailableBooks()` — returns `bookRepo.findAvailable()`.
- `searchBooks(String keyword)` — returns `bookRepo.searchByTitle(keyword)`.
- `listAllMembers()` — returns `memberRepo.findAll()`.

Design notes:

- ID generation is done with `UUID.randomUUID()` and truncated to six uppercase characters, which makes IDs short and human-readable while still being very likely unique.
- The class intentionally stays thin; most behavior is delegated to the repositories instead of being reimplemented here.

### `LoanService`

Source: [service/LoanService.java](service/LoanService.java:13)

`LoanService` coordinates the lifecycle of borrowing and returning books. It uses the repositories to validate that books and members exist, mutates book availability, and stores loan records in an in-memory `List<Loan>`.

Key responsibilities:

- Validates book and member existence before creating a loan
- Prevents borrowing books that are already marked unavailable
- Marks books unavailable when borrowed and available again when returned
- Tracks loan records locally so active loans can be queried without repository support

Methods:

- `LoanService(BookRepository bookRepo, MemberRepository memberRepo)` — constructor that injects the repositories needed for validation and state updates.
- `borrowBook(String bookId, String memberId)` — looks up the requested book and member, returns an error message if either is missing, checks book availability, marks the book unavailable, creates a new `Loan`, stores it in the local loan list, and returns a success message containing the loan ID.
- `returnBook(String loanId)` — finds the matching non-returned loan by ID, marks it returned by calling `loan.returnBook()`, and returns a success or error message.
- `getActiveLoans()` — returns the subset of loans that have not been returned yet.

Design notes:

- The service uses return strings for success and failure cases instead of exceptions or a result type. Callers should expect user-facing messages such as `Book not found`, `Member not found`, or `Borrowed successfully`.
- Loan state is held in memory in the `loans` list. That means active loans will be lost if the process restarts unless another layer persists them.
- `borrowBook(...)` directly flips the borrowed book’s availability flag to `false`, so the book repository and any other views of the same `Book` instance will reflect the change immediately.

## How It Works

### Borrowing flow

1. A caller invokes `LoanService.borrowBook(bookId, memberId)`.
2. The service looks up the book with `bookRepo.findById(bookId)`.
3. The service looks up the member with `memberRepo.findById(memberId)`.
4. If either lookup fails, the method returns a descriptive error string.
5. If the book exists but is not available, the method returns `Book is currently unavailable.`
6. If all checks pass, the service sets the book’s availability to `false`.
7. It generates a loan ID with the `L` prefix.
8. It creates a new `Loan` from the book and member and stores it in memory.
9. It returns a success message containing the loan ID.

### Return flow

1. A caller invokes `LoanService.returnBook(loanId)`.
2. The service scans the in-memory loan list for a matching loan that has not already been returned.
3. If no active loan matches, it returns `Active loan not found`.
4. If the loan exists, the service calls `loan.returnBook()`.
5. The method returns a success message.

### Listing and search flow

`LibraryService` simply forwards read requests to the repositories. This keeps query behavior in one place and makes the service layer a thin coordination boundary rather than a second data-access layer.

## Data Model

The service layer works with three domain types:

- `Book` — used for catalog entries and availability tracking.
- `Member` — used for registered library users.
- `Loan` — used to represent a book borrowed by a member.

Relationships inferred from the code:

- A `Loan` references one `Book` and one `Member`.
- A `Book` has an availability flag that changes when the book is borrowed or returned.
- `LibraryService` creates `Book` and `Member` instances.
- `LoanService` creates and manages `Loan` instances.

```mermaid
flowchart TD
ServiceModule["Service module"] --> LibraryService["LibraryService"]
ServiceModule --> LoanService["LoanService"]
LibraryService --> BookRepository["BookRepository"]
LibraryService --> MemberRepository["MemberRepository"]
LoanService --> BookRepository
LoanService --> MemberRepository
LoanService --> Loan["Loan"]
LibraryService --> Book["Book"]
LibraryService --> Member["Member"]
```

## Dependencies and Integration

The service package depends on the following layers and types:

- `repository.BookRepository` — used for creating, locating, listing, and searching books
- `repository.MemberRepository` — used for creating and locating members
- `model.Book` — the catalog entity whose availability is mutated during borrowing
- `model.Member` — the registered user entity used for loan assignment
- `model.Loan` — the loan record stored by `LoanService`

From the evidence, these services are designed to be called from the `ui` layer. The indexed package dependency data shows `ui` as a consumer, which suggests the UI should talk to services rather than directly to repositories.

## Notes for Developers

- **ID format is generated locally.** Book IDs start with `B`, member IDs with `M`, and loan IDs with `L`. If you extend the system, keep those prefixes consistent unless you update downstream expectations.
- **Loan storage is in memory.** `LoanService` does not persist loans through a repository, so restarting the app resets active loan state.
- **Availability is stateful on the `Book` object.** Borrowing mutates the `Book` instance returned from the repository. Any code that shares that object will observe the changed availability flag.
- **Error handling is message-based.** The service returns strings for both success and failure in loan operations. If you add new callers, plan for string parsing or consider introducing a richer result type later.
- **The service layer is intentionally thin.** Most operations are simple orchestration around repository calls. This makes the code easy to follow, but it also means business rules are concentrated in a few methods and should be updated carefully.
