# Org / Springframework / Samples / Petclinic / Owner/other

## Overview

This subpackage contains the core owner-facing domain model for the Petclinic sample: owners, pets, pet types, and visits. It also includes the Spring MVC infrastructure needed to bind pet types from forms and validate pet input before persistence. In practice, this module appears to sit at the center of the pet ownership workflow: an owner can have many pets, each pet can have many visits, and the web layer uses formatter and validator support to make the forms work cleanly.

## Key Classes and Interfaces

### `Owner`
- [Owner](src/main/java/org/springframework/samples/petclinic/owner/Owner.java:47) is the aggregate root for the owner workflow. It extends the shared `Person` model and maps to the `owners` table.
- It stores address, city, and telephone, plus an eagerly loaded, ordered list of pets.
- Important methods:
  - [Owner.getAddress()](src/main/java/org/springframework/samples/petclinic/owner/Owner.java:69) / [Owner.setAddress(String address)](src/main/java/org/springframework/samples/petclinic/owner/Owner.java:73): basic address accessors.
  - [Owner.getCity()](src/main/java/org/springframework/samples/petclinic/owner/Owner.java:77) / [Owner.setCity(String city)](src/main/java/org/springframework/samples/petclinic/owner/Owner.java:81): city accessors.
  - [Owner.getTelephone()](src/main/java/org/springframework/samples/petclinic/owner/Owner.java:85) / [Owner.setTelephone(String telephone)](src/main/java/org/springframework/samples/petclinic/owner/Owner.java:89): telephone accessors. The field is constrained to 10 digits with `@Pattern` and cannot be blank.
  - [Owner.getPets()](src/main/java/org/springframework/samples/petclinic/owner/Owner.java:93): returns the live pet collection.
  - [Owner.addPet(Pet pet)](src/main/java/org/springframework/samples/petclinic/owner/Owner.java:97): adds a pet only when it is new, which helps avoid duplicate attachment of already persisted pets.
  - [Owner.getPet(String name)](src/main/java/org/springframework/samples/petclinic/owner/Owner.java:108): finds a pet by name.
  - [Owner.getPet(Integer id)](src/main/java/org/springframework/samples/petclinic/owner/Owner.java:117): finds a persisted pet by id.
  - [Owner.getPet(String name, boolean ignoreNew)](src/main/java/org/springframework/samples/petclinic/owner/Owner.java:135): name-based lookup with optional filtering of unsaved pets.
  - [Owner.toString()](src/main/java/org/springframework/samples/petclinic/owner/Owner.java:147): emits a diagnostic string including identity and contact details.
  - [Owner.addVisit(Integer petId, Visit visit)](src/main/java/org/springframework/samples/petclinic/owner/Owner.java:164): validates arguments, locates the target pet, and delegates to `Pet.addVisit`.
- Design role: `Owner` is the object that controller code can load once and then navigate to pets and visits through.

### `Pet`
- [Pet](src/main/java/org/springframework/samples/petclinic/owner/Pet.java:44) models an individual animal owned by an owner.
- It maps to `pets` and extends `NamedEntity`, so it inherits an id and name.
- Important state:
  - `birthDate`, stored as `LocalDate` with `@DateTimeFormat(pattern = "yyyy-MM-dd")` for form binding.
  - `type`, a many-to-one association to [PetType](src/main/java/org/springframework/samples/petclinic/owner/PetType.java:26).
  - `visits`, an eagerly loaded, date-ordered set of [Visit](src/main/java/org/springframework/samples/petclinic/owner/Visit.java:34) records.
- Important methods:
  - [Pet.setBirthDate(LocalDate birthDate)](src/main/java/org/springframework/samples/petclinic/owner/Pet.java:61) / [Pet.getBirthDate()](src/main/java/org/springframework/samples/petclinic/owner/Pet.java:65): birth date accessors.
  - [Pet.getType()](src/main/java/org/springframework/samples/petclinic/owner/Pet.java:69) / [Pet.setType(PetType type)](src/main/java/org/springframework/samples/petclinic/owner/Pet.java:73): pet type accessors.
  - [Pet.getVisits()](src/main/java/org/springframework/samples/petclinic/owner/Pet.java:77): exposes the underlying visit collection.
  - [Pet.addVisit(Visit visit)](src/main/java/org/springframework/samples/petclinic/owner/Pet.java:81): appends a visit to the set.
- Design role: `Pet` is a simple persistence entity with just enough behavior to manage its visit history.

### `PetType`
- [PetType](src/main/java/org/springframework/samples/petclinic/owner/PetType.java:26) is the lookup entity for the set of valid pet categories.
- It maps to the `types` table and extends `NamedEntity`, so the primary behavior is inherited.
- This class intentionally contains no additional methods or fields; its purpose is to represent persisted reference data such as dog, cat, or hamster.

### `PetTypeFormatter`
- [PetTypeFormatter](src/main/java/org/springframework/samples/petclinic/owner/PetTypeFormatter.java:36) is a Spring MVC `Formatter<PetType>` that bridges between text submitted by forms and actual `PetType` entities.
- It is annotated with `@Component`, so it can be discovered and registered in the web layer.
- Important methods:
  - [PetTypeFormatter.PetTypeFormatter(PetTypeRepository types)](src/main/java/org/springframework/samples/petclinic/owner/PetTypeFormatter.java:41): constructor injection of the repository used for lookups.
  - [PetTypeFormatter.print(PetType petType, Locale locale)](src/main/java/org/springframework/samples/petclinic/owner/PetTypeFormatter.java:45): renders the name, or `"<null>"` if the entity has no name.
  - [PetTypeFormatter.parse(String text, Locale locale)](src/main/java/org/springframework/samples/petclinic/owner/PetTypeFormatter.java:51): scans all pet types from the repository and returns the one whose name matches the input text; throws `ParseException` if none match.
- Design role: this formatter makes the pet form bind human-readable type names while still storing a proper entity association.

### `PetValidator`
- [PetValidator](src/main/java/org/springframework/samples/petclinic/owner/PetValidator.java:32) implements Spring’s `Validator` for `Pet` form submissions.
- It uses manual validation logic rather than Bean Validation for a few form-specific rules.
- Important methods:
  - [PetValidator.validate(Object obj, Errors errors)](src/main/java/org/springframework/samples/petclinic/owner/PetValidator.java:36): checks three fields and rejects missing values with the `required` error code.
    - name must contain text
    - type is required for new pets
    - birthDate must be present
  - [PetValidator.supports(Class<?> clazz)](src/main/java/org/springframework/samples/petclinic/owner/PetValidator.java:59): returns true only for `Pet`-compatible classes.
- Design role: controller code can apply it to ensure consistent form errors before saving a pet.

### `Visit`
- [Visit](src/main/java/org/springframework/samples/petclinic/owner/Visit.java:34) represents a single appointment or visit associated with a pet.
- It maps to `visits` and extends `BaseEntity`, so it participates in the shared persistence model.
- Important methods:
  - [Visit.Visit()](src/main/java/org/springframework/samples/petclinic/owner/Visit.java:48): initializes the visit date to the current day.
  - [Visit.getDate()](src/main/java/org/springframework/samples/petclinic/owner/Visit.java:52) / [Visit.setDate(LocalDate date)](src/main/java/org/springframework/samples/petclinic/owner/Visit.java:56): date accessors.
  - [Visit.getDescription()](src/main/java/org/springframework/samples/petclinic/owner/Visit.java:60) / [Visit.setDescription(String description)](src/main/java/org/springframework/samples/petclinic/owner/Visit.java:64): description accessors.
- Design role: `Visit` stores the timeline of care for a pet, with date and free-text description.

## How It Works

A typical owner workflow moves through these objects in a predictable sequence:

1. The application loads an `Owner` from persistence.
2. The owner’s `pets` collection is traversed to show pet details or add a new pet.
3. When a pet form is submitted, `PetTypeFormatter` converts the submitted type label into a `PetType` entity.
4. `PetValidator` checks that the pet has the required fields, especially when the pet is being created.
5. If the user adds a visit, `Owner.addVisit(Integer petId, Visit visit)` finds the matching persisted pet and delegates to `Pet.addVisit(Visit visit)`.
6. The `Pet` then holds its ordered `visits` set, which the UI can render on the owner details page.

### Relationship flow

```mermaid
flowchart TD
OwnerEntity["Owner"] --> PetEntity["Pet"]
PetEntity --> VisitEntity["Visit"]
PetTypeEntity["PetType"] --> PetEntity
PetTypeFormatterNode["PetTypeFormatter"] --> PetTypeRepositoryNode["PetTypeRepository"]
PetValidatorNode["PetValidator"] --> PetEntity
OwnerEntity --> OwnerControllerNode["OwnerController"]
PetEntity --> PetControllerNode["PetController"]
VisitEntity --> VisitControllerNode["VisitController"]
```

## Data Model

### Owner
- Fields: address, city, telephone, plus inherited person fields such as first and last name.
- Relationships:
  - one owner to many pets
  - pets are loaded eagerly and ordered by pet name
- Validation:
  - address and city must be present
  - telephone must be present and match a 10-digit pattern

### Pet
- Fields: name inherited from `NamedEntity`, birthDate, type.
- Relationships:
  - many pets belong to one owner
  - one pet can have many visits
- Ordering:
  - visits are stored in insertion order via `LinkedHashSet`
  - JPA ordering sorts visits by date ascending

### PetType
- Reference data entity used by forms and persistence.
- Represents the allowed categories for pets.

### Visit
- Fields: date and description.
- Validation:
  - description is required
- Defaulting:
  - date defaults to `LocalDate.now()` when a visit is created

## Dependencies and Integration

This module depends on shared model types from `org.springframework.samples.petclinic.model`, especially `Person`, `NamedEntity`, and `BaseEntity`. It also integrates with Spring Data repositories such as `OwnerRepository` and `PetTypeRepository` indirectly through the controller and formatter tests.

Spring MVC integration points include:
- `@DateTimeFormat` on date fields for form binding
- `Formatter<PetType>` for translating between submitted strings and entity values
- `Validator` for form-level pet validation
- JPA annotations for persistence mapping and relationship management

The tests in this module show how the pieces are wired in practice:
- [OwnerControllerTests](src/test/java/org/springframework/samples/petclinic/owner/OwnerControllerTests.java:58) covers owner creation, search, edit, and detail pages.
- [PetControllerTests](src/test/java/org/springframework/samples/petclinic/owner/PetControllerTests.java:48) covers pet creation and update, including validation failures.
- [PetTypeFormatterTests](src/test/java/org/springframework/samples/petclinic/owner/PetTypeFormatterTests.java:41) verifies text-to-entity conversion.
- [PetValidatorTests](src/test/java/org/springframework/samples/petclinic/owner/PetValidatorTests.java:39) verifies the manual validation rules.
- [VisitControllerTests](src/test/java/org/springframework/samples/petclinic/owner/VisitControllerTests.java:43) covers visit creation.

## Notes for Developers

- `Owner.addPet(Pet pet)` only adds pets that are still new. If you pass an already persisted pet, it will be ignored.
- `Owner.getPet(String name, boolean ignoreNew)` is case-insensitive, which helps avoid duplicate-name issues during form handling.
- `Owner.addVisit(Integer petId, Visit visit)` performs defensive `Assert.notNull` checks and fails fast if the pet id is invalid.
- `PetValidator` intentionally validates only `Pet` instances and only enforces a small set of rules. Additional constraints should be added carefully so controller error codes stay consistent.
- `PetTypeFormatter.parse(...)` performs a linear scan through all pet types returned by the repository. That is simple and readable, but it assumes the type list is small and stable.
- `Visit` sets its date in the constructor. If a caller wants a different date, it must explicitly override it after construction.
- The web tests show the expected field error codes:
  - `required` for blank names or missing types
  - `typeMismatch` for malformed dates
  - `notFound` for owner search misses

## Test Coverage Summary

The module’s tests focus on the user-facing owner workflows rather than low-level unit behavior:
- owner creation, lookup, update, and display
- pet creation and update, including blank name, duplicate name, missing type, and bad date cases
- pet type formatting success and failure
- pet validation success and failure
- visit creation success and validation failure

These tests are a good reference when changing the module because they document the expected controller and binding behavior end to end.
