# KKW01021SF02DBean

## Purpose

`KKW01021SF02DBean` is a data-bound JavaBean that represents a single customer (contractor) record displayed on a web form in a Japanese-language business application. It encapsulates all visible fields for a contract party -- identification, name, address components, and phone number -- along with metadata for each field controlling its editability and display state. The class provides dynamic keyed property access through a string-key dispatcher pattern, enabling generic framework code (e.g., a view-layer binding mechanism) to read and write individual properties without compile-time knowledge of the bean's fields.

## Design

The class follows the **JavaBean / data-bound bean** pattern, commonly used in older JSP-based MVC frameworks (specifically the X33V framework). It implements two framework interfaces:

- **`X33VDataTypeBeanInterface`** -- requires `loadModelData(String key, String subkey)` and `typeModelData(String key, String subkey)` for dynamic property retrieval.
- **`X33VListedBeanInterface`** -- requires `listKoumokuIds()` for listing the known property keys.

### Field Architecture

Each logical field in the customer record is exposed through a **four-property group** following a consistent naming convention:

| Suffix | Type | Meaning |
|--------|------|---------|
| `_value` | `String` | The actual field value (e.g. the customer name) |
| `_enabled` | `Boolean` | Whether the field is editable (`true` / `false`, defaults `false`) |
| `_state` | `String` | A display-state indicator (e.g. for conditional styling, defaults `""`) |
| `_update` | `String` | A change-tracking flag set by the framework (not initialized) |

This `_value` / `_enabled` / `_state` / `_update` grouping is repeated for every data column, yielding **36 direct field declarations** across 10 logical properties. All `_value` fields default to `""`, and all `_enabled` fields default to `false`.

### Keyed-Property Dispatcher

Rather than relying on Java's introspection, the bean implements an explicit switch-chain over string keys and sub-keys:

- **Keys** are Japanese-language property labels (e.g. `"お客名"` for "Customer Name", `"契約者都道府県名"` for "Contractor Prefecture Name").
- **Sub-keys** are one of `"value"`, `"enable"`, or `"state"` (case-insensitive comparison via `equalsIgnoreCase`).

This design decouples the JSP view from Java introspection -- the framework code passes string keys and the bean routes to the correct getter/setter. The trade-off is a large monolithic `if-else` chain, but it avoids reflection overhead and works reliably with compiled JSPs that use scriptlets.

## Key Methods

### Constructors

#### `KKW01021SF02DBean()`

Default no-arg constructor. Initializes no fields beyond their declared defaults. The constructor body is intentionally empty; all initialization is done via field initializer expressions (`= ""` or `= false`).

### Individual Getters/Setters (36 pairs)

For each of the 10 logical fields, the bean provides four accessor pairs. The methods are straightforward delegators:

| Logical Field | Key (Japanese) | Sub-key | Getter Method | Setter Method |
|---------------|----------------|---------|---------------|---------------|
| System ID | `"SYSID"` | `value` | `getSysid_value()` | `setSysid_value(String)` |
| System ID | `"SYSID"` | `enable` | `getSysid_enabled()` | `setSysid_enabled(Boolean)` |
| System ID | `"SYSID"` | `state` | `getSysid_state()` | `setSysid_state(String)` |
| Customer Name | `"お客名"` | `value` | `getCust_nm_value()` | `setCust_nm_value(String)` |
| Customer Name | `"お客名"` | `enable` | `getCust_nm_enabled()` | `setCust_nm_enabled(Boolean)` |
| Customer Name | `"お客名"` | `state` | `getCust_nm_state()` | `setCust_nm_state(String)` |
| Contractor Prefecture | `"契約者都道府県名"` | `value` | `getKeisha_state_nm_value()` | `setKeisha_state_nm_value(String)` |
| Contractor City/Town/Village | `"契約者市区町村名"` | `value` | `getKeisha_city_nm_value()` | `setKeisha_city_nm_value(String)` |
| Contractor Oaza/Street | `"契約者大字通称名"` | `value` | `getKeisha_oaztsu_nm_value()` | `setKeisha_oaztsu_nm_value(String)` |
| Contractor Choume/Block | `"契約者字丁目名"` | `value` | `getKeisha_azcho_nm_value()` | `setKeisha_azcho_nm_value(String)` |
| Contractor Lot Number | `"契約者番地号"` | `value` | `getKeisha_bnchigo_value()` | `setKeisha_bnchigo_value(String)` |
| Contractor Address (Building) | `"契約者住所補記・建物名"` | `value` | `getKeisha_adrttm_value()` | `setKeisha_adrttm_value(String)` |
| Contractor Address (Room) | `"契約者住所補記・部屋番号"` | `value` | `getKeisha_adrrm_value()` | `setKeisha_adrrm_value(String)` |
| Contractor Phone | `"契約者電話番号"` | `value` | `getKeisha_telno_value()` | `setKeisha_telno_value(String)` |

All getters return `String` (except `_enabled` getters which return `Boolean`). All setters accept `String` or `Boolean` as appropriate. There is no null-checking or validation in the setters.

### `setIndex(int)` / `getIndex()`

Stores a row index integer, likely used when the bean represents one row in a multi-row table.

```java
public int getIndex();
public void setIndex(int index);
```

This is the only primitive `int` field in the bean and is not tied to the keyed-property dispatcher.

### `loadModelData(String key, String subkey) → Object`

**The most important method in the class.** It serves as the read-side of the keyed-property dispatcher. Given a Japanese-language property key and a sub-key (`"value"`, `"enable"`, or `"state"`), it returns the corresponding field value.

- Returns `null` if `key` or `subkey` is `null`.
- Returns `null` if no matching property is found.
- Returns the actual field value (String or Boolean) via the appropriate getter.
- Sub-key comparison is **case-insensitive** (`equalsIgnoreCase`).

**Example:**
```java
Object val = bean.loadModelData("お客名", "value");
// Returns the customer name String via getCust_nm_value()

Object enabled = bean.loadModelData("契約者電話番号", "enable");
// Returns the Boolean from getKeisha_telno_enabled()
```

The method is the contract-implementing method of `X33VDataTypeBeanInterface`. Framework code in the JSP or a backing controller calls this to dynamically read any field without casting to the specific bean type.

### `storeModelData(...)` (overloaded, 3 signatures)

Write-side counterpart to `loadModelData`. Three overloads:

1. **`storeModelData(String gamenId, String key, String subkey, Object in_value)`**
   
   Accepts a `gamenId` (screen ID) parameter that is **currently unused** (passes through to overload #2). Likely a leftover from a parent class contract or reserved for future use.

2. **`storeModelData(String key, String subkey, Object in_value)`**
   
   Delegates to overload #3 with `isSetAsString = false`.

3. **`storeModelData(String key, String subkey, Object in_value, boolean isSetAsString)`**
   
   The core implementation. Mirrors the `if-else` chain of `loadModelData` but calls setters:
   - If sub-key is `"value"`, casts `in_value` to `String` and calls the `_value` setter.
   - If sub-key is `"enable"`, casts `in_value` to `Boolean` and calls the `_enabled` setter.
   - If sub-key is `"state"`, casts `in_value` to `String` and calls the `_state` setter.
   
   Silently returns without action if `key` or `subkey` is `null`. Does nothing if no property matches.

The `isSetAsString` parameter is accepted but **not used in the current implementation** -- the casts are hardcoded. This suggests a planned extension that was never implemented, or that the flag was intended to override casting behavior for future numeric/date fields.

### `listKoumokuIds() → ArrayList<String>`

**Static factory method.** Returns an `ArrayList` of all 10 property keys in a fixed order. This implements `X33VListedBeanInterface` and allows the framework to enumerate all valid property names for validation, iteration, or form generation.

The returned list is:
```
SYSID, お客名, 契約者都道府県名, 契約者市区町村名,
契約者大字通称名, 契約者字丁目名, 契約者番地号,
契約者住所補記・建物名, 契約者住所補記・部屋番号, 契約者電話番号
```

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

Returns the Java type for a given property key/sub-key combination. Used by the framework for type-safe data binding and validation.

- Returns `String.class` for all `"value"` and `"state"` sub-keys.
- Returns `Boolean.class` for all `"enable"` sub-keys.
- Returns `null` if `key` or `subkey` is `null`, or if no property matches.

This mirrors the structure of `loadModelData` and `storeModelData` exactly.

## Relationships

```mermaid
flowchart TD
    subgraph View
        JSP["KKW010210PJP<br/>JSP View"]
    end
    subgraph Model
        SFBean["KKW01021SFBean<br/>Parent Form Bean"]
        DBean["KKW01021SF02DBean<br/>Customer Data Bean"]
    end
    subgraph Interface
        VT["X33VDataTypeBeanInterface<br/>loadModelData / typeModelData"]
        VL["X33VListedBeanInterface<br/>listKoumokuIds"]
    end
    JSP -->|casts to| DBean
    SFBean -->|holds list of| DBean
    DBean -->|implements| VT
    DBean -->|implements| VL
```

### Dependents

| Consumer | Relationship | How It's Used |
|----------|-------------|---------------|
| `KKW010210PJP` (JSP) | View template | Casts the first element from `getServiceFormBeanList().get(0).getCust_list().get(0)` to `KKW01021SF02DBean` and invokes individual getters (e.g., `getSysid_value()`, `getCust_nm_value()`, `getKeisha_telno_value()`) to populate table cells with customer data. |

### No Outbound Dependencies

`KKW01021SF02DBean` has no references to other application classes beyond the two interfaces it implements. It is a pure data holder with no business logic, no database access, and no side effects.

## Usage Example

The bean is instantiated by the framework (likely via the parent `KKW01021SFBean`) and placed into a list of form beans. The JSP retrieves it and accesses individual fields:

```jsp
// In KKW010210PJP.jsp - retrieving a single customer record
KKW01021SF02DBean customer =
    (KKW01021SF02DBean) ((KKW01021SFBean)
        KKW010210PJP.getServiceFormBeanList().get(0))
        .getCust_list().get(0);

// Display fields via direct getter calls (escaped and newline-safe)
String sysid = KKW010210PJP.tool_Escape(true, "full",
    customer.getSysid_value());
String name = KKW010210PJP.tool_Escape(true, "full",
    customer.getCust_nm_value());
String address = KKW010210PJP.tool_Escape(true, "full",
    customer.getKeisha_state_nm_value())
    + customer.getKeisha_city_nm_value()
    + customer.getKeisha_oaztsu_nm_value()
    + customer.getKeisha_azcho_nm_value();
```

Alternatively, framework code can use the keyed-property API for dynamic access:

```java
KKW01021SF02DBean customer = ...;

// Read dynamically
Object name = customer.loadModelData("お客名", "value");
boolean editable = (Boolean) customer.loadModelData("お客名", "enable");

// Write dynamically
customer.storeModelData("契約者電話番号", "value", "03-1234-5678");
customer.storeModelData("契約者電話番号", "enable", true);

// Check type
Class<?> type = customer.typeModelData("お客名", "value");
// Returns String.class

// List all available keys
ArrayList<String> keys = KKW01021SF02DBean.listKoumokuIds();
```

## Notes for Developers

### Thread Safety

The bean is **not thread-safe**. It has no synchronization and all fields are mutable. Each bean instance represents a single customer record for a single HTTP request. Do not share instances across threads or requests.

### Framework Conventions

- The **four-property-per-field** pattern (`_value`, `_enabled`, `_state`, `_update`) is significant. If you add a new data field, you must add all four variants and update the three dispatcher methods (`loadModelData`, `storeModelData`, `typeModelData`) and `listKoumokuIds`.
- The keyed dispatcher methods use **exact string matches** on Japanese-language keys. Do not refactor the keys (e.g., to English) without updating all call sites.
- The `gamenId` parameter in the 4-argument `storeModelData` is unused. Removing it would be a safe refactoring if the parent interface allows.
- The `isSetAsString` parameter in the 4-argument `storeModelData` is accepted but the implementation ignores it. The casts to `String` and `Boolean` are always applied.

### Known Patterns / Observations

- **No validation**: The bean stores data as-is. Validation is expected to happen in the service layer or the JSP view, not in the bean itself.
- **No null defaults**: `_value` fields default to empty string `""`, not `null`. `_enabled` defaults to `false`. `_state` defaults to `""`. This means callers generally don't need null checks on `_value` results, but should check for `null` when calling `loadModelData` / `typeModelData` (which can return `null` for unrecognized keys).
- **`index` field**: The `int index` field is independent of the keyed-property system. It appears to be used as a row indicator when displaying multiple customer records in a table.
- **`separaterPoint` variable**: Both `loadModelData` and `storeModelData` declare `int separaterPoint = key.indexOf("/")` but never use it. This is likely leftover code from a previous version that used a `/` separator convention.

### Adding a New Property

To add a new data column (e.g., a fax number), you would need to:

1. Add four protected fields: `keisha_faxnm_value` (String), `keisha_faxnm_enabled` (Boolean), `keisha_faxnm_state` (String), `keisha_faxnm_update` (String).
2. Add the four getter/setter pairs.
3. Add a new entry to `listKoumokuIds()`.
4. Add a new `if-else` block in `loadModelData()` (three sub-key branches).
5. Add a new `if-else` block in `storeModelData()` (three sub-key branches).
6. Add a new `if-else` block in `typeModelData()` (three sub-key branches).
7. Update the JSP view to display the new fields.

Failure to update any of the three dispatcher methods will cause the keyed-property API to silently return `null` for the new field, which is a difficult-to-debug omission.
