210 lines
12 KiB
Markdown
210 lines
12 KiB
Markdown
---
|
||
source_files:
|
||
- Common/DTS.Common.DataModel/Classes/Export/ExportHeader.cs
|
||
- Common/DTS.Common.DataModel/Classes/Export/ExportTestSetup.cs
|
||
generated_at: "2026-04-16T03:34:31.793274+00:00"
|
||
model: "Qwen/Qwen3-Coder-Next-FP8"
|
||
schema_version: 1
|
||
sha256: "e1688a84f19142ea"
|
||
---
|
||
|
||
# Export
|
||
|
||
## Documentation: `ExportTestSetup` Module
|
||
|
||
---
|
||
|
||
### **Purpose**
|
||
|
||
The `ExportTestSetup` static class orchestrates the preparation and serialization of test configuration data for export to XML. It aggregates test templates, associated groups, sensors, calibrations, DAS hardware, sensor models, ISO metadata (customer, engineer, lab), users, and global settings into dictionaries, validates and deduplicates entries, and writes them to an XML file using a structured writer. This module serves as the core export engine for test setup data, supporting both full exports and field-only exports (e.g., for partial updates or migrations). It bridges domain models (`TestTemplate`, `IGroup`, `SensorData`, etc.) with serialization infrastructure (`IExportHeader`-like patterns, XML writers) and database abstractions.
|
||
|
||
---
|
||
|
||
### **Public Interface**
|
||
|
||
#### **1. `PrepareForExport`**
|
||
```csharp
|
||
public static void PrepareForExport(
|
||
DataModel.TestTemplate t,
|
||
Dictionary<string, DataModel.TestTemplate> includedTests,
|
||
Dictionary<string, IGroup> includedGroups,
|
||
Dictionary<string, DataModel.DASHardware> includedDAS,
|
||
Dictionary<string, SensorData> includedSensors,
|
||
HashSet<int> sensorsAlreadyAdded,
|
||
Dictionary<string, SensorModel> includedSensorModels,
|
||
Dictionary<string, SensorCalibration[]> includedCalibration,
|
||
Dictionary<string, DTS.Common.ISO.CustomerDetails> includedCustomerDetails,
|
||
Dictionary<string, DTS.Common.ISO.TestEngineerDetails> includedTestEngineerDetails,
|
||
Dictionary<string, DTS.Common.ISO.LabratoryDetails> includedLabDetails,
|
||
bool savingRunningTest,
|
||
bool savingTTSImport
|
||
)
|
||
```
|
||
**Behavior**: Populates the provided dictionaries with data derived from the input `TestTemplate` `t`.
|
||
- Adds `t` to `includedTests`.
|
||
- Extracts and deduplicates ISO metadata (customer, engineer, lab) into respective dictionaries.
|
||
- Iterates over embedded groups in `t.Groups`, collects associated sensors (via channels), calibrations, and DAS hardware, skipping test-specific digital outputs/squibs/digital inputs.
|
||
- Resolves and processes non-embedded (static) groups via `GetNonEmbeddedGroup`, ensuring thread-safe dispatcher invocation.
|
||
- Deduplicates sensors and calibrations using `sensorsAlreadyAdded`.
|
||
- Collects sensor models and calibrations for non-test-specific sensors.
|
||
- Adds hardware from `t.GetHardware()`.
|
||
- If `savingTTSImport` is `true`, *also* includes *all* sensors (even unused ones) and their calibrations/models.
|
||
- Mutates all input dictionaries and sets in-place.
|
||
|
||
#### **2. `ExportToFile`**
|
||
```csharp
|
||
public static string ExportToFile(
|
||
Dictionary<string, DataModel.TestTemplate> includedTests,
|
||
Dictionary<string, IGroup> includedGroups,
|
||
Dictionary<string, DataModel.DASHardware> includedDAS,
|
||
Dictionary<string, SensorData> includedSensors,
|
||
Dictionary<string, SensorModel> includedSensorModels,
|
||
Dictionary<string, SensorCalibration[]> includedCalibration,
|
||
Dictionary<string, DTS.Common.ISO.CustomerDetails> includedCustomerDetails,
|
||
Dictionary<string, DTS.Common.ISO.TestEngineerDetails> includedTestEngineerDetails,
|
||
Dictionary<string, DTS.Common.ISO.LabratoryDetails> includedLabDetails,
|
||
Dictionary<string, DTS.Slice.Users.User> includedUsers,
|
||
Dictionary<string, string> includedGlobalSettings,
|
||
string exportFile,
|
||
string originalImportFile,
|
||
bool bUseFirstUseDate = true
|
||
)
|
||
```
|
||
**Behavior**: Serializes the aggregated data into an XML document and optionally writes it to `exportFile`.
|
||
- Uses `FileUtils.GetExportWriter(...)` to create an `XmlWriter` with progress tracking.
|
||
- Writes `OriginalImportFile` as an attribute on the root element.
|
||
- Iterates over `TopLevelFields` enum values, writing only non-empty sections in a fixed order (e.g., `Calibrations`, `DASList`, `Groups`, `Sensors`, `TestSetups`, etc.).
|
||
- Calls `WriteXML(ref writer)` on each item in the dictionaries (e.g., `SensorData.WriteXML`, `SensorCalibration.WriteXML`).
|
||
- Returns the full XML string (via `StringBuilder`) and writes it to `exportFile` if non-null.
|
||
- Logs exceptions via `APILogger.Log` and returns `string.Empty` on failure.
|
||
|
||
#### **3. `PrepareForExportFields`**
|
||
```csharp
|
||
public static void PrepareForExportFields(
|
||
DataModel.TestTemplate t,
|
||
Dictionary<string, DataModel.TestTemplate> includedTests,
|
||
Dictionary<string, DataModel.DASHardware> includedDAS
|
||
)
|
||
```
|
||
**Behavior**: A *lightweight* variant of `PrepareForExport` that only populates `includedTests` and `includedDAS`.
|
||
- Adds `t` to `includedTests`.
|
||
- Collects embedded and non-embedded group hardware into `includedDAS`.
|
||
- Does *not* process sensors, calibrations, groups, or metadata.
|
||
- Includes logic to remove unused DAS sample rates from `t.DASSampleRateList`.
|
||
- Intended for scenarios where only test setup and hardware metadata need updating (e.g., field-level sync).
|
||
|
||
#### **4. `ExportToFileFields`**
|
||
```csharp
|
||
public static string ExportToFileFields(
|
||
Dictionary<string, DataModel.TestTemplate> includedTests,
|
||
Dictionary<string, DataModel.DASHardware> includedDAS,
|
||
string originalImportFile
|
||
)
|
||
```
|
||
**Behavior**: Serializes *only* `TestSetups` and `DASList` sections (no sensors, calibrations, groups, etc.).
|
||
- Uses the same XML writer infrastructure as `ExportToFile`.
|
||
- Skips all `TopLevelFields` except `DASList` and `TestSetups`.
|
||
- Returns the XML string (no file write).
|
||
- Used for minimal exports (e.g., updating only test and hardware definitions).
|
||
|
||
#### **5. `ExportHeader` (Class)**
|
||
```csharp
|
||
public class ExportHeader : IExportHeader
|
||
```
|
||
**Behavior**: A simple data model for UI-level export header selection.
|
||
- Implements `INotifyPropertyChanged`.
|
||
- Properties:
|
||
- `HeaderName` (`string`): Name of the export section/group.
|
||
- `IsSelected` (`bool`): Whether the header is selected for export.
|
||
- Raises `PropertyChanged` on property changes.
|
||
- Used to drive UI checkboxes or toggles for export sections (e.g., in a configuration dialog).
|
||
|
||
---
|
||
|
||
### **Invariants**
|
||
|
||
1. **Deduplication by Key**:
|
||
- `includedTests`, `includedGroups`, `includedDAS`, `includedSensors`, `includedSensorModels`, `includedCalibration`, `includedCustomerDetails`, `includedTestEngineerDetails`, `includedLabDetails`, `includedUsers`, and `includedGlobalSettings` use string keys (e.g., `Name`, `SerialNumber`) to avoid duplicates.
|
||
- `sensorsAlreadyAdded` uses `DatabaseId` (int) to prevent reprocessing sensors.
|
||
|
||
2. **Hardware Deduplication**:
|
||
- `includedDAS` uses `SerialNumber` as the key. Hardware is added only if not already present.
|
||
|
||
3. **Sensor Exclusion Rules**:
|
||
- Sensors marked `IsTestSpecificDigitalOutput`, `IsTestSpecificSquib`, or `IsTestSpecificDigitalIn` are *excluded* from `includedSensors` and `includedCalibration` *unless* `savingTTSImport` is `true`.
|
||
|
||
4. **Static Group Resolution**:
|
||
- Non-embedded groups must exist in the database (resolved via `GetNonEmbeddedGroup`). If not, `embeddedGroup.StaticGroupId` is set to `null` and processing continues (no exception thrown).
|
||
|
||
5. **Thread Safety for Dispatcher**:
|
||
- Access to `Application.Current.Dispatcher` for static group resolution uses `CheckAccess()` and `BeginInvoke` with `ManualResetEvent` to block on non-UI threads.
|
||
|
||
6. **XML Serialization Order**:
|
||
- Sections are written in the order defined by `TopLevelFields` enum (via `Enum.GetValues`). Unsupported/empty sections are skipped.
|
||
|
||
---
|
||
|
||
### **Dependencies**
|
||
|
||
#### **Imports/Usings (Direct Dependencies)**
|
||
- `DTS.Common.Interface.ExportData` (`IExportHeader`)
|
||
- `DTS.Common.Interface.Groups.GroupList` (`IGroup`, `IGroupChannel`)
|
||
- `DTS.SensorDB` (`SensorData`, `SensorCalibration`)
|
||
- `DTS.Common.Interface.Sensors` (`ISensorData`)
|
||
- `DTS.Common.Interface.Channels` (`IGroupChannel`)
|
||
- `DTS.Common.Interface.DataRecorders` (`IDASHardware`)
|
||
- `DTS.Common.Storage` (`DbOperations`, `FileUtils`)
|
||
- `Prism.Ioc`, `Unity` (`ContainerLocator`, `IUnityContainer`)
|
||
- `DTS.Common.ISO` (`CustomerDetails`, `TestEngineerDetails`, `LabratoryDetails`, `Hardware`, `SensorModel`)
|
||
- `DTS.Common.Utils`, `DTS.Common.Utilities.Logging` (`APILogger`)
|
||
- `DTS.Common.Enums.DBExport` (`TopLevelFields`)
|
||
- `System`, `System.Linq`, `System.Windows`, `System.Threading`, `System.Text`, `System.Xml`
|
||
|
||
#### **External Services/Modules Used**
|
||
- `SensorsCollection.SensorsList` (static): For sensor lookup (`GetAllSensors`, `GetOriginalSensorBySensorId`).
|
||
- `SensorModelCollection.SensorModelList` (static): For sensor model lookup.
|
||
- `DbOperations`: For DAS (`DASGet`), channel defaults (`GetChannelSettingDefaults`).
|
||
- `ContainerLocator.Container`: For resolving `IUnityContainer` → `IGroupListViewModel`.
|
||
- `FileUtils.GetExportWriter`: For XML writer creation.
|
||
- `APILogger`: For exception logging.
|
||
|
||
#### **Depended Upon By**
|
||
- UI layers (e.g., export dialogs) that use `ExportHeader` for section selection.
|
||
- Export workflows (e.g., full export, TTS import, field sync) that call `PrepareForExport` or `PrepareForExportFields` before `ExportToFile`/`ExportToFileFields`.
|
||
|
||
---
|
||
|
||
### **Gotchas**
|
||
|
||
1. **`savingTTSImport` Behavior**:
|
||
- When `savingTTSImport` is `true`, *all* sensors (including unused ones) are added to `includedSensors`/`includedCalibration`/`includedSensorModels`. This may significantly increase export size and processing time.
|
||
|
||
2. **Static Group Resolution Failure**:
|
||
- If a static group referenced by `embeddedGroup.StaticGroupId` no longer exists in the database, `GetNonEmbeddedGroup` returns `null`, and `embeddedGroup.StaticGroupId` is set to `null`. This silently discards the group’s channels/hardware. Pre-existing database records may be affected.
|
||
|
||
3. **Thread-Safe Dispatcher Usage**:
|
||
- `GetNonEmbeddedGroup` uses `ManualResetEvent.WaitOne()` to block on non-UI threads. This can cause deadlocks if the UI thread is blocked or the dispatcher is unavailable.
|
||
|
||
4. **Hardware Serial Number Fallback**:
|
||
- `GetHardwareSerialNumber` returns `string.Empty` if `hardwareId` is not found. This may cause `GetDAS` to return `null`, skipping hardware inclusion (no error raised).
|
||
|
||
5. **`bUseFirstUseDate` Parameter**:
|
||
- Passed to `SensorData.WriteXML`. Its effect is not documented in the source—behavior depends on `SensorData.WriteXML` implementation.
|
||
|
||
6. **`TopLevelFields` Enum Gaps**:
|
||
- Many `TopLevelFields` enum values (e.g., `CustomChannels`, `CustomDirections`) are skipped in both export methods. This is intentional but may confuse readers expecting completeness.
|
||
|
||
7. **No Validation of Input Dictionaries**:
|
||
- The methods assume input dictionaries are properly initialized (not `null`). Passing `null` will cause `NullReferenceException`.
|
||
|
||
8. **`ExportHeader` Not Used in Export Logic**:
|
||
- Despite being in the same namespace (`Export`), `ExportHeader` is *not* used by `ExportTestSetup`. It is likely used in UI layers for export section selection, but this is not evident from the source.
|
||
|
||
9. **`ExportToFileFields` Does Not Write to File**:
|
||
- Unlike `ExportToFile`, `ExportToFileFields` returns the XML string but does *not* write to `exportFile` (parameter is unused). This is inconsistent and may cause confusion.
|
||
|
||
10. **Hardcoded XML Version**:
|
||
- `FileUtils.CurrentXmlVersion` and assembly version (`.ToString(4)`) are hardcoded in writer initialization. Changes to versioning may break compatibility.
|
||
|
||
11. **Calibration Null Handling**:
|
||
- In `PrepareForExport`, if `SensorCalibration.GetCalibrationsBySerialNumber(sd)` returns `null`, the sensor is skipped. In `savingTTSImport` mode, a `Trace.WriteLine` logs `"calibration record is null"` but processing continues. |