# (DD02) Module: com.github.blaxk3.api — Detailed Design [41 LOC]

## Module Overview
The `com.github.blaxk3.api` module provides a small HTTP client wrapper for the ExchangeRate-API service. It is responsible for loading the API key from application resources, constructing service URLs, issuing GET requests, and extracting currency metadata or conversion results from the returned JSON payloads.

The module currently contains a single integration class, `CurrencyRateAPI`, which acts as a thin facade over three concerns: configuration loading, remote request execution, and JSON response interpretation. The class is stateless apart from a logger, so each method operates independently and can be invoked from higher-level UI or service code whenever exchange-rate data is needed.

---

## Class: CurrencyRateAPI

### Class Summary
| Field | Value |
|-------|-------|
| FQN | `com.github.blaxk3.api.CurrencyRateAPI` |
| Layer | API integration / external service client |
| Methods | 5 |

### Method: getJsonObject(URL url)

#### 1. Role
This method sends a GET request to the supplied URL and converts a successful HTTP response into a `JsonObject`. It is the main low-level transport method used by the class, and it centralizes the network and JSON parsing work for the rest of the API wrapper.

If the request fails or the response code is not `200 OK`, the method logs the failure and returns `null`. That makes it a shared error boundary for all upstream currency operations.

#### 2. Processing Pattern
```mermaid
flowchart TD
    A["Start"] --> B["Accept URL input"]
    B --> C["Open HTTP connection"]
    C --> D["Set request method to GET"]
    D --> E["Read response code"]
    E --> F{Response code is 200 OK}
    F -->|Yes| G["Parse response stream into JsonElement"]
    G --> H["Convert JsonElement to JsonObject"]
    H --> I["Return JsonObject"]
    F -->|No| J["Log response code error"]
    J --> K["Return null"]
    E --> L{Exception thrown}
    L -->|Yes| M["Log request failure"]
    M --> K
```

#### 3. Parameter Analysis
| Parameter | Type | Meaning | Validation / Constraints |
|-----------|------|---------|--------------------------|
| `url` | `URL` | Fully formed remote endpoint to call | Must be non-null and reachable; method assumes it can be opened as an `HttpURLConnection` |

#### 4. CRUD Operations / Called Services
| Dependency / Service | Operation | Purpose |
|----------------------|-----------|---------|
| Remote ExchangeRate API endpoint | Read | Fetches JSON data over HTTP GET |
| `Logger` | Create / Read | Writes diagnostics for HTTP failures and exceptions |
| `JsonParser` / Gson | Read | Parses the HTTP response body into JSON objects |

#### 5. Dependency Trace
| Caller / Entry Point | Trace |
|----------------------|-------|
| `getCurrencyCode()` | Calls `getJsonObject(new URI(getURL() + "/latest/" + "USD").toURL())` |
| `convert(String, String, BigDecimal)` | Calls `getJsonObject(new URI(getURL() + "/pair/..." ).toURL())` |
| External integration code | Can call this method directly with any valid API URL |

#### 6. Per-Branch Detail Blocks
- Success branch
  - Open connection and execute HTTP GET
  - Confirm `HTTP_OK`
  - Parse the response stream into a JSON tree
  - Return the root object to the caller
- Non-OK branch
  - Detect a non-200 response code
  - Emit an error log with the response code
  - Return `null` so callers can handle the absence of data
- Exception branch
  - Catch any runtime or I/O-related exception during request setup or parsing
  - Log the failure with stack trace
  - Return `null`

### Method: getApiKeyService()

#### 1. Role
This method loads the API key from the `config.properties` resource on the application classpath. It is the configuration access point for the module and ensures the API secret is not hardcoded in business logic.

The method returns the value stored under `API_KEY`, or `null` if the resource is missing or cannot be loaded. Downstream URL construction depends on this value being available.

#### 2. Processing Pattern
```mermaid
flowchart TD
    A["Start"] --> B["Create Properties object"]
    B --> C["Load config.properties from classpath"]
    C --> D{Resource found}
    D -->|No| E["Log missing config.properties"]
    E --> F["Return null"]
    D -->|Yes| G["Load properties"]
    G --> H["Read API_KEY property"]
    H --> I["Return API key value"]
    G --> J{IOException thrown}
    J -->|Yes| K["Log load failure"]
    K --> F
```

#### 3. Parameter Analysis
| Parameter | Type | Meaning | Validation / Constraints |
|-----------|------|---------|--------------------------|
| None | - | This method requires no arguments | It depends on the presence of `config.properties` in the runtime classpath |

#### 4. CRUD Operations / Called Services
| Dependency / Service | Operation | Purpose |
|----------------------|-----------|---------|
| ClassLoader resource stream | Read | Loads `config.properties` from the classpath |
| `Properties` | Read | Parses key-value pairs from the configuration file |
| `Logger` | Create | Logs missing-resource and I/O failure conditions |

#### 5. Dependency Trace
| Caller / Entry Point | Trace |
|----------------------|-------|
| `getURL()` | Calls `getApiKeyService()` to embed the key in the base URL |
| Any code building ExchangeRate-API URLs | Relies on this method for secret retrieval |

#### 6. Per-Branch Detail Blocks
- Resource found branch
  - Open the classpath stream for `config.properties`
  - Load all properties into a `Properties` instance
  - Read the `API_KEY` entry and return it
- Missing resource branch
  - Detect that the stream is `null`
  - Log an error that the configuration file was not found
  - Return `null`
- I/O exception branch
  - Catch `IOException` during property loading
  - Log the failure and stack trace
  - Return `null`

### Method: getCurrencyCode()

#### 1. Role
This method requests the latest USD exchange-rate dataset and extracts the list of available currency codes from the `conversion_rates` object. It provides the application with a catalog of supported currencies, which can be used to populate dropdowns or validate user selections.

The method is a convenience wrapper over the lower-level JSON request method. It also performs a small amount of structural validation before returning the extracted keys.

#### 3. Parameter Analysis
| Parameter | Type | Meaning | Validation / Constraints |
|-----------|------|---------|--------------------------|
| None | - | No explicit arguments are accepted | The method depends on a valid API key, a reachable endpoint, and a JSON response containing `conversion_rates` |

#### 4. CRUD Operations / Called Services
| Dependency / Service | Operation | Purpose |
|----------------------|-----------|---------|
| `getJsonObject(URL)` | Read | Retrieves the latest USD exchange-rate JSON document |
| ExchangeRate API `/latest/USD` endpoint | Read | Supplies currency rate metadata |
| `JsonObject` | Read | Extracts the `conversion_rates` object and its keys |

#### 5. Dependency Trace
| Caller / Entry Point | Trace |
|----------------------|-------|
| Higher-level UI or service code | Invokes this method to populate supported currency lists |
| `getJsonObject(URL)` | Downstream dependency used to fetch the response |

#### 6. Per-Branch Detail Blocks
- Successful extraction branch
  - Build the `/latest/USD` URL from the base service URL
  - Fetch the JSON object
  - Confirm the payload contains `conversion_rates`
  - Convert the key set to a `String[]`
- Missing payload branch
  - Detect a `null` JSON response or missing `conversion_rates`
  - Return `null` to signal unavailable codes
- Empty object branch
  - Detect an empty `conversion_rates` object
  - Return `null` rather than an empty array, preserving current behavior

### Method: getURL()

#### 1. Role
This helper assembles the base ExchangeRate-API URL by combining the fixed service prefix with the API key retrieved from configuration. It is a small composition method that isolates URL construction from the rest of the class.

Although simple, it is a critical dependency for every remote call in the module because all endpoint paths are appended to this base string. A missing API key therefore propagates into all higher-level request methods.

#### 3. Parameter Analysis
| Parameter | Type | Meaning | Validation / Constraints |
|-----------|------|---------|--------------------------|
| None | - | No explicit arguments are accepted | The returned value is only useful when `getApiKeyService()` yields a valid key |

#### 4. CRUD Operations / Called Services
| Dependency / Service | Operation | Purpose |
|----------------------|-----------|---------|
| `getApiKeyService()` | Read | Retrieves the configured API key |
| String concatenation | Create | Builds the base API endpoint |

#### 5. Dependency Trace
| Caller / Entry Point | Trace |
|----------------------|-------|
| `getCurrencyCode()` | Uses `getURL()` before appending `/latest/USD` |
| `convert(String, String, BigDecimal)` | Uses `getURL()` before appending `/pair/...` |

#### 6. Per-Branch Detail Blocks
- Normal branch
  - Read the API key from configuration
  - Prefix it with the ExchangeRate-API base path
  - Return the composed service root
- Missing key branch
  - If the API key is `null`, the returned URL still contains the `null` token
  - Downstream methods may then fail during HTTP access

### Method: convert(String foreignCurrency1, String foreignCurrency2, BigDecimal amount)

#### 1. Role
This method requests a currency conversion result for a specific source currency, target currency, and amount. It is the primary business-facing operation in the class because it performs the actual exchange-rate lookup and returns the conversion result as a string.

The method delegates all transport and JSON parsing work to `getJsonObject(URL)` and then directly reads the `conversion_result` field from the returned payload. Because it does not perform null protection after the fetch, callers must rely on a successful API response.

#### 3. Parameter Analysis
| Parameter | Type | Meaning | Validation / Constraints |
|-----------|------|---------|--------------------------|
| `foreignCurrency1` | `String` | Source currency code | Expected to match ExchangeRate-API currency identifiers |
| `foreignCurrency2` | `String` | Target currency code | Expected to match ExchangeRate-API currency identifiers |
| `amount` | `BigDecimal` | Quantity to convert | Should be non-null and numerically valid for the API endpoint |

#### 4. CRUD Operations / Called Services
| Dependency / Service | Operation | Purpose |
|----------------------|-----------|---------|
| `getJsonObject(URL)` | Read | Retrieves the pair-conversion JSON payload |
| ExchangeRate API `/pair/{from}/{to}/{amount}` endpoint | Read | Performs the remote conversion calculation |
| `JsonObject` | Read | Extracts `conversion_result` from the response |

#### 5. Dependency Trace
| Caller / Entry Point | Trace |
|----------------------|-------|
| UI conversion action | Calls this method to calculate a currency conversion |
| Service/controller layer | Passes selected currencies and amount into this method |
| `getJsonObject(URL)` | Fetches the remote response used for the result |

#### 6. Per-Branch Detail Blocks
- Success branch
  - Compose the `/pair/{from}/{to}/{amount}` URL
  - Fetch the JSON response
  - Read the `conversion_result` member
  - Return the value as a string
- Failure branch
  - If the request fails or returns `null`, dereferencing the result can raise an exception
  - Current implementation does not guard against this path

---

## Module Relationships
- `getApiKeyService()` feeds `getURL()` with the secret needed for all service calls.
- `getJsonObject(URL)` is the shared transport primitive for both `getCurrencyCode()` and `convert(...)`.
- `getCurrencyCode()` and `convert(...)` are the externally useful operations that higher layers are expected to invoke.

## Design Notes
- The class is stateless and can be instantiated on demand.
- Error handling is intentionally conservative: failures are logged and often propagated as `null` values rather than wrapped in custom exceptions.
- The current implementation assumes the upstream API response schema is stable and that `conversion_result` and `conversion_rates` are present when requests succeed.
