# 業務ロジック — PetController.initCreationForm() [6 LOC]

| 項目 | 値 |
|-------|-------|
| 完全修飾名 | `org.springframework.samples.petclinic.owner.PetController` |
| レイヤー | Controller |
| モジュール | `owner` (パッケージ: `org.springframework.samples.petclinic.owner`)

## 1. 役割

### PetController.initCreationForm()

`initCreationForm` メソッドは、ペット飼い主（Owner）が新たにペット（Pet）を登録するための作成画面を初期表示する役割を担う Spring MVC コントローラメソッドである。このメソッドは `GET /owners/{ownerId}/pets/new` エンドポイントにマッピングされており、飼い主の詳細ページから「ペットの新規追加」リンクがクリックされた際に呼び出される入口（エントリーポイント）となる。

処理内容は本質的に単純であり、以下の 2 つのステップから構成される。まず `new Pet()` により空の新規ペットエンティティをインスタンス化し、次に `owner.addPet(pet)` により当該オーナーの pet 一覧リストに当該ペットオブジェクトを追加する。この追加により、後続のフォーム送信時に Spring のデータバインディングがオーナーの所有関係（`@OneToMany`）を通じてペットデータを受信・永続化できるようになる。

このメソッドは Spring の `@ModelAttribute` パターンに基づく「フォーム初期化ルーチン」として設計されており、画面表示前にモデル属性（`pet`）を自動的にセットアップする。フォーム画面（`pets/createOrUpdatePetForm`）では、この時点でセットされた空の `Pet` オブジェクトを起点として、名前（name）、種類（type）、生年月日（birthDate）などの入力フィールドが描画される。

制御分岐は存在せず、常に同じ処理パスを辿る。これは「新規作成」に特化した単一パスの初期化メソッドであり、既存ペットの編集画面（`petId` が存在する場合）とは分離された責務を持つ。

## 2. 処理パターン（詳細業務ロジック）

```mermaid
flowchart TD
    START(["GET /owners/{ownerId}/pets/new"]) --> STEP1["new Pet()"]
    STEP1 --> STEP2["owner.addPet(pet)"]
    STEP2 --> STEP3["pets/createOrUpdatePetForm"]
    STEP3 --> END_NODE(["画面表示: 新規ペット作成フォーム"])
```

**処理ステップの説明:**

| ステップ | 種別 | 内容 |
|----------|------|------|
| 1 | CREATE | `new Pet()` — 新規ペットエンティティを空の状態で作成 |
| 2 | EXEC | `owner.addPet(pet)` — オーナーのペット一覧に新規ペットを追加（`Pet.isNew()` が true のみ追加） |
| 3 | RETURN | `"pets/createOrUpdatePetForm"` — 新規作成画面テンプレートを返す |

`owner.addPet(pet)` 内部では、`pet.isNew()` が true の場合に限り `getPets().add(pet)` が実行される。これは JavaDoc に明記された通り「新規ペットのみをオーナーのコレクションに追加する」仕様である。`Pet.isNew()` は主キー（`id`）が `null` の場合に true を返すため、新規作成中のペットは常にコレクションに保持される。

## 3. パラメータ分析

| No | パラメータ名 | 型 | 業務的説明 |
|----|---------------|------|---------------------|
| 1 | `owner` | `Owner` | ペットを新規登録する対象の飼い主エンティティ。`@ModelAttribute("owner")` により、URL の `{ownerId}` パスパラメータから `OwnerRepository.findById()` で取得されたオーナーオブジェクトが自動的にバインドされる。このオブジェクトは `@OneToMany` 関係を通じてペット一覧（`List<Pet>`）を保持しており、新規ペットの追加先となる。 |
| 2 | `model` | `ModelMap` | Spring MVC のモデルオブジェクト。本メソッドでは直接使用されていないが、シグネチャの整合性のために存在する。実際には `@ModelAttribute("pet")` が付与された `findPet()` メソッド（同一コントローラ内）によってモデルに `pet` 属性が自動的にセットされる。 |

**関連するインスタンスフィールド:**

| フィールド名 | 型 | 業務的説明 |
|-------------|------|---------------------|
| `VIEWS_PETS_CREATE_OR_UPDATE_FORM` | `String` | 新規作成・編集画面のビュー名の定数。値は `"pets/createOrUpdatePetForm"` |
| `owners` | `OwnerRepository` | 飼い主（Owner）エンティティのリポジトリ。このメソッドでは直接使用されないが、`@ModelAttribute` 経由で間接的に参照される。 |

## 4. CRUD操作／呼び出しサービス

### コード解析グラフからの事前抽出エビデンス:

| CRUD | SC / CBS | SCコード | エンティティ / DB | 操作の説明 |
|------|----------|---------|-------------|----------------------|
| C | `Owner.addPet` | - | `pets` (オーナーの子エンティティ) | オーナーの pet リストに新規ペットエンティティを追加 |

**詳細 CRUD 分析:**

| CRUD | SC / CBS | SCコード | エンティティ / DB | 操作の説明 |
|------|----------|---------|-------------|----------------------|
| C | `Owner.addPet` | - | `pets` (JPA Entity) | 新規 Pet オブジェクトを Owner の `List<Pet>` に追加。`pets` テーブルへの物理的な INSERT は行われず、後続の `processCreationForm` において `OwnerRepository.save()` 実行時に ORM によって永続化される（カスケード設定による）。 |

**CRUD 分類の補足:**

本メソッドは直接的なデータベース書き込み（INSERT）を実行しない。`Owner.addPet(pet)` は JPA の `@OneToMany(cascade = CascadeType.ALL)` 設定により、オーナーエンティティが永続化されるタイミングで子エンティティ（Pet）も自動的に永続化されるよう設計されている。つまり、本メソッドは「フォーム表示前のメモリ上でのオブジェクト関連付け」のみを担当し、実際の DB への書き込みは後続の `processCreationForm` で実行される `owners.save(owner)` に委譲されている。

## 5. 依存関係トレース

| # | 呼び出し元（画面/バッチ） | 呼び出しチェーン（本メソッドまでの全経路） | 終端（SC / CRUD / エンティティ） |
|---|----------------------|--------------------------------------|-------------------------------|
| 1 | 画面: PetController | `PetController.initCreationForm → Owner.addPet → Pet.isNew → List.add` | `pets [C] JPA Entity` |

**呼び出し元の詳細:**

| 呼び出し元 | 種別 | 説明 |
|-----------|------|------|
| `PetController.initCreationForm` (GET) | HTTP エンドポイント | `/owners/{ownerId}/pets/new` に対する GET リクエストから直接呼び出される。URL パスパラメータ `{ownerId}` から `@ModelAttribute("owner")` により Owner が自動バインドされる。 |
| `PetControllerTests.initCreationForm` | テストケース | `mockMvc.perform(get("/owners/{ownerId}/pets/new", TEST_OWNER_ID))` により、テスト実行時に直接呼び出される。応答状態（`status().isOk()`）とビュー名（`pets/createOrUpdatePetForm`）を検証する。 |

**本メソッドが呼び出す先:**

| 呼び出し先 | 種類 | 説明 |
|-----------|------|------|
| `Owner.addPet(Pet)` | Entity Method | オーナーエンティティのメソッド。新規ペットをコレクションに追加。 |
| `Pet.isNew()` | Entity Method | Pet エンティティのアクセサ。主キー `id` が `null` かどうかを判定。 |
| `List.add(Pet)` | Collection Operation | `ArrayList` への要素追加。 |

## 6. 分岐ごとの詳細ブロック

本メソッドは制御分岐を含まない直線的な処理である。ただし、内部呼び出しである `Owner.addPet()` 内に条件分岐が存在するため、それについても言及する。

---

**Block 1** — [PROCESS] `(本メソッドの全処理)` (L100)

> GET リクエストを受け付け、新規ペット作成フォーム用のモデルを初期化する。

| # | 種別 | コード |
|---|------|------|
| 1 | CREATE | `Pet pet = new Pet();` — 新規 Pet オブジェクトをインスタンス化 |
| 2 | CALL | `owner.addPet(pet);` — オーナーの pet リストに新規ペットを追加 |
| 3 | RETURN | `return VIEWS_PETS_CREATE_OR_UPDATE_FORM;` — ビュー名文字列を返す |

---

**Block 2** — [IF] `(pet.isNew())` [`Owner.addPet` 内部] (L Owner.java)

> `Owner.addPet` メソッド内に存在する条件分岐。新規ペット（`isNew() == true`）のみをオーナーの pet リストに追加する。

| # | 種別 | コード |
|---|------|------|
| 1 | COND | `if (pet.isNew())` — `Pet.isNew()` が true の場合のみ追加処理を実行 |
| 2 | CALL | `getPets().add(pet);` — `@OrderBy("name")` 付きの `List<Pet>` に要素を追加 |

**`Pet.isNew()` の判定ロジック:**
- `Pet.getId()` が `null` の場合 → `true`（新規登録中）
- `Pet.getId()` が `null` でない場合 → `false`（既存エンティティ）

## 7. 用語集

| 用語 | 種別 | 業務的意味 |
|------|------|------------------|
| `Owner` | Entity | ペットを所有する飼い主エンティティ。`owners` テーブルにマッピングされ、住所（address）、都市（city）、電話番号（telephone）などの属性を持つ。 |
| `Pet` | Entity | 飼い主が飼育するペットエンティティ。名前（name）、種類（type）、生年月日（birthDate）などの属性を持ち、`pets` テーブルにマッピングされる。 |
| `pets/createOrUpdatePetForm` | ビュー名 | 新規ペット作成フォームおよび既存ペット編集フォームを統一して描画する Thymeleaf テンプレート。 |
| `@ModelAttribute` | アノテーション | Spring MVC のアノテーション。リクエスト前にモデル属性を自動バインド・初期化するために使用される。`@ModelAttribute("owner")` は Owner を、`@ModelAttribute("pet")` は Pet をモデルにセットする。 |
| `@GetMapping` | アノテーション | HTTP GET リクエストを特定のメソッドにマッピングするための Spring MVC アノテーション。本メソッドでは `/owners/{ownerId}/pets/new` にマッピングされている。 |
| `OwnerRepository` | Repository | Owner エンティティの永続化を管理する Spring Data JPA リポジトリ。`findById()` などで使用される。 |
| `@OneToMany` | JPA アノテーション | 一方（Owner）と多側（Pet）のリレーションを定義する JPA アノテーション。`cascade = CascadeType.ALL` により、親エンティティの操作が子エンティティにも伝搬される。 |
| `CascadeType.ALL` | JPA 指定 | 親エンティティ（Owner）に対する永続化・削除・更新などの操作が、全て子エンティティ（Pet）にも伝搬される設定。 |
| `new Pet()` | オブジェクト操作 | Pet エンティティの新規インスタンス生成。主キー（`id`）は `null` で初期化され、`isNew()` が true を返す状態となる。 |
| `Pet.isNew()` | メソッド | Pet が未永続化（`id == null`）かどうかを判定するアクセサメソッド。新規登録チェックに使用される。 |
