# Business Logic — FUW00156SF02DBean.typeModelData() [113 LOC]

| Field | Value |
|-------|-------|
| Fully Qualified Name | `eo.web.webview.FUW00156SF.FUW00156SF02DBean` |
| Layer | Service / Data Bean (WebView layer — DBean) |
| Module | `FUW00156SF` (Package: `eo.web.webview.FUW00156SF`) |

## 1. Role

### FUW00156SF02DBean.typeModelData()

This method serves as the **type introspection dispatcher** for the survey (アンケート) data model within the FUW00156SF screen module. Its business responsibility is to determine the Java class type of a data field given a field name (`key`) and a sub-key (`subkey`), enabling the view layer to correctly render survey items — deciding whether a field should be treated as a string, boolean, integer, or delegated to a nested data-type bean.

The method implements a **routing/dispatch pattern**: it inspects the `key` parameter and branches into distinct processing paths for five static survey fields (`アンケート内容`, `アンケートチェック種類`, `アンケート番号`, `表示順序（アンケート内容）`, `ラジオボタン選択値`), each of which shares the same subkey contract of `value`/`enable`/`state`. When the `key` is `アンケート回答リスト` (Answer List), the method enters a more complex **recursive delegation path**: it parses a hierarchical key format (e.g., `アンケート回答リスト/0/プラン名`), validates the index, and delegates type resolution to the `typeModelData` method of the specific survey answer item at that index. This nested delegation is recursive, meaning the answer list items themselves can contain further nested typed fields.

In the larger system, this method is a shared utility within the DBean hierarchy. The parent class `FUW00156SFBean` overrides and extends this method to handle additional survey list types (`データ取得用アンケート番号`, `アンケートリスト`), making this method a component in a layered type-resolution chain that feeds the view layer's data binding for dynamic survey screens.

## 2. Processing Pattern (Detailed Business Logic)

```mermaid
flowchart TD
    START(["typeModelData key, subkey"])
    CHECK_NULL["key or subkey is null?"]
    RETURN_NULL1["Return null"]
    FIND_SLASH1["Find first / in key"]
    CHECK_KEY1{key equals アンケート内容}
    SUBKEY_CHECK1{subkey?}
    CASE_VALUE1["Return String.class"]
    CASE_ENABLE1["Return Boolean.class"]
    CASE_STATE1["Return String.class"]
    CHECK_KEY2{key equals アンケートチェック種類}
    SUBKEY_CHECK2{subkey?}
    CASE_VALUE2["Return String.class"]
    CASE_ENABLE2["Return Boolean.class"]
    CASE_STATE2["Return String.class"]
    CHECK_KEY3{key equals アンケート番号}
    SUBKEY_CHECK3{subkey?}
    CASE_VALUE3["Return String.class"]
    CASE_ENABLE3["Return Boolean.class"]
    CASE_STATE3["Return String.class"]
    CHECK_KEY4{key equals 表示順序（アンケート内容）}
    SUBKEY_CHECK4{subkey?}
    CASE_VALUE4["Return String.class"]
    CASE_ENABLE4["Return Boolean.class"]
    CASE_STATE4["Return String.class"]
    CHECK_KEY5{key equals ラジオボタン選択値}
    SUBKEY_CHECK5{subkey?}
    CASE_VALUE5["Return String.class"]
    CASE_ENABLE5["Return Boolean.class"]
    CASE_STATE5["Return String.class"]
    CHECK_KEY6{key equals アンケート回答リスト}
    SUBSTR_REMAIN["Get keyRemain after first /"]
    CHECK_ASTERISK{keyRemain equals *}
    RETURN_INTEGER1["Return Integer.class"]
    FIND_SLASH2["Find next / in keyRemain"]
    CHECK_SLASH2{separator not found}
    RETURN_NULL2["Return null"]
    EXTRACT_INDEX["Extract index substring"]
    PARSE_INT_TRY["Integer.valueOf index"]
    CATCH_NFE{NumberFormatException}
    RETURN_NULL3["Return null"]
    CHECK_BOUNDS{index out of range}
    RETURN_NULL4["Return null"]
    EXTRACT_NESTED_KEY["key = keyRemain after second /"]
    DELEGATE["Delegate to enquete_answer_list_list.get(index)"]
    NO_MATCH["Return null"]
    END_NODE["End"]
    START --> CHECK_NULL
    CHECK_NULL -->|Yes| RETURN_NULL1
    CHECK_NULL -->|No| FIND_SLASH1
    FIND_SLASH1 --> CHECK_KEY1
    CHECK_KEY1 -->|Yes| SUBKEY_CHECK1
    CHECK_KEY1 -->|No| CHECK_KEY2
    CHECK_KEY2 -->|Yes| SUBKEY_CHECK2
    CHECK_KEY2 -->|No| CHECK_KEY3
    CHECK_KEY3 -->|Yes| SUBKEY_CHECK3
    CHECK_KEY3 -->|No| CHECK_KEY4
    CHECK_KEY4 -->|Yes| SUBKEY_CHECK4
    CHECK_KEY4 -->|No| CHECK_KEY5
    CHECK_KEY5 -->|Yes| SUBKEY_CHECK5
    CHECK_KEY5 -->|No| CHECK_KEY6
    CHECK_KEY6 -->|Yes| SUBSTR_REMAIN
    CHECK_KEY6 -->|No| NO_MATCH
    SUBKEY_CHECK1 -->|value| CASE_VALUE1
    SUBKEY_CHECK1 -->|enable| CASE_ENABLE1
    SUBKEY_CHECK1 -->|state| CASE_STATE1
    CASE_VALUE1 --> END_NODE
    CASE_ENABLE1 --> END_NODE
    CASE_STATE1 --> END_NODE
    SUBKEY_CHECK2 -->|value| CASE_VALUE2
    SUBKEY_CHECK2 -->|enable| CASE_ENABLE2
    SUBKEY_CHECK2 -->|state| CASE_STATE2
    CASE_VALUE2 --> END_NODE
    CASE_ENABLE2 --> END_NODE
    CASE_STATE2 --> END_NODE
    SUBKEY_CHECK3 -->|value| CASE_VALUE3
    SUBKEY_CHECK3 -->|enable| CASE_ENABLE3
    SUBKEY_CHECK3 -->|state| CASE_STATE3
    CASE_VALUE3 --> END_NODE
    CASE_ENABLE3 --> END_NODE
    CASE_STATE3 --> END_NODE
    SUBKEY_CHECK4 -->|value| CASE_VALUE4
    SUBKEY_CHECK4 -->|enable| CASE_ENABLE4
    SUBKEY_CHECK4 -->|state| CASE_STATE4
    CASE_VALUE4 --> END_NODE
    CASE_ENABLE4 --> END_NODE
    CASE_STATE4 --> END_NODE
    SUBKEY_CHECK5 -->|value| CASE_VALUE5
    SUBKEY_CHECK5 -->|enable| CASE_ENABLE5
    SUBKEY_CHECK5 -->|state| CASE_STATE5
    CASE_VALUE5 --> END_NODE
    CASE_ENABLE5 --> END_NODE
    CASE_STATE5 --> END_NODE
    SUBSTR_REMAIN --> CHECK_ASTERISK
    CHECK_ASTERISK -->|Yes| RETURN_INTEGER1
    CHECK_ASTERISK -->|No| FIND_SLASH2
    RETURN_INTEGER1 --> END_NODE
    FIND_SLASH2 --> CHECK_SLASH2
    CHECK_SLASH2 -->|Yes| RETURN_NULL2
    CHECK_SLASH2 -->|No| EXTRACT_INDEX
    RETURN_NULL2 --> END_NODE
    EXTRACT_INDEX --> PARSE_INT_TRY
    PARSE_INT_TRY --> CATCH_NFE
    CATCH_NFE -->|Yes| RETURN_NULL3
    CATCH_NFE -->|No| CHECK_BOUNDS
    RETURN_NULL3 --> END_NODE
    CHECK_BOUNDS -->|Out of range| RETURN_NULL4
    CHECK_BOUNDS -->|Valid| EXTRACT_NESTED_KEY
    RETURN_NULL4 --> END_NODE
    EXTRACT_NESTED_KEY --> DELEGATE
    DELEGATE --> END_NODE
```

**Constant Resolution:** This method uses no external constant classes. All key values are **hard-coded Japanese strings** defined in `FUW00156SFConst.java` (e.g., `ENQUETE_ANSWER_LIST = "アンケート回答リスト"`). The subkey values (`value`, `enable`, `state`) and the wildcard (`*`) are also literal strings.

## 3. Parameter Analysis

| No | Parameter Name | Type | Business Description |
|----|---------------|------|---------------------|
| 1 | `key` | `String` | The field name / item identifier for a survey element. It may reference a static survey field (e.g., "アンケート内容" = Survey Content), or a hierarchical path for repeated/nested items in the answer list (e.g., "アンケート回答リスト/0/プラン名" = Answer List Item 0 / Plan Name). In the answer list path, the key format is `fieldName/index/fieldName...`. |
| 2 | `subkey` | `String` | The property sub-identifier within a field. For static survey fields, it specifies the property: `value` (the data value), `enable` (whether the field is editable/active), or `state` (the display state, e.g., visible/disabled). For nested delegation, it is passed through to the inner item's type model resolution. |

**Instance fields read:**

| Field | Type | Business Description |
|-------|------|---------------------|
| `enquete_answer_list_list` | `X33VDataTypeList` | A list of survey answer items, each implementing `X33VDataTypeBeanInterface`. Represents a dynamic, repeated list of survey responses where each element is itself a typed data bean. Used when `key` references "アンケート回答リスト". |

## 4. CRUD Operations / Called Services

| CRUD | SC / CBS | SC Code | Entity / DB | Operation Description |
|------|----------|---------|-------------|----------------------|
| - | `FUW00156SF02DBean.typeModelData` | - | - | Recursive delegation: calls `typeModelData(key, subkey)` on a nested `X33VDataTypeBeanInterface` item within the answer list (line 650). This is a type query, not a database operation. |

This method is a **pure type introspection utility** — it does not perform any database CRUD operations, nor does it call any service components (SCs) or CBS endpoints. All operations are in-memory type lookups, string parsing, list access via `get(index)`, and recursive delegation to nested bean type resolution.

## 5. Dependency Trace

| # | Caller (Screen/Batch) | Call Chain (Full Path to this Method) | Terminal (SC / CRUD / Entity) |
|---|----------------------|--------------------------------------|-------------------------------|
| 1 | `FUW00156SFBean` (parent DBean) | `FUW00156SFBean.typeModelData(gamenId, key, subkey)` -> `FUW00156SFBean.typeModelData(key, subkey)` -> delegates to `FUW00156SF02DBean.typeModelData(key, subkey)` (line 1203) | None — type introspection only |
| 2 | `FUW00156SF06DBean`, `FUW00156SF01DBean`, `FUW00156SF05DBean`, `FUW00156SF04DBean`, `FUW00156SF03DBean`, `FUW00156SF07DBean` | Same signature (`typeModelData(key, subkey)`) — independent overrides in sibling DBeans. Each has its own survey field type mappings. | None — type introspection only |
| 3 | `FUW00156SFBean` (nested delegation) | `FUW00156SFBean.typeModelData()` delegates to `enquete_answer_list_list.get(i).typeModelData(key, subkey)` which invokes the same interface method on answer list items | None — type introspection only |

**Notes:**
- The pre-computed caller analysis confirms that direct callers exist only within the same class (`FUW00156SF02DBean.typeModelData()` — self-referencing via delegation).
- The parent `FUW00156SFBean` calls `super.typeModelData(key, subkey)` from its own `typeModelData(key, subkey)` implementation (line 1202-1203) as part of a chain: first it handles shared-info and nested survey list types in the parent, and falls through to the subclass (`FUW00156SF02DBean`) for the remaining survey fields.
- Screen classes for module FUW00156SF (e.g., KKSV0004) would invoke this indirectly through the DBean hierarchy via view data binding.

## 6. Per-Branch Detail Blocks

**Block 1** — [IF-NULL] (L548)

> Early null-guard: returns null if either parameter is null. Prevents NPE on downstream string operations.

| # | Type | Code |
|---|------|------|
| 1 | IF | `key == null \|\| subkey == null` |
| 2 | RETURN | `return null;` // early exit on null input [-> null] |

**Block 2** — [EXTRACTION] (L551)

| # | Type | Code |
|---|------|------|
| 1 | SET | `int separaterPoint = key.indexOf("/")` // find first separator position in key [-> index of "/" or -1] |

**Block 3** — [IF/ELSE-IF chain: static survey field "アンケート内容"] (L554)
Key: `"アンケート内容"` = Survey Content [ENQUETE_CONTENT]

| # | Type | Code |
|---|------|------|
| 1 | IF | `key.equals("アンケート内容")` |
| 2 | ELSE-IF | `subkey.equalsIgnoreCase("value")` [L556] |
| 3 | RETURN | `return String.class;` // the value property is a String |
| 4 | ELSE-IF | `subkey.equalsIgnoreCase("enable")` [L558] |
| 5 | RETURN | `return Boolean.class;` // the enabled/disabled state is a Boolean |
| 6 | ELSE-IF | `subkey.equalsIgnoreCase("state")` [L560] // comment: "If subkey is 'state', return the status." |
| 7 | RETURN | `return String.class;` // the state display status is a String |

**Block 4** — [ELSE-IF: static survey field "アンケートチェック種類"] (L564)
Key: `"アンケートチェック種類"` = Survey Check Type [ENQUETE_CHK_SBT]

| # | Type | Code |
|---|------|------|
| 1 | ELSE-IF | `key.equals("アンケートチェック種類")` |
| 2 | ELSE-IF | `subkey.equalsIgnoreCase("value")` [L566] |
| 3 | RETURN | `return String.class;` |
| 4 | ELSE-IF | `subkey.equalsIgnoreCase("enable")` [L568] |
| 5 | RETURN | `return Boolean.class;` |
| 6 | ELSE-IF | `subkey.equalsIgnoreCase("state")` [L570] |
| 7 | RETURN | `return String.class;` |

**Block 5** — [ELSE-IF: static survey field "アンケート番号"] (L574)
Key: `"アンケート番号"` = Survey Number [ENQUETE_CONTENT_NO]

| # | Type | Code |
|---|------|------|
| 1 | ELSE-IF | `key.equals("アンケート番号")` |
| 2 | ELSE-IF | `subkey.equalsIgnoreCase("value")` [L576] |
| 3 | RETURN | `return String.class;` |
| 4 | ELSE-IF | `subkey.equalsIgnoreCase("enable")` [L578] |
| 5 | RETURN | `return Boolean.class;` |
| 6 | ELSE-IF | `subkey.equalsIgnoreCase("state")` [L580] |
| 7 | RETURN | `return String.class;` |

**Block 6** — [ELSE-IF: static survey field "表示順序（アンケート内容）"] (L584)
Key: `"表示順序（アンケート内容）"` = Display Order (Survey Content) [DSP_JUN_CONTENT]

| # | Type | Code |
|---|------|------|
| 1 | ELSE-IF | `key.equals("表示順序（アンケート内容）")` |
| 2 | ELSE-IF | `subkey.equalsIgnoreCase("value")` [L586] |
| 3 | RETURN | `return String.class;` |
| 4 | ELSE-IF | `subkey.equalsIgnoreCase("enable")` [L588] |
| 5 | RETURN | `return Boolean.class;` |
| 6 | ELSE-IF | `subkey.equalsIgnoreCase("state")` [L590] |
| 7 | RETURN | `return String.class;` |

**Block 7** — [ELSE-IF: static survey field "ラジオボタン選択値"] (L594)
Key: `"ラジオボタン選択値"` = Radio Button Selection Value [RADIO_VALUE]

| # | Type | Code |
|---|------|------|
| 1 | ELSE-IF | `key.equals("ラジオボタン選択値")` |
| 2 | ELSE-IF | `subkey.equalsIgnoreCase("value")` [L596] |
| 3 | RETURN | `return String.class;` |
| 4 | ELSE-IF | `subkey.equalsIgnoreCase("enable")` [L598] |
| 5 | RETURN | `return Boolean.class;` |
| 6 | ELSE-IF | `subkey.equalsIgnoreCase("state")` [L600] |
| 7 | RETURN | `return String.class;` |

**Block 8** — [ELSE-IF: nested survey answer list "アンケート回答リスト"] (L604)
Key: `"アンケート回答リスト"` = Survey Answer List [ENQUETE_ANSWER_LIST] — the most complex branch.

**Block 8.1** — [EXTRACTION] (L607)
> Get the portion of the key after the first "/" to handle hierarchical indexing.

| # | Type | Code |
|---|------|------|
| 1 | SET | `String keyRemain = key.substring(separaterPoint + 1)` // extract substring after first "/" [-> e.g., "0/プラン名" from "アンケート回答リスト/0/プラン名"] |

**Block 8.2** — [IF: wildcard index check] (L609)
> If the index placeholder is "*", return the type for list element count.

| # | Type | Code |
|---|------|------|
| 1 | IF | `keyRemain.equals("*")` |
| 2 | RETURN | `return Integer.class;` // the count of list elements is an Integer |

**Block 8.3** — [EXTRACTION & VALIDATION] (L612)
> Find the second "/" separator to locate the index substring.

| # | Type | Code |
|---|------|------|
| 1 | SET | `separaterPoint = keyRemain.indexOf("/")` // find the next separator |
| 2 | IF | `separaterPoint <= 0` [L614] // separator not found, or invalid format |
| 3 | RETURN | `return null;` // comment: "If separator not found or invalid, return null here." |

**Block 8.4** — [INDEX EXTRACTION] (L617)

| # | Type | Code |
|---|------|------|
| 1 | SET | `key = keyRemain.substring(0, separaterPoint)` // extract the index value as a string |

**Block 8.5** — [TRY-CATCH: index parsing] (L620-L625)
> Attempt to parse the index string as an integer.

| # | Type | Code |
|---|------|------|
| 1 | SET | `Integer tmpIndexInt = null` |
| 2 | TRY | `tmpIndexInt = Integer.valueOf(key)` [L622] |
| 3 | CATCH | `NumberFormatException e` [L624] // comment: "If index is not a numeric string, return null here." |
| 4 | RETURN | `return null;` |

**Block 8.6** — [NULL CHECK] (L627)

| # | Type | Code |
|---|------|------|
| 1 | IF | `tmpIndexInt == null` |
| 2 | RETURN | `return null;` |

**Block 8.7** — [BOUNDS CHECK] (L630)

| # | Type | Code |
|---|------|------|
| 1 | SET | `int tmpIndex = tmpIndexInt.intValue()` |
| 2 | IF | `tmpIndex < 0 \|\| tmpIndex >= enquete_answer_list_list.size()` [L630] // comment: "If index exceeds list size-1, return null here." |
| 3 | RETURN | `return null;` |

**Block 8.8** — [NESTED KEY EXTRACTION & DELEGATION] (L633-L650)
> Generate the nested field name and delegate type resolution to the answer list item.

| # | Type | Code |
|---|------|------|
| 1 | SET | `key = keyRemain.substring(separaterPoint + 1)` // extract nested field name after index [-> e.g., "プラン名"] |
| 2 | EXEC | `((X33VDataTypeBeanInterface)enquete_answer_list_list.get(tmpIndex))` // cast list item to interface |
| 3 | CALL | `.typeModelData(key, subkey)` // delegate to nested item's type resolution [-> comment: "Generate item name and return typeModelData result from data-type view"] |
| 4 | RETURN | `return ...;` |

**Block 9** — [FINAL DEFAULT RETURN] (L654)
> No matching key found — return null.

| # | Type | Code |
|---|------|------|
| 1 | RETURN | `return null;` // comment: "If no matching property, return null." |

## 7. Glossary

| Term | Type | Business Meaning |
|------|------|------------------|
| `アンケート内容` | Japanese field | Survey Content — the main text/content of a survey question item |
| `アンケートチェック種類` | Japanese field | Survey Check Type — the type of check box / selection control used in the survey |
| `アンケート番号` | Japanese field | Survey Number — the sequential number / ID of a survey question |
| `表示順序（アンケート内容）` | Japanese field | Display Order (Survey Content) — the presentation order of survey items on the screen |
| `ラジオボタン選択値` | Japanese field | Radio Button Selection Value — the selected value from a radio button group |
| `アンケート回答リスト` | Japanese field | Survey Answer List — a dynamic, repeated list of survey response items (each item is itself a typed data bean) |
| `value` | Subkey | The data value of a survey field |
| `enable` | Subkey | Whether the survey field is enabled/editable (Boolean) |
| `state` | Subkey | The display state of the survey field (e.g., visible, hidden, disabled) |
| `*` | Literal | Wildcard placeholder for index — used to request the element count type (Integer.class) |
| `enquete_answer_list_list` | Field | The list instance holding survey answer items, each implementing `X33VDataTypeBeanInterface` |
| `X33VDataTypeBeanInterface` | Interface | Base interface for data-type beans that provide `typeModelData` and `loadModelData` methods |
| `X33VDataTypeList` | Class | A list container for objects implementing `X33VDataTypeBeanInterface` |
| DBean | Acronym | Data Bean — a view-layer bean that manages data type information and model binding for a screen |
| `FUW00156SF` | Module | Survey / questionnaire screen module (F = Front-end, SF = Screen Function) |
| `key` | Parameter | Field identifier used to look up type information |
| `subkey` | Parameter | Property identifier within a field (value, enable, state) |
| `separaterPoint` | Local variable | Index position of the "/" separator character used to parse hierarchical keys |
| `keyRemain` | Local variable | The substring of the key after the first separator, used for index-based nested access |
| `tmpIndex` | Local variable | Parsed integer index into the `enquete_answer_list_list` for the answer list branch |
