# W-TNMS Rule Implementation

**HISTORY:**
###### 2020: initial implementation
###### 15/4/2026: ECARS-2380 - apply only when Beh=3
###### 20/5/2026: ECARS-2424 - fix bugs (multiple tables, T/N/M prefix/suffix, value snapshot)
###### 27/5/2026: ECARS-2430 - support adjuvant therapy
###### 08/6/2026: ECARS-2443 - yaml config sub-tables fix (share `any` T/N/M across sub-table groups)
###### 06/2026: ECARS-2451 - update Grade handling (optional per table, separate from T/N/M `any` lists)
###### 15/06/2026: ECARS-2451 - Grade handled per row (a table can mix rows with and without Grade)

## Overview
This document describes the implementation of the W-TNMS validation rule.

## Rule Description
**Rule Definition ID**: 238
**Rule Code**: W-TNMS
**Rule Type**: WARNING  
**Description**: Topography + TNM edition + T,N,M + Stage (+ Grade when required by the matched table) not in accordance with the target TNM edition  
**Protocol**: Incidence

## Rule Logic

### 0. Preparatory checks — skip if any fails
- Key fields (Topography, Morphology, Stage, ToS, Behaviour) must be valid and in range.
  - Staging system must be TNM-based (not A, D, E, TI1, TI2, COG, SIO, 8).
  - If Stage is metastatic (IV) and pM or cM contains `1` → skip (always valid).
  - If record already triggered W-MOTO or W-TNME → skip.
  - TNM edition must be 6, 7, or 8 (only those have configuration files).
  - Behaviour must be `3` (ECARS-2380).
- **Grade is not checked here.** It is evaluated later, only when the candidate YAML table defines a `Grade` column (ECARS-2451).

### 1. Load edition tables
At startup, three YAML files are loaded and cached:
`TNMRuleEdition6.yaml`, `TNMRuleEdition7.yaml`, `TNMRuleEdition8.yaml`.  
Each file contains staging tables grouped by cancer site (topography).

### 2. Select T/N/M values to check
- **Normal case**: prefer pathological values (pT, pN, pM); fall back to clinical (cT, cN, cM) if pathological are missing.
- **Adjuvant therapy case** *(ECARS-2430)*: if all pT/pN/pM have a `y`/`Y` prefix (post-neoadjuvant), or ToS begins with `y`/`Y`, and cT/cN/cM are valid → use clinical values only (Stage was assigned from pre-treatment clinical assessment).

### 3. Find the right table
From the edition matching the record, find all tables whose topography range covers the record's topography code.  
→ If no table found → **valid** (skip).

### 4. Check morphology
Does the table's morphology group include the record's morphology code?  
→ No → try next table.

### 5. Check age
Does the table have an age restriction that matches the record's age?  
→ No → try next table.

### 6. Check stage rows
Find all rows in the table for the record's Stage (e.g. Stage IV matches rows IV, IVA, IVB, IVC).  
→ No rows for this stage → try next table (or **invalid** if no more tables).

### 7. Check T/N/M combination
For each stage row: does the record's T / N / M match what the row allows?

- `T: any` → T must appear in the allowed "any" list for that table (with fuzzy suffix/prefix matching, ECARS-2424).
  - For sub-tables (`TableN-M`), the "any" list is built from **all** sub-tables with the same `N` and the same `topography` (+ `topographyExcept`), not only from rows in the current sub-table. This covers split tables where one sub-table has only `T: any` / `N: any` rows.
- `T: T1,T2` → T must be one of the listed values.
- Grade is not checked in this step.

→ If T/N/M do not match the row → try next row (or next table).

### 8. Check Grade on matched row — per row (ECARS-2451)
Grade is evaluated per config table row, only after T/N/M match a stage row.

For a matched (T/N/M) stage row:
- Row without `Grade` value → Grade is not a constraint → the row matches (valid).
- Row with `Grade` value and the record's Grade is valid:
  - `Grade: any` → any valid grade is accepted.
  - `Grade: 1,2,3` → the record's grade must be in the set.
- Row with `Grade` value but the record's Grade is invalid → the row cannot be matched (we have no valid grade to compare).


When W-TNMS fires, the error detail includes Topography, Morphology, TNM edition, Stage, pT/pN/pM, cT/cN/cM, **Grade**, Age, Behaviour, and ToS.

## Implementation Files

### 1. Java Implementation
**File**: `src/main/java/eu/europa/ec/jrc/qcs/engine/rule/crossfield/encr2020/TNMStageRule.java`

### 2. Configuration
`src/main/resources/configuration/rules/encr2020/TNMRuleEdition{6,7,8}.yaml`

