--- source_files: - Common/DTS.Common.Import/Parsers/EQX/EQXTestSetupParser.cs - Common/DTS.Common.Import/Parsers/EQX/EQXGroupImport.cs - Common/DTS.Common.Import/Parsers/EQX/EQXSensorsParser.cs generated_at: "2026-04-16T02:08:30.752253+00:00" model: "Qwen/Qwen3-Coder-Next-FP8" schema_version: 1 sha256: "ce57e1c33a0387ff" --- # Documentation: EQX Test Setup Parser Module ## 1. Purpose This module provides parsing logic for EQX files that contain test setup information (i.e., groupings of sensors into test groups and assignment to a test template). It is part of the `DTS.Common.Import` namespace and is specifically responsible for interpreting group-to-sensor mappings defined in an EQX file, constructing `TestTemplate`, static `IGroup`, and `SensorData` objects accordingly, and integrating them into the `ImportObject`. It depends on prior parsing of sensor and calibration data (handled by `EQXSensorsParser`) and uses `EQXGroupImport` to implement group creation logic. The parser aborts the import if the EQX file lacks test setup data (e.g., no `GroupNameTestObjectLookup`). ## 2. Public Interface ### `EQXTestSetupParser` class **Constructor** ```csharp public EQXTestSetupParser( IImportNotification importNotification, EqxImportOptions eqxImportOptions, IGroupImport groupImport, EquipmentExchange.EQXSensorDatabase eqxSensorDatabase, bool createDynamicGroups) ``` Initializes the parser with dependencies required for parsing and group creation. - `importNotification`: Used for reporting errors and progress. - `eqxImportOptions`: Configuration options for EQX import. - `groupImport`: Implementation of `IGroupImport` (typically `EQXGroupImport`) for group creation logic. - `eqxSensorDatabase`: Pre-populated sensor database from `EQXSensorsParser`. - `createDynamicGroups`: Flag indicating whether dynamic groups should be created (if `false`, static groups are created). **Override Method** ```csharp public override void Parse(ref ImportObject importObject) ``` Main entry point for parsing test setup data from the EQX file. - Validates `FileName` and `importObject` (throws `ArgumentNullException` if `importObject` is `null`). - Checks for presence of test setup data in `sensorImportData.GroupNameTestObjectLookup`; if missing, adds a critical error and aborts. - Assigns group-to-object and group-to-sensor lookups from the database to `importObject`. - Extracts setup name from XML using `ParseSetupName`, falls back to file name. - Skips if a test setup with the same name already exists in `importObject`. - Calls `FixCalibrations` to ensure sensors use the correct calibration from import. - Delegates group creation to `AssignGroupsToTestSetup`. - Cleans sensor data placeholders, clears existing sensors, adds cleaned sensors, and adds the resulting `TestTemplate` and static groups to `importObject`. - Sets `importObject.TestSetupImportFileFormat`. **Private Helper Methods** ```csharp private void FixCalibrations(ImportObject importObject) ``` For each sensor in `importObject`, retrieves calibrations via `CalibrationLookup(sensor.SerialNumber)`, sorts them, and assigns the first (earliest) calibration to `sensor.Calibration`. Logs exceptions via `APILogger`. ```csharp private Tuple, List> AssignGroupsToTestSetup( TestTemplate testTemplate, ImportObject importObject, Dictionary> groupNameSensorListLookup, IGroupImport groupImport, IImportNotification importNotification) ``` Implements the group assignment logic (moved here per FB 36879). - Reverses channel order using `GroupHelper.ReverseChannelOrder`. - Calls `groupImport.GetGroupSensorLookup` to build `groupSensorLookup`. - Normalizes sensor IDs via `GroupHelper.NormalizeSensorIds`. - Re-applies `FixCalibrations` (to revert potential calibration resets from normalization). - Calls `groupImport.CreateGroups(...)` to generate groups and test setup. - Returns `Tuple, List>`, or `null` on failure (with error reported via `importNotification`). - Returns `null` for `testTemplate`/`staticGroups` if `groupImport.CreateGroups` returns `null`. ```csharp private string ParseSetupName(string filename) ``` Parses the `` value from the first `` element under `` in the EQX XML file. Returns empty string on any failure (including missing element or XML parse error). ## 3. Invariants - **`importObject` must be non-null** at start of `Parse`; otherwise, `ArgumentNullException` is thrown. - **`GroupNameTestObjectLookup` must be non-null and non-empty** in `sensorImportData`; otherwise, a critical error is added and parsing aborts. - **Calibrations must be sorted before selecting the first one** in `FixCalibrations`; sorting is performed explicitly. - **Sensors are cleared and re-added** after cleaning (`GroupHelper.CleanUneededSensorDataPlaceHolder`) to ensure consistency. - **Test setup name uniqueness is enforced**: if a test setup with the same name already exists in `importObject.TestSetups()`, the method returns early without modifying the object. - **`EQXGroupImport.CreateGroups` may return `null`**, in which case `AssignGroupsToTestSetup` returns a tuple of `null` values and no groups/test setup are added. ## 4. Dependencies ### Dependencies *of* this module: - **`EQXSensorsParser`**: Must run first to populate `ImportObject.Sensors()`, `ImportObject.CalibrationsLookup()`, and `EquipmentExchange.EQXSensorDatabase` (via `EQXSensorDatabase.Read`). - **`EquipmentExchange.EQXSensorDatabase`**: Must be pre-populated with sensor, calibration, and group mapping data from the EQX file. - **`IGroupImport`**: Typically implemented by `EQXGroupImport`; provides `GetGroupSensorLookup` and `CreateGroups`. - **`GroupHelper`**: Used for `ReverseChannelOrder`, `NormalizeSensorIds`, and `CleanUneededSensorDataPlaceHolder`. - **`DbOperations`**: Referenced indirectly (e.g., `GetChannelSettingDefaults`, `TagsGet`, etc.) via `EQXGroupImport` and `EQXSensorsParser`. - **`APILogger`**: Used for logging failures in `FixCalibrations`. - **`StringResources`**: Used for error messages (e.g., `Import_EQXFileNotForTestSetup`). ### Dependencies *on* this module: - **`EQXSensorsParser`**: Must be invoked before `EQXTestSetupParser` to ensure sensor and calibration data are available. - **`ImportObject` consumers**: Any downstream logic that consumes `TestTemplate`, `StaticGroups`, or `Sensors` after import will depend on this parser’s output. ## 5. Gotchas - **Calibration resets after normalization**: `GroupHelper.NormalizeSensorIds` may reset sensor calibrations; `FixCalibrations` is called *twice* (before and after normalization) to mitigate this (see FB 44105 comment in `AssignGroupsToTestSetup`). - **Setup name extraction is fragile**: `ParseSetupName` silently returns `string.Empty` on any XML parsing error or missing `` element. - **No overwrite of existing test setups**: If a test setup with the same name already exists, `Parse` returns early without warning or modification (only silent skip). - **Group creation may silently fail**: If `groupImport.CreateGroups` throws or returns `null`, `AssignGroupsToTestSetup` returns `null` and no groups/test setup are added, but only the exception message is reported via `importNotification.ReportErrors` (no additional context). - **`ImportCreateDynamicGroups` flag is not used directly in this class**: It is passed to `EQXGroupImport.CreateGroups` via `EQXTestSetupParser` constructor, but the flag is stored as a property in `EQXSensorsParser`, not `EQXTestSetupParser`. - **Excitation errors are computed but not reported**: `EQXSensorsParser.GetExcitationErrors()` collects errors but the `TODO Report the errors` comment indicates they are not currently surfaced (only in `EQXSensorsParser`, not here). - **`SensorData` is modified in-place**: `FixCalibrations` mutates `sensor.Calibration` directly; callers must be aware of side effects. - **No handling of duplicate sensor serial numbers**: If duplicate serial numbers exist in the import, behavior is undefined (e.g., `sensorLookup` in `EQXGroupImport` will only retain the last one).