---

# (DD12) Business Logic — PatternCExtractor.extract() [11 LOC]

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

## 1. Role

### PatternCExtractor.extract()

This method parses a free-form document string and extracts the structured metadata required to build a `FileHeader` object. In business terms, it reads the header area of a specification or change document, captures the system name, module name, and Japanese purpose summary, and also derives the revision history entries embedded in the text. The method acts as a pattern-based extractor: it does not interpret business rules deeply, but routes the input through a fixed set of regular-expression rules so that document metadata can be normalized for downstream display or indexing. It is a shared utility in the parser layer and is typically used when the system needs to convert human-authored document text into structured header data. The method has no branching business categories beyond the metadata fields it collects; all extraction paths are mandatory, and missing matches are represented as `null` or an empty revision list. The implementation also preserves empty placeholders for two `FileHeader` fields, indicating that this extractor is intentionally focused on the subset of header data relevant to Pattern C documents.

## 2. Processing Pattern (Detailed Business Logic)

```mermaid
flowchart TD
    START(["extract(code)"])
    F1["extractField(code, SYSTEM_NAME_PATTERN)"]
    F2["extractField(code, MODULE_NAME_PATTERN)"]
    F3["extractField(code, PURPOSE_PATTERN)"]
    F4["extractRevisions(code)"]
    R1{"matcher.find() in extractField"}
    R2{"matcher.find() in extractRevisions"}
    A1["Return FileHeader(systemName, moduleName, empty values, purposeJa, revisions.size(), revisions)"]
    START --> F1
    F1 --> R1
    R1 -->|true| F2
    R1 -->|false| F2
    F2 --> F3
    F3 --> F4
    F4 --> R2
    R2 -->|loop each matched revision line| R2
    R2 --> A1
```

The method performs four sequential extraction steps. First, it resolves the system name using the system-name pattern, then the module name, then the Japanese purpose statement, and finally the revision list. Each field extraction follows the same pattern-matching helper and either returns the first matched group or `null` if the text is absent. The revision extraction repeatedly scans the document for revision lines and accumulates them into a list. After all values are collected, the method constructs a `FileHeader` with the extracted values, two fixed empty-string placeholders, and the revision count derived from the list size.

## 3. Parameter Analysis

| No | Parameter Name | Type | Business Description |
|----|---------------|------|---------------------|
| 1 | `code` | `String` | Source document text to be parsed; it contains the header metadata, Japanese purpose description, and revision history lines that the extractor normalizes into a `FileHeader`. |

External state read by the method:
- `SYSTEM_NAME_PATTERN` — regular expression for the system name line
- `MODULE_NAME_PATTERN` — regular expression for the module name line
- `PURPOSE_PATTERN` — regular expression for the Japanese purpose summary
- `REVISION_PATTERN` — regular expression for revision history rows

## 4. CRUD Operations / Called Services

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

| CRUD | SC / CBS | SC Code | Entity / DB | Operation Description |
|------|----------|---------|-------------|----------------------|
| - | `PatternCExtractor.extractField` | PatternCExtractor | - | Calls `extractField` in `PatternCExtractor` |
| - | `PatternCExtractor.extractRevisions` | PatternCExtractor | - | Calls `extractRevisions` in `PatternCExtractor` |

Analyze all method calls within this method and classify each as a CRUD operation.

| CRUD | SC / CBS | SC Code | Entity / DB | Operation Description |
|------|----------|---------|-------------|----------------------|
| R | `PatternCExtractor.extractField` | PatternCExtractor | Regex pattern / input text | Reads the source text with a regular expression and extracts the first matching field value. |
| R | `PatternCExtractor.extractField` | PatternCExtractor | Regex pattern / input text | Reads the source text with a regular expression and extracts the first matching field value for module name. |
| R | `PatternCExtractor.extractField` | PatternCExtractor | Regex pattern / input text | Reads the source text with a regular expression and extracts the first matching purpose summary. |
| R | `PatternCExtractor.extractRevisions` | PatternCExtractor | Regex pattern / input text | Scans the source text for revision rows and builds an in-memory revision list. |
| C | `FileHeader` constructor | FileHeader | FileHeader object | Creates the final header DTO that carries extracted metadata and revision entries. |

## 5. Dependency Trace

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

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

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 | Test:PatternCExtractorTest | `PatternCExtractorTest.test*` -> `PatternCExtractor.extract` | `extractField [R] Regex pattern / input text`, `extractRevisions [R] Regex pattern / input text`, `FileHeader [C] FileHeader object` |
| 2 | Test:IntegrationTest | `IntegrationTest.test*` -> `PatternCExtractor.extract` | `extractField [R] Regex pattern / input text`, `extractRevisions [R] Regex pattern / input text`, `FileHeader [C] FileHeader object` |

## 6. Per-Branch Detail Blocks

**Block 1** — [SEQUENTIAL] `(extract(String code))` (L22)

> Main extraction flow that normalizes Pattern C document metadata into a `FileHeader`.

| # | Type | Code |
|---|------|------|
| 1 | CALL | `extractField(code, SYSTEM_NAME_PATTERN);` |
| 2 | CALL | `extractField(code, MODULE_NAME_PATTERN);` |
| 3 | CALL | `extractField(code, PURPOSE_PATTERN);` |
| 4 | CALL | `extractRevisions(code);` |
| 5 | SET | `new FileHeader(systemName, moduleName, "", "", purposeJa, revisions.size(), revisions);` |
| 6 | RETURN | `return new FileHeader(...);` |

**Block 1.1** — [CALL] `(extractField(code, SYSTEM_NAME_PATTERN))` (L23)

| # | Type | Code |
|---|------|------|
| 1 | EXEC | `pattern.matcher(code);` |
| 2 | EXEC | `matcher.find();` |
| 3 | RETURN | `return matcher.find() ? matcher.group(1).trim() : null;` |

**Block 1.1.1** — [CONDITIONAL] `(matcher.find())` (L30)

| # | Type | Code |
|---|------|------|
| 1 | EXEC | `matcher.group(1).trim();` |
| 2 | RETURN | `return matcher.find() ? matcher.group(1).trim() : null;` |

**Block 1.1.2** — [ELSE] `(no match found)` (L30)

| # | Type | Code |
|---|------|------|
| 1 | RETURN | `return matcher.find() ? matcher.group(1).trim() : null;` |

**Block 1.2** — [CALL] `(extractField(code, MODULE_NAME_PATTERN))` (L24)

| # | Type | Code |
|---|------|------|
| 1 | EXEC | `pattern.matcher(code);` |
| 2 | EXEC | `matcher.find();` |
| 3 | RETURN | `return matcher.find() ? matcher.group(1).trim() : null;` |

**Block 1.3** — [CALL] `(extractField(code, PURPOSE_PATTERN))` (L25)

| # | Type | Code |
|---|------|------|
| 1 | EXEC | `pattern.matcher(code);` |
| 2 | EXEC | `matcher.find();` |
| 3 | RETURN | `return matcher.find() ? matcher.group(1).trim() : null;` |

**Block 1.4** — [CALL] `(extractRevisions(code))` (L26)

| # | Type | Code |
|---|------|------|
| 1 | SET | `List<FileHeader.RevisionEntry> revisions = new ArrayList<>();` |
| 2 | EXEC | `REVISION_PATTERN.matcher(code);` |
| 3 | EXEC | `while (matcher.find())` |
| 4 | EXEC | `matcher.group(1);` |
| 5 | EXEC | `matcher.group(2);` |
| 6 | CALL | `new FileHeader.RevisionEntry("", "", author, null, description);` |
| 7 | EXEC | `revisions.add(...);` |
| 8 | RETURN | `return revisions;` |

**Block 1.4.1** — [WHILE] `(matcher.find())` (L40)

| # | Type | Code |
|---|------|------|
| 1 | SET | `String author = matcher.group(1);` |
| 2 | SET | `String description = matcher.group(2);` |
| 3 | CALL | `new FileHeader.RevisionEntry("", "", author, null, description);` |
| 4 | EXEC | `revisions.add(...);` |

## 7. Glossary

| Term | Type | Business Meaning |
|------|------|------------------|
| `FileHeader` | DTO | Structured header object that stores file metadata such as system name, module name, purpose, and revision count. |
| `code` | Field | Raw source document text being parsed by the extractor. |
| `systemName` | Field | System name extracted from the document header. |
| `moduleName` | Field | Module name extracted from the document header. |
| `purposeJa` | Field | Japanese purpose summary extracted from the document body. |
| `revisions` | Field | Revision history entries parsed from revision lines in the source text. |
| `SYSTEM_NAME_PATTERN` | Constant | Regular expression that captures the system name line. |
| `MODULE_NAME_PATTERN` | Constant | Regular expression that captures the module name line. |
| `PURPOSE_PATTERN` | Constant | Regular expression that captures the Japanese functional overview section. |
| `REVISION_PATTERN` | Constant | Regular expression that captures revision history rows. |
| `Matcher` | Technical term | Java regex cursor used to find and extract matching text segments. |
| `Pattern` | Technical term | Java regex pattern definition used to match header fields. |
| `trim()` | Method behavior | Removes leading and trailing whitespace from the extracted text. |
| `RevisionEntry` | DTO | Single revision-history record inside `FileHeader`. |
