---
# (DD07) Business Logic — PatternAExtractor.extract() [35 LOC]

| Field | Value |
|-------|-------|
| Fully Qualified Name | `com.optage.parser.PatternAExtractor` |
| Layer | Utility |
| Module | `parser` (Package: `com.optage.parser`) |

## 1. Role

### PatternAExtractor.extract()

`PatternAExtractor.extract()` is a source-code annotation parser that scans a text block line by line and converts matched `START` / `END` marker pairs into structured `ChangeMarker` records. In business terms, it is responsible for identifying change history boundaries in code comments and capturing the metadata associated with each completed change entry, including ticket identifier, operation type, author, version, date, and source line range.

The method implements a simple routing and correlation pattern: it first remembers the line number for each `START` marker, then waits until the corresponding `END` marker appears before creating an output object. This means the method does not emit partial results; it only produces a `ChangeMarker` when both ends of the marker pair are present in the input. The method also delegates metadata extraction to helper methods for version, author, and date resolution, which keeps the main loop focused on marker pairing logic.

Within the larger system, this method acts as a reusable parsing utility for downstream extractors and tests that need standardized change-marker detection from textual source content. It is not tied to a specific screen, batch, or database operation; instead, it serves as a domain-neutral transformer that turns raw comment lines into a business-friendly list of change records. Its behavior is deterministic and stateless except for the local start-marker map used to correlate paired markers during one invocation.

## 2. Processing Pattern (Detailed Business Logic)

```mermaid
flowchart TD
    START["extract(code)"]
    INIT["Initialize markers list, split input into lines, initialize startMarkers map"]
    LOOP["For each line in code"]
    MATCHER["Create matcher from MARKER_PATTERN and test line"]
    FOUND{"matcher.find()"}
    GET_FIELDS["Read ticketId, opType, marker from regex groups"]
    IS_START{"marker == START"}
    PUT_START["Store start line in startMarkers using ticketId and opType"]
    IS_END{"marker == END"}
    HAS_KEY{"startMarkers contains matching key"}
    REMOVE_START["Remove start line and capture startLine"]
    CALL_VERSION["Call extractVersion(line)"]
    CALL_AUTHOR["Call extractAuthor(line)"]
    CALL_DATE["Call extractDate(line)"]
    CREATE_CM["Create ChangeMarker and add to markers"]
    END_NODE["Return markers"]
    START --> INIT
    INIT --> LOOP
    LOOP --> MATCHER
    MATCHER --> FOUND
    FOUND -->|Yes| GET_FIELDS
    FOUND -->|No| LOOP
    GET_FIELDS --> IS_START
    IS_START -->|Yes| PUT_START
    IS_START -->|No| IS_END
    PUT_START --> LOOP
    IS_END -->|Yes| HAS_KEY
    IS_END -->|No| LOOP
    HAS_KEY -->|Yes| REMOVE_START
    HAS_KEY -->|No| LOOP
    REMOVE_START --> CALL_VERSION
    CALL_VERSION --> CALL_AUTHOR
    CALL_AUTHOR --> CALL_DATE
    CALL_DATE --> CREATE_CM
    CREATE_CM --> LOOP
    LOOP -->|done| END_NODE
```

**Constant resolution:**
- `MARKER_PATTERN` = `//\\s*(?:v[\\d.]+)?\\s*([A-Z]+[-\\d]+)\\s+(ADD|MOD|DEL)\\s+(START|END)`
- `TICKET_PATTERN` exists in `PatternAExtractor` but is not used by this method.

## 3. Parameter Analysis

| No | Parameter Name | Type | Business Description |
|----|---------------|------|---------------------|
| 1 | `code` | `String` | Entire source text or comment text to be scanned for change-history markers. It may contain multiple lines of code comments, each of which can carry a `START` or `END` marker that contributes to a `ChangeMarker` record. The content drives all processing decisions: if no valid marker pair exists, the method returns an empty list. |

**Instance fields / external state read by the method:**
- `MARKER_PATTERN` regular expression used to detect marker lines.
- Local helper methods `extractVersion`, `extractAuthor`, and `extractDate` are invoked for metadata resolution.

## 4. CRUD Operations / Called Services

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

| CRUD | SC / CBS | SC Code | Entity / DB | Operation Description |
|------|----------|---------|-------------|----------------------|
| - | `PatternAExtractor.extractAuthor` | PatternAExtractor | - | Calls `extractAuthor` in `PatternAExtractor` |
| - | `PatternAExtractor.extractDate` | PatternAExtractor | - | Calls `extractDate` in `PatternAExtractor` |
| - | `PatternAExtractor.extractVersion` | PatternAExtractor | - | Calls `extractVersion` in `PatternAExtractor` |

This method does not perform CRUD against a database or external service. Its only callable dependencies are local helper methods that enrich the parsed marker with metadata values.

| CRUD | SC / CBS | SC Code | Entity / DB | Operation Description |
|------|----------|---------|-------------|----------------------|
| R | `PatternAExtractor.extractVersion` | PatternAExtractor | - | Reads version metadata from the `END` marker line before creating the output record. |
| R | `PatternAExtractor.extractAuthor` | PatternAExtractor | - | Reads author metadata from the `END` marker line before creating the output record. |
| R | `PatternAExtractor.extractDate` | PatternAExtractor | - | Reads date metadata from the `END` marker line before creating the output record. |

## 5. Dependency Trace

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

No screen/batch entry points found within 8 hops. Direct callers found: 8 methods.
Terminal operations from this method: `extractDate` [-], `extractAuthor` [-], `extractVersion` [-]

The available evidence shows that this method is called by sibling extractor and test code rather than by a business screen or batch entry point. The current trace set only proves direct usage by `PatternBExtractor`, `PatternCExtractor`, and test classes; no higher-level operational entry point was identified in the available graph summary.

| # | Caller (Screen/Batch) | Call Chain (Full Path to this Method) | Terminal (SC / CRUD / Entity) |
|---|----------------------|--------------------------------------|-------------------------------|
| 1 | Utility: `PatternBExtractor` | `PatternBExtractor` -> `PatternAExtractor.extract` | `extractVersion [R] -`, `extractAuthor [R] -`, `extractDate [R] -` |
| 2 | Utility: `PatternCExtractor` | `PatternCExtractor` -> `PatternAExtractor.extract` | `extractVersion [R] -`, `extractAuthor [R] -`, `extractDate [R] -` |
| 3 | Test: `PatternAExtractorTest` | `PatternAExtractorTest` -> `PatternAExtractor.extract` | `extractVersion [R] -`, `extractAuthor [R] -`, `extractDate [R] -` |
| 4 | Test: `PatternBExtractorTest` | `PatternBExtractorTest` -> `PatternAExtractor.extract` | `extractVersion [R] -`, `extractAuthor [R] -`, `extractDate [R] -` |
| 5 | Test: `PatternCExtractorTest` | `PatternCExtractorTest` -> `PatternAExtractor.extract` | `extractVersion [R] -`, `extractAuthor [R] -`, `extractDate [R] -` |
| 6 | Test: `IntegrationTest` | `IntegrationTest` -> `PatternAExtractor.extract` | `extractVersion [R] -`, `extractAuthor [R] -`, `extractDate [R] -` |

## 6. Per-Branch Detail Blocks

**Block 1** — [FOR] `(for each line in code)` (L21)

> Scans the input text one line at a time to detect candidate marker comments.

| # | Type | Code |
|---|------|------|
| 1 | SET | `String line = lines[i];` |
| 2 | SET | `Matcher matcher = MARKER_PATTERN.matcher(line);` [-> `MARKER_PATTERN="//\\s*(?:v[\\d.]+)?\\s*([A-Z]+[-\\d]+)\\s+(ADD|MOD|DEL)\\s+(START|END)`] |
| 3 | EXEC | `matcher.find();` |
| 4 | BRANCH | `if (matcher.find())` |

**Block 1.1** — [IF] `(matcher.find() == true)` (L24)

> Parses marker metadata only when the line matches the expected change-comment format.

| # | Type | Code |
|---|------|------|
| 1 | SET | `String ticketId = matcher.group(1);` |
| 2 | SET | `String opType = matcher.group(2);` |
| 3 | SET | `String marker = matcher.group(3);` |

**Block 1.1.1** — [IF] `(marker.equals("START"))` (L28)

> Stores the start line for a matching ticket and operation type.

| # | Type | Code |
|---|------|------|
| 1 | EXEC | `"START".equals(marker);` |
| 2 | SET | `startMarkers.put(ticketId + "_" + opType, i);` |

**Block 1.1.2** — [ELSE-IF] `(marker.equals("END"))` (L30)

> Completes a marker pair when the corresponding start entry has already been seen.

| # | Type | Code |
|---|------|------|
| 1 | EXEC | `"END".equals(marker);` |
| 2 | SET | `String key = ticketId + "_" + opType;` |
| 3 | BRANCH | `if (startMarkers.containsKey(key))` |

**Block 1.1.2.1** — [IF] `(startMarkers.containsKey(key))` (L32)

> Correlates the `END` line with the remembered `START` line and enriches the record with parsed metadata.

| # | Type | Code |
|---|------|------|
| 1 | SET | `int startLine = startMarkers.remove(key);` |
| 2 | CALL | `String version = extractVersion(line);` |
| 3 | CALL | `String author = extractAuthor(line);` |
| 4 | CALL | `String date = extractDate(line);` |
| 5 | SET | `ChangeMarker cm = new ChangeMarker(ticketId, version, opType, author, date, startLine, i);` |
| 6 | EXEC | `markers.add(cm);` |

**Block 1.1.3** — [ELSE] `(marker is neither START nor END)` (L28-L44)

> Ignores unrelated marker text and continues scanning.

| # | Type | Code |
|---|------|------|
| 1 | EXEC | `continue loop to next line` |

**Block 2** — [RETURN] `(end of method)` (L51)

> Returns all completed `ChangeMarker` entries gathered during the scan.

| # | Type | Code |
|---|------|------|
| 1 | RETURN | `return markers;` |

## 7. Glossary

| Term | Type | Business Meaning |
|------|------|------------------|
| `code` | Field / Input | Full source text being inspected for embedded change markers. |
| `markers` | Variable | Accumulator list of completed change history records. |
| `startMarkers` | Variable | In-memory correlation map that stores the line number of each `START` marker until its `END` pair is found. |
| `ticketId` | Field | Issue or ticket identifier extracted from a marker comment. |
| `opType` | Field | Operation category for the change entry, such as add, modify, or delete. |
| `marker` | Field | Marker boundary indicator; expected values are `START` or `END`. |
| `startLine` | Field | Zero-based line index where the corresponding `START` marker was found. |
| `ChangeMarker` | Domain object | Structured output representing one completed change-history record. |
| `MARKER_PATTERN` | Constant / Regex | Regular expression that detects marker comments and extracts ticket, operation, and boundary type. |
| `START` | Business term | Beginning boundary of a change-history annotation pair. |
| `END` | Business term | Ending boundary of a change-history annotation pair. |
| `ADD` | Business term | Operation type indicating a new change or addition. |
| `MOD` | Business term | Operation type indicating a modification. |
| `DEL` | Business term | Operation type indicating a deletion. |
| `version` | Field | Version string extracted from the marker line for release traceability. |
| `author` | Field | Author name extracted from the marker line for accountability. |
| `date` | Field | Date value extracted from the marker line for chronology and auditability. |
| `extractVersion` | Helper method | Internal parser that reads version information from the marker line. |
| `extractAuthor` | Helper method | Internal parser that reads author information from the marker line. |
| `extractDate` | Helper method | Internal parser that reads date information from the marker line. |
| `parser` | Package | Source-code parsing utility area within the application. |
| `Utility` | Layer | Shared helper logic with no direct screen, batch, or persistence responsibility. |
