# (DD09) Business Logic — CurrencyRateAPI.getCurrencyCode() [10 LOC]

| Field | Value |
|-------|-------|
| Fully Qualified Name | `com.github.blaxk3.api.CurrencyRateAPI` |
| Layer | Utility (Package: `com.github.blaxk3.api` — external API client wrapper) |
| Module | `api` (Package: `com.github.blaxk3.api`) |

## 1. Role

### CurrencyRateAPI.getCurrencyCode()

This method retrieves the complete set of supported currency codes from the Exchangerate API v6, a third-party foreign exchange rate data service. It constructs a URL pointing to the `/latest/USD` endpoint of the API (using USD as the base currency), performs an authenticated HTTP GET request via `getJsonObject()`, parses the JSON response, and extracts the set of currency code keys from the `conversion_rates` object contained in the response.

The method serves as a discovery endpoint: it does not perform currency conversion itself, but instead returns the catalog of all currency codes that the API supports. This allows downstream consumers (e.g., currency conversion screens, batch reporting jobs, or rate lookup utilities) to determine which currencies are available before attempting actual conversion operations.

It implements the **delegation pattern**: it delegates URL construction to `getURL()`, the HTTP communication and JSON parsing to `getJsonObject()`, and returns the raw result without additional transformation. The method is a thin wrapper that coordinates two internal API-client methods and transforms the external JSON response into a simple `String[]` of currency code names (e.g., `"USD"`, `"EUR"`, `"JPY"`).

In the larger system, this method acts as a shared utility invoked by components that need to validate or enumerate available currencies. It is a read-only operation with no side effects, making it suitable for pre-flight checks, dropdown population in UI screens, or integration validation.

## 2. Processing Pattern (Detailed Business Logic)

```mermaid
flowchart TD
    START(["getCurrencyCode()"])
    A["Build API URL : getURL() + /latest/USD"]
    B["getJsonObject(url)"]
    C{"jsonObject not null and conversion_rates exists"}
    D["Extract conversion_rates JsonObject"]
    E{"code not null and keySet not empty"}
    F["Return code.keySet().toArray"]
    G["Return null"]
    END_NODE(["Return / Next"])

    START --> A --> B --> C
    C -- true --> D --> E
    C -- false --> G --> END_NODE
    E -- true --> F --> END_NODE
    E -- false --> G --> END_NODE
```

**Processing Description:**

1. **URL Construction**: The method builds a full API endpoint URL by concatenating the base URL (obtained from `getURL()`, which internally combines the Exchangerate API base with the API key from `config.properties`) with the path `/latest/USD`. This targets the "latest exchange rates" endpoint with USD as the base currency.

2. **API Call**: It passes the constructed URL (as a `java.net.URI` converted to `java.net.URL`) to `getJsonObject()`, which performs an HTTP GET request, reads the response, and returns the parsed `JsonObject` containing exchange rate data.

3. **First Validation (Null + Key Check)**: The method verifies that the returned `JsonObject` is not null and that the `conversion_rates` field exists within it. If either condition fails (network error, authentication failure, unexpected API response structure), the method returns `null`.

4. **Extraction**: When the response is valid, it extracts the `conversion_rates` sub-object, which contains key-value pairs where keys are ISO 4217 currency codes (e.g., `"USD"`, `"EUR"`) and values are the exchange rates relative to USD.

5. **Second Validation (Non-empty Key Set)**: The method checks that the extracted `conversion_rates` object is not null and has at least one key. If the object is empty or null, it returns `null`.

6. **Return**: When all validations pass, the method returns an array of all currency code strings found in the `conversion_rates` key set.

## 3. Parameter Analysis

| No | Parameter Name | Type | Business Description |
|----|---------------|------|---------------------|
| - | (none) | - | This method takes no parameters. It is a parameterless query that fetches the full list of supported currency codes from the Exchangerate API. |
| 1 | `jsonObject` (local) | `JsonObject` | The parsed JSON response from the Exchangerate API containing exchange rate data, including the `conversion_rates` object with all supported currency codes. |
| 2 | `apiUrl` (implicit) | URL | The full API endpoint URL constructed from `getURL() + "/latest/" + "USD"`. Points to the Exchangerate API v6 `/latest/USD` endpoint. |
| 3 | `API_KEY` (via `getApiKeyService()`) | String | API key loaded from `config.properties` on the classpath. Used for authentication with the Exchangerate API. |

**External State Read:**
- `config.properties` file (classpath resource) — contains `API_KEY` property used for Exchangerate API authentication.

## 4. CRUD Operations / Called Services

### Pre-computed evidence from code analysis graph:

| CRUD | SC / CBS | SC Code | Entity / DB | Operation Description |
|------|----------|---------|-------------|----------------------|
| R | `CurrencyRateAPI.getJsonObject` | CurrencyRateAPI | - | Calls `getJsonObject(url)` which performs an HTTP GET to the Exchangerate API and parses the JSON response |
| R | `CurrencyRateAPI.getURL` | CurrencyRateAPI | - | Calls `getURL()` which constructs the base API URL by appending the API key to the Exchangerate API endpoint |

**Classification Rationale:**
- `getURL()` — **Read**. Constructs and returns a URL string; no data mutation.
- `getJsonObject(url)` — **Read**. Performs an HTTP GET request to the external Exchangerate API and parses the JSON response. No create, update, or delete operation.

## 5. Dependency Trace

### Pre-computed evidence from code analysis graph:

No screen/batch entry points found within 8 hops. Direct callers found: 0 methods.
Terminal operations from this method: `getURL` [R], `getJsonObject` [R]

**Caller Analysis:**
No direct callers of `getCurrencyCode()` were found within 8 hops in the codebase. This method appears to be a leaf-level utility method available for invocation by external consumers (e.g., other modules not yet linked, test code, or future integration points). It functions as a self-contained API wrapper method that can be called from any component needing currency code discovery.

| # | Caller (Screen/Batch) | Call Chain (Full Path to this Method) | Terminal (SC / CRUD / Entity) |
|---|----------------------|--------------------------------------|-------------------------------|
| 1 | (No callers found) | — | `getURL [R] Exchangerate API`, `getJsonObject [R] Exchangerate API` |

## 6. Per-Branch Detail Blocks

**Block 1** — [CALL] `(line 62)`

> Constructs the API request URL and invokes the HTTP GET request to fetch exchange rate data from the Exchangerate API.

| # | Type | Code |
|---|------|------|
| 1 | SET | `jsonObject = getJsonObject(new URI(getURL() + "/latest/" + "USD").toURL())` |
| 2 | CALL | `getURL()` [R] — returns `https://v6.exchangerate-api.com/v6/{API_KEY}` |
| 3 | CALL | `new URI(baseURL + "/latest/" + "USD").toURL()` — constructs the `/latest/USD` endpoint |
| 4 | CALL | `getJsonObject(url)` [R] — performs HTTP GET, parses JSON, returns `JsonObject` or `null` |

**Block 2** — [IF] `(jsonObject != null && jsonObject.has("conversion_rates"))` (L63)

> Validates that the API response is non-null and contains the expected `conversion_rates` field. If the API call failed (network error, invalid API key, server error) or returned an unexpected JSON structure, this condition is false and the method returns `null`.

| # | Type | Code |
|---|------|------|
| 1 | EXEC | `jsonObject.has("conversion_rates")` — checks if the JSON root contains the `conversion_rates` key |

**Block 2.1** — [IF] `(code != null && !code.keySet().isEmpty())` (L65)

> Validates that the extracted `conversion_rates` object is not null and contains at least one currency code entry. If the API returned an empty `conversion_rates` object (e.g., due to an error response with an empty data object), this condition is false.

| # | Type | Code |
|---|------|------|
| 1 | SET | `code = jsonObject.getAsJsonObject("conversion_rates")` — extracts the nested `conversion_rates` JsonObject |
| 2 | EXEC | `code.keySet()` — gets the set of currency code keys (e.g., `{"USD", "EUR", "JPY", ...}`) |
| 3 | EXEC | `code.keySet().isEmpty()` — checks if the key set has no entries |

**Block 2.1.1** — [THEN] `(code != null && keySet not empty)` (L66)

> All validations passed. Returns the array of currency code strings extracted from the `conversion_rates` object. Each string is an ISO 4217 three-letter currency code.

| # | Type | Code |
|---|------|------|
| 1 | CALL | `code.keySet().toArray(new String[0])` — converts the key set to a `String[]` |
| 2 | RETURN | `String[]` — array of ISO 4217 currency codes (e.g., `["USD", "EUR", "JPY", "GBP", ...]`) |

**Block 2.1.2** — [ELSE] `(code == null || keySet empty)` (L66)

> The `conversion_rates` object was empty or null. No currency codes to return.

| # | Type | Code |
|---|------|------|
| 1 | RETURN | `null` — indicates the API returned no currency data |

**Block 2.2** — [ELSE] `(jsonObject == null || no conversion_rates)` (L63)

> The API call failed entirely or returned a response without `conversion_rates`. This occurs when `getJsonObject()` returns null due to HTTP errors, network failures, or malformed JSON.

| # | Type | Code |
|---|------|------|
| 1 | RETURN | `null` — indicates the API call produced no usable response |

## 7. Glossary

| Term | Type | Business Meaning |
|------|------|------------------|
| Exchangerate API | Service | Exchangerate-API.com v6 — a third-party REST API providing foreign exchange rate data, including real-time rates, historical data, and currency conversion. Uses API key authentication. |
| `/latest/USD` | Endpoint | Exchangerate API endpoint that returns the latest exchange rates with USD as the base currency. All rates are expressed as "1 USD = X [currency]" |
| `conversion_rates` | JSON Field | The `conversion_rates` object in the API response, containing key-value pairs where keys are ISO 4217 currency codes and values are the exchange rate from USD to that currency. |
| ISO 4217 | Standard | International standard for currency codes. Three-letter alphabetic codes (e.g., USD for US Dollar, EUR for Euro, JPY for Japanese Yen) and three-digit numeric codes. |
| API_KEY | Config | API authentication key for the Exchangerate API. Loaded from `config.properties` file on the classpath. Required for all API requests. |
| `config.properties` | Config File | Java Properties file on the classpath containing key-value pairs including the `API_KEY` used for Exchangerate API authentication. |
| `String[]` | Return Type | Array of ISO 4217 three-letter currency codes (e.g., `["USD", "EUR", "JPY", "GBP", "CNY"]`) representing all currencies supported by the Exchangerate API. |
| `java.net.URI` / `java.net.URL` | Java Class | Java networking classes used to construct and resolve the API endpoint URL. `URI` is used for parsing, then converted to `URL` for the HTTP connection. |
