# Business Logic — KKW01027SF02DBean.typeModelData() [80 LOC]

| Field | Value |
|-------|-------|
| Fully Qualified Name | `eo.web.webview.KKA15001SF.KKW01027SF02DBean` |
| Layer | Utility / Data-Binding Bean (webview layer) |
| Module | `KKA15001SF` (Package: `eo.web.webview.KKA15001SF`) |

## 1. Role

### KKW01027SF02DBean.typeModelData()

This method serves as the **type introspection router** for the `KKA15001SF` screen, implementing the `X33VDataTypeBeanInterface` contract. It maps a hierarchical key/subkey pair to a Java `Class` type at runtime, enabling dynamic data binding in the webview framework. The method acts as a shared utility invoked during screen initialization and data binding cycles, allowing the framework to determine the expected type of form fields without hardcoding type information in HTML/JavaScript.

The method implements a **routing/dispatch pattern** based on the `key` parameter. For scalar fields like the "追加字" (Add Field) group — which manages dynamic input fields for new data entries — it resolves subkeys "value", "enable", and "state" to `String.class` or `Boolean.class`. For list-based fields such as "コードリスト" (Code List) and "コード名リスト" (Code Name List), it parses the index from the key (e.g., "コードリスト/0"), delegates to the corresponding list element's `typeModelData()` method, and returns the nested type. If no matching branch exists or the index is out of bounds, it returns `null`, signaling an unrecognized field to the caller.

This method plays a central role in the **X33V webview data-binding system**, a framework used across the KKA15001SF screen family to achieve type-safe binding between Java beans and JavaScript form elements. By centralizing type resolution here, the system supports dynamic list population, runtime type validation, and consistent form behavior across multiple screens that share the same bean infrastructure.

## 2. Processing Pattern (Detailed Business Logic)

```mermaid
flowchart TD
    START(["typeModelData key, subkey"])

    START --> COND_NULL["key == null || subkey == null"]
    COND_NULL -->|true| RET_NULL_1["return null"]
    COND_NULL -->|false| FIND_SLASH["key.indexOf('/')"]
    FIND_SLASH --> COND_ADD["key equals '追加字'"]

    COND_ADD -->|true| SUB_VALUE["subkey.equalsIgnoreCase('value')"]
    SUB_VALUE -->|true| RET_STRING_1["return String.class"]
    SUB_VALUE -->|false| SUB_ENABLE["subkey.equalsIgnoreCase('enable')"]
    SUB_ENABLE -->|true| RET_BOOL["return Boolean.class"]
    SUB_ENABLE -->|false| SUB_STATE["subkey.equalsIgnoreCase('state')"]
    SUB_STATE -->|true| RET_STRING_2["return String.class"]
    SUB_STATE -->|false| NO_ADD_END["no match for 追加字"]

    COND_ADD -->|false| COND_CODE_LIST["key equals 'コードリスト'"]

    COND_CODE_LIST -->|true| CODE_LIST_SLICE["key.substring(separaterPoint + 1)"]
    CODE_LIST_SLICE --> CODE_WILDCARD["key equals '*'"]
    CODE_WILDCARD -->|true| RET_INTEGER_1["return Integer.class"]
    CODE_WILDCARD -->|false| CODE_PARSE_INT["Integer.valueOf(key)"]
    CODE_PARSE_INT --> CODE_PARSE_CATCH{NumberFormatException?}
    CODE_PARSE_CATCH -->|yes| RET_NULL_2["return null"]
    CODE_PARSE_CATCH -->|no| CODE_CHECK_NULL["tmpIndexInt == null"]
    CODE_CHECK_NULL -->|true| RET_NULL_3["return null"]
    CODE_CHECK_NULL -->|false| CODE_BOUNDS["tmpIndex >= cd_div_list_list.size()"]
    CODE_BOUNDS -->|true| RET_NULL_4["return null"]
    CODE_BOUNDS -->|false| CODE_DELEGATE["cd_div_list_list.get(tmpIndex).typeModelData(subkey)"]

    COND_CODE_LIST -->|false| COND_CODE_NM["key equals 'コード名リスト'"]

    COND_CODE_NM -->|true| CODE_NM_SLICE["key.substring(separaterPoint + 1)"]
    CODE_NM_SLICE --> CODE_NM_WILDCARD["key equals '*'"]
    CODE_NM_WILDCARD -->|true| RET_INTEGER_2["return Integer.class"]
    CODE_NM_WILDCARD -->|false| CODE_NM_PARSE_INT["Integer.valueOf(key)"]
    CODE_NM_PARSE_INT --> CODE_NM_PARSE_CATCH{NumberFormatException?}
    CODE_NM_PARSE_CATCH -->|yes| RET_NULL_5["return null"]
    CODE_NM_PARSE_CATCH -->|no| CODE_NM_CHECK_NULL["tmpIndexInt == null"]
    CODE_NM_CHECK_NULL -->|true| RET_NULL_6["return null"]
    CODE_NM_CHECK_NULL -->|false| CODE_NM_BOUNDS["tmpIndex >= cd_div_nm_list_list.size()"]
    CODE_NM_BOUNDS -->|true| RET_NULL_7["return null"]
    CODE_NM_BOUNDS -->|false| CODE_NM_DELEGATE["cd_div_nm_list_list.get(tmpIndex).typeModelData(subkey)"]

    COND_CODE_NM -->|false| RET_NULL_8["return null"]

    RET_NULL_1 --> END(["END"])
    RET_NULL_2 --> END
    RET_NULL_3 --> END
    RET_NULL_4 --> END
    RET_NULL_5 --> END
    RET_NULL_6 --> END
    RET_NULL_7 --> END
    RET_NULL_8 --> END
    RET_STRING_1 --> END
    RET_STRING_2 --> END
    RET_BOOL --> END
    RET_INTEGER_1 --> END
    RET_INTEGER_2 --> END
    NO_ADD_END --> RET_NULL_8
    CODE_DELEGATE --> END
    CODE_NM_DELEGATE --> END
```

## 3. Parameter Analysis

| No | Parameter Name | Type | Business Description |
|----|---------------|------|---------------------|
| 1 | `key` | `String` | The field identifier used to route type resolution. Can be a static field name (e.g., "追加字" for the Add Field group, "コードリスト" for the Code List array, "コード名リスト" for the Code Name List array), or a list-path key with an index suffix (e.g., "コードリスト/0", "コード名リスト/3"). The presence of a "/" separator indicates a list index lookup. |
| 2 | `subkey` | `String` | The sub-field specifier within a field. For the "追加字" (Add Field) group, valid values are "value" (the input field content), "enable" (whether the field is enabled), or "state" (display state). For list items, this delegates to the inner bean's typeModelData. Can be "*" to request the list count, or a type-specific subkey for nested fields. |

**Instance fields read:**

| Field | Type | Business Description |
|-------|------|---------------------|
| `cd_div_list_list` | `X33VDataTypeList` | The Code List (コードリスト) dynamic array backing — holds entries for code value lookups used in the screen's dropdown/select controls |
| `cd_div_nm_list_list` | `X33VDataTypeList` | The Code Name List (コード名リスト) dynamic array backing — holds entries for code name lookups used in label/description display columns |

## 4. CRUD Operations / Called Services

### Pre-computed evidence from code analysis graph:

| CRUD | SC / CBS | SC Code | Entity / DB | Operation Description |
|------|----------|---------|-------------|----------------------|
| - | `KKW01027SF02DBean.typeModelData` | KKW01027SF02DBean | - | Recursive call to typeModelData on list element beans (X33VDataTypeStringBean) |

**Analysis:**

| CRUD | SC / CBS | SC Code | Entity / DB | Operation Description |
|------|----------|---------|-------------|----------------------|
| - | `X33VDataTypeStringBean.typeModelData` | (Delegated via X33VDataTypeList) | (Inner list bean — no DB interaction) | Delegates type resolution for list index items. The method casts the list element at the parsed index to `X33VDataTypeStringBean` and calls its `typeModelData(subkey)` recursively. No direct database or SC calls are performed within this method or its delegation chain. |

This method is a **pure type resolution utility** with zero CRUD operations. It operates entirely on in-memory list structures (`cd_div_list_list`, `cd_div_nm_list_list`) and performs type introspection only.

## 5. Dependency Trace

Trace who calls this method and what this method ultimately calls.

| # | Caller (Screen/Batch) | Call Chain (Full Path to this Method) | Terminal (SC / CRUD / Entity) |
|---|----------------------|--------------------------------------|-------------------------------|
| 1 | KKW01027SF02DBean | `KKW01027SF02DBean.typeModelData` -> `KKW01027SF02DBean.typeModelData` (recursive on list elements) | No terminal DB/SC calls — pure type introspection |

**Notes:**
- The only documented caller is the class itself (`KKW01027SF02DBean`), which invokes this method during screen initialization or data binding setup.
- The method also calls itself recursively through delegation: when a list key is encountered (e.g., "コードリスト/0"), it extracts the list element (`X33VDataTypeStringBean`) and calls `typeModelData(subkey)` on that element, creating a two-level dispatch chain.
- No database tables or SC codes are accessed — this method is a pure in-memory type router.

## 6. Per-Branch Detail Blocks

**Block 1** — IF (null check) `(key == null || subkey == null)` (L355)

> If either parameter is null, return null immediately. This is an early-exit guard that prevents NPE during subsequent string operations.

| # | Type | Code |
|---|------|------|
| 1 | CHECK | `key == null || subkey == null` // Early exit for null input |
| 2 | RETURN | `return null` // No type info for null keys/subkeys |

---

**Block 2** — SET (delimiter position detection) `(L359)`

> Compute the position of the "/" separator in the key to enable list-index parsing for list-type fields.

| # | Type | Code |
|---|------|------|
| 1 | SET | `separaterPoint = key.indexOf("/")` // Index of the "/" delimiter in the key |

---

**Block 3** — ELSE-IF (key == "追加字") `[key.equals("追加字") == true]` (L362)

> Handle the "Add Field" (追加字) scalar field group. The Add Field is a dynamic input area where users can add new data entries. Each add field has three sub-properties: value (content), enable (enabled/disabled state), and state (display state).

**Block 3.1** — IF (subkey == "value") `(subkey.equalsIgnoreCase("value"))` (L364)

> Return `String.class` for the value sub-property of the Add Field.

| # | Type | Code |
|---|------|------|
| 1 | RETURN | `return String.class` // Field value is a string |

**Block 3.2** — ELSE-IF (subkey == "enable") `(subkey.equalsIgnoreCase("enable"))` (L367)

> Return `Boolean.class` for the enable sub-property of the Add Field.

| # | Type | Code |
|---|------|------|
| 1 | RETURN | `return Boolean.class` // Enabled/disabled is a boolean flag |

**Block 3.3** — ELSE-IF (subkey == "state") `[subkey.equalsIgnoreCase("state")]` (L370)

> subkeyが"state"の場合、ステータスを返す。 (If subkey is "state", return the status.)

| # | Type | Code |
|---|------|------|
| 1 | RETURN | `return String.class` // Display state is a string (e.g., "default", "error") |

---

**Block 4** — ELSE-IF (key == "コードリスト") `[key.equals("コードリスト") == true]` (L375)

> Handle the Code List (コードリスト) array field. This is a list of code values (e.g., dropdown options) used in the screen. The key includes an index (e.g., "コードリスト/0"), which is parsed to resolve the type of a specific list element.

**Block 4.1** — SET (index extraction) `(L377)`

> Extract the index portion of the key by removing the "コードリスト/" prefix using substring.

| # | Type | Code |
|---|------|------|
| 1 | SET | `key = key.substring(separaterPoint + 1)` // Extract index: "0" from "コードリスト/0" |

**Block 4.2** — IF (wildcard check) `(key.equals("*"))` (L379)

> If the key is "*", the caller wants the total count of items in the list.

| # | Type | Code |
|---|------|------|
| 1 | RETURN | `return Integer.class` // List count is an integer |

**Block 4.3** — TRY-CATCH (index parsing) `(L383–L389)`

> Attempt to parse the index as an integer. If the index is not a valid number (e.g., "abc"), return null.

| # | Type | Code |
|---|------|------|
| 1 | SET | `tmpIndexInt = Integer.valueOf(key)` // Parse index string to integer |
| 2 | CATCH | `NumberFormatException` → `return null` // Invalid index string, return null |

**Block 4.4** — IF (null check after parse) `(tmpIndexInt == null)` (L392)

> Defensive check — if parsing somehow resulted in null (though Integer.valueOf() should not return null), exit early.

| # | Type | Code |
|---|------|------|
| 1 | RETURN | `return null` // Null index after parse — exit early |

**Block 4.5** — SET (primitive conversion) `(L395)`

| # | Type | Code |
|---|------|------|
| 1 | SET | `tmpIndex = tmpIndexInt.intValue()` // Unbox Integer to int primitive |

**Block 4.6** — IF (bounds check) `(tmpIndex < 0 || tmpIndex >= cd_div_list_list.size())` (L397)

> If the index is out of the valid range (negative or beyond the list size), return null. The comment states: インデックス値がリスト個数-1を超えれば、ここでnullを返す。 (If the index value exceeds list count minus 1, return null here.)

| # | Type | Code |
|---|------|------|
| 1 | RETURN | `return null` // Index out of bounds — no such list item |

**Block 4.7** — CALL (delegate to list element) `(L399)`

> Cast the list element at the parsed index to `X33VDataTypeStringBean` and delegate type resolution. This creates a recursive dispatch chain: the outer bean routes to the inner list element, which resolves its own field types.

| # | Type | Code |
|---|------|------|
| 1 | CAST | `((X33VDataTypeStringBean)cd_div_list_list.get(tmpIndex))` // Cast list element to String data type bean |
| 2 | CALL | `.typeModelData(subkey)` // Delegate: resolve the subkey type within this list element |

---

**Block 5** — ELSE-IF (key == "コード名リスト") `[key.equals("コード名リスト") == true]` (L403)

> Handle the Code Name List (コード名リスト) array field. This is a list of code names/descriptions (e.g., dropdown labels) that mirrors the Code List. The processing is structurally identical to Block 4 but operates on `cd_div_nm_list_list` instead.

**Block 5.1** — SET (index extraction) `(L405)`

| # | Type | Code |
|---|------|------|
| 1 | SET | `key = key.substring(separaterPoint + 1)` // Extract index: "0" from "コード名リスト/0" |

**Block 5.2** — IF (wildcard check) `(key.equals("*"))` (L407)

| # | Type | Code |
|---|------|------|
| 1 | RETURN | `return Integer.class` // List count is an integer |

**Block 5.3** — TRY-CATCH (index parsing) `(L411–L417)`

| # | Type | Code |
|---|------|------|
| 1 | SET | `tmpIndexInt = Integer.valueOf(key)` // Parse index string to integer |
| 2 | CATCH | `NumberFormatException` → `return null` // Invalid index string, return null |

**Block 5.4** — IF (null check after parse) `(tmpIndexInt == null)` (L420)

| # | Type | Code |
|---|------|------|
| 1 | RETURN | `return null` // Null index after parse — exit early |

**Block 5.5** — SET (primitive conversion) `(L423)`

| # | Type | Code |
|---|------|------|
| 1 | SET | `tmpIndex = tmpIndexInt.intValue()` // Unbox Integer to int primitive |

**Block 5.6** — IF (bounds check) `(tmpIndex < 0 || tmpIndex >= cd_div_nm_list_list.size())` (L425)

> If the index is out of the valid range, return null. The comment states: インデックス値がリスト個数-1を超えれば、ここでnullを返す。 (If the index value exceeds list count minus 1, return null here.)

| # | Type | Code |
|---|------|------|
| 1 | RETURN | `return null` // Index out of bounds — no such list item |

**Block 5.7** — CALL (delegate to list element) `(L427)`

> Cast the list element at the parsed index to `X33VDataTypeStringBean` and delegate type resolution. This mirrors Block 4.7 but uses the code name list.

| # | Type | Code |
|---|------|------|
| 1 | CAST | `((X33VDataTypeStringBean)cd_div_nm_list_list.get(tmpIndex))` // Cast list element to String data type bean |
| 2 | CALL | `.typeModelData(subkey)` // Delegate: resolve the subkey type within this list element |

---

**Block 6** — ELSE (no match) `(L430)`

> No condition matched — return null. The comment states: 条件に合致するプロパティが存在しない場合は、nullを返す。 (If no property matches the condition, return null.)

| # | Type | Code |
|---|------|------|
| 1 | RETURN | `return null` // Unrecognized field — return null |

## 7. Glossary

| Term | Type | Business Meaning |
|------|------|------------------|
| `追加字` | Japanese field name | "Add Field" — a dynamic input field group that allows users to add new data entries. Each add field has value (content), enable (toggle), and state (display status) sub-properties. |
| `コードリスト` | Japanese field name | "Code List" — a dynamic array of code values (e.g., dropdown option values) managed in the screen. Stored in `cd_div_list_list`. |
| `コード名リスト` | Japanese field name | "Code Name List" — a dynamic array of code names/labels (e.g., dropdown option labels) that mirrors the Code List. Stored in `cd_div_nm_list_list`. |
| `cd_div_list_list` | Instance field | Code List (コードリスト) backing list — an `X33VDataTypeList` containing entries for code value data type management. |
| `cd_div_nm_list_list` | Instance field | Code Name List (コード名リスト) backing list — an `X33VDataTypeList` containing entries for code name data type management. |
| `index` | Instance field | Integer index used for temporary range checking during list element access. |
| `index_update` | Instance field | String field for tracking update status of the index-based field. |
| `index_value` | Instance field | String field storing the current value of the indexed field. Default is empty string. |
| `index_enabled` | Instance field | Boolean field indicating whether the indexed field is enabled. Default is false. |
| `index_state` | Instance field | String field storing the display state of the indexed field. Default is empty string. |
| `X33VDataTypeBeanInterface` | Interface | Interface contract requiring this bean to implement `typeModelData()` for type introspection in the X33V webview framework. |
| `X33VListedBeanInterface` | Interface | Interface contract marking this bean as a listed (array-capable) bean in the X33V framework. |
| `X33VDataTypeList` | Class | A typed list collection used to hold list items in the X33V webview data-binding system. |
| `X33VDataTypeStringBean` | Class | A list element bean representing a string data type entry in a list. Its `typeModelData()` method is called during delegation to resolve subfield types. |
| `X33V` | Framework acronym | The internal webview data-binding framework name used across the KKA15001SF screen family. |
| `*` (asterisk) | Special key value | Wildcard used to request the total count of items in a list field. Returns `Integer.class`. |
