# KKW01037SFBean

## Purpose

`KKW01037SFBean` is a **presentation-model (form bean) / data-holder** for a single web page in an X33 framework-based Java web application. It aggregates every field, list, and display attribute that the page `KKW010370PJP` needs -- contract IDs, customer referral data, service-agreement lists, and popup-mode state -- and exposes a generic `loadModelData` / `storeModelData` / `typeModelData` API so the framework's MVC controller can read and write page data through a unified key-based routing mechanism.

## Design

This class plays three architectural roles simultaneously:

1. **Model-backing form bean** -- It holds both the *input data* (e.g. customer name, phone number) and *UI metadata* (enable/disable state, update flags, display state) for every form element.
2. **Indexable data router** -- Its three `*ModelData` methods implement a string-key dispatcher that parses human-readable Japanese labels (e.g. "紹介者契約者名") and sub-keys (e.g. `"value"`, `"enable"`, `"state"`) into the appropriate Java field or child bean, supporting nested list access via slash-delimited paths (e.g. `"サービス契約一覧リスト/0/fieldName"`).
3. **List-data manager** -- It implements `X33VListedBeanInterface` and `X31CBaseBean` to provide CRUD-style list operations (`addListDataInstance`, `removeElementFromListData`, `clearListDataInstance`) for two repeatable sections on the page.

```mermaid
classDiagram
    class KKW01037SFBean {
        +String hktg_sysid_value
        +String hktg_sysid_state
        +String hktg_svc_kei_no_value
        +String hktg_svc_kei_no_state
        +String hi_cust_nm_value
        +Boolean hi_cust_nm_enabled
        +String hi_cust_nm_state
        +String hi_telno_value
        +Boolean hi_telno_enabled
        +String hi_telno_state
        +String hi_sysid_value
        +Boolean hi_sysid_enabled
        +String hi_sysid_state
        +X33VDataTypeList svc_kei_list_list
        +X33VDataTypeList cust_kei_hktgi_list_list
        +String popup_mode_value
        +String popup_mode_state
        +getHktg_sysid_value() String
        +setHktg_sysid_value(String) void
        +getHi_cust_nm_value() String
        +getJsflist_typelist_svc_kei_list() ArrayList~SelectItem~
        +loadModelData(String, String) Object
        +storeModelData(String, String, Object) void
        +typeModelData(String, String) Class~?~
        +listKoumokuIds(String) ArrayList~String~
        +addListDataInstance(String) int
        +removeElementFromListData(String, int) void
        +clearListDataInstance(String) void
    }
    class X33VViewBaseBean {
        <<abstract>>
        +loadCommonInfoData() Object
        +storeCommonInfoData() void
        +typeCommonInfoData() Class~?~
        +listKoumokuIds() ArrayList~String~
    }
    class X33VListedBeanInterface {
        <<interface>>
        +listServiceFormIds() String[]
    }
    class X31CBaseBean {
        <<interface>>
        +loadModelData() Object
        +storeModelData() void
        +typeModelData() Class~?~
        +listKoumokuIds() ArrayList~String~
        +addListDataInstance() int
        +removeElementFromListData() void
        +clearListDataInstance() void
    }
    class X33VDataTypeList {
        +add(Object) void
        +get(int) Object
        +remove(int) void
        +clear() void
        +size() int
        +getMaxElementCnt() int
    }
    class KKW01037SF01DBean {
        <<data type bean>>
    }
    class KKW01037SF02DBean {
        <<data type bean>>
    }

    KKW01037SFBean --|> X33VViewBaseBean
    KKW01037SFBean ..|> X33VListedBeanInterface
    KKW01037SFBean ..|> X31CBaseBean
    KKW01037SFBean --> X33VDataTypeList : uses
    X33VDataTypeList --> KKW01037SF01DBean : holds
    X33VDataTypeList --> KKW01037SF02DBean : holds
```

### Class diagram (structural overview)

```mermaid
flowchart TD
    subgraph KKW01037SFBean["KKW01037SFBean"]
        direction TB
        HKTG_SYSID["hktg_sysid<br/>（継承システムID）"]
        HKTG_SVC["hktg_svc_kei_no<br/>（継承お客様番号）"]
        HI_CUST["hi_cust_nm<br/>（紹介者契約者名）"]
        HI_TELNO["hi_telno<br/>（紹介者電話番号）"]
        HI_SYSID["hi_sysid<br/>（紹介者システムID）"]
        SVC_LIST["svc_kei_list_list<br/>サービス契約一覧リスト<br/>X33VDataTypeList<KKW01037SF01DBean>"]
        CUST_LIST["cust_kei_hktgi_list_list<br/>顧客契約引継リスト<br/>X33VDataTypeList<KKW01037SF02DBean>"]
        POPUP["popup_mode<br/>（ポップアップモード）"]
    end

    KKW01037SFBean -->|holds| SVC_LIST
    KKW01037SFBean -->|holds| CUST_LIST
    SVC_LIST -->|contains items of| SVC01["KKW01037SF01DBean"]
    CUST_LIST -->|contains items of| SVC02["KKW01037SF02DBean"]

    style KKW01037SFBean fill:#e1f5fe
    style SVC01 fill:#f3e5f5
    style SVC02 fill:#f3e5f5
```

## Field Inventory

The bean declares 20 protected fields, grouped into four categories.

### Single-value fields (scalar properties)

| Field | Java Type | Default | Sub-keys exposed |
|---|---|---|---|
| `hktg_sysid_value` | `String` | `""` | `"value"`, `"state"` |
| `hktg_sysid_state` | `String` | `""` | (display state) |
| `hktg_svc_kei_no_value` | `String` | `""` | `"value"`, `"state"` |
| `hktg_svc_kei_no_state` | `String` | `""` | (display state) |
| `hi_cust_nm_value` | `String` | `""` | `"value"`, `"enable"`, `"state"` |
| `hi_cust_nm_enabled` | `Boolean` | `false` | (field enabled?) |
| `hi_cust_nm_state` | `String` | `""` | (display state) |
| `hi_telno_value` | `String` | `""` | `"value"`, `"enable"`, `"state"` |
| `hi_telno_enabled` | `Boolean` | `true` | (field enabled?) |
| `hi_sysid_value` | `String` | `""` | `"value"`, `"enable"`, `"state"` |
| `hi_sysid_enabled` | `Boolean` | `true` | (field enabled?) |
| `popup_mode_value` | `String` | `""` | `"value"`, `"state"` |

Each scalar property also has a corresponding `_update` field (`hktg_sysid_update`, `hi_cust_nm_update`, etc.) whose setter and getter exist but whose runtime usage is not exercised within this bean; they are likely used by the framework's change-detection mechanism.

### List fields (repeatable sections)

| Field | Java Type | Initial Content |
|---|---|---|
| `svc_kei_list_list` | `X33VDataTypeList` | New empty list (initialized in constructor) |
| `cust_kei_hktgi_list_list` | `X33VDataTypeList` | Initialized with 1 `KKW01037SF02DBean` instance |

The `cust_kei_hktgi_list_list` list starts with one pre-instantiated element (max element count of 0 or unbounded), while `svc_kei_list_list` starts empty and grows only when `addListDataInstance("サービス契約一覧リスト")` is called.

## Key Methods

### `loadModelData(String key, String subkey) -> Object`

The core routing method. Given a hierarchical string key and a sub-key, it returns the corresponding value.

**Key formats recognized:**

| Key format | Meaning | Example |
|---|---|---|
| `項目名` | Simple field (no repeat index) | `"紹介者契約者名"` |
| `項目名/インデックス/フィールド名` | Nested list element access | `"サービス契約一覧リスト/0/値"` |
| `項目名/*` | Get list element count | `"サービス契約一覧リスト/*"` |
| `//インデックス/項目名` | Shared/common-info bean access | `"//0/共通フィールド"` |

**Sub-keys and their mappings per field group:**

| Field group (keyElement) | sub-key | Returns |
|---|---|---|
| `継承システムID` | `"value"` | `hktg_sysid_value` |
| `継承システムID` | `"state"` | `hktg_sysid_state` |
| `継承お客様番号` | `"value"` | `hktg_svc_kei_no_value` |
| `継承お客様番号` | `"state"` | `hktg_svc_kei_no_state` |
| `紹介者契約者名` | `"value"` | `hi_cust_nm_value` |
| `紹介者契約者名` | `"enable"` | `hi_cust_nm_enabled` |
| `紹介者契約者名` | `"state"` | `hi_cust_nm_state` |
| `紹介者電話番号` | `"value"` | `hi_telno_value` |
| `紹介者電話番号` | `"enable"` | `hi_telno_enabled` |
| `紹介者電話番号` | `"state"` | `hi_telno_state` |
| `紹介者システムID` | `"value"` | `hi_sysid_value` |
| `紹介者システムID` | `"enable"` | `hi_sysid_enabled` |
| `紹介者システムID` | `"state"` | `hi_sysid_state` |
| `サービス契約一覧リスト` | `"0/fieldName"` | Delegates to `KKW01037SF01DBean` |
| `サービス契約一覧リスト` | `"*"` | List size as `Integer` |
| `顧客契約引継リスト` | `"0/fieldName"` | Delegates to `KKW01037SF02DBean` |
| `顧客契約引継リスト` | `"*"` | List size as `Integer` |
| `ポップアップモード` | `"value"` | `popup_mode_value` |
| `ポップアップモード` | `"state"` | `popup_mode_state` |

**Side effects:** None (pure read).

**Error handling:** Returns `null` for unrecognized keys, out-of-range indices, or malformed paths -- never throws.

### `storeModelData(String key, String subkey, Object in_value)` + overloads

The write counterpart to `loadModelData`. The three overloads are:

1. `storeModelData(String key, String subkey, Object in_value, boolean isSetAsString)` -- full dispatch with a type-flag (used when writing to `Long` properties as strings).
2. `storeModelData(String key, String subkey, Object in_value)` -- delegates to overload 1 with `isSetAsString = false`.
3. `storeModelData(String gamenId, String key, String subkey, Object in_value)` -- accepts an extra `gamenId` parameter (unused, for compatibility) and delegates to overload 2.

**Behavior:** Parses the same key-routing scheme as `loadModelData` and invokes the matching setter. For list fields, the value is delegated down to the child bean (`KKW01037SF01DBean` or `KKW01037SF02DBean`) at the specified index.

**Side effects:** Mutates the bean's fields (or child bean fields).

### `typeModelData(String key, String subkey) -> Class<?>`

Returns the Java type class for a given key/sub-key combination, used by the framework for type-safe data binding.

| Key + sub-key | Return type |
|---|---|
| `継承システムID` + `"value"` / `"state"` | `String.class` |
| `紹介者契約者名` + `"value"` | `String.class` |
| `紹介者契約者名` + `"enable"` | `Boolean.class` |
| `サービス契約一覧リスト` + `"*"` | `Integer.class` |
| `サービス契約一覧リスト` + `"0/fieldName"` | Delegates to `KKW01037SF01DBean.typeModelData()` |
| All other unrecognized combinations | `null` |

### `listKoumokuIds(String key) -> ArrayList<String>`

Returns a list of field names for a given key. If `key` is `null`, returns all top-level field names for the page:

```
継承システムID, 継承お客様番号, 紹介者契約者名, 紹介者電話番号,
紹介者システムID, サービス契約一覧リスト, 顧客契約引継リスト, ポップアップモード
```

If `key` matches a repeat-list name, it delegates to the child bean's `listKoumokuIds()` static method (`KKW01037SF01DBean` or `KKW01037SF02DBean`).

### `addListDataInstance(String key) -> int`

Appends a new element to a repeatable list and returns the new element's index.

| Key | Creates instance of | List initialized? |
|---|---|---|
| `サービス契約一覧リスト` | `KKW01037SF01DBean` | Yes, if `null` |
| `顧客契約引継リスト` | `KKW01037SF02DBean` | Yes, if `null` (creates initial list with 1 element) |

**Constraints:** `顧客契約引継リスト` respects `getMaxElementCnt()` -- if the list has reached its maximum, it throws an `X33SException` via `super.createExceptionForX31Method(ERRS_CANNOT_ADD_REPEATITEM)`.

**Returns:** The new element's index, or `-1` if the key is unrecognized or `null`.

### `removeElementFromListData(String key, int index) -> void`

Removes the element at `index` from the specified list. Bounds-checked (indices outside `[0, size)` are silently ignored). For shared-info beans (key starting with `//`), delegates to the superclass.

### `clearListDataInstance(String key) -> void`

Clears all elements from a repeatable list by calling `list.clear()`. Also delegates to the superclass for shared-info beans.

### `getJsflist_typelist_svc_kei_list() -> ArrayList<SelectItem>`

Converts the `svc_kei_list_list` into a JSF `SelectItem` list for rendering as a dropdown or radio-button group. Each item's value is the index (stringified), and its label is loaded via the child bean's `loadModelData("サービス契約一覧リスト", "value")`.

### `getJsflist_typelist_cust_kei_hktgi_list() -> ArrayList<SelectItem>`

Same pattern as above but for `cust_kei_hktgi_list_list`, delegating to `KKW01037SF02DBean` with sub-key `"顧客契約引継リスト"`.

### `listServiceFormIds() -> String[]`

A stub implementation that always returns `null`. Part of the `X33VListedBeanInterface` contract, likely intended for page-listing features that are not used on this page.

### Constructor

```java
public KKW01037SFBean() {
    svc_kei_list_list = new X33VDataTypeList();
    cust_kei_hktgi_list_list = new X33VDataTypeList(1);
    for(int i = 0; i < 1; i++) {
        KKW01037SF02DBean tmpBean = new KKW01037SF02DBean();
        cust_kei_hktgi_list_list.add(tmpBean);
    }
}
```

Always creates the customer-contract list with exactly one pre-populated row.

## Relationships

### Who uses this class (inbound)

| Consumer | How |
|---|---|
| `KKW010370PJP.jsp` | The JSP page that renders the form -- binds form fields to bean properties via EL or JSTL. |
| `WEBGAMEN_KKW010370PJP.xml` | An XML mapping file (likely Struts/JSF config) that declares this bean as a page-scoped or session-scoped model. |

### What this class depends on (outbound)

| Dependency | Role |
|---|---|
| `X33VViewBaseBean` | Abstract base class providing common-info bean routing, exception helpers, and shared `load/store` infrastructure. |
| `X33VListedBeanInterface` | Marker interface requiring `listServiceFormIds()` implementation. |
| `X31CBaseBean` | Core interface declaring the `*ModelData` and `*ListData` method signatures. |
| `X33VDataTypeList` | Generic list container holding child data-type beans. |
| `X33VDataTypeBeanInterface` | Interface implemented by child beans, allowing delegation of `loadModelData`/`storeModelData`/`typeModelData`. |
| `KKW01037SF01DBean` | Child bean type for "service contract list" items. |
| `KKW01037SF02DBean` | Child bean type for "customer contract succession list" items. |
| `javax.servlet.jsp.tagext.SelectItem` | JSF UI component helper for select-many/select-one renderers. |
| `Serializable` | Java marker interface indicating the bean is serializable across HTTP sessions. |

### Interaction sequence

```mermaid
sequenceDiagram
    participant JSP as JSP Page
    participant MVC as Controller
    participant BEAN as KKW01037SFBean
    participant VIEW as X33VViewBaseBean

    JSP->>MVC: Submit form (KKW010370PJP)
    MVC->>BEAN: storeModelData("紹介者契約者名", "value", "John")
    BEAN->>BEAN: setHi_cust_nm_value("John")
    note right of BEAN: Dispatches to correct field via key routing

    MVC->>BEAN: storeModelData("サービス契約一覧リスト", "0/fieldName", "data")
    BEAN->>BEAN: svc_kei_list_list[0].storeModelData()
    note right of BEAN: Delegates to child bean at index

    MVC->>BEAN: loadModelData("紹介者電話番号", "value")
    BEAN->>BEAN: getHi_telno_value()
    BEAN-->>MVC: Returns String value

    MVC->>BEAN: addListDataInstance("顧客契約引継リスト")
    BEAN->>BEAN: new KKW01037SF02DBean()
    BEAN->>BEAN: cust_kei_hktgi_list_list.add(bean)
    BEAN-->>MVC: Returns index

    MVC->>BEAN: removeElementFromListData("サービス契約一覧リスト", 2)
    BEAN->>BEAN: svc_kei_list_list.remove(2)
```

## Usage Example

A typical usage pattern (as orchestrated by the X33 framework's MVC controller):

**1. Page load -- populate the form:**
```java
KKW01037SFBean bean = new KKW01037SFBean();

// Load data from a database or business service
// Then set the fields:
bean.setHi_cust_nm_value("田中 太郎");
bean.setHi_telno_enabled(true);
bean.setHi_sysid_value("SYS001");
bean.setPopup_mode_value("edit");
```

**2. Page load -- build dropdown lists:**
```java
// Add rows to the service contract list
bean.addListDataInstance("サービス契約一覧リスト");
bean.addListDataInstance("サービス契約一覧リスト");

// Convert to JSF-selectable items
ArrayList<SelectItem> svcItems = bean.getJsflist_typelist_svc_kei_list();
```

**3. Form submission -- read user input generically:**
```java
String custName = (String) bean.loadModelData("紹介者契約者名", "value");
Boolean custEnabled = (Boolean) bean.loadModelData("紹介者契約者名", "enable");
Integer svcRowCount = (Integer) bean.loadModelData("サービス契約一覧リスト", "*");
```

**4. Form submission -- write changes generically:**
```java
bean.storeModelData("紹介者電話番号", "value", "090-1234-5678");
bean.storeModelData("紹介者電話番号", "enable", true);
```

**5. Dynamic row management:**
```java
// Add a new customer contract row
int newIndex = bean.addListDataInstance("顧客契約引継リスト");
// Set data in the new row via delegated key routing
bean.storeModelData("顧客契約引継リスト/" + newIndex + "/契約者名", "value", "株式会社新顧客");

// Remove a service contract row
bean.removeElementFromListData("サービス契約一覧リスト", 1);

// Clear all rows
bean.clearListDataInstance("顧客契約引継リスト");
```

## Notes for Developers

### Thread safety

This bean is **not thread-safe**. Like most JSF/Struts presentation models, it is expected to be instantiated per HTTP request (page-scoped or request-scoped). Sharing a single `KKW01037SFBean` instance across concurrent requests would lead to data races on all mutable fields.

### Null-handling conventions

- `loadModelData` returns `null` for any unrecognized key path, out-of-range list index, or `null` key input. Callers must handle this.
- `storeModelData` silently returns if the key is `null`.
- `typeModelData` returns `null.class` is not returned; it returns `null` (the object `null`) for unrecognized keys.
- `subkey` is internally coerced to an empty string when `null`.

### Key routing is exact-match only

The field-group matching uses `String.equals()` (case-sensitive for the Japanese key strings). The sub-key matching uses `equalsIgnoreCase()`. This means:
- `"紹介者契約者名"` matches, but `"紹介者契約者名 "` (with trailing space) does not.
- `"value"`, `"VALUE"`, and `"Value"` all match the `subkey.equalsIgnoreCase()` check.

### `isSetAsString` flag in `storeModelData`

The four-argument overload accepts `isSetAsString`. When `true`, it is intended for cases where a `Long` property should be set from a `String` value. In this specific bean, no `Long` fields are declared, so the flag currently has no effect. It is part of the `X31CBaseBean` interface contract.

### Constructor guarantees

The constructor always initializes `cust_kei_hktgi_list_list` with exactly one `KKW01037SF02DBean` element. `svc_kei_list_list` starts empty. These initializations mean that on first render, the page will always show at least one row in the customer-contract section, while the service-contract section starts empty (rows are added dynamically via `addListDataInstance`).

### Common-info bean routing

Keys starting with `//` are delegated to the superclass (`X33VViewBaseBean`) for shared/common information processing (e.g. session-user ID, system date). This mechanism is orthogonal to the page-specific fields documented above.

### `popup_mode` field

The `popup_mode` fields (`popup_mode_value`, `popup_mode_state`, `popup_mode_update`) appear to control some popup-related behavior on the page. The exact popup mechanics are not visible from this bean alone and would be documented in the JSP page (`KKW010370PJP.jsp`) or the associated controller logic.

### Adding new fields

To add a new field to this bean, a developer would need to:
1. Declare the field and its getter/setter.
2. Add a case in `loadModelData`, `storeModelData`, and `typeModelData` for the new field's key.
3. Add the key to `listKoumokuIds()` when `key` is `null`.
4. If it is a repeat-list field, also add handling in `addListDataInstance`, `removeElementFromListData`, `clearListDataInstance`, and the `getJsflist_typelist_*` methods.

This process is manual and error-prone because the routing is done via string matching rather than reflection. Any mismatch between the key string in the field declaration and the key strings in the `*ModelData` methods will result in silent data loss (the framework gets `null`).
