Files
2026-04-17 14:55:32 -04:00

183 lines
15 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
source_files:
- Common/DTS.Common.Import/XML/XMLPre20ParseGroupTemplates.cs
- Common/DTS.Common.Import/XML/XMLParseMMECustomDirections.cs
- Common/DTS.Common.Import/XML/XMLParseMMECustomTestObjects.cs
- Common/DTS.Common.Import/XML/XMLParseMMECustomPositions.cs
- Common/DTS.Common.Import/XML/XMLParseMMECustomFineLoc3s.cs
- Common/DTS.Common.Import/XML/XMLParseMMECustomFineLoc2s.cs
- Common/DTS.Common.Import/XML/XMLParseMMECustomFineLoc1s.cs
- Common/DTS.Common.Import/XML/XMLParseSensorModels.cs
- Common/DTS.Common.Import/XML/XMLParseMMECustomFilterClasses.cs
- Common/DTS.Common.Import/XML/XMLParseMMECustomChannels.cs
- Common/DTS.Common.Import/XML/XMLParseMMECustomMainLocations.cs
- Common/DTS.Common.Import/XML/XMLParseMMECustomPhysicalDimensions.cs
- Common/DTS.Common.Import/XML/XMLPre20ParseSensors.cs
- Common/DTS.Common.Import/XML/XMLParseUsers.cs
- Common/DTS.Common.Import/XML/XMLParseBase.cs
- Common/DTS.Common.Import/XML/XMLParseTestEngineerDetails.cs
- Common/DTS.Common.Import/XML/XMLParseLabDetails.cs
- Common/DTS.Common.Import/XML/XMLParseGlobalSettings.cs
- Common/DTS.Common.Import/XML/XMLPre20ParseDASList.cs
- Common/DTS.Common.Import/XML/XMLParseCustomerDetails.cs
- Common/DTS.Common.Import/XML/XMLParseSensors.cs
- Common/DTS.Common.Import/XML/XMLParseDASList.cs
- Common/DTS.Common.Import/XML/XMLParseGroupTemplates.cs
- Common/DTS.Common.Import/XML/XMLParseCalibrations.cs
- Common/DTS.Common.Import/XML/XMLPre20ParseCalibrations.cs
- Common/DTS.Common.Import/XML/XMLParseGroups.cs
- Common/DTS.Common.Import/XML/XMLParseTestSetups.cs
generated_at: "2026-04-16T02:07:16.226597+00:00"
model: "Qwen/Qwen3-Coder-Next-FP8"
schema_version: 1
sha256: "87dec39982bd8179"
---
# XML Import Parsers Module Documentation
## 1. Purpose
This module provides a family of XML parsing classes responsible for deserializing versioned XML export files into the systems in-memory `ImportObject` representation during data import operations. Each concrete parser targets a specific data domain (e.g., sensors, groups, channels, test setups, calibration data, MME custom objects) and handles both direct parsing and migration logic for pre-2.0 XML formats. These parsers implement the `IParseVariant` interface, inherit from `XMLParseBase`, and coordinate with other parsers (e.g., via constructor injection) to resolve cross-references and normalize identifiers across related entities. The module serves as the core deserialization layer for backward-compatible XML imports, ensuring robust handling of schema evolution and data integrity constraints.
## 2. Public Interface
All classes inherit from `XMLParseBase` and implement the abstract method `Parse(ref ImportObject importObject)`. Below are the public classes and their key behaviors.
### `XMLParseBase`
- **Constructor**: `XMLParseBase(XmlElement root, double importedVersion, Func<bool> isCancelled = null, bool skipNormalizing = false)`
- Stores the XML root node, imported file version, cancellation token, and normalization flag.
- Initializes internal XML writer and mapping dictionaries (`_dasIdMapping`, `_groupIdMapping`, `_sensorIdMapping`, `_channelIdMapping`) for cross-entity ID normalization.
- **Protected Methods**:
- `XmlElement GetXmlElement()` Finalizes XML writing and returns the constructed `XmlElement`.
- `bool IsCancelled()` Invokes the cancellation token (defaults to `() => false`).
### `XMLParseSensors`
- **Constructor**: `XMLParseSensors(XmlElement root, double importedVersion, Func<bool> isCancelled = null, bool skipNormalizing = false)`
- **Public Methods**:
- `XmlElement ConvertSensors(IEnumerable<SensorData> sensors)` Normalizes sensor `DatabaseId`s (assigns negative IDs starting at -2), updates `_sensorIdMapping`, and writes normalized XML.
- `IEnumerable<SensorData> ParseSensors(XmlElement root)` Parses `SensorData` objects from XML nodes; skips non-`XmlElement` nodes.
### `XMLPre20ParseSensors`
- **Constructor**: `XMLPre20ParseSensors(XmlElement root, double importedVersion, XMLParseSensors xmlParseSensors, Func<bool> isCancelled = null)`
- **Public Methods**:
- `XmlElement MigrateSensors(IEnumerable<SensorData> sensors)` Migrates pre-2.0 sensor data by assigning negative `DatabaseId`s (starting at -1) and writing to XML.
- **Behavior**: Parses sensors, migrates them to the new schema, then delegates to `_xmlParseSensors.ParseSensors()` for final parsing.
### `XMLParseDASList`
- **Constructor**: `XMLParseDASList(XmlElement root, double importedVersion, Func<bool> isCancelled = null, bool skipNormalizing = false)`
- **Public Methods**:
- `List<DASHardware> ParseDASList(XmlElement root)` Parses `DASHardware` objects; filters out entries with invalid `DASType` (logs serial numbers to `invalidDAS` list, but does not report errors).
- `XmlElement ConvertDASList(List<DASHardware> dasList)` Normalizes `DASId`s (starting at -2) and updates `_dasIdMapping`.
- **Behavior**: On import, validates `DASType` enum values; skips invalid entries silently.
### `XMLPre20ParseDASList`
- **Constructor**: `XMLPre20ParseDASList(XmlElement root, double importedVersion, XMLParseDASList xmlParseDASList, Func<bool> isCancelled = null)`
- **Public Methods**:
- `List<DASHardware> ParsePre20DASList(XmlElement root)` Parses pre-2.0 `DASHardware` objects.
- `XmlElement MigratePre20DASList(List<DASHardware> dasList)` Assigns negative `DASId`s (starting at -1) and writes to XML.
- **Behavior**: Migrates pre-2.0 DAS list, then delegates to `_xmlParseDASList.ParseDASList()`.
### `XMLParseGroups`
- **Constructor**: `XMLParseGroups(XmlElement root, double importedVersion, Func<bool> isCancelled = null)`
- **Public Methods**:
- `List<IGroup> ParseGroups(XmlElement root, ref ImportObject importObject)` Parses groups, resolving channel references to imported sensors/DAS via lookup dictionaries. Handles both pre-2.0 (name-based) and post-2.0 (ID-based) group IDs in `_groupIdMapping`.
- `XmlElement ConvertGroups(List<IGroup> staticGroups)` Normalizes group `Id`s (starting at -2), DAS/sensor IDs in channels (using `_dasIdMapping`/`_sensorIdMapping`), and writes to XML. Silently sets `SensorId = 0` for deleted sensors (FB 14308).
- **Behavior**: Normalizes group and channel IDs; handles sensor deletion gracefully.
### `XMLParseGroupTemplates`
- **Constructor**: `XMLParseGroupTemplates(XmlElement root, double importedVersion, ISO.ISO13499FileDb iSO13499FileDb, Func<bool> isCancelled = null)`
- **Public Methods**:
- `IEnumerable<DataPROWin7.DataModel.TestObjectTemplate> ParseGroupTemplates(ref ImportObject importObject, XmlElement root)` Parses group templates, resolving channels from `importObject.CustomChannels()`. Enforces that referenced ISO test objects exist in `importObject.TestObjects()` (throws `NotSupportedException` if missing, FB 8790).
- **Behavior**: Requires pre-parsed custom channels and test objects; validates test object existence.
### `XMLParseTestSetups`
- **Constructor**: `XMLParseTestSetups(XmlElement root, double importedVersion, Func<bool> isCancelled = null, bool skipNormalizing = false)`
- **Public Methods**:
- `XmlElement ConvertTestTemplates(IEnumerable<TestTemplate> testTemplates, ImportObject importObject)` Normalizes group IDs, channel IDs (using `_groupIdMapping`, `_channelIdMapping`), and DAS/sensor IDs in channels. Handles missing static group IDs (sets to `null`) and deleted sensors (sets `SensorId = 0`, FB 14308).
- `IEnumerable<TestTemplate> ParseTestTemplate(ImportObject importObject, XmlElement root)` Parses test setups using lookup dictionaries for test objects, groups, customer/lab details, sensors, etc. Catches and logs parsing errors as warnings (FB 36879).
- **Behavior**: Requires pre-parsed entities (groups, sensors, etc.) to resolve references; handles missing/invalid references gracefully.
### `XMLParseCalibrations`
- **Constructor**: `XMLParseCalibrations(XmlElement root, double importedVersion, Func<bool> isCancelled = null)`
- **Public Methods**:
- `XmlElement ConvertCalibrations(IEnumerable<SensorCalibration> calibrations)` Writes normalized calibration XML.
- `IEnumerable<SensorCalibration> ParseCalibrations(XmlElement root)` Parses calibrations with version-specific logic:
- For `importedVersion >= DataPROPre20XmlVersion`: Direct parsing.
- For `importedVersion == 1.0`: Sets `AtCapacity = false` and infers `SensitivityUnits` (mV/EU, mV/V/EU, or NONE) based on calibration type.
### `XMLPre20ParseCalibrations`
- **Constructor**: `XMLPre20ParseCalibrations(XmlElement root, double importedVersion, XMLParseCalibrations xmlParseCalibrations, Func<bool> isCancelled = null)`
- **Behavior**: Parses pre-2.0 calibrations, adds them to sensors via `AddToSensor()`, then delegates normalization and re-parsing to `_xmlParseCalibrations`.
### `XMLParseMMECustom*` Parsers (e.g., `XMLParseMMECustomChannels`, `XMLParseMMECustomPositions`, etc.)
- **Common Pattern**:
- **Constructor**: `XMLParseMMECustom* (XmlElement root, double importedVersion, Func<bool> isCancelled = null)`
- **Public/Protected Methods**:
- `ParseCustom* (XmlElement root)` Parses a list of MME objects (e.g., `ISO.MMEPossibleChannels`, `ISO.MMEPositions`) from XML child nodes.
- `Parse(ref ImportObject importObject)` Adds parsed list to `importObject` via `AddCustom*()` methods.
- **Behavior**: Iterates child `XmlElement`s, calls `ReadXML()` on each, and respects cancellation. No normalization or migration logic (assumes current-version format).
### `XMLPre20ParseGroupTemplates`
- **Constructor**: `XMLPre20ParseGroupTemplates(XmlElement root, double importedVersion, XMLParseGroupTemplates xmlParseGroupTemplates, Func<bool> isCancelled = null)`
- **Behavior**: Delegates parsing to `_xmlParseGroupTemplates.ParseGroupTemplates()`; no migration logic visible.
### `XMLParseUsers`
- **Constructor**: `XMLParseUsers(XmlElement root, double importedVersion, IEnumerable<IUIItems> uiItems, Func<bool> isCancelled = null)`
- **Behavior**: Parses `User` objects using `User.ReadXML()`, passing `uiItems` for UI context.
### `XMLParseTestEngineerDetails`, `XMLParseLabDetails`, `XMLParseCustomerDetails`
- **Pattern**: Parse → Convert → Re-parse → Add to `importObject`.
- `Parse*()` Initial parse.
- `Convert*()` Writes parsed objects to XML.
- Re-parse normalized XML to ensure consistency.
- **Behavior**: All use `Convert*()` to normalize and re-parse; no ID mapping beyond XML structure.
### `XMLParseGlobalSettings`
- **Constructor**: `XMLParseGlobalSettings(XmlElement root, double importedVersion, Func<bool> isCancelled = null)`
- **Behavior**: Parses `<SettingName>` and `<SettingValue>` child elements into a `Dictionary<string, string>`.
## 3. Invariants
- **ID Normalization**: All parsers that normalize IDs (e.g., `XMLParseSensors`, `XMLParseDASList`, `XMLParseGroups`, `XMLParseTestSetups`) assign negative integer IDs starting at -1 or -2 (to avoid conflicts with database IDs). Mappings are stored in static dictionaries (`_sensorIdMapping`, `_dasIdMapping`, `_groupIdMapping`, `_channelIdMapping`) and used during cross-entity resolution.
- **Cancellation Handling**: All parsers check `IsCancelled()` before processing each node and return partial results if cancelled.
- **XML Node Validation**: All parsers skip non-`XmlElement` nodes (e.g., whitespace, comments) during iteration.
- **Version-Specific Parsing**: Calibrations and sensors have distinct parsing logic for `importedVersion == 1.0` vs. newer versions.
- **Group Template Validation**: `XMLParseGroupTemplates` enforces that referenced ISO test objects exist in `importObject.TestObjects()`; throws `NotSupportedException` if missing.
- **DAS Type Validation**: `XMLParseDASList` filters out `DASHardware` with invalid `DASType` enums but does not report errors (silently drops entries).
- **Sensor Deletion Handling**: Group and Test Setup parsers set `SensorId = 0` for deleted sensors (FB 14308) to avoid import failures.
## 4. Dependencies
### Internal Dependencies
- **Imports**:
- `DTS.Common.Import.Interfaces` (`ImportObject`, `IParseVariant`, `IImportNotification`, `ImportStatus`, `ImportError`, `ImportSeverityError`)
- `DTS.Common.Interface.*` (e.g., `GroupTemplate`, `Groups.GroupList`, `Sensors`, `Channels`)
- `DTS.SensorDB` (`SensorModel`, `SensorData`, `SensorCalibration`)
- `DataPROWin7.DataModel` (`DASHardware`, `TestObjectTemplate`)
- `ISO.*` (e.g., `MMEPossibleChannels`, `MMETestObjects`, `MMEPositions`, `TestEngineerDetails`, `CustomerDetails`, `LabratoryDetails`)
- `System.Xml` (`XmlElement`, `XmlDocument`, `XmlWriter`)
- **Shared State**:
- Static dictionaries in `XMLParseBase` (`_dasIdMapping`, `_groupIdMapping`, `_sensorIdMapping`, `_channelIdMapping`) are shared across parsers in the same import session.
- `ImportNotification` property used for status updates (settable via property).
- **Constructor Injection**:
- Pre-2.0 parsers (`XMLPre20ParseSensors`, `XMLPre20ParseDASList`, `XMLPre20ParseCalibrations`, `XMLPre20ParseGroupTemplates`) depend on their post-2.0 counterparts to perform normalization and final parsing.
### External Dependencies
- `DataPROWin7.DataModel.DASHardware.ReadXML()` Static method for pre-2.0 DAS parsing.
- `ISO.*.ReadXML()` Static methods for MME object parsing (e.g., `ISO.MMEPossibleChannels.ReadXML()`).
- `User.ReadXML()` Static method for user parsing.
- `SensorData.ReadXML()`, `SensorCalibration.ReadXML()` Static methods for sensor/calibration parsing.
- `DataPROWin7.DataModel.TestObjectTemplate.ReadXML()` Static method for group template parsing.
## 5. Gotchas
- **Silent DAS Filtering**: `XMLParseDASList.ParseDASList()` silently drops DAS entries with invalid `DASType` enums (no error logged or reported).
- **ID Mapping Side Effects**: Static ID mappings in `XMLParseBase` are shared across parsers; clearing them (e.g., in `XMLParseDASList` constructor) may affect other parsers if not coordinated.
- **Version-Specific Calibration Logic**: For `importedVersion == 1.0`, `XMLParseCalibrations` mutates calibration records (e.g., sets `AtCapacity = false`, infers `SensitivityUnits`). This logic is duplicated in `XMLPre20ParseCalibrations`.
- **FB References**: Several parsers reference internal bug IDs (e.g., FB 8790, FB 14308, FB 36879) in comments or exceptions; these are internal tracking references.
- **Test Setup Reference Resolution**: `XMLParseTestSetups.ParseTestTemplate()` uses lookup dictionaries built from `importObject` entities; if entities are not parsed in the correct order, lookups may fail (e.g., missing groups/sensors).
- **Group Template Test Object Validation**: `XMLParseGroupTemplates` throws `NotSupportedException` if a referenced ISO test object is missing; this is a hard failure.
- **XML Writer State**: `XMLParseBase` uses a shared `XmlWriter` instance per parser; reusing the same writer across multiple `Convert*()` calls without reinitialization may cause issues (though current code creates a new `_doc` per instance).
- **Pre-2.0 Migration Assumptions**: `XMLPre20Parse*` parsers assume the target parser (`_xmlParse*`) handles normalization; no validation that the target parser is compatible with the migrated XML structure.
- **Group ID Mapping Ambiguity**: `XMLParseGroups` uses `_groupIdMapping` with keys as `g.Id.ToString()` (post-2.0) or `g.Name` (pre-2.0); this dual-key approach may cause issues if group names collide with numeric IDs.
- **Channel ID Normalization**: `XMLParseTestSetups` normalizes channel IDs *after* normalizing group IDs; order of normalization matters for cross-references.