# (DD10) Business Logic — NumericFilter.isValid() [17 LOC]

| Field | Value |
|-------|-------|
| Fully Qualified Name | `com.github.blaxk3.ui.NumericFilter.isValid(String)` |
| Layer | Controller (UI Framework — `com.github.blaxk3.ui`) |
| Module | `ui` (Package: `com.github.blaxk3.ui`) |

## 1. Role

### NumericFilter.isValid()

`NumericFilter.isValid()` is a private input-validation method embedded within the `NumericFilter` inner class, which extends `javax.swing.text.DocumentFilter`. It serves as the gatekeeper for all text mutations on the numeric input `JTextField` used in the UI. Its sole responsibility is to determine whether the given text string — representing the full proposed content of the text field after a user action — constitutes a valid numeric value. A valid value consists of digits (0–9) and at most one decimal point (`.`). The method implements a **guard clause** design pattern: it returns `true` to permit the edit or `false` to reject it. Its role in the larger system is as a **user-facing data integrity filter** within a Swing desktop application that deals with numeric/rate display (as indicated by the `CurrencyRateAPI` dependency in the outer class). It is called by both `insertString` (when a user types a character) and `replace` (when a user pastes or backspaces text), ensuring the text field never contains invalid input.

## 2. Processing Pattern (Detailed Business Logic)

```mermaid
flowchart TD
    START(["isValid(String text)"])

    START --> C1{"Is text empty?"}

    C1 -->|true| R1["Return true"]
    C1 -->|false| INIT["decimalCount = 0
i = 0"]

    INIT --> LOOP{"i < text.length()"}

    LOOP -->|false| R2["Return true"]
    LOOP -->|true| CH["ch = text.charAt(i)"]

    CH --> D1{"ch == '.'
AND
decimalCount != 1?"}

    D1 -->|true| INC["decimalCount++"]
    INC --> ADV["i++"]

    D1 -->|false| N1{"!Character.isDigit(ch)"}

    N1 -->|true| R3["Return false"]
    N1 -->|false| ADV

    ADV --> LOOP
    R1 --> END(["END"])
    R2 --> END
    R3 --> END
```

**Processing Summary:**

1. **Guard clause for empty text** — If the text is empty, return `true` immediately. An empty field is considered valid (it may be waiting for user input).
2. **Initialization** — Set a character scan index `i` to `0` and a decimal-point counter `decimalCount` to `0`.
3. **Character-by-character scan loop** — Iterate through every character of the input string:
   - **Decimal point check**: If the character is a period (`.`) and no decimal point has been seen yet (`decimalCount != 1`), increment the decimal counter. This allows exactly one decimal point.
   - **Non-digit check**: If the character is neither a digit nor an allowed decimal point, return `false` immediately — the text is invalid.
   - **Valid digit**: If the character is a valid digit (and not a second decimal point), continue scanning.
4. **Final result** — If the loop completes without encountering an invalid character, return `true` (the text is a valid numeric string).

## 3. Parameter Analysis

| No | Parameter Name | Type | Business Description |
|----|---------------|------|---------------------|
| 1 | `text` | `String` | The full proposed content of the numeric text field, including both the existing text and the newly inserted/replaced characters. It represents what the text field would display if the user's edit were accepted. Acceptable values are strings containing only digits (`0-9`) and at most one decimal point (`.`). An empty string is accepted as valid (indicating the field is being cleared). |

**No instance fields or external state** are read by this method. It is a pure function — its return value depends entirely on the content of the `text` parameter.

## 4. CRUD Operations / Called Services

This method performs **pure UI-level input validation**. It does not invoke any service components, database operations, or external APIs. All operations are local character inspection using Java standard library methods.

| CRUD | SC / CBS | SC Code | Entity / DB | Operation Description |
|------|----------|---------|-------------|----------------------|
| — | (none) | — | — | No CRUD operations. This method is a pure validation function. It calls `String.isEmpty()`, `String.length()`, `String.charAt()`, and `Character.isDigit()` — all standard Java library methods with no data persistence. |

## 5. Dependency Trace

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

No external callers found. Direct callers found: 2 methods (both within the same inner class).
Terminal operations from this method: -

Trace who calls this method and what this method ultimately calls.

| # | Caller (Screen/Batch) | Call Chain (Full Path to this Method) | Terminal (SC / CRUD / Entity) |
|---|----------------------|--------------------------------------|-------------------------------|
| 1 | N/A (Internal UI) | `NumericFilter.insertString` -> `isValid` | No external calls |
| 2 | N/A (Internal UI) | `NumericFilter.replace` -> `isValid` | No external calls |

**Explanation:**
- `NumericFilter` is an inner class of `UI` (which extends `javax.swing.JFrame`).
- It is attached as a `DocumentFilter` to a `JTextField` via `setDocumentFilter(new NumericFilter())` in the `textField()` method.
- The `isValid()` method is `private` and is called exclusively by the two overridden `DocumentFilter` methods: `insertString` (line 177) and `replace` (line 190).
- There are no external callers from screen controllers, batch processes, or service components.
- `isValid` itself calls no service methods, so there is no terminal endpoint to trace further.

## 6. Per-Branch Detail Blocks

**Block 1** — IF `(condition: text.isEmpty())` (L197)

> Guard clause: reject edits that result in empty text.

| # | Type | Code |
|---|------|------|
| 1 | COND | `text.isEmpty()` |
| 2 | RETURN | `return true` // Accept empty text — field can be cleared |

**Block 2** — INITIALIZATION (L199–200)

> Initialize loop variables for character-by-character validation.

| # | Type | Code |
|---|------|------|
| 1 | SET | `byte decimalCount = 0` // Tracks number of decimal points encountered (max 1) |
| 2 | SET | `for (int i = 0; i < text.length(); i++)` // Iterate over each character |

**Block 2.1** — FOR LOOP BODY: CHARACTER EXTRACTION (L201)

> Extract the current character for inspection.

| # | Type | Code |
|---|------|------|
| 1 | SET | `char ch = text.charAt(i)` // Get character at current index |

**Block 2.2** — FOR LOOP BODY: DECIMAL POINT CHECK (L202–204)

> Allow at most one decimal point. If a second `.` is encountered, the condition fails and falls through to the non-digit check.

| # | Type | Code |
|---|------|------|
| 1 | COND | `ch == '.' && decimalCount != 1` // Is this a period and have we not yet seen one? |
| 2 | SET | `decimalCount++` // Mark that we've now seen one decimal point |

**Block 2.3** — FOR LOOP BODY: NON-DIGIT CHECK (L205–206)

> If the character is not a digit (and not an allowed decimal point), the text is invalid.

| # | Type | Code |
|---|------|------|
| 1 | COND | `!Character.isDigit(ch)` // Is this character NOT a digit 0-9? |
| 2 | RETURN | `return false` // Reject: contains invalid character (e.g., letters, special symbols) |

**Block 3** — FINAL RETURN (L208)

> If all characters passed validation, the text is a valid numeric string.

| # | Type | Code |
|---|------|------|
| 1 | RETURN | `return true` // All characters are valid: digits and at most one '.' |

## 7. Glossary

| Term | Type | Business Meaning |
|------|------|------------------|
| `NumericFilter` | Class | A Swing `DocumentFilter` that restricts user input to numeric characters only on a text field |
| `DocumentFilter` | Java API Class | Part of `javax.swing.text` — intercepts all text modifications in a `JTextComponent` to allow filtering |
| `insertString` | Override Method | `DocumentFilter` callback invoked when a user types a character; validates the full resulting text before committing |
| `replace` | Override Method | `DocumentFilter` callback invoked when text is replaced (paste, backspace, drag-drop); validates the full resulting text before committing |
| `JTextField` | Java UI Component | A single-line text input widget in Swing; the `DocumentFilter` is attached to restrict what characters can be entered |
| `Decimal point` | Domain concept | The `.` character allowed at most once in the numeric input; enables decimal number entry (e.g., "3.14") |
| `Character.isDigit` | Java API Method | Returns `true` if the character is a Unicode digit (`0-9`); used to validate each input character |
| `UI` | Class | The main Swing `JFrame` window class containing the application's user interface |
| `CurrencyRateAPI` | External dependency | An API client used by the outer `UI` class to fetch currency exchange rates (indicates the application is a currency/rate tool) |
