# Business Logic — KKW22301SF02DBean.typeModelData() [160 LOC]

| Field | Value |
|-------|-------|
| Fully Qualified Name | `eo.web.webview.KKW22301SF.KKW22301SF02DBean` |
| Layer | Utility / Data Type Bean (View-layer data binding helper) |
| Module | `KKW22301SF` (Package: `eo.web.webview.KKW22301SF`) |

## 1. Role

### KKW22301SF02DBean.typeModelData()

This method implements a **type-dispatch lookup** for the X33 View data-binding framework. Its purpose is to provide runtime type information for individual fields within the "Campaign List" (`キャンペーン一覧`) data model, enabling the framework to perform proper data conversion, validation, and UI rendering without requiring compile-time knowledge of each field's type.

The method implements a **routing/dispatch design pattern**: it receives a field identifier (`key`, also called "item name" or 項目名) and a sub-field identifier (`subkey`), then dispatches to the appropriate type by performing a chain of string-equality checks across **11 distinct service fields**. Each field consistently maps three subkeys — `value` (the field's data value), `enable` (the field's editability flag), and `state` (the field's state/visibility indicator) — to their corresponding Java types.

This method plays the role of a **shared framework utility** called from the parent bean's `modelData()` method during list-item initialization. When the framework processes "Campaign List" data, it instantiates `KKW22301SF02DBean` for each campaign entry and invokes `typeModelData` to determine how to bind, validate, and display each field. It has **zero side effects**: it performs no database access, no service component calls, and no state mutations.

The method supports the following **11 service fields**, each representing a business attribute of a telecom service campaign: campaign code, discount service name, service start/end dates, application date, related customer number, status name, discount start/end dates, application route, and target scope.

## 2. Processing Pattern (Detailed Business Logic)

```mermaid
flowchart TD
    START(["typeModelData key, subkey"])
    START --> CHECK_NULL{key or subkey null?}
    CHECK_NULL -->|Yes| R_NULL_1(["Return null"])
    CHECK_NULL -->|No| FIND_SEP["int separaterPoint = key.indexOf /\"]
    FIND_SEP --> BRANCH{Match key?}
    BRANCH -->|"表示用キャンペーンコード"| FIELD_CAMPAIGN["dsp_campaign_cd"]
    BRANCH -->|"割引サービス名"| FIELD_WRIB_SVC["wrib_svc_nm"]
    BRANCH -->|"サービス開始年月日"| FIELD_SVC_START["svc_sta_ymd"]
    BRANCH -->|"サービス終了年月日"| FIELD_SVC_END["svc_endymd"]
    BRANCH -->|"申請年月日"| FIELD_APPLY["mskm_ymd"]
    BRANCH -->|"関連お客さま番号"| FIELD_RELATED["knrn_svc_kei_no"]
    BRANCH -->|"ステータス名"| FIELD_STATUS["status_nm"]
    BRANCH -->|"割引開始日"| FIELD_DISC_START["wrib_staymd"]
    BRANCH -->|"割引終了日"| FIELD_DISC_END["wrib_endymd"]
    BRANCH -->|"セット割申請経路名"| FIELD_ROUTE["wrib_shin_route_nm"]
    BRANCH -->|"セット割対象区分"| FIELD_SCOPE["wrib_trgt_div"]
    BRANCH -->|No match| R_NULL_2(["Return null"])

    FIELD_CAMPAIGN --> SUB_CHECK{subkey check}
    FIELD_WRIB_SVC --> SUB_CHECK
    FIELD_SVC_START --> SUB_CHECK
    FIELD_SVC_END --> SUB_CHECK
    FIELD_APPLY --> SUB_CHECK
    FIELD_RELATED --> SUB_CHECK
    FIELD_STATUS --> SUB_CHECK
    FIELD_DISC_START --> SUB_CHECK
    FIELD_DISC_END --> SUB_CHECK
    FIELD_ROUTE --> SUB_CHECK
    FIELD_SCOPE --> SUB_CHECK

    SUB_CHECK -->|value| R_STR(["Return String.class"])
    SUB_CHECK -->|enable| R_BOOL(["Return Boolean.class"])
    SUB_CHECK -->|state| R_STATE(["Return String.class"])
    SUB_CHECK -->|No match| R_NULL_3(["Return null"])

    R_NULL_1 --> END_1(["Return / Next"])
    R_NULL_2 --> END_1
    R_NULL_3 --> END_1
    R_STR --> END_1
    R_BOOL --> END_1
    R_STATE --> END_1
```

**CRITICAL — Constant Resolution:**

No external constants are used in this method. All branch values are **literal Japanese strings** hard-coded as item name identifiers:

| Literal Key | Field ID | Business Meaning |
|------------|----------|------------------|
| `"表示用キャンペーンコード"` | `dsp_campaign_cd` | Display Campaign Code |
| `"割引サービス名"` | `wrib_svc_nm` | Discount Service Name |
| `"サービス開始年月日"` | `svc_sta_ymd` | Service Start Date (YYYY-MM-DD) |
| `"サービス終了年月日"` | `svc_endymd` | Service End Date (YYYY-MM-DD) |
| `"申請年月日"` | `mskm_ymd` | Application Date (YYYY-MM-DD) |
| `"関連お客さま番号"` | `knrn_svc_kei_no` | Related Customer Number (ANK-3521) |
| `"ステータス名"` | `status_nm` | Status Name (ANK-4195) |
| `"割引開始日"` | `wrib_staymd` | Discount Start Date (ANK-4195) |
| `"割引終了日"` | `wrib_endymd` | Discount End Date (ANK-4195) |
| `"セット割申請経路名"` | `wrib_shin_route_nm` | Set Discount Application Route Name (ANK-4195) |
| `"セット割対象区分"` | `wrib_trgt_div` | Set Discount Target Scope (ANK-4195) |

The method follows a **two-phase dispatch** pattern:
1. **Phase 1** — `if/else-if` chain matching the `key` parameter against 11 known field names. If no match, returns `null` immediately.
2. **Phase 2** — For each matched field, an inner `if/else-if` chain matching the `subkey` parameter case-insensitively against `value`, `enable`, or `state`. Returns `String.class` for `value` and `state`, `Boolean.class` for `enable`.

## 3. Parameter Analysis

| No | Parameter Name | Type | Business Description |
|----|---------------|------|---------------------|
| 1 | `key` | `String` | Item name (項目名) — the business field identifier for a campaign attribute. It maps to a specific service data field such as campaign code, service date, discount info, or customer reference. Values are one of 11 hard-coded Japanese strings listed above. The value determines which branch of the dispatch chain is entered, and thus which field's type information is returned. |
| 2 | `subkey` | `String` | Sub-key — a property descriptor within the field. It selects one of three metadata dimensions: `value` (the actual data value type), `enable` (the editability flag type), or `state` (the state/visibility indicator type). Matching is case-insensitive via `equalsIgnoreCase`. Values are: `"value"`, `"enable"`, `"state"`, or any unrecognized string (which returns `null`). |

**External State:** This method is **stateless** — it reads no instance fields, no static state, and no external configuration. The only computation besides the dispatch chain is `key.indexOf("/")`, which computes the position of a separator character (the result is stored but never used).

## 4. CRUD Operations / Called Services

This method performs **no CRUD operations** and **calls no services**. It is a pure read-only type lookup that returns a `Class<?>` reference. There are no database accesses, no SC (Service Component) invocations, and no CBS (Business Service) calls.

| CRUD | SC / CBS | SC Code | Entity / DB | Operation Description |
|------|----------|---------|-------------|----------------------|
| *(N/A)* | *(none)* | *(none)* | *(none)* | Pure type dispatch — no data access |

## 5. Dependency Trace

This method is called through the X33 View Framework's `X33VDataTypeBeanInterface.modelData(key, subkey)` mechanism. The parent bean `KKW22301SFBean` creates an instance of `KKW22301SF02DBean` when processing the "Campaign List" (`キャンペーン一覧`) item, and the framework invokes `typeModelData` on that instance during data binding.

| # | Caller (Screen/Batch) | Call Chain (Full Path to this Method) | Terminal (SC / CRUD / Entity) |
|---|----------------------|--------------------------------------|-------------------------------|
| 1 | Screen:KKW22301SF | `KKW22301SFBean.modelData("キャンペーン一覧", idx)` -> `campaign_icrn_list.add(new KKW22301SF02DBean())` -> Framework calls `typeModelData(subkey)` on the bean instance | *(none — pure type lookup)* |
| 2 | Screen:KKW22301SF | `KKW22301SFBean.modelData(key, subkey)` -> dispatches to `KKW22301SF02DBean.typeModelData(key, subkey)` via `if (key.equals("キャンペーン一覧"))` branch | *(none — pure type lookup)* |

Note: The method is defined as part of `X33VDataTypeBeanInterface` (a framework contract shared by all data-type beans in the X33 View system). Many other DBean classes (e.g., `FUW00912SF01DBean`, `FUW00926SF02DBean`, etc.) implement the same interface pattern, but the specific keys and subkeys differ per screen domain.

## 6. Per-Branch Detail Blocks

**Block 1** — [IF] Null guard `(key == null || subkey == null)` (L864)

> If either parameter is null, return null immediately. This is an early-exit guard for invalid input.

| # | Type | Code |
|---|------|------|
| 1 | RETURN | `return null;` // key or subkey is null — early exit (key,subkeyがnullの場合、nullを返す) [L865] |

---

**Block 2** — [SET] Separator computation (L868)

> Computes the position of "/" separator in key. This value is stored but never used — likely a remnant from a previous implementation that split on "/".

| # | Type | Code |
|---|------|------|
| 1 | SET | `int separaterPoint = key.indexOf("/");` // Computes separator position (unused) [L868] |

---

**Block 3** — [ELSE-IF CHAIN — 11 Key Branches] Field name dispatch (L871–L1012)

> The core dispatch logic: an if/else-if chain matching `key` against 11 hard-coded field names. Each branch performs an identical inner subkey check (value -> String, enable -> Boolean, state -> String). The pattern repeats 11 times for each service field.

**Block 3.1** — [IF] `"表示用キャンペーンコード"` (dsp_campaign_cd) (L872)

> The display campaign code field — the first and canonical campaign identifier.

| # | Type | Code |
|---|------|------|
| 1 | IF | `if(key.equals("表示用キャンペーンコード"))` // Field: dsp_campaign_cd [L872] |
| 2 | ELSE-IF | `else if(subkey.equalsIgnoreCase("value"))` |
| 3 | RETURN | `return String.class;` // value subkey -> String [L874] |
| 4 | ELSE-IF | `else if(subkey.equalsIgnoreCase("enable"))` |
| 5 | RETURN | `return Boolean.class;` // enable subkey -> Boolean [L877] |
| 6 | ELSE-IF | `else if(subkey.equalsIgnoreCase("state"))` // subkeyが"state"の場合、ステータスを返す (If subkey is "state", return status) [L880] |
| 7 | RETURN | `return String.class;` // state subkey -> String [L882] |

**Block 3.2** — [ELSE-IF] `"割引サービス名"` (wrib_svc_nm) (L886)

> The discount service name field — identifies which discounted telecom service is being offered.

| # | Type | Code |
|---|------|------|
| 1 | ELSE-IF | `else if(key.equals("割引サービス名"))` // Field: wrib_svc_nm [L886] |
| 2 | ELSE-IF | `else if(subkey.equalsIgnoreCase("value"))` |
| 3 | RETURN | `return String.class;` [L888] |
| 4 | ELSE-IF | `else if(subkey.equalsIgnoreCase("enable"))` |
| 5 | RETURN | `return Boolean.class;` [L891] |
| 6 | ELSE-IF | `else if(subkey.equalsIgnoreCase("state"))` // subkeyが"state"の場合、ステータスを返す [L894] |
| 7 | RETURN | `return String.class;` [L896] |

**Block 3.3** — [ELSE-IF] `"サービス開始年月日"` (svc_sta_ymd) (L900)

> The service start date field — when the telecom service begins (YYYY-MM-DD format).

| # | Type | Code |
|---|------|------|
| 1 | ELSE-IF | `else if(key.equals("サービス開始年月日"))` // Field: svc_sta_ymd [L900] |
| 2 | ELSE-IF | `else if(subkey.equalsIgnoreCase("value"))` |
| 3 | RETURN | `return String.class;` [L902] |
| 4 | ELSE-IF | `else if(subkey.equalsIgnoreCase("enable"))` |
| 5 | RETURN | `return Boolean.class;` [L905] |
| 6 | ELSE-IF | `else if(subkey.equalsIgnoreCase("state"))` |
| 7 | RETURN | `return String.class;` [L908] |

**Block 3.4** — [ELSE-IF] `"サービス終了年月日"` (svc_endymd) (L912)

> The service end date field — when the telecom service terminates (YYYY-MM-DD format).

| # | Type | Code |
|---|------|------|
| 1 | ELSE-IF | `else if(key.equals("サービス終了年月日"))` // Field: svc_endymd [L912] |
| 2 | ELSE-IF | `else if(subkey.equalsIgnoreCase("value"))` |
| 3 | RETURN | `return String.class;` [L914] |
| 4 | ELSE-IF | `else if(subkey.equalsIgnoreCase("enable"))` |
| 5 | RETURN | `return Boolean.class;` [L917] |
| 6 | ELSE-IF | `else if(subkey.equalsIgnoreCase("state"))` |
| 7 | RETURN | `return String.class;` [L920] |

**Block 3.5** — [ELSE-IF] `"申請年月日"` (mskm_ymd) (L924)

> The application date field — when the customer application was submitted (YYYY-MM-DD format).

| # | Type | Code |
|---|------|------|
| 1 | ELSE-IF | `else if(key.equals("申請年月日"))` // Field: mskm_ymd [L924] |
| 2 | ELSE-IF | `else if(subkey.equalsIgnoreCase("value"))` |
| 3 | RETURN | `return String.class;` [L926] |
| 4 | ELSE-IF | `else if(subkey.equalsIgnoreCase("enable"))` |
| 5 | RETURN | `return Boolean.class;` [L929] |
| 6 | ELSE-IF | `else if(subkey.equalsIgnoreCase("state"))` |
| 7 | RETURN | `return String.class;` [L932] |

**Block 3.6** — [ELSE-IF] `"関連お客さま番号"` (knrn_svc_kei_no) (L935) — ANK-3521

> The related customer number field — associates a campaign with a related customer's service contract line item. Added in ANK-3521-00-00 on 2018/12/21.

| # | Type | Code |
|---|------|------|
| 1 | ELSE-IF | `else if(key.equals("関連お客さま番号"))` // Field: knrn_svc_kei_no [ANK-3521] [L937] |
| 2 | ELSE-IF | `else if(subkey.equalsIgnoreCase("value"))` |
| 3 | RETURN | `return String.class;` [L939] |
| 4 | ELSE-IF | `else if(subkey.equalsIgnoreCase("enable"))` |
| 5 | RETURN | `return Boolean.class;` [L942] |
| 6 | ELSE-IF | `else if(subkey.equalsIgnoreCase("state"))` |
| 7 | RETURN | `return String.class;` [L945] |

**Block 3.7** — [ELSE-IF] `"ステータス名"` (status_nm) (L950) — ANK-4195

> The status name field — human-readable display name for the campaign/service status. Part of the ANK-4195-00-00 feature additions.

| # | Type | Code |
|---|------|------|
| 1 | ELSE-IF | `else if(key.equals("ステータス名"))` // Field: status_nm [ANK-4195] [L952] |
| 2 | ELSE-IF | `else if(subkey.equalsIgnoreCase("value"))` |
| 3 | RETURN | `return String.class;` [L954] |
| 4 | ELSE-IF | `else if(subkey.equalsIgnoreCase("enable"))` |
| 5 | RETURN | `return Boolean.class;` [L957] |
| 6 | ELSE-IF | `else if(subkey.equalsIgnoreCase("state"))` |
| 7 | RETURN | `return String.class;` [L960] |

**Block 3.8** — [ELSE-IF] `"割引開始日"` (wrib_staymd) (L964) — ANK-4195

> The discount start date field — when the discount promotion becomes active (YYYY-MM-DD format).

| # | Type | Code |
|---|------|------|
| 1 | ELSE-IF | `else if(key.equals("割引開始日"))` // Field: wrib_staymd [ANK-4195] [L964] |
| 2 | ELSE-IF | `else if(subkey.equalsIgnoreCase("value"))` |
| 3 | RETURN | `return String.class;` [L966] |
| 4 | ELSE-IF | `else if(subkey.equalsIgnoreCase("enable"))` |
| 5 | RETURN | `return Boolean.class;` [L969] |
| 6 | ELSE-IF | `else if(subkey.equalsIgnoreCase("state"))` |
| 7 | RETURN | `return String.class;` [L972] |

**Block 3.9** — [ELSE-IF] `"割引終了日"` (wrib_endymd) (L976) — ANK-4195

> The discount end date field — when the discount promotion expires (YYYY-MM-DD format).

| # | Type | Code |
|---|------|------|
| 1 | ELSE-IF | `else if(key.equals("割引終了日"))` // Field: wrib_endymd [ANK-4195] [L976] |
| 2 | ELSE-IF | `else if(subkey.equalsIgnoreCase("value"))` |
| 3 | RETURN | `return String.class;` [L978] |
| 4 | ELSE-IF | `else if(subkey.equalsIgnoreCase("enable"))` |
| 5 | RETURN | `return Boolean.class;` [L981] |
| 6 | ELSE-IF | `else if(subkey.equalsIgnoreCase("state"))` |
| 7 | RETURN | `return String.class;` [L984] |

**Block 3.10** — [ELSE-IF] `"セット割申請経路名"` (wrib_shin_route_nm) (L988) — ANK-4195

> The set discount application route name field — identifies the channel/path through which a bundled-discount application was submitted.

| # | Type | Code |
|---|------|------|
| 1 | ELSE-IF | `else if(key.equals("セット割申請経路名"))` // Field: wrib_shin_route_nm [ANK-4195] [L988] |
| 2 | ELSE-IF | `else if(subkey.equalsIgnoreCase("value"))` |
| 3 | RETURN | `return String.class;` [L990] |
| 4 | ELSE-IF | `else if(subkey.equalsIgnoreCase("enable"))` |
| 5 | RETURN | `return Boolean.class;` [L993] |
| 6 | ELSE-IF | `else if(subkey.equalsIgnoreCase("state"))` |
| 7 | RETURN | `return String.class;` [L996] |

**Block 3.11** — [ELSE-IF] `"セット割対象区分"` (wrib_trgt_div) (L1000) — ANK-4195

> The set discount target scope field — defines which items/customers are eligible for the bundled discount.

| # | Type | Code |
|---|------|------|
| 1 | ELSE-IF | `else if(key.equals("セット割対象区分"))` // Field: wrib_trgt_div [ANK-4195] [L1000] |
| 2 | ELSE-IF | `else if(subkey.equalsIgnoreCase("value"))` |
| 3 | RETURN | `return String.class;` [L1002] |
| 4 | ELSE-IF | `else if(subkey.equalsIgnoreCase("enable"))` |
| 5 | RETURN | `return Boolean.class;` [L1005] |
| 6 | ELSE-IF | `else if(subkey.equalsIgnoreCase("state"))` |
| 7 | RETURN | `return String.class;` [L1008] |

---

**Block 4** — [RETURN] No match fallback (L1013)

> If the key does not match any of the 11 known field names, return null. This is the default case indicating the framework should skip type resolution for unrecognized fields.

| # | Type | Code |
|---|------|------|
| 1 | RETURN | `return null;` // 条件に一致するプロパティが存在しない場合は、nullを返す (Return null if no matching property exists) [L1013] |

## 7. Glossary

| Term | Type | Business Meaning |
|------|------|------------------|
| `dsp_campaign_cd` | Field | Display Campaign Code — the identifier for a marketing/service campaign as shown to customers |
| `wrib_svc_nm` | Field | Discount Service Name — the name of a service eligible for discount pricing |
| `svc_sta_ymd` | Field | Service Start Date (YYYY-MM-DD) — when the telecom service contract begins |
| `svc_endymd` | Field | Service End Date (YYYY-MM-DD) — when the telecom service contract terminates |
| `mskm_ymd` | Field | Application Date (YYYY-MM-DD) — when the customer submitted their service application |
| `knrn_svc_kei_no` | Field | Related Customer Service Contract Number — links a campaign to a customer's service line item |
| `status_nm` | Field | Status Name — human-readable label for the current status of a campaign or service |
| `wrib_staymd` | Field | Discount Start Date (YYYY-MM-DD) — when a discount promotion becomes effective |
| `wrib_endymd` | Field | Discount End Date (YYYY-MM-DD) — when a discount promotion expires |
| `wrib_shin_route_nm` | Field | Discount Application Route Name — the channel/path (e.g., web, store, phone) used to apply for a bundled discount |
| `wrib_trgt_div` | Field | Discount Target Scope — classification of which services or customers are subject to the discount |
| X33 | Framework | X33 View Framework — K-Opticom's proprietary web view/data-binding framework for telecom billing screens |
| `X33VDataTypeBeanInterface` | Interface | Contract that data-type beans must implement to support framework-driven data binding and type resolution |
| DBean | Abbreviation | Data Bean — a view-layer bean that holds type and data metadata for X33 data binding |
| `modelData` | Method | The parent bean's dispatch method that creates DBean instances for list-type fields like "Campaign List" |
| ANK-3521 | Ticket/Feature | Feature ticket (2018/12/21) that added "Related Customer Number" field to the campaign data model |
| ANK-4195 | Ticket/Feature | Feature ticket that added status name, discount dates, application route, and target scope fields |
| `キャンペーン一覧` | Japanese | Campaign List — the list-type field containing campaign entries, each represented as a KKW22301SF02DBean instance |
| 項目名 (key) | Japanese | Item Name — the business field identifier passed as the `key` parameter |
| サブキー (subkey) | Japanese | Sub-Key — the metadata property within a field (value, enable, or state) passed as the `subkey` parameter |
| セット割 | Business term | Set Discount (Settlement Discount) — a bundled-service discount offering reduced pricing when multiple telecom services are contracted together |
