# CRW03407SF01DBean

## Purpose

`CRW03407SF01DBean` is the central data management bean for handling **response history external connection URLs** (`対応履歴外部接続URL`) across a set of related JSP screens. It encapsulates three distinct URL lists — index-only URLs, named URLs, and a generic URL list — along with an index pointer field and its auxiliary metadata (value, enabled state, and display state). The class provides a unified, key-subkey-based API for reading, writing, and introspecting its data, making it the primary data source consumed by five JSP pages in the application.

## Design

This class follows the **data bean** pattern common in Japanese enterprise web frameworks (likely an X33/X31C-based MVC architecture). It implements two framework interfaces:

- **`X33VDataTypeBeanInterface`** — mandates the `loadModelData`, `storeModelData`, and `typeModelData` methods, enabling generic data access via key/subkey strings.
- **`X33VListedBeanInterface`** — mandates the `addListDataInstance`, `removeElementFromListData`, `clearListDataInstance`, and `listKoumokuIds` methods, enabling dynamic list management at the view layer.

The bean is **not generic** — its routing logic is hardcoded against four specific Japanese key strings (see the "Key Methods" section). It has **no outbound dependencies** beyond the fields themselves (which hold `X33VDataTypeList` and `X33VDataTypeStringBean` instances) and `ArrayList`/`SelectItem`, making it a pure data holder with view-convenience methods.

```mermaid
flowchart TD
    subgraph ViewLayers["JSP View Layers"]
        J1["CRW034010PJP"]
        J2["CRW034020PJP"]
        J3["CRW034030PJP"]
        J4["CRW034050PJP"]
        J5["CRW034060PJP"]
    end

    subgraph BeanCore["CRW03407SF01DBean"]
        L1["l0_taiorrk_out_url_no_list"]
        L2["l0_taiorrk_out_url_list"]
        L3["l0_taiorrk_out_url_nm_list"]
        IDX["l0_taiorrk_out_url_no_idx_*"]
        INT["index"]
    end

    subgraph ListMembers["List Element Beans"]
        S1["X33VDataTypeStringBean"]
    end

    subgraph Interfaces["Implemented Interfaces"]
        I1["X33VDataTypeBeanInterface"]
        I2["X33VListedBeanInterface"]
    end

    J1 --> BeanCore
    J2 --> BeanCore
    J3 --> BeanCore
    J4 --> BeanCore
    J5 --> BeanCore

    BeanCore -.-> S1

    BeanCore --> I1
    BeanCore --> I2
```

## Fields

| Field | Type | Description |
|---|---|---|
| `l0_taiorrk_out_url_no_idx_update` | `String` | Update timestamp for the index field (no public accessor). |
| `l0_taiorrk_out_url_no_idx_value` | `String` | Current value of the external connection URL number index. Initialized to `""`. |
| `l0_taiorrk_out_url_no_idx_enabled` | `Boolean` | Whether the index field is enabled. Defaults to `false`. |
| `l0_taiorrk_out_url_no_idx_state` | `String` | Display state of the index field. Initialized to `""`. |
| `l0_taiorrk_out_url_no_list` | `X33VDataTypeList` | List of URL entries for the "no" (index-number) variant. |
| `l0_taiorrk_out_url_list` | `X33VDataTypeList` | Generic URL list. |
| `l0_taiorrk_out_url_nm_list` | `X33VDataTypeList` | Named URL list. |
| `index` | `int` | An integer index (purpose inferred — likely tracks the currently selected row). |

All fields are `protected`, meaning subclasses may access them directly, but public access is mediated through getters and setters.

## Key Methods

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

The primary read accessor. Dispatches based on the `key` value to return data from the appropriate field or list element. Handles three categories:

1. **Index field** — When `key` equals `"対応履歴外部接続URL番号インデックス"`:
   - `subkey` `"value"` → returns `l0_taiorrk_out_url_no_idx_value`
   - `subkey` `"enable"` → returns `l0_taiorrk_out_url_no_idx_enabled`
   - `subkey` `"state"` → returns `l0_taiorrk_out_url_no_idx_state`

2. **List items** — When `key` starts with one of the three list types, the method parses the index from the remainder of the key (after the first `/`). Special handling for `"*"` returns the list size as an `Integer`. Otherwise, it casts the element at the given index to `X33VDataTypeStringBean` and delegates to its `loadModelData(subkey)`.

3. **No match** → returns `null`.

```mermaid
flowchart TD
    A["Client/JSP Request"] --> B["loadModelData key subkey"]
    A --> C["storeModelData key subkey value"]
    A --> D["typeModelData key subkey"]

    B --> E{"Is key a direct
idx field?"}
    C --> E
    D --> E

    E -->|"Yes"| F["Dispatch to
l0_taiorrk_out_url_no_idx_*"]
    E -->|"No"| G{"Is key a list type?"}
    G -->|"No"| H["Return null"]
    G -->|"Yes"| I{"Parse index
from key"}
    I -->|"Invalid"| H
    I -->|"Valid"| J{"Which list?"}
    J -->|"no"| K["Dispatch to
url_no_list[index]"]
    J -->|"url"| L["Dispatch to
url_list[index]"]
    J -->|"nm"| M["Dispatch to
url_nm_list[index]"]
    K --> N["X33VDataTypeStringBean
.loadModelData(subkey)"]
    L --> N
    M --> N
    F --> O["Return data"]
    N --> O
```

**Side effects:** None. This is a pure read operation.

### `storeModelData(String key, String subkey, Object in_value) → void`

Three overloaded versions of this method handle data writes:

- `storeModelData(gamenId, key, subkey, in_value)` — The `gamenId` (screen ID) parameter is accepted but **ignored**; it delegates to the 3-parameter version.
- `storeModelData(key, subkey, in_value)` — Delegates to the 4-parameter version with `isSetAsString = false`.
- `storeModelData(key, subkey, in_value, isSetAsString)` — The actual routing logic, mirroring `loadModelData` but in reverse:
  - For the index field: casts and sets `value`, `enable`, or `state`.
  - For list items: parses the index from the key, validates bounds, then casts the element at that index to `X33VDataTypeStringBean` and delegates to its `storeModelData(subkey, in_value)`.

**Side effects:** Mutates internal state. No list size changes (elements must already exist).

**Note on `isSetAsString`:** This flag is passed through to `X33VDataTypeStringBean.storeModelData`, but the bean elements in this class are all `X33VDataTypeStringBean` instances (not `X33VDataTypeLongBean` or `X33VDataTypeBooleanBean`), so the flag may have limited effect in practice.

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

Returns the Java type of the data at the given key/subkey path. This enables the view layer to perform type-safe operations:

- Index field: `"value"` → `String.class`, `"enable"` → `Boolean.class`, `"state"` → `String.class`
- List items with `"*"` → `Integer.class` (list size)
- List items with valid index → delegates to the element's `typeModelData(subkey)`
- No match → `null`

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

A **static** method that returns the list of all valid top-level key strings used by this bean. Used by the framework to discover which fields the bean manages:

```java
[
  "対応履歴外部接続URL番号インデックス",
  "対応履歴外部接続URL番号リスト",
  "対応履歴外部接続URLリスト",
  "対応履歴外部接続URL名リスト"
]
```

### `addListDataInstance(String key) → int`

Dynamically adds a new `X33VDataTypeStringBean` instance to the list specified by `key`. Returns the index of the newly added element, or `-1` if the key is unrecognized or null. Creates the list if it is currently null.

### `removeElementFromListData(String key, int index) → void`

Removes the element at the given index from the list specified by `key`. Bounds-checked: silently does nothing if the index is out of range.

### `clearListDataInstance(String key) → void`

Clears all elements from the list specified by `key`. The list object itself is retained (not set to null).

### JSF Convenience Methods

The `getJsflist_l0_taiorrk_out_url_*()` methods convert each `X33VDataTypeList` into an `ArrayList<SelectItem>` suitable for JSF `<h:selectOneMenu>` or similar dropdown components:

- `getJsflist_l0_taiorrk_out_url_no()` → converts `l0_taiorrk_out_url_no_list`
- `getJsflist_l0_taiorrk_out_url()` → converts `l0_taiorrk_out_url_list`
- `getJsflist_l0_taiorrk_out_url_nm()` → converts `l0_taiorrk_out_url_nm_list`

Each iterates the list, casts elements to `X33VDataTypeStringBean`, extracts the value, and creates a `SelectItem` where the value is the index (as a string) and the label is the URL string.

**Caveat:** These methods assume all elements in the list are `X33VDataTypeStringBean` instances. If a non-String bean is present, a `ClassCastException` will be thrown at runtime.

## Relationships

### Who uses this class

Five JSP pages depend on this bean:

| Consumer | Relationship |
|---|---|
| `CRW034010PJP` | References the bean for data binding |
| `CRW034020PJP` | References the bean for data binding |
| `CRW034030PJP` | References the bean for data binding |
| `CRW034050PJP` | References the bean for data binding |
| `CRW034060PJP` | References the bean for data binding |

All consumers are JSP view pages, indicating this bean is the **primary data model** for a set of related screens dealing with response history and external URL connections.

### What this class depends on

This class has **no outbound references** to other application classes. Its only dependencies are:

- `X33VDataTypeList` — the framework's generic list container
- `X33VDataTypeStringBean` — the framework's string data type bean (used as list element type)
- `X33VDataTypeBeanInterface` / `X33VListedBeanInterface` — framework interfaces defining the data bean contract
- `ArrayList` / `SelectItem` — standard Java and JSF classes for the convenience methods
- `X33SException` — framework exception class (thrown by list mutation methods)

## Usage Example

While the framework handles bean lifecycle, a typical usage pattern in a JSP page would look like:

```jsp
<!-- In the JSP, the bean is typically obtained via a request-scoped getter -->
<%
    CRW03407SF01DBean bean = (CRW03407SF01DBean) request.getAttribute("bean");
%>

<!-- Access a list element's value -->
<%
    String urlValue = (String) bean.loadModelData(
        "対応履歴外部接続URLリスト/0", "value");
%>

<!-- Check list size -->
<%
    Integer count = (Integer) bean.loadModelData(
        "対応履歴外部接続URLリスト/*", null);
%>

<!-- Add a new row to the list -->
<%
    int newIndex = bean.addListDataInstance(
        "対応履歴外部接続URLリスト");
%>

<!-- Populate a JSF dropdown -->
<h:selectOneMenu value="#{bean.jsflist_l0_taiorrk_out_url}">
    <f:selectItems value="#{bean.jsflist_l0_taiorrk_out_url_no}" />
</h:selectOneMenu>

<!-- Remove a row -->
<%
    bean.removeElementFromListData("対応履歴外部接続URLリスト", selectedIndex);
%>
```

The key-subkey routing also supports type introspection:

```java
// Check what type a field holds
Class<?> type = bean.typeModelData("対応履歴外部接続URL番号インデックス", "value");
// Returns: String.class

Boolean enabled = (Boolean) bean.loadModelData(
    "対応履歴外部接続URL番号インデックス", "enable");
```

## Notes for Developers

**Thread safety:** This bean is **not thread-safe**. It maintains mutable internal lists and fields, and the framework likely instantiates a new bean per request/session. Do not share instances across threads.

**Key string immutability:** The four key strings used in routing are hardcoded Japanese literals. Any change to these strings (e.g., localization) must be coordinated across all callers. The `listKoumokuIds()` static method is the single source of truth for valid keys.

**Subkey case sensitivity:** In `loadModelData` and `storeModelData`, the subkey comparison for the index field uses `equalsIgnoreCase()` (case-insensitive) for `"value"`, `"enable"`, and `"state"`. For list elements, the subkey is passed through verbatim to the element bean's own `loadModelData`/`storeModelData`, so case sensitivity depends on the underlying type bean.

**Null handling:** All routing methods return `null` (or do nothing for setters) when `key` or `subkey` is null. List index parsing catches `NumberFormatException` and returns null — invalid index strings are silently ignored rather than throwing.

**List element type assumption:** The JSF convenience methods (`getJsflist_*`) and the list routing logic in `loadModelData`/`storeModelData`/`typeModelData` all assume that list elements are `X33VDataTypeStringBean` instances. If a list contains a different type, a `ClassCastException` will occur at runtime.

**Boundaries are soft:** `addListDataInstance` does not validate the current list size. `removeElementFromListData` silently ignores out-of-bounds indices rather than throwing. This means callers must track list sizes themselves (via `loadModelData(key, "*")`) to avoid subtle silent failures.

**Constructor guarantees:** The constructor creates all three lists as empty `X33VDataTypeList` instances — the bean is always in a valid initial state with no null list fields.

**`index` field:** The `index` field (getter/setter at lines 155–161) is not integrated into the key-subkey routing. It appears to be a standalone integer used for tracking the currently selected row or element index, managed separately from the list-based methods.

**Unused `separaterPoint` variable:** In `storeModelData`, the `separaterPoint` variable is calculated but never used (it was present in `loadModelData` as `key.indexOf("/")` but the variable is not referenced before `key` is reassigned via `substring`). This is a benign dead variable.

**Framework binding:** This bean is designed for binding within a specific framework (X33/X31C) that uses the `loadModelData`/`storeModelData`/`typeModelData` pattern for generic data access. The framework likely iterates over the keys returned by `listKoumokuIds()` to automatically bind form data to the bean. Modifying these methods without understanding the framework contract will break data binding.
