# Business Logic - KKW02701SF02DBean.typeModelData() [146 LOC]

| Field | Value |
|-------|-------|
| Fully Qualified Name | `eo.web.webview.KKA16701SF.KKW02701SF02DBean` |
| Layer | Utility / Data Bean (webview data type routing) |
| Module | `KKA16701SF` (Package: `eo.web.webview.KKA16701SF`) |

## 1. Role

### KKW02701SF02DBean.typeModelData()

This method serves as the **data type resolution hub** for the data type bean pattern used in the K-Opticom web framework. It maps business-level field names (in Japanese -- item names: 項目名) and subkeys to their corresponding Java reflection types (`Class<?>`). The method implements a **routing/dispatch design pattern**: it receives a `key` (the field name) and a `subkey` (the property accessor), then returns the correct Java type so that the calling layer can dynamically construct, bind, or render form fields without hardcoding type information.

The method handles 12 distinct business field categories used in course history screens -- including service contract details (サービス契約内訳), registration timestamps (世代登録年月日時分秒), move reservation numbers (異動予約番号), application detail numbers (申込明細番号), status flags (状態), course metadata (コース適用年月日, コース名, マンションID, マンション名), and legacy/new pricing course codes (旧料金コースコード, 新料金コースコード).

Its **role in the larger system** is that of a shared metadata provider. It is called by the framework's data type bean infrastructure (e.g., `KKW02701SFBean.listKoumokuIds` delegates to this class for type lookups) and also by screen-level beans (e.g., `CCW00203SFBean.typeModelData(String gamenId, String key, String subkey)` delegates here). This method is purely read-only -- it performs no CRUD operations, does not access the database, and has no side effects. It is a pure function: given the same `(key, subkey)` pair, it always returns the same type.

For each field, the subkey determines which property's type is requested: `"value"` returns the data value type, `"state"` returns the display state type, and `"enable"` (for certain fields) returns the type of a boolean enable/disable flag. If no matching field or subkey is found, the method returns `null`.

## 2. Processing Pattern (Detailed Business Logic)

```mermaid
flowchart TD
    START(["typeModelData key, subkey"])
    COND_NULL{key or subkey null?}
    SEP[int separaterPoint = key.indexOf /]
    COND_SVC{key = サービス契約内訳番号?}
    SUBVAL1{subkey = value?}
    SUBST1{subkey = state?}
    COND_GENE{key = 世代登録年月日時分秒?}
    SUBVAL2{subkey = value?}
    SUBST2{subkey = state?}
    COND_IDO{key = 異動予約番号?}
    SUBVAL3{subkey = value?}
    SUBST3{subkey = state?}
    COND_MS{key = 申込明細番号?}
    SUBVAL4{subkey = value?}
    SUBST4{subkey = state?}
    COND_STAT{key = 状態?}
    SUBVAL5{subkey = value?}
    SUBEN{subkey = enable?}
    SUBST5{subkey = state?}
    COND_COURSE_APLY{key = コース適用年月日?}
    SUBVAL6{subkey = value?}
    SUBEN2{subkey = enable?}
    SUBST6{subkey = state?}
    COND_COURSE_NM{key = コース名?}
    SUBVAL7{subkey = value?}
    SUBEN3{subkey = enable?}
    SUBST7{subkey = state?}
    COND_MAN_ID{key = マンションID?}
    SUBVAL8{subkey = value?}
    SUBEN4{subkey = enable?}
    SUBST8{subkey = state?}
    COND_MAN_NM{key = マンション名?}
    SUBVAL9{subkey = value?}
    SUBEN5{subkey = enable?}
    SUBST9{subkey = state?}
    COND_NEW_PCRS{key = 新料金コースコード?}
    SUBVAL10{subkey = value?}
    SUBEN6{subkey = enable?}
    SUBST10{subkey = state?}
    COND_OLD_PCRS{key = 旧料金コースコード?}
    SUBVAL11{subkey = value?}
    SUBEN7{subkey = enable?}
    SUBST11{subkey = state?}
    END_NULL["return null"]
    END_STRING["return String.class"]
    END_BOOL["return Boolean.class"]

    START --> COND_NULL
    COND_NULL -->|"Yes"| END_NULL
    COND_NULL -->|"No"| SEP
    SEP --> COND_SVC
    COND_SVC -->|"Yes"| SUBVAL1
    COND_SVC -->|"No"| COND_GENE
    SUBVAL1 -->|"Yes"| END_STRING
    SUBVAL1 -->|"No"| SUBST1
    SUBST1 -->|"Yes"| END_STRING
    SUBST1 -->|"No"| COND_GENE
    COND_GENE -->|"Yes"| SUBVAL2
    COND_GENE -->|"No"| COND_IDO
    SUBVAL2 -->|"Yes"| END_STRING
    SUBVAL2 -->|"No"| SUBST2
    SUBST2 -->|"Yes"| END_STRING
    SUBST2 -->|"No"| COND_IDO
    COND_IDO -->|"Yes"| SUBVAL3
    COND_IDO -->|"No"| COND_MS
    SUBVAL3 -->|"Yes"| END_STRING
    SUBVAL3 -->|"No"| SUBST3
    SUBST3 -->|"Yes"| END_STRING
    SUBST3 -->|"No"| COND_MS
    COND_MS -->|"Yes"| SUBVAL4
    COND_MS -->|"No"| COND_STAT
    SUBVAL4 -->|"Yes"| END_STRING
    SUBVAL4 -->|"No"| SUBST4
    SUBST4 -->|"Yes"| END_STRING
    SUBST4 -->|"No"| COND_STAT
    COND_STAT -->|"Yes"| SUBVAL5
    COND_STAT -->|"No"| COND_COURSE_APLY
    SUBVAL5 -->|"Yes"| END_STRING
    SUBVAL5 -->|"No"| SUBEN
    SUBEN -->|"Yes"| END_BOOL
    SUBEN -->|"No"| SUBST5
    SUBST5 -->|"Yes"| END_STRING
    SUBST5 -->|"No"| COND_COURSE_APLY
    COND_COURSE_APLY -->|"Yes"| SUBVAL6
    COND_COURSE_APLY -->|"No"| COND_COURSE_NM
    SUBVAL6 -->|"Yes"| END_STRING
    SUBVAL6 -->|"No"| SUBEN2
    SUBEN2 -->|"Yes"| END_BOOL
    SUBEN2 -->|"No"| SUBST6
    SUBST6 -->|"Yes"| END_STRING
    SUBST6 -->|"No"| COND_COURSE_NM
    COND_COURSE_NM -->|"Yes"| SUBVAL7
    COND_COURSE_NM -->|"No"| COND_MAN_ID
    SUBVAL7 -->|"Yes"| END_STRING
    SUBVAL7 -->|"No"| SUBEN3
    SUBEN3 -->|"Yes"| END_BOOL
    SUBEN3 -->|"No"| SUBST7
    SUBST7 -->|"Yes"| END_STRING
    SUBST7 -->|"No"| COND_MAN_ID
    COND_MAN_ID -->|"Yes"| SUBVAL8
    COND_MAN_ID -->|"No"| COND_MAN_NM
    SUBVAL8 -->|"Yes"| END_STRING
    SUBVAL8 -->|"No"| SUBEN4
    SUBEN4 -->|"Yes"| END_BOOL
    SUBEN4 -->|"No"| SUBST8
    SUBST8 -->|"Yes"| END_STRING
    SUBST8 -->|"No"| COND_MAN_NM
    COND_MAN_NM -->|"Yes"| SUBVAL9
    COND_MAN_NM -->|"No"| COND_NEW_PCRS
    SUBVAL9 -->|"Yes"| END_STRING
    SUBVAL9 -->|"No"| SUBEN5
    SUBEN5 -->|"Yes"| END_BOOL
    SUBEN5 -->|"No"| SUBST9
    SUBST9 -->|"Yes"| END_STRING
    SUBST9 -->|"No"| COND_NEW_PCRS
    COND_NEW_PCRS -->|"Yes"| SUBVAL10
    COND_NEW_PCRS -->|"No"| COND_OLD_PCRS
    SUBVAL10 -->|"Yes"| END_STRING
    SUBVAL10 -->|"No"| SUBEN6
    SUBEN6 -->|"Yes"| END_BOOL
    SUBEN6 -->|"No"| SUBST10
    SUBST10 -->|"Yes"| END_STRING
    SUBST10 -->|"No"| COND_OLD_PCRS
    COND_OLD_PCRS -->|"Yes"| SUBVAL11
    COND_OLD_PCRS -->|"No"| END_NULL
    SUBVAL11 -->|"Yes"| END_STRING
    SUBVAL11 -->|"No"| SUBEN7
    SUBEN7 -->|"Yes"| END_BOOL
    SUBEN7 -->|"No"| SUBST11
    SUBST11 -->|"Yes"| END_STRING
    SUBST11 -->|"No"| END_NULL
```

## 3. Parameter Analysis

| No | Parameter Name | Type | Business Description |
|----|---------------|------|---------------------|
| 1 | `key` | `String` | The Japanese field name (item name: 項目名) of a data type bean property. Represents a business entity field on the course history screen. Possible values: "サービス契約内訳番号" (Service Contract Detail Number, item ID: `svc_kei_ucwk_no`), "世代登録年月日時分秒" (Generation Registration Date/Time, item ID: `gene_add_dtm`), "異動予約番号" (Move Reservation Number, item ID: `ido_rsv_no`), "申込明細番号" (Application Detail Number, item ID: `mskm_dtl_no`), "状態" (Status, item ID: `stat`), "コース適用年月日" (Course Apply Date, item ID: `course_aply_ymd`), "コース名" (Course Name, item ID: `course_nm`), "マンションID" (Mansion ID, item ID: `mansion_id`), "マンション名" (Mansion Name, item ID: `mansion_nm`), "新料金コースコード" (New Pricing Course Code, item ID: `new_pcrs_cd`), "旧料金コースコード" (Old Pricing Course Code, item ID: `old_pcrs_cd`). |
| 2 | `subkey` | `String` | The property accessor within a field -- determines which aspect of the field's type to return. Values: `"value"` (returns the data value's type), `"state"` (returns the display state type -- always `String.class`), `"enable"` (returns the enable/disable flag type -- `Boolean.class` for status, course, mansion, and pricing fields). |

No instance fields or external state are read by this method. It is a pure function with no side effects.

## 4. CRUD Operations / Called Services

This method performs **no CRUD operations** and calls **no external services, SCs, or CBSs**. It is a pure type-resolution utility that uses only `String.equals()`, `String.equalsIgnoreCase()`, `String.indexOf()`, and returns Java reflection `Class<?>` literals (`String.class`, `Boolean.class`).

| CRUD | SC / CBS | SC Code | Entity / DB | Operation Description |
|------|----------|---------|-------------|----------------------|
| *(none)* | - | - | - | This method is a pure type router with no data access. |

## 5. Dependency Trace

| # | Caller (Screen/Batch) | Call Chain (Full Path to this Method) | Terminal (SC / CRUD / Entity) |
|---|----------------------|--------------------------------------|-------------------------------|
| 1 | Screen:KKW02701SF | `KKW02701SFBean.listKoumokuIds` -> `KKW02701SF02DBean.listKoumokuIds` (static, invoked by bean framework) -- `typeModelData` used by the data type bean infrastructure for dynamic field typing | *(none - pure utility)* |
| 2 | Screen:CCW00203SF | `CCW00203SFBean.typeModelData(String gamenId, String key, String subkey)` -> `KKW02701SF02DBean.typeModelData(key, subkey)` (direct delegation, wrapper with unused gamenId param) | *(none - pure utility)* |
| 3 | Screen:KKW02701SF | `KKW02701SFBean.addListDataInstance("コース履歴一覧リスト")` -> `new KKW02701SF02DBean()` -- the data type bean instance creation triggers type resolution via `typeModelData` during dynamic field binding | *(none - pure utility)* |

## 6. Per-Branch Detail Blocks

### Block 1 - IF (L790) [Null guard check]

> Early-exit: if either parameter is null, return null immediately. No further processing occurs.

| # | Type | Code |
|---|------|------|
| 1 | IF | `key == null || subkey == null` // null guard - returns null immediately [nullの場合、nullを返す] |
| 2 | RETURN | `return null;` |

---

### Block 2 - EXEC (L793)

> Compute a separator point index (unused in the current code - likely legacy or reserved for future use).

| # | Type | Code |
|---|------|------|
| 1 | SET | `int separaterPoint = key.indexOf("/")` // reserved separator computation - value is unused |

---

### Block 3 - ELSE-IF (L797) [key = サービス契約内訳番号 (Service Contract Detail Number)]

> The first branch matches the field "サービス契約内訳番号" (item ID: `svc_kei_ucwk_no`). This is the service contract detail number field whose data type is String. For subkey `"value"` or `"state"`, it returns `String.class`.

| # | Type | Code |
|---|------|------|
| 1 | IF | `key.equals("サービス契約内訳番号")` // Field: Service Contract Detail Number [item ID: svc_kei_ucwk_no] |
| 2 | IF (Block 3.1) | `subkey.equalsIgnoreCase("value")` // data value accessor -> `return String.class` |
| 3 | IF (Block 3.2) | `subkey.equalsIgnoreCase("state")` // state accessor -> `return String.class` [subkeyが"state"の場合、ステータスを返す] |

---

### Block 4 - ELSE-IF (L808) [key = 世代登録年月日時分秒 (Generation Registration Date/Time)]

> Matches the field "世代登録年月日時分秒" (item ID: `gene_add_dtm`). The registration date/time field is typed as `String.class` for both `"value"` and `"state"` subkeys.

| # | Type | Code |
|---|------|------|
| 1 | IF | `key.equals("世代登録年月日時分秒")` // Field: Generation Registration Date/Time [item ID: gene_add_dtm] |
| 2 | IF (Block 4.1) | `subkey.equalsIgnoreCase("value")` -> `return String.class` |
| 3 | IF (Block 4.2) | `subkey.equalsIgnoreCase("state")` -> `return String.class` |

---

### Block 5 - ELSE-IF (L819) [key = 異動予約番号 (Move Reservation Number)]

> Matches the field "異動予約番号" (item ID: `ido_rsv_no`). Used in move/transfer processing screens. Both `"value"` and `"state"` return `String.class`.

| # | Type | Code |
|---|------|------|
| 1 | IF | `key.equals("異動予約番号")` // Field: Move Reservation Number [item ID: ido_rsv_no] |
| 2 | IF (Block 5.1) | `subkey.equalsIgnoreCase("value")` -> `return String.class` |
| 3 | IF (Block 5.2) | `subkey.equalsIgnoreCase("state")` -> `return String.class` |

---

### Block 6 - ELSE-IF (L830) [key = 申込明細番号 (Application Detail Number)]

> Matches the field "申込明細番号" (item ID: `mskm_dtl_no`). Used to identify application detail line items. Both subkeys return `String.class`.

| # | Type | Code |
|---|------|------|
| 1 | IF | `key.equals("申込明細番号")` // Field: Application Detail Number [item ID: mskm_dtl_no] |
| 2 | IF (Block 6.1) | `subkey.equalsIgnoreCase("value")` -> `return String.class` |
| 3 | IF (Block 6.2) | `subkey.equalsIgnoreCase("state")` -> `return String.class` |

---

### Block 7 - ELSE-IF (L841) [key = 状態 (Status)]

> Matches the field "状態" (item ID: `stat`). This is a **status/enablement field** -- it has three subkey branches: `"value"` returns `String.class`, `"enable"` returns `Boolean.class` (indicating whether the status field is active/enabled), and `"state"` returns `String.class`.

| # | Type | Code |
|---|------|------|
| 1 | IF | `key.equals("状態")` // Field: Status/Enablement [item ID: stat] |
| 2 | IF (Block 7.1) | `subkey.equalsIgnoreCase("value")` -> `return String.class` |
| 3 | IF (Block 7.2) | `subkey.equalsIgnoreCase("enable")` -> `return Boolean.class` // enable/disable flag |
| 4 | IF (Block 7.3) | `subkey.equalsIgnoreCase("state")` -> `return String.class` |

---

### Block 8 - ELSE-IF (L855) [key = コース適用年月日 (Course Apply Date)]

> Matches the field "コース適用年月日" (item ID: `course_aply_ymd`). The course apply date field supports `"value"` (String), `"enable"` (Boolean -- whether the course is enabled), and `"state"` (String) subkeys.

| # | Type | Code |
|---|------|------|
| 1 | IF | `key.equals("コース適用年月日")` // Field: Course Apply Date [item ID: course_aply_ymd] |
| 2 | IF (Block 8.1) | `subkey.equalsIgnoreCase("value")` -> `return String.class` |
| 3 | IF (Block 8.2) | `subkey.equalsIgnoreCase("enable")` -> `return Boolean.class` |
| 4 | IF (Block 8.3) | `subkey.equalsIgnoreCase("state")` -> `return String.class` |

---

### Block 9 - ELSE-IF (L869) [key = コース名 (Course Name)]

> Matches the field "コース名" (item ID: `course_nm`). The course name field supports `"value"` (String), `"enable"` (Boolean), and `"state"` (String) subkeys -- enabling dynamic display of whether a course name field is active.

| # | Type | Code |
|---|------|------|
| 1 | IF | `key.equals("コース名")` // Field: Course Name [item ID: course_nm] |
| 2 | IF (Block 9.1) | `subkey.equalsIgnoreCase("value")` -> `return String.class` |
| 3 | IF (Block 9.2) | `subkey.equalsIgnoreCase("enable")` -> `return Boolean.class` |
| 4 | IF (Block 9.3) | `subkey.equalsIgnoreCase("state")` -> `return String.class` |

---

### Block 10 - ELSE-IF (L883) [key = マンションID (Mansion ID)]

> Matches the field "マンションID" (item ID: `mansion_id`). Used in apartment/residence-based service provision. Supports `"value"` (String), `"enable"` (Boolean), and `"state"` (String) subkeys.

| # | Type | Code |
|---|------|------|
| 1 | IF | `key.equals("マンションID")` // Field: Mansion (Apartment) ID [item ID: mansion_id] |
| 2 | IF (Block 10.1) | `subkey.equalsIgnoreCase("value")` -> `return String.class` |
| 3 | IF (Block 10.2) | `subkey.equalsIgnoreCase("enable")` -> `return Boolean.class` |
| 4 | IF (Block 10.3) | `subkey.equalsIgnoreCase("state")` -> `return String.class` |

---

### Block 11 - ELSE-IF (L897) [key = マンション名 (Mansion Name)]

> Matches the field "マンション名" (item ID: `mansion_nm`). The apartment name field, with the same three-subkey pattern as mansion_id.

| # | Type | Code |
|---|------|------|
| 1 | IF | `key.equals("マンション名")` // Field: Mansion (Apartment) Name [item ID: mansion_nm] |
| 2 | IF (Block 11.1) | `subkey.equalsIgnoreCase("value")` -> `return String.class` |
| 3 | IF (Block 11.2) | `subkey.equalsIgnoreCase("enable")` -> `return Boolean.class` |
| 4 | IF (Block 11.3) | `subkey.equalsIgnoreCase("state")` -> `return String.class` |

---

### Block 12 - ELSE-IF (L911) [key = 新料金コースコード (New Pricing Course Code)] - ANK-4592-00-00 ADD

> **New in ANK-4592-00-00** (2025.01.09, developer: 森下). Matches the field "新料金コースコード" (item ID: `new_pcrs_cd`). This field was added to support the **television course (SkyPerfec!) introduction** -- a new premium TV pricing tier. Supports `"value"` (String), `"enable"` (Boolean), and `"state"` (String) subkeys.

| # | Type | Code |
|---|------|------|
| 1 | IF | `key.equals("新料金コースコード")` // Field: New Pricing Course Code [item ID: new_pcrs_cd] - ANK-4592-00-00 ADD |
| 2 | IF (Block 12.1) | `subkey.equalsIgnoreCase("value")` -> `return String.class` |
| 3 | IF (Block 12.2) | `subkey.equalsIgnoreCase("enable")` -> `return Boolean.class` |
| 4 | IF (Block 12.3) | `subkey.equalsIgnoreCase("state")` -> `return String.class` |

---

### Block 13 - ELSE-IF (L923) [key = 旧料金コースコード (Old Pricing Course Code)] - ANK-4592-00-00 ADD

> **New in ANK-4592-00-00** (2025.01.09, developer: 森下). Matches the field "旧料金コースコード" (item ID: `old_pcrs_cd`). The legacy pricing course code for comparison/migration during the television course introduction. Same three-subkey pattern.

| # | Type | Code |
|---|------|------|
| 1 | IF | `key.equals("旧料金コースコード")` // Field: Old Pricing Course Code [item ID: old_pcrs_cd] - ANK-4592-00-00 ADD |
| 2 | IF (Block 13.1) | `subkey.equalsIgnoreCase("value")` -> `return String.class` |
| 3 | IF (Block 13.2) | `subkey.equalsIgnoreCase("enable")` -> `return Boolean.class` |
| 4 | IF (Block 13.3) | `subkey.equalsIgnoreCase("state")` -> `return String.class` |

---

### Block 14 - ELSE (L932) [No match - default null return]

> No matching field was found. The comment states: "条件に一致するプロパティが存在しない場合は、nullを返す" (If no matching property exists, return null).

| # | Type | Code |
|---|------|------|
| 1 | RETURN | `return null;` // No matching property exists - return null [条件に一致するプロパティが存在しない場合は、nullを返す] |

## 7. Glossary

| Term | Type | Business Meaning |
|------|------|------------------|
| `svc_kei_ucwk_no` | Field | Service contract detail work number - internal tracking ID for service contract line items (サービス契約内訳番号) |
| `gene_add_dtm` | Field | Generation registration date/time - timestamp of when a data generation/revision was registered (世代登録年月日時分秒) |
| `ido_rsv_no` | Field | Move reservation number - ID for service move/transfer reservations (異動予約番号) |
| `mskm_dtl_no` | Field | Application detail number - unique identifier for application detail records (申込明細番号) |
| `stat` | Field | Status/enablement flag - indicates the current operational state of a field (状態) |
| `course_aply_ymd` | Field | Course apply date - date when a pricing/service course was applied (コース適用年月日) |
| `course_nm` | Field | Course name - human-readable name of a service/pricing course (コース名) |
| `mansion_id` | Field | Mansion (apartment/residence) ID - identifier for apartment-based service provision locations (マンションID) |
| `mansion_nm` | Field | Mansion (apartment/residence) name - name of the apartment/residence building (マンション名) |
| `new_pcrs_cd` | Field | New pricing course code - code for the newly introduced pricing course (新料金コースコード) - added in ANK-4592-00-00 |
| `old_pcrs_cd` | Field | Old pricing course code - code for the legacy pricing course being replaced (旧料金コースコード) - added in ANK-4592-00-00 |
| `key` | Parameter | Item name (項目名) - the Japanese business label used to identify a data type bean field |
| `subkey` | Parameter | Sub-key (サブキー) - property accessor sub-identifier within a data type bean field |
| Data type bean | Business term | データタイプビューン型 - a design pattern where beans dynamically resolve field types via `typeModelData` for runtime form field construction |
| ANK-4592-00-00 | Change ID | Television course (SkyPerfec!) introduction project - added new_pcrs_cd and old_pcrs_cd fields in January 2025 |
| koumokumei (項目名) | Japanese term | Item name - the human-readable field label used throughout the web framework's data type bean system |
| subuki (サブキー) | Japanese term | Sub-key - the property accessor sub-identifier within a data type bean field |
| sutetasu (ステータス) | Japanese term | Status - the display state of a field, returned as String.class |
