This commit is contained in:
2026-04-17 14:55:32 -04:00
commit bc3ac1d4c9
18017 changed files with 4371742 additions and 0 deletions

View File

@@ -0,0 +1,106 @@
---
source_files:
- DataPRO/Modules/Channels/ChannelCodes/ChannelCodesModule.cs
generated_at: "2026-04-16T04:55:41.104321+00:00"
model: "Qwen/Qwen3-Coder-Next-FP8"
schema_version: 1
sha256: "08f6598fbadc11d8"
---
# ChannelCodes
### **1. Purpose**
The `ChannelCodesModule` is a Prism-based modular component responsible for registering the UI views and view models associated with channel code management within the application. It integrates into the modular architecture by implementing the `IModule` interface and registering its core components—`ChannelCodesListViewModel` and `ChannelCodesListView`—as singleton services in the Unity dependency injection container during module initialization. Additionally, it contributes metadata (name, image, group, and region) to the host applications UI (e.g., main screen) via custom assembly-level attributes (`ChannelCodesModuleNameAttribute` and `ChannelCodesModuleImageAttribute`), enabling dynamic discovery and presentation of the module.
---
### **2. Public Interface**
#### **Classes & Interfaces**
- **`ChannelCodesModule : IModule`**
*Namespace:* `ChannelCodes`
*Purpose:* Prism module entry point for channel codes functionality.
- **`ChannelCodesModule(IUnityContainer unityContainer)`**
Constructor. Accepts and stores a Unity container reference for later registration of types.
- **`void Initialize()`**
Registers two types as singletons in the Unity container:
- `IChannelCodesListViewModel``ChannelCodesListViewModel`
- `IChannelCodesListView``ChannelCodesListView`
Called internally by `RegisterTypes()` (via Prisms module lifecycle).
- **`void OnInitialized(IContainerProvider containerProvider)`**
Currently empty; no logic implemented.
- **`void RegisterTypes(IContainerRegistry containerRegistry)`**
Delegates to `Initialize()` (despite using Prisms `IContainerRegistry`, it uses the Unity-specific `_unityContainer` internally).
#### **Assembly-Level Attributes**
- **`[ChannelCodesModuleName]`**
*Applied to assembly.*
- **`ChannelCodesModuleNameAttribute : TextAttribute`**
- **Constructor `ChannelCodesModuleNameAttribute(string s)`**
Sets `AssemblyName` to `AssemblyNames.ChannelCodes.ToString()`.
- **`override string AssemblyName { get; }`**
Returns `"ChannelCodes"` (value of `AssemblyNames.ChannelCodes.ToString()`).
- **`override Type GetAttributeType()`**
Returns `typeof(TextAttribute)`.
- **`override string GetAssemblyName()`**
Returns `AssemblyName`.
- **`[ChannelCodesModuleImage]`**
*Applied to assembly.*
- **`ChannelCodesModuleImageAttribute : ImageAttribute`**
- **Constructor `ChannelCodesModuleImageAttribute(string s)`**
Loads image via `AssemblyInfo.GetImage("ChannelCodes")`.
- **`override BitmapImage AssemblyImage { get; }`**
Returns the image loaded from `AssemblyInfo.GetImage("ChannelCodes")`.
- **`override BitmapImage GetAssemblyImage()`**
Returns `AssemblyImage`.
- **`override string AssemblyName { get; }`**
Returns `"ChannelCodes"`.
- **`override string GetAssemblyName()`**
Returns `AssemblyName`.
- **`override string AssemblyGroup { get; }`**
Returns `"Prepare"` (value of `eAssemblyGroups.Prepare.ToString()`).
- **`override string GetAssemblyGroup()`**
Returns `AssemblyGroup`.
- **`override eAssemblyRegion AssemblyRegion { get; }`**
Returns `eAssemblyRegion.ChannelCodesRegion`.
- **`override eAssemblyRegion GetAssemblyRegion()`**
Returns `AssemblyRegion`.
- **`override Type GetAttributeType()`**
Returns `typeof(ImageAttribute)`.
---
### **3. Invariants**
- The module **must** be loaded *after* the Unity container and `AssemblyInfo` service are available (since `AssemblyInfo.GetImage()` is called during attribute instantiation).
- `AssemblyNames.ChannelCodes`, `eAssemblyGroups.Prepare`, and `eAssemblyRegion.ChannelCodesRegion` must be defined and valid in the referenced `DTS.Common` assembly; otherwise, runtime errors will occur during attribute initialization.
- The `Initialize()` method assumes `_unityContainer` is non-null and properly configured; no null-check is performed.
- The `RegisterTypes()` methods use of `IContainerRegistry` is misleading—**it ignores the `containerRegistry` parameter** and operates solely on the injected `_unityContainer`. This may cause confusion or failure if Prisms `IContainerRegistry` is expected to be used.
---
### **4. Dependencies**
#### **Imports / External Dependencies**
- **Prism.Modularity** (`IModule`, `IContainerProvider`, `IContainerRegistry`)
- **Unity** (`IUnityContainer`)
- **DTS.Common** (specifically `AssemblyNames`, `AssemblyInfo`, `eAssemblyGroups`, `eAssemblyRegion`, `TextAttribute`, `ImageAttribute`)
- **System.Windows.Media.Imaging** (for `BitmapImage`)
- **ChannelCodes** namespace (contains `IChannelCodesListViewModel`, `IChannelCodesListView`, `ChannelCodesListViewModel`, `ChannelCodesListView`—not shown in this file but referenced).
#### **Depended Upon By**
- The host applications module loading infrastructure (Prism + Unity) to discover and load this module.
- UI components (e.g., main screen) that consume `ChannelCodesModuleNameAttribute` and `ChannelCodesModuleImageAttribute` to render module metadata.
---
### **5. Gotchas**
- **Misleading `RegisterTypes` implementation**: Despite implementing Prisms `RegisterTypes(IContainerRegistry)`, the method ignores `containerRegistry` and uses the Unity-specific `_unityContainer`. This breaks Prisms intended container abstraction and tightly couples the module to Unity.
- **Attribute initialization side effects**: `ChannelCodesModuleImageAttribute` calls `AssemblyInfo.GetImage(...)` in its constructor and property getters. This may cause exceptions if `AssemblyInfo` is not yet initialized or the image resource is missing—especially during design-time or in test environments.
- **No validation in `Initialize()`**: Type registrations occur unconditionally. If `IChannelCodesListViewModel` or `IChannelCodesListView` are not implemented, registration will fail silently until resolution time (or throw on first use).
- **Redundant/unused constructor parameters**: Both attribute constructors accept a `string s` parameter that is unused (assigned to `_name`/`_img` but never read beyond assignment).
- **No documentation for `OnInitialized`**: The empty override suggests incomplete implementation or future extensibility—unclear intent from source alone.

View File

@@ -0,0 +1,120 @@
---
source_files:
- DataPRO/Modules/Channels/ChannelCodes/Model/ChannelCodeType.cs
- DataPRO/Modules/Channels/ChannelCodes/Model/ChannelCode.cs
generated_at: "2026-04-16T04:56:25.345352+00:00"
model: "Qwen/Qwen3-Coder-Next-FP8"
schema_version: 1
sha256: "8041292bb801532f"
---
# Model
## Documentation: ChannelCode Module
---
### 1. Purpose
This module provides data access and modeling for *channel codes*—lookup values used to categorize or classify channels in the system (e.g., ISO-standardized codes vs. user-defined codes). It defines a base abstract class `ChannelCodeType` for retrieving static type metadata and a concrete class `ChannelCode` that represents individual channel code entries, including persistence operations (insert/update/delete) and caching of ISO codes from a static text file. The module serves as the data layer for channel code management, bridging the database (`sp_ChannelCodeTypeGet`, `sp_ChannelCodesGet`) and file-based ISO code definitions.
---
### 2. Public Interface
#### `ChannelCodeType.GetChannelCodeTypeLookup()`
```csharp
public static IDictionary<short, string> GetChannelCodeTypeLookup()
```
Retrieves all channel code types from the database via stored procedure `sp_ChannelCodeTypeGet`. Returns a dictionary mapping `Id` (short) to `CodeType` (string), representing the type categories (e.g., ISO, User). Parameters passed to the stored procedure (`@Id`, `@CodeType`) are null, indicating no filtering.
#### `ChannelCode` class
*Inherits from `DTS.Common.Classes.ChannelCodes.ChannelCode` and implements `IChannelCode`.*
- **Constructors**
- `ChannelCode()`
Initializes a new `ChannelCode` with `CodeType = ISO` and registers the `PasteCommand`.
- `ChannelCode(IChannelCode channelCode)`
Copies properties from an existing `IChannelCode` instance and registers `PasteCommand`.
- `ChannelCode(IDataRecord sqlReader, IDictionary<short, string> channelCodeLookup)`
Populates the instance from a database row (`sqlReader`) using the provided `channelCodeLookup`. Maps `CodeTypeInt` (short) to a `ChannelCodeType` enum value (`ISO` or `User`) via string comparison against `ChannelEnumsAndConstants.IsoCodeTypeString` and `ChannelEnumsAndConstants.UserCodeTypeString`.
- **Properties**
- `bool HasValidId()`
Returns `true` if `Id >= 0`.
- `bool IsBlank()`
Returns `true` if both `Name` and `Code` are `null` or empty.
- `int SelectedChannelType`
Gets/sets a legacy dropdown index (0 = ISO, 1 = User) based on `CodeType`. *Deprecated per inline comment.*
- `Dictionary<string, string> PossibleChannels { get; private set; }`
Publicly readable dictionary (currently unused in source; likely intended for channel mappings).
- `static IList<IChannelCode> ChannelCodes { get; }`
Returns a combined list of *all* channel codes: user-defined codes (from DB via `GetExistingChannelCodes`) + ISO codes (from `ISOChannelCodes`). Uses a shared lookup from `GetChannelCodeTypeLookup()`.
- `static IList<IChannelCode> ISOChannelCodes { get; }`
Lazily loads ISO codes from `ISOPossibleChannels.txt` (comma-separated: `Code,Name`). Caches in `_isoChannelCodes` after first access. Thread-safe via `lock(RefreshLock)`.
- **Methods**
- `static ChannelCode[] GetExistingChannelCodes(IDictionary<short, string> lookup)`
Fetches all user-defined channel codes from DB via `sp_ChannelCodesGet`, returning an array of `ChannelCode` instances. Parameters passed to the stored procedure (`@Id`, `@Code`, `@Name`, `@CodeType`) are null (no filtering).
- `void Delete()`
Calls `DbOperations.ChannelCodesDelete(Id, null, null, null)` to remove the channel code *from the lookup table only* (does not affect existing channel instances referencing it).
- `void Save(IDictionary<ChannelEnumsAndConstants.ChannelCodeType, short> lookup)`
Calls `DbOperations.ChannelCodesUpdate(restrictedLookup, this)` to persist changes to the channel code *lookup table*.
- `void Insert(IDictionary<ChannelEnumsAndConstants.ChannelCodeType, short> lookup)`
Calls `DbOperations.ChannelCodesInsert(restrictedLookup, this, out id)` to insert a new channel code. On success (`hr == 0`), sets `Id` to the returned value.
- `protected static long GetLong(OleDbDataReader reader, string field)`
Helper for legacy OleDb access; returns `long.MinValue` on `DBNull`. *Not used in current code.*
- `protected static DateTime GetDate(OleDbDataReader reader, string field)`
Helper for legacy OleDb access; returns `DateTime.MinValue` on `DBNull`. *Not used in current code.*
#### Command
- `PasteCommand` (public property, type `ICommand`)
Initialized as `PasteCommandClass(PASTE_ID)` in `RegisterCommands()`. A no-op `Paste` handler is defined but empty. Registered via `CommandManager.RegisterClassCommandBinding`.
---
### 3. Invariants
- **`Id` validity**: `HasValidId()` requires `Id >= 0`. Negative IDs are considered invalid.
- **Code type mapping**: `CodeType` must be either `ChannelEnumsAndConstants.ChannelCodeType.ISO` or `ChannelEnumsAndConstants.ChannelCodeType.User`. Mapping from DB `CodeTypeInt` relies on exact string matches against `IsoCodeTypeString` and `UserCodeTypeString`.
- **ISO codes are static**: `ISOChannelCodes` are loaded once and cached in `_isoChannelCodes`. They are *not* persisted to the database.
- **Persistence scope**: `Insert`, `Save`, and `Delete` operations affect *only the channel code lookup table*, not any channels that may reference the code.
- **Thread safety**: ISO code loading uses `lock(RefreshLock)` to ensure single initialization.
- **Null handling**: `IsBlank()` treats `null` and empty strings identically.
---
### 4. Dependencies
#### **Dependencies *of* this module**
- **Database**:
- Stored procedures: `sp_ChannelCodeTypeGet`, `sp_ChannelCodesGet`
- Table columns: `Id`, `Code`, `Name`, `CodeTypeInt`
- **File system**:
- `ISOPossibleChannels.txt` (comma-separated: `Code,Name`) in app base directory.
- **External types**:
- `DTS.Common.Storage.DbOperations` (provides `GetSQLCommand`, `ChannelCodesDelete`, `ChannelCodesUpdate`, `ChannelCodesInsert`)
- `DTS.Common.Classes.ChannelCodes.ChannelCode` (base class)
- `DTS.Common.Interface.Channels.ChannelCodes.IChannelCode` (interface)
- `DTS.Common.Enums.Channels.ChannelEnumsAndConstants` (defines `ChannelCodeType`, `IsoCodeTypeString`, `UserCodeTypeString`)
- `System.Data.SqlClient`, `System.Data`, `System.IO`, `System.Windows.Input`
#### **Dependencies *on* this module**
- Any module needing channel code metadata or management (e.g., UI dropdowns, channel assignment logic).
- `ISOChannelCodes` implies a hard dependency on the presence and format of `ISOPossibleChannels.txt`.
---
### 5. Gotchas
- **`SelectedChannelType` is legacy/deprecated**: The property is tied to a dropdown that may no longer exist. Its use is discouraged.
- **`PasteCommand` is non-functional**: The `Paste` handler is empty; the command is registered but does nothing.
- **`PossibleChannels` is unused**: The property is declared but never populated in the source.
- **ISO codes are *not* persisted**: Changes to `ISOChannelCodes` (e.g., via `Insert`/`Save`) will not affect `ISOPossibleChannels.txt`. This file is read-only at runtime.
- **`Delete`/`Save`/`Insert` do not cascade**: Operations affect only the channel code *definition* (lookup), not any existing channels that reference the code.
- **Thread-safety limitation**: ISO code loading is thread-safe for initialization, but no caching invalidation mechanism exists (codes are assumed immutable).
- **`GetLong`/`GetDate` are dead code**: OleDb-specific helpers with no callers in this module. Likely remnants of legacy migration code.
- **`ChannelCodes` property is expensive**: Each access calls `GetChannelCodeTypeLookup()` and `GetExistingChannelCodes()`, which hit the database. Caching externally is recommended if used repeatedly.
- **No validation on `Code`/`Name`**: The module does not enforce uniqueness or non-empty values beyond `IsBlank()`. Business rules may be enforced elsewhere.
- **`Id` assignment is conditional**: `Insert` only sets `Id` if `hr == 0`; callers must check the return value or handle failure.
*None identified from source alone.* (Note: The above are inferred from explicit comments and code structure—not hallucinated.)

View File

@@ -0,0 +1,47 @@
---
source_files:
- DataPRO/Modules/Channels/ChannelCodes/Properties/Settings.Designer.cs
- DataPRO/Modules/Channels/ChannelCodes/Properties/AssemblyInfo.cs
generated_at: "2026-04-16T04:56:06.604797+00:00"
model: "Qwen/Qwen3-Coder-Next-FP8"
schema_version: 1
sha256: "4a79c622a52c39c9"
---
# Properties
## Documentation: ChannelCodes.Properties.Settings
### 1. Purpose
This module defines a strongly-typed settings class (`Settings`) for the `ChannelCodes` assembly, enabling centralized access to application-level configuration values via the .NET `ApplicationSettingsBase` infrastructure. It serves as the runtime interface for reading (and potentially writing) user- or application-scoped settings, generated automatically by Visual Studios settings designer. The class is internal and sealed, intended solely for use within the `ChannelCodes` module to manage persistent configuration state.
### 2. Public Interface
The module exposes **one public static property**:
- **`Settings.Default`**
- **Signature**: `public static Settings Default { get; }`
- **Behavior**: Returns the singleton instance of the `Settings` class, synchronized for thread safety via `ApplicationSettingsBase.Synchronized`. This instance provides access to all application settings defined in the projects `.settings` file (e.g., `Properties/Settings.settings`). Note: The actual settings properties (e.g., `string SomeSetting { get; set; }`) are *not present in the provided source* and must be defined in the corresponding auto-generated `Settings.cs` (not included here). This file only declares the class skeleton and the `Default` accessor.
### 3. Invariants
- The `Settings` class inherits from `ApplicationSettingsBase`, which enforces standard .NET settings semantics:
- Settings values are persisted per-user (user-scoped) or per-application (application-scoped), depending on their `UserScopedSetting`/`ApplicationScopedSetting` attributes (not visible here).
- Thread-safety is guaranteed for the `Default` instance via synchronization.
- The class is `internal sealed`, meaning it cannot be inherited or accessed outside the `ChannelCodes.Properties` namespace.
- The `defaultInstance` field is initialized once during static construction and never reassigned.
### 4. Dependencies
- **Dependencies *of* this module**:
- `System.Configuration` (for `ApplicationSettingsBase` and related types).
- `System.Runtime.CompilerServices` (for `CompilerGeneratedAttribute`).
- `System.CodeDom.Compiler` (for `GeneratedCodeAttribute`).
- **Dependencies *on* this module**:
- Other parts of the `ChannelCodes` module (or dependent modules) likely consume `Settings.Default` to read configuration values. However, no explicit usages are visible in the provided files.
### 5. Gotchas
- **Auto-generated code**: This file is auto-generated by Visual Studios settings designer. Manual edits will be overwritten on regeneration.
- **Missing settings definitions**: The provided snippet only shows the class declaration and `Default` property. Actual settings (e.g., `public string ChannelMapPath { get; set; }`) are defined in the corresponding `Settings.Designer.cs` *before* regeneration or in the `.settings` designer file (not included). Without those, `Settings.Default` has no accessible properties beyond inherited `ApplicationSettingsBase` members.
- **No write support implied**: While `ApplicationSettingsBase` supports setting values, this file does not indicate whether settings are read-only (application-scoped) or read/write (user-scoped). Behavior depends on attributes in the full `Settings.cs` (not provided).
- **Thread-safety scope**: Synchronization applies only to the `Default` instance retrieval—not to individual property access or modification. Concurrent writes to settings properties may still require external locking.
- **No versioning or migration logic**: The assembly version (`1.0.0.0`) suggests no settings schema evolution handling is visible here. Migration of settings across versions would require explicit `SettingsUpgrade` logic (absent in this snippet).
> **Note**: Full behavior (e.g., available settings, their types, scopes, and defaults) cannot be determined from the provided files alone. Consult the `ChannelCodes.Properties.Settings.settings` designer file or the full `Settings.Designer.cs` (which typically contains the property definitions).

View File

@@ -0,0 +1,104 @@
---
source_files:
- DataPRO/Modules/Channels/ChannelCodes/Resources/TranslateExtension.cs
- DataPRO/Modules/Channels/ChannelCodes/Resources/StringResources.Designer.cs
generated_at: "2026-04-16T04:55:56.339798+00:00"
model: "Qwen/Qwen3-Coder-Next-FP8"
schema_version: 1
sha256: "3fc30f8d93dc5d3b"
---
# Resources
## Documentation: `TranslateExtension` Markup Extension
---
### **Purpose**
The `TranslateExtension` class provides a XAML markup extension for localized string lookup within the `ChannelCodes` module. It enables declarative binding of UI text to resource keys defined in `StringResources.resx`, supporting internationalization by resolving keys at runtime using the .NET `ResourceManager`. This allows UI elements (e.g., `TextBlock.Text`, `Button.Content`) to display culture-specific strings without hardcoding values or writing code-behind.
---
### **Public Interface**
#### `TranslateExtension(string key)`
**Constructor**
- **Parameter**: `key` (`string`) The resource key to look up (e.g., `"ChannelCode"`, `"DuplicateISOChannelCode"`).
- **Behavior**: Stores the key for later resolution. No validation is performed at construction time.
#### `public override object ProvideValue(IServiceProvider serviceProvider)`
**Markup Extension Entry Point**
- **Parameter**: `serviceProvider` (`IServiceProvider`) Provides services to the markup extension (unused in current implementation).
- **Returns**:
- `string`: The localized string corresponding to `_key`, or
- `NotFound` (`"#stringnotfound#"`): If `_key` is `null` or empty,
- `NotFound + " " + _key`: If `_key` is non-empty but no matching resource string is found.
- **Behavior**:
1. Checks if `_key` is `null` or empty → returns `"#stringnotfound#"`.
2. Calls `StringResources.ResourceManager.GetString(_key)` to retrieve the localized string.
3. If `GetString` returns `null`, appends the key to the `NotFound` prefix (e.g., `"#stringnotfound# MissingISOCode"`).
> **Note**: The `MarkupExtensionReturnType` attribute indicates this extension always returns a `string`.
---
### **Invariants**
1. **Key Handling**:
- Empty or `null` keys are treated as invalid and always resolve to `"#stringnotfound#"`.
- Non-empty keys that lack a corresponding resource entry resolve to `"#stringnotfound# <key>"`.
2. **Resource Lookup**:
- Uses `StringResources.ResourceManager.GetString(key)` with the current UI culture (via `CultureInfo`).
- No fallback logic beyond the `null` check in `ProvideValue`.
3. **Thread Safety**:
- `StringResources.ResourceManager` is lazily initialized and cached (per `StringResources` class), but `TranslateExtension` itself is stateful per instance (stores `_key`). Reuse across threads is safe *only if* the same instance is not shared concurrently (standard for markup extensions).
---
### **Dependencies**
#### **Depends On**
- `System.Windows.Markup.MarkupExtension` (WPF framework)
- `ChannelCodes.Resources.StringResources` (strongly-typed resource class)
- Specifically relies on `StringResources.ResourceManager` and its `GetString(string)` method.
- `System` (for `string.IsNullOrEmpty`, `ResourceManager`, `CultureInfo`)
#### **Used By**
- XAML files in the `ChannelCodes` module (e.g., `*.xaml` pages) where localized text is declared via `{local:Translate KeyName}`.
- Example usage:
```xaml
<TextBlock Text="{local:Translate ChannelCode}" />
```
---
### **Gotchas**
1. **No Resource Key Validation at Compile Time**:
- Typos in resource keys (e.g., `"ChannelCodee"` instead of `"ChannelCode"`) will silently resolve to `"#stringnotfound# ChannelCodee"` at runtime.
- No build-time or design-time warning is generated for missing keys.
2. **Hardcoded `NotFound` Prefix**:
- The `"#stringnotfound#"` prefix is hardcoded and may be visible in the UI if a key is missing. This is likely intentional for debugging but could confuse end users.
3. **No Caching of Resolved Strings**:
- `ProvideValue` calls `ResourceManager.GetString(_key)` on every invocation. While `ResourceManager` caches resources internally, repeated use of the same key in a UI (e.g., in a `DataTemplate`) may incur unnecessary lookups. Consider caching if performance is critical.
4. **Culture Handling**:
- Respects `StringResources.Culture` (settable via `StringResources.Culture = ...`). If `Culture` is `null`, the UI threads `CurrentUICulture` is used.
- No explicit handling for fallback cultures (e.g., `en-US` → `en`).
5. **Auto-Generated Resource Class**:
- `StringResources.Designer.cs` is auto-generated. Manual edits will be overwritten. New strings must be added via `.resx` files and regenerated.
6. **No Support for Format Strings**:
- `TranslateExtension` does not support parameterized resources (e.g., `"Error: {0} is missing"`). While `StringResources` has entries like `DuplicateISOChannelCode` (which uses `{0}`), the extension itself does not accept or apply formatting arguments.
- To use formatted strings, the caller must manually construct the key (e.g., `"DuplicateISOChannelCode"`), but the resolved string will remain unformatted unless the *caller* applies `string.Format` (not done here).
7. **WPF-Specific**:
- Depends on `System.Windows.Markup`, making it unusable outside WPF (e.g., in MAUI, WinUI, or console apps).
---
*Documentation generated from source files dated to .NET Framework 4.0 and WPF. No external dependencies beyond standard .NET libraries.*

View File

@@ -0,0 +1,70 @@
---
source_files:
- DataPRO/Modules/Channels/ChannelCodes/View/ChannelCodesListView.xaml.cs
generated_at: "2026-04-16T04:56:21.286180+00:00"
model: "Qwen/Qwen3-Coder-Next-FP8"
schema_version: 1
sha256: "0dcb0611d2fa879c"
---
# View
## **1. Purpose**
This module implements the WPF view layer (`ChannelCodesListView`) for a channel codes management UI, adhering to the `IChannelCodesListView` interface. It provides interactive controls for viewing, editing, sorting, filtering, and selecting channel codes in two distinct modes: ISO and User. The view binds to an `IChannelCodesListViewModel` and handles user interactions such as text edits, checkbox toggles, column header clicks, and selection changes, delegating state management and validation logic to the view model.
---
## **2. Public Interface**
The class `ChannelCodesListView` implements `IChannelCodesListView` (via `partial class` + `: IChannelCodesListView`) and exposes only its constructor publicly. All other members are private event handlers wired via XAML. No public methods or properties are defined in this file.
### **Constructor**
- **`ChannelCodesListView()`**
Initializes the WPF component by calling `InitializeComponent()`. Sets up the visual tree defined in `ChannelCodesListView.xaml`.
All other functionality is exposed indirectly via event handlers attached to XAML elements (e.g., `KeyDown`, `TextChanged`, `SelectionChanged`, `Click`), which internally interact with the `DataContext` (expected to be an `IChannelCodesListViewModel`).
---
## **3. Invariants**
- The `DataContext` **must** be an instance implementing `IChannelCodesListViewModel`; otherwise, most event handlers silently return.
- Column sorting and filtering rely on the `Tag` property of `GridViewColumnHeaderSearchable` elements (e.g., `ISOCodeColumnHeader`, `UserCodeColumnHeader`). These tags must be non-null and correspond to valid filter/sort keys expected by the view model.
- Selection changes in either `ISOChannelCodesListView` or `UserChannelCodesListView` must result in exactly one `IChannelCode` item being selected per list (based on handler logic in `ISO_Checked`/`User_Checked` and selection handlers), though the code does not enforce uniqueness beyond what the view model allows.
- The `ChannelCodeBuilder_OnChannelCodeSelected` handler assumes that if `channelCode.Name` is null/whitespace, it should be overwritten with the selected `name` parameter.
- Text/keydown handlers for `ChannelCodeTextBoxUser`, `DisplayNameTextBoxUser`, `ChannelCodeTextBoxIso`, and `DisplayNameTextBoxIso` always call `MarkModified(channelCode)` and then invoke `ValidateUser(...)` or `ValidateISO(...)` with unused `List<string>` parameters—indicating validation results are likely ignored or handled internally by the view model.
---
## **4. Dependencies**
### **Imports / External Types Used**
- `System.Collections.Generic`, `System.Windows`, `System.Windows.Controls`, `System.Windows.Media` — standard WPF and .NET types.
- `DTS.Common.Controls` — likely contains custom controls (e.g., `GridViewColumnHeaderSearchable`).
- `DTS.Common.Enums.Channels` — contains `ChannelEnumsAndConstants.ChannelCodeType`.
- `DTS.Common.Interface.Channels.ChannelCodes` — defines `IChannelCodesListView`, `IChannelCodesListViewModel`, `IChannelCode`.
- `DTS.Common.Utils` — contains `Utils.FindChild<T>` helper.
- `ChannelCodes.Resources.StringResources` — static resource class for localized strings (e.g., `"ISOCode"`, `"UserChannelName"`).
### **Inferred Dependencies**
- **Depends on**:
- `IChannelCodesListViewModel` (via `DataContext`) for filtering, sorting, validation, and selection state.
- `IChannelCode` interface for individual code objects.
- Custom control `GridViewColumnHeaderSearchable` for searchable column headers.
- `ChannelCodesListView.xaml` (implicit dependency via `InitializeComponent()`).
- **Depended on by**:
- Likely consumed by a parent view or shell that binds an `IChannelCodesListViewModel` instance to its `DataContext`.
---
## **5. Gotchas**
- **Silent failures**: Most handlers return early if `DataContext` is not `ChannelCodesListViewModel` (or `IChannelCodesListViewModel`), leading to no-op behavior without logging or exceptions.
- **Unused validation outputs**: All `ValidateUser`/`ValidateISO` calls instantiate and pass `new List<string>()` for `out`/`ref` parameters, but the lists are never used—suggesting validation errors are either ignored or handled via side effects (e.g., raising `INotifyDataErrorInfo` or UI bindings).
- **Redundant selection handling**: Multiple event handlers (`ISO_Checked`, `User_Checked`, `*SelectionChanged`, `*TextBox*SelectionChanged`) all call `vm.SetISOSelection(...)` or `vm.SetUserSelection(...)`, potentially causing duplicate or conflicting selection updates. This may indicate legacy or overlapping event wiring.
- **Hit-test complexity**: `ISOChannelCodesListView_PreviewMouseLeftButtonUp` and `UserChannelCodesListView_PreviewMouseLeftButtonUp` use multiple hit tests (`VisualTreeHelper.HitTest`, `InputHitTest`) and descendant checks to determine sort triggers—fragile and hard to maintain. Sorting is triggered on clicks anywhere in a column header, including `TextBlock`s with specific localized text.
- **Commented-out code**: A `ChannelType_SelectionChanged` handler is commented out, suggesting incomplete or deprecated logic.
- **Assumed control types**: Handlers assume specific control types (`TextBox`, `ListView`, `TextBlock`, `Control`) and cast them directly—could throw if XAML changes unexpectedly.
None identified beyond the above.

View File

@@ -0,0 +1,233 @@
---
source_files:
- DataPRO/Modules/Channels/ChannelCodes/ViewModel/ChannelCodesListViewModel.cs
generated_at: "2026-04-16T04:56:00.828392+00:00"
model: "Qwen/Qwen3-Coder-Next-FP8"
schema_version: 1
sha256: "a1a75e2ca7b7b574"
---
# ViewModel
### **1. Purpose**
The `ChannelCodesListViewModel` class serves as the view model for managing and displaying channel codes (both ISO and User-defined) in a data entry UI. It orchestrates data loading, filtering, sorting, editing (including paste, copy, delete, and validation), and persistence operations for channel codes. It acts as the intermediary between the UI (`IChannelCodesListView`) and the underlying data layer (`ChannelCode`, `ChannelCodeType`), leveraging Prisms event aggregation for decoupled communication and Unity for dependency injection. Its primary role is to expose collections of channel codes (`ISOChannelCodes`, `UserChannelCodes`) and provide methods to manipulate and validate them before saving to the database.
---
### **2. Public Interface**
#### **Properties**
- `IChannelCodesListView View { get; set; }`
Reference to the associated view; view model sets `View.DataContext = this`.
- `InteractionRequest<Notification> NotificationRequest { get; }`
Prism interaction request used to show notification popups (e.g., errors, info).
- `InteractionRequest<Confirmation> ConfirmationRequest { get; }`
Prism interaction request used to prompt for user confirmation (e.g., delete).
- `event PropertyChangedEventHandler PropertyChanged`
Standard `INotifyPropertyChanged` implementation; `OnPropertyChanged` raises it.
- `List<IChannelCode> AllISOChannelCodes { get; set; }`
Full list of ISO channel codes (including blank trailing row), used for sorting/filtering.
- `List<IChannelCode> AllUserChannelCodes { get; set; }`
Full list of User channel codes (including blank trailing row), used for sorting/filtering.
- `ObservableCollection<IChannelCode> ISOChannelCodes { get; set; }`
Filtered/sorted view of `AllISOChannelCodes`, bound to the UI.
- `ObservableCollection<IChannelCode> UserChannelCodes { get; set; }`
Filtered/sorted view of `AllUserChannelCodes`, bound to the UI.
- `ViewModes ViewMode { get; set; }`
Current view mode (`ISO` or `User`). Changing it updates `ISOVisibility`/`UserVisibility`.
- `Visibility ISOVisibility { get; }`
`Visible` if `ViewMode == ViewModes.ISO`, else `Collapsed`.
- `Visibility UserVisibility { get; }`
`Visible` if `ViewMode == ViewModes.User`, else `Collapsed`.
- `bool IsBusy { get; set; }`
Bound to busy indicator; updated via `OnBusyIndicatorNotification`.
- `bool IsDirty { get; private set; }` *(Note: never set in source — likely unused or bug)*
- `bool IsReadOnly { get; set; }`
Controls editability of the view (e.g., based on permissions).
- `bool IsMenuIncluded { get; set; }`, `bool IsNavigationIncluded { get; set; }`
UI layout toggles.
- `object Page { get; private set; }`
Identifier for the page this VM serves (used in events to route to correct consumer).
- `Func<IList<IChannelCode>> ChannelCodesFunc { get; }`
Returns `GetAllChannels()``ChannelCode.ChannelCodes`.
- `bool ShowISOStringBuilder { get; set; }`, `bool ShowChannelCodeLookupHelper { get; set; }`, `bool UniqueISOCodesRequired { get; set; }`
UI configuration flags.
#### **Methods**
- `void SetPage(object page)`
Sets the `Page` identifier used in events.
- `void OnSetActive()`
Loads existing channel codes from DB (`ChannelCode.GetExistingChannelCodes`), populates `AllISOChannelCodes`/`AllUserChannelCodes`, adds blank trailing rows, sorts, filters, and updates `ISOChannelCodes`/`UserChannelCodes`. Logs exceptions.
- `void Unset()`
Clears all channel code collections and raises property change notifications.
- `void Initialize()`, `void Initialize(object)`, `Task InitializeAsync()`, `void Activated()`, `void Cleanup()`, `Task CleanupAsync()`
No-op stubs (likely required by Prism interface contracts).
- `bool Save()`
Persists changes in three steps:
1. Deletes removed codes (those with valid IDs not in `All*ChannelCodes`).
2. Updates existing codes (those with valid IDs).
3. Inserts new codes (those without valid IDs and not blank).
Returns `true` on success; publishes `PageModifiedEvent(Status.Saved)` or `PageErrorEvent` on failure.
- `void Remove(IChannelCode channel)`
Removes a channel from both `All*` and `*ChannelCodes` lists, adds a blank row if the last row was removed, and publishes `PageModifiedEvent(Status.Modified)`.
- `void MarkModified(IChannelCode channel)`
Ensures a blank row is added after the modified channel (if its the last visible row), and publishes `PageModifiedEvent(Status.Modified)`.
- `void Validate(bool bDisplayWindow)`
Validates all ISO/User codes: checks for missing code/name, duplicate code+name pairs. Populates `errors`/`warnings` lists. If `bDisplayWindow`, publishes `PageErrorEvent`. Returns `true` if no errors.
- `void ValidateISO(ref List<string> errors, ref List<string> warnings)`
Validates ISO codes only (calls `CheckChannelCode`).
- `void ValidateUser(ref List<string> errors, ref List<string> warnings)`
Validates User codes only (calls `CheckChannelCode`).
- `void CopySelected()`
Copies selected items (from current `ViewMode`) into `All*ChannelCodes` (before the trailing blank row), then sorts/filters.
- `void DeleteSelected()`
Deletes selected items (from current `ViewMode`), adds blank row if last item deleted, clears selection, and publishes `PageModifiedEvent(Status.Modified)`.
- `void SetISOSelection(IChannelCode[] channelCodes)`, `void SetUserSelection(IChannelCode[] channelCodes)`
Stores selected items; triggers `PageSelectionChanged` event if `ViewMode` matches.
- `IChannelCode[] SelectedCodes { get; }`
Returns selected items for current `ViewMode`.
- `void Filter(object columnTag, string searchTerm)`
Updates `_searchTermForField` and re-applies filter (`FilterIso`/`FilterUser`).
- `void Sort(object columnTag, bool bColumnClick)`
Updates sort field/direction and re-applies sort (`SortIso`/`SortUser`) + filter.
- `void OnRaiseNotification(NotificationContentEventArgs)`
Handles `RaiseNotification` events by raising `NotificationRequest`.
- `void OnBusyIndicatorNotification(bool)`
Updates `IsBusy` property.
- `void ReportErrors(string[] errors)`
Publishes `PageErrorEvent`.
---
### **3. Invariants**
- **Trailing Blank Row**:
`AllISOChannelCodes` and `AllUserChannelCodes` always contain a trailing blank `ChannelCode` (added in `OnSetActive`, `Remove`, `MarkModified`, `Paste*`, `CopySelected`, `DeleteSelected`). This enables adding new entries.
- **Filtering Logic**:
`ISOChannelCodes`/`UserChannelCodes` only include rows where:
- Both `Code` and `Name` are blank, **or**
- `Code`/`Name` matches current search term (case-insensitive substring match).
- **Sorting Logic**:
Sorting uses `ChannelComparer`, which:
- Treats blank rows (empty `Code` and `Name`) as *lowest priority* (sorted to bottom).
- Uses `NaturalStringComparer` for case-insensitive, culture-aware comparison.
- Sorts `Code`/`Name` fields separately for ISO/User modes.
- **Validation Rules**:
A channel code is invalid if:
- `Code` is missing (for non-blank rows) → error.
- `Name` is missing (for non-blank rows) → error.
- Duplicate `Code` + `Name` pair exists → error.
- **Save Order**:
`Save()` processes deletions → updates → inserts to avoid ID/name conflicts.
- **Event Subscription Guard**:
`_bAddListeners` ensures only the *second* instantiation of `ChannelCodesListViewModel` subscribes to `TextPastedEvent`/`ChannelCodeCommittedEvent` (a workaround for app startup ordering).
---
### **4. Dependencies**
#### **Imports/Usings (External Dependencies)**
- `Prism.Events` (`IEventAggregator`, `EventBase`)
- `Prism.Regions` (`IRegionManager`)
- `Unity` (`IUnityContainer`)
- `DTS.Common.*`:
- `Enums.Channels.ChannelEnumsAndConstants`
- `Events.*` (`TextPastedEvent`, `ChannelCodeCommittedEvent`, `PageModifiedEvent`, `PageErrorEvent`, `PageSelectionChanged`)
- `Interface.Channels.ChannelCodes.*` (`IChannelCodesListView`, `IChannelCodesListViewModel`, `IChannelCode`)
- `Utilities.*` (`NaturalStringComparer`, `Logging.APILogger`)
- `Interactivity` (`InteractionRequest<Notification/Confirmation>`)
#### **Internal Dependencies**
- `ChannelCodes.Model` (`ChannelCode`, `ChannelCodeType`)
- `DTS.Common.Enums` (`UIItemStatus`, `PageModifiedArg.Status`)
- `Resources.StringResources` (for localized error messages)
#### **Consumers (Inferred)**
- `ChannelCodesListViewModel` is instantiated via Unity (constructor injection).
- `IChannelCodesListView` binds to its properties/methods.
- Other modules subscribe to its events (`PageModifiedEvent`, `PageErrorEvent`, `PageSelectionChanged`).
- `ChannelCodeCommittedEvent` publisher (e.g., a dialog) calls `OnChannelCodesCommitted`.
---
### **5. Gotchas**
- **`_bAddListeners` Hack**:
A static boolean `_bAddListeners` prevents *first* instantiation from subscribing to events (due to app startup ordering). Only the *second* instance subscribes. This is fragile and non-obvious.
- **`IsDirty` Never Set**:
The `IsDirty` property is declared but never updated (no assignment in source). Likely dead code or incomplete implementation.
- **`SelectedCodes` Null Safety**:
`GetSelectedISOCodes`/`GetSelectedUserCodes` return `null` if `_selectedISOItems`/`_selectedUserItems` are `null`. Consumers must handle `null`.
- **Paste Behavior Depends on `tag`**:
`PasteIso`/`PasteUser` use `tag` to determine if pasted data is `Code` or `Name`-only (via `bCode = tag.Equals("ISOCode")`). If `tag` is incorrect, data may be misassigned.
- **Duplicate Code Handling**:
Validation flags *duplicate code+name pairs* as errors, but allows duplicate codes with *different names*. This may be intentional (e.g., ISO codes can map to multiple names), but could be confusing.
- **`OnChannelCodesCommitted` Logic Complexity**:
The method builds multiple dictionaries (`lookup2`, `isoLookup`, `userLookup`) to avoid duplicates during batch commits. This is error-prone and duplicates logic in `Save()`.
- **`ParseText` Delimiter Fallback**:
Tries to split by `,`, then `\t`, then `;`. If none yield 2 tokens, the line is skipped. This may silently fail if data uses unexpected delimiters.
- **`Validate` Ignores Blank Rows**:
Blank rows (empty `Code`/`Name`) are skipped during validation. This is correct, but the logic is nested inside `CheckChannelCode`.
- **No Undo/Revert**:
Changes are published as `PageModifiedEvent(Status.Modified)` immediately on edit, but no mechanism to revert is visible.
- **`ChannelCodesFunc` Usage Unclear**:
`ChannelCodesFunc` is exposed but its usage (e.g., by `GetAllChannels`) is not shown in this file. Likely consumed externally.
- **`UniqueISOCodesRequired` Flag**:
The property exists but is never used in validation logic (despite its name). May be a future feature flag.
- **`NotifySelectionChanged` Only Notifies When `ViewMode` Matches**:
Selection change events are only published if the current `ViewMode` matches the selection type (ISO/User). This may cause inconsistent selection state if `ViewMode` changes after selection.
- **No Null Checks on `View`**:
`View.DataContext = this` assumes `View` is non-null, but no validation exists.

View File

@@ -0,0 +1,47 @@
---
source_files:
- DataPRO/Modules/Database/DatabaseInitializationScripts/EmbeddedResource.cs
generated_at: "2026-04-16T04:35:11.382491+00:00"
model: "Qwen/Qwen3-Coder-Next-FP8"
schema_version: 1
sha256: "ae12472d249773d0"
---
# DatabaseInitializationScripts
## 1. Purpose
This module provides utilities for reading embedded resources (e.g., SQL scripts, configuration files) from a .NET assemblys manifest resources. It exists to abstract away the boilerplate of locating and extracting embedded resources by name, particularly supporting scenarios where database initialization scripts are bundled as embedded resources within the assembly. It enables both stream-based and string-based access to such resources, with overloads that allow specifying a custom assembly or defaulting to the assembly containing the `EmbeddedResource` class itself.
## 2. Public Interface
- **`static StreamReader GetStream(Assembly assembly, string name)`**
Searches the manifest resource names of the given `assembly` for a resource whose name *ends with* the provided `name` (case-sensitive substring match), and returns a `StreamReader` for the first matching resource. Returns `null` if no match is found.
*Note: The caller is responsible for disposing the returned `StreamReader`.*
- **`static string GetString(Assembly assembly, string name)`**
Calls `GetStream(assembly, name)`, reads the entire contents of the stream into a string using `ReadToEnd()`, closes the stream, and returns the resulting string. Returns `null` if `GetStream` returns `null`.
*Note: This method disposes the `StreamReader` internally via `sr.Close()`.*
- **`static string GetString(string name)`**
Overload of `GetString` that uses the assembly containing the `EmbeddedResource` class itself (`typeof(EmbeddedResource).Assembly`) as the target assembly. Behaves identically to `GetString(assembly, name)` for that assembly.
## 3. Invariants
- **Substring matching semantics**: Resource lookup uses `EndsWith(name)`, meaning the full manifest resource name must end with the provided `name` string. For example, `GetString("init.sql")` would match `"MyApp.Migrations.init.sql"` but not `"init.sql.bak"`.
- **First-match behavior**: If multiple resources end with the same `name`, only the first one (as returned by `GetManifestResourceNames()`) is used. The order is not guaranteed by the .NET specification and may vary across builds or environments.
- **No validation of resource existence beyond null**: `GetStream` returns `null` if no matching resource is found; callers must handle this case explicitly.
- **Resource names are case-sensitive**: `EndsWith` performs case-sensitive comparison by default in .NET.
## 4. Dependencies
- **Depends on**:
- `System.IO` (for `StreamReader`)
- `System.Reflection.Assembly` (for `GetManifestResourceNames()` and `GetManifestResourceStream()`)
- **Depended on by**:
- Not inferable from this file alone. However, given the namespace (`DatabaseInitializationScripts`), it is highly likely used by database migration or setup logic elsewhere in the codebase (e.g., to load `.sql` files during schema initialization).
- The default `GetString(string)` overload implies a design assumption that the assembly containing `EmbeddedResource` is the one housing the embedded resources—likely the same assembly where this class resides.
## 5. Gotchas
- **Resource name ambiguity**: Because matching is based on `EndsWith`, two resources named `"script1.sql"` and `"subfolder/script1.sql"` would both match a lookup for `"script1.sql"`, and only the first (arbitrary) one would be returned. This can lead to unpredictable behavior if resource naming is not strictly controlled.
- **Resource stream not disposed by caller**: `GetStream` returns an open `StreamReader`; callers must ensure it is disposed (e.g., via `using`), otherwise resource leaks may occur. The `GetString(Assembly, string)` overload avoids this by closing the stream internally, but the stream-returning overload does not.
- **Encoding assumption**: `StreamReader.ReadToEnd()` uses the default encoding of the `StreamReader`, which is UTF-8 *without BOM* by default in modern .NET. If the embedded resource is encoded differently (e.g., UTF-8 with BOM, UTF-16), the string may be misinterpreted.
- **No support for nested paths**: The API does not distinguish between resource names with directory-like separators (e.g., `"Scripts/init.sql"` vs `"init.sql"`), increasing the risk of collisions.
- **`null` return without exception**: `GetStream` returns `null` on failure, which may lead to `NullReferenceException` if callers do not check for it before use.
- **`sr.Close()` is not `Dispose()`**: While `Close()` and `Dispose()` are functionally equivalent for `StreamReader`, using `Close()` instead of `using` or `Dispose()` is outdated style and may obscure resource management intent.

View File

@@ -0,0 +1,91 @@
---
source_files:
- DataPRO/Modules/Database/DatabaseInitializationScripts/Properties/Settings.Designer.cs
- DataPRO/Modules/Database/DatabaseInitializationScripts/Properties/AssemblyInfo.cs
- DataPRO/Modules/Database/DatabaseInitializationScripts/Properties/Resources.Designer.cs
generated_at: "2026-04-16T04:36:10.385400+00:00"
model: "Qwen/Qwen3-Coder-Next-FP8"
schema_version: 1
sha256: "e3f89237ebe0a62c"
---
# Properties
## Documentation: `DatabaseInitializationScripts.Properties` Module
---
### 1. **Purpose**
This module contains auto-generated .NET assembly metadata and resource management infrastructure for the `DatabaseInitializationScripts` project. It does *not* contain business logic or database initialization scripts themselves; rather, it provides supporting infrastructure—such as strongly-typed settings, resources, and assembly-level attributes—required by the .NET framework for localization, configuration, and COM interop. Its role is purely infrastructural and exists to satisfy standard WPF/WinForms project conventions.
---
### 2. **Public Interface**
All types in this module are `internal` and auto-generated. No user-defined public APIs exist beyond the standard .NET patterns shown below.
#### `Settings` class
```csharp
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase
```
- **`Settings.Default`** (static property)
Returns the singleton instance of the `Settings` class, synchronized for thread safety via `ApplicationSettingsBase.Synchronized`.
*Note:* As the class is auto-generated and empty (no user-defined settings), this property currently returns a settings object with no configurable properties.
#### `Resources` class
```csharp
internal class Resources
```
- **`Resources.ResourceManager`** (static property)
Returns a cached `System.Resources.ResourceManager` instance initialized for the `"DatabaseInitializationScripts.Properties.Resources"` base name. Used internally for localized resource lookups.
- **`Resources.Culture`** (static property)
Gets or sets the `CultureInfo` used for resource lookups. Allows overriding the current UI culture for localization.
#### `AssemblyInfo` (via assembly attributes)
No runtime types are defined here; attributes are applied at assembly level:
- `AssemblyTitle("DatabaseInitializationScripts")`
- `AssemblyVersion("1.0.0.0")`
- `AssemblyFileVersion("1.0.0.0")`
- `ComVisible(false)`
- `ThemeInfo(ResourceDictionaryLocation.None, ResourceDictionaryLocation.SourceAssembly)`
---
### 3. **Invariants**
- The `Settings` class is implemented as a singleton with thread-safe access via `Synchronized`.
- Resource lookups use the fully qualified resource name `"DatabaseInitializationScripts.Properties.Resources"` (hardcoded in `Resources.ResourceManager`).
- The assembly is marked `ComVisible(false)`, meaning it is not intended for COM interop.
- The `ThemeInfo` attribute indicates the assembly does not ship theme-specific resources (`ResourceDictionaryLocation.None`) and expects generic resources in the main assembly (`SourceAssembly`).
- All generated files include explicit warnings that manual edits will be lost on regeneration.
---
### 4. **Dependencies**
#### Dependencies *of* this module:
- `System.Configuration` (for `ApplicationSettingsBase`)
- `System.Resources` / `System.Globalization` (for `ResourceManager`, `CultureInfo`)
- `System.Windows` (for `ThemeInfo` attribute usage, though no WPF UI is present in this module)
#### Dependencies *on* this module:
- The parent project `DatabaseInitializationScripts` (inferred from namespace and assembly name) likely consumes `Settings.Default` and `Resources` for configuration and localization, though no such usage is visible in the provided files.
#### External tooling:
- Generated by Visual Studios `SettingsDesigner` and `StronglyTypedResourceBuilder` (versions 17.12.0.0 and 17.0.0.0 respectively).
- Requires project-level `.settings` and `.resx` files (not provided) to generate content.
---
### 5. **Gotchas**
- **No user-defined settings or resources are present in the source.** The `Settings` class has no properties, and `Resources` has no strongly-typed properties for specific resources (e.g., `Resources.MyString`). This suggests either:
- The project has no localizable strings or configurable settings, *or*
- Such resources/settings exist in `.resx`/`.settings` files but have not been compiled into these designer files yet.
- **Auto-generated warning is critical:** Manual edits to `Settings.Designer.cs` or `Resources.Designer.cs` will be overwritten on build.
- **Thread-safety is superficial:** `Settings.Default` uses `Synchronized`, but since no settings are defined, thread-safety is irrelevant.
- **`ThemeInfo` is misleading:** The presence of `ThemeInfo` (a WPF attribute) in a module with no UI code may indicate legacy scaffolding or project template inheritance. No WPF resources are referenced here.
- **Version is fixed at `1.0.0.0`:** Both `AssemblyVersion` and `AssemblyFileVersion` are hardcoded and unchanging.
None identified beyond the above.

View File

@@ -0,0 +1,58 @@
---
source_files:
- DataPRO/Modules/Database/DatabaseMigrationScripts/EmbeddedResource.cs
generated_at: "2026-04-16T04:34:42.810625+00:00"
model: "Qwen/Qwen3-Coder-Next-FP8"
schema_version: 1
sha256: "ab2d5b23dd090ece"
---
# DatabaseMigrationScripts
### **Purpose**
This module provides utilities for reading embedded resources (e.g., SQL migration scripts) from a .NET assemblys manifest resources. It exists to simplify access to versioned, compiled-in migration files without requiring external file system dependencies, enabling reliable deployment of database schema changes across environments.
---
### **Public Interface**
- **`static StreamReader GetStream(Assembly assembly, string name)`**
Searches the manifest resources of the given `assembly` for a resource whose name *ends with* `name` (case-sensitive substring match), and returns a `StreamReader` for the first match. Returns `null` if no matching resource is found.
*Note: Caller is responsible for disposing the `StreamReader`.*
- **`static string GetString(Assembly assembly, string name)`**
Reads the full content of the resource matching `name` (via `GetStream`) from the specified `assembly` and returns it as a `string`. Closes the `StreamReader` internally. Returns `null` if no matching resource is found.
- **`static string GetString(string name)`**
Overload of `GetString` that uses the assembly containing the `EmbeddedResource` type itself (`typeof(EmbeddedResource).Assembly`) as the source. Behaves identically to `GetString(assembly, name)` otherwise.
---
### **Invariants**
- Resource matching is performed via `EndsWith(name)` on the full manifest resource name (e.g., `"MyApp.Migrations.V1_0_0.sql"` matches for `name = "V1_0_0.sql"`).
- Only the *first* matching resource (by enumeration order) is used—no error is raised if multiple resources match.
- `GetString(Assembly, string)` and `GetString(string)` return `null` if no matching resource exists (not an exception).
- The `StreamReader` returned by `GetStream` must be explicitly closed/disposed by the caller to avoid resource leaks.
- `GetString` methods assume the resource content is text-encoded (UTF-8 or system default encoding, per `StreamReader` default behavior).
---
### **Dependencies**
- **Depends on**:
- `System.IO` (`StreamReader`, `Stream`)
- `System.Reflection.Assembly` (for `GetManifestResourceNames`, `GetManifestResourceStream`)
- **Depended on by**:
- Presumably database migration orchestration logic (e.g., a `MigrationRunner` class) that loads `.sql` files from embedded resources.
- *Inferred*: Other types in the `DatabaseMigrationScripts` namespace (not visible here) likely consume `EmbeddedResource` to retrieve migration scripts.
---
### **Gotchas**
- **Substring matching is ambiguous**: A request for `"V1.sql"` could match `"V1.sql"`, `"Old/V1.sql"`, or `"Backup_V1.sql"`—only the first match in `GetManifestResourceNames()` order is used. This may cause unexpected behavior if resource naming is not strictly controlled.
- **No encoding specification**: `StreamReader` uses default encoding (typically UTF-8 without BOM on .NET Core/.NET 5+, but system default on .NET Framework), which may cause issues if migration files contain non-ASCII characters and were authored with a different encoding.
- **Resource enumeration order is undefined**: `GetManifestResourceNames()` does not guarantee consistent ordering across builds or platforms, so multiple matching resources may yield non-deterministic results.
- **No validation of resource existence before `ReadToEnd()`**: If `GetStream` returns `null`, `GetString` will throw a `NullReferenceException` when calling `sr.ReadToEnd()`. *This is a critical bug*: `GetString(Assembly, string)` lacks null-checking on `sr`.
- **`EmbeddedResource()` constructor is private but unused**: The class is never instantiated (all members are static), but the empty constructor serves no functional purpose.
- **No support for binary resources**: Designed exclusively for text-based resources; binary files would require a different approach.
*Note: The `NullReferenceException` risk in `GetString(Assembly, string)` when `GetStream` returns `null` is a likely source of runtime failures and should be addressed.*

View File

@@ -0,0 +1,40 @@
---
source_files:
- DataPRO/Modules/Database/DatabaseMigrationScripts/Properties/AssemblyInfo.cs
generated_at: "2026-04-16T04:35:19.675266+00:00"
model: "Qwen/Qwen3-Coder-Next-FP8"
schema_version: 1
sha256: "9006601d5721f158"
---
# Properties
## 1. Purpose
This module is an assembly containing metadata for the `DatabaseMigrationScripts` component of the DataPRO system. It does not contain executable logic or migration scripts themselves; rather, it defines assembly-level attributes (e.g., title, version, COM visibility) used by the .NET runtime and build/deployment tooling to identify and manage the assembly. Its role is to provide standard .NET assembly metadata, likely to support versioning, deployment, and integration with external tools (e.g., database migration runners or CI/CD pipelines) that rely on assembly identity.
## 2. Public Interface
**No public types, functions, classes, or methods are defined in this file.**
The file contains only assembly-level attributes via `System.Reflection` and `System.Runtime.InteropServices` attributes. It does not declare any classes, interfaces, structs, delegates, or methods.
## 3. Invariants
- The assembly identity is fixed at version `1.0.0.0` (both `AssemblyVersion` and `AssemblyFileVersion`), with no build/revision auto-increment.
- The assembly is **not visible to COM** (`ComVisible(false)`), meaning it cannot be consumed by COM clients unless explicitly overridden.
- The GUID `efab771c-7aa7-4715-8ac3-9a1b6194fcc2` is permanently assigned as the typelib ID for COM interop purposes (though irrelevant given `ComVisible(false)`).
- All assembly attributes are static and immutable at runtime.
## 4. Dependencies
- **Depends on**:
- `System.Runtime.InteropServices` (for `ComVisible`, `Guid`)
- `System.Reflection` (for `AssemblyTitle`, `AssemblyVersion`, etc.)
- **Depends on nothing else** (no custom or third-party imports).
- **Used by**:
- The .NET runtime (for reflection and identity resolution).
- Build/deployment tooling (e.g., MSBuild, NuGet, or custom migration orchestrators) that reads assembly metadata.
- Potentially other modules in the `DataPRO` solution that reference this assembly (e.g., a migration runner expecting metadata from `DatabaseMigrationScripts`), though this is not evident from the file alone.
## 5. Gotchas
- **No executable code**: This file is purely metadata; developers should not expect to find migration logic here. Actual migration scripts are likely in separate `.sql` files or code-based migration classes in other modules (e.g., `DatabaseMigrationScripts` project but outside this file).
- **Version stagnation**: The fixed version `1.0.0.0` may indicate legacy or manual versioning—developers should verify how versioning is managed across the broader migration system (e.g., via database schema version tables or external tooling).
- **COM irrelevance**: Despite the GUID and `ComVisible(false)`, the assembly is unlikely to be used for COM interop; the GUID may be vestigial or reserved for future use.
- **No documentation**: `AssemblyDescription` and `AssemblyProduct` are empty or generic; developers should consult external documentation for the purpose of this assembly.
- **None identified from source alone.**

View File

@@ -0,0 +1,183 @@
---
source_files:
- DataPRO/Modules/Database/DatabaseMigrator/MigrateDatabase.cs
- DataPRO/Modules/Database/DatabaseMigrator/MigrationForm.Designer.cs
- DataPRO/Modules/Database/DatabaseMigrator/MigrationForm.cs
generated_at: "2026-04-16T04:35:00.160493+00:00"
model: "Qwen/Qwen3-Coder-Next-FP8"
schema_version: 1
sha256: "ea93d67370ed0c49"
---
# DatabaseMigrator Module Documentation
## 1. Purpose
This module provides a Windows Forms-based utility for upgrading a local DataPRO database to a specified target version. It serves as a standalone migration tool that interacts with SQL Server Express LocalDB instances, validates the current database version, creates backups before migration, executes version-specific upgrade scripts via the `DbOperations.Connection.UpgradeVersionsIfNeeded` method, and handles error reporting and user interaction. It is intended for use during application upgrades where the embedded database schema has changed, ensuring safe and traceable schema evolution.
## 2. Public Interface
The module exposes only one public class: `MigrationForm`. All other types (`MigrateDatabase`, `DbOperations`, `MigrationResult`, etc.) are referenced but not defined in the provided source.
### `MigrationForm(string targetDir)`
**Namespace:** `DatabaseMigrator`
**Inherits:** `System.Windows.Forms.Form`
**Behavior:** Constructor that initializes the form UI and stores the `_targetDir` path (used to locate database files and configuration). It does not perform any migration logic itself.
### `MigrationForm.buttonOK_Click(object sender, EventArgs e)`
**Access:** `private` (event handler)
**Behavior:** Handles the OK button click. Performs the following sequence:
1. Queries the current database version via `GetDatabaseVersion(true)`.
2. Compares current version to `_desiredDatabaseVersion`.
3. If versions match or current > desired, shows a warning message.
4. If migration is needed:
- Calls `CopyLocalDB()` to create a backup.
- Invokes `DbOperations.Connection.UpgradeVersionsIfNeeded(...)` with hardcoded arguments (`"DataPRO"`, `"previousdir"`, `"targetdir"`, `"DataPRO.exe"`, `"applicationSettings"`).
- Displays success or failure via `MessageBox`.
5. Closes the form.
### `MigrationForm.buttonCancel_Click(object sender, EventArgs e)`
**Access:** `private` (event handler)
**Behavior:** Closes the form without performing any migration.
### `MigrationForm.GetDatabaseVersion(bool usingLocalDatabase)`
**Access:** `private`
**Behavior:** Determines the current database version by:
- Attempting to run the stored procedure `sp_DbVersionGet` (via `DbOperations.GetSQLCommand(true)`).
- Parsing the returned version numbers and returning the maximum.
- Falls back to returning `0` on failure (commented-out SQLite fallback logic is present but inactive).
- If `localSQLLocalDbDataExists` is true, calls `InstallDatabase()` first to set up the LocalDB instance.
### `MigrationForm.CopyLocalDB()`
**Access:** `private`
**Behavior:** Creates a timestamped backup of the `DataPRO.mdf` and `DataPRO_log.ldf` files in the `_targetDir`. It:
- Calls `ProcessSqlLocalDbCommand(...StopDataProInstance...)` to stop the LocalDB instance.
- Copies the `.mdf` and `.ldf` files to new filenames with suffix `_YYYY_MM_DD HH_MM`.
- Returns `true` if `.mdf` copy succeeds (`.ldf` copy is not checked for success).
### `MigrationForm.InstallDatabase()`
**Access:** `private`
**Behavior:** Sets up a fresh LocalDB instance named `(localdb)\DataPROInstance` by:
- Setting `DbOperations._usingMSSQL = true`, `_usingCentralizedDB = false`, `_usingNTLMAuthentication = true`.
- Executing a sequence of `sqllocaldb.exe` commands via `ProcessSqlLocalDbCommand(...)`:
- Stop instance
- Delete instance
- Create instance
- Start instance
- Attaching two databases (`DataPRO` and `ISO`) using `AttachDatabase(...)`, which internally calls `sqlcmd.exe` via a batch file.
### `MigrationForm.SetMigrationStatus(string migrationStatus)`
**Access:** `private`
**Behavior:** Updates the `MigrationStatusLabel` UI element with the given status string and forces a UI refresh.
### `MigrationForm.SetStatus(string status, bool output = false)`
**Access:** `private`
**Behavior:** Updates the `statusTextLabel` UI element with the given status string and forces a UI refresh. The `output` parameter is unused.
### `MigrationForm.numericUpDownDesiredVersion_ValueChanged(object sender, EventArgs e)`
**Access:** `private` (event handler)
**Behavior:** Updates `_desiredDatabaseVersion` to the current value of `numericUpDownDesiredVersion`.
### `MigrationForm.LocalDataExists()`
**Access:** `private`
**Behavior:** Checks for existence of database files in `_targetDir\LocalDb\`:
- First checks for `DataPRO.mdf` → sets `localSQLLocalDbDataExists = true`.
- Else checks for `DataPRO.db` (SQLite) → sets `localSQLiteDataExists = true`.
- Returns `true` if either exists.
### `MigrationForm.MigrationForm_Load(object sender, EventArgs e)`
**Access:** `private` (event handler)
**Behavior:** On form load:
- Sets `numericUpDownDesiredVersion` range to `[61, DbOperations.CURRENT_DB_VERSION]`.
- Sets initial value to `DbOperations.CURRENT_DB_VERSION`.
- Calls `LocalDataExists()` to detect existing database type.
- Populates `TbDatabasePath.Text` with the full path to `DataPRO.mdf` if LocalDB data exists.
### `MigrationForm.ConvertMigrationResultToSetting(MigrationResult result)`
**Access:** `private`
**Behavior:** Maps `MigrationResult` enum values to user-facing strings using `Settings.Default.*` resources. Currently only handles `WarningAllowStreamingModesWasNotMigrated`.
### `MigrationForm.ConvertResultAndDisplay(MigrationResult result)`
**Access:** `private`
**Behavior:** Calls `ConvertMigrationResultToSetting(...)` and displays the result in a `MessageBox`.
### `MigrationForm.ProcessSqlLocalDbCommand(string command)` *(static)*
**Access:** `private static`
**Behavior:** Executes a command string via `sqllocaldb.exe`:
- Locates the highest installed LocalDB version via registry (`HKLM\...\LocalDB\InstalledVersions`).
- Constructs full path to `SqlLocalDB.exe`.
- Invokes `SqlCommandProcessor(...)` to run the command and capture output.
### `MigrationForm.AttachDatabase(string targetDir, string dbName, string sqlDbFileName, string sqlLogFileName)` *(static)*
**Access:** `private static`
**Behavior:** Attaches a database using a batch file (`Settings.Default.AttachDBsbat`) via `BatchCommandProcessor(...)`. Uses `sqlcmd.exe` from ODBC tools path.
### `MigrationForm.GetSqlServerLocalDBPath()` *(static)*
**Access:** `private static`
**Behavior:** Reads the Windows registry to find the highest installed SQL Server LocalDB version and returns the path to its tools directory.
### `MigrationForm.OutputHandler(...)` *(static)*
**Access:** `private static`
**Behavior:** Appends asynchronous output from a `Process` to a static `StringBuilder` (`sb`).
### `MigrationForm.SqlCommandProcessor(...)` *(static)*
**Access:** `public static`
**Behavior:** Executes a command-line process (e.g., `sqllocaldb.exe` or batch file), captures output via `OutputHandler`, and returns accumulated output as a string.
### `MigrationForm.BatchCommandProcessor(...)` *(static)*
**Access:** `public static`
**Behavior:** Executes a batch file with arguments (e.g., database attach script), captures output, and returns accumulated output.
> **Note:** The following types are used but *not defined* in the provided source:
> - `DbOperations` (class with static `Connection`, `_usingCentralizedDB`, `_usingMSSQL`, `CURRENT_DB_VERSION`, `GetSQLCommand(...)`, `DbVersions`, `DbVersionFields`)
> - `DbOperationsEnum.StoredProcedure`
> - `MigrationResult` (enum with at least `OK`, `ExceptionThrown`, `WarningAllowStreamingModesWasNotMigrated`)
> - `Settings.Default` (properties: `LocalDbDataPROInstance`, `StopDataProInstance`, `DeleteDataProInstance`, `CreateDataProInstance`, `StartDataProInstance`, `LocalDbFolder`, `Mdf`, `LogLdf`, `DataPRO`, `ISO`, `AttachDBsbat`, `RegistrySoftwareMicrosoftMicrosoftSQLServerLocalDBInstalledVersions`, `InstanceAPIPath`, `SqlUserInstanceDll`, `LocalDB`, `Tools`, `SqlLocalDBExe`, `SqlServerLocalDbNotInstalled`, `SameVersionDatabase`, `CurrentVersionGreater`, `DatabaseMigrationSucceeded`, `DatabaseMigrationFailed`, `ActionRequired`, `Warning`, `WarningAllowStreamingModesWasNotMigrated`, `Db`)
> - `DTS.Common.Storage`, `DTS.Common.Enums`, `DTS.Common.Utils.Database` namespaces
## 3. Invariants
- `_desiredDatabaseVersion` is always set to the current value of `numericUpDownDesiredVersion` via the `ValueChanged` event handler.
- `numericUpDownDesiredVersion` is constrained to `[61, DbOperations.CURRENT_DB_VERSION]` at form load.
- Database backup is *always* attempted before migration (even if `CopyDatabaseFile` does not validate `.ldf` copy success).
- `GetDatabaseVersion` returns `0` if no version can be determined (e.g., stored procedure fails or no versions found).
- LocalDB instance setup (`InstallDatabase`) is only triggered if `localSQLLocalDbDataExists` is true *and* `GetDatabaseVersion` is called.
- `DbOperations.Connection.Server` is hardcoded to `Settings.Default.LocalDbDataPROInstance` in `InstallDatabase`.
- `DbOperations.Connection.DBName` is hardcoded to `"DataPRO"` in `GetDatabaseVersion`.
- `DbOperations.Connection.UpgradeVersionsIfNeeded(...)` is called with fixed string arguments: `"DataPRO"`, `"previousdir"`, `"targetdir"`, `"DataPRO.exe"`, `"applicationSettings"` — no dynamic configuration is used.
## 4. Dependencies
### External Dependencies (Inferred from Imports/Usings):
- `System.Windows.Forms` (UI framework)
- `System.Data.SqlClient` (SQL Server client)
- `System.Diagnostics` (process execution)
- `System.IO` (file operations)
- `Microsoft.Win32` (registry access)
- `DTS.Common.Storage` (likely contains `DbOperations` and related types)
- `DTS.Common.Enums` (likely contains `DbOperationsEnum.StoredProcedure`, `MigrationResult`, `STARTUP_ERRORS`)
- `DTS.Common.Utils.Database` (contains `GetODBCToolsPath(...)`)
### Internal Dependencies (Inferred from Usage):
- `DatabaseMigrator.Properties.Settings.Default` — provides configuration strings (e.g., instance names, file extensions, registry keys, messages).
- `DbOperations.Connection` — central database access object (must expose `Server`, `DBName`, `DbVersion`, `UpgradeVersionsIfNeeded(...)`, `GetSQLCommand(...)`, and static fields like `_usingMSSQL`, `_usingCentralizedDB`, `_usingNTLMAuthentication`).
- `DbOperationsEnum.StoredProcedure` — must include `sp_DbVersionGet`.
- `DbOperations.DbVersions` — must contain `DbVersionFields.Version`.
- `DTS.Common.Utils.Database.GetODBCToolsPath(...)` — returns path to `sqlcmd.exe`.
### What Depends on This Module:
- The main entry point (`MigrateDatabase.Main`) is invoked as a standalone executable (likely triggered by the main DataPRO installer or updater).
- No other modules in this codebase reference `MigrationForm` — it is self-contained.
## 5. Gotchas
- **Hardcoded Migration Arguments**: `DbOperations.Connection.UpgradeVersionsIfNeeded(...)` is called with fixed string parameters (`"previousdir"`, `"targetdir"`, etc.) that do not appear to be derived from user input or configuration. This may cause migration to fail if those strings are not meaningful to the underlying upgrade logic.
- **Silent `.ldf` Copy Failure**: `CopyDatabaseFile` copies the `.mdf` file first and returns `true` if that succeeds, but does *not* check success of the `.ldf` copy — potentially leaving the backup incomplete.
- **`GetDatabaseVersion` Ignores `usingLocalDatabase` Parameter**: The parameter is always `true` in practice (hardcoded in `buttonOK_Click` and `MigrationForm_Load`), and the `else` branch for centralized DB is commented out.
- **SQLite Support Inactive**: `localSQLiteDataExists` is set but never used — the SQLite fallback path in `GetDatabaseVersion` is commented out.
- **Registry Assumptions**: `GetSqlServerLocalDBPath` assumes LocalDB is installed in a specific registry path and uses hardcoded suffixes (`Settings.Default.LocalDB`, `SqlUserInstanceDll`, `InstanceAPIPath`, `Tools`). Failure to match these will cause `ProcessSqlLocalDbCommand` to fail.
- **No Validation of Desired Version**: User can select any version in the `NumericUpDown`, but `DbOperations.Connection.UpgradeVersionsIfNeeded(...)` may not support downgrades or arbitrary version jumps — behavior is unknown without its source.
- **UI Blocking**: All migration logic runs on the UI thread (synchronous `Process.WaitForExit()` calls), which may cause the form to freeze during long operations.
- **Hardcoded Database Names**: `"DataPRO"` and `"ISO"` are hardcoded in multiple places (`InstallDatabase`, `CopyLocalDB`, `LocalDataExists`). No support for custom database names.
- **`SetStatus` Parameter Unused**: The `output` parameter in `SetStatus(string status, bool output = false)` is never used.
- **`_testIDTimestamp` Format Ambiguity**: Backup filename timestamp uses space (`" {0:00}_{1:00}"`) which may cause issues on some filesystems (e.g., network shares with strict naming rules).

View File

@@ -0,0 +1,79 @@
---
source_files:
- DataPRO/Modules/Database/DatabaseMigrator/Properties/AssemblyInfo.cs
- DataPRO/Modules/Database/DatabaseMigrator/Properties/Settings.Designer.cs
generated_at: "2026-04-16T04:35:23.176246+00:00"
model: "Qwen/Qwen3-Coder-Next-FP8"
schema_version: 1
sha256: "044034bedb979c6c"
---
# Properties
## Documentation: DatabaseMigrator Module
### 1. Purpose
This module provides infrastructure and configuration for managing SQL Server LocalDB instance lifecycle and database schema migrations within the DataPRO system. It is responsible for defining application-scoped and user-scoped settings that control LocalDB operations (e.g., create/start/stop/delete instances), file naming conventions, registry paths, and user-facing messages (e.g., migration success/failure notifications). It does *not* contain migration logic itself (e.g., no migration scripts or versioning engine visible here), but supplies the configuration layer required by other components to orchestrate migrations and interact with LocalDB.
### 2. Public Interface
The only public surface exposed by this module is the auto-generated `Settings` class in the `DatabaseMigrator.Properties` namespace. All members are static properties accessed via `DatabaseMigrator.Properties.Settings.Default`.
| Property | Type | Scope | Default Value | Description |
|---------|------|-------|---------------|-------------|
| `LocalDbDataPROInstance` | `string` | Application-scoped | `"(localdb)\DataPROInstance"` | Name of the LocalDB instance used by DataPRO. |
| `StopDataProInstance` | `string` | Application-scoped | `"stop DataPROInstance"` | Command fragment used to stop the LocalDB instance (likely part of a larger command string). |
| `Warning` | `string` | Application-scoped | `"Warning"` | Literal string used in warning messages. |
| `DeleteDataProInstance` | `string` | Application-scoped | `"delete DataPROInstance"` | Command fragment used to delete the LocalDB instance. |
| `CreateDataProInstance` | `string` | Application-scoped | `"create DataPROInstance"` | Command fragment used to create the LocalDB instance. |
| `StartDataProInstance` | `string` | Application-scoped | `"start DataPROInstance"` | Command fragment used to start the LocalDB instance. |
| `LocalDbFolder` | `string` | Application-scoped | `"db"` | Default folder name for LocalDB database files (e.g., relative path). |
| `DataPRO` | `string` | Application-scoped | `"DataPRO"` | Product identifier string. |
| `ISO` | `string` | Application-scoped | `"ISO"` | Likely used for locale or collation settings. |
| `Mdf` | `string` | Application-scoped | `".mdf"` | File extension for primary database files. |
| `LogLdf` | `string` | Application-scoped | `"_log.ldf"` | Suffix for transaction log files. |
| `SqlServerLocalDbNotInstalled` | `string` | Application-scoped | `"SQL Server LocalDb is not installed."` | User-facing error message. |
| `SqlLocalDBExe` | `string` | Application-scoped | `"SqlLocalDB.exe"` | Executable name for the LocalDB CLI tool. |
| `ScriptsFolder` | `string` | Application-scoped | `"SQL Server Scripts"` | Folder name containing SQL scripts (e.g., migration scripts). |
| `AttachDBsbat` | `string` | Application-scoped | `"AttachDBs.bat"` | Batch file name used to attach databases. |
| `RegistrySoftwareMicrosoftMicrosoftSQLServerLocalDBInstalledVersions` | `string` | Application-scoped | `"SOFTWARE\\Microsoft\\Microsoft SQL Server Local DB\\Installed Versions"` | Registry path to check LocalDB installation status. |
| `InstanceAPIPath` | `string` | Application-scoped | `"InstanceAPIPath"` | Key name for registry value storing LocalDB instance path. |
| `SqlUserInstanceDll` | `string` | Application-scoped | `"SqlUserInstance.dll"` | Name of a LocalDB-related DLL (likely for user-instance support). |
| `LocalDB` | `string` | Application-scoped | `"LocalDB"` | Generic identifier for LocalDB. |
| `Tools` | `string` | Application-scoped | `"Tools"` | Folder name for tools (e.g., `SqlLocalDB.exe` location). |
| `Db` | `string` | Application-scoped | `".db"` | Alternative database file extension (possibly legacy). |
| `SameVersionDatabase` | `string` | Application-scoped | `"Database is already version {0} - no migration needed."` | Message template for no-op migration case. |
| `ActionRequired` | `string` | Application-scoped | `"Action required"` | Prefix for user prompts requiring manual intervention. |
| `CurrentVersionGreater` | `string` | Application-scoped | `"The current database version ({0}) is greater than what is requested. Downward migration is not available."` | Error message for downgrade attempt. |
| `DatabaseMigrationFailed` | `string` | Application-scoped | `"Database migration has failed.{0}Previous version of DataPRO must be used. Please contact DTS Support."` | Critical failure message. |
| `DatabaseMigrationSucceeded` | `string` | User-scoped | `"Database has been migrated from version {0} to {1}."` | Success message template (user-scoped, modifiable at runtime). |
| `WarningAllowStreamingModesWasNotMigrated` | `string` | User-scoped | `"Warning: The AllowStreaming config setting was not migrated and has been set to False.{0}{0}An \"Allow streaming modes\" checkbox is now in the \"Test setup settings\" step of the \"System Settings\" tab."` | Warning about legacy config migration gap (user-scoped). |
| `CreatingBackupDb` | `string` | User-scoped | `"Creating a backup database..."` | Status message during backup creation (user-scoped). |
### 3. Invariants
- All application-scoped settings are immutable at runtime (read-only; set only at compile-time via `DefaultSettingValueAttribute`).
- User-scoped settings (`DatabaseMigrationSucceeded`, `WarningAllowStreamingModesWasNotMigrated`, `CreatingBackupDb`) may be modified programmatically and persisted per-user.
- String values are used verbatim in command-line invocations (e.g., `SqlLocalDB.exe` commands), implying strict formatting expectations (e.g., instance names must match exactly).
- File extensions (`Mdf`, `LogLdf`, `Db`) are assumed to be consistent with SQL Server LocalDB conventions (`.mdf`, `_log.ldf`, `.db`).
- Registry path `RegistrySoftwareMicrosoftMicrosoftSQLServerLocalDBInstalledVersions` must exist and contain version keys for LocalDB detection to function.
### 4. Dependencies
**Depends on:**
- `System.Configuration` (for `ApplicationSettingsBase`, `ApplicationScopedSettingAttribute`, `UserScopedSettingAttribute`).
- `System.Runtime.CompilerServices` (for `CompilerGeneratedAttribute`).
- `System.CodeDom.Compiler` (for `GeneratedCodeAttribute`).
- `System.Diagnostics` (for `DebuggerNonUserCodeAttribute`).
- Implicitly depends on `SqlLocalDB.exe` being installed and accessible (via `Tools`/`SqlLocalDBExe` settings).
- Implicitly depends on SQL Server LocalDB runtime components (e.g., `SqlUserInstance.dll`).
**Depended on by:**
- Other modules in `DataPRO/Modules/Database/DatabaseMigrator` (e.g., migration orchestration logic, instance management classes) — not visible in this source but implied by module structure.
- Likely consumed by UI components (e.g., to display messages like `DatabaseMigrationFailed`, `WarningAllowStreamingModesWasNotMigrated`).
### 5. Gotchas
- **Hardcoded instance name**: The LocalDB instance name `DataPROInstance` is hardcoded in multiple settings (`LocalDbDataPROInstance`, `StopDataProInstance`, etc.). Renaming the instance requires coordinated changes across all related settings.
- **User-scoped settings are mutable**: Settings like `DatabaseMigrationSucceeded` can be altered at runtime and persisted, which may cause unexpected behavior if modified by users or other components.
- **Legacy config gap**: `WarningAllowStreamingModesWasNotMigrated` explicitly indicates a known migration gap for a deprecated setting (`AllowStreaming`), suggesting incomplete backward compatibility.
- **No versioning metadata**: This file contains no versioning information for migrations (e.g., no schema version constants or migration script ordering). Version tracking must be handled elsewhere.
- **Batch file assumption**: `AttachDBsbat` implies an external batch script (`AttachDBs.bat`) exists and is correctly structured; its absence or misconfiguration would cause failures.
- **Registry path format**: The registry path uses double backslashes (`\\`) in the source (as required for C# string literals), but this is correct for registry key paths. Ensure no accidental escaping errors in consuming code.
- **No public API beyond `Settings`**: This module exposes *only* configuration; actual migration logic resides in other files (not provided here). Do not assume migration behavior from this file alone.

View File

@@ -0,0 +1,119 @@
---
source_files:
- DataPRO/Modules/Database/DatabaseServices/DatabaseServicesModule.cs
generated_at: "2026-04-16T04:34:59.163908+00:00"
model: "Qwen/Qwen3-Coder-Next-FP8"
schema_version: 1
sha256: "674f1fac51c6e6cb"
---
# DatabaseServices
## Documentation: `DatabaseServicesModule`
---
### **1. Purpose**
The `DatabaseServicesModule` is a Prism module responsible for registering core database-related UI components (views and view models) into the Unity dependency injection container during application startup. It enables modular composition of the database services feature set within the larger application architecture, specifically integrating with Prisms module loading mechanism and Unity for dependency resolution. It also contributes metadata (name, image, group, region) to the main UI for discoverability and placement of database-related components.
---
### **2. Public Interface**
#### **`DatabaseServicesModule` class**
- **`public DatabaseServicesModule(IUnityContainer unityContainer)`**
Constructor. Accepts a Unity container via dependency injection and stores it for later use in type registration.
- **`public void Initialize()`**
Registers the following view/view-model pairs as singleton mappings in the Unity container:
- `IDatabaseCopyView``DatabaseCopyView`
- `IDatabaseCopyViewModel``DatabaseCopyViewModel`
- `IDatabaseStatusBarView``DatabaseStatusBarView`
- `IDatabaseStatusBarViewModel``DatabaseStatusBarViewModel`
- `IDatabaseSwitchView``DatabaseSwitchView`
- `IDatabaseSwitchViewModel``DatabaseSwitchViewModel`
*Note:* This method is called both directly by Prisms `IModule.Initialize()` and indirectly via `RegisterTypes()`.
- **`public void OnInitialized(IContainerProvider containerProvider)`**
Currently empty; no logic implemented.
- **`public void RegisterTypes(IContainerRegistry containerRegistry)`**
Delegates to `Initialize()`. This is required by Prisms `IModule` interface (via `IContainerRegistry`), but the implementation ignores `containerRegistry` and uses the injected `_unityContainer` instead.
#### **`DatabaseServicesModuleNameAttribute` class**
- **`public override string AssemblyName { get; }`**
Returns `"DatabaseServices"` (value of `AssemblyNames.DatabaseServices.ToString()`).
- **`public override string GetAssemblyName()`**
Returns the same value as `AssemblyName`.
- **`public override Type GetAttributeType()`**
Returns `typeof(TextAttribute)`.
#### **`DatabaseServicesModuleImageAttribute` class**
- **`public override BitmapImage AssemblyImage { get; }`**
Loads and returns a `BitmapImage` by calling `AssemblyInfo.GetImage("DatabaseServices")`.
- **`public override string AssemblyName { get; }`**
Returns `"DatabaseServices"`.
- **`public override string AssemblyGroup { get; }`**
Returns `"Prepare"` (value of `eAssemblyGroups.Prepare.ToString()`).
- **`public override eAssemblyRegion AssemblyRegion { get; }`**
Returns `eAssemblyRegion.DatabaseServicesRegion`.
- **`public override string GetAssemblyName()`**
Returns `"DatabaseServices"`.
- **`public override string GetAssemblyGroup()`**
Returns `"Prepare"`.
- **`public override eAssemblyRegion GetAssemblyRegion()`**
Returns `eAssemblyRegion.DatabaseServicesRegion`.
- **`public override BitmapImage GetAssemblyImage()`**
Returns the value of `AssemblyImage`.
- **`public override Type GetAttributeType()`**
Returns `typeof(ImageAttribute)`.
---
### **3. Invariants**
- **Singleton Registration**: All view/view-model pairs registered in `Initialize()` are registered as singletons (default Unity behavior for `RegisterType<T, TImpl>()` without specifying `LifetimeManager`).
- **Assembly Name Consistency**: Both attributes (`DatabaseServicesModuleNameAttribute`, `DatabaseServicesModuleImageAttribute`) consistently use `"DatabaseServices"` as the assembly name (via `AssemblyNames.DatabaseServices`).
- **Group & Region Constraints**:
- `AssemblyGroup` is always `"Prepare"` (from `eAssemblyGroups.Prepare`).
- `AssemblyRegion` is always `eAssemblyRegion.DatabaseServicesRegion`.
- **Image Loading**: `AssemblyImage` is loaded exactly once per instance (cached in `_img`), using `AssemblyInfo.GetImage("DatabaseServices")`. No fallback or error handling is visible in the source.
---
### **4. Dependencies**
#### **Dependencies *of* this module:**
- **Prism.Modularity (`IModule`)**: Required for module discovery and initialization.
- **Unity (`IUnityContainer`, `IContainerProvider`, `IContainerRegistry`)**: Used for DI container registration.
- **DTS.Common (`AssemblyNames`, `eAssemblyGroups`, `eAssemblyRegion`, `AssemblyInfo`)**: Provides metadata constants and image-loading utilities.
- **System.ComponentModel.Composition (`Export`)**: Enables Prism to discover this module via MEF.
- **System.Windows.Media.Imaging (`BitmapImage`)**: Required for the image attribute.
#### **Dependencies *on* this module:**
- **Prism-based shell/application**: The main application must load this module (via Prism module catalog) to register the database services views/view-models.
- **UI regions**: The `DatabaseServicesRegion` (referenced in `AssemblyRegion`) must be defined elsewhere (e.g., in XAML or shell layout) for views to be injected into.
---
### **5. Gotchas**
- **Redundant `Initialize()` call**: `RegisterTypes()` calls `Initialize()`, but `Initialize()` is also called directly by Prism. This is safe (idempotent for registration), but indicates potential design redundancy or legacy code.
- **Ignored `containerRegistry`**: `RegisterTypes()` receives `IContainerRegistry containerRegistry` but ignores it in favor of the injected `_unityContainer`. This couples the module to Unity and may break if another DI container is used.
- **No error handling for image loading**: If `AssemblyInfo.GetImage("DatabaseServices")` fails (e.g., missing image resource), `_img` may be `null` with no visible fallback or logging.
- **Hardcoded string `"DatabaseServices"`**: Used in both attributes and `AssemblyInfo.GetImage()`. A typo or rename in `AssemblyNames.DatabaseServices` would cause runtime issues.
- **No `OnInitialized()` logic**: The `OnInitialized()` method is empty. If initialization order or cross-module coordination is needed, this is currently unsupported.
- **Attribute usage**: Both attributes are applied at the *assembly* level (via `[assembly: ...]`), meaning they are not tied to the `DatabaseServicesModule` class itself but to the entire assembly. This may cause confusion if multiple modules exist in the same assembly.
None identified beyond the above.

View File

@@ -0,0 +1,85 @@
---
source_files:
- DataPRO/Modules/Database/DatabaseServices/Converters/DbTypeToVisibilityConverter.cs
generated_at: "2026-04-16T04:35:48.144608+00:00"
model: "Qwen/Qwen3-Coder-Next-FP8"
schema_version: 1
sha256: "b05fe9322ad19457"
---
# Converters
### **DbTypeToVisibilityConverter.cs Documentation**
---
#### **1. Purpose**
This module provides a WPF `IMultiValueConverter` implementation (`DbTypeToVisibilityConverter`) used to dynamically control the visibility of UI elements (e.g., menu items, buttons, or status bar controls) in the `DatabaseStatusBarView`, based on the current database configuration and connection state. It translates the combination of a `DbType` value and the current view context into a `Visibility` enum (`Visible` or `Collapsed`), enabling UI elements to be conditionally shown only when relevant to the active database mode (e.g., remote-only, local-only, or hybrid with/without remote connection).
---
#### **2. Public Interface**
- **`DbTypeToVisibilityConverter`**
- *Implements*: `System.Windows.Data.IMultiValueConverter`
- *Namespace*: `DatabaseServices.Converters`
- *Inherits*: `object`
- **`object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)`**
- **Signature**: `public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)`
- **Behavior**: Converts a two-element input array (`values`) into a `Visibility` value:
- `values[0]`: An `int` representing a `DbType` enum value (cast to `DbType`).
- `values[1]`: A `DatabaseStatusBarView` instance (used to access its `DataContext`, expected to be a `DatabaseStatusBarViewModel`).
- Returns `Visibility.Visible` if the `dbType` matches the visibility rules for the current `vm.DatabaseType` and `vm.RemoteConnected` state; otherwise returns `Visibility.Collapsed`.
- If `view.DataContext` is `null`, returns `Visibility.Collapsed`.
- Throws no exceptions explicitly, but may throw `InvalidCastException` if inputs are not of expected types.
- **`object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)`**
- **Signature**: `public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)`
- **Behavior**: Always throws `NotImplementedException`. This converter is one-way only.
---
#### **3. Invariants**
- `values` array **must** contain exactly two elements:
- Element 0: An `int` that can be safely cast to `DbType`.
- Element 1: A `DatabaseStatusBarView` instance (non-null).
- `view.DataContext` **must** be non-null and assignable to `DatabaseStatusBarViewModel`; otherwise, the converter returns `Visibility.Collapsed`.
- Visibility logic is strictly governed by the `DatabaseStatusBarViewModel.DatabaseType` and `DatabaseStatusBarViewModel.RemoteConnected` properties:
- For `RemoteOnly`: Only `DbType.RemoteOnly` is visible.
- For `LocalOnly`: Only `DbType.LocalOnly` is visible.
- For `RemoteLocalHybrid`:
- If `RemoteConnected == true`: Only `DbType.RemoteOnly` is visible.
- If `RemoteConnected == false`: Only `DbType.RemoteLocalHybrid` is visible.
- Any other `DatabaseType` value results in `Visibility.Collapsed`.
- The converter is **not** intended for two-way binding (`ConvertBack` is unimplemented).
---
#### **4. Dependencies**
- **Imports/References**:
- `System`, `System.Globalization`, `System.Windows`, `System.Windows.Data` (WPF core)
- `DTS.Common.Enums.Database` (external library/namespace) — provides `DbType` and likely `DatabaseStatusBarView`/`DatabaseStatusBarViewModel`.
- **Assumed Dependencies (from usage context)**:
- `DatabaseStatusBarView`: A WPF `UserControl` or `Window` used in the status bar.
- `DatabaseStatusBarViewModel`: View model with properties:
- `DatabaseType` (`DbType`)
- `RemoteConnected` (`bool`)
- `DbType` enum (from `DTS.Common.Enums.Database`) — expected to include at least: `RemoteOnly`, `LocalOnly`, `RemoteLocalHybrid`.
- **Depended upon by**:
- XAML bindings in `DatabaseStatusBarView` (or related views) where `MultiBinding` is used with this converter to toggle visibility based on database type and connection state.
---
#### **5. Gotchas**
- **Type safety**: Assumes `values[0]` is an `int` that maps to a valid `DbType` enum value. Passing a non-integer or out-of-range value may cause `InvalidCastException` at runtime.
- **Null safety**: Relies on `view.DataContext` being non-null; otherwise, silently returns `Collapsed`. No logging or error handling is present.
- **Hybrid mode logic is conditional**: In `RemoteLocalHybrid` mode, visibility depends on `RemoteConnected`, but the converter does **not** handle cases where `RemoteConnected` is `false` and `dbType == DbType.RemoteOnly` — such cases correctly collapse, but this may be counterintuitive if the UI expects hybrid elements to always show.
- **No support for `parameter`**: The `parameter` argument (often used to customize converter behavior in XAML) is ignored.
- **One-way only**: `ConvertBack` throws `NotImplementedException`, so this converter cannot be used in two-way bindings.
- **No validation of `DbType` values**: Unknown `DbType` values (e.g., future enum additions) fall through to `default: return Visibility.Collapsed`, which may hide UI elements unexpectedly.
None identified beyond these.

View File

@@ -0,0 +1,62 @@
---
source_files:
- DataPRO/Modules/Database/DatabaseServices/Properties/Settings.Designer.cs
- DataPRO/Modules/Database/DatabaseServices/Properties/AssemblyInfo.cs
generated_at: "2026-04-16T04:35:58.384112+00:00"
model: "Qwen/Qwen3-Coder-Next-FP8"
schema_version: 1
sha256: "a47b7825dcdbbbb0"
---
# Properties
## Documentation Page: `DatabaseServices.Properties.Settings`
---
### 1. **Purpose**
This module defines the auto-generated settings class `Settings` for the `DatabaseServices` assembly. It provides a strongly-typed, thread-safe accessor (`Default`) to application-level configuration settings stored in the standard .NET configuration system (e.g., `app.config` or `web.config`). Its role is to abstract access to persisted settings values, enabling type-safe retrieval without manual parsing or casting. It does *not* define any settings itself—only the infrastructure to access them—meaning actual settings keys and values must be defined elsewhere (e.g., via Visual Studios Settings designer or `app.config`).
---
### 2. **Public Interface**
The module exposes a single internal, auto-generated class:
- **`class Settings : ApplicationSettingsBase`**
- **`public static Settings Default { get; }`**
Returns the singleton instance of `Settings`, synchronized for thread safety via `ApplicationSettingsBase.Synchronized`. This is the *only* public member exposed.
> ⚠️ **Note**: The class is `internal`, so `Default` is only accessible within the `DatabaseServices` assembly. External consumers cannot directly reference this class.
---
### 3. **Invariants**
- The `Default` property always returns a non-null reference (initialized lazily and synchronized).
- The class is `sealed` and `partial`, indicating it is not designed for inheritance or manual extension.
- Thread-safety is guaranteed *only for the `Default` accessor* (via `Synchronized`), but not necessarily for individual property accesses on the returned instance (e.g., `Settings.Default.MySetting` is not inherently thread-safe beyond the initial retrieval of `Default`).
- Settings values themselves are not validated or constrained by this class—validation (if any) occurs at the configuration layer or in consuming code.
---
### 4. **Dependencies**
- **Depends on**:
- `System.Configuration` (specifically `ApplicationSettingsBase`, `CompilerGeneratedAttribute`, `GeneratedCodeAttribute`).
- `System.Runtime.CompilerServices` (for `CompilerGeneratedAttribute`).
- **Depended upon by**:
- Other classes in the `DatabaseServices` assembly (e.g., data access layers) that require configuration values (e.g., connection strings, timeouts).
- *Not* exposed to external assemblies due to `internal` visibility.
- **Assembly metadata** (from `AssemblyInfo.cs`):
- Assembly name: `DatabaseServices`
- GUID: `f1a366bc-6128-4c10-be7f-f62628895d8f`
- Version: `1.0.0.0`
- `ComVisible(false)` → not exposed to COM.
---
### 5. **Gotchas**
- **No settings defined here**: This file *only* scaffolds the settings infrastructure. Actual settings (e.g., `ConnectionString`, `CommandTimeout`) must be defined in `Settings.settings` (designer) or `app.config`. If these are missing, accessing `Settings.Default` will succeed, but property access (e.g., `Settings.Default.MyProp`) will throw a `ConfigurationErrorsException` at runtime.
- **Auto-generated**: Manual edits will be overwritten on rebuild (per the `auto-generated` header).
- **Internal visibility**: External consumers cannot use `Settings.Default` directly. They must rely on `DatabaseServices` to expose settings via its public API (e.g., a wrapper method).
- **Thread-safety nuance**: While `Default` is thread-safe, *reading/writing settings values* from multiple threads may require additional synchronization if mutable settings are used (though `ApplicationSettingsBase` typically treats settings as read-only after initialization).
- **No documentation comments**: The class lacks XML documentation, making it harder to infer intended usage without external context.
None identified beyond these.

View File

@@ -0,0 +1,52 @@
---
source_files:
- DataPRO/Modules/Database/DatabaseServices/Resources/TranslateExtension.cs
- DataPRO/Modules/Database/DatabaseServices/Resources/StringResources.Designer.cs
generated_at: "2026-04-16T04:35:33.501804+00:00"
model: "Qwen/Qwen3-Coder-Next-FP8"
schema_version: 1
sha256: "79b93425a9c97e71"
---
# Resources
## Documentation: `TranslateExtension` Markup Extension
### 1. Purpose
The `TranslateExtension` class is a WPF `MarkupExtension` that enables declarative localization of UI text directly in XAML. It resolves string resources by key at runtime using the `StringResources` strongly-typed resource class, returning localized strings or a standardized fallback for missing keys. This module exists to support multi-language UIs in the DatabaseServices module by abstracting resource lookup into a XAML-friendly syntax (e.g., `{local:Translate KeyName}`), decoupling UI text from code and enabling runtime culture switching.
### 2. Public Interface
- **`TranslateExtension(string key)`**
Constructor. Accepts a resource key (e.g., `"ClearingLocalDb"`) to look up. Throws no exceptions on invalid input—invalid keys are handled at lookup time.
- **`override object ProvideValue(IServiceProvider serviceProvider)`**
WPF framework method invoked during XAML parsing. Returns the localized string corresponding to `_key`, or a fallback value if the key is missing/empty.
- If `_key` is `null` or empty: returns `"#stringnotfound#"`.
- If `StringResources.ResourceManager.GetString(_key)` returns `null`: returns `"#stringnotfound# " + _key`.
- Otherwise: returns the localized string.
### 3. Invariants
- `_key` is immutable after construction (stored in a `readonly` field).
- The returned value is always a `string` (per `[MarkupExtensionReturnType(typeof(string))]`).
- No exceptions are thrown during `ProvideValue`—all error cases return a fallback string.
- Resource lookup uses the current UI culture (via `StringResources.Culture`), which may be set externally (e.g., by WPFs `FrameworkElement.Language` or manual assignment).
- The `StringResources` class is auto-generated and must be kept in sync with `.resx` files; changes to `.resx` require regeneration.
### 4. Dependencies
- **Depends on**:
- `System.Windows.Markup` (for `MarkupExtension` and `MarkupExtensionReturnType`).
- `DatabaseServices.Resources.StringResources` (strongly-typed resource class).
- `System.Resources.ResourceManager` (via `StringResources.ResourceManager`).
- **Used by**:
- XAML files in the `DatabaseServices` module (e.g., `Window.xaml`, `UserControl.xaml`) to bind localized text to UI elements.
- No direct programmatic callers in the provided source—usage is exclusively via XAML markup.
### 5. Gotchas
- **Hardcoded fallback prefix**: The `"#stringnotfound#"` string is hardcoded; changing it requires updating both `TranslateExtension` and any tests/scripts expecting this pattern.
- **No caching of lookups**: `ResourceManager.GetString(_key)` is called on every `ProvideValue` invocation. While `ResourceManager` caches internally, repeated lookups for the same key in high-frequency UI scenarios (e.g., data-bound lists) may incur overhead.
- **Silent failure on missing keys**: Missing keys produce visible text like `"#stringnotfound# ClearingLocalDb"` in the UI, which may confuse end users. No logging or telemetry is performed.
- **No null-safety for `serviceProvider`**: The `serviceProvider` parameter is unused, but if future changes require it (e.g., for service resolution), this could break.
- **Auto-generated resource class**: `StringResources.Designer.cs` is auto-generated—manual edits are unsafe and will be overwritten. Resource keys must match exactly (case-sensitive) with entries in the `.resx` file.
- **No support for pluralization/formatting**: The extension only supports simple key→string lookups; composite strings (e.g., `"Connected to: {0}"`) require manual formatting in code-behind or XAML.
None identified beyond these.

View File

@@ -0,0 +1,52 @@
---
source_files:
- DataPRO/Modules/Database/DatabaseServices/View/DatabaseStatusBarView.xaml.cs
- DataPRO/Modules/Database/DatabaseServices/View/DatabaseCopyView.xaml.cs
- DataPRO/Modules/Database/DatabaseServices/View/DatabaseSwitchView.xaml.cs
generated_at: "2026-04-16T04:36:08.419533+00:00"
model: "Qwen/Qwen3-Coder-Next-FP8"
schema_version: 1
sha256: "0a8da82e58412ddf"
---
# View
## Documentation: Database UI Views Module
### 1. Purpose
This module contains WPF view classes that implement the user interface layer for database-related operations—specifically, displaying status information, copying databases, and switching between local and remote database contexts. It serves as the presentation layer for database service functionality, adhering to the MVVM pattern by delegating business logic to corresponding view models (`IDatabaseCopyViewModel`, `IDatabaseSwitchViewModel`, `IDatabaseStatusBarView`). The views are thin wrappers that wire UI events (e.g., button clicks) to view model methods, and they rely on WPFs data binding and command infrastructure.
### 2. Public Interface
| Type | Signature | Behavior |
|------|-----------|----------|
| `DatabaseStatusBarView` | `public partial class DatabaseStatusBarView : IDatabaseStatusBarView` | WPF `UserControl` (inferred from `InitializeComponent()`) implementing `IDatabaseStatusBarView`. Provides UI for displaying database status (e.g., connection state, server info). No additional logic beyond initialization. |
| `DatabaseCopyView` | `public partial class DatabaseCopyView : IDatabaseCopyView` | WPF `UserControl` implementing `IDatabaseCopyView`. Contains a copy operation button. On click, casts `DataContext` to `IDatabaseCopyViewModel` and invokes `CopyDatabase()`. |
| `DatabaseSwitchView` | `public partial class DatabaseSwitchView : IDatabaseSwitchView` | WPF `UserControl` implementing `IDatabaseSwitchView`. Contains two buttons: `SwitchToLocal` and `SwitchToRemote`. On click, casts `DataContext` to `IDatabaseSwitchViewModel` and invokes `SwitchLocal()` or `SwitchRemote()` respectively. |
> **Note**: All classes are `partial`, indicating they are tied to corresponding `.xaml` files (e.g., `DatabaseStatusBarView.xaml`). Constructor calls `InitializeComponent()` to load XAML and wire UI elements.
### 3. Invariants
- **View-ViewModel Contract**: Each view expects its `DataContext` to be an instance of the corresponding view model interface (`IDatabaseStatusBarView` has no explicit contract beyond inheritance; `DatabaseCopyView` and `DatabaseSwitchView` require `IDatabaseCopyViewModel` and `IDatabaseSwitchViewModel` respectively).
- **UI Thread Execution**: Event handlers (`Copy_Click`, `SwitchToLocal_Click`, `SwitchToRemote_Click`) assume execution on the UI thread (standard for WPF event handlers), and view model methods (`CopyDatabase`, `SwitchLocal`, `SwitchRemote`) are invoked synchronously on this thread.
- **Null Safety**: No null checks are present in handlers; assumes `sender` is always a `Control` and `DataContext` is always the expected view model type. Failure to satisfy this will cause runtime exceptions (e.g., `InvalidCastException`, `NullReferenceException`).
### 4. Dependencies
- **External Interfaces**:
- `DTS.Common.Interface.Database.IDatabaseStatusBarView`
- `DTS.Common.Interface.Database.IDatabaseCopyView`
- `DTS.Common.Interface.Database.IDatabaseSwitchView`
- `DTS.Common.Interface.Database.IDatabaseCopyViewModel` (used in `DatabaseCopyView`)
- `DTS.Common.Interface.Database.IDatabaseSwitchViewModel` (used in `DatabaseSwitchView`)
- **WPF Framework**: `System.Windows`, `System.Windows.Controls`, `System.Windows.RoutedEventArgs`.
- **Dependents**: Likely consumed by a module or shell that registers these views with a DI container or view locator (e.g., Caliburn.Micro, Prism), though this is not explicit in the source.
- **No internal dependencies**: No references to other modules beyond the `DTS.Common.Interface.Database` interface layer.
### 5. Gotchas
- **No Error Handling**: Event handlers perform direct casts without validation. If `DataContext` is misconfigured (e.g., wrong view model type or `null`), a runtime exception will occur.
- **Tight Coupling to View Models**: Views assume specific method names (`CopyDatabase`, `SwitchLocal`, `SwitchRemote`) exist on the view model interface. Changes to these interfaces require synchronized updates.
- **No Command Binding**: Uses event handlers instead of `ICommand` bindings (e.g., `Button.Command`), which is less idiomatic in MVVM and reduces testability (e.g., cannot easily unit test button logic without UI interaction).
- **Namespace Quirk**: `// ReSharper disable CheckNamespace` suggests the namespace is intentionally `DatabaseServices` (not nested under `DataPRO.Modules.Database...`), possibly for legacy or build-system reasons.
- **Missing Implementation Details**: Source provides no insight into what `IDatabaseStatusBarView` actually exposes (e.g., properties, events), as the interface is only inherited—not implemented or used directly in logic.
None identified beyond the above.

View File

@@ -0,0 +1,206 @@
---
source_files:
- DataPRO/Modules/Database/DatabaseServices/ViewModel/DatabaseStatusBarViewModel.cs
- DataPRO/Modules/Database/DatabaseServices/ViewModel/DatabaseSwitchViewModel.cs
- DataPRO/Modules/Database/DatabaseServices/ViewModel/DatabaseCopyViewModel.cs
generated_at: "2026-04-16T04:35:56.029845+00:00"
model: "Qwen/Qwen3-Coder-Next-FP8"
schema_version: 1
sha256: "f187d4b018ffae25"
---
# Database Services ViewModels Documentation
## 1. Purpose
This module provides UI-facing view models (`DatabaseStatusBarViewModel`, `DatabaseSwitchViewModel`, and `DatabaseCopyViewModel`) that manage database connection state, user interaction for database switching/copying, and status reporting in the DataPRO application. These view models coordinate database operations (local vs. remote), handle UI state (busy indicators, progress bars, notifications), and integrate with Prisms event aggregation and Unity DI container for decoupled communication with other system components. They serve as the bridge between low-level database operations (e.g., `DbOperations`, `DatabaseServices`) and the WPF UI layer.
---
## 2. Public Interface
### `DatabaseStatusBarViewModel`
- **`string ActiveDbName { get; }`**
Returns a string representing the active database: `"Local"` for `DbType.LocalOnly`, `ServerName` for `DbType.RemoteOnly`, or `ServerName`/`"Local"` conditionally for `DbType.RemoteLocalHybrid`.
- **`Brush BackgroundBrush { get; }`**
Returns `Brushes.Red` when `DatabaseType == DbType.RemoteLocalHybrid` and `RemoteConnected == false`; otherwise `Brushes.Transparent`.
- **`bool RemoteConnected { get; }`**
Returns the value of `DbOperations._usingCentralizedDB`.
- **`string ServerName { get; private set; }`**
Holds the remote server name; updated via `InitializeValues` or `OnDbEvent`.
- **`void InitializeValues(DbType dbType, string serverName, bool remoteConnected)`**
Sets `DatabaseType`, `ServerName`, and triggers property change notifications for `ActiveDbName` and `BackgroundBrush`.
- **`void OnDbEvent(DbStatusArg args)`**
Internal event handler for `DbStatusEvent`; updates `ServerName` and notifies changes to `ActiveDbName`/`BackgroundBrush` when `args.Status == LegacyStatus`.
- **`bool IsBusy { get; set; }`**
Binds to UI busy indicator; updated via `OnBusyIndicatorNotification`.
- **`bool IsMenuIncluded`, `bool IsNavigationIncluded`**
UI state flags for menu/navigation visibility; support INotifyPropertyChanged.
- **`InteractionRequest<Notification> NotificationRequest { get; }`**
Prism interaction request used to show notification popups.
- **`InteractionRequest<Confirmation> ConfirmationRequest { get; }`**
Prism interaction request used to show confirmation dialogs.
- **`IDatabaseStatusBarView View { get; set; }`**
Reference to the associated view; `View.DataContext` is set to `this` in constructor.
- **Constructors**
- `DatabaseStatusBarViewModel(IDatabaseStatusBarView view, IRegionManager regionManager, IEventAggregator eventAggregator, IUnityContainer unityContainer)`
Registers event subscriptions for `RaiseNotification`, `BusyIndicatorChangeNotification`, and `DbStatusEvent`.
- `DatabaseStatusBarViewModel()`
Parameterless constructor (used for design-time or manual instantiation).
- **Lifecycle methods (no-op)**
`Unset()`, `Cleanup()`, `CleanupAsync()`, `Initialize()`, `Initialize(object)`, `Initialize(object, object)`, `InitializeAsync()`, `InitializeAsync(object)`, `Activated()` — all currently empty.
### `DatabaseSwitchViewModel`
- **`bool RemoteIsActive { get; }`**
Returns `DbOperations._usingCentralizedDB`.
- **`void SwitchRemote()`**
Attempts to switch to remote database:
1. Publishes `AppStatusArg.Busy`.
2. Calls `DatabaseServices.SetupForRemoteDb(...)` with stored credentials.
3. Validates connection via `SimpleDbTest()`.
4. On failure: publishes `DbStatusEvent` with `FailedToConnectToRemote`, calls `SwitchLocal()`, logs exception.
5. On success: publishes `DbStatusEvent.LegacyStatus`, `AppStatusArg.Available`, and `LogoutUserEvent` (reason: `DatabaseSwitch`).
- **`void SwitchLocal()`**
Switches to local database:
1. Checks local DB files exist via `CheckLocalDatabaseFilesExist(...)`.
2. Publishes `AppStatusArg.Busy`.
3. Calls `DatabaseServices.SetupLocal(...)`.
4. Publishes `DbStatusEvent.LegacyStatus`, `AppStatusArg.Available`, and `LogoutUserEvent`.
- **`void InitializeDbSettings(string defaultDbName, string dbHost, bool ntlmAuthentication, string dbUser, string dbPassword)`**
Stores connection settings for later use in `SwitchRemote()`.
- **Properties**: `DefaultDbName`, `DbHost`, `NTLMAuthentication`, `DbUser`, `DbPassword` (all `private set`).
- **`bool IsBusy`, `IsMenuIncluded`, `IsNavigationIncluded`**
Same semantics as `DatabaseStatusBarViewModel`.
- **Constructors & Lifecycle methods**
Same as `DatabaseStatusBarViewModel`; constructor subscribes to `RaiseNotification` and `BusyIndicatorChangeNotification`.
### `DatabaseCopyViewModel`
- **`bool CopyEnabled { get; }`**
Returns `true` only if `DatabaseType == DbType.RemoteLocalHybrid` and `DbOperations._usingCentralizedDB == true`.
- **`void CopyDatabase()`**
Triggers `CopyFunc()` on a background task (`Task.Run`). Publishes `AppStatusArg.Busy` before and `AppStatusArg.Available` after.
- **`void InitializeState(DbType dbType, string dbName)`**
Sets `DatabaseType` and `DbName`, publishes initial `ProgressBarEvent` for both progress bars (collapsed), and notifies `CopyEnabled`.
- **`string DbName { get; private set; }`**
Name of the database being copied.
- **`bool IsCopyVisible { get; set; }`**
Controls visibility of the copy UI section.
- **`IStatusAndProgressBarView OverallProgressBarView`, `IStatusAndProgressBarView CurrentTaskProgressBarView`**
References to progress bar views resolved during `InitializeAsync()`.
- **`Task InitializeAsync()`**
Resolves and configures two `IStatusAndProgressBarView` instances:
- One for `OverallTaskBar` (named `"OverallStatus"`).
- One for `CurrentTaskBar` (named `"CurrentTaskStatus"`).
Each is bound to a shared `IStatusAndProgressBarViewModel` instance.
- **`void OnRaiseNotification(NotificationContentEventArgs)`**
Wraps event args into `Notification` and raises `NotificationRequest`.
- **`void OnBusyIndicatorNotification(bool)`**
Sets `IsBusy`.
- **`bool IsBusy`, `IsMenuIncluded`, `IsNavigationIncluded`, `IsDirty`**
Same semantics as above.
- **Internal helper methods (private)**
- `CopyFunc()`: Main copy logic:
1. Backs up local DB.
2. Disables constraints.
3. Copies all tables in `_allDBTables` via `CopyRemoteTable(...)`.
4. Fixes `Channels.DASId = 0 → NULL`.
5. Re-enables constraints.
6. Restores local DB on failure.
7. Publishes progress via `ProgressBarEvent`.
- `CopyRemoteTable(string tableName, bool bIndentityTable)`: Fetches all rows from remote DB, stores in memory.
- `InsertIntoLocalTable(...)`: Inserts rows in batches (max 20 rows/batch to avoid SQL parameter limit), handles `IDENTITY_INSERT` for tables in `_tablesWithIdentities`.
- `SetStatus(string bar, double percentage, string text)`: Publishes `ProgressBarEvent`.
- **Constants & Data**
- `MAX_BATCH_SIZE = 20`
- `_allDBTables`: List of 72 table names (includes duplicates like `"tblDataPRODbVersion"` and `"DataPRODbVersion"`).
- `_tablesWithIdentities`: HashSet of 58 table names requiring `IDENTITY_INSERT ON/OFF`.
---
## 3. Invariants
- **`RemoteConnected` is derived solely from `DbOperations._usingCentralizedDB`** — no local state overrides it.
- **`ActiveDbName` and `BackgroundBrush` depend on `DatabaseType` and `RemoteConnected`** — their values are recalculated only when `DatabaseType` or `ServerName` changes (via `InitializeValues` or `OnDbEvent`).
- **Progress bars are always reset to collapsed/zero on completion/failure** — `CopyFunc()` publishes `ProgressBarEvent` with `Visibility.Collapsed` in `finally`.
- **`CopyDatabase()` runs asynchronously** — `Task.Run` is used explicitly; no `async/await` is used internally.
- **`DatabaseCopyViewModel` requires `InitializeAsync()` to be called before `CopyDatabase()`** — otherwise `OverallProgressBarView`/`CurrentTaskProgressBarView` remain `null`.
- **`DatabaseSwitchViewModel.SwitchRemote()` and `SwitchLocal()` always trigger `LogoutUserEvent`** — user session is invalidated after any database switch.
- **`DatabaseStatusBarViewModel.OnDbEvent(...)` only handles `LegacyStatus`** — other `DbStatusArg.EventTypes` are ignored.
---
## 4. Dependencies
### Internal Dependencies (from source):
- **`DTS.Common.*`**:
- `DTS.Common.Enums.Database.DbType`
- `DTS.Common.Events.*` (`RaiseNotification`, `BusyIndicatorChangeNotification`, `DbStatusEvent`, `AppStatusEvent`, `PageErrorEvent`, `LogoutUserEvent`)
- `DTS.Common.Storage.DatabaseServices` (`SetupForRemoteDb`, `SimpleDbTest`, `SetupLocal`, `BackupLocalDatabase`, `RestoreLocalDatabase`, `LOCAL_DB_FOLDER`)
- `DTS.Common.Storage.DatabaseServices` (via `DbOperations`, `LocalOnlyOperations`)
- `DTS.Common.Interface.Database.*` (e.g., `IDatabaseStatusBarView`, `IDatabaseCopyViewModel`)
- `DTS.Common.Interface.*` (e.g., `IStatusAndProgressBarView`)
- `DTS.Common.Utilities.Logging.APILogger`
- `DTS.Common.Interactivity.*` (`InteractionRequest`, `Notification`, `Confirmation`)
- **Prism Framework**:
- `Prism.Events.IEventAggregator`, `Prism.Regions.IRegionManager`
- `Prism.Commands`, `Prism.Interactivity.InteractionRequest`
- **Unity DI Container** (`IUnityContainer`)
- **WPF** (`System.Windows.Media.Brush`, `System.Windows.Visibility`)
### External Dependencies:
- **SQL Server** (via `System.Data.SqlClient`, `DbOperations.Connection`, `LocalOnlyOperations`)
- **`Resources.StringResources`** (localized strings: `"Local"`, `"CopyingTable"`, `"ClearingLocalDb"`, `"EnablingConstraints"`, `"SwitchFileNotFound"`)
### Inferred Consumers:
- Views (`IDatabaseStatusBarView`, `IDatabaseSwitchView`, `IDatabaseCopyView`) bind to these view models.
- Event publishers (`RaiseNotification`, `DbStatusEvent`, `AppStatusEvent`, etc.) drive view model state changes.
- `DatabaseServices` layer (`DbOperations`, `LocalOnlyOperations`) is called directly by these view models.
---
## 5. Gotchas
- **`DatabaseStatusBarViewModel` has two constructors** — the parameterless one does not subscribe to events, so `OnDbEvent`, `OnBusyIndicatorNotification`, and `OnRaiseNotification` will not be triggered if used. This is likely a design flaw or legacy artifact.
- **`DatabaseStatusBarViewModel.OnDbEvent` only handles `LegacyStatus`** — other status types (e.g., `FailedToConnectToRemote`) are silently ignored.
- **`DatabaseCopyViewModel.CopyFunc()` loads entire remote tables into memory** — `CopyRemoteTable` fetches all rows via `QueryDataSet` before copying. This may cause OOM for large tables.
- **`DatabaseCopyViewModel` uses hardcoded table list (`_allDBTables`)** — not dynamically fetched from DB schema. Duplicates exist (`"DataPRODbVersion"` and `"tblDataPRODbVersion"`), and missing tables will cause copy failures.
- **Batch size (`MAX_BATCH_SIZE = 20`) is arbitrary** — comment notes it was tuned empirically to avoid SQL parameter limits (2100), but no validation ensures column count × rows ≤ 2100.
- **`DatabaseSwitchViewModel.SwitchRemote()` calls `SwitchLocal()` on failure** — this may cause cascading failures or confusing UI state if local DB is also unavailable.
- **`DatabaseStatusBarViewModel.ServerName` is updated only in `OnDbEvent` for `LegacyStatus`** — if `InitializeValues` is not called first, `ServerName` remains `null`/empty, leading to incorrect `ActiveDbName`.
- **`DatabaseCopyViewModel.InitializeAsync()` resolves views/models twice** — two separate `Resolve` calls for `IStatusAndProgressBarView`/`IStatusAndProgressBarViewModel` per progress bar, potentially creating duplicate view model instances.
- **No cancellation support** — `CopyDatabase()` and `SwitchRemote()`/`SwitchLocal()` lack cancellation tokens or progress callbacks for user-initiated aborts.
- **`DbOperations._usingCentralizedDB` is a static field** — shared across the app domain; changes in one view model affect others unexpectedly.
- **`DatabaseStatusBarViewModel.ActiveDbName` returns `""` for unhandled `DbType`** — no fallback or exception on unknown types.
- **`DatabaseCopyViewModel` uses `sp_msforeachtable`** — undocumented, unsupported SQL Server stored procedure; may break on future SQL Server versions or non-standard DB configurations.

View File

@@ -0,0 +1,71 @@
---
source_files:
- DataPRO/Modules/DatabaseImporter/ConfigToDb/ConfigToDbMigrator.cs
generated_at: "2026-04-16T04:28:52.088463+00:00"
model: "Qwen/Qwen3-Coder-Next-FP8"
schema_version: 1
sha256: "489635ffcf3025b3"
---
# ConfigToDb
### **Purpose**
The `ConfigToDbMigrator` class facilitates migration of legacy application and user settings from an old configuration file (typically from a previous DataPRO installation) into the database-backed user property store. It reads settings from a specified legacy config path, maps known settings keys to standardized `PropertyEnums.PropertyIds`, performs type/conversion logic where necessary (e.g., milliseconds to seconds), and inserts the converted values into the database for all existing users via the `sp_UserPropertiesUpdateInsert` stored procedure. This enables backward compatibility during upgrades where settings previously stored in `.config` files are now persisted in a centralized, user-scoped database table.
---
### **Public Interface**
#### `bool migrateConfigToDb(string nextLowerPath, out string result)`
- **Behavior**: Attempts to migrate user and application settings from the legacy config file located at `nextLowerPath + Resources.RegistryDataPROExe`.
- First retrieves user settings; if successful (i.e., `result` does not contain `"OldSettingsCouldNotBeFound"` or `"OldSettingsCouldNotBeProcessed"`), it then retrieves application settings.
- If both are retrieved successfully, calls `InsertConfigSettingsIntoDb` to persist them.
- Returns `true` only if all steps succeed; otherwise `false`.
- **Parameters**:
- `nextLowerPath`: Path to the directory containing the legacy DataPRO executable (e.g., `"C:\\Program Files\\DataPRO\\"`).
- `result`: Output string describing success/failure (e.g., `"Could not find settings file: {exception message} at {path}"`).
---
### **Invariants**
- **User and Application Settings Separation**: User and application settings are processed independently; failure to retrieve user settings prevents application settings from being processed.
- **Explicit Key Mapping**: Only settings with explicitly listed keys (e.g., `"LastUsedSampleRate"`, `"DefaultUploadFolder"`, etc.) are migrated. Any unmapped keys are silently ignored.
- **User-Scoped Insertion**: Every migrated setting is inserted for *all* existing users (as returned by `GetAllUserIds()`), not just the current user.
- **No Rollback**: If an error occurs during DB insertion for one user or property, the method does not roll back prior successful inserts; it continues processing remaining users/properties.
- **Path Assumption**: Assumes the legacy config file resides at `nextLowerPath + Resources.RegistryDataPROExe` (i.e., the default install path).
---
### **Dependencies**
#### **Internal Dependencies**
- `ConfigToDb.Properties.Resources`: Used for localized strings (`Resources.UserSettings`, `Resources.ApplicationSettings`, `Resources.OldSettingsCouldNotBeFound`, `Resources.OldSettingsCouldNotBeProcessed`).
- `DTS.Common.Storage`: Provides `DatabaseImport.DbOperations`, `DbOperationsEnum.StoredProcedure`, and `DbOperations.Users.UserFields`.
- `DTS.Slice.Users.UserSettings`: Provides `SettingElementCollection` and `SettingElement` types (from .NET `System.Configuration`).
- `System.Configuration`: Used via `ConfigurationManager.OpenExeConfiguration`.
- `System.Data.SqlClient`: Used for `SqlCommand`, `SqlDbType`, `SqlParameter`.
- `PropertyEnums.PropertyIds`: Enum defining property IDs for database storage (e.g., `LastUsedSampleRate`, `DefaultUploadFolder`).
- `SupportedExportFormatBitFlags`: Nested enum used to decode `DefaultTestExportFormat` bitmask.
#### **External Dependencies**
- SQL Server database with stored procedures:
- `sp_UserPropertiesUpdateInsert`
- `sp_UserGetIdsAll` (via `DbOperationsEnum.StoredProcedure.sp_UserGetIdsAll`)
- Legacy `.config` files in .NET `clientSettings` format.
#### **Depended Upon**
- Unknown from source alone — this class is likely invoked during application startup or upgrade workflows, but no callers are visible in the provided file.
---
### **Gotchas**
- **Silent Ignoring of Unmapped Settings**: Settings not explicitly listed in the `switch` blocks (e.g., `"SomeNewSetting"`) are ignored without warning or logging.
- **Hardcoded Key-to-ID Mapping**: The mapping from config keys to `PropertyEnums.PropertyIds` is hardcoded; adding new settings requires code changes and recompilation.
- **No Error Propagation from DB**: In `StoreInDb`, if the stored procedure returns a non-zero `@errorNumber`, the error is *not* propagated or logged (only commented as a potential action). The method continues and returns `true` even if DB writes fail for some users.
- **Culture-Specific Number Conversion**: The `"DefaultTestExcitationWarmupMS"` → seconds conversion uses `CultureInfo.InvariantCulture`, but other numeric conversions (e.g., `Convert.ToDouble`, `Convert.ToInt32`) use the current culture, risking parsing errors in non-US locales.
- **Bitmask Parsing Assumption**: `ExportDesired` assumes the `settingValue` string can be parsed as an `int` (via `Convert.ToInt32`) — if the config value is malformed or non-numeric, this will throw.
- **No Validation of Setting Values**: No validation is performed on the `setting.Value.ValueXml.InnerXml` before insertion (e.g., empty strings, invalid XML, or type mismatches may be stored).
- **Assumes Single Section per Group**: `GetConfigSettings` assumes each section group (e.g., `"userSettings"`) contains exactly one section and uses `Sections[0]`. If multiple sections exist, only the first is used.
- **No Cleanup of Old Settings**: After successful migration, the old config file is *not* modified or deleted — old settings may remain and cause confusion.
- **`GetAllUserIds()` Swallows Exceptions**: If `GetAllUserIds()` fails (e.g., DB connection issue), it returns an empty list, causing `InsertConfigSettingsIntoDb` to silently do nothing (no rows inserted) with no error indication.
- **`migrateConfigToDb` Returns `true` Only on Full Success**: If user settings succeed but application settings fail, the method returns `false`, even though partial migration occurred.

View File

@@ -0,0 +1,93 @@
---
source_files:
- DataPRO/Modules/DatabaseImporter/ConfigToDb/Properties/AssemblyInfo.cs
- DataPRO/Modules/DatabaseImporter/ConfigToDb/Properties/Resources.Designer.cs
generated_at: "2026-04-16T04:33:27.836179+00:00"
model: "Qwen/Qwen3-Coder-Next-FP8"
schema_version: 1
sha256: "c71978bea4a91840"
---
# Properties
## Documentation Page: `ConfigToDb` Assembly (Properties Module)
---
### 1. **Purpose**
This module (`ConfigToDb`) is a .NET assembly responsible for managing localized string resources used in configuration-related operations—specifically, for generating user-facing messages related to updating `DataPRO.exe.config` during version upgrades. It does not contain business logic itself but provides a strongly-typed resource layer (`Resources`) to centralize and localize error/warning messages. Its role is ancillary: supporting diagnostics and user feedback during configuration migration workflows elsewhere in the system.
---
### 2. **Public Interface**
The module exposes only one public type: the auto-generated `ConfigToDb.Properties.Resources` class. This class is **internal**, but its members are used by the rest of the assembly (and potentially by consuming code via reflection or resource loading). No public *functions* or *classes* are declared in the visible source files.
#### `ConfigToDb.Properties.Resources` (internal class)
- **`ResourceManager ResourceManager { get; }`**
Returns a cached `System.Resources.ResourceManager` instance for the `ConfigToDb.Properties.Resources` resource set. Lazily initializes on first access.
- **`CultureInfo Culture { get; set; }`**
Gets or sets the UI culture used for resource lookups (overrides the current threads `CurrentUICulture` for this class only).
- **`string ApplicationSettings { get; }`**
Returns the localized string `"applicationSettings"`.
- **`string OldSettingsCouldNotBeFound { get; }`**
Returns the localized warning string:
`"Warning: DataPRO.exe.config was not updated because config settings from previously-installed version of DataPRO could not be found: {0}; {1}."`
- **`string OldSettingsCouldNotBeProcessed { get; }`**
Returns the localized warning string:
`"Warning: DataPRO.exe.config was not updated because config settings from previously-installed version of DataPRO could not be processed.."`
- **`string RegistryDataPROExe { get; }`**
Returns the localized string `"DataPRO.exe."`
- **`string UserSettings { get; }`**
Returns the localized string `"userSettings"`.
> ⚠️ **Note**: All resource accessors are auto-generated and rely on an external `.resx` file (not provided). The actual resource keys (e.g., `"ApplicationSettings"`) are inferred from the source code comments and method bodies.
---
### 3. **Invariants**
- The `ResourceManager` instance is lazily initialized and cached per-appdomain (thread-safe via reference equality check).
- Resource strings are **statically defined** at compile time and loaded from embedded resources (`.resources` file compiled from `.resx`).
- The `Culture` property can be set at runtime to override localization, but defaults to the current threads UI culture.
- No runtime validation or mutation of resource content occurs—strings are immutable once compiled.
---
### 4. **Dependencies**
#### Dependencies *of* this module:
- `System.Resources` (for `ResourceManager`)
- `System.Globalization` (for `CultureInfo`)
- `System.CodeDom.Compiler`, `System.Diagnostics`, `System.ComponentModel` (for attributes used in auto-generated code)
#### Dependencies *on* this module:
- Not directly inferable from the provided files, but based on resource content, it is highly likely that:
- A configuration migration or upgrade module (e.g., in `DatabaseImporter` or `ConfigToDb`s main logic—*not shown here*) consumes `Resources` to format warnings/errors during config file updates.
- The `DataPRO.exe.config` update logic (likely in another module) calls `Resources.OldSettingsCouldNotBeFound` or `Resources.OldSettingsCouldNotBeProcessed` with formatted arguments.
#### Assembly metadata:
- **Assembly Name**: `ConfigToDb`
- **COM Visibility**: Disabled (`ComVisible(false)`)
- **GUID**: `98a0afb3-7bbf-4e43-8c5b-552d69c8d3a9`
- **Version**: `1.0.0.0` (both `AssemblyVersion` and `AssemblyFileVersion`)
---
### 5. **Gotchas**
- **No public API surface**: This module is *purely* a resource container. Developers should not expect to instantiate or extend it directly—its purpose is internal localization.
- **Missing `.resx` file**: The actual resource strings and keys are defined in a `.resx` file (not included), so the exact set of supported keys and their current values cannot be verified from source alone.
- **Auto-generated code**: The `Resources.Designer.cs` file is regenerated automatically. Manual edits will be overwritten—changes must be made in the `.resx` file.
- **Hardcoded placeholder `{0}; {1}`**: The `OldSettingsCouldNotBeFound` string expects *two* substitution parameters, but the source provides no context on how these are supplied or validated. Passing fewer/more arguments will cause a runtime `FormatException`.
- **Trailing period in `RegistryDataPROExe`**: The string `"DataPRO.exe."` ends with a period—this may be intentional (e.g., for sentence completion) or a typo. Verify usage context before reuse.
> ✅ **Best practice**: When consuming `Resources`, always validate argument count for formatted strings (e.g., via `string.Format` or interpolated strings) to avoid runtime exceptions.

View File

@@ -0,0 +1,171 @@
---
source_files:
- DataPRO/Modules/DatabaseImporter/DatabaseImport/CustomChannel.cs
- DataPRO/Modules/DatabaseImporter/DatabaseImport/TestGraph.cs
- DataPRO/Modules/DatabaseImporter/DatabaseImport/SerializedSettings.cs
- DataPRO/Modules/DatabaseImporter/DatabaseImport/DbImporter.cs
generated_at: "2026-04-16T04:28:50.017817+00:00"
model: "Qwen/Qwen3-Coder-Next-FP8"
schema_version: 1
sha256: "35545dbb44d8a4ab"
---
# Documentation: Database Import Module
## 1. Purpose
This module provides functionality for importing database content from XML files and managing custom channels and test graphs within the DataPRO system. It serves as the core data ingestion layer for migrating legacy or external test configurations into the applications internal database schema, while supporting both ISO 13499-standardized and user-defined (custom) channels. The module enables safe, structured population of database tables—including sensors, calibrations, test objects, and custom definitions—without disrupting existing ISO-defined data, and includes specialized handling for hardware-specific migrations (e.g., TDAS G5 VDS, SPS) and per-user setting inheritance.
## 2. Public Interface
### `CustomChannel` class
- **`public MMEPossibleChannels Channel { get; }`**
The underlying ISO channel definition wrapped by this custom channel. Immutable after construction.
- **`public string Text1 { get; set; }`**
Exposes `Channel.Text_L1` via a property setter that delegates to `Channel.SetText1(value)`. Used for user-facing display name.
- **`public CustomChannel(MMEPossibleChannels channel, bool newChannel = true)`**
Constructor. If `newChannel` is `true`, creates a copy of the input `channel`; otherwise uses the reference directly. Initializes private fields (`_direction`, `_filterClass`, `_finLoc1`, etc.) by querying `IsoDb` via `App.IsoDb` methods. Catches and stores `ISO13499FileDb.ExpiredISOFieldException` for expired ISO fields (e.g., main location) in `_expiredErrors`.
- **`public int CompareTo(CustomChannel other)`**
Implements `IComparable<CustomChannel>`. Returns `0` if references are equal; otherwise compares `Text1` values using ordinal string comparison.
### `CustomChannelList` class (singleton)
- **`public static CustomChannelList List { get; }`**
Thread-safe singleton accessor. Uses double-checked locking with `LockObject`.
- **`public void ReloadAll()`**
Clears cached channel lists (`_listChannels`, `_dictChannels`), refreshes all ISO data via `IsoDb.RefreshAllData()`, and repopulates channels via `PopulateChannelsIfNecessary()`.
- **`public void DeleteAll()`**
Clears cached lists and calls `IsoDb.DeleteSQL()` to delete all custom channels and related tables. Does *not* delete DAS tables (per comment).
- **`public ISO13499FileDb IsoDb { get; }`**
Lazy-initialized singleton for ISO database access. Instantiates `ISO13499FileDb`, calls `RefreshAllData()`, and caches the instance.
### `TestGraph` class
- **`public TestGraph(TestTemplate template)`**
Constructor. Initializes `_template`, `_groups`, and `_addedGroups` from `template.TestObjectsWithChannels` and `template.AddedGroups`.
- **`public void SetThresholdsFromSQL(string sThresholds)`**
Parses a semicolon-separated (`§`) string of numeric thresholds (braces `{}` stripped), adding valid doubles to `_thresholds`.
- **`public void SetChannelsFromSQL(string sChannels)`**
Parses a semicolon-separated (`§`) string of channel IDs (parentheses `()` stripped), looks up each ID in `AvailableChannels`, and adds matching channels via `AddChannel()`.
- **`public TestObjectChannel[] AvailableChannels { get; }`**
Returns up to `MAX_CHANNELS_PER_GRAPH` (8) available channels. Builds list by iterating `_groups` and `_addedGroups`, adding non-disabled, non-optional channels with valid sensor serial numbers. Special handling for SQUIB sensors: adds both current and voltage sub-channels if not already present. Returns `null` if any group fails to add channels (e.g., missing ISO test object). Sorts result before returning.
### `SerializedSettings` class (static, sealed)
- **`public enum Keys`**
Contains 100+ named keys for global settings (e.g., `IgnorePowerMode`, `RealtimeSampleRate`, `SLICE6_PowerSetting`, etc.).
- **`public static string ExportINIFile { get; set; }`**
Gets/sets the path of the export INI file via `SettingsDB.GetGlobalValue`/`SetGlobalValue`.
- **`public static IsoChannelSensorCompatibilityLevels IsoChannelSensorCompatibilityLevel { get; set; }`**
Gets/sets compatibility level (warn/error/etc.) for ISO channel-sensor mismatches. Defaults to `Warn`.
- **`public static ISOSupportLevels ISOSupportLevel { get; set; }`**
Gets/sets ISO support mode: `ISO_ONLY`, `TRANSITORY`, or `NO_ISO`. Defaults to `ISO_ONLY`.
- **`public static SensorTypeToDimension[] AllSensorTypeToDimensions { get; set; }`**
Gets/sets a list of sensor-type-to-ISO-dimension mappings (code, name, dimension). Stored as serialized strings in `SettingsDB` with index-based keys (`SENSORTYPE_0`, `SENSORTYPE_1`, …). Default includes 7 mappings (e.g., Acceleration → AC, Force → FO).
- **`public static Dictionary<string, string> GetAllSensorTypeToDimensionMappings()`**
Returns a dictionary mapping sensor type codes to ISO physical dimension codes.
- **`public static bool TestSetupDefaultDontAllowOutOfCalSensors { get; set; }`**
Gets/sets whether out-of-calibration sensors are disallowed by default in test setup.
### `DbImporter` class
- **`public DbImporter(int dbType, string dbName, string server, bool useNTLMAuthentication, string localDbUser, string localDbPassword)`**
Constructor. Configures `DbOperations.Connection` for local or centralized database access.
- **`public void ImportXML(string ImportFile, SetStatusDelegate SetStatus)`**
Imports database content from an XML file. Clears all tables via `ImportSensorsImportControl.ClearAllTables(true)`, then iterates XML elements mapping to `TopLevelFields` (e.g., `"CustomChannels"`, `"Sensors"`, `"Calibrations"`), calling `ImportTestSetup.ProcessRootNode` for each. Handles special post-import steps: `AssignSettingsToAllUsers()`, `MigrateG5ChannelSupportedBridges()`, `MigrateSPSChannelSupportedBridges()`.
- **`public bool MigrateG5ChannelSupportedBridges()`**
Fixes TDAS G5 VDS channel bridge compatibility by updating `DASChannels.SupportedBridges` from `12` to `140` for DAS IDs where `DAS.Type = 12`.
- **`public void MigrateSPSChannelSupportedBridges()`**
Fixes SPS channel bridge compatibility by updating `DASChannels.SupportedBridges` from `15` to `143` for DAS IDs where `DAS.Type = 19` and `ProtocolVersion >= 154`.
- **`public bool IsServerConnected()`**
Returns `DbOperations.IsServerConnected()`.
## 3. Invariants
- **`CustomChannel`**:
- `_expiredErrors` may contain `ISO13499FileDb.ExpiredISOFieldException` instances only for fields that failed during construction (e.g., main location), not for other fields.
- `Channel` is either a copy (if `newChannel == true`) or the original reference; never null after construction.
- `Text1` is always synchronized with `Channel.Text_L1`.
- **`CustomChannelList`**:
- `_listChannels` and `_dictChannels` are either both `null` or both fully populated and consistent (same channels, keyed by ISO code).
- Channel ISO codes (from `ISO.IsoCode.GetString(ch.Channel, false)`) are unique in `_dictChannels`.
- `List` is lazily initialized once per AppDomain; thread-safe via `lock`.
- **`TestGraph`**:
- `AvailableChannels` returns at most 8 channels.
- SQUIB channels are added as *two* distinct channels (current and voltage) only if not already present in the graph.
- `ContainsCurrentChannel` checks for both the channel itself and its current variant suffixed with `DTS.Common.Constants.CURRENT_SUFFIX`.
- `AvailableChannels` returns `null` if any group fails to contribute channels (e.g., missing ISO test object).
- **`SerializedSettings`**:
- `AllSensorTypeToDimensions` defaults to 7 mappings; index-based storage uses `(char)149` (`ō`) as delimiter.
- Settings values are stored as strings in `SettingsDB`; parsing may fall back to defaults on failure.
- **`DbImporter`**:
- `ImportXML` clears *all* tables before import (including custom tables).
- Post-import migrations (`MigrateG5ChannelSupportedBridges`, `MigrateSPSChannelSupportedBridges`) are unconditional and do not update DB version.
## 4. Dependencies
### Imports/References:
- `System`, `System.Collections.Generic`, `System.Linq`, `System.Xml`, `System.Data`, `System.Data.SqlClient`
- `System.Windows` (for `Application.Current`)
- `DTS.Common.Constants` (used in `TestGraph.ContainsCurrentChannel`)
- `Test.Module.Channel.Sensor` (for `BridgeType.SQUIB`)
- `SensorsCollection.SensorsList` (for `GetSensorBySerialNumber`)
- `ISO.IsoCode` (for `GetString`)
- `App` class (accessed via `Application.Current` for `IsoDb`)
- `ISO13499FileDb`, `MMEPossibleChannels`, `MMEPositions`, etc. (ISO-related enums/objects)
- `SettingsDB`, `DbOperations`, `DbOperationsEnum` (for settings and DB access)
- `ImportTestSetup`, `ImportSensorsImportControl` (external classes for XML processing)
### Depends on:
- `ISO13499FileDb` for ISO data lookup and persistence.
- `SettingsDB` for global and user-specific settings.
- `DbOperations` for SQL execution and connection management.
- `ImportTestSetup` and `ImportSensorsImportControl` for XML parsing and table population.
- `App` singleton for application-wide database and configuration access.
## 5. Gotchas
- **`CustomChannel`**:
- `_expiredErrors` is populated but never exposed or used elsewhere in the provided source—potential silent failure point.
- Constructor silently ignores failures for most fields (e.g., `_position`, `_testObject`) but only catches exceptions for `_mainLocation`. Other fields may throw or default silently.
- **`CustomChannelList`**:
- `ReloadAll()` calls `IsoDb.RefreshAllData()` *inside* the lock, which may block UI or other threads if refresh is slow.
- `DeleteAll()` clears `_listChannels` and `_dictChannels` *before* calling `IsoDb.DeleteSQL()`—if the DB call fails, the in-memory state is already corrupted.
- **`TestGraph`**:
- `AvailableChannels` returns `null` on *any* group failure, not just partial failure—this may be overly strict.
- SQUIB voltage channel reuses the original `channel` object (sets `SquibChannelType` and `NameOfTheChannel` in-place), which may cause side effects if the original channel is reused elsewhere.
- **`SerializedSettings`**:
- `AllSensorTypeToDimensions` uses `(char)149` as delimiter—non-standard and may break with different encodings or string operations.
- Default mappings are hardcoded in `GetSensorTypeMapping(int, string, string, string)`; changing defaults requires updating both the method and `AllSensorTypeToDimensions` setter logic.
- **`DbImporter`**:
- `ImportXML` clears *all* tables unconditionally—no backup is performed despite commented-out code.
- `MigrateG5ChannelSupportedBridges` and `MigrateSPSChannelSupportedBridges` are called unconditionally during import, even if not needed (e.g., non-migration imports).
- `AssignSettingsToAllUsers` silently swallows all exceptions—settings may fail to propagate without notification.

View File

@@ -0,0 +1,107 @@
---
source_files:
- DataPRO/Modules/DatabaseImporter/DatabaseImport/App/WaitCursor.cs
- DataPRO/Modules/DatabaseImporter/DatabaseImport/App/App.cs
generated_at: "2026-04-16T04:29:09.171697+00:00"
model: "Qwen/Qwen3-Coder-Next-FP8"
schema_version: 1
sha256: "85d98116aaeec020"
---
# App
## Documentation: `WaitCursor` and `App` Module (DatabaseImporter)
---
### 1. Purpose
This module provides UI-level cursor and application state management during long-running operations in a WPF-based database import workflow. Specifically, the `WaitCursor` class offers a lightweight, `IDisposable` wrapper to temporarily override the mouse cursor to a wait state and restore it upon disposal. The `App` class (a partial class for `Application`) extends this functionality at the application level by coordinating global busy/idle states: it disables the main window and manages a singleton `WaitCursor` instance across thread boundaries using the WPF `Dispatcher`, ensuring safe, re-entrant, and exception-safe busy/idle transitions—typically used before/after data-intensive operations (e.g., database refreshes or imports).
---
### 2. Public Interface
#### `WaitCursor` class (`DataImport.WaitCursor`)
- **`public WaitCursor()`**
Constructor. Saves the current `Mouse.OverrideCursor`, sets `Mouse.OverrideCursor = Cursors.Wait`, and prepares for later restoration via `Dispose()`.
- **`public void Dispose()`**
Restores the previously saved cursor (`_previousCursor`) to `Mouse.OverrideCursor`. Must be called exactly once per instance (per `using` or manual disposal pattern). No-op if called multiple times (but cursor may be incorrectly restored if disposed more than once).
#### `App` class (`DatabaseImport.App`, partial)
- **`public ISO13499FileDb IsoDb { get; }`**
Lazy-initialized singleton accessor for the `ISO13499FileDb` database instance. On first access, instantiates `_isoDb`, calls `_isoDb.RefreshAllData()`, and returns it. Thread-safety is *not* guaranteed (no locking around initialization or `RefreshAllData()`).
- **`public void SetAppBusy()`**
Sets the application into a *busy* state:
- Marshals to the UI thread via `Dispatcher.BeginInvoke` if called from a non-UI thread.
- Disposes any existing `_wc` (if not null).
- Creates a new `WaitCursor` instance and assigns it to `_wc`.
- Sets `MainWindow.IsEnabled = false`.
- Uses `lock (WaitCursorLock)` to serialize concurrent calls.
- *No-op* if `MainWindow` is null.
- **`public void SetAppAvailable()`**
Sets the application into an *available* (idle) state:
- Marshals to the UI thread via `Dispatcher.BeginInvoke` if called from a non-UI thread.
- Disposes and nullifies `_wc` (if not null).
- Sets `MainWindow.IsEnabled = true`.
- Uses `lock (WaitCursorLock)` to serialize concurrent calls.
- *No-op* if `MainWindow` is null.
---
### 3. Invariants
- **Cursor restoration guarantee**: After a `WaitCursor` instance is disposed, `Mouse.OverrideCursor` is restored to the value it held at the time of construction.
- **Application busy/idle state consistency**:
- `MainWindow.IsEnabled` is `false` *only* when `_wc` is non-null (i.e., during a `SetAppBusy()` call with no intervening `SetAppAvailable()`).
- `_wc` is `null` *only* when the application is not busy (i.e., after `SetAppAvailable()` or before any `SetAppBusy()` call).
- **Thread-safety of state transitions**:
- `SetAppBusy()` and `SetAppAvailable()` are thread-safe *with respect to each other* via `lock (WaitCursorLock)`.
- Both methods *always* marshal to the UI thread via `Dispatcher.BeginInvoke` if invoked off-thread, ensuring UI mutations occur on the correct thread.
- **Singleton `IsoDb` initialization**: `_isoDb` is initialized at most once, and only upon first access to `IsoDb`. `RefreshAllData()` is called exactly once per instance creation.
---
### 4. Dependencies
#### This module depends on:
- `System.Windows.Input.Cursors` (for `Cursors.Wait`)
- `System.Windows.Input.Mouse` (for `Mouse.OverrideCursor`)
- `System.Windows.Threading.Dispatcher` (for `Dispatcher.CheckAccess`, `BeginInvoke`)
- `System.Windows.Application` (base class `App : Application`)
- `System.Windows.Window` (via `MainWindow`)
- `DatabaseImport.ISO13499FileDb` (referenced in `App.IsoDb` property; defined elsewhere in the codebase)
#### This module is depended on by:
- Any code that needs to wrap long-running operations in a wait cursor (e.g., `using (new WaitCursor()) { ... }`).
- Code that triggers database refreshes or imports (uses `App.IsoDb`).
- UI or service layers that call `App.SetAppBusy()` before and `App.SetAppAvailable()` in `finally` blocks (as recommended in comments).
---
### 5. Gotchas
- **`IsoDb` initialization is not thread-safe**: Multiple concurrent first-time accesses to `IsoDb` may result in multiple `ISO13499FileDb` instances being created and `RefreshAllData()` being called multiple times. No locking or double-check pattern is used.
- **`WaitCursor` is not re-entrant**: If `WaitCursor` is constructed multiple times without disposal (e.g., nested `using` blocks), only the *outermost* cursor state is preserved in `_previousCursor`. Inner disposals will overwrite the cursor prematurely.
*Example*:
```csharp
using (new WaitCursor()) // Saves cursor A, sets Wait
{
using (new WaitCursor()) // Saves cursor Wait, sets Wait again
{
// ...
} // Restores cursor Wait → incorrect!
} // Restores cursor A
```
- **`SetAppBusy()` / `SetAppAvailable()` may silently no-op**: If `MainWindow` is `null` at the time of call (e.g., during early startup or after window close), the methods exit early with no side effects—no exception is thrown.
- **`WaitCursorLock` is static and shared across all `App` instances**: Since `App` is a singleton in WPF, this is expected—but if multiple `App` instances were ever created (e.g., in tests), locking would be incorrectly shared.
- **No exception handling in `SetAppBusy()`/`SetAppAvailable()`**: If `MainWindow.IsEnabled = false/true` or `WaitCursor.Dispose()` throws, the busy/idle state may be left inconsistent (e.g., `_wc` disposed but `MainWindow.IsEnabled` not updated).
- **`_wc` is not thread-local**: Though marshaled to the UI thread, `_wc` is a *single instance field*—concurrent calls via `BeginInvoke` are serialized by `WaitCursorLock`, but the timing of disposal/creation may cause transient cursor flicker if not used carefully (e.g., overlapping busy periods).
- **`WaitCursor` does not prevent user input beyond disabling `MainWindow`**: `Mouse.OverrideCursor` alone does not block input; the disabling of `MainWindow` is what prevents interaction. If `MainWindow` is hidden or replaced, the busy state may persist incorrectly.
None identified beyond the above.

View File

@@ -0,0 +1,81 @@
---
source_files:
- DataPRO/Modules/DatabaseImporter/DatabaseImport/Classes/Constants.cs
- DataPRO/Modules/DatabaseImporter/DatabaseImport/Classes/Enums.cs
generated_at: "2026-04-16T04:29:22.195029+00:00"
model: "Qwen/Qwen3-Coder-Next-FP8"
schema_version: 1
sha256: "7d0744f20dc3772b"
---
# Classes
## Documentation: DatabaseImport Module Constants and Enums
---
### 1. Purpose
This module provides foundational type definitions and symbolic constants used throughout the `DatabaseImport` subsystem, primarily to support test configuration, channel handling, and recording behavior in the DataPRO test framework. It centralizes string literals for non-ISO test object metadata and defines strongly-typed enumerations for recording modes, ISO channel compatibility policies, and test template metadata tags—enabling consistent interpretation of test setup data imported from external databases or configuration sources.
---
### 2. Public Interface
#### Constants (`DatabaseImport.Constants`)
- **`NON_ISO_TESTOBJECT_CHANNEL_TYPE`** (`public const string`)
String value: `"x_NonISOTestObjectType_x"`. Used as a channel type identifier for non-ISO test objects during import.
- **`NON_ISO_TESTOBJECT_NAME`** (`public const string`)
String value: `"x_NonISOTestObjectName_x"`. Used as a channel name identifier for non-ISO test objects during import.
#### Enumerations
- **`RecordingModes`** (`public enum`)
Represents supported data acquisition recording strategies.
- `CircularBuffer`: `"RecordingModes_CircularBuffer"`
- `Recorder`: `"RecordingModes_Recorder"`
- `HybridRecorder`: `"RecordingModes_HybridRecorder"`
*Note:* Uses `[TypeConverter(typeof(EnumDescriptionTypeConverter))]` for localized description resolution.
- **`IsoChannelSensorCompatibilityLevels`** (`public enum`)
Defines policy for handling non-ISO sensors attached to ISO channels:
- `DontWarn`: No warning or restriction.
- `Warn`: Issue warning but allow operation.
- `DontAllow`: Block operation if non-ISO sensor detected.
- **`TestTemplateTags`** (`public enum`)
Contains 103 named constants representing keys for test template metadata fields (e.g., `"UploadData"`, `"RecordingMode"`, `"PreTriggerSeconds"`). Used to serialize/deserialize test configuration properties from structured data (e.g., XML, JSON, or database rows).
*Note:* Includes both high-level flags (`AllowMissingSensors`, `AutomaticProgression`) and granular settings (`AutomaticProgressionDelayMS`, `AutoVerifyDelaySeconds`).
- **`StrictLevel`** (`public enum`)
Controls validation strictness during import:
- `Strict`: Enforce strict schema/data validation.
- `UpdateTable`: Allow schema updates or relaxed validation (e.g., for backward compatibility).
---
### 3. Invariants
- All `TestTemplateTags` enum values are **string-identifiable keys**—their underlying integer values are irrelevant; only their symbolic names matter for lookup.
- `RecordingModes` enum values are **exhaustive and mutually exclusive**—a test configuration must specify exactly one mode.
- `IsoChannelSensorCompatibilityLevels` values define a **strict ordering of enforcement**: `DontWarn``Warn``DontAllow`.
- `Constants` values are **fixed string literals**—no runtime modification or localization is performed within this module.
---
### 4. Dependencies
- **Depends on**:
- `System` (for `TypeConverter`, `DescriptionAttribute`)
- `System.ComponentModel` (for `TypeConverter` and `DescriptionAttribute`)
- **Used by**:
- Other modules in `DatabaseImport` (e.g., importers, validators, test template processors) that parse test configurations or validate channel/sensor compatibility.
- Likely consumed by UI layers (via `TypeConverter`) for localized enum descriptions.
---
### 5. Gotchas
- **Non-ISO identifiers are placeholder strings**: The values `"x_NonISOTestObjectType_x"` and `"x_NonISOTestObjectName_x"` are *not* standardized—they are internal markers. Do not assume they match external schema names.
- **`TestTemplateTags` enum is exhaustive but not self-documenting**: The enum names map directly to string keys (e.g., `TestTemplateTags.RecordingMode``"RecordingMode"`), but the *meaning* of each key is defined elsewhere (e.g., in schema docs or template parsers).
- **`RecordingModes` descriptions are resource keys**: The `[Description(...)]` attributes contain *resource keys* (e.g., `"RecordingModes_CircularBuffer"`), not literal descriptions. Actual display text requires resource resolution via `EnumDescriptionTypeConverter`.
- **`StrictLevel.UpdateTable` implies leniency**: This may bypass validation that would otherwise fail imports (e.g., missing required fields), risking data inconsistency if misused.
- **No validation logic in this module**: These types define *what* can be configured, not *how*—validation rules reside in other modules (e.g., importers, validators).
None identified beyond the above.

View File

@@ -0,0 +1,177 @@
---
source_files:
- DataPRO/Modules/DatabaseImporter/DatabaseImport/Classes/Hardware/DASSettings.cs
- DataPRO/Modules/DatabaseImporter/DatabaseImport/Classes/Hardware/HardwareChannel.cs
- DataPRO/Modules/DatabaseImporter/DatabaseImport/Classes/Hardware/DASHardwareList.cs
- DataPRO/Modules/DatabaseImporter/DatabaseImport/Classes/Hardware/DASHardware.cs
generated_at: "2026-04-16T04:31:49.040833+00:00"
model: "Qwen/Qwen3-Coder-Next-FP8"
schema_version: 1
sha256: "d546885c144cb09e"
---
# Hardware
## Documentation: DAS Hardware Module (`DatabaseImport.Classes.Hardware`)
---
### 1. Purpose
This module provides data structures and utilities for representing and managing Data Acquisition System (DAS) hardware configurations within the `DatabaseImporter` module. It encapsulates hardware metadata (e.g., serial number, type, channels, settings) and supports persistence into the database (specifically `tblTestSetupDASSettings` for `DASSettings`). It serves as a bridge between raw database records (via `ISO.Hardware` and `ISO.HardwareChannel`) and higher-level application logic, enabling consistent handling of DAS hardware during test import and processing.
---
### 2. Public Interface
#### `DASSettings`
- **`public string DASSerialNumber { get; set; }`**
Serial number of the DAS device associated with these settings.
- **`public double SampleRate { get; set; }`**
Sample rate (in Hz) configured for the DAS.
- **`public int ExcitationWarmupTimeMS { get; set; }`**
Excitation warm-up time in milliseconds.
- **`public double HardwareAAF { get; set; }`**
Hardware anti-aliasing filter (AAF) cutoff frequency (in Hz).
- **`public double PreTriggerSeconds { get; set; }`**
Duration (in seconds) of pre-trigger buffer.
- **`public double PostTriggerSeconds { get; set; }`**
Duration (in seconds) of post-trigger buffer.
- **`public bool StatusLineCheck { get; set; }`**
Flag indicating whether status line checking is enabled.
- **`public bool BatteryCheck { get; set; }`**
Flag indicating whether battery voltage checking is enabled.
- **`public double InputVoltageMin { get; set; }`**
Minimum acceptable input voltage (V).
- **`public double InputVoltageMax { get; set; }`**
Maximum acceptable input voltage (V).
- **`public double BatteryVoltageMin { get; set; }`**
Minimum acceptable battery voltage (V).
- **`public double BatteryVoltageMax { get; set; }`**
Maximum acceptable battery voltage (V).
> **Note**: This class is intended for serialization into `tblTestSetupDASSettings`. No custom logic or validation is present in the class itself.
---
#### `HardwareChannel`
- **`public HardwareChannel(HardwareChannel copy)`**
Copy constructor. Copies `ChannelNumber`, `Sensor`, `_testObjectChannel`, `Hardware`, and `_isoChannel` from `copy`.
- **`public HardwareChannel(ISO.HardwareChannel channel, DASHardware hardware)`**
Constructor initializing from an `ISO.HardwareChannel` and its parent `DASHardware`.
- **`public int CompareTo(HardwareChannel right)`**
Compares two `HardwareChannel` instances first by `DASDisplayOrder`, then by `ChannelIdx` (0-based index). Returns `0` if either operand is `null` or reference-equal.
- **`public string GetId()`**
Returns a unique identifier string in the format `{HardwareId}x{ChannelNumber+1}` (1-based channel index).
- **`public bool IsSupportedBridgeType(Test.Module.Channel.Sensor.BridgeType bridgeType)`**
Returns `true` if the underlying `ISO.HardwareChannel.SupportedBridges` bitmask includes the specified `bridgeType`.
- **`public int ChannelNumber { get; }`**
0-based channel index (`ISO.HardwareChannel.ChannelIdx`).
- **`public DASHardware Hardware { get; }`**
Parent `DASHardware` instance.
- **`public SensorData Sensor { get; set; }`**
Optional sensor configuration associated with this channel.
- **`public ISO.HardwareChannel GetISOChannel()`**
Returns the underlying `ISO.HardwareChannel` instance.
---
#### `DASHardware`
- **`public DASHardware(Hardware hardware)`**
Constructor initializing from a `Hardware` instance. Populates `Channels` by wrapping each `ISO.HardwareChannel` in a `HardwareChannel`.
- **`public DASHardware(DASHardware copy, DASHardware parentDAS)`**
Constructor for creating a child DAS from a `copy`, with `parentDAS` as its logical parent. Copies `Channels` (deep copy via `HardwareChannel` copy constructor) and `DbTimeStamp`.
- **`public bool IsPseudoRack()`**
Returns `true` if the hardware type is `SLICE_LabEthernet`, `SLICE_EthernetController`, or `SLICE6DB`, indicating it should be UI-rendered as a rack despite not physically being one.
- **`public bool IsDummy()`**
Returns `true` if `SerialNumber` contains the substring `"Dummy"`.
- **`public int CompareTo(DASHardware right)`**
Implements ordering logic:
- `null``1`
- Same reference or `SerialNumber` match → `0`
- Parent/child relationship → child sorts after parent
- Same parent and `PositionOnDistributor` → sort by `PositionOnDistributor`
- Otherwise → lexicographic sort on `SerialNumber`.
- **`public string SerialNumber { get; set; }`**
Serial number of the DAS.
- **`public string ParentDAS { get; set; }`**
Serial number of the parent DAS (if any).
- **`public int PositionOnDistributor { get; set; }`**
Position index on a distributor rack (used for ordering).
- **`public HardwareChannel[] Channels { get; set; }`**
Array of channels. Setter sorts the list using `HardwareChannel.CompareTo()` before assignment.
- **`public int GetHardwareTypeInt()`**
Returns the raw integer type (`_hardware.DASType`).
- **`public HardwareTypes GetHardwareTypeEnum()`**
Casts `GetHardwareTypeInt()` to `HardwareTypes` enum.
- **`public long GetMaxMemoryLong()`**
Returns `_hardware.MaxMemory`.
- **`public Hardware GetHardware()`**
Returns the underlying `Hardware` instance.
---
#### `DASHardwareList`
- **`public static DASHardwareList GetList()`**
Singleton accessor. Returns the cached instance if present; otherwise instantiates and caches a new one. (Note: `PopulateHardware()` is commented out in both constructor and `GetList()`.)
- **`public void ReloadAll()`**
Intended to reload hardware definitions, but current implementation is commented out.
- **`public DASHardware GetHardware(string id, bool bUseCache = true)`**
Convenience overload of the 4-parameter version with `bThrowExceptionIfChanged = true`, `changed = out bool` ignored.
- **`public DASHardware GetHardware(string id, bool bThrowExceptionIfChanged, out bool changed, bool bUseCache = true)`**
Retrieves a `DASHardware` by `id`. Uses `_cachedHardware` if available and `bUseCache` is `true`. Falls back to `Hardware.GetAllDAS(id, null)`. Returns `null` if not found.
**Note**: Legacy logic for detecting hardware type changes (including `HardwareTypeChangedException`) is commented out and not active.
- **`public class HardwareTypeChangedException : Exception`**
Placeholder exception type for hardware type mismatch, but **not used** in current implementation.
---
### 3. Invariants
- **`HardwareChannel.ChannelNumber`** is always non-negative and corresponds to `ISO.HardwareChannel.ChannelIdx`.
- **`HardwareChannel.GetId()`** produces a 1-based channel index (i.e., `ChannelNumber + 1`).
- **`DASHardware.Channels`** is always sorted by `HardwareChannel.CompareTo()` after assignment (via setter).
- **`DASHardware.CompareTo()`** enforces a partial order where:
- Parent DAS sorts before its children.
- Siblings under the same parent sort by `PositionOnDistributor`.
- Otherwise, lexicographic by `SerialNumber`.
- **`DASSettings`** is a pure data container with no runtime validation or normalization. Values are assumed valid per database schema.
---
### 4. Dependencies
#### Internal Dependencies
- **`ISO.Hardware`** and **`ISO.HardwareChannel`**
Core data models representing raw database records. Used in `HardwareChannel` and `DASHardware` constructors.
- **`SensorData`**
Referenced in `HardwareChannel.Sensor`. Must be defined elsewhere in the codebase.
- **`Test.Module.Channel.Sensor.BridgeType`**
Referenced in `HardwareChannel.IsSupportedBridgeType()`.
- **`HardwareTypes`**
Enum used in `DASHardware.GetHardwareTypeEnum()`. Must be defined externally.
- **`DbTimeStampBase`**
Base class for `DASHardware`. Provides timestamping functionality.
#### External Dependencies
- **`System`** (core .NET types)
- **`DatabaseImport.Hardware`** (static class)
Used in `DASHardwareList.GetHardware()` via `Hardware.GetAllDAS(id, null)`. Must be defined elsewhere.
#### Dependencies on This Module
- Likely consumed by higher-level modules handling test setup, import, or configuration (e.g., `DatabaseImporter` entry points, UI layers).
---
### 5. Gotchas
- **Singleton caching is non-functional**: `GetList()` instantiates `_list`, but `_list.PopulateHardware()` is commented out. Similarly, `ReloadAll()` and caching logic in `GetHardware()` are commented out. As written, `DASHardwareList` does not cache hardware data beyond the initial instantiation.
- **`HardwareTypeChangedException` is unused**: The exception class exists but is never thrown—legacy logic for detecting hardware type changes is disabled.
- **`CompareTo()` returns `0` for `null`**: In `HardwareChannel.CompareTo()`, passing `null` returns `0`, which violates the `IComparable<T>` contract (should throw `ArgumentException` or return non-zero). This may cause unexpected behavior in sorting or collections.
- **`GetHardware()` in `DASHardwareList` silently returns `null`**: No exception or warning is raised if hardware is not found or if type changes occur (legacy checks are commented out).
- **Channel ID is 1-based in string but 0-based internally**: `HardwareChannel.GetId()` uses `ChannelNumber + 1`, which may cause off-by-one confusion if `ChannelNumber` is assumed to be 1-based elsewhere.
- **No validation in `DASSettings`**: All properties are auto-implemented with no guards. Invalid values (e.g., negative sample rate) are permitted.
- **`DASHardware.IsDummy()` is substring-based**: Relies on `"Dummy"` appearing anywhere in `SerialNumber`, which may yield false positives (e.g., `"Dummy123"` vs `"MyDummyDAS"`).
- **`DASHardwareList.GetHardware()` does not handle duplicate IDs**: If `Hardware.GetAllDAS()` returns multiple records, only the first is used—no conflict resolution or logging.
> **None identified from source alone** for additional gotchas beyond those explicitly visible in the code.

View File

@@ -0,0 +1,187 @@
---
source_files:
- DataPRO/Modules/DatabaseImporter/DatabaseImport/Classes/RegionsAndZones/Zone.cs
- DataPRO/Modules/DatabaseImporter/DatabaseImport/Classes/RegionsAndZones/RegionAdorner.cs
- DataPRO/Modules/DatabaseImporter/DatabaseImport/Classes/RegionsAndZones/Region.cs
generated_at: "2026-04-16T04:32:32.660920+00:00"
model: "Qwen/Qwen3-Coder-Next-FP8"
schema_version: 1
sha256: "cd00dc5bfe396de9"
---
# RegionsAndZones
## Documentation: Regions and Zones Module
### 1. Purpose
This module provides data structures and UI adorning capabilities for defining and managing spatial regions and zones within test object templates, primarily for ISO-compliant test configuration. It enables users to define named zones (e.g., anatomical or functional areas) containing one or more rectangular regions, each associated with metadata (e.g., direction, filter class, transducer location) used to generate ISO codes and filter available channels. The module bridges raw template data (`TemplateZone`, `TemplateRegion`) with WPF-based UI interaction (via `RegionAdorner`) and supports bidirectional conversion between in-memory objects and ISO database representations.
---
### 2. Public Interface
#### `Zone` class
- **`Zone(Zone copy, TestObjectTemplate template)`**
Copy constructor. Initializes a new `Zone` by copying properties (`Description`, `Image`, `Regions`) from an existing `Zone`, preserving `ISODllZone`, and preloading picture filenames.
- **`Zone(TemplateZone z, TestObjectTemplate template)`**
Constructor from ISO `TemplateZone`. Loads `Description`, `Image`, and `Regions` (converted to `Region` objects). Attempts to load and cache the zone picture as a `BitmapImage` if the file exists.
- **`string Name { get; set; }`**
Zone name, sourced from `ISODllZone.ZoneName`.
- **`string Description { get; set; }`**
Zone description, sourced from `ISODllZone.Description` (defaults to `""`).
- **`string Image { get; set; }`**
Filename of the zone picture, sourced from `ISODllZone.Picture`.
- **`TemplateZone ISODllZone { get; }`**
Read-only reference to the underlying ISO `TemplateZone` object.
- **`string[] AllPictures { get; }`**
Thread-safe array of filenames (not full paths) in the `ZonePictures` subdirectory of the app base directory. Populates on first access.
- **`void PopulateFilenamesIfNeeded()`**
Ensures `_fileNames` is populated (only if empty), using a lock to prevent concurrent population.
- **`int PictureIndex { get; set; }`**
Index into `AllPictures` for the currently selected picture. Setting triggers loading of the corresponding image into `PictureSource`. Index `-1` sets `PictureSource` to `null`.
- **`string GetPictureName()`**
Returns the filename of the currently selected picture (empty string if `PictureIndex < 0`).
- **`System.Windows.Media.ImageSource PictureSource { get; set; }`**
The WPF `ImageSource` for the currently selected picture.
- **`Region[] Regions { get; set; }`**
Array of `Region` objects in this zone. `get` returns a copy; `set` replaces the internal list.
#### `RegionAdorner` class
- **`RegionAdorner(UIElement adornedElement, TestObjectTemplate template, Contexts context)`**
Constructor. Creates a new adorner for an `Image` (or other `UIElement`). Initializes `_region`, sets up mouse event handlers, and configures visual path (AliceBlue stroke, 60% opacity, initially hidden).
- **`Point GetUpperLeft()`**
Returns the upper-left corner of `SelectRect`, adjusted for scaling between the adorned elements `RenderSize` and its `Source` dimensions.
- **`Point GetLowerRight()`**
Returns the lower-right corner of `SelectRect`, similarly scaled.
- **`bool IsNew { get; set; }`**
Controls visibility of region add/delete UI: `true``RegionAddVisibility=Visible`, `RegionDeleteVisibility=Hidden`; `false` → vice versa.
- **`Rect SelectRect { get; set; }`**
Bounding rectangle of the region in adorner coordinates. Setting it updates `MyRegion.RegionUpperLeft`/`RegionBottomRight` via `GetUpperLeft()`/`GetLowerRight()`.
- **`Region MyRegion { get; set; }`**
Reference to the associated `Region` object.
- **`Contexts Context { get; set; }`**
Context enum (`EditTestObject` or `EditTestObjectTemplate`) indicating usage mode.
- **`event RegionSelectedHandler OnRegionSelected`**
Raised on `MouseLeftButtonDown`.
- **`event EndSelectionHandler OnEndSelection`**
Raised on `MouseLeftButtonUp` (via `EndSelection()`).
- **`void DrawSelection(...)`**
Updates `SelectRect` to a rectangle defined by `AnchorPoint` and current mouse position (used during region creation).
- **`void MoveSelection(...)`**
Updates `SelectRect` by translating it by the mouse delta (used during region movement).
#### `Region` class
- **`Region(RegionAdorner adorner, TestObjectTemplate template)`**
Constructor for a *new* region. Sets default name/description, assigns `Template`, initializes `RegionChannels`/`RegionUIChannels` from template, and calls `DetermineAvailableISOSettings()`.
- **`Region(TestObjectTemplate template, TemplateRegion r)`**
Constructor from ISO `TemplateRegion`. Populates all properties from `r` (e.g., `RegionUpperLeft`, `RegionDirection`, `ISOCode`) and calls `FilterRegionChannels()` and `SetISOCode()`.
- **`string RegionName { get; set; }`**
User-facing region name.
- **`string RegionDescription { get; set; }`**
User-facing region description.
- **`Point RegionUpperLeft { get; set; }`**
Upper-left coordinate (WPF `Point`) of the region.
- **`Point RegionBottomRight { get; set; }`**
Lower-right coordinate (WPF `Point`) of the region.
- **`MMEDirections RegionDirection { get; set; }`**
Direction metadata (e.g., "Anterior", "Posterior"). Setting updates `_directionIndex` and calls `SetISOCode()`.
- **`MMEFilterClasses RegionFilterClass { get; set; }`**
Filter class metadata. Setting updates `_filterClassIndex` and calls `SetISOCode()`.
- **`MMEFineLocations1 RegionFineLocation1 { get; set; }`**
Fine location 1 metadata. Setting updates `_fineLocation1Index` and calls `SetISOCode()`.
- **`MMEFineLocations2 RegionFineLocation2 { get; set; }`**
Fine location 2 metadata. Setting updates `_fineLocation2Index` and calls `SetISOCode()`.
- **`MMEFineLocations3 RegionFineLocation3 { get; set; }`**
Fine location 3 metadata. Setting calls `SetISOCode()`.
- **`MMETransducerMainLocation RegionMainLocation { get; set; }`**
Main transducer location metadata. Setting updates `_mainLocationIndex` and calls `SetISOCode()`.
- **`MMEPhysicalDimensions RegionPhysicalDimension { get; set; }`**
Physical dimension metadata. Setting updates `_physicalDimensionIndex` and calls `SetISOCode()`.
- **`MMEPositions RegionPosition { get; set; }`**
Position metadata. Setting updates `_positionIndex` and calls `SetISOCode()`.
- **`MMETestObjects RegionTestObject { get; set; }`**
Test object type (e.g., "Breast", "Brain").
- **`TestObjectTemplate Template { get; set; }`**
Reference to the parent template. Setting triggers `DetermineAvailableISOSettings()`.
- **`string[] AllDirections { get; set; }`**
Available direction options (from template). `set` also populates `AllDirectionsStrings`.
- **`string[] AllDirectionsStrings { get; }`**
Human-readable direction names (e.g., `"Anterior"`).
- **`MMEFilterClasses[] AllFilterClasses { get; set; }`**
Available filter classes. `set` populates `AllFilterClassStrings`.
- **`string[] AllFilterClassStrings { get; }`**
Human-readable filter class names.
- **`MMEFineLocations1[] AllFineLocations1 { get; set; }`**
Available fine location 1 options. `set` populates `AllFineLocations1Strings`.
- **`string[] AllFineLocations1Strings { get; }`**
Human-readable fine location 1 names (`"??"` for null).
- **`MMEFineLocations2[] AllFineLocations2 { get; set; }`**
Available fine location 2 options. `set` populates `AllFineLocations2Strings`.
- **`string[] AllFineLocations2Strings { get; }`**
Human-readable fine location 2 names.
- **`int FineLocation2Index { get; set; }`**
Index into `AllFineLocations2`. Setting updates `RegionFineLocation2` and calls `FilterRegionChannels()`.
- **`MMEFineLocations3[] AllFineLocations3 { get; set; }`**
Available fine location 3 options. `set` populates `AllFineLocations3Strings`.
- **`string[] AllFineLocations3Strings { get; }`**
Human-readable fine location 3 names.
- **`MMETransducerMainLocation[] AllMainLocations { get; set; }`**
Available main location options. `set` populates `AllMainLocationsStrings`.
- **`string[] AllMainLocationsStrings { get; }`**
Human-readable main location names (`"????"` for null).
- **`MMEPhysicalDimensions[] AllPhysicalDimensions { get; set; }`**
Available physical dimension options. `set` populates `AllPhysicalDimensionStrings`.
- **`string[] AllPhysicalDimensionStrings { get; }`**
Human-readable physical dimension names (`"??"` for null).
- **`MMEPositions[] AllPositions { get; set; }`**
Available position options. `set` populates `AllPositionStrings`.
- **`string[] AllPositionStrings { get; }`**
Human-readable position names.
- **`string ISOCode { get; set; }`**
16-character ISO code string (e.g., `"BREAST?ANTERIOR???????"`). Generated by `SetISOCode()` from metadata fields.
- **`TestObjectTemplateChannel[] RegionChannels { get; set; }`**
List of channels *available* for this region (filtered by `RegionMainLocation`, `RegionDirection`, etc.). `set` triggers `DetermineAvailableISOSettings()`.
- **`TemplateChannelUI[] RegionUIChannels { get; set; }`**
UI-friendly channel list (mirrors `RegionChannels`).
- **`Visibility RegionAddVisibility { get; set; }`**
UI visibility flag for "add region" controls.
- **`Visibility RegionDeleteVisibility { get; set; }`**
UI visibility flag for "delete region" controls.
- **`TemplateRegion ToISORegion(TestObjectTemplate template, Zone zone, int number)`**
Converts this `Region` to a `TemplateRegion` for ISO export. Uses `RegionUpperLeft`/`RegionBottomRight` (converted to `System.Drawing.Point`), and maps null metadata to ISO defaults (`"?"`, `"??"`, `"????"`).
---
### 3. Invariants
- **Picture filename consistency**: `PictureIndex` must be in `[0, AllPictures.Length-1]` or `-1`. Setting `PictureIndex` to `-1` sets `PictureSource` to `null`.
- **ISO code format**: `ISOCode` is always 16 characters, with `"?"`, `"??"`, or `"????"` used for missing metadata fields.
- **Channel filtering**: `RegionChannels` is always a subset of `Template.TemplateAllChannels`, filtered by `RegionMainLocation`, `RegionDirection`, `RegionFilterClass`, `RegionFineLocation1/2/3`, `RegionPhysicalDimension`, and `RegionPosition`.
- **Metadata consistency**: `RegionDirection`, `RegionFilterClass`, etc., are always `null` or a valid object from their respective `All*` arrays.
- **Thread safety**: `_fileNames` population is guarded by a static lock (`MyLock`), and `AllPictures` always accesses `_fileNames` under this lock.
- **Region bounds**: `RegionUpperLeft` and `RegionBottomRight` are WPF `Point` coordinates relative to the adorned image.
---
### 4. Dependencies
- **Imports/References**:
- `System`, `System.Collections.Generic`, `System.Linq` (core .NET)
- `System.Windows`, `System.Windows.Controls`, `System.Windows.Documents`, `System.Windows.Input`, `System.Windows.Media`, `System.Windows.Shapes` (WPF)
- `System.ComponentModel` (`INotifyPropertyChanged`)
- `App` (from `Application.Current`), `IsoDb`, `TestObjectTemplate`, `TemplateZone`, `TemplateRegion`, `MMEDirections`, `MMEFilterClasses`, `MMEFineLocations1/2/3`, `MMETransducerMainLocation`, `MMEPhysicalDimensions`, `MMEPositions`, `MMETestObjects`, `TestObjectTemplateChannel`, `TemplateChannelUI` (all inferred from usage).
- **External resources**:
- `ZonePictures` subdirectory in `AppDomain.CurrentDomain.BaseDirectory` (for zone images).
- **Depended on by**:
- UI layers (e.g., WPF adorner layers using `RegionAdorner`).
- Database import/export logic (via `ToISORegion` and `Zone` constructors).
---
### 5. Gotchas
- **Picture loading failure**: If `Image` is set but the file does not exist at `ZonePictures/<Image>`, `PictureIndex` is set to `-1` silently (no exception thrown).
- **Scaling assumptions**: `GetUpperLeft()`/`GetLowerRight()` assume the adorned element is an `Image` with a `BitmapImage` source. Scaling logic may be incorrect if `Source` dimensions are unavailable or non-integer.
- **`FineLocation2Index` setter**: Only updates `RegionFineLocation2` and calls `FilterRegionChannels()`; does *not* update `_fineLocation2Index` directly (relies on `RegionFineLocation2` setter).
- **`RegionFineLocation3` setter**: Does not update `_fineLocation3Index` (empty `else` block), unlike other fine location properties.
- **`AllPictures` thread safety**: While `_fileNames` population is thread-safe, `AllPictures` returns a *snapshot* array. Concurrent modifications to `_fileNames` (e.g., via `PopulateFilenames()`) during enumeration could cause `IndexOutOfRangeException` if not for the lock (but `AllPictures` itself is safe).
- **`Region` constructor from `TemplateRegion`**: Uses `((App)Application.Current).IsoDb` for lookups. If `IsoDb` is not initialized, this will throw a `NullReferenceException`.
- **`RegionChannels`/`RegionUIChannels`**: The `set` accessor for `RegionChannels` calls `DetermineAvailableISOSettings()`, which may overwrite previously set values (e.g., `RegionDirection`, `RegionFilterClass`).
- **ISO code generation**: `SetISOCode()` uses `"?"` for null `RegionTestObject`, but `"???"` for null `RegionMainLocation` (inconsistent padding).

View File

@@ -0,0 +1,132 @@
---
source_files:
- DataPRO/Modules/DatabaseImporter/DatabaseImport/Classes/Sensors/ZeroMethod.cs
- DataPRO/Modules/DatabaseImporter/DatabaseImport/Classes/Sensors/InitialOffset.cs
generated_at: "2026-04-16T04:31:39.106411+00:00"
model: "Qwen/Qwen3-Coder-Next-FP8"
schema_version: 1
sha256: "f3a6aea6102ad03a"
---
# Sensors
## Documentation: Sensor Calibration Offset Classes
---
### 1. Purpose
This module defines two core data structures—`ZeroMethod` and `InitialOffset`—used to represent sensor calibration parameters within the database import pipeline. `ZeroMethod` encodes the *zeroing procedure* applied to a sensor (e.g., how and over what range the zero offset was determined), while `InitialOffset` encodes the *initial offset correction* applied to raw sensor data, supporting legacy single-value EU offsets as well as modern calibrated offsets specified in engineering units (EU) at a known millivolt (mV) input. Together, they enable accurate reconstruction of calibrated sensor readings from raw data during import.
---
### 2. Public Interface
#### `ZeroMethod` class
- **`public event PropertyChangedEventHandler PropertyChanged;`**
Implements `INotifyPropertyChanged`—raised when any property (`Method`, `Start`, `End`) is modified.
- **`protected bool SetProperty<T>(ref T storage, T value, string propertyName = null) → bool`**
Updates the backing field if the new value differs, raises `PropertyChanged`, and returns `true`; otherwise returns `false`. Used internally by property setters (not shown in source but implied by usage pattern).
- **`protected void OnPropertyChanged(string propertyName = null)`**
Raises the `PropertyChanged` event for the specified property name (or `null` for all properties).
- **`public ZeroMethodType Method { get; set; }`**
The zeroing method used (e.g., `ZeroMethodType.Average`, `ZeroMethodType.LinearFit`). *Type is referenced but not defined in this source file.*
- **`public double Start { get; set; }`**
Start index or time of the zeroing window/range.
- **`public double End { get; set; }`**
End index or time of the zeroing window/range.
- **`public ZeroMethod(ZeroMethodType zm, double start, double end)`**
Primary constructor: initializes `Method`, `Start`, and `End` directly.
- **`public ZeroMethod(string zm)`**
Deserialization constructor: parses a comma-separated string `zm` of the form `"Method,Start,End"` (e.g., `"Average,100.0,200.0"`), using `InvariantCulture`. Throws no exception on failure—invalid input silently leaves properties at default values.
- **`public ZeroMethod(ZeroMethod copy)`**
Copy constructor: performs deep copy of all fields (`Method`, `Start`, `End`).
#### `InitialOffset` class
- **`public enum Forms { None = 0, EU = 1, EUAtMV = 2 }`**
Indicates the format of the offset:
- `None`: No offset applied.
- `EU`: Single offset value in engineering units.
- `EUAtMV`: Offset specified as EU value measured at a known mV input (requires additional context to compute full offset).
- **`public Forms Form { get; set; }`**
Current format of this offset instance.
- **`public double EU { get; set; } = 0;`**
Engineering unit value. Interpretation depends on `Form`:
- `EU`: Direct offset to add to raw data.
- `EUAtMV`: EU value observed at `MV`.
- `None`: Unused.
- **`public double MV { get; set; } = 0;`**
Millivolt input at which `EU` was measured. Only meaningful when `Form == EUAtMV`.
- **`public InitialOffset(InitialOffset copy)`**
Copy constructor: copies `EU`, `MV`, and `Form`. Safely handles `null` input (no-op).
- **`public InitialOffset()`**
Default constructor: sets `Form = Forms.None`, `EU = 0`, `MV = 0`.
- **`public InitialOffset(double d)`**
Legacy constructor: creates an `EU`-form offset with `EU = d`, `MV = 0`, `Form = Forms.EU`.
- **`public void FromDbSerializeString(string input)`**
Deserializes from a database string (e.g., `"EUAtMV,12.5,45.3"` using `InvariantCulture` list separator).
- Throws `InvalidDataException` if fewer than 3 tokens or invalid `Forms` enum value.
- Throws `FormatException` if `EU` or `MV` token is not parseable as `double`.
- Sets `Form = Forms.None`, `EU = 0`, `MV = 0` on empty/whitespace input.
---
### 3. Invariants
- **`ZeroMethod`**
- `Start` and `End` may be in any order (no guarantee `Start ≤ End` is enforced).
- `Method` must be a valid `ZeroMethodType` enum value (enforced only if constructed via `ZeroMethodType` constructor; string constructor does not validate enum parsing).
- After deserialization via string constructor, if parsing fails (e.g., fewer than 3 tokens), properties retain their default values (`Method = default(ZeroMethodType)`, `Start = End = 0.0`).
- **`InitialOffset`**
- `Form == Forms.None``EU = 0` and `MV = 0` (enforced by constructors and `FromDbSerializeString` on empty input).
- `Form == Forms.EU``MV` is irrelevant (but not reset); `EU` holds the offset in EU.
- `Form == Forms.EUAtMV``EU` is the observed EU at `MV` (both must be non-zero in practice, though not enforced).
- `FromDbSerializeString` requires exactly 3 tokens; otherwise throws.
---
### 4. Dependencies
- **`ZeroMethod`**
- **Depends on**: `System.ComponentModel` (for `INotifyPropertyChanged`), `System` (for `Equals`, `Convert`, `Enum.Parse`, `PropertyChangedEventArgs`).
- **References**: `ZeroMethodType` (enum, not defined in this file—must be defined elsewhere in `DatabaseImport` namespace).
- **Used by**: Likely sensor configuration/import logic (inferred from namespace `DatabaseImport.Sensors`).
- **`InitialOffset`**
- **Depends on**: `System` (for `Enum.TryParse`, `double.TryParse`, `InvalidDataException`, `FormatException`).
- **References**: `Forms` nested enum (defined in this file).
- **Used by**: Sensor calibration/offset application logic during data import.
---
### 5. Gotchas
- **`ZeroMethod` string constructor is non-throwing on failure**: If the input string has fewer than 3 comma-separated tokens, the constructor silently leaves properties uninitialized (default values). Callers must validate or assume success only for well-formed inputs.
- **`ZeroMethodType` is undefined here**: Its possible values and semantics (e.g., `Average`, `LinearFit`) are not documented in this source—must be referenced externally.
- **`InitialOffset.EU` meaning is context-dependent**: In `EUAtMV` mode, `EU` is *not* the final offset—it is the EU value *at* `MV`. The actual offset calculation requires additional calibration data (e.g., sensor sensitivity), which is not provided in this class.
- **`FromDbSerializeString` uses list separator from `InvariantCulture`**: While `InvariantCulture` is used for number parsing, the list separator (`TextInfo.ListSeparator`) is *not* guaranteed to be a comma—it is culture-specific (though `InvariantCulture`s is `,`). This may cause issues if the DB string uses a different delimiter.
- **No validation of `Start`/`End` ranges**: `ZeroMethod` allows `Start > End` or negative values without error.
- **`InitialOffset` copy constructor does not throw on `null`**: It silently returns with default values if `copy == null`.

View File

@@ -0,0 +1,97 @@
---
source_files:
- DataPRO/Modules/DatabaseImporter/DatabaseImport/Classes/TestMetaData/LabratoryDetails.cs
- DataPRO/Modules/DatabaseImporter/DatabaseImport/Classes/TestMetaData/CustomerDetails.cs
- DataPRO/Modules/DatabaseImporter/DatabaseImport/Classes/TestMetaData/TestEngineerDetails.cs
generated_at: "2026-04-16T04:31:55.181756+00:00"
model: "Qwen/Qwen3-Coder-Next-FP8"
schema_version: 1
sha256: "6aa688c6b66d13f9"
---
# TestMetaData
## Documentation: Test Metadata Wrappers Module
---
### 1. Purpose
This module provides thin managed wrappers around low-level `ISO.*` data entities (`LabratoryDetails`, `CustomerDetails`, `TestEngineerDetails`) to support database import operations within the DataPRO system. It exposes simplified, namespaced access to metadata entities used during test configuration and reporting, including CRUD-like operations (e.g., `DeleteAll`) and instance management (e.g., singleton list for engineers). The module exists to decouple the import pipeline from direct dependencies on the `ISO` layer, enabling testability and future flexibility in metadata handling.
---
### 2. Public Interface
#### `LabratoryDetails`
- **`public string Name { get; set; }`**
Gets or sets the laboratory name by delegating to the underlying `_lab.Name` field.
#### `LabratoryDetailsList`
- **`public static void DeleteAll()`**
Invokes `ISO.LabratoryDetails.DeleteLabratoryDetails()` to remove all laboratory detail records from persistent storage.
#### `CustomerDetails`
- **`public string Name { get; set; }`**
Gets or sets the customer name by delegating to `_customerDetails.Name`.
#### `CustomerDetailsList`
- **`public static void DeleteAll()`**
Invokes `ISO.CustomerDetails.DeleteCustomerDetails()` to delete all customer detail records.
#### `TestEngineerDetails`
- **`public TestEngineerDetails()`**
Default constructor initializes `_testEngineerDetails` to a new `ISO.TestEngineerDetails` instance with `Name` set to `"(none)"`.
- **`public TestEngineerDetails(ISO.TestEngineerDetails testEngineerDetails)`**
Copy constructor: initializes `_testEngineerDetails` by constructing a new `ISO.TestEngineerDetails` from the provided instance.
- **`public string Name { get; set; }`**
Gets or sets the engineers name via `_testEngineerDetails.Name`.
#### `TestEngineerDetailsList`
- **`public static TestEngineerDetailsList TestEngineerList { get; }`**
Static singleton accessor for the single `TestEngineerDetailsList` instance.
- **`public void ReloadAll()`**
Thread-safely repopulates the internal `_testEngineers` dictionary by calling `GetAllTestEngineers()` and caching entries keyed by `Name`.
- **`public static void DeleteAll()`**
Clears the in-memory `_testEngineers` dictionary and invokes `ISO.TestEngineerDetails.DeleteAllTestEngineerDetails()` to purge persisted records.
- **`private TestEngineerDetails[] GetAllTestEngineers()`**
Returns an array of `TestEngineerDetails` objects: first a sentinel `"(none)"` entry (via default constructor), then one entry per record returned by `ISO.TestEngineerDetails.GetAllTestEngineerDetails()`.
> **Note**: `GetAllTestEngineers()` is `private`, but used internally by `ReloadAll()` and implicitly by the `PopulateEngineers()` method.
---
### 3. Invariants
- **`Name` is the only mutable property** exposed via the public interface for all three detail classes (`LabratoryDetails`, `CustomerDetails`, `TestEngineerDetails`).
- **`TestEngineerDetailsList` is a singleton** — only one instance exists (`_testEngineerList`), accessed via `TestEngineerList`.
- **Thread safety for `ReloadAll()`** is enforced via `lock (_testEngineerLock)` around `PopulateEngineers()`.
- **`"(none)"` sentinel entry** is always the first element in the list returned by `GetAllTestEngineers()`.
- **Duplicate names are prevented** in `_testEngineers` dictionary: `PopulateEngineers()` only adds an entry if `!_testEngineers.ContainsKey(t.Name)`.
- **`_testEngineers` is nullified on `DeleteAll()`**, forcing a full reload on next access.
---
### 4. Dependencies
#### Dependencies *of* this module:
- `ISO.LabratoryDetails` (type with static methods `DeleteLabratoryDetails()`)
- `ISO.CustomerDetails` (type with static method `DeleteCustomerDetails()`)
- `ISO.TestEngineerDetails` (type with static methods `GetAllTestEngineerDetails()`, `DeleteAllTestEngineerDetails()`, and constructors)
- `System.Collections.Generic.Dictionary<string, TestEngineerDetails>` (used in `TestEngineerDetailsList`)
#### Dependencies *on* this module:
- Not explicitly stated in source, but given the naming and structure, this module is likely consumed by:
- `DatabaseImport` pipeline components (e.g., importers that populate or validate test metadata).
- UI or service layers that require test metadata (e.g., selecting engineer or lab for a test run).
---
### 5. Gotchas
- **Typo in class names**: All classes use `Labratory` (misspelled) instead of `Laboratory`. This is preserved from the underlying `ISO` layer and must be maintained for compatibility.
- **`TestEngineerDetails` is *not* thread-safe for concurrent mutation** — while `ReloadAll()` is synchronized, direct access to `_testEngineerDetails.Name` (via `Name` property) is not guarded.
- **`_testEngineerDetails` field in `TestEngineerDetails` is *not* `readonly`**, unlike the others — implying potential reassignment (though not observed in current code).
- **`GetAllTestEngineers()` silently ignores duplicate names** — only the first occurrence is retained in `_testEngineers`.
- **No validation on `Name` values** — empty strings or duplicates are allowed at the wrapper level (though duplicates are deduped in `TestEngineerDetailsList`).
- **`CustomerDetailsList` and `LabratoryDetailsList` have no instance members beyond `DeleteAll()`** — they are effectively static namespaces.
- **`TestEngineerDetailsList` caches in-memory state** — changes made directly to `ISO.*` entities outside this module may not be reflected until `ReloadAll()` is called.
None identified beyond those above.

View File

@@ -0,0 +1,263 @@
---
source_files:
- DataPRO/Modules/DatabaseImporter/DatabaseImport/Classes/TestObject/TemplateChannelUI.cs
- DataPRO/Modules/DatabaseImporter/DatabaseImport/Classes/TestObject/TestObjectTemplateCollection.cs
- DataPRO/Modules/DatabaseImporter/DatabaseImport/Classes/TestObject/TestObjectList.cs
- DataPRO/Modules/DatabaseImporter/DatabaseImport/Classes/TestObject/TestTestObject.cs
- DataPRO/Modules/DatabaseImporter/DatabaseImport/Classes/TestObject/TestObjectTemplate.cs
- DataPRO/Modules/DatabaseImporter/DatabaseImport/Classes/TestObject/TestObject.cs
generated_at: "2026-04-16T04:33:08.085586+00:00"
model: "Qwen/Qwen3-Coder-Next-FP8"
schema_version: 1
sha256: "d8ddaddf5f4cb968"
---
# TestObject
**Documentation Page: Test Object & Template Management Module**
---
### 1. **Purpose**
This module provides in-memory wrappers and management abstractions for test object and template data originating from the `ISO.TestObject` and `ISO.TestObjectTemplate` types in the underlying `ISO` namespace. It serves as the data-access and UI-binding layer for test object configurations, templates, and associated channel/sensor metadata within the `DatabaseImporter` module. Its primary role is to decouple UI and business logic from raw database structures (`ISO13499FileDb`) while supporting both ISO-compliant and non-ISO (custom) test object types, and enabling template reuse, inheritance, and zone-based channel organization.
---
### 2. **Public Interface**
#### `TemplateChannelUI`
- **`TemplateChannelUI(TestObjectTemplateChannel channel)`**
Constructor wrapping a `TestObjectTemplateChannel`. No public properties or methods exposed beyond the internal `_channel` field.
#### `TestObjectTemplateCollection`
- **`static TestObjectTemplateCollection TemplateCollection { get; }`**
Singleton accessor for the global collection of test object templates.
- **`TestObjectTemplate GetTemplate(string templateId)`**
Retrieves a `TestObjectTemplate` by ID from the database (`IsoDb`) and wraps it in a `TestObjectTemplate` instance. Returns `null` if not found.
- **`TestObjectTemplate SysBuiltTestObjectTemplate { get; }`**
Returns the system-built template (currently uninitialized in source; `_sysBuiltTestObjectTemplate` is `null`).
- **`void ReloadAll(bool loadSubComponents)`**
Stubbed out (all logic commented out). Intended to refresh templates and subcomponents.
- **`static void DeleteAll()`**
Deletes all templates in the database via `ISO.TestObjectTemplate.DeleteAllTemplates()`, then resets the singleton collection.
#### `TestObjectList`
- **`static TestObjectList TestObjectsList { get; }`**
Singleton accessor for the main list of test objects (non-system-built).
- **`static TestObjectList AddedGroupsList { get; }`**
Singleton accessor for a separate list used for user-added groups (system-built).
- **`void ReloadAll(bool bLoadSubComponents)`**
Stubbed out (empty body). Intended to reload all test objects and subcomponents.
- **`TestObject GetTestObject(string serialNumber, bool bSysBuilt)`**
Retrieves a test object by serial number and `bSysBuilt` flag. Returns `null` if not found.
- **`TestObject GetTestObject(string serialNumber)`**
Convenience overload: tries non-system-built first, then system-built.
- **`TestObject GetAddedGroup(string serialNumber)`**
Alias for `GetTestObject(serialNumber, true)`.
- **`void DeleteAll()`**
Deletes all test objects in the database via `ISO.TestObject.DeleteAllTestObjects()`.
#### `TestTestObject`
- **`TestTestObject(TestObject obj)`**
Constructor wrapping a `TestObject`.
- **`MMEPositions Position { get; set; }`**
Gets/sets the group position. Setting to `UserSetKey` (`"@"`) hides the combo box and shows the position button; otherwise, vice versa. Also propagates position to all required sensors.
- **`string ChannelDefaultsKey { get; }`**
Constant `"#"` representing the default channel position.
- **`string UserSetKey { get; }`**
Constant `"@"` representing a user-defined position.
- **`Visibility GroupPositionComboBoxVisible { get; set; }`**
Controls visibility of the position combo box. Collapsed if `ISO13499` support is disabled (`NO_ISO`).
- **`Visibility GroupPositionButtonVisible { get; set; }`**
Controls visibility of the position button. Collapsed if `ISO13499` support is disabled.
- **`MMETestObjects TestObject { get; set; }`**
Gets/sets the test object for the group. Setting it propagates the change to all required sensors.
- **`int ChannelTypesIndex { get; set; }`**
Index into a list of channel types (used for UI binding).
- **`int ExcitationWarmupTimeMS { get; set; }`**
Excitation warm-up time in milliseconds.
- **`double TargetSampleRate { get; set; }`**
Target sample rate.
- **`double PreTriggerSeconds { get; set; }`**
Pre-trigger duration in seconds.
- **`double PostTriggerSeconds { get; set; }`**
Post-trigger duration in seconds.
- **`MMEPositions[] AvailablePositions { get; }`**
Returns available positions from `IsoDb`.
- **`MMEPositions[] AvailableGroupPositions { get; }`**
Returns combined list: `ChannelDefaultsKey` position first, then `AvailablePositions`.
- **`void SetTestObject(string s)`**
Sets `_testObject` and raises `TestObject` property change.
- **`void SetPosition(string s)`**
Sets `_position` and raises `Position` change; updates UI visibility flags.
#### `TestObjectTemplate`
- **`TestObjectTemplate()`**
Default constructor. Initializes `TestObject` based on `SerializedSettings.ISOSupportLevel`. For `NO_ISO`, creates a non-ISO test object and sets channel type to `Constants.NON_ISO_TESTOBJECT_CHANNEL_TYPE`.
- **`TestObjectTemplate(ISO.TestObjectTemplate template, ref ISO13499FileDb db)`**
Wraps an `ISO.TestObjectTemplate` instance.
- **`TestObjectTemplate(TestObjectTemplate copy, ref ISO13499FileDb db)`**
Copy constructor.
- **`string TemplateName { get; set; }`**
Template name.
- **`string TemplateDescription { get; set; }`**
Template description.
- **`string TemplateParent { get; set; }`**
Parent template name (for inheritance).
- **`bool SysBuilt { get; set; }`**
Whether the template is system-built.
- **`bool Embedded { get; set; }`**
Whether the template is embedded.
- **`string OriginalTemplateName { get; set; }`**
Original template name (preserved for tracking).
- **`MMETestObjects TestObject { get; set; }`**
Test object associated with the template.
- **`string TestObjectType { get; set; }`**
Test object type (e.g., channel type).
- **`int TestObjectTypeIndex { get; set; }`**
Index into `AvailableTestObjectTypes`.
- **`string[] AvailableTestObjectTypes { get; set; }`**
List of test object types compatible with current `TestObject`.
- **`TestObjectTemplateChannel[] RequiredChannels { get; }`**
List of required channels for the template.
- **`TestObjectTemplateChannel[] TemplateAllChannels { get; set; }`**
All channels (required + optional), sorted by `DisplayOrder`.
- **`TemplateChannelUI[] TemplateAllUIChannels { get; set; }`**
UI wrapper list for `TemplateAllChannels`.
- **`Zone[] TemplateZones { get; set; }`**
List of zones defined in the template.
- **`int CurrentZoneIndex { get; set; }`**
Index of the currently selected zone. Updates `CurrentZone`.
- **`Zone CurrentZone { get; set; }`**
Currently selected zone. Controls `AreZoneControlsEnabled`.
- **`bool AreZoneControlsEnabled { get; }`**
`true` if `CurrentZone` is non-null.
- **`DateTime LastModified { get; set; }`**
Last modification timestamp.
- **`string LastModifiedBy { get; set; }`**
User who last modified the template.
- **`static MMETestObjects GetNonISOTestObject()`**
Retrieves or creates a non-ISO test object (name: `Constants.NON_ISO_TESTOBJECT_NAME`). Tries letters AZ, then digits 09.
- **`ISO.TestObjectTemplate ToISOTestObjectTemplate()`**
Converts the wrapper to an `ISO.TestObjectTemplate` instance for persistence.
#### `TestObject`
- **`TestObject()`**
Default constructor. Initializes empty `_isoTestObject` and `Template`.
- **`TestObject(ISO.TestObject to, bool sysBuilt)`**
Wraps an `ISO.TestObject`. Initializes `Template` and hardware.
- **`TestObject(TestObject copy)`**
Copy constructor.
- **`string SerialNumber { get; set; }`**
Unique serial number.
- **`string SerialNumberConverted { get; set; }`**
Human-readable serial number (e.g., stripped prefix for system-built).
- **`string DisplaySerialNumber { get; set; }`**
Serial number used for display. Setting it updates `SerialNumber`, `OriginalSerialNumber`, and template name.
- **`string TestSetupName { get; set; }`**
Name prefix for user-added groups.
- **`string TestObjectType { get; set; }`**
Type of the test object (from template).
- **`string ParentObject { get; set; }`**
Parent test object (for hierarchy).
- **`bool SysBuilt { get; set; }`**
Whether the test object is system-built.
- **`TestObjectTemplate Template { get; set; }`**
Template associated with the test object.
- **`void SetTemplateDontResetISOObject(TestObjectTemplate value)`**
Sets template without resetting underlying `ISO.TestObject.Template`.
- **`string[] ZoneNames { get; set; }`**
Names of zones in the current template.
- **`string TemplateType { get; }`**
`Template.TestObjectType`, or `""` if no template.
- **`DASHardware[] Hardware { get; }`**
List of attached hardware devices, sorted.
- **`void SetHardwareFromISO()`**
Refreshes `_hardware` from `ISO.TestObject.HardwareIds`.
- **`void SetHardware(DASHardware[] hardware)`**
Sets hardware list in memory and updates `ISO.TestObject.HardwareIds`.
- **`void AddHardware(DASHardware hardware)`**
Adds hardware, handling dummy hardware naming collisions.
- **`bool ContainsHardware(DASHardware h)`**
Checks if hardware is attached.
- **`SensorData GetSensor(string channelId, string serialNumber, string alternateChannelId = null)`**
Retrieves sensor settings for a given channel and serial number. Applies ISO channel defaults and overrides from `ISO.TestObject.SensorSettings`.
- **`void SetSensor(string channelName, SensorData sensor)`**
Persists sensor settings to the underlying `ISO.TestObject`.
- **`ISO.TestObject GetISOTestObject()`**
Returns the underlying `ISO.TestObject` instance.
- **`void RefreshHardware()`**
Alias for `SetHardwareFromISO()`.
- **`string SerialNumberOrOriginalSerialNumber { get; }`**
Returns `OriginalSerialNumber` if embedded, else `SerialNumberConverted` or `SerialNumber`.
- **`SerializedSettings.ISOSupportLevels GetObjectISOLevel()`**
Returns `NO_ISO` if template type contains `NON_ISO_TESTOBJECT_CHANNEL_TYPE` or `NONISOCHANNELTYPE`, else `ISO_ONLY`.
---
### 3. **Invariants**
- **Singleton consistency**:
`TestObjectTemplateCollection.TemplateCollection` and `TestObjectList.TestObjectsList`/`AddedGroupsList` are lazily initialized singletons. Thread-safety is ensured via `volatile` and `lock(MyLock)` (in `TestObjectList`).
- **Template ↔ ISO mapping**:
Every `TestObjectTemplate` wraps exactly one `ISO.TestObjectTemplate`, and vice versa. The `ToISOTestObjectTemplate()` method must produce a valid `ISO.TestObjectTemplate` with all fields populated.
- **Sensor settings precedence**:
`TestObject.GetSensor()` applies ISO channel defaults *first*, then overlays `SensorSettings` from `ISO.TestObject`. If `FilterClassIso` is `"?"`, it is normalized to `"P"`.
- **Channel ordering**:
`TemplateAllChannels` is sorted by `DisplayOrder` (via `CompareChannels`).
- **Non-ISO test object uniqueness**:
`GetNonISOTestObject()` ensures a single non-ISO test object exists, using letters AZ first, then digits 09 if needed.
- **Template type consistency**:
`TestObject.TemplateType` is derived from `Template.TestObjectType`. If `Template` is `null`, it returns `""`.
---
### 4. **Dependencies**
#### **Internal Dependencies**
- `ISO.TestObject`, `ISO.TestObjectTemplate`, `ISO13499FileDb` (from `ISO` namespace).
- `App.IsoDb` (accessed via `Application.Current as App`).
- `DASHardware`, `DASHardwareList`, `SensorData`, `SensorsCollection.SensorsList`.
- `MMEPositions`, `MMETestObjects`, `MMEPossibleChannels`.
- `SerializedSettings`, `Constants` (e.g., `NON_ISO_TESTOBJECT_NAME`, `NON_ISO_TESTOBJECT_CHANNEL_TYPE`).
- `Zone`, `TemplateZone`, `TestObjectTemplateChannel`.
- `DbTimeStampBase` (base class for `TestObject`).
- `Tags` enum (used for property change notifications).
#### **External Dependencies**
- `System.Windows` (for `Visibility`, `Application`, `Guid.NewGuid()`).
- `System.Globalization` (for `CultureInfo.InvariantCulture` parsing).
- `System.Linq` (for LINQ queries in `GetNonISOTestObject()` and `TestObjectTemplate` initialization).
#### **Dependents**
- UI layers (e.g., WPF views binding to `TemplateChannelUI`, `TestObject`, `TestTestObject`).
- Import/export logic (e.g., TDM imports calling `DeleteAll()` on `TestObjectList` or `TestObjectTemplateCollection`).
- Template management UI (e.g., zone editing, channel assignment).
---
### 5. **Gotchas**
- **`SysBuiltTestObjectTemplate` is uninitialized**:
`_sysBuiltTestObjectTemplate` is declared but never assigned. `SysBuiltTestObjectTemplate` will always return `null`.
- **`ReloadAll` stubbed out**:
Both `TestObjectTemplateCollection.ReloadAll()` and `TestObjectList.ReloadAll()` have no implementation (all logic commented out). This may cause stale data if callers assume reload occurs.
- **`TemplateAllChannels` setter triggers side effects**:
Setting `TemplateAllChannels` in `TestObjectTemplate` instantiates `TemplateAllUIChannels` and updates `_channels` and `_availableTestObjectTypes`. This may cause unexpected behavior if called multiple times.
- **`TestObject.GetSensor()` uses ambiguous channel lookup**:
The method tries `channelId` first, then `alternateChannelId` (often `channelId` again). The comment notes historical inconsistency between channel name vs. ID usage.
- **`DisplaySerialNumber` setter mutates multiple fields**:
Setting `DisplaySerialNumber` on a user-added group updates `SerialNumber`, `SerialNumberConverted`, `OriginalSerialNumber`, and template names. This may cause unintended side effects if used on system-built objects.
- **`TestTestObject.Position` setter propagates to sensors**:
Changing `Position` updates *all* required sensors positions, but only if `Position != UserSetKey`. This may be unexpected if the UI allows switching to `UserSetKey` mid-edit.
- **`GetNonISOTestObject()` may throw**:
If no available letters/digits remain, `GetNonISOTestObject()` throws `NotSupportedException`. No fallback or logging is present.
- **`TemplateType` may be `"?"`**:
`TestObject.TestObjectType` defaults to `"?"`, and `TemplateType` inherits this. Consumers must handle this sentinel value.
- **No explicit `INotifyPropertyChanged` implementation visible**:
Classes reference `SetProperty` and `OnPropertyChanged`, but no base class (`BasePropertyChanged`) is included in the source. Behavior assumes a working implementation elsewhere.
---
*End of Documentation.*

View File

@@ -0,0 +1,124 @@
---
source_files:
- DataPRO/Modules/DatabaseImporter/DatabaseImport/Classes/TestTemplate/ICachedContainer.cs
- DataPRO/Modules/DatabaseImporter/DatabaseImport/Classes/TestTemplate/HardwareInclusionInstruction.cs
- DataPRO/Modules/DatabaseImporter/DatabaseImport/Classes/TestTemplate/TestTemplateLite.cs
- DataPRO/Modules/DatabaseImporter/DatabaseImport/Classes/TestTemplate/RegionOfInterest.cs
- DataPRO/Modules/DatabaseImporter/DatabaseImport/Classes/TestTemplate/TestTemplateList.cs
generated_at: "2026-04-16T04:32:24.918567+00:00"
model: "Qwen/Qwen3-Coder-Next-FP8"
schema_version: 1
sha256: "d58cccdbb5baf57a"
---
# Documentation: TestTemplate Module
## 1. Purpose
This module provides foundational data structures and utilities for representing and manipulating test templates within the DatabaseImporter subsystem. It defines lightweight and extensible models for test configurations (e.g., `TestTemplateLite`), hardware inclusion/exclusion rules (`HardwareInclusionInstruction`), time-domain regions of interest (`RegionOfInterest`), and a caching interface (`ICachedContainer`) for hardware lookups. It also includes helper methods in `TestTemplateList` for serializing/deserializing sensor settings and managing system-wide test template state. The module exists to decouple test template representation from full database persistence, enabling in-memory manipulation, validation, and deferred commit—particularly useful during test import workflows where DAS hardware may be excluded via group-based rules (e.g., for "DASless" tests).
## 2. Public Interface
### `ICachedContainer` (Interface)
- **`DASHardware GetCachedHardware(string serialNumber)`**
Retrieves a cached `DASHardware` instance by serial number. Returns `null` if not found (behavior inferred from usage context).
- **`IISOHardware[] GetAllCachedHardware()`**
Returns all cached hardware items as an array of `IISOHardware`.
### `HardwareInclusionInstruction` (Class)
- **Constructor `HardwareInclusionInstruction(string hardwareId, Actions action)`**
Initializes a new instruction to add or remove hardware from a test, overriding group-derived inclusion.
- `hardwareId`: Identifier for the hardware item (e.g., serial number).
- `action`: Either `Actions.Remove` (exclude despite group membership) or `Actions.Add` (include despite absence from groups).
- **Properties**
- `HardwareId`: Read-only string identifier.
- `Action`: Read-only `Actions` enum value (`Remove` or `Add`).
### `TestTemplateLite` (Class)
- **Properties**
- `Name`: `string` — Name of the test template.
- `Description`: `string` — Optional description (defaults to `""`).
- `RecordingMode`: `RecordingModes` — Determines pre-trigger behavior.
- `PreTriggerSeconds`: `double`
- Returns `0` for `Recorder` or `HybridRecorder` modes.
- Returns stored `_preTriggerSeconds` for `CircularBuffer` or other modes.
- Setter updates `_preTriggerSeconds` unconditionally.
- `ErrorMessage`: `string` — Raw error message (defaults to `string.Empty`).
- `CompletionErrorMessage`: `string` — Truncated error message (max 250 chars).
- `PostTriggerSeconds`: `double` — Post-trigger duration.
- `LastModified`: `DateTime` — Timestamp of last modification.
- `LastModifiedBy`: `string` — User who last modified the template.
- `IsComplete`: `bool` — Indicates if the template is fully configured.
### `RegionOfInterest` (Class)
- **Constructors**
- `RegionOfInterest()` — Default: `Suffix=""`, `Start=-1`, `End=1`, `IsEnabled=true`, `IsDefault=true`.
- `RegionOfInterest(bool isDefault)` — Sets `IsDefault`.
- `RegionOfInterest(string suffix, bool isDefault, double start, double end)` — Full initialization.
- **Properties**
- `Suffix`: `string` — Auto-normalized to start with `_` (e.g., `"foo"``"_foo"`; `""` remains `""`).
- `Start`: `double` — Clamped to `[PreTrigger, End - 0.01]`.
- `End`: `double` — Clamped to `[Start + 0.01, PostTrigger]`.
- `PreTrigger`: `double` — Setter updates `Start` if `Start < PreTrigger`.
- `PostTrigger`: `double` — Setter updates `End` if `End > PostTrigger`.
- `IsEnabled`: `bool` — Default `true`.
- `IsDefault`: `bool` — Read-only; set only via constructor.
- **Events**
- `PropertyChanged`: Implements `INotifyPropertyChanged` for UI binding.
### `TestTemplateList` (Class)
- **Static Properties**
- `TestTemplatesList`: Singleton instance (thread-safe via `lock`).
- **Instance Properties**
- `TemporaryTemplate`: `TestTemplate` — Holds a template in memory without DB persistence.
- **Static Methods**
- `GetSensorFromSettings(string settings, string serial, Dictionary<string, SensorData> lookup)`:
Parses `settings` (comma-separated `key=value` pairs) to populate a `SensorData` object. Falls back to `SensorsCollection.SensorsList.GetSensorBySerialNumber(serial)` if `lookup` is `null` or missing `serial`. Returns `null` if `serial` is null/empty or no `SensorData` found.
- `GetSensorFromSettings(string settings, string serial)`: Overload with `lookup=null`.
- `GetSensorSettings(SensorData sd)`: Serializes `sd` into a comma-separated `key=value` string. Only includes settings with non-default values (e.g., omits `Delay` if `DelayMS` is `0`).
- `SysBuiltObject(string serialNumber)`: Calls stored procedure `sp_TestObjectsGet` to determine if `serialNumber` corresponds to a system-built test object. Returns `bool`.
- `ConvertToDictionary(DataTable dt, ref Dictionary<string, List<Dictionary<string, object>>> lookup, string key)`: Populates `lookup` by grouping `dt` rows on `key`. Each row becomes a `Dictionary<string, object>` of column values.
- **Instance Methods**
- `Reload()`: Refreshes all related data collections (ISO DB, sensors, DAS hardware, etc.) and calls `Load()` (currently a no-op).
- `DeleteAll()`: Executes stored procedure `sp_TestSetupsDeleteAll` to clear all test setups. Handles output parameters for error info (logging suppressed in source).
## 3. Invariants
- **`RegionOfInterest`**:
- `Start < End` always holds (enforced via setter clamping).
- `Start ≥ PreTrigger` and `End ≤ PostTrigger` always hold (enforced via setter clamping and `PreTrigger`/`PostTrigger` setters).
- `Suffix` is normalized to start with `_` if non-empty and non-whitespace.
- **`TestTemplateLite`**:
- `PreTriggerSeconds` is `0` for `Recorder`/`HybridRecorder` modes regardless of stored `_preTriggerSeconds`.
- `CompletionErrorMessage` truncates `ErrorMessage` to 250 characters if longer.
- **`HardwareInclusionInstruction`**:
- `HardwareId` is never `null` or empty (enforced by constructor).
- **`TestTemplateList`**:
- `TestTemplatesList` is a singleton (lazy-initialized under lock).
- `GetSensorFromSettings` returns `null` if `serial` is null/empty or no matching sensor exists.
## 4. Dependencies
### Internal Dependencies
- **`DatabaseImport` namespace**: All types are internal to this module.
- **`ISO.TestObject.SensorSettings`**: Used in `GetSensorFromSettings`/`GetSensorSettings` (enum values drive parsing/serialization).
- **`SensorData`**: Core data type for sensor configuration (used in `GetSensorFromSettings`, `GetSensorSettings`).
- **`DASHardware`, `IISOHardware`**: Referenced in `ICachedContainer` (concrete types not defined in provided sources).
- **`RecordingModes`**: Enum used in `TestTemplateLite.PreTriggerSeconds` (concrete definition not provided).
- **`DigitalOutputModes`, `SquibFireMode`, `DigitalInputModes`**: Referenced in `GetSensorFromSettings` (enum definitions not provided).
- **Database Abstraction**:
- `DbOperations`, `DbOperationsEnum.StoredProcedure`, `SqlDbType`, `CommandType`, `SqlParameter`, `DataRow`, `DataTable` (from `System.Data`).
- Stored procedures: `sp_TestObjectsGet`, `sp_TestSetupsDeleteAll`.
- **UI Framework**: `Application.Current` (WPF `App` type) in `Reload()`.
- **Singleton Collections**: `SensorsCollection.SensorsList`, `CustomChannelList.List`, `SensorCalibrationList`, `DASHardwareList`, `TestEngineerDetailsList.TestEngineerList`, `TestObjectTemplateCollection.TemplateCollection`, `TestObjectList.TestObjectsList` (referenced in `Reload()`).
### External Dependencies
- `System`, `System.ComponentModel`, `System.Data`, `System.Data.SqlClient`, `System.Linq`, `System.Text`, `System.Windows` (WPF).
## 5. Gotchas
- **`PreTriggerSeconds` behavior**: For `Recorder`/`HybridRecorder` modes, `PreTriggerSeconds` always returns `0`, ignoring the stored `_preTriggerSeconds` value. This may cause confusion if persisted/serialized values are expected to be preserved.
- **`Suffix` normalization**: Non-empty suffixes are auto-prefixed with `_` (e.g., `"foo"``"_foo"`). Empty/whitespace suffixes remain unchanged.
- **`GetSensorFromSettings` fallback**: If `lookup` is provided but lacks `serial`, it falls back to `SensorsCollection.SensorsList.GetSensorBySerialNumber(serial)`. This dual-source lookup may mask missing data in `lookup`.
- **`GetSensorSettings` omits default values**: Settings with default/zero values (e.g., `DelayMS=0`) are excluded from the serialized string. This may cause deserialization to use defaults instead of explicit values if the caller expects all settings to be present.
- **`SysBuiltObject` return value**: Returns `false` if the stored procedure returns no rows, but does not distinguish between "not found" and "error occurred" (error handling logs are suppressed).
- **`DeleteAll` error handling**: Output parameters (`@ErrorSeverity`, `@ErrorState`, `@ErrorMessage`) are captured but not logged or propagated (commented-out logging suggests intentional suppression).
- **`TestTemplateLite` is incomplete**: The class is explicitly labeled a "lightweight" version and omits many fields of a full `TestTemplate`. Its `IsComplete` flag may not reflect full validation state.
- **`RegionOfInterest` clamping is cascading**: Setting `PreTrigger` may trigger `Start` updates (via `Start = PreTrigger`), and setting `Start` may trigger `End` updates (via `End = Start + 0.01`). This can cause unexpected side effects in UI bindings.
- **No documentation for `TestTemplate`**: `TemporaryTemplate` is typed as `TestTemplate`, but this class is not defined in the provided sources. Its structure and relationship to `TestTemplateLite` are unclear.

View File

@@ -0,0 +1,115 @@
---
source_files:
- DataPRO/Modules/DatabaseImporter/DatabaseImport/Controls/SensorsAndModels/ImportSensorsImportControl.cs
generated_at: "2026-04-16T04:33:13.762411+00:00"
model: "Qwen/Qwen3-Coder-Next-FP8"
schema_version: 1
sha256: "f5ef3c2722125dc9"
---
# SensorsAndModels
## Documentation: `ImportSensorsImportControl` Module
---
### 1. **Purpose**
This module provides utility functions for resetting or clearing large swaths of persistent application state—both in-memory collections and database records—prior to importing sensor and model data from an external source (e.g., a TDM export or database import). Its primary role is to ensure a clean state before data ingestion by deleting all non-essential data, including test templates, test objects, sensors, calibrations, users, UI items, tags, and legacy database versions. It is used exclusively during import workflows and is tightly coupled with database operations and legacy data structures.
---
### 2. **Public Interface**
#### `public static void ClearAllTables(bool clearForDbImport)`
- **Behavior**: Clears all in-memory collections (via `DeleteAll()` calls on static list/collection types) and, if `clearForDbImport` is `true`, also clears corresponding database tables and related entities.
- **In-memory deletions include**:
- `TestTemplateList.TestTemplatesList`
- `TestObjectList.AddedGroupsList`
- `TestObjectList.TestObjectsList` *(deleted twice per comment)*
- `CustomChannelList.List`
- `SensorsCollection.SensorsList`
- `SensorModelCollection.SensorModelList`
- `SensorCalibrationList`
- `CustomerDetailsList`
- `LabratoryDetailsList`
- `TestEngineerDetailsList`
- **Database deletions (only if `clearForDbImport == true`)**:
- Non-prototype DAS tables via `DTS.Common.Storage.DbOperations.ClearNonPrototypeDas()`
- `LockedItems` table
- All users (via stored procedure `sp_UserDelete`)
- All UI items (via `sp_UIItemsDelete`)
- All tags (via `sp_TagsDelete`)
- All database versions older than `DbOperations.CURRENT_DB_VERSION` (via `sp_DbVersionDelete`)
---
### 3. **Invariants**
- **Ordering**: The in-memory `DeleteAll()` calls must precede database operations to avoid stale references or orphaned data in memory.
- **Dependency on `clearForDbImport`**: If `false`, *no database operations* are performed. All database-clearing logic is guarded by this flag.
- **Assumption about prior state**:
- `ClearAllUsers()` must be called before `ClearAllUIItems()` because UI items depend on user metadata (per comment: *"We're assuming that all of the UIItemSettings and Users are already deleted"*).
- Similarly, `ClearAllUsers()` is assumed to delete `TagAssignments` before `ClearAllTags()` runs.
- **Versioning invariant**: Only database versions `< DbOperations.CURRENT_DB_VERSION` are deleted; the current version and newer versions are preserved.
---
### 4. **Dependencies**
#### **Internal Dependencies**
- Static collections:
- `TestTemplateList.TestTemplatesList`
- `TestObjectList.AddedGroupsList`, `TestObjectList.TestObjectsList`
- `CustomChannelList.List`
- `SensorsCollection.SensorsList`
- `SensorModelCollection.SensorModelList`
- `SensorCalibrationList`
- `CustomerDetailsList`, `LabratoryDetailsList`, `TestEngineerDetailsList`
- `DTS.Common.Storage.DbOperations` (for `ClearNonPrototypeDas()`)
- `DbOperations` class (for SQL command generation, connection handling, and stored procedure names)
- `DbOperationsEnum.StoredProcedure` enum (used to resolve stored procedure names like `sp_UserDelete`, `sp_UIItemsGet`, etc.)
- `Tags.Tag` class (used to parse rows from `sp_TagsGet`)
- `DbOperations.Users`, `DbOperations.Users.UserFields`, `DbOperations.Users.UIItemFields`, `DbOperations.DbVersions`, `DbOperations.DbVersions.DbVersionFields` (static field/enum types for column access)
#### **External Dependencies**
- `System.Data.SqlClient` (for `SqlCommand`, `SqlParameter`, `SqlDbType`, etc.)
- `System.Data` (for `DataSet`, `DataRow`, `CommandType`)
- WPF `UserControl` base class (though `ImportSensorsImportControl` is a UI control, this modules public method is static and does not rely on UI state)
#### **Dependents**
- Likely invoked by higher-level import logic (e.g., `DatabaseImporter` or `DataImportViewModel`) before populating the cleared state with new data.
---
### 5. **Gotchas**
- **Double deletion of `TestObjectsList`**:
`TestObjectList.TestObjectsList.DeleteAll()` is called twice with a comment indicating “we keep two copies of the list around”—a strong signal of legacy duplication or refactoring debt.
- **Stored procedure usage is environment-specific**:
Comments explicitly state that `sp_UserDelete` and `sp_UserGet` are *only used in `DataPROPre20.mdf`*, not `DataPRO.mdf`. This implies the module may behave incorrectly or throw if run against newer database schemas.
- **Error handling is silent**:
In `ClearAllUsers()`, `ClearAllUIItems()`, `ClearAllTags()`, and `ClearAllExceptCurrentDbVersion()`, errors returned via `@errorNumber` are *not logged or propagated*—only commented out (`//errorMessageParam.Value`). This could mask failures during deletion.
- **Assumption of deletion order**:
`ClearAllUsers()` must run before `ClearAllUIItems()` and `ClearAllTags()` due to foreign key or logical dependencies, but this ordering is *not enforced programmatically*—it relies on caller discipline.
- **`GetAllUIItemIds()` uses `DbOperations.Users.UIItemFields.ID`**:
This suggests a possible naming inconsistency or reuse of user-related field enums for UI items, which could be confusing.
- **`GetAllUsers()` returns all columns as `string[]`**:
The method returns raw string arrays with fixed column order (id, username, etc.), making it fragile to schema changes. No type safety or schema validation is applied.
- **Resource disposal pattern is manual**:
All `SqlCommand` objects use `try/finally` to dispose connections manually. While correct, this is error-prone and could be replaced with `using` blocks for clarity and safety.
- **No transactional safety**:
Database deletions are executed in separate commands without an explicit transaction. A failure mid-way (e.g., after deleting users but before deleting tags) could leave the database in a partially cleared state.
- **`ClearAllExceptCurrentDbVersion()` deletes *older* versions only**:
The logic skips versions `>= CURRENT_DB_VERSION`, but does *not* delete newer versions (e.g., if `CURRENT_DB_VERSION` is updated post-deployment). This may be intentional for forward compatibility, but could lead to stale schema data if not managed carefully.
---

View File

@@ -0,0 +1,129 @@
---
source_files:
- DataPRO/Modules/DatabaseImporter/DatabaseImport/Controls/TestSetups/ImportTestSetup.cs
generated_at: "2026-04-16T04:33:34.717126+00:00"
model: "Qwen/Qwen3-Coder-Next-FP8"
schema_version: 1
sha256: "c54de3e2daf5d6b9"
---
# TestSetups
### **Purpose**
The `ImportTestSetup` class is a WPF `UserControl` responsible for parsing and importing structured XML data representing test setup configurations (including sensors, calibrations, hardware, groups, and custom MME metadata) into the systems database via stored procedures. It acts as the core ingestion layer for legacy or exported test setup files, supporting versioned import logic (v1.0 and v2.0) and maintaining in-memory collections of imported entities prior to database persistence. Its role is to translate XML fragments into domain objects and orchestrate their bulk insertion into the database while preserving data integrity and handling version-specific transformations.
---
### **Public Interface**
#### **Static Fields (Publicly Exposed Collections)**
These collections hold imported data *before* it is persisted to the database. They are populated during XML processing and cleared by `Cleanup()`.
| Field | Type | Description |
|-------|------|-------------|
| `Directions` | `List<MMEDirections>` | Custom MME direction definitions imported from XML. |
| `FilterClasses` | `List<MMEFilterClasses>` | Custom MME filter class definitions. |
| `FineLoc1s` | `List<MMEFineLocations1>` | First-level fine location definitions. |
| `FineLoc2s` | `List<MMEFineLocations2>` | Second-level fine location definitions. |
| `FineLoc3s` | `List<MMEFineLocations3>` | Third-level fine location definitions. |
| `MainLocs` | `List<MMETransducerMainLocation>` | Transducer main location definitions. |
| `TestObjects` | `List<MMETestObjects>` | Custom test object definitions. |
| `PhysicalDimensions` | `List<MMEPhysicalDimensions>` | Physical dimension definitions. |
| `Positions` | `List<MMEPositions>` | Position definitions. |
| `Calibrations` | `List<SensorCalibration>` | Sensor calibration history records. |
| `CustomerDetails` | `List<ISO.CustomerDetails>` | Customer metadata imported from XML. |
| `LabDetails` | `List<ISO.LabratoryDetails>` | Laboratory metadata imported from XML. |
| `Sensors` | `List<SensorData>` | Sensor definitions (note: declared `public static readonly`, but no direct population logic visible in this file—likely populated via `ImportElement` → stored procedure). |
| `_testSetups` | `List<TestTemplate>` | Test setup templates (note: declared `public static`, not `readonly`). |
| `_sensorsWithDuplicateIds` | `List<SensorData>` | Internal tracking for sensors with duplicate IDs (not exposed publicly). |
#### **Static Methods**
| Method | Signature | Description |
|--------|-----------|-------------|
| `ProcessRootNode` | `public static void ProcessRootNode(string name, string outerXML, DbImporter.SetStatusDelegate SetStatus)` | Dispatches XML fragment processing based on `name` (e.g., `"SensorData"`, `"TestSetup"`). Maps element names to corresponding stored procedures and invokes `ImportElement`. Does *not* handle `DbVersion` or `SensorCalibration` directly—those have dedicated logic elsewhere (see `ImportCalibrations`). |
| `ImportElement` | `private static void ImportElement(string storedProcedure, string storedProcedureParameter, string outerElementName, string outerXML)` | Wraps `outerXML` in `<outerElementName>...</outerElementName>`, executes the specified stored procedure with the XML as an `@parameter`, and captures output error info. Throws on failure. Does *not* log or handle errors beyond re-throwing. |
| `GetTestSetupName` | `private static string GetTestSetupName(string outerXML)` | Extracts `SetupName` from `<TestSetup/Fields/SetupName>` in `outerXML` using `XmlDocument`. Returns `null` if not found. |
| `Cleanup` | `private static void Cleanup()` | Clears *all* static collections listed above (including `_sensorsWithDuplicateIds`, `_globalSettings`, `_customChannels`, etc.). Resets state for a new import session. |
#### **Nested Types (Referenced)**
- `PossibleStatus` enum: Defines UI states (`Waiting`, `Working`, `Done`, `Failed`).
- `DbOperationsEnum.StoredProcedure`: Used to resolve stored procedure names (e.g., `sp_DBImportSensors`).
- `SensorCalibration`, `SensorData`, `TestTemplate`, `DASHardware`, `User`, `TestObject`, etc.: Domain types imported via XML or stored procedures.
> **Note**: `ProcessRootNode` does *not* handle `SensorCalibration` or `DbVersion`—those are processed separately (implied by `ImportCalibrations` method and `_importedVersion` usage). `DbVersion` is imported via `ImportElement`, but `_importedVersion` is set elsewhere (not shown here).
---
### **Invariants**
1. **XML Structure**:
- `outerXML` passed to `ProcessRootNode` must be a well-formed XML fragment corresponding to the expected schema for the given `name` (e.g., `<SensorData>...</SensorData>`).
- `GetTestSetupName` assumes `outerXML` contains a `<TestSetup>` root with a `<Fields>` child containing `<SetupName>`.
2. **Version Handling**:
- `_importedVersion` (private) must be set *before* `ImportCalibrations` is called (not shown in this file).
- Calibration import logic diverges based on `_importedVersion == 1.0D` or `2.0D`. Version 1.0 applies transformations (e.g., setting `SensitivityUnits`, `AtCapacity = false`).
3. **Database Interaction**:
- All `ImportElement` calls use stored procedures with XML parameters.
- Stored procedure output parameters `@errorNumber` and `@errorMessage` are captured but only checked for non-zero `@errorNumber`; error messages are *not* propagated or logged in this method.
- Command timeout is fixed at 60 seconds.
4. **State Management**:
- `Cleanup()` must be called before a new import to reset all static collections.
- `_sensorsWithDuplicateIds` is populated elsewhere (not visible here) but is cleared on `Cleanup()`.
---
### **Dependencies**
#### **Internal Dependencies**
- **Types**:
- `DbOperations` (provides `GetSQLCommand` and `SetStatusDelegate`).
- `DbOperationsEnum.StoredProcedure` (for stored procedure names).
- `ISO.CustomerDetails`, `ISO.LabratoryDetails`, `SensorCalibration`, `SensorData`, `TestTemplate`, `DASHardware`, `User`, `TestObject`, `MME*` types (e.g., `MMEDirections`, `MMEPossibleChannels`).
- `Test.Module.Channel.Sensor.SensUnits` (used in `ImportCalibrations` for v1.0 transformations).
- **XAML**: `ImportTestSetup.xaml` (interaction logic partial class).
#### **External Dependencies**
- **.NET Framework**: `System.Data`, `System.Data.SqlClient`, `System.Xml`, `System.Windows.Controls`.
- **Database**: SQL Server (via stored procedures named `sp_DBImport*`).
- **Calling Code**: `DbImporter.SetStatusDelegate` (likely from `DbImporter` class) for status reporting.
#### **Depended Upon**
- Likely invoked by `DbImporter` (or similar orchestrator) during XML parsing of an import file.
- Public static fields are consumed by downstream logic (e.g., UI binding, final commit to DB).
---
### **Gotchas**
1. **Static State Management**:
- All data is held in *static* collections. This makes the class **not thread-safe** and unsuitable for concurrent imports without external synchronization.
- `Cleanup()` must be called explicitly before each import; otherwise, stale data persists across sessions.
2. **Incomplete Error Handling**:
- `ImportElement` captures `@errorNumber` and `@errorMessage` but *does nothing* with them (commented-out error handling block). Errors are silently ignored unless an exception is thrown.
- `ProcessRootNode` does *not* handle `SensorCalibration` or `DbVersion`—these require separate processing logic (implied by `ImportCalibrations` and `_importedVersion` usage), which is not visible here.
3. **Version-Specific Logic Fragility**:
- Calibration import for v1.0 assumes exactly one calibration record (`sc.Records.Records[0]`). If the schema changes, this will throw `IndexOutOfRangeException`.
- `_importedVersion` is set elsewhere (not in this file), creating a hidden dependency.
4. **XML Parsing Assumptions**:
- `GetTestSetupName` uses `SelectSingleNode` without null-checking beyond the null-conditional operator. If `SetupName` is missing, it returns `null`—callers must handle this.
- `outerXML` is naively wrapped in `<outerElementName>...</outerElementName>`. If `outerXML` already contains a root element, this produces invalid XML.
5. **Naming Inconsistencies**:
- `LabDetails` uses `LabratoryDetails` (misspelled) in the type name (`ISO.LabratoryDetails`).
- `_testSetups` is `public static List<TestTemplate>`, while other collections (e.g., `Calibrations`) are `readonly`. This suggests `_testSetups` may be reassigned elsewhere.
6. **No Version Validation**:
- No explicit check ensures `_importedVersion` matches `CurrentVersion` (2.0). Mismatched versions may cause silent data loss or corruption.
7. **Unused/Commented Code**:
- `ProcessRootNode` contains commented-out `CancelCheck` calls and `page` parameters, suggesting legacy cancellation UI support that is no longer active.
- The `//Store the compressed binary copy...` comment in the `"TestSetup"` case indicates incomplete or deprecated functionality.
> **None identified from source alone** for thread-safety, serialization, or external API contracts—these require examining `DbImporter` and related types.

View File

@@ -0,0 +1,41 @@
---
source_files:
- DataPRO/Modules/DatabaseImporter/DatabaseImport/Converters/EnumDescriptionTypeConverter.cs
generated_at: "2026-04-16T04:29:54.553980+00:00"
model: "Qwen/Qwen3-Coder-Next-FP8"
schema_version: 1
sha256: "60faab8710c59a2c"
---
# Converters
## Documentation: `EnumDescriptionTypeConverter`
### 1. Purpose
This module provides a custom type converter for .NET enums that enables WPF data binding to display human-readable descriptions (via `DescriptionAttribute`) instead of the raw enum names or underlying values. It extends `System.ComponentModel.EnumConverter` to support scenarios where enum members are decorated with `[Description("...")]`, allowing UI frameworks like WPF to render meaningful labels (e.g., "Active User" instead of `ActiveUser`) during data binding operations. Its role is to bridge the gap between enum definitions and user-facing text in UI contexts.
### 2. Public Interface
- **`EnumDescriptionTypeConverter(Type type)`**
*Constructor.* Initializes a new instance of `EnumDescriptionTypeConverter` for the specified `enum` type.
- **Parameters:**
- `type`: The `Type` of the enum to convert (must be an enum type).
- **Behavior:** Delegates to the base `EnumConverter` constructor. No additional logic is implemented in this class beyond inheritance.
### 3. Invariants
- The `type` parameter passed to the constructor **must** be an enum type (i.e., `Type.IsEnum == true`); otherwise, the base `EnumConverter` constructor will throw an `ArgumentException`.
- The converter does **not** validate or modify the enum type itself—it relies on the base `EnumConverter`s behavior for parsing and formatting.
- No runtime validation of `[DescriptionAttribute]` presence is performed; missing attributes fall back to the enum members name (handled by the base class).
### 4. Dependencies
- **Depends on:**
- `System.ComponentModel.EnumConverter` (base class).
- `System.DescriptionAttribute` (implicitly, via the base classs expected usage pattern—though not explicitly referenced in this file).
- **Used by:**
- WPF data binding infrastructure (e.g., via `TypeConverterAttribute` applied to enum types or properties).
- Likely referenced by other modules in `DatabaseImport` namespace that bind enums to UI controls (e.g., comboboxes, labels).
### 5. Gotchas
- **No custom logic implemented:** Despite the class name and summary comment, this implementation **does not override** `ConvertTo`/`ConvertFrom` methods. As written, it behaves identically to `EnumConverter` and will **not** automatically use `[DescriptionAttribute]` values. To achieve the described behavior, overrides for `ConvertTo` (and possibly `ConvertFrom`) are required but absent in the source.
- **Documentation mismatch:** The referenced blog post (`http://brianlagunas.com/...`) likely contains the intended implementation pattern, but the current code is incomplete.
- **Common mistake:** Developers may assume this converter enables `DescriptionAttribute` support out-of-the-box, leading to incorrect expectations about UI rendering.
- **None identified from source alone** regarding other behaviors, but the lack of overrides is a critical gap.

View File

@@ -0,0 +1,130 @@
---
source_files:
- DataPRO/Modules/DatabaseImporter/DatabaseImport/DASConcepts/Test.Module.Channel.Sensor.SensorUnits.cs
- DataPRO/Modules/DatabaseImporter/DatabaseImport/DASConcepts/Test.Module.Channel.Sensor.Bridge.cs
- DataPRO/Modules/DatabaseImporter/DatabaseImport/DASConcepts/DigitalInputScaleMultiplier.cs
- DataPRO/Modules/DatabaseImporter/DatabaseImport/DASConcepts/LinearizationFormula.cs
generated_at: "2026-04-16T04:29:46.893362+00:00"
model: "Qwen/Qwen3-Coder-Next-FP8"
schema_version: 1
sha256: "50ada406a17a3727"
---
# Documentation: Sensor & Linearization Concepts Module
## 1. Purpose
This module defines core data structures and enumerations used to represent sensor configuration and signal linearization behavior within the DatabaseImporter subsystem of the DTS DataPRO system. It provides strongly-typed representations of sensor sensitivity units (`SensUnits`), bridge configurations (`BridgeType`), digital input scaling (`DigitalInputScaleMultiplier`), and various linearization formulae (`LinearizationFormula`)—all derived from legacy database serialization formats. These constructs enable consistent interpretation and persistence of sensor metadata during database import operations, bridging historical DTS-specific formats with modern .NET type safety.
## 2. Public Interface
### `Test.Module.Channel.Sensor.SensUnits` (enum)
- **Definition**: `public enum SensUnits`
- **Values**:
- `NONE = 0` → Polynomial sensor with no sensitivity units.
- `mV = 1` → Sensitivity in millivolts at full-scale (Capacity EU).
- `mVperV = 2` → Excitation-proportional sensitivity in mV/V at full-scale.
- `mVperVperEU = 3` → Excitation-proportional sensitivity per engineering unit (mV/V/EU).
- `mVperEU = 4` → Sensitivity in mV per engineering unit.
- **Behavior**: Encodes the unit type for sensor sensitivity; used to interpret sensitivity values in configuration.
### `Test.Module.Channel.Sensor.BridgeType` (enum)
- **Definition**: `public enum BridgeType`
- **Values** (bitmask flags):
- `IEPE = 1 << 0` → IEPE (Integrated Electronics Piezo Electric) sensor setup.
- `QuarterBridge = 1 << 1` → Quarter-bridge configuration.
- `HalfBridge = 1 << 2` → Half-bridge configuration.
- `FullBridge = 1 << 3` → Full-bridge configuration.
- `DigitalInput = 1 << 4` → Digital input mode.
- `SQUIB = 1 << 5` → Squib (pyrotechnic) output setup.
- `TOMDigital = 1 << 6` → TOM (Test Output Module) digital output.
- `HalfBridge_SigPlus = 1 << 7` → G5 half-bridge with signal-plus wiring.
- **Behavior**: Represents physical bridge/wiring topology; supports bitwise combinations.
### `DigitalInputScaleMultiplier` (class)
- **Definition**: `public class DigitalInputScaleMultiplier`
- **Properties**:
- `Form`: `Forms` enum; currently only `ArbitraryLowAndHigh` supported.
- `DefaultValue`: `double`; value displayed when digital input = 0 (OFF).
- `ActiveValue`: `double`; value displayed when digital input = 1 (ON); defaults to `1.0`.
- **Constructors**:
- `DigitalInputScaleMultiplier()` → Initializes `DefaultValue = 0.0`.
- `DigitalInputScaleMultiplier(DigitalInputScaleMultiplier copy)` → Copy constructor.
- **Methods**:
- `void FromDbSerializeString(string s)` → Parses serialized string (e.g., `"ArbitraryLowAndHigh,0.0,5.0"`) into object state.
- Throws `NotSupportedException` on malformed input or unsupported format.
- Uses `InvariantCulture` for numeric parsing.
### `LinearizationFormula` (class)
- **Definition**: `public class LinearizationFormula`
- **Properties**:
- `NonLinearStyle`: `NonLinearStyles` (not defined in provided files; inferred from usage).
- `PolynomialSensitivity`: `double`; sensitivity for polynomial models.
- `LinearizationExponent`: `double`; exponent in power-law models.
- `MMPerV`: `double`; millimeters per volt (note: comment indicates variable name is inaccurate).
- `MVAt0MM`: `double`; millivolts at zero millimeters.
- `Slope`, `Intercept`: `double`; linear model parameters.
- `CalibrationFactor`: `double`; calibration coefficient.
- `ZeroPositionIntercept`: `double`; intercept at zero position.
- `UsemVOverVForPolys`: `bool`; flag for polynomial unit preference (default `true`).
- **Constructors**:
- `LinearizationFormula()` → Initializes default state (e.g., `_coefficients = [0,0,0,0]`, `_exponents = [0,1,2,3]`).
- `LinearizationFormula(LinearizationFormula copy)` → Copy constructor.
- **Methods**:
- `void MarkValid(bool bValid)` → Sets internal `_bIsValid` flag (no getter exposed).
- `void FromSerializeString(string s, CultureInfo culture)` → Parses serialized format: `<Style>_<params>`.
- Supports styles: `IRTraccDiagnosticsZero`, `IRTraccManual`, `IRTraccZeroMMmV`, `Polynomial`, `IRTraccAverageOverTime`, `IRTraccCalFactor`.
- Throws `NotSupportedException` for unknown styles or malformed data.
- `void FromSerializeString(string s)` → Overload using `InvariantCulture`.
- Private helper methods (called by `FromSerializeString`):
- `FromIRTraccCalFactorString`, `FromIRTraccDiagnosticZeroString`, `FromIRTraccManualString`, `FromIRTraccAverageOverTimeString`, `FromIRTraccZeroMMmVString`, `FromPolynomialString`
→ Parse style-specific parameter strings (e.g., `"Slope x Exponent x Intercept"`).
## 3. Invariants
- **`SensUnits`**:
- Values are mutually exclusive and non-overlapping (no bitwise combinations).
- `NONE` (0) is reserved for polynomial sensors lacking sensitivity units.
- **`BridgeType`**:
- Values are bitmask flags; multiple types may be combined via bitwise OR.
- Only one physical bridge type (e.g., `QuarterBridge`, `HalfBridge`, `FullBridge`) should be active per sensor, though combinations like `DigitalInput | TOMDigital` may be valid.
- **`DigitalInputScaleMultiplier`**:
- `Form` must be `ArbitraryLowAndHigh`; no other forms are implemented.
- `DefaultValue` and `ActiveValue` must be parseable as `double`; invalid values throw `NotSupportedException`.
- **`LinearizationFormula`**:
- `_bIsValid` is set only by `FromSerializeString` (via `MarkValid` internally); no public validation method exists.
- `FromSerializeString` expects format `<Style>_<param_string>`; parsing fails if tokens are missing or malformed.
- Polynomial parsing (`FromPolynomialString`) has ambiguous behavior: if a token lacks `'x'`, it may be interpreted as a special key (`"S"` or `"mV"`) instead of coefficient/exponent.
## 4. Dependencies
- **Internal Dependencies**:
- Relies on `Test.Module.Channel.Sensor` being defined elsewhere (via `partial class` and `//*** see ... ***` comments).
- `NonLinearStyles` enum is referenced but not defined in provided files; must be declared in another file (likely `DASConcepts/NonLinearStyles.cs`).
- Uses `System.ComponentModel.DescriptionAttribute` for enum metadata (not used in logic, likely for UI).
- **External Dependencies**:
- `System` (core types, `CultureInfo`, `double`, `List<T>`, `string`).
- `System.Globalization` (`InvariantCulture`, `NumberStyles`).
- **Depended Upon By**:
- Database import logic (e.g., parsing sensor configuration from legacy DB strings).
- UI components (via `DescriptionAttribute` for display names).
- Serialization/deserialization layers for sensor metadata.
## 5. Gotchas
- **`MMPerV` naming is misleading**: Comment explicitly states *"THIS IS MM/V, (UI has already been updated, we need to update the variable name)"*—the variable name does not match its meaning (millimeters per volt, not millivolts per volt).
- **`_bIsValid` is internal-only**: No public `IsValid()` method is exposed despite the private `_bIsValid` field and commented-out `IsValid()` method.
- **Polynomial parsing ambiguity**: In `FromPolynomialString`, tokens without `'x'` are treated as special keys (`"S"`/`"mV"`), but tokens with `'x'` but only one part (e.g., `"2"`) fall through to `PolynomialSensitivity` assignment—this may cause silent misinterpretation.
- **`DigitalInputScaleMultiplier` ignores null/empty input**: `FromDbSerializeString(null)` returns silently (with comment `//FIXME is this the right thing to do?`), potentially masking errors.
- **`BridgeType` values use bit shifts**: While designed for bitwise combination, the enum is not marked `[Flags]`, so tools may not display combined values intuitively.
- **Culture sensitivity**: All numeric parsing uses `InvariantCulture`, but `FromDbSerializeString` in `DigitalInputScaleMultiplier` splits on `CultureInfo.InvariantCulture.TextInfo.ListSeparator` (typically `','`), which may conflict with decimal separators in some locales if not handled consistently upstream.
- **No validation of polynomial coefficients/exponents**: `FromPolynomialString` does not enforce non-empty lists or valid exponents (e.g., negative exponents may be allowed).

View File

@@ -0,0 +1,188 @@
---
source_files:
- DataPRO/Modules/DatabaseImporter/DatabaseImport/Enums/DigitalInputs.cs
- DataPRO/Modules/DatabaseImporter/DatabaseImport/Enums/DigitalOutputs.cs
- DataPRO/Modules/DatabaseImporter/DatabaseImport/Enums/SupportedExportFormatBitFlags.cs
- DataPRO/Modules/DatabaseImporter/DatabaseImport/Enums/Squibs.cs
- DataPRO/Modules/DatabaseImporter/DatabaseImport/Enums/ExcitationVoltageOptions.cs
generated_at: "2026-04-16T04:30:02.337162+00:00"
model: "Qwen/Qwen3-Coder-Next-FP8"
schema_version: 1
sha256: "004a8160296448d2"
---
# Documentation: DatabaseImport Enumerations
## 1. Purpose
This module defines core enumerations used throughout the `DatabaseImport` subsystem to represent configuration states and capabilities related to digital I/O, squib (pyrotechnic initiator) measurement/fire modes, and data export formats. These enums provide strongly-typed, self-documenting representations of hardware and software configuration parameters, enabling consistent interpretation of digital channel behavior, squib operation, and export target formats across the codebase.
## 2. Public Interface
### `DigitalInputModes`
*Defined in:* `DataPRO/Modules/DatabaseImporter/DatabaseImport/Enums/DigitalInputs.cs`
*Attributes:* `[TypeConverter(typeof(EnumDescriptionTypeConverter))]`
*Purpose:* Represents supported input modes for digital channels.
| Member | Value | Description |
|--------|-------|-------------|
| `TLH` | `1 << 1` (2) | Transition low to high |
| `THL` | `1 << 2` (4) | Transition high to low |
| `CCNO` | `1 << 3` (8) | Contact closure normally open |
| `CCNC` | `1 << 4` (16) | Contact closure normally closed |
> **Note:** Values are powers of two, enabling bitwise combination.
---
### `DigitalOutputModes`
*Defined in:* `DataPRO/Modules/DatabaseImporter/DatabaseImport/Enums/DigitalOutputs.cs`
*Attributes:* `[TypeConverter(typeof(EnumDescriptionTypeConverter))]`
*Purpose:* Represents supported output modes for digital channels.
| Member | Value | Description |
|--------|-------|-------------|
| `NONE` | `0` | Digital channel mode not set |
| `FVLH` | `1 << 0` (1) | 5V, low-to-high transition |
| `FVHL` | `1 << 1` (2) | 5V, high-to-low transition |
| `CCNO` | `1 << 2` (4) | Contact closure normally open |
| `CCNC` | `1 << 3` (8) | Contact closure normally closed |
> **Note:** Values are powers of two, enabling bitwise combination.
---
### `SupportedExportFormatBitFlags`
*Defined in:* `DataPRO/Modules/DatabaseImporter/DatabaseImport/Enums/SupportedExportFormatBitFlags.cs`
*Attributes:* `[Flags]`
*Purpose:* Represents supported export file formats as bit flags.
| Member | Value | Description |
|--------|-------|-------------|
| `none` | `0x0` | No format selected |
| `csvunfiltered` | `0x1` | Unfiltered CSV export |
| `diademadc` | `0x2` | DIAdem ADC format |
| `isounfiltered` | `0x4` | ISO unfiltered export |
| `somatunfiltered` | `0x8` | Somat unfiltered export |
| `tdmsadc` | `0x10` | TDMS ADC format |
| `toyotaunfiltered` | `0x20` | Toyota unfiltered export |
| `tsvunfiltered` | `0x40` | TSV unfiltered export |
| `csvfiltered` | `0x80` | Filtered CSV export |
| `isofiltered` | `0x200` | ISO filtered export |
| `somatfiltered` | `0x400` | Somat filtered export |
| `tdasadc` | `0x800` | TDAS ADC format |
| `toyotafiltered` | `0x1000` | Toyota filtered export |
| `tsvfiltered` | `0x2000` | TSV filtered export |
| `rdfadc` | `0x4000` | RDF ADC format |
| `ChryslerDDAS` | `0x8000` | Chrysler DDAS format |
| `HDFUnfiltered` | `0x10000` | HDF unfiltered export |
| `HDFFiltered` | `0x20000` | HDF filtered export |
| `HDFMV` | `0x40000` | HDF MV format |
| `HDFADC` | `0x80000` | HDF ADC format |
| `xlsxfiltered` | `0x100000` | Excel (XLSX) filtered export |
| `xlsxunfiltered` | `0x200000` | Excel (XLSX) unfiltered export |
> **Note:** One format (`diademfiltered = 0x100`) is commented out and currently unused.
---
### `SquibMeasurementType`
*Defined in:* `DataPRO/Modules/DatabaseImporter/DatabaseImport/Enums/Squibs.cs`
*Attributes:* `[TypeConverter(typeof(EnumDescriptionTypeConverter))]`
*Purpose:* Specifies what squib-related signals are recorded during measurement.
| Member | Value | Description |
|--------|-------|-------------|
| `NONE` | `0` | Measurement mode not set |
| `CURRENT` | `1 << 0` (1) | Squib current recorded |
| `INIT_SIGNAL` | `1 << 1` (2) | Squib initiation indicator recorded |
| `VOLTAGE` | `1 << 2` (4) | Squib voltage recorded |
> **Note:** Values are powers of two, enabling bitwise combination.
---
### `SquibFireMode`
*Defined in:* `DataPRO/Modules/DatabaseImporter/DatabaseImport/Enums/Squibs.cs`
*Attributes:* `[TypeConverter(typeof(EnumDescriptionTypeConverter))]`
*Purpose:* Specifies the discharge method used to fire the squib.
| Member | Value | Description |
|--------|-------|-------------|
| `NONE` | `1 << 0` (1) | Fire mode not set |
| `CAP` | `1 << 1` (2) | Capacitor discharge |
| `CONSTANT` | `1 << 2` (4) | Constant current discharge |
| `AC` | `1 << 3` (8) | AC discharge |
> **Note:** `NONE` is *not* zero-valued (value = 1), unlike typical patterns. This may be intentional to distinguish "unset" from "disabled".
---
### `ExcitationVoltageOptions`
*Defined in:* `DataPRO/Modules/DatabaseImporter/DatabaseImport/Enums/ExcitationVoltageOptions.cs`
*Purpose:* Defines available excitation voltage levels for sensors, with associated metadata.
#### Nested Type: `ExcitationVoltageOption`
*Attributes:* `[TypeConverter(typeof(EnumDescriptionTypeConverter))]` (inferred from usage of `EnumDescriptionTypeConverter` elsewhere)
| Member | Value | Description | Voltage Magnitude |
|--------|-------|-------------|-------------------|
| `Undefined` | `1` | Undefined excitation voltage | `0.0` V |
| `Volt2` | `2` | 2.0 V | `2.0` V |
| `Volt2_5` | `4` | 2.5 V | `2.5` V |
| `Volt3` | `8` | 3.0 V | `3.0` V |
| `Volt5` | `16` | 5.0 V | `5.0` V |
| `Volt10` | `32` | 10.0 V | `10.0` V |
| `Volt1` | `64` | 1.0 V | `1.0` V |
#### Nested Type: `VoltageMagnitudeAttribute`
*Purpose:* Custom attribute to associate a numeric voltage magnitude with enum members.
| Member | Signature | Description |
|--------|-----------|-------------|
| `Value` | `public double Value { get; }` | Returns the voltage magnitude (in volts) associated with the enum field. |
| `VoltageMagnitudeAttribute(double value)` | `public VoltageMagnitudeAttribute(double value)` | Constructor. Stores the voltage magnitude. |
> **Note:** `VoltageMagnitudeAttribute` is defined *inside* `ExcitationVoltageOptions` class.
---
## 3. Invariants
- **Bitwise Independence:** All enums except `SquibFireMode.NONE` and `ExcitationVoltageOption` use powers of two, enabling safe bitwise OR/AND operations for flag combinations.
- **`DigitalInputModes` vs `DigitalOutputModes`:** Both share `CCNO` and `CCNC` names but have different underlying values (e.g., `CCNO` = 8 in inputs, 4 in outputs). They are *not* interchangeable.
- **`SquibFireMode.NONE` ≠ 0:** Unlike `SquibMeasurementType.NONE`, `SquibFireMode.NONE` has value `1` (not `0`). This is likely intentional to distinguish "unset" from a valid fire mode.
- **`VoltageMagnitudeAttribute.Value` is non-null:** Every `ExcitationVoltageOption` field decorated with `[VoltageMagnitude(...)]` has a corresponding `double` value.
- **No overlapping values within an enum:** Each enum member has a unique underlying integer value (no duplicates within the same enum).
---
## 4. Dependencies
### This module depends on:
- `System.ComponentModel` (for `[Description]` and `TypeConverter` infrastructure)
- `System` (for `[Flags]`, `[AttributeUsage]`, `Attribute`, `double`)
### This module is depended upon by:
- Other modules in `DatabaseImport` (inferred from namespace usage)
- Likely used by:
- Configuration parsers (e.g., reading from database or XML)
- Export pipeline (to select output format via `SupportedExportFormatBitFlags`)
- Hardware abstraction layer (to configure digital channels via `DigitalInputModes`/`DigitalOutputModes`)
- Squib control logic (via `SquibMeasurementType`/`SquibFireMode`)
- Sensor configuration (via `ExcitationVoltageOptions`)
> **Note:** `EnumDescriptionTypeConverter` is referenced but not defined in the provided files. Its implementation must exist elsewhere in the codebase.
---
## 5. Gotchas
- **`SquibFireMode.NONE` is non-zero (`1`)**: This breaks the common convention where "none" or "unset" is `0`. Code checking for unset mode must compare explicitly to `SquibFireMode.NONE`, not `0`.
- **`DigitalInputModes` and `DigitalOutputModes` share names but not values**: `CCNO` and `CCNC` have different bit positions in each enum. Do not assume equivalence or reuse across input/output contexts.
- **`diademfiltered` is commented out**: The value `0x100` is reserved but unused. Do not assume it is supported or safe to use.
- **`ExcitationVoltageOption` values are powers of two, but not sequential**: Values are `1, 2, 4, 8, 16, 32, 64` — not contiguous. Avoid arithmetic assumptions (e.g., `Volt10` is not `Volt5 + 5`).
- **`VoltageMagnitudeAttribute` is nested**: Its fully qualified name is `ExcitationVoltageOptions.VoltageMagnitudeAttribute`. Reflection or attribute lookup must account for nesting.
- **No validation on enum combinations**: The enums support bitwise combination, but no runtime checks ensure logically invalid combinations (e.g., `TLH | THL` for a single digital input).
- **Missing `diademfiltered` may cause confusion**: If legacy code references `0x100`, it may be unclear whether it was intended for `diademfiltered` or another format.
None identified beyond those above.

View File

@@ -0,0 +1,43 @@
---
source_files:
- DataPRO/Modules/DatabaseImporter/DatabaseImport/Enums/Hardware/HardwareTypes.cs
generated_at: "2026-04-16T04:32:55.929056+00:00"
model: "Qwen/Qwen3-Coder-Next-FP8"
schema_version: 1
sha256: "38a6927cd83972ad"
---
# Hardware
### 1. Purpose
This module defines the `HardwareTypes` enumeration, which serves as a canonical type-safe identifier for supported hardware devices within the DatabaseImport subsystem. It enables unambiguous referencing and mapping of physical hardware units (e.g., SLICE variants, TOM, SIM, DIM, G5-series devices) during data import operations—likely when correlating raw sensor data or configuration files with specific hardware models in the database. Its role is foundational: it standardizes hardware type representation across the import pipeline, ensuring consistent interpretation of device metadata.
### 2. Public Interface
The module exposes a single public type:
- **`HardwareTypes`** (`enum`)
A strongly-typed enumeration of hardware device types used in the system. Each member is assigned an explicit integer value starting from `0`. The enum includes variants of SLICE hardware (e.g., `SLICE_Base`, `SLICE2_IEPE_Hi`, `SLICE6DB`), legacy/legacy-adjacent devices (`TDAS_Pro_Rack`, `TDAS_LabRack`), and specialized modules (`TOM`, `SIM`, `DIM`, `Ribeye`, `G5INDUMMY`, `SLICE_EthernetController`).
*Note:* A commented-out entry `//G5IPORT=22` exists, indicating a planned or deprecated type.
### 3. Invariants
- **Sequential integer values (mostly):** All explicitly defined enum members have unique, non-overlapping integer values. However, the sequence is *not strictly contiguous* due to the commented-out `G5IPORT=22`—the value `22` is unused, and the next entry (`G5INDUMMY`) is `23`.
- **No negative values:** All enum values are ≥ 0.
- **No runtime validation:** The enum itself enforces no semantic constraints (e.g., it does not prevent invalid combinations or enforce hardware-specific rules). Validation (if any) must occur elsewhere in the codebase.
- **Stable identity:** The integer values are part of the public contract; changing them would break persistence (e.g., in database records or serialized configs).
### 4. Dependencies
- **No external dependencies:** The file imports only the `System` namespace implicitly (via `namespace` declaration) and contains no `using` statements or external references.
- **Consumers:** This enum is almost certainly referenced by other modules in the `DatabaseImport` namespace (e.g., classes handling hardware configuration parsing, database schema mapping, or device initialization). Based on naming conventions, consumers may include:
- Hardware-specific importers (e.g., `SLICEImporter`, `TOMImporter`)
- Database schema mappers (e.g., tables/columns storing `HardwareType` as an integer)
- Configuration parsers (e.g., reading hardware type strings and mapping them to `HardwareTypes` enum values)
*Exact consumers cannot be determined from this file alone.*
### 5. Gotchas
- **Non-contiguous numbering:** The gap at value `22` (due to commented-out `G5IPORT`) may cause issues if downstream code assumes contiguous ranges (e.g., using `Enum.GetValues(typeof(HardwareTypes)).Length` for array sizing without filtering).
- **Commented-out member:** `G5IPORT=22` is commented out but *not removed*, which could mislead developers into expecting support for this type. Its status (deprecated, planned, or obsolete) is unclear.
- **No documentation on semantics:** The enum provides no XML comments or inline descriptions explaining what each hardware type *does* (e.g., "SLICE_Bridge" vs. "SLICE2_Bridge_Hi"). This forces reliance on external documentation or reverse engineering.
- **Case sensitivity in string parsing:** If string-to-enum conversion is used (e.g., from config files), the enum is case-sensitive (standard C# behavior), and mismatches (e.g., `"slice_base"` vs. `"SLICE_Base"`) will fail unless explicitly handled.
- **No `Flags` attribute:** The enum is *not* marked with `[Flags]`, implying bitwise combinations are not intended—though this is not enforced by the compiler.
*None identified beyond these.*

View File

@@ -0,0 +1,77 @@
---
source_files:
- DataPRO/Modules/DatabaseImporter/DatabaseImport/Enums/Sensors/SensorStatus.cs
- DataPRO/Modules/DatabaseImporter/DatabaseImport/Enums/Sensors/LinearizationFormula.cs
- DataPRO/Modules/DatabaseImporter/DatabaseImport/Enums/Sensors/ZeroMethodType.cs
generated_at: "2026-04-16T04:32:45.162581+00:00"
model: "Qwen/Qwen3-Coder-Next-FP8"
schema_version: 1
sha256: "fee300d457ca6c5a"
---
# Sensors
## 1. Purpose
This module defines core enumeration types used for representing sensor metadata and calibration behavior within the `DatabaseImport` subsystem of the DataPRO system. Specifically, it standardizes how sensor operational status, nonlinear signal conversion methods, and zero-point calculation strategies are encoded—enabling consistent interpretation of imported sensor configuration data (e.g., from legacy databases like GM ISF). These enums serve as foundational building blocks for deserializing and validating sensor-related records during database import operations.
---
## 2. Public Interface
### `SensorStatus`
- **Namespace**: `DatabaseImport`
- **Type**: `public enum`
- **Members**:
- `Available`: Sensor is ready for use.
- `InUse`: Sensor is currently deployed or active.
- `OutForService`: Sensor is offline for maintenance.
- `OutForCalibration`: Sensor is offline for calibration.
- `Retired`: Sensor is no longer in service.
### `NonLinearStyles`
- **Namespace**: `DatabaseImport`
- **Type**: `public enum`
- **Members**:
- `IRTraccManual`: Manual linearization method (likely user-defined or legacy).
- `IRTraccDiagnosticsZero`: Linearization using diagnostic-based zero point.
- `IRTraccZeroMMmV`: Linearization using zero point derived from millivolt-level diagnostics.
- `IRTraccAverageOverTime`: Linearization using time-averaged zero point.
- `Polynomial`: Polynomial-based nonlinearity correction (e.g., higher-order fit).
- `IRTraccCalFactor`: Linearization using a calibration factor (likely multiplicative).
### `ZeroMethodType`
- **Namespace**: `DatabaseImport`
- **Type**: `public enum`
- **Members**:
- `AverageOverTime = 0`: Compute zero by averaging signal over time.
- `UsePreEventDiagnosticsZero = 1`: Compute zero using diagnostics captured *before* an event.
- `None = 2`: No zero calculation—use an absolute or pre-specified zero value.
- **Note**: The comment explicitly warns that legacy compatibility (e.g., GM ISF imports) depends on the *ordinal values* of this enum; changing them would break data import correctness.
---
## 3. Invariants
- **Ordinal stability for `ZeroMethodType`**: The underlying integer values (`0`, `1`, `2`) are part of the contract with legacy data sources (e.g., GM ISF). Reordering, inserting, or modifying values would corrupt imports.
- **Exhaustive status coverage**: `SensorStatus` must account for all known sensor lifecycle states in the system; no new statuses should be added without updating downstream import logic.
- **Nonlinearity method alignment**: `NonLinearStyles` values correspond to specific calibration workflows; each implies a particular data structure or processing pipeline (e.g., `Polynomial` likely requires coefficient arrays, while `IRTraccCalFactor` expects a scalar factor).
---
## 4. Dependencies
- **Depends on**: None (pure enum definitions; no external references).
- **Depended on by**:
- Other types in the `DatabaseImport` module (e.g., sensor record classes, import parsers) that consume these enums to interpret database fields.
- Likely used in serialization/deserialization layers (e.g., JSON/XML converters, database mappers) that handle sensor configuration data.
- Legacy import adapters (e.g., GM ISF importer) rely on `ZeroMethodType`s fixed ordinals for backward compatibility.
---
## 5. Gotchas
- **`ZeroMethodType.None` does *not* mean "no zero calculation" in the intuitive sense**: Its value (`2`) and comment clarify it means "use an absolute/external zero value," not "skip zeroing." Misinterpreting this could lead to incorrect signal offsets.
- **`NonLinearStyles` enum name mismatch**: The file is named `LinearizationFormula.cs`, but the enum is `NonLinearStyles`. This may cause confusion—ensure consumers use the *actual* type name.
- **Missing `Description` attributes**: Though `ZeroMethodType` members have XML summaries, they lack `[Description]` attributes (commented out). If the system relies on reflection-based description resolution (e.g., for UI or logging), this could cause runtime issues.
- **No validation of enum values in source**: The enums themselves do not enforce constraints (e.g., "only one status may be active at a time"). Validation logic, if any, resides elsewhere.
- **No guidance on fallback behavior**: If an unknown `NonLinearStyles` or `SensorStatus` value is encountered during import (e.g., from a newer database), the source provides no indication of how it should be handled (throw? default? warn?).

View File

@@ -0,0 +1,217 @@
---
source_files:
- DataPRO/Modules/DatabaseImporter/DatabaseImport/ISO/TemplateZone.cs
- DataPRO/Modules/DatabaseImporter/DatabaseImport/ISO/CalculatedValueClass.cs
- DataPRO/Modules/DatabaseImporter/DatabaseImport/ISO/LevelTriggerChannel.cs
- DataPRO/Modules/DatabaseImporter/DatabaseImport/ISO/TestObjectChannel.cs
- DataPRO/Modules/DatabaseImporter/DatabaseImport/ISO/TemplateRegion.cs
- DataPRO/Modules/DatabaseImporter/DatabaseImport/ISO/IsoCode.cs
- DataPRO/Modules/DatabaseImporter/DatabaseImport/ISO/TestEngineerDetails.cs
- DataPRO/Modules/DatabaseImporter/DatabaseImport/ISO/TestSetting.cs
- DataPRO/Modules/DatabaseImporter/DatabaseImport/ISO/HardwareChannel.cs
- DataPRO/Modules/DatabaseImporter/DatabaseImport/ISO/TestObjectMetaData.cs
- DataPRO/Modules/DatabaseImporter/DatabaseImport/ISO/CustomerDetails.cs
- DataPRO/Modules/DatabaseImporter/DatabaseImport/ISO/LabratoryDetails.cs
generated_at: "2026-04-16T04:29:31.413854+00:00"
model: "Qwen/Qwen3-Coder-Next-FP8"
schema_version: 1
sha256: "fd925eaa489a9345"
---
# Documentation: ISO Database Import Module Classes
## 1. Purpose
This module provides data transfer objects (DTOs) for importing and exporting ISO-compliant test data from a database. It encapsulates structured representations of test configurations—including templates, zones, regions, channels, triggers, calculated values, and metadata—enabling serialization/deserialization between database rows and in-memory objects. These classes serve as intermediaries between the database layer and higher-level application logic, supporting data migration, configuration management, and ISO standard compliance for crash testing systems.
## 2. Public Interface
### `TemplateZone`
- **`TemplateName`** (`string`, read-only)
Name of the template this zone belongs to.
- **`ZoneName`** (`string`)
Name of the zone; defaults to `"Default zone"` if null in database.
- **`Picture`** (`string`, read/write)
Path or identifier for an associated picture.
- **`Description`** (`string`)
Zone description; defaults to empty string if null in database.
- **`TemplateRegions`** (`TemplateRegion[]`, read/write)
Array of regions associated with this zone; populated via `TemplateRegion.GetAllRegions()` in the `DataRow` constructor.
### `CalculatedValueClass`
- **`Id`** (`int`)
Unique identifier; defaults to `-1`.
- **`Operation`** (`Operations` enum)
Operation type: `SUM`, `AVERAGE`, `IRTRACC3D`, `IRTRACC3D_ABDOMEN`, `IRTRACC3D_LOWERTHORAX`. Defaults to `SUM`.
- **`CalculatedValueCode`** (`string`)
Code string; defaults to `"???????????????X"`.
- **`InputChannelIds`** (`string[]`, read/write)
Array of input channel IDs; backed by `InputChannelIdsBlob`.
- **`InputChannelIdsBlob`** (`byte[]`, read/write)
UTF-8 encoded blob of channel IDs joined by `CultureInfo.InvariantCulture.TextInfo.ListSeparator`.
- **`CFCForInputChannels`** (`string`)
Filter class for input channels; defaults to `""`.
- **`ChannelFilterClassForOutput`** (`string`)
Filter class for output; defaults to `""`.
- **`TestSetupName`**, **`Name`** (`string`)
Test setup and calculated channel names.
### `LevelTriggerChannel`
- **`TestSetupName`**, **`GroupSerialNumber`**, **`TestObjectChannelId`**, **`HardwareChannelId`**, **`SensorSerialNumber`** (`string`)
Identifiers for test context and hardware.
- **`GreaterThanEnabled`** (`bool`)
Whether high-threshold triggering is enabled; defaults to `true`.
- **`GreaterThanThresholdEU`**, **`LessThanThresholdEU`** (`double`)
High and low threshold values in engineering units.
- **`LessThanEnabled`** (`bool`)
Whether low-threshold triggering is enabled.
- **`TriggerBetweenBounds`**, **`TriggerOutsideBounds`** (`bool`)
Bounds-triggering modes.
- **`InsideUpperLevelEU`**, **`InsideLowerLevelEU`**, **`OutsideUpperLevelEU`**, **`OutsideLowerLevelEU`** (`double`)
Upper/lower bounds for inside/outside triggering.
### `TestObjectChannel`
- **`Disabled`** (`bool`)
Whether the channel is excluded from data collection.
- **`ChannelIdx`** (`int`)
Channel index; `CHANNEL_IDX_UNKNOWN = -1` if unset.
- **`SensorSerialNumber`**, **`HardwareId`** (`string`)
Sensor and hardware channel identifiers; `HardwareId` setter normalizes format (e.g., strips `x` separators).
- **`SquibChannelType`** (`SquibChannelTypes` enum)
Channel type: `None`, `Voltage`, or `Current`.
- **`TestObject`** (`ISO.TestObject`)
Parent test object instance.
- **`CompareTo(TestObjectChannel)`** (`int`)
Comparison for sorting: by `DisplayOrder`, then `Name`, then `TestObject.SerialNumberOrOriginalSerialNumber`.
- **`GetGraphId()`**, **`GetId()`**, **`GetIdWithSpecificChannelId(long)`** (`string`)
Generate unique channel identifiers; `GetGraphId()` appends `DTS.Common.Constants.CURRENT_SUFFIX` for current-type squib channels.
### `TemplateRegion`
- **`TemplateName`**, **`TemplateZone`** (`string`, read-only)
Template and zone names.
- **`RegionNumber`**, **`RegionName`**, **`RegionDescription`** (`int`, `string`)
Region metadata.
- **`TestObject`**, **`Position`**, **`MainLocation`**, **`FineLocation13`**, **`PhysicalDimension`**, **`Direction`**, **`FilterClass`** (`string`)
Spatial and classification attributes.
- **`LocalOnly`** (`bool`, read-only)
Whether region is local-only.
- **`UpperLeft`**, **`LowerRight`** (`System.Drawing.Point`)
Bounding box coordinates.
- **`GetAllRegions(string templateName, string zoneName)`** (`TemplateRegion[]`, internal static)
Fetches regions from database via stored procedure `sp_TemplateRegionsGet`.
### `IsoCode`
- **`StringRepresentation`** (`string`, read/write)
16-character ISO code string; pads with `'?'` if shorter, truncates if longer.
- **`GetString(MMEPossibleChannels, bool careAboutTestTimeFields)`** (`string`, static)
Generates ISO code from channel metadata; masks `Test_Object` and `Default_Filter_Class` with `'?'` if `careAboutTestTimeFields` is `false`.
- **`GetString(...)`** (`string`, static)
Direct concatenation of ISO components.
### `TestEngineerDetails`
- **`TestEngineerName`**, **`TestEngineerPhone`**, **`TestEngineerFax`**, **`TestEngineerEmail`** (`string`)
Contact info; setters ignore empty strings.
- **`LocalOnly`** (`bool`)
Scope flag.
- **`Name`**, **`LastModified`**, **`LastModifiedBy`**, **`Version`** (`string`, `DateTime`, `string`, `int`)
Metadata fields.
- **`DeleteAllTestEngineerDetails()`**, **`GetAllTestEngineerDetails()`** (`void`, `TestEngineerDetails[]`, static)
Database CRUD operations.
### `TestSetting`
- **`Id`**, **`Value`**, **`DefaultValue`** (`string`)
Setting identifier, current value, and default value.
- **`ToSerializeString()`** (`string`)
Serializes as `Id=SEPARATOR=SEPARATOR=Value`.
- **`TryParse(string, out TestSetting)`** (`bool`, static)
Parses serialized string; sets `DefaultValue = Value` on success.
### `TestSettingDictionary`
- **`GetValue(string id, string defaultValue)`** (`string`)
Returns `Value` if present, else `DefaultValue`.
- **`SetValue(TestSetting, string)`**, **`SetValue(TestSetting)`**, **`SetValue(string, string)`** (`void`)
Updates or adds settings.
- **`ToSerializeString()`**, **`LoadSettings(string)`** (`string`, `void`)
Serializes/deserializes settings using `ListSeparator` as delimiter.
### `HardwareChannel`
- **`ParentDAS`** (`Hardware`)
Parent data acquisition system.
- **`SupportedBridges`**, **`SupportedExcitations`**, **`SupportedDigitalInputModes`**, **`SupportedDigitalOutputModes`**, **`SupportedSquibFireModes`** (`int`)
Hardware capabilities.
- **`ChannelIdx`**, **`DASDisplayOrder`**, **`ModuleSerialNumber`**, **`ModuleArrayIndex`** (`int`, `int`, `string`, `int`)
Channel identification and positioning.
- **`LocalOnly`** (`bool`)
Scope flag.
- **`PhysicalCompare(HardwareChannel, HardwareChannel)`** (`int`, static)
Compares by `ChannelIdx`.
### `TestObjectMetaData`, `TestSetupMetaData`
- **`TestObject`** (`char`)
Test object identifier (e.g., `'?'`).
- **`Version`** (`double`)
Schema version (`1.06`).
- **`NOVALUE`** (`const string`)
Placeholder for unset values (`"NOVALUE"`).
- **`SetProperty(MetaData)`** (`void`)
Adds/updates metadata properties.
- **`MetaData`**
- `Name`, `IsOptional`, `Value`, `Version` (`string`, `bool`, `string`, `double`)
- Represents a single metadata field.
### `CustomerDetails`
- **`CustomerName`**, **`CustomerTestRefNumber`**, **`ProjectRefNumber`**, **`CustomerOrderNumber`**, **`CustomerCostUnit`** (`string`)
Customer-related identifiers; setters ignore empty strings for non-required fields.
- **`LocalOnly`**, **`Name`**, **`LastModified`**, **`LastModifiedBy`**, **`Version`** (`bool`, `string`, `DateTime`, `string`, `int`)
Metadata fields.
- **`ReadXML(XmlElement)`**, **`WriteXML(ref XmlWriter)`**, **`DeleteCustomerDetails(string)`** (`CustomerDetails`, `void`, `void`, static)
XML persistence and deletion.
### `LabratoryDetails`
- **`LabratoryName`**, **`LabratoryContactName`**, **`LabratoryContactPhone`**, **`LabratoryContactFax`**, **`LabratoryContactEmail`**, **`LabratoryTestRefNumber`**, **`LabratoryProjectRefNumber`** (`string`)
Laboratory contact and reference data.
- **`Name`**, **`LocalOnly`**, **`LastModified`**, **`LastModifiedBy`**, **`Version`** (`string`, `bool`, `DateTime`, `string`, `int`)
Metadata fields.
- **`ReadXML(XmlElement)`**, **`DeleteLabratoryDetails()`** (`LabratoryDetails`, `void`, static)
XML persistence and deletion.
## 3. Invariants
- **`TemplateZone.ZoneName`**: Defaults to `"Default zone"` if database `ZoneName` is `DBNull`.
- **`TemplateZone.Description`**: Defaults to `""` if database `ZoneDescription` is `DBNull`.
- **`CalculatedValueClass.InputChannelIds`**: Stored as a `byte[]` blob using `CultureInfo.InvariantCulture.TextInfo.ListSeparator` as delimiter; deserialization splits on this separator.
- **`TestObjectChannel.HardwareId`**: Setter enforces format `prefix_number` (e.g., strips `x` separators beyond the first two segments).
- **`IsoCode.StringRepresentation`**: Always exactly 16 characters; missing characters padded with `'?'`, excess truncated.
- **`TestSettingDictionary`**: Preserves `DefaultValue` from existing settings during `LoadSettings`; only updates `Value`.
- **`TestEngineerDetails`, `CustomerDetails`, `LabratoryDetails`**: Contact fields (`Phone`, `Fax`, `Email`) ignore empty-string assignments.
- **`LevelTriggerChannel`**: Constructor silently ignores exceptions during field parsing (commented logging).
- **`TemplateRegion.GetAllRegions`**: Returns empty array on failure; logs exceptions (commented).
- **`HardwareChannel`**: Implements `INotifyPropertyChanged`; `SetProperty` raises `PropertyChanged` only on change.
## 4. Dependencies
- **Database Layer**:
- `DbOperations`, `DbOperationsEnum.StoredProcedure`, `DTS.Common.Storage.DbOperations` (e.g., `TestEngineerDetailsGet`, `CustomerDetailsDelete`, `LabratoryDetailsDelete`, `sp_TemplateRegionsGet`).
- `System.Data`, `System.Data.SqlClient` (ADO.NET types).
- **Core Types**:
- `DTS.Common.Constants.CURRENT_SUFFIX` (used in `TestObjectChannel.GetGraphId()`).
- `DTS.Common.Interface.TestMetaData.ITestEngineerDetailsDbRecord` (used in `TestEngineerDetails` constructor).
- `System.Drawing.Point` (used in `TemplateRegion`).
- **Serialization**:
- `System.Xml` (XML persistence in `CustomerDetails`, `LabratoryDetails`).
- `System.Text.Encoding`, `System.Globalization.CultureInfo` (used in `CalculatedValueClass` and `TestSetting`).
- **Inheritance/Usage**:
- `TestObjectChannel` extends `TestObjectTemplateChannel` and implements `IComparable<TestObjectChannel>`.
- `HardwareChannel` implements `INotifyPropertyChanged`.
## 5. Gotchas
- **`TemplateRegion.GetAllRegions`**: Uses `internal` access and database calls; not testable without database connectivity.
- **`LevelTriggerChannel` constructor**: Swallows all exceptions during deserialization (commented logging); may silently fail to populate fields.
- **`CalculatedValueClass.InputChannelIdsBlob`**: Uses `CultureInfo.InvariantCulture.TextInfo.ListSeparator` (typically `','`), but this may conflict with IDs containing commas.
- **`TestObjectChannel.HardwareId` setter**: Normalizes input by stripping `x` separators beyond the first two segments; may alter expected values unexpectedly.
- **`IsoCode`**: Masks `Test_Object` and `Default_Filter_Class` with `'?'` when `careAboutTestTimeFields` is `false`, but does not validate input strings (e.g., null/empty `Direction` may cause `IndexOutOfRangeException`).
- **`TestSettingDictionary.ToSerializeString`**: Uses `ListSeparator` as delimiter between settings, but escapes `=` with `SEPARATOR = "_x_"` or `"_X_"`; mismatched separators in `LoadSettings` could cause parsing errors.
- **`TestEngineerDetails`, `CustomerDetails`, `LabratoryDetails`**: Contact fields ignore empty strings, but `NOVALUE` is used as default—this may cause confusion if `NOVALUE` is stored in the database.
- **`TemplateZone`**: `TemplateRegions` is populated only in the `DataRow` constructor; the parameterized constructor does not initialize regions.
- **`TestObjectMetaData`/`TestSetupMetaData`**: `NOVALUE` is used as default, but `TestSetupMetaData` replaces `NOVALUE` with `string.Empty` for specific fields when `requireXCrashCompatibilityForISOExports` is `true`.

View File

@@ -0,0 +1,41 @@
---
source_files:
- DataPRO/Modules/DatabaseImporter/DatabaseImport/Interface/DataRecorders/IHardwareChannel.cs
- DataPRO/Modules/DatabaseImporter/DatabaseImport/Interface/DataRecorders/IDASHardware.cs
generated_at: "2026-04-16T04:31:18.077844+00:00"
model: "Qwen/Qwen3-Coder-Next-FP8"
schema_version: 1
sha256: "bd947523624c1bb7"
---
# DataRecorders
## 1. Purpose
This module defines foundational interfaces (`IHardwareChannel` and `IDASHardware`) within the `DatabaseImport` namespace, intended to represent abstractions for hardware-related data entities during TTS (presumably *Test Time Series* or similar) database import operations. As of the provided source, these interfaces are empty markers—likely placeholders for future extension or for use in type constraints elsewhere in the codebase—but they establish a conceptual separation between channel-specific hardware (`IHardwareChannel`) and general hardware (`IDASHardware`) within the import pipeline.
## 2. Public Interface
No public members are defined on either interface.
- **`IHardwareChannel`**
- *Type*: `interface`
- *Namespace*: `DatabaseImport`
- *Description*: Marker interface intended to represent a hardware channel in TTS import. Currently has no members.
- **`IDASHardware`**
- *Type*: `interface`
- *Namespace*: `DatabaseImport`
- *Description*: Marker interface representing hardware in TTS import, per its XML summary. Currently has no members.
## 3. Invariants
- Both interfaces are *marker interfaces* with no state or behavior defined; thus, no behavioral invariants apply.
- No explicit constraints (e.g., inheritance, implementation requirements) are declared in the source.
## 4. Dependencies
- **Imports/References**: Neither interface declares any `using` directives or external dependencies in the provided source.
- **Depended upon**: Inferred from naming and namespace (`DatabaseImport.Interface.DataRecorders`), these interfaces are likely consumed by other components in the `DatabaseImporter` module (e.g., concrete recorder classes, import logic), but no such consumers are visible in the provided files.
## 5. Gotchas
- **Ambiguity in intent**: The distinction between `IHardwareChannel` and `IDASHardware` is not documented beyond their names. Without further context (e.g., implementation files, usage sites), it is unclear whether they are meant to be mutually exclusive, hierarchical, or overlapping.
- **Empty interfaces**: As marker interfaces with no methods or properties, they provide no runtime guarantees—consumers must rely on external documentation or conventions to interpret their meaning.
- **No versioning or deprecation cues**: No attributes (e.g., `[Obsolete]`) or comments suggest these are deprecated or experimental.
- *None identified from source alone.*

View File

@@ -0,0 +1,30 @@
---
source_files:
- DataPRO/Modules/DatabaseImporter/DatabaseImport/Interface/Hardware/IISOHardware.cs
generated_at: "2026-04-16T04:31:11.809282+00:00"
model: "Qwen/Qwen3-Coder-Next-FP8"
schema_version: 1
sha256: "31b50715cab0bca0"
---
# Hardware
1. **Purpose**
This module defines the `IISOHardware` interface within the `DatabaseImport` namespace, which appears to be part of a larger system responsible for importing data—likely from external sources—into a database. The interface currently serves as an empty marker interface, suggesting it is intended to represent or categorize hardware-related entities involved in the import process (e.g., ISO-compliant hardware specifications or devices), but no behavior or contract has yet been defined.
2. **Public Interface**
No public methods, properties, or events are defined. The interface `IISOHardware` is empty and contains no members.
3. **Invariants**
No invariants can be inferred, as the interface imposes no constraints or guarantees. Its sole purpose at this stage appears to be type identification or tagging.
4. **Dependencies**
- **Internal**: This interface resides in the `DatabaseImport` namespace, implying it is part of the `DatabaseImporter` module, likely consumed by other components in the same assembly or dependent assemblies (e.g., import pipeline logic, hardware mapping layers).
- **External**: No external dependencies are referenced in this file.
- **Consumers**: Unknown from this file alone; would require analysis of other modules (e.g., classes implementing `IISOHardware` or methods accepting `IISOHardware` as a parameter).
5. **Gotchas**
- **Empty Interface Risk**: As a marker interface with no members, `IISOHardware` may be a placeholder for future functionality. Developers should verify whether implementations are expected to exist elsewhere or if this interface is intended to be extended in a future version.
- **Ambiguous Semantics**: Without documentation or usage context, it is unclear what qualifies as "ISOHardware"—e.g., whether it refers to ISO/IEC 14443, ISO 8583, or another standard.
- **No Validation or Contract**: Consumers cannot rely on any behavioral guarantees; runtime type checks (`is IISOHardware`) may be used for categorization only.
- **None identified from source alone.**

View File

@@ -0,0 +1,41 @@
---
source_files:
- DataPRO/Modules/DatabaseImporter/DatabaseImport/Interface/Sensors/ISensorData.cs
- DataPRO/Modules/DatabaseImporter/DatabaseImport/Interface/Sensors/ISensorCalibration.cs
- DataPRO/Modules/DatabaseImporter/DatabaseImport/Interface/Sensors/ICalibrationRecords.cs
generated_at: "2026-04-16T04:31:06.327262+00:00"
model: "Qwen/Qwen3-Coder-Next-FP8"
schema_version: 1
sha256: "21dc4c3dfa01bdb8"
---
# Sensors
## 1. Purpose
This module defines a set of empty marker interfaces (`ISensorData`, `ISensorCalibration`, `ICalibrationRecords`) within the `DatabaseImport` namespace. These interfaces serve as type contracts or tags for sensor-related data structures involved in database import operations, likely intended to be implemented by concrete classes elsewhere in the codebase. Their purpose is to enable compile-time type safety and polymorphic handling of sensor data, calibration metadata, and calibration record collections during data ingestion—though the interfaces themselves contain no members and thus convey no behavioral semantics.
## 2. Public Interface
No public members are defined in any of the interfaces. All three interfaces are empty:
- `ISensorData`
- *Description:* Marker interface for sensor data types. Intended to be implemented by classes representing raw or processed sensor measurements (e.g., temperature, pressure readings).
- `ISensorCalibration`
- *Description:* Marker interface for sensor calibration parameters or coefficients (e.g., offset, gain, polynomial terms).
- `ICalibrationRecords`
- *Description:* Marker interface for collections or containers of calibration records (e.g., time-series of calibration events or lookup tables).
## 3. Invariants
- All three interfaces are *marker interfaces* (also known as tag interfaces): they impose no runtime constraints, validation rules, or behavioral guarantees.
- Implementing types are not required to expose any specific properties, methods, or events by virtue of implementing these interfaces.
- No ordering, lifecycle, or consistency guarantees are enforced by these interfaces alone.
## 4. Dependencies
- **Namespace:** All interfaces reside in the `DatabaseImport` namespace, suggesting they are part of a larger database import pipeline module (`DataPRO/Modules/DatabaseImporter/DatabaseImport`).
- **Usage context (inferred):** These interfaces are likely referenced by other types in the `DatabaseImport` module (e.g., import handlers, mappers, or validators) that operate on sensor-related data. However, no direct dependencies (imports, `using` statements, or references) are visible in the provided source files.
- **No external dependencies** are declared in the source files (no `using` directives or external references).
## 5. Gotchas
- **Empty interfaces may indicate incomplete or aspirational design:** These interfaces currently convey no semantics and could be placeholders for future functionality. Relying on them for type-based dispatch without additional constraints (e.g., via generics or attributes) may lead to runtime errors if implementers do not conform to expected conventions.
- **No documentation or examples provided:** The absence of XML comments or sample implementations makes it unclear how these interfaces are intended to be used or what concrete types implement them.
- **Risk of misuse:** Developers may incorrectly assume these interfaces imply specific data structures or behaviors (e.g., that `ISensorData` implies a `Timestamp` or `Value` property), leading to assumptions not enforced by the type system.
- **None identified from source alone** — but the emptiness of the interfaces themselves is a potential anti-pattern requiring external context to validate correctness.

View File

@@ -0,0 +1,31 @@
---
source_files:
- DataPRO/Modules/DatabaseImporter/DatabaseImport/Interface/TestSetups/TestSetupsList/ITestSetup.cs
generated_at: "2026-04-16T04:31:20.119441+00:00"
model: "Qwen/Qwen3-Coder-Next-FP8"
schema_version: 1
sha256: "1e3ba8a6dc409c4f"
---
# TestSetupsList
1. **Purpose**
This module defines the `ITestSetup` interface, a marker interface intended to identify types that represent test setup configurations within the `DatabaseImport` modules test infrastructure. Its existence suggests a design pattern where different test scenarios or data initialization routines can be tagged and potentially discovered or processed via reflection or dependency injection—though the interface itself currently carries no members, indicating it may be a placeholder for future extensibility or a convention-based tagging mechanism.
2. **Public Interface**
- **`ITestSetup`** (`interface`)
A marker interface with no members. Any class implementing `ITestSetup` is considered a test setup definition. As written, it provides no behavioral contract—its sole purpose is type identification.
3. **Invariants**
- Any type claiming to implement `ITestSetup` must be a class (interfaces cannot be instantiated directly).
- Since the interface is empty, there are no runtime invariants enforced by its definition. Validation or ordering guarantees (if any) must be enforced by consumers of this interface, which are not visible in this file.
4. **Dependencies**
- **Internal**: Depends only on the `DatabaseImport` namespace (no external or framework imports beyond standard C# runtime).
- **Consumers**: Unknown from this file alone. The interface is likely used elsewhere in the `DatabaseImport` module (e.g., in test runners, setup factories, or DI containers), but no such usages are present in the provided source.
5. **Gotchas**
- The interface is currently a *marker interface* with no methods or properties, which may indicate incomplete implementation or reliance on external conventions (e.g., naming, attributes, or DI registration).
- Developers may mistakenly assume `ITestSetup` implies lifecycle management, initialization logic, or configuration capabilities—none of which are defined here.
- No documentation comments or attributes (e.g., `[Obsolete]`, `[EditorBrowsable]`) are present, so tooling or future maintainers may lack context about intended usage.
- None identified from source alone.

View File

@@ -0,0 +1,65 @@
---
source_files:
- DataPRO/Modules/DatabaseImporter/DatabaseImport/Properties/AssemblyInfo.cs
- DataPRO/Modules/DatabaseImporter/DatabaseImport/Properties/Settings.Designer.cs
generated_at: "2026-04-16T04:30:25.113253+00:00"
model: "Qwen/Qwen3-Coder-Next-FP8"
schema_version: 1
sha256: "ae1921064164fa41"
---
# Properties
## Documentation: DatabaseImport Module
### 1. Purpose
This module (`DatabaseImport`) is a .NET assembly responsible for managing database import functionality within the DataPRO system. It provides configuration-driven behavior for import operations, including specifying where downloaded data is stored (`DownloadFolder`), controlling whether automatic arming of systems is permitted (`AllowAutoArm`), defining calibration warning thresholds (`CalWarningPeriodDays`), selecting the target database type (`DBType`), and enforcing compatibility requirements for ISO export generation (`RequireXCrashCompatibilityForISOExports`). Its role is to encapsulate and expose application-level settings used during database import workflows.
### 2. Public Interface
The module exposes only one public type:
- **`DatabaseImport.Properties.Settings`** (internal sealed class, but accessible via `Settings.Default` static property)
A strongly-typed settings class derived from `System.Configuration.ApplicationSettingsBase`. Provides read/write access to application and user-scoped configuration values.
- **`public static Settings Default { get; }`**
Returns the singleton instance of the `Settings` class, synchronized for thread safety.
- **`public string DownloadFolder { get; }`**
*Application-scoped*. Returns the default path for downloaded data files. Default value: `"..\Data"`.
- **`public bool AllowAutoArm { get; }`**
*Application-scoped*. Controls whether automatic arming (likely of measurement or acquisition systems) is permitted during import. Default value: `false`.
- **`public int CalWarningPeriodDays { get; set; }`**
*User-scoped*. Specifies the number of days before calibration expiry at which a warning should be issued. Default value: `7`. Supports runtime modification (setter present).
- **`public int DBType { get; }`**
*Application-scoped*. Encodes the type of database to target for import (e.g., enum-like integer). Default value: `1`. Interpretation of values is not defined in this file.
- **`public bool RequireXCrashCompatibilityForISOExports { get; }`**
*Application-scoped*. Enforces compatibility with "XCrash" format when exporting ISO data. Default value: `true`.
### 3. Invariants
- `Settings.Default` is a singleton and thread-safe (via `ApplicationSettingsBase.Synchronized`).
- `DownloadFolder`, `AllowAutoArm`, `DBType`, and `RequireXCrashCompatibilityForISOExports` are *application-scoped* and immutable at runtime (read-only properties).
- `CalWarningPeriodDays` is *user-scoped* and mutable at runtime (has a public setter).
- All settings have explicitly defined default values via `[DefaultSettingValueAttribute]`.
- No runtime validation of setting values (e.g., `DBType` values, `CalWarningPeriodDays` sign) is present in this file.
### 4. Dependencies
- **Dependencies of this module**:
- `System.Configuration` (for `ApplicationSettingsBase`, attributes like `ApplicationScopedSettingAttribute`, `UserScopedSettingAttribute`)
- `System.Runtime.CompilerServices`, `System.CodeDom.Compiler`, `System.Diagnostics` (for attributes)
- `System` (core types)
- **Depended upon by**:
- Other modules in the `DataPRO.Modules.DatabaseImporter` solution (e.g., import logic that consumes `Settings.Default.DownloadFolder`, `Settings.Default.DBType`, etc.).
- UI layers (e.g., settings dialogs) that bind to `Settings.Default` for user-modifiable values like `CalWarningPeriodDays`.
### 5. Gotchas
- **`DBType` semantics are opaque**: The integer value has no documented meaning (e.g., 1 = SQLite? SQL Server? Custom DB?). Consumers must infer or document externally.
- **`DownloadFolder` is relative**: Path `"..\Data"` is relative to the applications base directory; behavior may vary if the app is launched from a different working directory.
- **No schema versioning**: Settings are not versioned or migrated; changing defaults (e.g., `DBType`) may break existing user configurations if not handled by a higher-level updater.
- **`AllowAutoArm` default is `false`**: If auto-arm is expected to be enabled by default in production, this may indicate legacy or safety-conscious design.
- **User-scoped settings persist per-user**: Changes to `CalWarningPeriodDays` are saved per-user profile; may cause inconsistent behavior in shared environments (e.g., terminals, kiosks).
- **Auto-generated file**: `Settings.Designer.cs` is generated by Visual Studios Settings Designer; manual edits risk being overwritten.
None identified beyond the above.

View File

@@ -0,0 +1,239 @@
---
source_files:
- DataPRO/Modules/DatabaseImporter/DatabaseImport/SensorDB/SensorRange.cs
- DataPRO/Modules/DatabaseImporter/DatabaseImport/SensorDB/SensorDB.cs
- DataPRO/Modules/DatabaseImporter/DatabaseImport/SensorDB/DigitalInputSetting.cs
- DataPRO/Modules/DatabaseImporter/DatabaseImport/SensorDB/DigitalOutputSetting.cs
- DataPRO/Modules/DatabaseImporter/DatabaseImport/SensorDB/SquibSetting.cs
- DataPRO/Modules/DatabaseImporter/DatabaseImport/SensorDB/FilterClass.cs
- DataPRO/Modules/DatabaseImporter/DatabaseImport/SensorDB/SensorCalibrationList.cs
- DataPRO/Modules/DatabaseImporter/DatabaseImport/SensorDB/CalibrationRecords.cs
- DataPRO/Modules/DatabaseImporter/DatabaseImport/SensorDB/IsoCode.cs
- DataPRO/Modules/DatabaseImporter/DatabaseImport/SensorDB/SensorsCollection.cs
- DataPRO/Modules/DatabaseImporter/DatabaseImport/SensorDB/SensorCalibration.cs
generated_at: "2026-04-16T04:31:14.887778+00:00"
model: "Qwen/Qwen3-Coder-Next-FP8"
schema_version: 1
sha256: "927e0a96c4cf2bf8"
---
# Sensor Database Module Documentation
## 1. Purpose
This module provides data structures and services for importing, managing, and accessing sensor configuration and calibration data from a database into the DataPRO system. It defines concrete types for various sensor categories (analog, digital input, digital output, squib), their associated calibration records, and supporting classes for ISO code parsing, filter classification, and range definitions. The module acts as the data layer abstraction for sensor metadata, enabling consistent representation of sensor properties, calibration parameters, and configuration settings across the application.
## 2. Public Interface
### Classes
#### `SensorRange`
- **`SensorRange(string value)`**
Parses a comma-separated string of three doubles into `Low`, `Medium`, and `High` properties. Throws `InvalidDataException` if the input does not contain exactly three values.
- **`SensorRange(double low, double medium, double high)`**
Constructor that directly initializes `Low`, `Medium`, and `High` properties.
#### `LowHigh`
- **`LowHigh(double low, double high)`**
Constructor initializing `Low` and `High` properties.
- **`LowHigh(string value)`**
Parses a comma-separated string of two doubles into `Low` and `High`. Throws `InvalidDataException` if fewer than two values are present. Uses `InvariantCulture` for parsing.
#### `FilterClass`
- **`FilterClass(FilterClassType fc)`**
Constructor initializing `FClass` and `Frequency` based on predefined CFC filter types. Throws `Exception` for unknown types.
- **`FilterClass(string fclass)`**
Constructor parsing a string representation (e.g., `"17"`, `"CFC60"`, `"1000"`, `"AdHoc"`) into `FClass` and `Frequency`. Supports numeric codes, CFC names, and arbitrary numeric values for `AdHoc`.
- **`ToString()`**
Returns a human-readable string representation (e.g., `"17 (CFC10)"`, `"None"`, `"100"` for `AdHoc`).
- **`FilterClassType` enum**:
`None = 0`, `AdHoc = -1`, `CFC10 = 17`, `CFC60 = 100`, `CFC180 = 300`, `CFC600 = 1000`, `CFC1000 = 1650`.
#### `IsoCode`
- **`IsoCode(string isoCode)`**
Constructor initializing the 16-character ISO code. Truncates or pads with `'?'` as needed.
- **`StringRepresentation` property (string)**
Gets/sets the full 16-character ISO code string.
- **Component properties** (all `string` type, each representing a fixed-width segment):
- `TestObject` (1 char, index 0)
- `Position` (1 char, index 1)
- `MainLocation` (4 chars, indices 25)
- `FineLocation1` (2 chars, indices 67)
- `FineLocation2` (2 chars, indices 89)
- `FineLocation3` (2 chars, indices 1011)
- `PhysicalDimension` (2 chars, indices 1213)
- `Direction` (1 char, index 14)
- `FilterClass` (1 char, index 15)
Each property setter pads with `'?'` or truncates as needed; empty or null inputs default to `'?'`.
#### `SensorCalibration`
- **`SensorCalibration()`**
Default constructor.
- **`SensorCalibration(string s)`**
Deserializes from a `ListSeparator`-delimited string (see `SEPARATOR_REPLACEMENT`).
- **`SensorCalibration(DataRow dr)`**
Populates from a database row using `DbOperations.SensorDB.SensorCalibrationFields` enum.
- **`SensorCalibration(SensorCalibration sc)`**
Copy constructor.
- **`FromSerializedString(string s)`**
Deserializes from a string using `SEPARATOR_REPLACEMENT` (`"__SC__"`) to escape list separators.
- **`NewDigitalSC()`**
Static factory returning a default calibration for digital sensors (`Sensitivity=1`, `EngineeringUnits="V"`, `Excitation=Volt5`, `IsProportional=false`, `RemoveOffset=false`).
- **`GetLatestCalibrationBySerialNumberAndExcitation(SensorData sd, ExcitationVoltageOption exc)`**
Static method delegating to `SensorCalibrationList.GetLatestCalibrationBySerialNumberAndExcitation`.
- **`CompareTo(SensorCalibration other)`**
Implements `IComparable<SensorCalibration>`: sorts descending by `CalibrationDate`, then `ModifyDate`, then `CalVersion`.
- **Properties**:
- `CalVersion` (`long`)
- `CalibrationDate` (`DateTime`)
- `ModifyDate` (`DateTime`)
- `SerialNumber` (`string`)
- `Username` (`string`)
- `Records` (`CalibrationRecords`)
- `IsProportional` (`bool`, read-only logic: `!NonLinear && _isProportional`)
- `RemoveOffset` (`bool`, read-only logic: `!NonLinear && _bRemoveOffset`)
- `NonLinear` (`bool`)
- `LocalOnly` (`bool`)
- `ZeroMethod` (`ZeroMethod`)
- `InitialOffset` (`InitialOffset`)
- `CertificationDocuments` (`string[]`)
#### `SensorCalibrationList`
- **`Reload()`**
Static method that clears and rebuilds the internal `_calibrationList` singleton instance (thread-safe via `LOCK`).
- **`GetLatestCalibrationBySerialNumberAndExcitation(SensorData sd, ExcitationVoltageOption exc)`**
Static method returning the most recent calibration for a given sensor and excitation. Returns `SensorCalibration.NewDigitalSC()` for digital/squib types. Uses `_cachedCalibrations` if available; otherwise queries `_calibrationList`.
- **`DeleteAll()`**
Static method calling stored procedure `sp_SensorCalibrationsDelete`, clearing `_calibrationList._calibrations`, and logging errors.
#### `CalibrationRecords`
- **`CalibrationRecords()`**
Default constructor initializing `Records` to a single default `CalibrationRecord`.
- **`CalibrationRecords(string records)`**
Parses a serialized string using `"__x__"` as primary separator and `"___xx___"` as backup escape sequence.
- **`CalibrationRecords(CalibrationRecords copy)`**
Deep copy constructor.
- **`FromSerializedString(string s)`**
Parses serialized string into `Records` array.
#### `CalibrationRecord`
- **`CalibrationRecord()`**
Default constructor initializing `Poly` to a new `LinearizationFormula`.
- **`CalibrationRecord(string s)`**
Parses from a `ListSeparator`-delimited string (e.g., `";"` in `InvariantCulture`).
- **`CalibrationRecord(CalibrationRecord copy)`**
Copy constructor.
- **`FromString(string s)`**
Deserializes from a `ListSeparator`-delimited string. Uses `"x_Separator_x"` as escape sequence for list separators.
- **Properties**:
- `Sensitivity` (`double`)
- `ZeroPoint` (`double`, computed from `Poly.ZeroPositionIntercept / Poly.CalibrationFactor` if `Poly.CalibrationFactor != 0`, else stored `_zeroPoint`)
- `Poly` (`LinearizationFormula`)
- `AtCapacity` (`bool`)
- `EngineeringUnits` (`string`, default `"g"`)
- `SensitivityUnits` (`SensUnits`, default `NONE`)
- `Excitation` (`ExcitationVoltageOption`, default `Volt5`)
- `CapacityOutputIsBasedOn` (`double`, default `1.0`)
#### `DigitalInputSetting`
- **`DigitalInputSetting(IDataRecord reader)`**
Constructor populating from database record using `DbOperations.DigitalInputSettings.Fields` enum. Calls `SetDefaults(this)` first. Catches and logs exceptions.
- **`SetDefaults(SensorData sd)`**
Static method setting default values for digital input sensors (e.g., `Bridge=DigitalInput`, `Capacity=1`, `DisplayUnit="V"`, `Shunt=ShuntMode.None`).
#### `DigitalOutputSetting`
- **`DigitalOutputSetting()`**
Default constructor calling `SetDefaults(this)`.
- **`DigitalOutputSetting(IDataRecord reader)`**
Constructor populating from database record using `DbOperations.DigitalOutputSettings.Fields` enum. Sets `Bridge` to `TOMDigital` before calling `SetDefaults(this)`.
- **`ChannelDescription` property**
Getter returns `SerialNumber`; setter assigns to `SerialNumber` and raises `PropertyChanged("ChannelDescription")`.
- **`SetDefaults(SensorData sd)`**
Static method setting defaults for digital output sensors (e.g., `Bridge=TOMDigital`, `SupportedExcitation=[Volt5]`, `DisplayUnit="V"`).
#### `SquibSetting`
- **`SquibSetting(IDataRecord reader)`**
Constructor populating from database record using `DbOperations.Squib.Fields` enum. Calls `SetDefaults(this)` first, then overrides with DB values. Ensures `Comment` is non-null (defaults to `SerialNumber` if empty).
- **`SquibDescription` property**
Getter returns `SerialNumber`; setter assigns to `SerialNumber` and raises `PropertyChanged("SquibDescription")`.
- **`ArticleId` property**
Getter returns `Id`; setter assigns to `Id` and raises `PropertyChanged("ArticleId")`.
- **`BypassCurrentFilter` / `BypassVoltageFilter` properties**
Boolean properties with `SetProperty` pattern for `INotifyPropertyChanged`.
- **`SetDefaults(SensorData sd)`**
Static method setting defaults for squib sensors (e.g., `Bridge=SQUIB`, `Capacity=5`, `SupportedExcitation=[Volt5]`, `DisplayUnit="V"`).
#### `SensorsCollection`
- **`SensorsList` property**
Static singleton property (thread-safe via `Lock`).
- **`GetSensorBySerialNumber(string serialNumber, bool excludeBroken = true, bool bUseCache = true)`**
Returns a `SensorData` (or derived type) by serial number. Checks cache first if `bUseCache`. Queries database via stored procedures in order: `sp_SensorsAnalogGet`, `sp_SensorsDigitalInGet`, `sp_SensorsSquibGet`, `sp_SensorsDigitalOutGet`. Returns `null` if not found. Handles test-specific digital output serial numbers.
- **`DeleteAll()`**
Static method calling `sp_SensorDeleteAll` stored procedure, then calling `SensorCalibrationList.DeleteAll()`, and raising `OnPropertyChanged("AllSensors")`.
- **`HookedUp` property**
Controls whether `OnPropertyChanged` events are raised (if `false`, events suppressed).
### Enums
#### `ShuntMode` (SensorDB.cs)
`None`, `Emulation`, `Internal`, `External`
#### `BridgeLeg` (SensorDB.cs)
`First`, `Second`, `Third`, `Fourth`
#### `CouplingModes` (SensorDB.cs)
`AC = 0`, `DC`
## 3. Invariants
- **`SensorRange`**: Must contain exactly three comma-separated numeric values; otherwise, `InvalidDataException` is thrown.
- **`LowHigh`**: Must contain at least two comma-separated numeric values; otherwise, `InvalidDataException` is thrown.
- **`FilterClass`**: `Frequency` is always set to the numeric value corresponding to `FClass` (e.g., `CFC10``17.0`). `AdHoc` type stores arbitrary numeric frequency.
- **`IsoCode`**: The internal `_isoCodeFull` array is always exactly 16 characters. Any component property setter ensures its segment is exactly the correct width (1, 2, or 4 chars) by padding with `'?'` or truncating. Invalid/empty inputs default to `'?'`.
- **`SensorCalibration`**:
- `IsProportional` and `RemoveOffset` are forced to `false` when `NonLinear` is `true`.
- `ZeroPoint` in `CalibrationRecord` is computed from `Poly` if possible; otherwise, it uses the stored `_zeroPoint`.
- Serialization uses `SEPARATOR_REPLACEMENT = "__SC__"` to escape list separators.
- **`CalibrationRecords`**: Uses `"__x__"` as primary separator and `"___xx___"` as escape sequence during serialization/deserialization.
- **`CalibrationRecord`**: Uses `InvariantCulture` for numeric parsing and `"x_Separator_x"` as escape sequence for list separators.
- **`DigitalInputSetting`, `DigitalOutputSetting`, `SquibSetting`**: All inherit from `SensorData` and call `SetDefaults()` during construction to ensure consistent baseline properties.
## 4. Dependencies
### Internal Dependencies (from source)
- **`DbOperations`**: Used for database field names (`DbOperations.*.Fields.*`), SQL command creation (`GetSQLCommand`), and stored procedure names (`DbOperationsEnum.StoredProcedure.*`).
- **`Test.Module.Channel.Sensor`**: Referenced for `BridgeType`, `SensUnits`, and `ExcitationVoltageOptions`.
- **`ZeroMethod`**, **`InitialOffset`**, **`LinearizationFormula`**, **`SensorData`**: Referenced but not included in the provided source files. Their definitions are assumed to exist elsewhere in the codebase.
- **`ICalibrationRecords`**, **`ISensorCalibration`**: Interfaces implemented by `CalibrationRecords` and `SensorCalibration` respectively.
### External Dependencies
- **System**: `System`, `System.ComponentModel`, `System.Data`, `System.Data.SqlClient`, `System.Globalization`, `System.Linq`, `System.Text`, `System.Xml`.
- **Database**: SQL Server stored procedures:
- `sp_SensorDeleteAll`
- `sp_SensorCalibrationsDelete`
- `sp_SensorsAnalogGet`
- `sp_SensorsDigitalInGet`
- `sp_SensorsSquibGet`
- `sp_SensorsDigitalOutGet`
### Dependencies on this Module
- `SensorsCollection.SensorsList` is used to retrieve sensor configurations by serial number.
- `SensorCalibrationList.GetLatestCalibrationBySerialNumberAndExcitation` is used to retrieve calibration data.
- `SensorRange`, `LowHigh`, `FilterClass`, `IsoCode` are likely used for parsing configuration strings and ISO codes elsewhere in the system.
## 5. Gotchas
- **`SensorRange` constructor**: Throws `InvalidDataException` for malformed input, but no validation is performed on the numeric values (e.g., `Low > Medium` is allowed).
- **`LowHigh` constructor**: Uses `InvariantCulture` for parsing, but `SensorRange` does not specify culture—assumes current culture or default parsing behavior.
- **`FilterClass` constructor**: Ambiguity in parsing `"1000"`: matches both `CFC600` (1000 Hz) and `CFC1000` (1650 Hz)? The code prioritizes exact numeric match (`case 1000``CFC600`), but `"CFC1000"` string match would take precedence if present.
- **`IsoCode`**: Setter for `StringRepresentation` pads with `'0'` if input is shorter than 16 chars, but constructor pads with `'?'`. Inconsistent behavior.
- **`CalibrationRecord.ZeroPoint`**: The computed value depends on `Poly.CalibrationFactor`; if `Poly` is uninitialized or `CalibrationFactor == 0`, the stored `_zeroPoint` is returned. This could lead to stale or incorrect values if `Poly` is modified after `ZeroPoint` is set.
- **`SensorCalibrationList.GetLatestCalibrationBySerialNumberAndExcitation`**: Uses `_cachedCalibrations` if available, but this field is never populated in the provided source—likely populated elsewhere (e.g., during `Reload()` or initial load). If `_cachedCalibrations` is null, it falls back to `_calibrationList`, which may be uninitialized if `Reload()` hasnt been called.
- **`SensorCalibrationList.DeleteAll()`**: Clears `_calibrationList._calibrations` but does not clear `_cachedCalibrations`, potentially leaving stale data in memory.
- **`DigitalInputSetting` constructor**: Assigns `Comment = UserValue1` (line 25), but `UserValue1` is also assigned from `DbOperations.DigitalInputSettings.Fields.UserValue1.ToString()` (line 18). This may be intentional, but could be a source of confusion.
- **`SquibSetting` constructor**: Assigns `Comment = UserValue1` after reading from DB, but then reassigns `Comment = SerialNumber` if `Comment` is null/whitespace. This double-assignment is redundant and could be simplified.
- **`DigitalOutputSetting.ChannelDescription`**: Setter modifies `SerialNumber` and raises `PropertyChanged("ChannelDescription")`. This is unusual—typically, a property named `ChannelDescription` would not mutate `SerialNumber`.
- **`SensorCalibration` serialization**: Uses `SEPARATOR_REPLACEMENT = "__SC__"` to escape list separators, but `CalibrationRecord` uses `"x_Separator_x"`—different escaping schemes for nested serialization.
- **`SensorCalibrationList` constructor**: The private constructor contains a comment indicating removed code that “appeared it would never work (wrong parameters to sql sp)”, suggesting potential instability or incomplete implementation.
- **`SensorsCollection.GetSensorBySerialNumber`**: Does not use the `excludeBroken` parameter in the provided code—broken sensors are not filtered out despite the parameter name.
- **`SensorCalibrationList.GetLatestCalibrationBySerialNumberAndExcitation`**: Returns `SensorCalibration.NewDigitalSC()` for digital/squib sensors, but this default calibration may not reflect actual sensor behavior (e.g., `Sensitivity=1` is arbitrary).

View File

@@ -0,0 +1,126 @@
---
source_files:
- DataPRO/Modules/DatabaseImporter/DatabaseImport/SettingsDB/GlobalSetting.cs
- DataPRO/Modules/DatabaseImporter/DatabaseImport/SettingsDB/SettingsDB.cs
- DataPRO/Modules/DatabaseImporter/DatabaseImport/SettingsDB/Setting.cs
generated_at: "2026-04-16T04:30:58.292022+00:00"
model: "Qwen/Qwen3-Coder-Next-FP8"
schema_version: 1
sha256: "f40d6df6287d52df"
---
# SettingsDB
## Documentation: Global Settings Module (`DatabaseImport`)
---
### 1. Purpose
This module provides a centralized, thread-safe mechanism for managing **application-wide (global) settings** stored in a SQL Server database. It abstracts the persistence logic for global configuration properties, ensuring that each setting is lazily loaded from the database on first access, falls back to a provided default value if missing, and caches the setting instance in memory for subsequent lookups. It is part of the `DatabaseImporter` module and serves as the canonical source for global configuration values used during database import operations.
---
### 2. Public Interface
#### `SettingsDB` (Static Class)
- **`public static string GetGlobalValue(string id, string defaultValue)`**
Retrieves the global setting value for `id`. If the setting does not exist in the cache or database, it is created with `defaultValue`, stored in the DB, and returned. Thread-safe via singleton + lock.
- **`public static bool GetGlobalValueBool(string id, bool defaultValue)`**
Retrieves the global setting as a `bool`. Converts the stored string value using `bool.TryParse`; if parsing fails, returns `defaultValue`. Thread-safe.
- **`public static void SetGlobalValue(string id, string value)`**
Sets the global setting `id` to `value`. Updates the in-memory cache and persists to the database via `StoreInDB()`. Thread-safe.
- **`public static void SetGlobalValueBoolean(string id, bool value)`**
Sets the global setting `id` to the string representation of `value` (using `InvariantCulture`). Updates cache and persists. Thread-safe.
#### `GlobalSetting` (Concrete Class, inherits `Setting`)
- **`public GlobalSetting(string id, string defaultPropertyValue)`**
Constructor. Initializes a `GlobalSetting` with `PropertyType = Global`, `UserId = "SYSTEM"`, and triggers `GetPropertyValue(defaultPropertyValue)`.
#### `Setting` (Abstract Base Class)
- **`public string PropertyId { get; }`**
Read-only identifier of the setting (e.g., `"ImportBatchSize"`).
- **`public string PropertyValue { get; }`**
Current value of the setting (as `string`). *Note: No length validation is enforced at this layer.*
- **`public string UserId { get; }`**
User context for the setting. For `GlobalSetting`, this is always `"SYSTEM"`.
- **`public void SetValue(string value)`**
Updates `_propertyValue` and persists the change via `StoreInDB()`.
- **`protected abstract void GetPropertyValue(string defaultValue)`**
Implemented by subclasses to fetch the value from the database (or other source). `GlobalSetting` implements this to query the DB.
---
### 3. Invariants
- **Singleton & Thread Safety**: `SettingsDB` is a singleton with lazy initialization. All public static methods (`GetGlobalValue`, `SetGlobalValue`, etc.) are guarded by a `lock (LOCK_OBJECT)` on the singleton instance, ensuring thread-safe access to `_settingsLookup` and DB operations.
- **Global Scope**: `GlobalSetting` instances are always associated with `UserId = "SYSTEM"` and `PropertyType = PropertyTypes.Global` (value `2`).
- **Default Fallback**: If a setting does not exist in the database, `GetPropertyValue` falls back to the provided `defaultValue`, stores it in the DB via `StoreInDB()`, and returns it.
- **Caching**: Once instantiated, a `Setting` object is cached in `SettingsDB._settingsLookup`. Subsequent lookups for the same `id` reuse the cached instance.
- **DB Schema Assumption**: The module assumes:
- A stored procedure `sp_SettingsGet` exists, accepting `@UserId` (NVARCHAR) and `@PropertyId` (NVARCHAR), returning a result set with a column named `PropertyValue` (via `DbOperations.Settings.UserFields.PropertyValue`).
- A stored procedure `sp_SettingsUpdateInsert` exists, accepting parameters: `@PropertyId`, `@PropertyType`, `@PropertyValue`, `@UserId`, `@new_id` (OUTPUT), `@errorNumber` (OUTPUT), `@errorMessage` (OUTPUT). All string parameters are NVARCHAR(255).
---
### 4. Dependencies
#### **Dependencies *of* this module:**
- `System.Data` and `System.Data.SqlClient` (for `SqlDataAdapter`, `SqlCommand`, `SqlParameter`, `SqlDbType`, etc.)
- `DbOperations` (static class, not shown) — provides:
- `GetSQLCommand(bool)` → returns `SqlCommand`
- `Connection.QueryDataSet(SqlCommand)` → returns `DataSet`
- `Settings.UserFields.PropertyValue` → string constant for column name (e.g., `"PropertyValue"`)
- `DbOperationsEnum.StoredProcedure.sp_SettingsGet`, `sp_SettingsUpdateInsert` → enum values for stored procedure names.
#### **Dependencies *on* this module:**
- Any code requiring global configuration (e.g., import batch size, timeout, feature flags) calls `SettingsDB.GetGlobalValue(...)` or `GetGlobalValueBool(...)`.
#### **Inferred callers:**
- `DatabaseImporter` module (e.g., import pipeline components that read global settings like `"MaxRetryCount"`, `"DefaultSchema"`).
---
### 5. Gotchas
- **Exception Handling is Minimal**:
`GetPropertyValue` and `StoreInDB` both catch `Exception` and silently fall back to `defaultValue` or do nothing, respectively. No logging is active (commented-out `APILogger.LogException` suggests future intent). This makes debugging DB issues difficult.
- **No Validation on Value Length**:
`PropertyValue` is stored as `NVARCHAR(255)` in DB calls, but no validation occurs in `Setting` or `GlobalSetting`. Passing a >255-character value may cause a DB error (silently ignored in `StoreInDB`).
- **Race Condition in Initialization (Low Risk)**:
While `GetGlobalValue` locks before checking `_settingsLookup`, the *first* call for a new `id` creates a new `GlobalSetting` *inside* the lock. However, `GlobalSetting` constructor calls `GetPropertyValue`, which performs a DB round-trip *while holding the lock*. This can cause contention if many settings are requested concurrently for the first time.
- **Hardcoded `"SYSTEM"` User**:
`GlobalSetting` hardcodes `UserId = "SYSTEM"`. This is not configurable and assumes all global settings are owned by a system user.
- **`_allGlobalSetting` Cache is Unused**:
The `GetPropertyValue` method contains commented-out code for a `_allGlobalSetting` cache. This suggests a previous optimization attempt that was reverted or incomplete — the current implementation hits the DB on *every* first access for a new `id`.
- **Culture-Specific Boolean Parsing**:
`GetGlobalValueBool` uses `defaultValue.ToString(CultureInfo.InvariantCulture)` for the fallback string, but `bool.TryParse` is culture-insensitive for `"True"/"False"`. This is safe, but the use of `InvariantCulture` here is redundant and could mislead.
- **No Explicit Disposal of `Setting` Instances**:
`Setting` instances are stored in `_settingsLookup` and never removed. If settings are frequently added/removed at runtime, this could lead to memory leaks.
- **No Distinction Between `null` and Empty String**:
If the DB stores `NULL` for `PropertyValue`, `Convert.ToString(...)` returns `""` (empty string), not `null`. This may or may not be intended.
---
*Documentation generated from provided source files. No external assumptions or behaviors inferred beyond what is explicitly present.*

View File

@@ -0,0 +1,198 @@
---
source_files:
- DataPRO/Modules/DatabaseImporter/DatabaseImport/Storage/IDbTimeStampAware.cs
- DataPRO/Modules/DatabaseImporter/DatabaseImport/Storage/DbOperationsEnum.cs
- DataPRO/Modules/DatabaseImporter/DatabaseImport/Storage/DbOperations.cs
generated_at: "2026-04-16T04:30:21.712903+00:00"
model: "Qwen/Qwen3-Coder-Next-FP8"
schema_version: 1
sha256: "604c24fe0c2a5ffe"
---
# Storage
## Documentation: `DatabaseImport` Storage Module
---
### 1. Purpose
This module provides foundational infrastructure for database versioning, timestamp tracking, and database abstraction within the `DatabaseImport` subsystem. Its primary role is to enable consistent detection of data staleness (via `IDbTimeStampAware`) and to centralize database operation utilities (via `DbOperations`), including stored procedure enumeration (`DbOperationsEnum`), database schema metadata (via nested `abstract class` enums), and connection management. It supports both local and centralized SQL Server databases, with authentication configurable at runtime.
---
### 2. Public Interface
#### `IDbTimeStampAware` Interface
*Defined in `IDbTimeStampAware.cs`*
- **`long GetTimeStampMemory()`**
Returns the in-memory timestamp value (stored in the protected `DbTimeStamp` field).
- **`void SetTimeStampMemory(long value)`**
Sets the in-memory timestamp to `value`.
- **`long GetTimeStampDb()`**
Returns the database timestamp for the current object. *Currently unimplemented* — always returns `0`. The commented-out code suggests it was intended to query a database table (`tblDbVersions` or similar) using constraints derived from `GetConstraints()` (not present in this file).
- **`bool IsOutOfDate()`**
Compares the in-memory and database timestamps. Returns `true` if the database timestamp (`db`) is non-zero and differs from the in-memory timestamp (`mem`). If `mem == 0` and `db != 0`, it auto-updates `mem` to `db` before comparison.
#### `DbTimeStampBase` Abstract Class
*Defined in `IDbTimeStampAware.cs`*
- **`event PropertyChangedEventHandler PropertyChanged`**
Implements `INotifyPropertyChanged`. Notifies listeners of property changes.
- **`protected bool SetProperty<T>(ref T storage, T value, string propertyName = null)`**
Sets `storage` to `value` if different, raises `PropertyChanged`, and returns `true`. Otherwise returns `false`.
- **`protected void OnPropertyChanged(string propertyName = null)`**
Invokes the `PropertyChanged` event with the given property name.
- **`public long GetTimeStampMemory()`**
Returns the current value of the protected field `DbTimeStamp`.
- **`public void SetTimeStampMemory(long value)`**
Sets `DbTimeStamp` to `value`.
- **`public void SetTimeStampMemory(DataRow row)`**
Sets `DbTimeStamp` to `0`. *No-op beyond assignment*.
- **`public void SetTimeStampMemory(IDataReader reader)`**
Sets `DbTimeStamp` to `0`. *No-op beyond assignment*.
- **`public long GetTimeStampDb(Dictionary<string, long> lookup)`**
Returns `0`. *Unimplemented*. Commented-out code suggests lookup by constraint values.
- **`public long GetTimeStampDb()`**
Returns `0`. *Unimplemented*. Commented-out code shows intended SQL query logic.
#### `DbOperationsEnum.StoredProcedure` Enum
*Defined in `DbOperationsEnum.cs`*
- **`StoredProcedure` enum**
Lists all stored procedure names used in the system (e.g., `sp_UserDelete`, `sp_DBImportUsers`, `sp_TestSetupsUpdateInsert`). Used to parameterize stored procedure calls.
#### `DbOperations` Class
*Defined in `DbOperations.cs`*
- **`public const int CURRENT_DB_VERSION = 61`**
Hardcoded current database schema version.
- **`public static bool _usingCentralizedDB`**
`true` if using a remote centralized server; `false` for local `SqlLocalDb`.
- **`public static bool _usingMSSQL`**
`true` if using Microsoft SQL Server.
- **`public static bool _usingNTLMAuthentication`**
`true` if using Windows Authentication (NTLM); otherwise SQL authentication.
- **`public static string _previousDir`**
Stores the previous working directory (unused in current code).
- **`public static DbOperations Connection`**
Singleton instance of `DbOperations`. Thread-safe via `lock(dbLock)`.
- **`public static SqlCommand GetSQLCommand(bool newCommand = false)`**
Returns a `SqlCommand` instance, reusing `_cmd` unless `newCommand` is `true`. Automatically opens a connection using `Connection.GetLocalConnectionString()` if needed.
- **`public static bool IsServerConnected()`**
Returns `true` if a connection to the local database (via `Connection.GetLocalConnectionString()`) succeeds.
- **`public DataSet QueryDataSet(SqlCommand icmd)`**
Executes `icmd` and returns results in a `DataSet`. Throws exceptions on failure.
- **`public string GetLocalConnectionString()`**
Builds and caches the connection string based on `_usingNTLMAuthentication`, `Server`, `DBName`, `Username`, and `Password`. Throws if connection not initialized.
- **`public string Server`, `Username`, `Password`, `DBName`**
Properties used to configure connection parameters.
#### Nested Abstract Classes (Schema Metadata)
*Defined in `DbOperations.cs`*
These provide strongly-typed field names and database column metadata for various tables. All use `enum` fields annotated with `[DbTypeAttr(...)]` where applicable.
- **`Tags.TagFields`**
`TagId`, `TagText`, `Obsolete`
- **`DbVersions.DbVersionFields`**
`Version`, `Step`, `Date`, `Remarks`, `UserField`
- **`Settings.UserFields`**
`PropertyId`, `PropertyType`, `PropertyValue`, `UserId`
- **`Users.UserFields`**, **`Users.UIItemFields`**
User and UI item schema fields.
- **`SensorDB.*Fields`**
Sensor, SensorModel, and SensorCalibration schema fields (e.g., `SerialNumber`, `Model`, `CalibrationDate`).
- **`CalculatedChannels.Fields`**
Includes `[DbTypeAttr(...)]` annotations (e.g., `Id``"INTEGER PRIMARY KEY NOT NULL"`).
- **`LevelTriggers.Fields`**
Trigger configuration fields (e.g., `GreaterThanEU`, `TriggerInside`).
- **`TestSetups.*Fields`**
Test setup, hardware, channel settings, graphs, and object metadata fields.
- **`DigitalOutputSettings.Fields`**, **`Squib.Fields`**, **`DigitalInputSettings.Fields`**
Device-specific configuration fields.
- **`MMETables.*Fields`**
MME (likely "Measurement Management Environment") lookup table fields (e.g., `MMEFineLocations1Fields`, `MMETestObjectsFields`).
- **`DAS.Fields`**, **`DAS.DASChannelFields`**
DAS (Data Acquisition System) device and channel schema fields.
#### `DbTypeAttr` Attribute
*Defined in `DbOperations.cs`*
- **`public static string GetDbType(object o)`**
Retrieves the `DbType` string from a `[DbTypeAttr(...)]`-annotated enum value.
---
### 3. Invariants
- **`DbTimeStamp` is always initialized to `0`** on construction or via `SetTimeStampMemory(DataRow)`/`SetTimeStampMemory(IDataReader)`.
- **`IsOutOfDate()` never returns `true` if `GetTimeStampDb()` returns `0`**, even if `GetTimeStampMemory() != 0`.
- **`GetTimeStampDb()` always returns `0`** — the implementation is stubbed and untested.
- **`DbOperations.Connection` is a singleton** — only one instance exists per AppDomain.
- **`_usingCentralizedDB`, `_usingMSSQL`, `_usingNTLMAuthentication` are global flags** — changing them affects all subsequent connection attempts.
- **`CURRENT_DB_VERSION` is fixed at compile time** — no runtime schema migration logic is visible in this module.
---
### 4. Dependencies
#### *This Module Depends On*
- `System.Data` (for `DataSet`, `SqlDataAdapter`, `SqlDataReader`, `DataRow`, `ConnectionState`)
- `System.Data.SqlClient` (for `SqlConnection`, `SqlCommand`)
- `System.ComponentModel` (for `INotifyPropertyChanged`)
- `System` (for `Attribute`, `Exception`, `StringBuilder`, `BitConverter`, `Trace`, `Dictionary`, `string`)
#### *This Module Is Used By*
- Any module requiring database timestamp checks (e.g., import/export logic, cache invalidation).
- Modules that execute stored procedures (via `DbOperationsEnum.StoredProcedure`).
- Modules that construct SQL queries or map database rows to objects (via `DbOperations.*Fields` enums).
- UI layers that bind to objects implementing `IDbTimeStampAware` (for change tracking).
---
### 5. Gotchas
- **`GetTimeStampDb()` is unimplemented** — always returns `0`. This renders `IsOutOfDate()` effectively useless for detecting *real* DB staleness unless the caller manually populates `DbTimeStamp` and assumes DB matches memory.
- **`SetTimeStampMemory(DataRow)` and `SetTimeStampMemory(IDataReader)` ignore their inputs** — they unconditionally set `DbTimeStamp = 0`, which may be unintentional.
- **`GetTimeStampDb(Dictionary<string, long> lookup)` is unimplemented** — the `lookup` parameter is unused.
- **`DbOperations.Connection` is a singleton with mutable state** — `Server`, `Username`, `Password`, `DBName` are settable properties, but not thread-safe for concurrent reconfiguration.
- **`_cmd` is a static field reused across calls** — calling `GetSQLCommand()` without `newCommand: true` may cause parameter leakage between queries if callers do not clear parameters.
- **`IsServerConnected()` only tests the *local* connection string** — if `_usingCentralizedDB == true`, it may not reflect connectivity to the remote server.
- **`CURRENT_DB_VERSION` is hardcoded** — no schema versioning logic (e.g., migration, upgrade checks) is present in this module.
- **No actual database access occurs in `DbTimeStampBase`** — all DB-related methods are stubbed. Real DB logic may reside elsewhere (not visible here).
- **`DbTypeAttr.GetDbType()` relies on reflection** — may be slow or fail if enum values lack attributes or are not defined in the expected way.
None identified beyond the above.

View File

@@ -0,0 +1,98 @@
---
source_files:
- DataPRO/Modules/DatabaseImporter/DatabaseImport/Users/User.cs
- DataPRO/Modules/DatabaseImporter/DatabaseImport/Users/ITagAware.cs
- DataPRO/Modules/DatabaseImporter/DatabaseImport/Users/Tags.cs
generated_at: "2026-04-16T04:30:38.280273+00:00"
model: "Qwen/Qwen3-Coder-Next-FP8"
schema_version: 1
sha256: "f22aee5e7f816592"
---
# Users
## Documentation: `User` Class and Related Tag Infrastructure
---
### 1. Purpose
This module provides foundational data structures for handling *tag-aware* entities—specifically, the `User` class, which represents a single user in the system and inherits tag-related functionality from `TagAwareBase`. Tags are metadata labels (ID + text) used to categorize or annotate entities; they are immutable in structure (no delete/modify operations, only add) and stored in a binary blob (`TagsBlobBytes`) for efficient serialization/deserialization. The module supports importing user data (and by extension, other tag-aware entities) from database records via `IDataRecord`, and enables cloning of tag definitions.
---
### 2. Public Interface
#### `class User : TagAwareBase`
- **Inherits** all members of `TagAwareBase` (see below).
- **No additional public members** declared in the provided source.
- **Purpose**: Encapsulates a single user; tag-related behavior is inherited.
#### `interface ITagAware`
- **Empty interface**.
- **Purpose**: Marker interface for classes that support tagging. No methods or properties defined.
#### `abstract class TagAwareBase : DbTimeStampBase`
*(Note: `DbTimeStampBase` is referenced but not defined in the provided source—its members are unknown.)*
- **`public int[] TagIDs { get; set; }`**
- Gets/sets an array of integer tag IDs associated with the entity.
- Setter is null-safe: assigns `new int[0]` if `value` is `null`.
- **`public byte[] TagsBlobBytes { get; set; }`**
- **Getter**: Converts `TagIDs` to a `byte[]` via `Buffer.BlockCopy` (int array → bytes).
- **Setter**: Attempts to reconstruct `TagIDs` from a `byte[]` by interpreting bytes as `int` values.
- Silently returns if `value.Length < sizeof(int)` (i.e., < 4 bytes).
- Silently ignores exceptions during `Buffer.BlockCopy` (no rethrow or logging—commented-out `APILogger.Log` suggests intentional suppression).
#### `class Tags.Tag : ICloneable`
*(Nested within `Tags` class)*
- **`public int ID { get; set; }`**
- Unique identifier for the tag.
- **`public string Text { get; set; }`**
- Human-readable label for the tag.
- **`public bool IsObsolete { get; set; }`**
- Indicates whether the tag is deprecated (but not deleted).
- **`public Tag(Tag copy)`**
- Copy constructor: initializes fields from another `Tag` instance.
- **`public Tag(IDataRecord reader)`**
- Constructor that populates the `Tag` from a database record.
- Reads fields via `DbOperations.Tags.TagFields` enum (values: `TagId`, `Obsolete`, `TagText`).
- Silently ignores exceptions during parsing (commented-out logging).
- **`public object Clone()`**
- Returns a shallow copy of the `Tag` via the copy constructor.
---
### 3. Invariants
- **`TagIDs` is never `null`**: The setter enforces `value ?? new int[0]`.
- **`TagsBlobBytes``TagIDs` consistency**:
- Getter always produces a `byte[]` of length `TagIDs.Length * sizeof(int)`.
- Setter *attempts* to restore `TagIDs` from `TagsBlobBytes`, but may silently fail (e.g., if `value.Length` is not a multiple of `sizeof(int)` or contains invalid data).
- **Tag immutability constraints**:
- Tags are *not* deletable or editable (per `Tags.cs` summary). Only new tags may be added.
- `IsObsolete` is a flag but does not imply deletion; obsolete tags remain in the system.
- **`DbTimeStampBase` inheritance**: `TagAwareBase` inherits from `DbTimeStampBase` (not shown), implying timestamp-related fields (e.g., `Created`, `Modified`) are expected but not defined here.
---
### 4. Dependencies
- **Internal dependencies**:
- `DbOperations.Tags.TagFields` enum (used in `Tags.Tag` constructor).
- `DbTimeStampBase` (base class of `TagAwareBase`; not provided).
- `APILogger` (referenced in commented-out logging statements; assumed external).
- **External dependencies**:
- `System` (for `Buffer`, `Exception`, `ICloneable`).
- `System.Data` (for `IDataRecord`).
- **Depended upon by**:
- `User` (direct consumer of `TagAwareBase`).
- Likely other tag-aware entities (e.g., `Project`, `Asset`) not included in this source set.
---
### 5. Gotchas
- **Silent failure in `TagsBlobBytes` setter**: Exceptions during deserialization are caught and ignored—no error is surfaced to callers. This may mask data corruption or schema mismatches.
- **No validation of `TagIDs`**: The `TagIDs` array may contain IDs that do not correspond to valid tags (no cross-reference validation).
- **`IsObsolete` is not enforced**: While tags *can* be marked obsolete, the system does not prevent their use (e.g., assignment to users).
- **`TagAwareBase` inherits from `DbTimeStampBase`**: Behavior of timestamp fields is undefined here; assume they exist but require external documentation.
- **`Tags` class is not a collection**: Despite its name, `Tags` only defines the `Tag` inner class—no methods for managing a set of tags (e.g., add/remove/lookup). Tag management is implied to occur elsewhere.
- **No thread-safety guarantees**: `TagsBlobBytes` and `TagIDs` use simple field access; concurrent modification risks exist if shared across threads.
*None identified beyond the above.*

View File

@@ -0,0 +1,41 @@
---
source_files:
- DataPRO/Modules/DatabaseImporter/DatabaseImport/Utilities/DiskUtility.cs
generated_at: "2026-04-16T04:30:13.126152+00:00"
model: "Qwen/Qwen3-Coder-Next-FP8"
schema_version: 1
sha256: "f18ece9cd807d7b1"
---
# Utilities
## 1. Purpose
`DiskUtility` is a static utility class providing disk-related validation logic for file and path names within the `DatabaseImport` module. Its primary role is to enforce naming constraints on file and directory names used during database import operations—specifically, to reject names containing any characters deemed invalid by the .NET runtime *and* any period (`.`) characters, which are explicitly disallowed beyond standard OS restrictions. This helps prevent filesystem errors and potential security issues (e.g., path traversal, ambiguous extensions) during file I/O operations.
## 2. Public Interface
- **`bool ValidateFileAndPathNameChars(string nameToValidate)`**
Validates whether the input string is a permissible file or path name. Returns `false` if:
- The trimmed string is empty or whitespace-only,
- It contains *any* character returned by `Path.GetInvalidFileNameChars()`,
- It contains *any* character returned by `Path.GetInvalidPathChars()`,
- It contains a period (`.`) character anywhere in the string.
Returns `true` only if all checks pass.
## 3. Invariants
- **Empty/whitespace rejection**: Any input that trims to zero length is invalid.
- **Strict character filtering**: The presence of *any* invalid filename *or* path character (as defined by `Path.GetInvalidFileNameChars()` and `Path.GetInvalidPathChars()` for the current platform) causes failure.
- **Period prohibition**: The literal `'.'` character is *always* invalid, regardless of context (e.g., even in otherwise valid names like `"file.txt"` or `"."`), per the explicit `Contains('.')` check.
- **No partial validation**: The method performs *all* checks and returns `false` on the *first* failure encountered (due to short-circuiting via `bValid = false` without early exit), but the logic ensures *all* invalid conditions are evaluated before returning.
## 4. Dependencies
- **Imports**: `System.IO` (for `Path.GetInvalidFileNameChars()`, `Path.GetInvalidPathChars()`), `System.Linq` (for `Contains()` extension method on `string`).
- **Usage context**: Inferred to be used by other components in the `DatabaseImport` namespace (e.g., import pipeline logic that constructs file paths from user input or metadata). No external dependencies beyond the .NET runtime.
- **Dependents**: Not specified in source; must be determined via codebase search for `DiskUtility.ValidateFileAndPathNameChars`.
## 5. Gotchas
- **Overly restrictive period check**: The explicit ban on `.` prevents valid names like `"data"` (if followed by an extension in practice) or `"."` (for current directory), but also blocks *all* extensions (e.g., `"file.csv"` fails). This may conflict with standard filesystem behavior where `.` is only invalid in *certain* positions (e.g., not at the start/end of a filename on Windows).
- **No early exit**: The method sets `bValid = false` but continues iterating through all invalid characters—even after failure—resulting in unnecessary work.
- **Case sensitivity**: `Contains()` is case-sensitive by default; if `nameToValidate` contains uppercase invalid characters (e.g., `':'` is invalid on Windows), it will still be caught, but this behavior is platform-dependent (e.g., `Path.GetInvalidFileNameChars()` returns platform-specific invalid chars).
- **No distinction between filename vs. path**: The method validates *both* filename and path characters in one pass, but a path like `"C:\folder\file"` contains `\` (valid in paths but *invalid* in filenames). This may cause false negatives for legitimate paths.
- **Commented-out base class**: The class declaration is `public class DiskUtility //: Exceptional`, suggesting past inheritance from an `Exceptional` type (possibly for error handling), but this is inactive. No exception-throwing behavior is present.
- **No localization or culture considerations**: Relies on `string.Contains(char)`, which is culture-invariant for `char`, but the underlying `Path.GetInvalid*Chars()` results depend on the OS/runtime environment.

View File

@@ -0,0 +1,108 @@
---
source_files:
- DataPRO/Modules/Groups/GroupChannelList/GroupChannelListModule.cs
generated_at: "2026-04-16T04:44:06.724645+00:00"
model: "Qwen/Qwen3-Coder-Next-FP8"
schema_version: 1
sha256: "3066a4421ff164bf"
---
# GroupChannelList
## Documentation: `GroupChannelListModule`
---
### 1. Purpose
The `GroupChannelListModule` is a Prism-based modular component responsible for registering the view and view model types associated with the group channel list UI functionality. It integrates into the applications modular architecture by implementing `IModule`, and uses Unity as its dependency injection container to register key UI components (`IGroupChannelListViewModel`, `IGroupChannelListView`, and `IGroupChannelSettingsListView`) as singleton services. Additionally, it exposes assembly-level metadata via custom attributes (`GroupChannelListModuleNameAttribute`, `GroupChannelListModuleImageAttribute`) to support dynamic discovery and UI presentation (e.g., in a module summary screen), including image, name, group, and region information.
---
### 2. Public Interface
#### `GroupChannelListModule`
- **`public GroupChannelListModule(IUnityContainer unityContainer)`**
Constructor. Injects the Unity container used for type registration.
- **`public void Initialize()`**
Registers three interfaces to their concrete implementations as singletons in the Unity container:
- `IGroupChannelListViewModel``GroupChannelListViewModel`
- `IGroupChannelListView``GroupChannelListView`
- `IGroupChannelSettingsListView``GroupChannelSettingsListView`
This method is called both directly by the constructors usage context (via `RegisterTypes`) and explicitly during Prism module initialization.
- **`public void OnInitialized(IContainerProvider containerProvider)`**
Currently empty; no logic implemented.
- **`public void RegisterTypes(IContainerRegistry containerRegistry)`**
Delegates to `Initialize()` (note: despite using `IContainerRegistry`, it internally uses `_unityContainer`, implying a potential mismatch or legacy pattern).
#### `GroupChannelListModuleNameAttribute`
- **`public GroupChannelListModuleNameAttribute()` / `GroupChannelListModuleNameAttribute(string s)`**
Constructor; ignores the `string s` parameter. Sets `AssemblyName` to `AssemblyNames.GroupChannelList.ToString()`.
- **`public override string AssemblyName { get; }`**
Returns `"GroupChannelList"` (value of `AssemblyNames.GroupChannelList.ToString()`).
- **`public override Type GetAttributeType()`**
Returns `typeof(TextAttribute)`.
- **`public override string GetAssemblyName()`**
Returns the value of `AssemblyName`.
#### `GroupChannelListModuleImageAttribute`
- **`public GroupChannelListModuleImageAttribute()` / `GroupChannelListModuleImageAttribute(string s)`**
Constructor; initializes `_img` by calling `AssemblyInfo.GetImage("GroupChannelList")`.
- **`public override BitmapImage AssemblyImage { get; }`**
Returns the image retrieved via `AssemblyInfo.GetImage("GroupChannelList")`.
- **`public override BitmapImage GetAssemblyImage()`**
Returns `AssemblyImage`.
- **`public override string AssemblyName { get; }`**
Returns `"GroupChannelList"`.
- **`public override string GetAssemblyName()`**
Returns `AssemblyName`.
- **`public override string AssemblyGroup { get; }`**
Returns `"Prepare"` (value of `eAssemblyGroups.Prepare.ToString()`).
- **`public override string GetAssemblyGroup()`**
Returns `AssemblyGroup`.
- **`public override eAssemblyRegion AssemblyRegion { get; }`**
Returns `eAssemblyRegion.GroupChannelListRegion`.
- **`public override eAssemblyRegion GetAssemblyRegion()`**
Returns `AssemblyRegion`.
- **`public override Type GetAttributeType()`**
Returns `typeof(ImageAttribute)`.
---
### 3. Invariants
- The module **must** be loaded in a Prism-based application using Unity as the DI container (as it directly uses `IUnityContainer` and `Unity` namespace).
- `Initialize()` must be called exactly once during module initialization to register the three types as singletons.
- `AssemblyNames.GroupChannelList`, `eAssemblyGroups.Prepare`, and `eAssemblyRegion.GroupChannelListRegion` must be defined elsewhere (in `DTS.Common` or `DTS.Common.Interface`) and must have consistent string/enum values; otherwise, runtime errors may occur (e.g., `AssemblyInfo.GetImage()` failure, region resolution failure).
- The `AssemblyImage` property assumes `AssemblyInfo.GetImage("GroupChannelList")` returns a valid `BitmapImage`; if not, null or exception may result (no null-check observed).
- The `RegisterTypes` method uses `IContainerRegistry`, but internally calls `Initialize()`, which uses `_unityContainer` (a `IUnityContainer`). This implies either:
- `IContainerRegistry` wraps `IUnityContainer` (e.g., via Prism.Unity integration), or
- A design inconsistency (see *Gotchas*).
---
### 4. Dependencies
#### Dependencies *of* this module:
- `DTS.Common` (specifically `AssemblyNames.GroupChannelList`, `eAssemblyGroups`, `eAssemblyRegion`, and `AssemblyInfo.GetImage(...)`)
- `DTS.Common.Interface.Groups.GroupChannelList` (for `IGroupChannelListViewModel`, `IGroupChannelListView`, `IGroupChannelSettingsListView`)
- `Prism.Modularity` (`IModule`, `ModuleAttribute`)
- `Prism.Ioc` (`IContainerProvider`, `IContainerRegistry`)
- `Unity` (`IUnityContainer`)
- `System.Windows.Media.Imaging` (`BitmapImage`)
#### Dependencies *on* this module:
- The host application (or other modules) must resolve `IGroupChannelListViewModel`, `IGroupChannelListView`, and `IGroupChannelSettingsListView` via DI after module initialization.
- UI regions (e.g., `GroupChannelListRegion`) must be defined elsewhere (e.g., in a shell or region manager) for views to be injected.
- The modules metadata attributes (`GroupChannelListModuleNameAttribute`, `GroupChannelListModuleImageAttribute`) are used by the host applications module discovery/UI logic (e.g., to populate a summary screen), implying external consumers rely on the attribute metadata structure.
---
### 5. Gotchas
- **`RegisterTypes` vs `Initialize` mismatch**: `RegisterTypes` accepts `IContainerRegistry` (Prisms abstraction), but `Initialize()` uses `_unityContainer` (`IUnityContainer`). If `IContainerRegistry` does not expose the underlying Unity container (or if `Initialize()` is called before `_unityContainer` is set), this could lead to incorrect registration or null reference. *This suggests potential tech debt or reliance on Prism.Unitys internal bridging.*
- **No null safety in `AssemblyImage`**: `AssemblyInfo.GetImage(...)` may return `null` if the image resource is missing or misnamed, but no defensive handling is present.
- **Unused constructor parameters**: The `string s` parameter in both attribute constructors is ignored, which may confuse developers expecting configurability.
- **Hardcoded string `"GroupChannelList"`**: Used in multiple places (`AssemblyNames.GroupChannelList.ToString()`, `AssemblyInfo.GetImage(...)`, `AssemblyGroup`). A typo or rename in `AssemblyNames.GroupChannelList` or `AssemblyInfo` would cause silent failures.
- **`OnInitialized` is empty**: Suggests incomplete implementation or future extensibility point.
- **No validation of view/view-model registration**: Assumes `IGroupChannelListViewModel`, etc., are implemented by `GroupChannelListViewModel`, etc., with compatible lifetimes (singletons). Misconfiguration here could cause runtime issues.
- **No documentation on `IGroupChannelListViewModel`/`IGroupChannelListView` interfaces**: Their contract (methods, events, properties) is not visible in this file.
None identified beyond the above.

View File

@@ -0,0 +1,120 @@
---
source_files:
- DataPRO/Modules/Groups/GroupChannelList/Converters/BooleanToWidthConverter.cs
- DataPRO/Modules/Groups/GroupChannelList/Converters/SensorIdBackgroundConverter.cs
generated_at: "2026-04-16T04:46:41.293810+00:00"
model: "Qwen/Qwen3-Coder-Next-FP8"
schema_version: 1
sha256: "b2bc34d167251ea0"
---
# Converters
## Documentation: `GroupChannelList.Converters` Module
### 1. Purpose
This module provides WPF value converters used for UI data binding in the `GroupChannelList` module. Specifically, it enables conditional presentation logic—converting boolean values to UI properties such as width (for collapsing/expanding UI elements) and background color (for highlighting sensor-related items). These converters facilitate declarative UI behavior in XAML without requiring additional view-model logic.
---
### 2. Public Interface
#### `BooleanToWidthConverter`
- **Namespace**: `GroupChannelList.Converters`
- **Type**: `class` implementing `IValueConverter`
- **Method**:
```csharp
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
```
- **Behavior**: Converts a `bool` input to a `double` width.
- If `value` is `null`, returns `0`.
- If `parameter` is provided and parses successfully as a `double`, uses that value for `true`; otherwise defaults to `double.NaN`.
- Returns the parsed width for `true`, and `0` for `false`.
- **Example usage in XAML**:
```xaml
Width="{Binding IsSensorActive, Converter={StaticResource BooleanToWidthConverter}, ConverterParameter=100}"
```
- **Method**:
```csharp
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
```
- **Behavior**: Always throws `NotImplementedException`. One-way conversion only.
#### `SensorIdBackgroundConverter`
- **Namespace**: `GroupChannelList.Converters`
- **Type**: `class` implementing `IValueConverter`
- **Field**:
```csharp
private static SolidColorBrush SensorIdBrush = new SolidColorBrush(Color.FromArgb(0xFF, 0xE3, 0xFB, 0xE1));
```
- A frozen `SolidColorBrush` with ARGB color `(0xFF, 0xE3, 0xFB, 0xE1)` (light green, #E3FBE1).
- **Method**:
```csharp
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
```
- **Behavior**: Converts a `bool` input to a `Brush`.
- If `value` is `null`, returns `Brushes.Transparent`.
- If `value` is `true`, returns `SensorIdBrush` (frozen for performance).
- If `value` is `false`, returns `Brushes.Transparent`.
- Any exception during conversion logs the message via `Trace.WriteLine` and returns `Brushes.Transparent`.
- **Example usage in XAML**:
```xaml
Background="{Binding HasSensorId, Converter={StaticResource SensorIdBackgroundConverter}}"
```
- **Method**:
```csharp
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
```
- **Behavior**: Always throws `NotImplementedException`. One-way conversion only.
---
### 3. Invariants
- **`BooleanToWidthConverter`**:
- Output is always `0` or a `double` (including `double.NaN` if `parameter` parsing fails).
- `parameter` is optional; if missing or invalid, `double.NaN` is used for `true`.
- No validation on `value` beyond null-checking; non-`bool` values will cause a runtime `InvalidCastException` (not caught).
- **`SensorIdBackgroundConverter`**:
- `SensorIdBrush` is frozen after first use (via `.Freeze()`) to ensure thread-safety and performance.
- Output is always a `Brush`; specifically `Brushes.Transparent` or `SensorIdBrush`.
- Null or non-`bool` inputs are handled gracefully (return `Brushes.Transparent`), but exceptions during conversion are silently logged.
---
### 4. Dependencies
- **Dependencies on external frameworks**:
- `System.Windows.Data` (WPF `IValueConverter` interface)
- `System.Windows.Media` (`SolidColorBrush`, `Brushes`)
- `System.Diagnostics` (`Trace`)
- `System.Globalization` (`CultureInfo`)
- **Dependencies on other modules**:
- None inferred from source (no internal project references in imports).
- Used by XAML views in the `GroupChannelList` module (inferred from namespace path).
- **Depended upon by**:
- XAML UI elements in `DataPRO.Modules.Groups.GroupChannelList` (e.g., `GroupChannelListView.xaml`), where these converters are referenced as static resources.
---
### 5. Gotchas
- **`BooleanToWidthConverter`**:
- `ConvertBack` is unimplemented—cannot be used in two-way bindings.
- `parameter` parsing is silent: invalid values (e.g., `"abc"`) result in `double.NaN` without error.
- Non-`bool` inputs (e.g., `null`, `int`, `string`) will throw `InvalidCastException` at runtime (not caught).
- **`SensorIdBackgroundConverter`**:
- `SensorIdBrush` is shared and frozen *after first use*; if frozen prematurely (e.g., before first conversion), subsequent calls are safe but the freeze is redundant.
- Exception handling is minimal: only logs to `Trace`, no user-facing error.
- Assumes `value` is `bool`; non-`bool` inputs (e.g., `null`, `int`) will throw `InvalidCastException` (not caught).
- **Both converters**:
- One-way only (`ConvertBack` throws `NotImplementedException`).
- No support for culture-specific formatting (uses default `CultureInfo` behavior).
- No documentation of expected `targetType` constraints (assumes WPF expects `double`/`Brush` outputs).
None identified beyond the above.

View File

@@ -0,0 +1,60 @@
---
source_files:
- DataPRO/Modules/Groups/GroupChannelList/Properties/Settings.Designer.cs
- DataPRO/Modules/Groups/GroupChannelList/Properties/AssemblyInfo.cs
generated_at: "2026-04-16T04:46:44.908575+00:00"
model: "Qwen/Qwen3-Coder-Next-FP8"
schema_version: 1
sha256: "068d1583fe59a4bb"
---
# Properties
## Documentation Page: `GroupChannelList.Properties.Settings`
---
### 1. **Purpose**
This module defines a strongly-typed settings class (`GroupChannelList.Properties.Settings`) for the `GroupChannelList` assembly, enabling centralized access to application-level configuration values via the .NET `ApplicationSettingsBase` infrastructure. It exists solely to expose a thread-safe singleton instance (`Default`) for reading (and potentially writing, though not evident here) user- or application-scoped settings—though no actual settings properties are declared in the provided source, indicating either a minimal placeholder or that settings are defined elsewhere (e.g., in `Settings.settings` or `App.config`).
---
### 2. **Public Interface**
The only public API surface exposed is:
- **`Settings.Default`**
- **Type**: `Settings` (a singleton instance)
- **Signature**: `public static Settings Default { get; }`
- **Behavior**: Returns the synchronized singleton instance of the `Settings` class, derived from `ApplicationSettingsBase`. This instance provides access to configuration properties (though none are visible in the provided source). Thread-safety is ensured via `ApplicationSettingsBase.Synchronized()`.
> **Note**: No additional public properties, methods, or fields are declared in the `Settings` class within the provided source. All settings (if any) are implicitly inherited from `ApplicationSettingsBase` and defined externally (e.g., in designer-generated or config files not included here).
---
### 3. **Invariants**
- The `Settings` class is **sealed** and **partial**, with auto-generated code marked with `<auto-generated>` and attributed with `CompilerGeneratedAttribute` and `GeneratedCodeAttribute`.
- The `Default` property returns a **synchronized singleton**, implying thread-safe access to settings (via `ApplicationSettingsBase.Synchronized`).
- The class resides in the `GroupChannelList.Properties` namespace, consistent with .NET conventions for strongly-typed settings.
- No runtime validation or custom logic is present in the provided source—behavior depends entirely on settings defined externally.
---
### 4. **Dependencies**
- **Depends on**:
- `System.Configuration` (specifically `ApplicationSettingsBase`)
- `System.Runtime.CompilerServices` (for `CompilerGeneratedAttribute`)
- `System.CodeDom.Compiler` (for `GeneratedCodeAttribute`)
- **Depended upon by**:
- Other modules in the `DataPRO` solution (e.g., `GroupChannelList` UI or logic layers) that consume `GroupChannelList.Properties.Settings.Default` to read configuration values.
- The .NET configuration system (e.g., `App.config` or `user.config` files) that backs the settings properties.
---
### 5. **Gotchas**
- **Settings are not defined here**: The `Settings` class contains no explicit property declarations (e.g., `public string SomeSetting { get; set; }`). Actual settings must be defined in the corresponding `.settings` file (e.g., `Settings.settings`) and regenerated—this file is purely the generated wrapper.
- **No write support evident**: While `ApplicationSettingsBase` supports setting values, the provided source does not confirm whether write operations are enabled or used.
- **Thread-safety caveat**: The `Synchronized()` wrapper ensures thread-safe *access*, but atomicity of multi-step operations (e.g., read-modify-write) is not guaranteed.
- **Versioning risk**: The assembly version is fixed at `1.0.0.0` (both `AssemblyVersion` and `AssemblyFileVersion`), which may complicate upgrades or settings migration if settings evolve.
- **Auto-generated warning**: Manual edits to this file will be overwritten on rebuild—settings must be modified via the Visual Studio Settings Designer or `App.config`.
> **None identified from source alone** beyond the above.

View File

@@ -0,0 +1,77 @@
---
source_files:
- DataPRO/Modules/Groups/GroupChannelList/Resources/TranslateExtension.cs
- DataPRO/Modules/Groups/GroupChannelList/Resources/StringResources.Designer.cs
generated_at: "2026-04-16T04:46:25.212575+00:00"
model: "Qwen/Qwen3-Coder-Next-FP8"
schema_version: 1
sha256: "5dba578a99876d46"
---
# Documentation: `TranslateExtension` Markup Extension
## 1. Purpose
This module provides a WPF `MarkupExtension` (`TranslateExtension`) that enables localization of UI strings directly in XAML by resolving resource keys against a strongly-typed resource class (`StringResources`). It serves as a bridge between declarative UI markup and localized string resources, allowing developers to bind text content (e.g., labels, tooltips, headers) to culture-sensitive values without writing code-behind. Its role is critical for internationalization of the `GroupChannelList` module, ensuring that user-facing text adapts to the current UI culture.
## 2. Public Interface
### `TranslateExtension` class
- **Namespace**: `GroupChannelList`
- **Base class**: `System.Windows.Markup.MarkupExtension`
- **Attribute**: `[MarkupExtensionReturnType(typeof(string))]`
#### Constructor
```csharp
public TranslateExtension(string key)
```
- **Parameters**:
- `key` (`string`): The resource key (e.g., `"ChannelName"`) used to look up a localized string in `StringResources`.
- **Behavior**: Stores the key for later resolution during `ProvideValue`.
#### `ProvideValue` method
```csharp
public override object ProvideValue(IServiceProvider serviceProvider)
```
- **Parameters**:
- `serviceProvider` (`IServiceProvider`): WPF service provider (unused in current implementation).
- **Returns**:
- `string`: The localized string if the key exists and is non-null/non-empty; otherwise, one of two fallback values:
- If `_key` is `null` or empty → returns `"#stringnotfound#"`
- If `StringResources.ResourceManager.GetString(_key)` returns `null` → returns `"#stringnotfound# " + _key` (e.g., `"#stringnotfound# ChannelName"`)
- **Behavior**: Performs a culture-aware lookup using `StringResources.ResourceManager.GetString(_key)`.
## 3. Invariants
- **Key must be a valid resource key**: The `_key` passed to the constructor must match a property name in `StringResources` (e.g., `"ChannelName"`, `"AnalogParameters_Range"`). Mismatched keys will result in the fallback `"#stringnotfound# <key>"` string.
- **Null/empty key handling**: If `_key` is `null` or `string.Empty`, the extension *always* returns `"#stringnotfound#"` (no concatenation with key).
- **No culture override via extension**: The extension does not expose or support overriding the culture used for lookup; it relies on the current `Thread.CurrentUICulture` via `StringResources.Culture`.
- **No side effects**: `ProvideValue` is pure—no state mutation or I/O occurs beyond the resource lookup.
## 4. Dependencies
### Dependencies *of* this module:
- **`System.Windows.Markup`**: Required for `MarkupExtension` base class and `MarkupExtensionReturnTypeAttribute`.
- **`GroupChannelList.Resources.StringResources`**: Strongly-typed resource class generated from `.resx` files. Relies on:
- `System.Resources.ResourceManager`
- `System.Globalization.CultureInfo`
- **WPF runtime**: Required for `IServiceProvider` and XAML markup extension resolution.
### Dependencies *on* this module:
- **XAML files in `GroupChannelList` module**: Used via XMLNS (e.g., `xmlns:res="clr-namespace:GroupChannelList"`) to localize UI elements:
```xml
<TextBlock Text="{res:Translate ChannelName}" />
```
- **No other modules directly depend on `TranslateExtension`**—it is consumed only via XAML markup.
## 5. Gotchas
- **No runtime validation of key existence**: If a resource key is misspelled (e.g., `"ChannelNme"` instead of `"ChannelName"`), the extension silently returns `"#stringnotfound# ChannelNme"`, which may appear as visible text in the UI.
- **No fallback to default language**: If a key exists in the `.resx` but lacks a translation for the current culture, `ResourceManager.GetString` returns `null`, triggering the fallback string. This may cause inconsistent behavior if translations are incomplete.
- **Hardcoded fallback prefix**: The `"#stringnotfound#"` prefix is hardcoded and not configurable. This could conflict with legitimate strings if used as a key.
- **No support for parameterized strings**: While `StringResources` includes format strings (e.g., `"Sensor {0} can not be assigned..."`), `TranslateExtension` does not support passing arguments (e.g., `{res:Translate Key, Arg1, Arg2}`). Developers must use `String.Format` manually in code-behind or elsewhere.
- **Auto-generated resource class**: `StringResources.Designer.cs` is auto-generated; manual edits are overwritten. Adding new keys requires updating the `.resx` file and regenerating the class.
- **No thread-safety guarantees**: Though `ResourceManager` is thread-safe, the extension itself is stateful (via `_key`), but this is harmless since each usage creates a new instance.
None identified beyond the above.

View File

@@ -0,0 +1,83 @@
---
source_files:
- DataPRO/Modules/Groups/GroupChannelList/View/GroupChannelListView.xaml.cs
generated_at: "2026-04-16T04:46:59.687984+00:00"
model: "Qwen/Qwen3-Coder-Next-FP8"
schema_version: 1
sha256: "a7a7f5755050a82e"
---
# View
### **Purpose**
`GroupChannelListView` is the WPF view implementation for displaying and interacting with a list of channels associated with a test group or test setup. It provides UI controls for channel management—including reordering, deletion, clearing, filtering, and drag-and-drop assignment of sensors and hardware—while dynamically adjusting column visibility and layout based on the current view mode (`IsoViewMode`), group/test context, and global settings (e.g., `ShowGroups`). It acts as the presentation layer for `GroupChannelListViewModel`, synchronizing UI state with the view model via data binding and event-driven interactions.
---
### **Public Interface**
The class implements `IGroupChannelListView` (inferred from `partial class GroupChannelListView : IGroupChannelListView`) and exposes the following public members:
1. **`bool ReadOnlyChannelsMode { get; }`**
Returns `true` if user input controls in the channel list should be read-only. Delegates to `IGroupChannelListViewModel.ReadOnlyChannelsMode`, returning `false` if `DataContext` is unset or not a `IGroupChannelListViewModel`.
2. **`void HandleColumns(IsoViewMode viewMode)`**
Dynamically configures the columns of `ChannelListListView` (an `AutoSizedGridView`) based on `viewMode` and global settings (`ShowGroups`, `UseTestSetupOrder`, `ShowDallasIdColumn`). Adds/removes columns for:
- Group order (`GroupColumn`, `GroupOrderColumn`)
- Test setup order (`TestSetupOrderColumn`)
- User code/name (`UserCodeColumn`, `UserChannelNameColumn`)
- ISO code/name (`ISOCodeColumn`, `ISOChannelNameColumn`)
- Dallas ID (`DallasIdColumn`)
Ensures column ordering respects `usingTestSetup` context.
---
### **Invariants**
The following must hold during operation:
- **`ChannelListListView` must be initialized before `HandleColumns()` is called**, as all column operations assume `ChannelListListView.View` is an `AutoSizedGridView`.
- **`DataContext` must be set to a `GroupChannelListViewModel` (or `IGroupChannelListViewModel`) for most functionality**. If `DataContext` is `null` or of the wrong type, methods silently return (e.g., `OnListViewEvent`, `Clear_Click`, `Delete_Click`, `MoveUp_Click`, etc.).
- **Drag-and-drop operations require `e.Data` to be non-null and contain supported formats** (e.g., `DragAndDropPayload.FORMAT`, `DTS.Common.Classes.Hardware.DragAndDropPayload.FORMAT`). Unsupported formats result in `DragDropEffects.None`.
- **Channel deletion for blank channels requires valid ordering**:
- If `UseTestSetupOrder`, `channel.TestSetupOrder > 0` must hold.
- Otherwise, `channel.GroupChannelOrder > 0` must hold.
(Per issue #14546 comment in `Delete_Click`.)
- **`ReadOnlyChannelsMode` is `false` if `DataContext` is `null` or not a `IGroupChannelListViewModel`**.
- **Column insertion/removal preserves ordering**:
- `TestSetupOrderColumn`/`GroupOrderColumn` are always first (index `0`).
- User/ISO columns are inserted at indices `0` or `1` depending on `usingTestSetup`.
---
### **Dependencies**
**Imports/References (from source):**
- `DTS.Common.*`: Core domain classes (`Groups`, `Sensors`, `Controls`, `Enums`, `Events`, `Interface`, `Settings`, `Utils`).
- `Prism.Ioc`, `Prism.Events`: For `IEventAggregator`, `ContainerLocator`, and event publication/subscription (`ListViewStatusEvent`, `GroupChannelDeleteRequestEvent`, `PageNavigationRequestEvent`).
- WPF namespaces (`System.Windows.*`): For `ListView`, `DragEventArgs`, `Hyperlink`, etc.
**Key External Dependencies (inferred):**
- `GroupChannelListViewModel`: Required as `DataContext` for all interactive logic.
- `IGroupChannel`: Interface implemented by channel objects (e.g., `GroupChannel`).
- `AutoSizedGridView`: Custom WPF control (from `DTS.Common.Controls`) used as `ChannelListListView.View`.
- `MouseUtilities`: Used in `IsMouseOverTarget()` for drag-drop hit-testing (from `DTS.Common.Utils`).
- `DTS.SensorDB.SoftwareFilter`: Used in `ISOCode_LostFocus` to fetch filter classes.
- Global settings via `SettingsDB.GetGlobalValueBool("ShowGroups", true)`.
**Depended upon by:**
- `GroupChannelListViewModel` (via `IGroupChannelListView` interface).
- Event handlers (`ListViewStatusEvent`, `GroupChannelDeleteRequestEvent`, `PageNavigationRequestEvent`) suggest integration with broader Prism-based navigation and state management.
---
### **Gotchas**
- **Silent failures**: Most event handlers and property getters return early if `DataContext` is `null` or of incorrect type (e.g., `Clear_Click`, `Delete_Click`, `MoveUp_Click`, `HandleColumns`). No exceptions or logging occur—debugging requires inspecting call stacks.
- **Drag-drop modifier key handling is fragile**:
- `ALT`/`CTRL` key states are checked via bitwise operations on `DragDropKeyStates`, but formats are mutated *in-place* (e.g., `"ALT_FORMAT"`), which may cause issues if `e.Data.GetFormats()` is called multiple times.
- `TextBox_Drop` and `ChannelList_Drop` duplicate logic for format handling—risk of divergence if updated in one place but not the other.
- **`ReadOnlyChannelsMode` is read-only and computed**: It does not raise change notifications; UI consumers must re-query it when `DataContext` changes.
- **`HandleColumns` assumes `ChannelListListView.View` is always `AutoSizedGridView`**: If the view is changed (e.g., to `GridView`), column operations will silently fail.
- **`MoveUp`/`MoveDown` via keyboard (Alt+↑/↓) uses `ChannelListListView.SelectedItems` order**, but `GetSelectedChannelsOrdered()` sorts by *view index*—this may differ from selection order if items are selected non-contiguously.
- **`ISOCode_LostFocus` mutates `FilterClass` based on ISO code**, but only if `UseISOCodeFilterMapping` is `true`. No fallback or error handling if `GetFilterClassFromISOCode` fails.
- **`Delete_Click` allows deletion of blank channels with valid orders** (per issue #14546), but blocks deletion if order ≤ 0—this may confuse users expecting blank channels to be deletable unconditionally.
- **`TextBoxSourceUpdated` handles group name changes**, but the comment implies complex group reorganization logic in `GroupNameChanged`—behavior is not visible in this file.
*None identified from source alone.*

View File

@@ -0,0 +1,209 @@
---
source_files:
- DataPRO/Modules/Groups/GroupChannelList/ViewModel/GroupChannelListViewModel.cs
generated_at: "2026-04-16T04:46:34.697931+00:00"
model: "Qwen/Qwen3-Coder-Next-FP8"
schema_version: 1
sha256: "7af2406ccff6580f"
---
# ViewModel
**Documentation Page: `GroupChannelListViewModel`**
---
### **1. Purpose**
The `GroupChannelListViewModel` class serves as the core view model for managing channel assignments within the *GroupChannelList* UI module. It orchestrates the display, editing, and synchronization of channel data—linking logical channel definitions (e.g., ISO/user codes, sensor assignments, hardware mappings) to physical test hardware and sensor metadata. It supports operations such as bulk import via text paste, drag-and-drop assignment of sensors and hardware channels, range synchronization across channels on the same DAS, and real-time filtering/sorting. It acts as the intermediary between the view (`IGroupChannelListView`, `IGroupChannelSettingsListView`) and domain models (`IGroup`, `ITestSetup`, `ISensorData`, `IHardwareChannel`), publishing events for UI updates and system-wide state changes.
---
### **2. Public Interface**
#### **Constructor**
```csharp
public GroupChannelListViewModel(
IGroupChannelListView view,
IGroupChannelSettingsListView settingsView,
IRegionManager regionManager,
IEventAggregator eventAggregator,
IUnityContainer unityContainer)
```
- Initializes the view model, wires up views, sets up interaction requests (`NotificationRequest`, `ConfirmationRequest`), and subscribes to events (`RaiseNotification`, `BusyIndicatorChangeNotification`, `TextPastedEvent`).
- Initializes `SelectedChannelItems` as an `ObservableCollection<IGroupChannel>`.
#### **Properties**
| Property | Type | Description |
|---------|------|-------------|
| `View` | `IGroupChannelListView` | Reference to the main channel list view. |
| `SettingsView` | `IGroupChannelSettingsListView` | Reference to the channel settings view. |
| `NotificationRequest` | `InteractionRequest<Notification>` | Prism interaction request for displaying notifications. |
| `ConfirmationRequest` | `InteractionRequest<Confirmation>` | Prism interaction request for confirmation dialogs. |
| `PropertyChanged` | `event PropertyChangedEventHandler` | Standard `INotifyPropertyChanged` event. |
| `ChannelCount` | `int` | Derived from `AllChannels.Count`; triggers `GroupChannelsChangedEvent` on change. |
| `AllChannels` | `IList<IGroupChannel>` | *Internal* full list of channels (including blank trailing channel). |
| `Channels` | `IList<IGroupChannel>` | *Internal* list of non-blank channels (used for UI rendering). |
| `SettingChannels` | `ObservableCollection<IGroupChannel>` | Sorted, filtered list of non-blank channels for settings view. |
| `SelectedChannelItems` | `ObservableCollection<IGroupChannel>` | Currently selected channels (for multi-select operations). |
| `SearchTerm` | `string` | Current search filter term. |
| `BridgeFilter` | `PossibleFilters` | Bridge-type filter (e.g., `Analog`, `Squib`, `DigitalIn`). |
| `UseTestSetupOrder` | `bool` | Whether channels are ordered by `TestSetupOrder` (vs `GroupChannelOrder`). |
| `ISOViewMode` | `bool` | Controls display of ISO/user fields. |
| `ShowSensorChannelUserValues` | `bool` | Controls visibility of sensor/user-specific fields. |
| `AllowSensorPushAndPull` | `bool` | Enables sensor parameter comparison and push/pull UI. |
| `UserIsAdmin` | `bool` | Admin status for permission checks. |
| `AllowChannelDeletionByNonAdminUser` | `bool` | Whether non-admin users can delete channels. |
| `AllowChannelDeletionFromFixedGroup` | `bool` | Whether channels in fixed groups can be deleted. |
| `IsBusy` | `bool` | Bound to busy indicator via `BusyIndicatorChangeNotification`. |
| `Group` | `IGroup` | *Set externally*; the group currently being edited. |
| `TestSetup` | `ITestSetup` | *Set externally*; the test setup currently being edited. |
| `Page` | `object` | *Set externally*; the page context (e.g., `GroupsPage`, `TestSetupsPage`). |
#### **Key Methods**
| Method | Signature | Description |
|--------|-----------|-------------|
| `UpdateRangeLowG` | `public void UpdateRangeLowG(IGroupChannel channelChanged)` | Propagates `RangeLowG` to all other channels on the same DAS that have `RangeModifiableSensorLowG = true`. |
| `UpdateRangeARS` | `public void UpdateRangeARS(IGroupChannel channelChanged)` | Propagates `Range` to all other channels on the same DAS that have `RangeModifiableSensorARS = true`. |
| `UpdateACCouplingEnabled` | `public void UpdateACCouplingEnabled(IGroupChannel channelChanged)` | Propagates `ACCouplingEnabled` to other channels on the same DAS (casts to `GroupChannel`). |
| `DoSensorAssignment` | `public void DoSensorAssignment(IGroupChannel groupChannel, IDragAndDropItem[] sensors)` | Assigns sensors to consecutive channels starting at `groupChannel`. Skips assignment to TSR-AIR channels (except StreamOut/UART). Adds new channels if needed. |
| `DoHardwareAssignment` | `public void DoHardwareAssignment(IGroupChannel groupChannel, IHardwareChannel[] hardwareChannels)` | Assigns hardware channels to consecutive channels. Skips assignment to non-blank/non-StreamOut/UART channels if source is TSR-AIR. |
| `OnTextPasted` | `public void OnTextPasted(ITextPastedEventArgs args)` | Handles paste events (ID = `GroupChannel.PASTE_ID`). Parses tab/semicolon/comma-delimited text into channels, inserting/updating starting at the senders position. |
| `ParseText` | `private IEnumerable<IGroupChannel> ParseText(string text, object tag, out bool oneColumn)` | Parses raw text into `IGroupChannel` objects. Supports column mapping via `tag` (e.g., `"GroupName"`, `"ISOCode"`). Handles sensor/hardware lookup via dictionaries. |
| `GetSensorSerialNumber` | `private string GetSensorSerialNumber(string channelSensor)` | Extracts serial number from sensor string (e.g., `"strain gauge 1 (SG1)"``"SG1"`). |
| `CreateGroupIfNeeded` | `public IGroup CreateGroupIfNeeded(ITestSetup testSetup, string groupName)`<br>`private IGroup CreateGroupIfNeeded(string groupName)` | Creates a new group if none exists for `groupName` under `TestSetup`. |
| `OnSetActive` | `public void OnSetActive()` | Called when view becomes active. Updates channel group names, compares sensor parameters (`CompareAndMarkChannelParameters`), refreshes view settings/columns, and resets sort/filter state. |
| `CompareAndMarkChannelParameters` | `public bool CompareAndMarkChannelParameters(IGroupChannel ch)` | Compares channel parameters (e.g., `Range`, `FilterClass`, `SquibFireMode`) against sensor DB defaults. Marks channel as *different* if mismatched. Returns `true` if any change detected. |
| `ResetSettingChannels` | `private void ResetSettingChannels()` | Rebuilds `SettingChannels` from `Channels`, applying sort (via `GroupChannelComparer`), filtering blanks, and setting `DigitalOutDurationMax` for TOM hardware. |
| `Unset` | `public void Unset()` | Clears all internal state: `AllChannels`, `Channels`, sensor/hardware lookup dictionaries, filters. |
| `ClearAllFilters` | `public void ClearAllFilters()` | Resets `SearchTerm`, `BridgeFilter`, `_filterByField`, `_dontFilterList`, and publishes `ListViewStatusEvent.Unloaded`. |
| `PopulateChannels` | `public IDictionary<IGroup, IGroupChannel[]> PopulateChannels(...)` | **Core initialization method.** Loads channels from `Group` or `TestSetup`, populates lookup dictionaries (`_idToSensorDictionary`, `_displayToHardwareChannel`), sets up channel metadata (e.g., `RemoveSensorVisibility`, `DeleteShouldBeEnabled`), and returns `ChannelsForGroup` mapping. |
| `MarkModified` | `public void MarkModified(IGroupChannel channel, bool bNotifyChanged = true)` | Handles adding a new blank channel after `channel` (if its the last non-blank), updates ordering, and ensures group assignment. |
| `Remove` | `public void Remove(IGroupChannel channel, bool notifyChanged = true)` | Removes `channel`, adds a new blank channel if needed, updates group/channel mappings, and triggers `NotifyChannelsChanged`. |
| `NotifyChannelsChanged` | `public void NotifyChannelsChanged()` | Publishes `PageModifiedEvent` and `GroupUpdatedEvent`, and updates `ChannelCount`/`AssignedPhysicalChannelCount`. |
| `GroupNameChanged` | `public void GroupNameChanged(IGroupChannel channel)` | Updates `TestSetup.ChannelsForGroup` when a channels group name changes (removes from old group, adds to new). |
| `ReportErrors` | `public void ReportErrors(string[] errors)` | Publishes `PageErrorEvent` with error messages. |
| `Clear` | `public void Clear(IGroupChannel channel)` | Calls `channel.Clear()` (resets channel fields to defaults). |
| `OnBusyIndicatorNotification` | `private void OnBusyIndicatorNotification(bool eventArg)` | Event handler for `BusyIndicatorChangeNotification`; sets `IsBusy`. |
| `OnRaiseNotification` | `private void OnRaiseNotification(NotificationContentEventArgs eventArgsWithTitle)` | Event handler for `RaiseNotification`; wraps message and title into `Notification` for UI. |
#### **Event Handlers (Private)**
- `OnTextPasted`: Handles paste events.
- `OnBusyIndicatorNotification`: Updates `IsBusy`.
- `OnRaiseNotification`: Triggers `NotificationRequest`.
#### **Event Properties (Public)**
- `PropertyChanged`: Standard property change notification.
---
### **3. Invariants**
- **Channel Ordering**:
- `AllChannels` always ends with a blank `GroupChannel` (used for adding new channels).
- `Channels` is a subset of `AllChannels` containing only non-blank channels.
- Channel ordering is maintained via `TestSetupOrder` (if `UseTestSetupOrder`) or `GroupChannelOrder`.
- `DetermineButtonState()` enforces `CanMoveUp`/`CanMoveDown` constraints (first channel cannot move up; last non-blank cannot move down).
- **Group/Hardware Consistency**:
- Channels are associated with a `Group` (from `Group` or `TestSetup`) and `HardwareChannel`.
- `GroupChannel.GroupName` must match `Group.DisplayName`.
- Hardware assignments to TSR-AIR channels are restricted (only to blank, StreamOut, or UART channels).
- **Sensor/Hardware Lookup**:
- `_idToSensorDictionary`, `_serialNumberToSensorDictionary`, and `_displayToHardwareChannel` must be populated before `PopulateChannels` completes.
- Sensor serial numbers are extracted from strings (e.g., `"name (SN)"``"SN"`) using `GetSensorSerialNumber`.
- **Filtering**:
- `_dontFilterList` preserves channels during filtering (e.g., after drag/drop or paste).
- `Filter()` respects `BridgeFilter`, `SearchTerm`, and per-field filters (`_filterByField`).
- **Notification & Events**:
- `OnPropertyChanged("ChannelCount")` triggers `GroupChannelsChangedEvent`.
- `MarkModified`, `Remove`, `NotifyChannelsChanged` publish `PageModifiedEvent` and `GroupUpdatedEvent`.
---
### **4. Dependencies**
#### **External Dependencies (Imports/Usings)**
- **Prism Framework**: `IEventAggregator`, `IRegionManager`, `UnityContainer`, `InteractionRequest<T>`, `DelegateCommand`.
- **DTS Common Libraries**:
- `DTS.Common.Classes.Groups`
- `DTS.Common.Enums` (e.g., `PossibleFilters`, `Fields`, `HardwareTypes`)
- `DTS.Common.Interface.*` (e.g., `IGroupChannel`, `ISensorData`, `IHardwareChannel`)
- `DTS.Common.Events.*` (e.g., `TextPastedEvent`, `PageErrorEvent`)
- `DTS.Common.Storage`, `DTS.Common.Converters`, `DTS.Common.Interactivity`
#### **Key Dependencies**
- **Views**: `IGroupChannelListView`, `IGroupChannelSettingsListView`.
- **Services**: `IEventAggregator`, `IUnityContainer`, `IRegionManager`.
- **Data Sources**: `ITestSetup`, `IGroup`, `ISensorData`, `IDASHardware`, `IChannelSetting`.
- **Events Published**:
- `GroupChannelsChangedEvent`
- `PageModifiedEvent`
- `GroupUpdatedEvent`
- `PageErrorEvent`
- `ListViewStatusEvent`
- `AppStatusEvent`
- `RaiseNotification`
#### **Dependents**
- `GroupChannelList` view (binds to `View`, `SettingsView`).
- Other modules via `GroupChannelsChangedEvent`, `PageModifiedEvent`, `GroupUpdatedEvent`.
---
### **5. Gotchas**
- **TSR-AIR Channel Restrictions**:
- Sensor/hardware assignments are blocked for non-StreamOut/UART TSR-AIR channels (see `DoSensorAssignment`, `DoHardwareAssignment`).
- Embedded sensors in TSR-AIR units are only added if the unit is not already in the group.
- **Blank Channel Handling**:
- `AllChannels` always ends with a blank channel; `Channels` excludes it.
- `MarkModified` and `Remove` manage blank channel insertion/removal to maintain this invariant.
- **Paste Parsing Ambiguity**:
- `ParseText` splits on `,`, `\t`, or `;` (in order) if tokens < 2. Column mapping depends on `tag` (e.g., `"GroupName"`).
- `oneColumn` output indicates if only one column was present (used for single-field pastes).
- **Sensor Serial Number Parsing**:
- `GetSensorSerialNumber` assumes serial numbers are enclosed in parentheses (e.g., `"name (SN)"`). If no parentheses, the entire string is used.
- **Group Name Changes**:
- `GroupNameChanged` modifies `TestSetup.ChannelsForGroup` and may remove empty groups. Does *not* publish `PageModifiedEvent` (commented out).
- **Filtering Behavior**:
- `_dontFilterList` is cleared on user-initiated filter changes (`initiatedByUser = true`).
- Per-field filters (`_filterByField`) are applied *after* `BridgeFilter` and `SearchTerm`.
- **Hardware Channel Lookup**:
- `_displayToHardwareChannel` uses `channel.ToString(hardware)` as the key (implementation-dependent string representation).
- **Sensor Constants**:
- `CompareAndMarkChannelParameters` skips comparison for test-specific sensors (e.g., `TEST_SPECIFIC_ANALOG_SERIAL`).
- **Settings View Loading**:
- `SettingsViewLoaded` controls whether `SettingChannels` triggers `OnPropertyChanged`.
- `SettingChannelsLoaded` publishes `AppStatusEvent` (Busy → Available) during UI initialization.
- **No-Op Initialization Methods**:
- `Initialize`, `InitializeAsync`, `Activated`, `Cleanup`, `CleanupAsync` are stubbed (no implementation).
- **Range Propagation Scope**:
- `UpdateRangeLowG`/`UpdateRangeARS` only propagate within the same `DASId`.
- `UpdateACCouplingEnabled` requires `GroupChannel` cast (runtime risk if non-`GroupChannel` instances exist).
- **Channel Ordering After Paste**:
- After paste, `AllChannels[i].TestSetupOrder`/`GroupChannelOrder` is reset to `1 + i` for all non-blank channels.
- **Resource Strings**:
- Uses `Resources.StringResources.TestChannelsGroupName` for default group names in `TestSetup` mode.
- **Missing Validation**:
- `ParseText` does not validate sensor/hardware references beyond existence in dictionaries (e.g., invalid IDs are logged but do not halt processing).
---
*Note: All behaviors are derived strictly from the provided source. No external documentation or runtime behavior was assumed.*

View File

@@ -0,0 +1,113 @@
---
source_files:
- DataPRO/Modules/Groups/GroupImport/GroupImportModule.cs
generated_at: "2026-04-16T04:45:20.865762+00:00"
model: "Qwen/Qwen3-Coder-Next-FP8"
schema_version: 1
sha256: "99bf820620f80499"
---
# GroupImport
## Documentation: `GroupImportModule`
---
### 1. **Purpose**
The `GroupImportModule` is a Prism module responsible for registering the views and view models required for the *Group Import* functionality within the applications UI. It integrates with the Unity dependency injection container to expose the necessary components (`IGroupImportImportView`, `IGroupImportOptionsView`, `IGroupImportPreviewView`, and `IGroupImportViewModel`) as singleton registrations, enabling modular, testable, and loosely coupled UI construction. Additionally, it provides assembly-level metadata via the `GroupImageAttribute`, which is used by the main UI to display the modules name, group (e.g., “Prepare”), and associated icon.
---
### 2. **Public Interface**
#### `GroupImportModule` class
- **`GroupImportModule(IUnityContainer unityContainer)`**
Constructor. Accepts a Unity container via dependency injection and stores it for later use in type registration.
- **`void Initialize()`**
Registers the following types as singletons in the Unity container:
- `IGroupImportImportView``GroupImportImportView`
- `IGroupImportOptionsView``GroupImportOptionsView`
- `IGroupImportPreviewView``GroupImportPreviewView`
- `IGroupImportViewModel``GroupImportViewModel`
This method is called by both `Prism.Modularity.IModule.Initialize()` and `RegisterTypes()`.
- **`void OnInitialized(IContainerProvider containerProvider)`**
Currently empty; no initialization logic beyond type registration is performed.
- **`void RegisterTypes(IContainerRegistry containerRegistry)`**
Delegates to `Initialize()`. (Note: Despite accepting `IContainerRegistry`, it uses the injected `IUnityContainer` internally.)
#### `GroupImageAttribute` class
- **`GroupImageAttribute()`**
Default constructor; initializes image via `AssemblyInfo.GetImage(AssemblyNames.GroupImport.ToString())`.
- **`GroupImageAttribute(string s)`**
Constructor accepting a string argument (unused); initializes image identically to the default constructor.
- **`override BitmapImage AssemblyImage`**
Returns a `BitmapImage` loaded via `AssemblyInfo.GetImage(AssemblyNames.GroupImport.ToString())`.
- **`override string AssemblyName`**
Returns `"GroupImport"` (from `AssemblyNames.GroupImport.ToString()`).
- **`override string AssemblyGroup`**
Returns `"Prepare"` (from `eAssemblyGroups.Prepare.ToString()`).
- **`override eAssemblyRegion AssemblyRegion`**
Throws `NotImplementedException`. *Not implemented.*
- **`override Type GetAttributeType()`**
Returns `typeof(ImageAttribute)`.
- **`override BitmapImage GetAssemblyImage()`**
Returns the value of `AssemblyImage`.
- **`override string GetAssemblyName()`**
Returns the value of `AssemblyName`.
- **`override string GetAssemblyGroup()`**
Returns the value of `AssemblyGroup`.
- **`override eAssemblyRegion GetAssemblyRegion()`**
Throws `NotImplementedException`. *Not implemented.*
---
### 3. **Invariants**
- The `GroupImportModule` must be initialized *after* the Unity container is available (via DI), and before any views/view models are resolved.
- All registered types (`IGroupImport*View`, `IGroupImportViewModel`) are registered as *singletons* (default Unity lifetime).
- `GroupImageAttribute` is applied at the **assembly level** (via `[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = false)]`), and only one instance per assembly is allowed.
- `AssemblyImage`, `AssemblyName`, and `AssemblyGroup` are computed *at runtime* using static methods (`AssemblyInfo.GetImage`, `AssemblyNames.GroupImport`, `eAssemblyGroups.Prepare`). Their values depend on external definitions in `DTS.Common` and must be consistent.
- `AssemblyRegion` and `GetAssemblyRegion()` are **not implemented** and will throw `NotImplementedException` if invoked.
---
### 4. **Dependencies**
#### **Depends on**
- `DTS.Common` (specifically `AssemblyInfo`, `AssemblyNames`, `eAssemblyGroups`)
- `Prism.Modularity` (`IModule`, `IContainerProvider`, `IContainerRegistry`)
- `Unity` (`IUnityContainer`)
- `System.Windows.Media.Imaging` (`BitmapImage`)
#### **Depended on by**
- The Prism bootstrapper/container infrastructure (via `[Export(typeof(IModule))]` and `[Module(...)]` attributes).
- UI components that resolve `IGroupImport*View` or `IGroupImportViewModel`.
- The main application shell or module catalog system that consumes `GroupImageAttribute` to display module metadata.
---
### 5. **Gotchas**
- **`RegisterTypes` does not use `IContainerRegistry`**: Despite implementing `IContainerRegistry`, the method ignores it and calls `Initialize()`, which uses the injected `IUnityContainer`. This is inconsistent with Prisms recommended pattern (where `RegisterTypes` should use `containerRegistry`) and may cause confusion or breakage if the module is used in a non-Unity Prism setup.
- **`AssemblyRegion` is unimplemented**: Both `AssemblyRegion` and `GetAssemblyRegion()` throw `NotImplementedException`. If the UI or module loader relies on this property, it will crash at runtime.
- **Redundant constructor**: The `GroupImageAttribute(string s)` constructor accepts a parameter that is never used.
- **No validation of image loading**: `AssemblyInfo.GetImage(...)` may return `null` if the image resource is missing; this is not handled, potentially leading to `NullReferenceException` at runtime when the image is rendered.
- **No documentation on view/view model responsibilities**: While the types are registered, their roles (e.g., what `IGroupImportImportView` vs `IGroupImportPreviewView` does) are not described here and must be inferred from their implementations.
None identified beyond the above.

View File

@@ -0,0 +1,44 @@
---
source_files:
- DataPRO/Modules/Groups/GroupImport/Properties/AssemblyInfo.cs
generated_at: "2026-04-16T04:45:50.776697+00:00"
model: "Qwen/Qwen3-Coder-Next-FP8"
schema_version: 1
sha256: "06eddeeb5b49ca9c"
---
# Properties
## 1. Purpose
This module (`GroupImportModule`) is an assembly containing metadata and configuration for a .NET component responsible for group import functionality within the larger DataPRO system. Based solely on the file name (`GroupImport`) and assembly title, its role is to encapsulate logic (not visible in this file) related to importing group data—likely from external sources (e.g., CSV, XML, or legacy systems)—into the applications internal group management subsystem. This file itself contains only assembly-level attributes (e.g., versioning, COM visibility), not executable logic.
## 2. Public Interface
**No public API surface is defined in this file.**
This file (`AssemblyInfo.cs`) is strictly metadata and contains no types, functions, classes, or methods. It only declares assembly-level attributes via `System.Reflection` and `System.Runtime.InteropServices` attributes.
## 3. Invariants
- The assembly identity is fixed:
- `AssemblyTitle` = `"GroupImportModule"`
- `AssemblyVersion` = `"1.0.0.0"`
- `AssemblyFileVersion` = `"1.0.0.0"`
- `ComVisible` = `false`
- `Guid` = `"f3e176ef-8eaf-4277-95f2-c8546c254248"`
- The assembly is not intended for COM interop (per `ComVisible(false)`), and the GUID is reserved for typelib identification *only if* COM exposure were enabled in the future.
- No runtime invariants apply, as this file contributes no executable code.
## 4. Dependencies
- **Dependencies**:
- `System.Reflection`
- `System.Runtime.CompilerServices`
- `System.Runtime.InteropServices`
These are standard .NET Framework/BCL namespaces (no external dependencies inferred).
- **Dependents**:
- Unknown from this file alone. This assembly is likely referenced by other modules in the `DataPRO` solution (e.g., a core group management module or a UI layer), but no explicit references are declared here.
## 5. Gotchas
- **Assembly versioning is static**: Both `AssemblyVersion` and `AssemblyFileVersion` are hardcoded to `1.0.0.0`. This may indicate legacy or placeholder configuration; in practice, versioning should be updated for releases to avoid binding issues.
- **COM visibility is disabled**: If COM interop is required (e.g., for legacy automation), `ComVisible(true)` and explicit `Guid` on *types* (not just the assembly) would be necessary—this file alone does not enable COM.
- **No functional code**: Developers should not expect to find import logic here. The actual implementation resides in other files (e.g., `GroupImporter.cs`, `ImportHandler.cs`), which are not provided.
- **Copyright year is 2017**: May indicate outdated metadata if the module has been recently modified.
None identified beyond the above.

View File

@@ -0,0 +1,87 @@
---
source_files:
- DataPRO/Modules/Groups/GroupImport/Resources/TranslateExtension.cs
- DataPRO/Modules/Groups/GroupImport/Resources/StringResources.Designer.cs
generated_at: "2026-04-16T04:45:43.131858+00:00"
model: "Qwen/Qwen3-Coder-Next-FP8"
schema_version: 1
sha256: "d8e7eb58224237bd"
---
# Resources
## Documentation: `TranslateExtension` Markup Extension
---
### 1. **Purpose**
This module provides a WPF `MarkupExtension` (`TranslateExtension`) to enable declarative, localized string resolution in XAML. It allows UI elements to bind to localized resources using a string key, falling back to a visible placeholder if the key is missing or the resource is unavailable. Its role is to support internationalization (i18n) of the Group Import modules UI by abstracting resource lookup away from code-behind and into XAML markup.
---
### 2. **Public Interface**
#### `TranslateExtension` class
**Namespace:** `DBImportExport.Resources`
**Base class:** `System.Windows.Markup.MarkupExtension`
**Attribute:** `[MarkupExtensionReturnType(typeof(string))]`
##### Constructor
```csharp
public TranslateExtension(string key)
```
- **Parameters:**
- `key`: The resource key (e.g., `"GroupTags"`, `"Import_Importing"`) used to look up a localized string in `StringResources`.
- **Behavior:** Stores the key for later use in `ProvideValue`.
##### `ProvideValue` method
```csharp
public override object ProvideValue(IServiceProvider serviceProvider)
```
- **Returns:** `string`
- **Behavior:**
- If `_key` is `null` or empty → returns `"#stringnotfound#"`.
- Otherwise, attempts to retrieve the string via `StringResources.ResourceManager.GetString(_key)`.
- If found → returns the localized string.
- If not found (`null`) → returns `"#stringnotfound# " + _key` (e.g., `"#stringnotfound# Import_Importing"`).
- **Note:** The `serviceProvider` parameter is unused.
---
### 3. **Invariants**
- `_key` is immutable after construction (no setter, no mutation).
- `StringResources.ResourceManager.GetString(key)` is the *only* source of localized strings; no fallback logic beyond the `NotFound` constant is implemented.
- The `NotFound` constant (`"#stringnotfound#"`) is used consistently for both missing keys and missing values.
- If `StringResources.ResourceManager` fails to initialize (e.g., due to assembly/resource loading issues), `GetString` may throw — but this is not handled in the extension and would result in a runtime exception.
---
### 4. **Dependencies**
#### **Internal Dependencies**
- `GroupImport.Resources.StringResources`:
- Strongly-typed resource class generated from `.resx` files.
- Provides access to localized strings via `ResourceManager.GetString(key)`.
- Contains keys like `"GroupTags"`, `"Import_Importing"`, `"Preview_InvalidName"`, etc.
#### **External Dependencies**
- `System.Windows.Markup.MarkupExtension`: Base class for WPF markup extensions.
- `System`: Used for `string.IsNullOrEmpty`, `object.ReferenceEquals`, etc.
#### **Consumers (Inferred)**
- XAML files in the `GroupImport` module (e.g., `*.xaml`) that use `{local:Translate KeyName}` syntax to bind UI text to localized resources.
---
### 5. **Gotchas**
- **No null-safety for `ResourceManager.GetString()`**: If `StringResources.ResourceManager` is misconfigured (e.g., wrong base name `"GroupImport.Resources.StringResources"`), `GetString` may return `null` or throw — the extension only handles `null` by appending the key to `#stringnotfound#`.
- **Hardcoded `NotFound` string**: The placeholder `"#stringnotfound#"` is visible in the UI if a key is missing, which may confuse end users. No localization-aware fallback (e.g., returning the key itself) is implemented.
- **No caching of resolved values**: `ProvideValue` is called repeatedly (e.g., during layout updates), and each call re-invokes `ResourceManager.GetString`. While `ResourceManager` caches internally, repeated calls are still inefficient.
- **Namespace mismatch**: The class resides in `DBImportExport.Resources` but references `GroupImport.Resources.StringResources`. This may indicate legacy refactoring or intentional decoupling — developers should verify assembly/resource naming consistency.
- **No support for format strings**: While `StringResources` contains format strings (e.g., `"Importing {0}:{1}"`), `TranslateExtension` does not accept or apply arguments — it only resolves the raw key. Formatting must be handled elsewhere (e.g., in code-behind or via `String.Format` after resolution).
- **Auto-generated `StringResources.Designer.cs`**: Changes to `.resx` files require regeneration of `StringResources`. If keys are renamed/removed in `.resx` but not updated in XAML, `TranslateExtension` will return the `#stringnotfound#` fallback.
> **None identified from source alone** regarding thread-safety, disposal, or WPF-specific lifecycle quirks — but given the simplicity of the extension, it is likely safe for standard WPF usage.

View File

@@ -0,0 +1,100 @@
---
source_files:
- DataPRO/Modules/Groups/GroupImport/View/GroupImportImportView.xaml.cs
- DataPRO/Modules/Groups/GroupImport/View/GroupImportOptionsView.xaml.cs
- DataPRO/Modules/Groups/GroupImport/View/GroupImportPreviewView.xaml.cs
generated_at: "2026-04-16T04:46:11.528450+00:00"
model: "Qwen/Qwen3-Coder-Next-FP8"
schema_version: 1
sha256: "4920dece220dd9a5"
---
# View
### **Purpose**
This module provides the WPF UI views for the group import workflow within the DataPRO system, specifically handling user interaction for selecting source files, configuring import options, previewing imported groups and channels, and validating the import state before proceeding. It serves as the presentation layer for the group import functionality, coordinating with a shared `GroupImportViewModel` to manage state and business logic, while enforcing UI-specific validation rules and user privilege checks (e.g., admin-only tag editing).
---
### **Public Interface**
#### **`GroupImportImportView`**
- **Type**: `partial class` implementing `IGroupImportImportView`
- **Constructor**: `GroupImportImportView()`
- Initializes the WPF component via `InitializeComponent()`.
- *No additional logic or public members exposed beyond initialization.*
#### **`GroupImportOptionsView`**
- **Type**: `partial class` implementing `IGroupImportOptionsView`
- **Constructor**: `GroupImportOptionsView()`
- Initializes the WPF component via `InitializeComponent()`.
- **`Validate(out List<string> errors, out List<string> warnings)`**
- **Signature**: `public bool Validate(out List<string> errors, out List<string> warnings)`
- **Behavior**: Validates that at least one source file is selected.
- Returns `true` if `vm.SourceFiles.Length >= 1`.
- Returns `false` and populates `errors` with `StringResources.Preview_NoFilesSelected` if no files are selected.
- *Note*: Does not validate file contents or other options—only file presence.
#### **`GroupImportPreviewView`**
- **Type**: `partial class` implementing `IGroupImportPreviewView`
- **Constructor**: `GroupImportPreviewView()`
- Initializes the WPF component via `InitializeComponent()`.
- **Event Handlers** (WPF event wiring, not public API but critical for behavior):
- `GroupName_Changed(object sender, TextChangedEventArgs e)`
- Updates the `GroupName` property of the bound `GroupGRPImportGroup` instance.
- Calls `GroupNameInvalidate()` on all channels in the group.
- Triggers `vm.CheckGroupName()` on the `GroupImportViewModel`.
- `GroupTags_Changed(object sender, TextChangedEventArgs e)`
- Updates the `GroupTags` property of the bound `GroupGRPImportGroup` instance.
- `IncludedChecked(object sender, RoutedEventArgs e)`
- Calls `vm.InvalidateChannels()` on the `GroupImportViewModel`.
- `IncludedUnchecked(object sender, RoutedEventArgs e)`
- Calls `vm.InvalidateChannels()` on the `GroupImportViewModel`.
- **`Validate(bool userIsAdmin, out List<string> errors, out List<string> warnings)`**
- **Signature**: `public bool Validate(bool userIsAdmin, out List<string> errors, out List<string> warnings)`
- **Behavior**: Performs comprehensive validation of groups and channels for import.
- Checks admin-only tag compatibility: if `!userIsAdmin` and `GroupTags` contains tags not in `ImportingUserTags`, adds a formatted error and returns `false`.
- Checks `GroupNameHasError`: adds `StringResources.Preview_InvalidName` error and returns `false`.
- Checks `GroupErrors`: adds all `ExtraInfo` strings as errors and returns `false`.
- Checks if group exists (`vm.CheckGroupExists`) and `!Overwrite`: adds `StringResources.Preview_InvalidName` error and returns `false`.
- Iterates channels:
- On `ch.Error != null`:
- Adds warnings or errors based on `ErrorCode` (e.g., `InvalidISOCodeInput`, `InvalidFullScaleInput`, `SensorNotFound`).
- Some errors (`FileEmpty`, `InvalidISOCodeInput`) set `bAnyValidChannels = true` but do *not* fail validation.
- On `ch.Error == null`: sets `bValid = true` and `bAnyValidChannels = true`.
- If no valid channels exist (`!bAnyValidChannels`), adds `StringResources.Preview_NoGroupsToImport` to errors and returns `false`.
- Returns `true` only if no fatal errors occurred and at least one valid channel exists.
---
### **Invariants**
- **File Selection**: `GroupImportOptionsView.Validate()` requires `SourceFiles.Length >= 1` for success; otherwise, it fails with a specific error.
- **Admin Tag Enforcement**: Non-admin users cannot set `GroupTags` that include tags not present in `ImportingUserTags`; this causes immediate validation failure with a detailed error message.
- **Group Name Validity**: A group with `GroupNameHasError == true`, existing group name without `Overwrite == true`, or non-empty `GroupErrors` causes immediate validation failure in `GroupImportPreviewView.Validate()`.
- **Channel-Level Errors**:
- `FileEmpty` and `InvalidISOCodeInput` errors do *not* prevent import (but may indicate partial failure).
- `InvalidFullScaleInput`, `InvalidInvertInput`, `InvalidSensorInput`, and `SensorNotFound` produce warnings but do *not* block import.
- **No-Import Guard**: If no channels are valid (`bAnyValidChannels == false`), validation fails with `StringResources.Preview_NoGroupsToImport`.
---
### **Dependencies**
- **External Dependencies**:
- `DTS.Common.Interface.Groups`: Defines interfaces `IGroupImportImportView`, `IGroupImportOptionsView`, `IGroupImportPreviewView`.
- `DTS.Common.Classes.Groups`: Provides concrete types `GroupGRPImportGroup`, `GroupGRPImportError`.
- `DTS.Common.Strings`: Provides `StringResources` for localized error/warning messages.
- `GroupImport.Resources`: Contains `StringResources` (likely auto-generated `.resx`-based resources).
- **Internal Dependencies**:
- `GroupImportViewModel`: Used as `DataContext` in all three views; its methods (`CheckGroupName`, `InvalidateChannels`, `CheckGroupExists`) are called directly.
- WPF framework (`System.Windows.Controls`, `System.Windows.RoutedEventArgs`, etc.).
---
### **Gotchas**
- **Typo in XML comment**: `GroupImportPreviewView.xaml.cs` has `/// <summary> Interaction logic for GroupImportOptionsView.xaml </summary>` instead of `GroupImportPreviewView.xaml`.
- **Ambiguous `bValid` logic**: In `GroupImportPreviewView.Validate()`, `bValid` is initialized to `true`, then set to `false` *before* checking channels, and only set to `true` if a channel has no error. This may be confusing—`bValid` is ultimately determined by whether *at least one* channel is valid *and* no fatal errors occurred.
- **Tag validation is strict**: Non-admin users are blocked if *any* tag in `GroupTags` is not in `ImportingUserTags`. The error message lists both sets explicitly.
- **Duplicate error suppression**: Errors/warnings are deduplicated via `!errors.Contains(...)` checks, but this is linear-time and may be inefficient for large error sets.
- **No explicit handling for null `vm`**: All views cast `DataContext` to `GroupImportViewModel` without null checks; a null `DataContext` will cause a `NullReferenceException`.
- **`GroupNameInvalidate()` and `InvalidateChannels()` are called on UI thread changes**: These likely trigger re-validation or UI refreshes; callers must ensure thread-safety if invoked off-thread (though WPF data binding typically handles this).
- **`Split()` extension method**: Used on `ImportingUserTags` and `GroupTags` (e.g., `g.ImportingUserTags.Split()`), implying a custom extension method (not standard `string.Split()`); behavior depends on its implementation (e.g., whitespace delimiters? empty entries?).

View File

@@ -0,0 +1,188 @@
---
source_files:
- DataPRO/Modules/Groups/GroupImport/ViewModel/GroupImportViewModel.cs
generated_at: "2026-04-16T04:45:51.906727+00:00"
model: "Qwen/Qwen3-Coder-Next-FP8"
schema_version: 1
sha256: "f514e88931e0b70e"
---
# GroupImportViewModel Documentation
## 1. Purpose
`GroupImportViewModel` is the central view model for the group and channel import functionality in the DTS application. It orchestrates the end-to-end workflow of importing data from `.grp` files—parsing file contents, validating sensor and field data, allowing user review and selection of groups/channels for import, and committing validated data to the database via background processing. It serves as the data context for three distinct views (`IGroupImportOptionsView`, `IGroupImportPreviewView`, `IGroupImportImportView`) and integrates with Prisms region management, event aggregation, and Unity DI container to coordinate UI state and external service calls.
## 2. Public Interface
### Constructor
```csharp
public GroupImportViewModel(
IGroupImportOptionsView optionsView,
IGroupImportPreviewView previewView,
IGroupImportImportView importView,
IRegionManager regionManager,
IEventAggregator eventAggregator,
IUnityContainer unityContainer)
```
Initializes the view model, assigns views and their `DataContext`, sets up interaction requests (`NotificationRequest`, `ConfirmationRequest`), and subscribes to `RaiseNotification` and `BusyIndicatorChangeNotification` events.
### Methods
- **`void ParseSourceFiles(string userTags)`**
Reads and parses all `.grp` files listed in `SourceFiles`. For each file:
- Extracts group name from file name (strips extension).
- Assigns `userTags` to `GroupTags` and `ImportingUserTags`.
- Parses each non-empty line using `Parse()` (supports escaped commas via parentheses).
- Validates fields: expects 5 fields per line (`SensorSerialNumber`, `DisplayName`, `ISOCode`, `Invert`, `FullScale`).
- Reports errors for missing sensors (unless empty), invalid invert/full-scale values, wrong field count, or empty files.
- Populates `Groups` and calls `ProcessChannels()`.
- **`void Import()`**
Starts the import process on a background thread via `ThreadPool.QueueUserWorkItem(ImportFunc)`.
- **`private void ImportFunc(object o)`**
Background method that:
- Fetches default channel settings via `DbOperations.GetChannelSettingDefaults()`.
- Updates UI progress state (`ImportProgressValue`, `ImportProgressBarVisibility`, `ImportProgressColor`, `DisableUI`).
- Iterates over included groups and their channels:
- Skips channels with critical errors (`FileEmpty`, `InvalidSensorInput`, `SensorNotFound`).
- For non-critical errors, uses `null` for invalid `FullScale` or `Invert`.
- Calls `CreateGroup`, `AddChannel`, and finally `CommitGroups`.
- Restores UI state on completion (though commented-out lines suggest UI reset is incomplete).
- **`void SetStatus(string message, Color color)`**
Updates `ImportProgressText`, `ImportProgressColor`, `ImportProgressBarVisibility` (collapsed), and invokes `EnableUI`.
- **`void Reset()`**
Clears all imported data: `SourceFiles`, `Channels`, `Groups`, progress state, and resets `ImportProgressValue` to 0.
- **`void CheckGroupName()`**
Validates group names:
- Flags groups with duplicate names in the import set.
- Flags groups whose name already exists in the application *and* `Overwrite` is `false`.
- Sets `GroupNameHasError = true` on invalid groups.
- **`private static string[] Parse(string line)`**
Parses a single `.grp` line, respecting parenthetical escaping (e.g., `"this(,)is"` → one field `"this(,)is"`).
- **`private void ProcessChannels()`**
Flattens all channels from `Groups` into the `Channels` array.
- **`void InvalidateChannels()`**
Raises `PropertyChanged` for `IncompleteChannels` and `CompleteChannels` computed properties.
- **`void Cleanup()` / `Task CleanupAsync()` / `void Initialize()` / `Task InitializeAsync()` / `void Activated()`**
No-op stubs; likely required by Prism interfaces (`INavigationAware`, `IInitializeAsync`, etc.) but not implemented.
### Properties
- **`IGroupImportOptionsView ImportOptionsView`**, **`IGroupImportPreviewView ImportPreviewView`**, **`IGroupImportImportView ImportView`**
References to the three associated views.
- **`string[] SourceFiles`**
Array of `.grp` file paths to parse.
- **`GroupGRPImportGroup[] Groups`**
Parsed groups with their channels and errors.
- **`GroupGRPImportChannel[] Channels`**
Flattened list of all channels from `Groups`.
- **`GroupGRPImportChannel[] IncompleteChannels`**
Channels in included groups that have *non-recoverable* errors (e.g., `SensorNotFound`, `InvalidSensorInput`). These will *not* be imported.
- **`GroupGRPImportChannel[] CompleteChannels`**
Channels in included groups that either have no errors *or* have recoverable errors (`InvalidFullScaleInput`, `InvalidInvertInput`). These *will* be imported (with `null` for invalid fields).
- **`string ImportProgressText`**, **`Color ImportProgressColor`**, **`Visibility ImportProgressBarVisibility`**, **`double ImportProgressValue`**
UI state for the import progress bar.
- **`bool IsBusy`**
Bound to busy indicator; set via `OnBusyIndicatorNotification`.
- **`InteractionRequest<Notification> NotificationRequest`**, **`InteractionRequest<Confirmation> ConfirmationRequest`**
Prism interaction requests for showing notifications and confirmation dialogs.
- **`bool IsDirty`**
Read-only; always `false` (never set to `true` in source).
- **`bool IsMenuIncluded`**, **`bool IsNavigationIncluded`**
UI state flags (bound to menu/navigation visibility); no logic sets them beyond property change notifications.
- **`string HeaderInfo`**
Returns `"MainRegion"`.
### Commands
- **`DelegateCommand ImportBrowseCommand`**
Opens a file dialog (`OpenFileDialog`) with `Multiselect=true`, `Filter` from `StringResources.ImportFileFilter`, sets `SourceFiles`, `BrowseOk=true`, and navigates to `Steps.Preview` via `SwitchNavSteps`.
### Delegates (Settable Properties)
- **`CheckGroupExistsDelegate CheckGroupExists`**
Function to check if a group exists in the application.
- **`CheckSensorExistsDelegate CheckSensorExists`**
Function to check if a sensor exists.
- **`CreateGroupDelegate CreateGroup`**
Action to create a group.
- **`AddChannelToGroupDelegate AddChannel`**
Action to add a channel to a group.
- **`CommitGroupsDelegate CommitGroups`**
Action to commit groups to the database.
- **`Disable_UIDelegate DisableUI`**, **`Enable_UIDelegate EnableUI`**
Actions to disable/enable the UI during import.
- **`SwitchNavStepsDelegate SwitchNavSteps`**
Action to navigate between import steps (e.g., `Steps.Preview`).
- **`FileUtils.LogDelegate Logger`**
Optional logging delegate; invoked on exceptions.
## 3. Invariants
- **File Parsing**: Each `.grp` line must contain 5 comma-separated fields (or be empty/whitespace). Lines with fewer or more fields are marked with `InvalidSensorInput`.
- **Sensor Validation**: A channel is flagged `SensorNotFound` if `CheckSensorExists` is non-null, the sensor serial number is non-empty, and `CheckSensorExists(sensorSerialNumber)` returns `false`. Empty sensor serial numbers are *allowed* (per comment referencing FB13753).
- **Invert Field**: Accepts `"yes"/"no"` (case-insensitive) or `bool.TryParse`-compatible strings. Invalid values trigger `InvalidInvertInput`.
- **FullScale Field**: Must parse as `double`; otherwise, `InvalidFullScaleInput`.
- **Group Name Uniqueness**: Within the import set, duplicate group names are flagged. Across the import set and application, group names must be unique *unless* `Overwrite=true`.
- **Import Progress State**: During `ImportFunc`, `ImportProgressBarVisibility` is set to `Visible`, `DisableUI` is called, and progress is tracked. Completion logic is partially commented out, so UI may not fully reset.
- **Channel Inclusion Logic**: Only channels from groups where `Included=true` are considered for import. Channels with critical errors (`FileEmpty`, `InvalidSensorInput`, `SensorNotFound`) are skipped entirely; others may be imported with `null` for invalid fields.
## 4. Dependencies
### Imports/References
- **DTS.Common**:
- `Events` (`IEventAggregator`, `RaiseNotification`, `BusyIndicatorChangeNotification`)
- `Utils` (`FileUtils.LogDelegate`)
- `Classes.Groups` (`GroupGRPImportGroup`, `GroupGRPImportChannel`, `GroupGRPImportError`)
- `Enums.Groups` (`GroupImportEnums.Steps`, `GroupGRPImportError.Errors`)
- `Interface.Groups` (`IGroupImportOptionsView`, `IGroupImportPreviewView`, `IGroupImportImportView`, `IGroupImportViewModel`)
- `Storage` (`DbOperations`)
- `Interactivity` (`InteractionRequest<T>`)
- **Prism**:
- `Regions` (`IRegionManager`)
- `Events` (`IEventAggregator`)
- `DelegateCommand`
- **Unity** (`IUnityContainer`)
- **System.Windows** (`Visibility`, `Color`)
- **System.Windows.Forms** (`OpenFileDialog`)
- **StringResources** (resource strings for UI messages)
### Dependencies on External Services
- `DbOperations.GetChannelSettingDefaults()` — for default channel settings.
- `CheckSensorExists`, `CheckGroupExists`, `CreateGroup`, `AddChannel`, `CommitGroups` — injected delegates for database operations.
- `SwitchNavSteps` — navigation delegate (likely from a parent view model or shell).
## 5. Gotchas
- **Incomplete UI Reset After Import**: `ImportFunc` sets `ImportProgressBarVisibility = Visibility.Visible` and `DisableUI`, but the corresponding reset (`Visibility.Collapsed`, `EnableUI`) is commented out. This may leave the UI in a disabled state if import completes without error.
- **Empty Sensor Serial Numbers Are Allowed**: Despite `CheckSensorExists` validation, empty serial numbers bypass the `SensorNotFound` check (FB13753).
- **Partial Error Tolerance**: Channels with `InvalidFullScaleInput` or `InvalidInvertInput` are included in `CompleteChannels` and imported, but with `null` for the invalid field. This may cause downstream issues if the database or business logic does not handle `null` gracefully.
- **No Validation of Group Name Format**: Only existence and duplication are checked; no format validation (e.g., reserved characters, length limits) is implemented.
- **`Parse()` Escaping Logic**: Parentheses are treated as literal characters *only* when nested (via `leftParenCount`). A single `(` or `)` without matching pairs is still treated as a delimiter if not balanced.
- **`IsDirty` Never Set**: The `IsDirty` property is declared but never updated, so it always returns `false`.
- **`Initialize*` and `Cleanup*` Methods Are No-ops**: These likely exist to satisfy Prism interfaces but contain no logic.
- **`Channels` Property Triggers `InvalidateChannels()`**: Setting `Channels` raises property change notifications for `IncompleteChannels` and `CompleteChannels`, but these are computed properties—modifying `Channels` directly may not reflect changes in the UI if `Groups` is not updated.
- **Thread Safety**: `ImportFunc` runs on a background thread but updates UI properties directly (e.g., `ImportProgressValue`). While Prisms `INotifyPropertyChanged` may handle thread marshaling in some cases, this pattern is fragile and may cause cross-thread exceptions if the UI framework is strict.

View File

@@ -0,0 +1,108 @@
---
source_files:
- DataPRO/Modules/Groups/GroupList/GroupListModule.cs
generated_at: "2026-04-16T04:45:30.391660+00:00"
model: "Qwen/Qwen3-Coder-Next-FP8"
schema_version: 1
sha256: "eeab36663d49ff59"
---
# GroupList
### **1. Purpose**
The `GroupListModule` is a Prism-based modular component responsible for registering the view and view model for the group list UI functionality within the application. It integrates with the Unity dependency injection container to expose `IGroupListView` and `IGroupListViewModel` as singleton registrations, enabling the module to be discovered and loaded dynamically by the Prism modularity framework. Additionally, it defines assembly-level metadata attributes (`GroupListModuleNameAttribute` and `GroupListModuleImageAttribute`) that supply identifying information (name, image, group, and region) for UI presentation—specifically, to render the modules representation on the main screen under the *Prepare* group in the *GroupListRegion*.
---
### **2. Public Interface**
#### **Class: `GroupListModule`**
- **`GroupListModule(IUnityContainer unityContainer)`**
Constructor. Accepts a Unity container via dependency injection and stores it for later use in type registration.
- **`void Initialize()`**
Registers two interfaces with the Unity container as singleton mappings:
- `IGroupListView``GroupListView`
- `IGroupListViewModel``GroupListViewModel`
This method is called both directly during module initialization and indirectly via `RegisterTypes`.
- **`void OnInitialized(IContainerProvider containerProvider)`**
Currently empty; no logic implemented.
- **`void RegisterTypes(IContainerRegistry containerRegistry)`**
Delegates to `Initialize()` to perform the same type registrations. This is part of the Prism `IModule` lifecycle, though note it uses `IUnityContainer` internally rather than the `containerRegistry` parameter.
#### **Attribute: `GroupListModuleNameAttribute`**
- **`AssemblyName` (read-only `string`)**
Returns `"GroupList"` (via `AssemblyNames.GroupList.ToString()`).
- **`GetAttributeType()``Type`**
Returns `typeof(TextAttribute)`.
- **`GetAssemblyName()``string`**
Returns the value of `AssemblyName`.
#### **Attribute: `GroupListModuleImageAttribute`**
- **`AssemblyImage` (read-only `BitmapImage`)**
Loads and returns the image associated with the *GroupList* assembly via `AssemblyInfo.GetImage("GroupList")`.
- **`AssemblyName` (read-only `string`)**
Returns `"GroupList"`.
- **`AssemblyGroup` (read-only `string`)**
Returns `"Prepare"` (via `eAssemblyGroups.Prepare.ToString()`).
- **`AssemblyRegion` (read-only `eAssemblyRegion`)**
Returns `eAssemblyRegion.GroupListRegion`.
- **`GetAttributeType()``Type`**
Returns `typeof(ImageAttribute)`.
- **`GetAssemblyImage()``BitmapImage`**
Returns the value of `AssemblyImage`.
- **`GetAssemblyName()``string`**
Returns `"GroupList"`.
- **`GetAssemblyGroup()``string`**
Returns `"Prepare"`.
- **`GetAssemblyRegion()``eAssemblyRegion`**
Returns `eAssemblyRegion.GroupListRegion`.
---
### **3. Invariants**
- The module **must** be loaded *after* the Unity container is initialized and available for injection (as it depends on `IUnityContainer`).
- The `AssemblyNames.GroupList` enum value **must** resolve to `"GroupList"` for `AssemblyName` to be correct.
- The `eAssemblyGroups.Prepare` enum value **must** resolve to `"Prepare"` for `AssemblyGroup` to be correct.
- The `eAssemblyRegion.GroupListRegion` enum value **must** be defined and valid for `AssemblyRegion` to be correct.
- The `AssemblyInfo.GetImage(...)` call **must** succeed and return a non-null `BitmapImage`; otherwise, `AssemblyImage` may be null (no explicit null-checking is present).
- `Initialize()` is idempotent in practice (re-registering the same types is safe in Unity), but not explicitly guarded against duplicate registration.
---
### **4. Dependencies**
#### **Module Dependencies (Imports/Usings)**
- **`DTS.Common`** and **`DTS.Common.Interface`** — Provides core types like `AssemblyNames`, `eAssemblyGroups`, `eAssemblyRegion`, `AssemblyInfo`, and attribute base classes (`TextAttribute`, `ImageAttribute`).
- **`Prism.Modularity`** and **`Prism.Ioc`** — Required for implementing `IModule` and using Prisms module infrastructure.
- **`Unity`** — Specifically `IUnityContainer` and `IContainerRegistry`/`IContainerProvider` for DI.
- **`System.ComponentModel.Composition`** — Likely used for `[Export]` (though Unity is used for actual DI).
- **`System.Windows.Media.Imaging`** — For `BitmapImage` used in `AssemblyImage`.
#### **Module Consumers**
- The Prism bootstrapper/module catalog (e.g., `ModuleCatalog`) consumes this module via the `[Export(typeof(IModule))]` and `[Module(ModuleName = "GroupListModule")]` attributes.
- UI components (e.g., main shell) consume metadata from `GroupListModuleImageAttribute` to render the modules icon, name, group, and region.
- Other modules or services may depend on `IGroupListView` or `IGroupListViewModel` being registered in the container.
---
### **5. Gotchas**
- **`RegisterTypes` ignores its parameter**: The method receives `IContainerRegistry containerRegistry` but internally calls `Initialize()`, which uses the injected `_unityContainer` (of type `IUnityContainer`) instead. This may cause confusion or breakage if the container registry is expected to be used.
- **No error handling in image loading**: If `AssemblyInfo.GetImage("GroupList")` fails (e.g., missing image resource), `_img` may be `null`, and no fallback is provided.
- **Redundant attribute constructors**: Both attributes have a redundant `string s` constructor parameter that is unused (assigned but never read).
- **`OnInitialized` is empty**: Suggests incomplete implementation or legacy stub; no logic currently runs post-initialization.
- **No explicit validation of registration order**: If other modules depend on `IGroupListView`/`IGroupListViewModel`, they must ensure `GroupListModule` is loaded first.
- **Assembly-level attributes**: The attributes are applied at the assembly level (`[assembly: ...]`), meaning they are not tied to runtime module state—this is correct for metadata, but implies the image/name must be static and compile-time known.
- **None identified from source alone.** *(Note: The above are inferred from code structure and patterns, not documented quirks.)*

View File

@@ -0,0 +1,31 @@
---
source_files:
- DataPRO/Modules/Groups/GroupList/Model/ChannelSetting.cs
generated_at: "2026-04-16T04:47:17.887032+00:00"
model: "Qwen/Qwen3-Coder-Next-FP8"
schema_version: 1
sha256: "51a43b8567809d4b"
---
# Model
1. **Purpose**
This module file (`ChannelSetting.cs`) is a placeholder or stub within the `GroupList.Model` namespace and currently contains no implementation. As written, it serves no functional purpose in the system—it declares no types, properties, methods, or logic—and appears to be an incomplete or scaffolding file awaiting future development.
2. **Public Interface**
No public types, functions, classes, or methods are defined in this file. The namespace `GroupList.Model` and the file itself are empty aside from the `using` directive.
3. **Invariants**
No invariants can be determined, as no logic or state is present.
4. **Dependencies**
- **Imports**: The file imports `DTS.Common.Interface.Channels`, indicating a *potential* future dependency on channel-related abstractions defined in that namespace (e.g., interfaces like `IChannel`, `ChannelType`, etc.). However, no types from this namespace are currently used.
- **No internal dependencies**: No other modules, namespaces, or types within the codebase are referenced.
5. **Gotchas**
- **Empty file**: The file is functionally inert; any assumptions about its role (e.g., modeling channel settings for groups) are speculative.
- **Misleading namespace**: The `GroupList.Model` namespace suggests this file may eventually model channel-related configuration for groups, but no such contract exists yet.
- **No validation or safety guarantees**: Since no code exists, no correctness properties, thread-safety, or lifecycle rules apply.
- **Potential tech debt**: If this file was intended to be a model for channel settings but remains unimplemented, it may indicate pending work or incomplete refactoring.
None identified beyond what is evident from the empty structure.

View File

@@ -0,0 +1,65 @@
---
source_files:
- DataPRO/Modules/Groups/GroupList/Properties/Settings.Designer.cs
- DataPRO/Modules/Groups/GroupList/Properties/AssemblyInfo.cs
generated_at: "2026-04-16T04:47:23.586422+00:00"
model: "Qwen/Qwen3-Coder-Next-FP8"
schema_version: 1
sha256: "1fd4dfff93afcd30"
---
# Properties
## Documentation Page: `GroupList.Properties.Settings`
---
### 1. **Purpose**
This module defines the application settings class (`Settings`) for the `GroupList` module within the DataPRO system. It provides a strongly-typed, thread-safe accessor (`Default`) to application-level configuration values stored in the standard .NET configuration system (e.g., `app.config`). As a generated class, its purpose is to abstract access to user- or application-scoped settings, though **no settings properties are defined in the provided source**—they are presumably declared in the corresponding `.settings` file (not included here) and auto-generated into this class.
---
### 2. **Public Interface**
The following members are explicitly defined in the provided source:
- **`public static Settings Default { get; }`**
A static property returning the singleton instance of the `Settings` class. The instance is created via `ApplicationSettingsBase.Synchronized(...)`, ensuring thread-safe access to settings values.
- *Type*: `Settings` (a subclass of `System.Configuration.ApplicationSettingsBase`)
- *Behavior*: Returns the same instance on every call (singleton pattern). Values are loaded from configuration at first access.
> **Note**: No additional public properties, methods, or fields are visible in the provided source. Any settings (e.g., `string GroupFilter`, `int MaxGroups`) would be auto-generated by the Visual Studio Settings Designer and are *not present in this file*.
---
### 3. **Invariants**
- The `Settings` class is **sealed** and **partial**, with auto-generation metadata (`CompilerGeneratedAttribute`, `GeneratedCodeAttribute`).
- The `Default` instance is **synchronized** using `ApplicationSettingsBase.Synchronized(...)`, implying thread-safe reads/writes to settings values.
- The class inherits from `ApplicationSettingsBase`, so it adheres to standard .NET settings semantics:
- Settings are persisted per-user (user-scoped) and/or per-application (application-scoped), depending on their `UserScopedSetting` or `ApplicationScopedSetting` attributes (not visible here).
- No explicit validation or invariants are enforced in the provided code.
---
### 4. **Dependencies**
**Dependencies *of* this module**:
- `System.Configuration` (via `ApplicationSettingsBase`)
- `System.Runtime.CompilerServices` (for `CompilerGeneratedAttribute`)
- `System.CodeDom.Compiler` (for `GeneratedCodeAttribute`)
**Dependencies *on* this module**:
- Not inferable from this file alone. However, any consumer of `GroupList.Properties.Settings.Default` would depend on this module.
- The assembly `GroupList` (as per `AssemblyInfo.cs`) is the containing assembly for this class.
---
### 5. **Gotchas**
- **No settings are defined in this file** — the `Settings` class is empty *in the provided source*. Actual settings (e.g., `public string SomeSetting { get; set; }`) must be declared in the `.settings` designer file (e.g., `Settings.settings`) and regenerated into this class.
- **Do not manually edit this file** — the auto-generated header explicitly warns: *"Changes to this file may cause incorrect behavior and will be lost if the code is regenerated."*
- The `defaultInstance` is initialized synchronously via `Synchronized(...)`, but **no default values are set here** — defaults come from the `Settings.settings` designer or `app.config`.
- The assembly GUID (`95d3c318-8333-4d0b-b508-21d654404443`) and version (`1.0.0.0`) suggest this is an early or placeholder version; verify versioning strategy if upgrading or refactoring.
- **None identified from source alone** — beyond the above, behavior is standard for .NET `ApplicationSettingsBase` subclasses.
---
> **Recommendation for Developers**:
> To inspect or modify settings, open the `Settings.settings` file in Visual Studio (if present in the project). This will regenerate `Settings.Designer.cs`. Always verify the actual settings schema in the designer or `app.config` before relying on specific property names or values.

View File

@@ -0,0 +1,84 @@
---
source_files:
- DataPRO/Modules/Groups/GroupList/Resources/TranslateExtension.cs
- DataPRO/Modules/Groups/GroupList/Resources/StringResources.Designer.cs
generated_at: "2026-04-16T04:47:13.405699+00:00"
model: "Qwen/Qwen3-Coder-Next-FP8"
schema_version: 1
sha256: "30656f2a830a5a31"
---
# Resources
## Documentation: `TranslateExtension` Markup Extension
---
### 1. **Purpose**
This module provides a WPF `MarkupExtension` (`TranslateExtension`) to enable declarative, data-bound localization of UI strings directly in XAML. It allows developers to reference localized string resources by key (e.g., `{local:Translate Name}`) and automatically retrieve the appropriate localized value at runtime from the `StringResources` resource class. Its role is to bridge XAML markup with the applications resource management system, supporting multi-language UI without requiring code-behind or manual string lookups.
---
### 2. **Public Interface**
#### `TranslateExtension` class
- **Namespace**: `GroupList`
- **Base class**: `System.Windows.Markup.MarkupExtension`
- **Attributes**:
- `[MarkupExtensionReturnType(typeof(string))]` — Indicates the extension returns a `string`.
##### Constructor
- **`TranslateExtension(string key)`**
Initializes a new instance with the specified resource key. The key is stored in the private readonly field `_key`.
- *Parameter*: `key` — The string key used to look up a localized resource (e.g., `"Name"`, `"Description"`).
- *Behavior*: Validates `key` is non-null/non-empty at *runtime* during `ProvideValue` (not in constructor).
##### Overridden Method
- **`public override object ProvideValue(IServiceProvider serviceProvider)`**
Returns the localized string for `_key`, or a fallback value if the key is missing or lookup fails.
- *Behavior*:
- If `_key` is `null` or empty → returns `"#stringnotfound#"`.
- Otherwise, calls `StringResources.ResourceManager.GetString(_key)`.
- If the result is non-null → returns the localized string.
- If the result is `null` → returns `"#stringnotfound# " + _key` (e.g., `"#stringnotfound# MissingKey"`).
- *Note*: The `serviceProvider` parameter is unused in the implementation.
---
### 3. **Invariants**
- **Resource key must be a valid string resource name** (e.g., `"Name"`, `"Channels"`). Invalid keys (e.g., `"UnknownKey"`) will not throw but will return the fallback string `"#stringnotfound# UnknownKey"`.
- **Case sensitivity**: Resource keys are case-sensitive (e.g., `"name"``"Name"`).
- **No runtime exceptions** are thrown for missing keys; the extension gracefully degrades to the `NotFound` prefix.
- **Thread-safety**: Relies on `StringResources.ResourceManager`, which is thread-safe per .NET documentation (uses lazy initialization and locking internally).
- **XAML-only usage**: Intended for use in XAML markup only; not designed for programmatic invocation outside markup extension context.
---
### 4. **Dependencies**
#### Dependencies *on* this module:
- **WPF framework**: Requires `System.Windows.Markup` and `System.Windows` (for `MarkupExtension`).
- **`StringResources` class**:
- Defined in `GroupList.Resources` namespace.
- Auto-generated from `.resx` files (not shown here, but implied by `StringResources.Designer.cs`).
- Provides the underlying `ResourceManager` and strongly-typed properties (e.g., `StringResources.Name`).
- **No external third-party dependencies** beyond .NET Framework 4.0+ (per runtime version in `StringResources.Designer.cs`).
#### Dependencies *of* this module:
- None beyond standard WPF/.NET Framework types.
- **Consumers**: Any XAML file in the `GroupList` module (e.g., `GroupList/Resources/TranslateExtension.cs` is likely used in `*.xaml` files in the same module) to localize UI elements.
---
### 5. **Gotchas**
- **No compile-time safety for keys**: Using an incorrect key (e.g., `"Nam"` instead of `"Name"`) will not cause a compile error—only a runtime fallback string (`#stringnotfound# Nam`).
- **No culture switching support in extension itself**: While `StringResources.Culture` can be set globally (e.g., via `Thread.CurrentThread.CurrentUICulture`), the extension does not expose or manage culture selection.
- **Hardcoded fallback string**: The `"#stringnotfound#"` prefix is fixed and may be visible to end-users if keys are missing.
- **No validation of key format**: Keys like `""` (empty string) or `" "` (whitespace) are treated as invalid and return `NotFound`, but no explicit error logging occurs.
- **Auto-generated resource class**: `StringResources.Designer.cs` is auto-generated; manual edits will be overwritten. Resource keys must match entries in the corresponding `.resx` file (not visible here).
- **No support for parameterized strings**: The extension only supports simple key-based lookups (e.g., `"{local:Translate Name}"`). It cannot handle format strings like `"{0} is {1}"` (e.g., `String.Format`-style substitution).
None identified beyond the above.

View File

@@ -0,0 +1,71 @@
---
source_files:
- DataPRO/Modules/Groups/GroupList/View/GroupListView.xaml.cs
generated_at: "2026-04-16T04:47:32.695881+00:00"
model: "Qwen/Qwen3-Coder-Next-FP8"
schema_version: 1
sha256: "b80e86a41868129e"
---
# View
### **Purpose**
This module implements the WPF UI view (`GroupListView`) for displaying a list of groups in a tabular format using a `ListView` with `GridView`. It serves as the concrete implementation of the `IGroupListView` interface, bridging user interactions (sorting, filtering, double-clicking) with the corresponding `IGroupListViewModel` logic. Its role is to render group data and translate UI events into view model commands, adhering to the MVVM pattern.
---
### **Public Interface**
The class itself is public and implements `IGroupListView` (interface defined elsewhere), but no explicit public methods are declared in this file. All behavior is exposed via event handlers wired in XAML (not shown). The following private methods handle UI events:
- **`ListViewHeader_Click(object sender, RoutedEventArgs e)`**
Handles clicks on standard `GridViewColumnHeader` elements. Extracts the `Tag` (column identifier) and `DataContext` (view model), then invokes `viewModel.Sort(columnTag, true)` to sort ascending.
- **`GridViewColumnHeaderSearchable_OnSearch(object sender, RoutedEventArgs e)`**
Handles search input events on a custom `GridViewColumnHeaderSearchable` control. Extracts the `searchTerm` from `e.OriginalSource` and the `columnTag` from the senders `Tag`, then calls `vm.Filter(columnTag, searchTerm)`.
- **`GridViewColumnHeader_OnClick(object sender, RoutedEventArgs e)`**
Handles clicks on `GridViewColumnHeaderSearchable` controls (fallback to standard headers). Attempts to extract `columnTag` from the sender or via `Utils.FindChild`, then calls `vm?.Sort(columnTag, true)`.
- **`MouseDoubleClick(object sender, MouseButtonEventArgs e)`**
Handles double-clicks on the `ListView`. Determines the clicked item index using `GetCurrentIndex`, and if valid, invokes `vm.MouseDoubleClick(index)` on the view model.
- **`GetCurrentIndex(GetPositionDelegate getPosition, ListView lv)`** *(private static)*
Iterates over `ListView` items, checks if the mouse position (via delegate) is within the bounds of each `ListViewItem`, and returns the zero-based index of the first matching item, or `-1` if none.
- **`GetListViewItem(int index, ListView lv)`** *(private static)*
Retrieves the `ListViewItem` container for a given item index using `ItemContainerGenerator.ContainerFromIndex`.
- **`IsMouseOverTarget(Visual target, GetPositionDelegate getPosition)`** *(private static)*
Computes the visual bounds of a `Visual` and checks if the mouse position (from the delegate) lies within those bounds.
---
### **Invariants**
- The `DataContext` of `GroupListView` **must** be an instance implementing `IGroupListViewModel`; otherwise, casting in event handlers (`(IGroupListViewModel)DataContext`) will fail at runtime.
- Column identifiers (`Tag` properties on `GridViewColumnHeader` or `GridViewColumnHeaderSearchable`) **must** be non-null and consistent with expected keys used by `IGroupListViewModel.Sort` and `IGroupListViewModel.Filter`.
- The `ListView` must contain items compatible with the view models data source; `GetCurrentIndex` assumes `lv.Items.Count` is stable during iteration (no concurrent modifications).
- Double-click events only trigger `MouseDoubleClick` on the view model if the mouse is over a valid, generated `ListViewItem`.
---
### **Dependencies**
**Imports/References (from source):**
- `DTS.Common.Interface.Groups.GroupTemplateList` (namespace, likely contains `IGroupListView` and related interfaces)
- `DTS.Common.Interface.Groups.GroupList` (contains `IGroupListViewModel`)
- `DTS.Common.Controls` (contains `GridViewColumnHeaderSearchable`)
- `DTS.Common.Utils` (contains `Utils.FindChild<T>`)
- Standard WPF namespaces (`System.Windows.*`)
**Depended upon by:**
- XAML file `GroupListView.xaml` (not provided, but implied by `InitializeComponent()` and event bindings).
- Likely consumed by a DI container or view factory that resolves `IGroupListView` and sets its `DataContext` to an `IGroupListViewModel` implementation.
---
### **Gotchas**
- **Ambiguous event routing**: `ListViewHeader_Click` and `GridViewColumnHeader_OnClick` both handle header clicks but for different header types. If a `GridViewColumnHeaderSearchable` is clicked, `GridViewColumnHeader_OnClick` runs, but `ListViewHeader_Click` may also fire depending on XAML event wiring—risk of duplicate sorting/filtering if not coordinated.
- **Unsafe cast in `ListViewHeader_Click`**: Assumes `colHeader.DataContext` is `IGroupListViewModel`; if the view is reused or bound incorrectly, this throws `InvalidCastException`.
- **Fallback logic in `GridViewColumnHeader_OnClick`**: Uses `Utils.FindChild<GridViewColumnHeaderSearchable>` to extract `Tag` if the sender is not already a `GridViewColumnHeaderSearchable`. This implies tight coupling to a specific visual tree structure and may break if the control template changes.
- **Mouse position calculation**: `GetCurrentIndex` uses `VisualTreeHelper.GetDescendantBounds`, which may be expensive or inaccurate if items are virtualized (e.g., with `VirtualizingStackPanel`).
- **No null-safety for `vm`**: In `MouseDoubleClick`, `vm?.Sort(...)` uses null-conditional, but `vm.MouseDoubleClick(index)` does not—risk of `NullReferenceException` if `DataContext` is unset.
- **Search term source**: `GridViewColumnHeaderSearchable_OnSearch` casts `e.OriginalSource` to `string` for `searchTerm`, implying the event args `OriginalSource` *is* the search string—this is non-standard and highly dependent on how `GridViewColumnHeaderSearchable` raises the event.

View File

@@ -0,0 +1,149 @@
---
source_files:
- DataPRO/Modules/Groups/GroupList/ViewModel/GroupListViewModel.cs
generated_at: "2026-04-16T04:47:12.822358+00:00"
model: "Qwen/Qwen3-Coder-Next-FP8"
schema_version: 1
sha256: "efb48e4bf6e2c1c7"
---
# ViewModel
## Documentation: `GroupListViewModel`
---
### 1. Purpose
`GroupListViewModel` is the core view model for the Group List UI module. It manages the display, filtering, sorting, selection, and lifecycle of `IGroup` entities within the application. It acts as the intermediary between the `IGroupListView` view and the underlying group data model (`Group`), handling user interactions (e.g., double-click to edit, filtering/sorting), coordinating background operations (e.g., loading test setup lists), and publishing/subscribing to domain events via `IEventAggregator`. It supports both single- and multi-select group operations and integrates with the Prism region management and Unity DI container.
---
### 2. Public Interface
#### Constructors
- **`GroupListViewModel(IGroupListView view, IRegionManager regionManager, IEventAggregator eventAggregator, IUnityContainer unityContainer)`**
Initializes the view model. Sets up the view binding, event subscriptions (e.g., `RaiseNotification`, `BusyIndicatorChangeNotification`), and initializes `SelectedGroupItems` as an `ObservableCollection<IGroup>`.
#### Public Methods
- **`void ClearAllFilters()`**
Clears all per-field filter terms stored in `_filterByField`.
- **`void MouseDoubleClick(int index)`**
If a single group is selected and `index` is valid, publishes a `GroupListEditGroupEvent` with the selected groups `Id`.
- **`void Filter(string term)`**
Sets `CurrentSearchTerm` to `term`, then re-applies sorting (which triggers filtering and re-sorting of `Groups`).
- **`IGroup GetGroup(int? id, bool updateTags = true)`**
Returns the group with the given `id` (if `id >= 0`). If `updateTags` is `true`, updates the global tag cache before fetching. Returns a new empty `Group()` if not found.
- **`IGroup GetGroup(string displayName)`**
Returns the *non-embedded* group matching `displayName`, preferring non-embedded over embedded groups (for backward compatibility with pre-2.0 group types). Returns `null` if none found.
- **`IGroup[] GetGroups(int[] ids)`**
Returns an array of groups whose `Id`s are in `ids`, preserving order only in that groups *not* in `ids` are removed (i.e., order is not guaranteed to match `ids` order).
- **`IGroup[] GetAllGroups()`**
Returns *all* groups (via `Group.GetAllGroups()`), unfiltered and unsorted.
- **`void DeleteGroups(int[] ids)`**
Deletes groups with given `ids`. For each group, nullifies `StaticGroupId` on all related embedded groups, deletes the group, updates `AllGroups`, and re-applies filters. Publishes errors via `PageErrorEvent`.
- **`IGroup CreateGroup()`**
Returns a new unsaved `Group(true)` (likely a new transient instance).
- **`IGroup CreateGroup(SqlDataReader, List<string>, List<int>)`**
Constructs a `Group` from a data reader and hardware/test setup lists.
- **`IGroup CreateGroup(IGroupDbRecord, List<string>, List<int>)`**
Constructs a `Group` from a database record and hardware/test setup lists.
- **`IGroup CreateGroup(List<string>)`**
Constructs a new `Group` with the given `includedHardwareStringList`.
- **`void Filter(object tag, string term)`**
Parses `tag` as a `GroupFields` enum value; if successful, stores `term` in `_filterByField[tag]`, sets `_sortField`, and calls `Filter(term)`.
- **`void OnSetActive(object page, bool groupTile, object o)`**
Sets `Page`, filters `AllGroups` to groups compatible with the current users role/tags, and either calls `GetTestSetupListsAsync()` (if `groupTile == true`) or `Sort()`.
- **`private void GetTestSetupListsAsync()`**
Runs asynchronously: sets app status to busy, iterates over `AllGroups` in parallel to call `g.SetTestSetupLists()`, then re-sorts on the UI thread.
- **`void Unset()`**
Clears `AllGroups`, `Groups`, filters, and publishes `ListViewStatusEvent` with status `Unloaded`.
- **`void Sort(object o, bool bColumnClick)`**
Sorts `AllGroups` by `GroupFields` (parsed from `o`), applies `CurrentSearchTerm` and per-field filters (`GroupFilter`), and sets `Groups`. Updates sort direction on column click.
- **`void Cleanup()` / `Task CleanupAsync()` / `void Initialize()` / `Task InitializeAsync()` / `void Activated()`**
No-op stubs; likely required by Prism or custom interfaces but not implemented.
#### Public Properties
- **`IGroupListView View`** Bound view instance.
- **`InteractionRequest<Notification> NotificationRequest`** For displaying notification popups.
- **`InteractionRequest<Confirmation> ConfirmationRequest`** For confirmation dialogs.
- **`event PropertyChangedEventHandler PropertyChanged`** Implements `INotifyPropertyChanged`.
- **`ObservableCollection<IGroup> SelectedGroupItems`** Tracks selected groups; raises `GroupListGroupSelectedEvent` on change.
- **`IGroup[] Groups`** Currently displayed (filtered + sorted) groups.
- **`bool IsBusy`** Bound to busy indicator; updated via `OnBusyIndicatorNotification`.
- **`bool IsMenuIncluded` / `bool IsNavigationIncluded`** UI toggle flags.
- **`string ListViewId`** `"GroupListView"`; used for event scoping.
- **`int SelectedGroupIndex`** Index of selected group in `Groups`; default `-1`.
#### Private Properties (used in logic)
- **`_filterByField: Dictionary<GroupFields, string>`** Per-field filter terms.
- **`CurrentSearchTerm: string`** Global search term.
- **`_sortField: GroupFields`** Current sort field (default `LastModified`).
- **`_sortAscending: bool`** Sort direction (default `false` = descending).
- **`_comparer: GroupComparer`** Comparison logic for sorting.
---
### 3. Invariants
- `Groups` is always a filtered and sorted subset of `AllGroups`.
- `AllGroups` is always filtered by user role and tag compatibility (via `currentUser.TagCompatible(@group.TagIDs)`).
- `SelectedGroupItems` is an `ObservableCollection`; changes trigger `GroupListGroupSelectedEvent`.
- `_filterByField` stores per-field filter terms; `CurrentSearchTerm` is a global term applied in `Sort`.
- `Groups` is sorted by `_sortField` in `_sortAscending` order using `GroupComparer`.
- `IsBusy` is updated via `BusyIndicatorChangeNotification` event (thread-safe subscription on `PublisherThread`).
- `SelectedGroupItems.CollectionChanged` handler skips updates during flagged "updating" states (via `DTS.Common.Enums.SelectedItemsStatus.GetUpdating`).
---
### 4. Dependencies
#### Imports / Dependencies Used
- **Prism**: `IEventAggregator`, `IRegionManager`, `Unity`, `Prism.Events`, `Prism.Regions`, `Prism.Interactivity`.
- **DTS Common Libraries**:
- `DTS.Common.Events.*` (e.g., `RaiseNotification`, `BusyIndicatorChangeNotification`, `PageErrorEvent`, `AppStatusEvent`, `ProgressBarEvent`, `ListViewStatusEvent`, `GroupListEditGroupEvent`, `GroupListGroupSelectedEvent`)
- `DTS.Common.Interface.Groups.*` (`IGroup`, `IGroupListView`, `IGroupListViewModel`)
- `DTS.Common.Enums.Groups.GroupList.*` (`GroupFields`, `ListViewStatusArg`)
- `DTS.Common.Storage.*` (`DbOperations`)
- `DTS.Slice.Users.User`
- `DTS.Common.Classes.Tags.TagsInstance`
- **.NET**: `System.ComponentModel`, `System.Collections.ObjectModel`, `System.Threading.Tasks`, `System.Linq`, `System.Collections.Specialized`, `System.Windows`, `System.Data.SqlClient.SqlDataReader`.
#### Dependencies on This Module
- `GroupListViewModel` is exported via MEF (`[PartCreationPolicy(CreationPolicy.Shared)]`) and likely consumed by DI container resolution for `IGroupListViewModel`.
- `IGroupListView` must be provided at construction (likely via Prism view injection).
- Other modules subscribe to events it publishes: `GroupListEditGroupEvent`, `GroupListGroupSelectedEvent`, `PageErrorEvent`, `ListViewStatusEvent`.
---
### 5. Gotchas
- **Sorting logic comment**: The `Sort` method contains commented-out logic suggesting a potential bug or inconsistency in handling already-sorted lists (especially for `LastModified`). This may cause unexpected sort direction toggling.
- **`GetGroup(string displayName)` behavior**: Returns only non-embedded groups *if* any exist; otherwise returns `null`. This may hide embedded groups unexpectedly.
- **`GetGroups(int[] ids)` order**: Output order is not guaranteed to match input `ids` order (uses `Contains` in reverse iteration).
- **`SelectedGroupItems` setter**: Unsubscribes from `CollectionChanged` only if `_selectedGroupItems` was non-null *before* assignment. If `SelectedGroupItems` is set multiple times, old handlers may leak if not handled carefully.
- **`OnSetActive` filtering**: Filtering by user role/tag compatibility happens *only* in `OnSetActive`, not in `Filter` or `Sort`. Thus, filtering/sorting operates on already-filtered `AllGroups`.
- **`GetTestSetupListsAsync`**: Runs `SetTestSetupLists()` in parallel (`AsParallel().ForAll`), but UI thread re-sort is done via `Dispatcher.Invoke`. Potential for race conditions if `SetTestSetupLists()` modifies group state accessed during sort.
- **`GroupFilter` case sensitivity**: Uses `CompareOptions.OrdinalIgnoreCase` for all fields, including `LastModified` (stringified) — may yield unexpected matches (e.g., "12" matches "12" but also "12" in "12/12/2023").
- **No validation on `DeleteGroups`**: Does not check if groups are in use (e.g., by tests); relies on underlying `Group.Delete(id)` to handle errors (which are then published via `PageErrorEvent`).
- **`IsDirty` property**: Declared but never set; always `false`.
- **`Cleanup()`/`Initialize()` stubs**: All `Initialize*`, `Cleanup*`, and `Activated()` methods are empty — may indicate incomplete implementation or reliance on external lifecycle management.
None identified beyond those above.

View File

@@ -0,0 +1,102 @@
---
source_files:
- DataPRO/Modules/Hardware/AddEditHardware/AddEditHardwareModule.cs
generated_at: "2026-04-16T04:36:26.348285+00:00"
model: "Qwen/Qwen3-Coder-Next-FP8"
schema_version: 1
sha256: "05d78156d7f176cf"
---
# AddEditHardware
### 1. **Purpose**
The `AddEditHardwareModule` is a Prism-based modular component responsible for registering the view and view model for the hardware add/edit functionality within the applications UI. It integrates with the Unity dependency injection container to expose `IAddEditHardwareView` and `IAddEditHardwareViewModel` as singleton services, enabling consistent instantiation and composition via Prisms module loading infrastructure. Additionally, it defines assembly-level metadata attributes (`AddEditHardwareModuleNameAttribute` and `AddEditHardwareModuleImageAttribute`) that supply identifying information (name, image, group, region) for UI presentation—specifically for listing and rendering the module on the main screen.
---
### 2. **Public Interface**
#### **Class: `AddEditHardwareModule`**
- **`public AddEditHardwareModule(IUnityContainer unityContainer)`**
Constructor. Accepts and stores a Unity container reference via dependency injection for later type registration.
- **`public void Initialize()`**
Registers the view and view model types as singletons in the Unity container:
- `IAddEditHardwareView → AddEditHardwareView`
- `IAddEditHardwareViewModel → AddEditHardwareViewModel`
- **`public void OnInitialized(IContainerProvider containerProvider)`**
Empty implementation. No logic executed during Prisms `OnInitialized` phase.
- **`public void RegisterTypes(IContainerRegistry containerRegistry)`**
Delegates to `Initialize()` to perform type registration. (Note: Uses `IContainerRegistry` from Prism but internally invokes the legacy `Initialize()` method that operates on `IUnityContainer`.)
#### **Attribute: `AddEditHardwareModuleNameAttribute`**
- **Inherits from `TextAttribute`**
- **`public override string AssemblyName { get; }`**
Returns `"AddEditHardware"` (via `AssemblyNames.AddEditHardware.ToString()`).
- **`public override string GetAssemblyName()`**
Returns the same `AssemblyName` value.
- **`public override Type GetAttributeType()`**
Returns `typeof(TextAttribute)`.
#### **Attribute: `AddEditHardwareModuleImageAttribute`**
- **Inherits from `ImageAttribute`**
- **`public override BitmapImage AssemblyImage { get; }`**
Loads and returns a `BitmapImage` by calling `AssemblyInfo.GetImage("AddEditHardware")`.
- **`public override BitmapImage GetAssemblyImage()`**
Returns `AssemblyImage`.
- **`public override string AssemblyName { get; }`**
Returns `"AddEditHardware"`.
- **`public override string GetAssemblyName()`**
Returns `AssemblyName`.
- **`public override string AssemblyGroup { get; }`**
Returns `"Prepare"` (via `eAssemblyGroups.Prepare.ToString()`).
- **`public override string GetAssemblyGroup()`**
Returns `AssemblyGroup`.
- **`public override eAssemblyRegion AssemblyRegion { get; }`**
Returns `eAssemblyRegion.AddEditHardwareRegion`.
- **`public override eAssemblyRegion GetAssemblyRegion()`**
Returns `AssemblyRegion`.
- **`public override Type GetAttributeType()`**
Returns `typeof(ImageAttribute)`.
> **Note**: The attributes are applied at the assembly level via `[assembly: ...]` directives and are not tied to instance-based usage.
---
### 3. **Invariants**
- The module *must* be loaded by Prism after the Unity container is available (via `RegisterTypes`), and *before* views requiring `IAddEditHardwareView` or `IAddEditHardwareViewModel` are resolved.
- `AssemblyNames.AddEditHardware` and `eAssemblyGroups.Prepare` and `eAssemblyRegion.AddEditHardwareRegion` must be defined elsewhere (in `DTS.Common` or `DTS.Common.Interface`) and be non-null/valid at runtime for attribute initialization to succeed.
- `AssemblyInfo.GetImage(...)` must return a non-null `BitmapImage` for `"AddEditHardware"`; otherwise, `AssemblyImage` may be `null`.
- Type registrations in `Initialize()` are *idempotent* only if Unity allows re-registration of the same mapping (behavior depends on Unity configuration, but no explicit safeguards are present here).
- The `OnInitialized` method is intentionally empty; no side effects occur during Prisms `OnInitialized` phase.
---
### 4. **Dependencies**
#### **Module Dependencies**
- **`DTS.Common`** and **`DTS.Common.Interface`**
Provide core types: `AssemblyNames`, `eAssemblyGroups`, `eAssemblyRegion`, `AssemblyInfo`, `TextAttribute`, `ImageAttribute`, and the interfaces `IAddEditHardwareView`, `IAddEditHardwareViewModel`.
- **`Prism.Modularity`** and **`Prism.Ioc`**
Required for `IModule`, `IContainerRegistry`, and `IContainerProvider`.
- **`Unity`** (`Microsoft.Practices.Unity`)
Required for `IUnityContainer`.
- **`System.Windows.Media.Imaging`**
Used for `BitmapImage`.
#### **Dependents (Inferred)**
- The main shell/UI layer likely consumes `AddEditHardwareModuleImageAttribute` metadata to render module cards/tiles on the main screen.
- Other modules or views may depend on `IAddEditHardwareView` or `IAddEditHardwareViewModel` being registered and available via the container.
---
### 5. **Gotchas**
- **Redundant `Initialize()` call**: `RegisterTypes` calls `Initialize()`, but `Initialize()` uses `_unityContainer` directly instead of the `IContainerRegistry containerRegistry` parameter passed to `RegisterTypes`. This suggests legacy or transitional code (e.g., migration from Unity-specific `IUnityContainer` to Prisms `IContainerRegistry`), and may cause issues if `RegisterTypes` is invoked *before* `_unityContainer` is injected (though Prism guarantees `RegisterTypes` runs first).
- **No null-safety in attribute constructors**: `AssemblyInfo.GetImage(...)` is called in both the parameterless and string-constructor overloads of `AddEditHardwareModuleImageAttribute`. If `"AddEditHardware"` is not a valid image key, `_img` may be `null`, and `AssemblyImage` will return `null` silently.
- **Assembly-level attributes**: The attributes are applied at the assembly level and *not* tied to any runtime instance. Their properties are computed once at attribute instantiation time (i.e., during assembly load), not lazily.
- **Unused `string s` parameter**: Both attribute constructors accept a `string s` parameter that is ignored—likely a remnant of base class expectations.
- **No validation of view/viewmodel types**: `RegisterType` calls assume `AddEditHardwareView` and `AddEditHardwareViewModel` exist and implement `IAddEditHardwareView`/`IAddEditHardwareViewModel`. A mismatch would only surface at resolution time.
> **None identified from source alone** beyond the above—no obvious logic errors, but the design hints at technical debt in the `RegisterTypes`/`Initialize` interaction.

View File

@@ -0,0 +1,141 @@
---
source_files:
- DataPRO/Modules/Hardware/AddEditHardware/Model/DASModule.cs
generated_at: "2026-04-16T04:37:06.260294+00:00"
model: "Qwen/Qwen3-Coder-Next-FP8"
schema_version: 1
sha256: "05acdd30203849a0"
---
# Model
## Documentation: `DASModule.cs`
---
### 1. **Purpose**
The `DASModule` class models a hardware module in a Data Acquisition System (DAS) for use in a WPF-based UI for adding or editing hardware configurations. It encapsulates module-specific metadata—including type, bridge configuration (for SLICE modules), serial number, and associated visual representation—and exposes this data through a property-changed-aware model suitable for data binding. It serves as a view-model-like abstraction for hardware modules in the `AddEditHardware` workflow, implementing `IAddEditHardwareDASModule` and inheriting from `BasePropertyChanged` to support UI updates via `INotifyPropertyChanged`.
---
### 2. **Public Interface**
#### `public bool Disabled { get; set; } = false;`
- Indicates whether this module instance is disabled (e.g., not in use). Default is `false`.
#### `public SLICEBridgeTypes SLICEBridgeType { get; set; }`
- Gets or sets the bridge type for SLICE modules (e.g., `Bridge`, `IEPE`, `ARS`, `ACC`).
- **Behavior**: On change, triggers `SetProperty`, then calls `SetImage()` to update the image based on the new type.
#### `public HardwareTypes ModuleType { get; set; }`
- Gets or sets the high-level hardware type (e.g., `SLICE_Bridge`, `TOM`, `SIM`, `DIM`, `UNDEFINED`).
- **Behavior**: On change, triggers `SetProperty`, then calls `SetImage()`.
#### `public string SerialNumber { get; set; }`
- Gets or sets the modules serial number (empty string by default). No validation or prefix enforcement is performed in this property.
#### `public ImageSource DASImage { get; set; }`
- Gets or sets the `ImageSource` used to display the modules image in the UI.
- **Behavior**: Set via `SetImage()` based on `ModuleType` and (for `SLICE_Bridge`) `SLICEBridgeType`. May be `null` if image loading fails or no matching asset is found.
#### `public SLICEBridgeTypes[] AvailableNanoBridges { get; }`
- Returns a read-only array of valid `SLICEBridgeTypes` for *nano*-form-factor SLICE modules:
`SLICEBridgeTypes.Bridge`, `SLICEBridgeTypes.IEPE`.
#### `public SLICEBridgeTypes[] AvailableMicroBridges { get; }`
- Returns a read-only array of valid `SLICEBridgeTypes` for *micro*-form-factor SLICE modules:
`SLICEBridgeTypes.Bridge`, `SLICEBridgeTypes.IEPE`, `SLICEBridgeTypes.ARS`, `SLICEBridgeTypes.ACC`.
#### `public HardwareTypes[] AvailableRACKModules { get; }`
- Returns a read-only array of valid hardware types for rack-mounted modules:
`HardwareTypes.UNDEFINED`, `HardwareTypes.SIM`, `HardwareTypes.TOM`, `HardwareTypes.DIM`.
#### `public IAddEditHardwareHardware OwningHardware { get; set; }`
- Reference to the parent hardware object (e.g., chassis or device) that owns this module. Used for contextual navigation or validation.
#### `public string GetSerialNumberPrefix()`
- Returns a short string prefix used for generating or validating serial numbers based on module type:
- `"DIM"` for `HardwareTypes.DIM`
- `"SIM"` for `HardwareTypes.SIM`
- `"TOM"` for `HardwareTypes.TOM`
- For `HardwareTypes.SLICE_Bridge`, returns a 2-letter prefix based on `SLICEBridgeType`:
- `"AC"` for `ACC`
- `"AR"` for `ARS`
- `"BR"` for `Bridge`
- `"IEPE"` for `IEPE`
- Returns `string.Empty` for `UNDEFINED` or unrecognized types.
#### `public DASModule()`
- Default constructor. Initializes `Disabled = false`, `_sliceBridgeType = Bridge`, `_moduleType = UNDEFINED`.
---
### 3. **Invariants**
- **Image Consistency**: `DASImage` is always derived from `ModuleType` and (if applicable) `SLICEBridgeType`. Changing either triggers `SetImage()` and updates `DASImage`.
- **Image Source URI**: All image paths are relative to the pack URI `pack://application:,,,/ResourceFile.xaml`.
- **Image Loading Failure Handling**: If image loading fails (e.g., missing file), `DASImage` is set to `null`, and an error is logged via `APILogger`.
- **Image Freezing**: Loaded `BitmapImage` instances are frozen for thread-safety and performance.
- **Module Type Constraints**:
- `SLICEBridgeType` is only meaningful when `ModuleType == HardwareTypes.SLICE_Bridge`.
- `AvailableNanoBridges` and `AvailableMicroBridges` are static and immutable; they define allowed values but are not enforced by property setters.
- **Serial Number Prefix**:
- `GetSerialNumberPrefix()` returns `string.Empty` for unrecognized or `UNDEFINED` module types.
---
### 4. **Dependencies**
#### **Imports/Usings**
- `System`, `System.Windows`, `System.Windows.Input`, `System.Windows.Media`, `System.Windows.Media.Imaging`
- `DTS.Common.Base``BasePropertyChanged`
- `DTS.Common.Enums.Hardware``SLICEBridgeTypes`, `HardwareTypes`
- `DTS.Common.Interface.Hardware.AddEditHardware``IAddEditHardwareDASModule`, `IAddEditHardwareHardware`
- `DTS.Common.Utilities.Logging``APILogger`
#### **External Dependencies**
- **WPF**: Uses `ImageSource`, `BitmapImage`, `Uri`, `pack://` URIs.
- **Common Libraries**:
- `DTS.Common.Base` for `BasePropertyChanged` (likely implements `INotifyPropertyChanged`).
- `DTS.Common.Enums.Hardware` for type definitions.
- `DTS.Common.Interface.Hardware.AddEditHardware` for interface contracts.
- `DTS.Common.Utilities.Logging` for error logging.
#### **Consumers**
- UI components bound to `DASModule` (e.g., `DataGrid`, `UserControl`) for editing hardware configurations.
- Any class implementing or consuming `IAddEditHardwareDASModule`.
- Likely instantiated and managed by a parent `IAddEditHardwareHardware` (via `OwningHardware`).
---
### 5. **Gotchas**
- **No Validation on `ModuleType`/`SLICEBridgeType` Combinations**:
The class allows setting `ModuleType = SLICE_Bridge` and `SLICEBridgeType = ACC`, but also allows `ModuleType = TOM` with `SLICEBridgeType = IEPE`, which is semantically invalid. Validation (if any) must occur elsewhere (e.g., in UI or service layer).
- **`Disabled` Property Has No Side Effects**:
Setting `Disabled = true` does not affect image loading, serial number generation, or any other logic in this class.
- **Image Paths Are Hardcoded and Fragile**:
`SetImage()` uses hardcoded relative paths (e.g., `@"Assets/Hardware/SLICEIEPE_Side.png"`). If assets are renamed or moved, image loading silently fails (logs error, sets `DASImage = null`).
- **`GetSerialNumberPrefix()` Returns `"IEPE"` (4 chars) While Others Are 23 chars**:
Inconsistent prefix length may cause downstream parsing issues if consumers assume fixed-width prefixes.
- **No Null/Empty Handling for `SerialNumber`**:
The property accepts any string, including `null` or whitespace. No validation or trimming is applied.
- **`OwningHardware` Is Not Initialized**:
The property is nullable and must be set externally; no constructor overloads or defaults are provided.
- **`_baseUri` Is Static and Fixed**:
Assumes all images are in the same resource file (`ResourceFile.xaml`). Not configurable at runtime.
- **Exception Handling in `SetImage()` Is Broad**:
Catches all exceptions during image loading but logs only the message (no stack trace or context), making debugging harder.
- **No Explicit Interface Implementation**:
The class implements `IAddEditHardwareDASModule` implicitly; if the interface defines additional members, they are not visible in this file.
- **None identified from source alone.** *(Note: The above are inferred from observed behavior, not documented quirks.)*

View File

@@ -0,0 +1,60 @@
---
source_files:
- DataPRO/Modules/Hardware/AddEditHardware/Properties/Settings.Designer.cs
- DataPRO/Modules/Hardware/AddEditHardware/Properties/AssemblyInfo.cs
generated_at: "2026-04-16T04:36:44.098121+00:00"
model: "Qwen/Qwen3-Coder-Next-FP8"
schema_version: 1
sha256: "2868c6abccf6511a"
---
# Properties
## Documentation: `AddEditHardware.Properties.Settings`
---
### 1. **Purpose**
This module defines the strongly-typed application settings class `AddEditHardware.Properties.Settings`, which inherits from `System.Configuration.ApplicationSettingsBase`. It serves as the programmatic interface for accessing user- or application-scoped configuration values for the `AddEditHardware` module. The class is auto-generated by Visual Studios settings designer and provides a singleton-style static accessor (`Default`) for retrieving settings at runtime. It does not contain any custom settings properties in the provided source—only the infrastructure to host them.
---
### 2. **Public Interface**
- **`Settings Default`** *(static property)*
- **Signature**: `internal static Settings Default { get; }`
- **Behavior**: Returns the singleton instance of the `Settings` class, synchronized for thread safety via `ApplicationSettingsBase.Synchronized()`. This is the sole public member exposed in the current source. No custom settings properties are defined here—any actual settings (e.g., `HardwareId`, `LastUsedTemplate`) would appear in the designer-generated body but are absent in the provided snippet.
> **Note**: The class is `internal sealed partial`, and the `Settings` type itself is `internal`. No public constructors or instance members are present.
---
### 3. **Invariants**
- The `defaultInstance` field is initialized once and reused for all accesses to `Default`.
- Thread safety is ensured by wrapping the initial `Settings` instance with `ApplicationSettingsBase.Synchronized()`, which enforces that all access to the settings instance is synchronized on a shared lock.
- The class is sealed and non-extensible in this file (though `partial` allows extension in other generated files, not shown here).
- No validation or custom logic is present in the provided source—behavior relies entirely on `ApplicationSettingsBase`.
---
### 4. **Dependencies**
- **Depends on**:
- `System.Configuration` (specifically `ApplicationSettingsBase`)
- `System.Runtime.CompilerServices.CompilerGeneratedAttribute`
- `System.CodeDom.Compiler.GeneratedCodeAttribute`
- **Depended on by**:
- Other modules in the `AddEditHardware` assembly (e.g., UI forms or services in `DataPRO/Modules/Hardware/AddEditHardware`) that consume settings via `Settings.Default`.
- The Visual Studio Settings Designer (at design time), which regenerates this file when settings are modified in the `.settings` designer file (not included here).
---
### 5. **Gotchas**
- **Auto-generated file**: This file is auto-generated by Visual Studio. Manual edits will be overwritten on rebuild or settings modification.
- **No settings defined in source**: The provided snippet contains *only* the base infrastructure—no actual settings properties (e.g., `public string SomeSetting { get; set; }`) are visible. Developers must check the corresponding `.settings` designer file (e.g., `Properties/Settings.settings`) to see configured values.
- **Internal visibility**: The `Settings` class and its `Default` property are `internal`, meaning they are only accessible within the `AddEditHardware` assembly. External consumers (e.g., other modules) must reference this assembly and access it via `AddEditHardware.Properties.Settings.Default`.
- **Thread-safety overhead**: The use of `Synchronized()` implies a performance cost for every access; if settings are read frequently, consider caching locally.
- **Versioning**: Assembly version is fixed at `1.0.0.0` (both `AssemblyVersion` and `AssemblyFileVersion`), which may impact upgrade behavior for user-scoped settings (e.g., migration logic in `Settings.Default.Upgrade()`).

View File

@@ -0,0 +1,51 @@
---
source_files:
- DataPRO/Modules/Hardware/AddEditHardware/Resources/TranslateExtension.cs
- DataPRO/Modules/Hardware/AddEditHardware/Resources/StringResources.Designer.cs
generated_at: "2026-04-16T04:36:34.790176+00:00"
model: "Qwen/Qwen3-Coder-Next-FP8"
schema_version: 1
sha256: "df6887e304a35dc7"
---
# Resources
## Documentation: `TranslateExtension` Markup Extension
### 1. Purpose
This module provides a WPF `MarkupExtension` (`TranslateExtension`) that enables declarative localization of UI strings in XAML. It allows UI elements (e.g., `TextBlock.Text`, `Button.Content`) to bind to localized string resources defined in `StringResources` by specifying a resource key. Its role is to abstract away manual resource lookup and support runtime culture switching in the `AddEditHardware` modules UI.
### 2. Public Interface
- **`TranslateExtension(string key)`**
Constructor. Accepts a string `key` corresponding to a resource name in `StringResources`. Stores the key for later lookup.
- **`object ProvideValue(IServiceProvider serviceProvider)`**
Overrides `MarkupExtension.ProvideValue`. Performs resource lookup at XAML load time:
- Returns `"#stringnotfound#"` if `_key` is `null` or empty.
- Returns the localized string from `StringResources.ResourceManager.GetString(_key)` if found.
- Returns `"#stringnotfound# <key>"` (e.g., `"#stringnotfound# MyKey"`) if the key is non-empty but no matching resource exists.
### 3. Invariants
- `_key` is immutable after construction (no setter or mutation).
- The extension **always returns a `string`** (per `[MarkupExtensionReturnType(typeof(string))]`).
- Lookup is **case-sensitive** (relies on `ResourceManager.GetString(string)` behavior).
- If a resource key is missing, the fallback string explicitly includes the original key for debugging visibility.
### 4. Dependencies
- **Depends on**:
- `System.Windows.Markup` (for `MarkupExtension` base class).
- `AddEditHardware.Resources.StringResources` (strongly-typed resource class generated from `.resx`).
- `System.Resources.ResourceManager` (used internally via `StringResources.ResourceManager`).
- **Used by**:
- XAML files in the `AddEditHardware` module (e.g., `AddEditHardwareView.xaml`) to localize UI elements.
- No direct runtime dependencies beyond WPF framework and the `StringResources` assembly.
### 5. Gotchas
- **Static resource resolution**: `ProvideValue` is called **once at XAML load time**, not at runtime. Changing `StringResources.Culture` *after* XAML is parsed will **not** update already-bound UI elements.
- **Fallback format**: Missing keys yield `"#stringnotfound# <key>"`, which may appear in UI if keys are misspelled or missing from `.resx`. This is intentional for debugging but may confuse end users.
- **No null-safety for `serviceProvider`**: The implementation does not validate `serviceProvider`, though WPF typically provides a valid instance.
- **Hardcoded fallback**: The `"#stringnotfound#"` prefix is hardcoded and not configurable.
- **No async or caching optimization**: Each usage triggers a `ResourceManager.GetString()` call; no caching is applied within `TranslateExtension` (though `ResourceManager` itself caches resources internally).
- **Auto-generated resource class**: `StringResources` is auto-generated; manual edits will be overwritten. Resource keys must match exactly (case-sensitive) with entries in the `.resx` file.
None identified beyond the above.

View File

@@ -0,0 +1,109 @@
---
source_files:
- DataPRO/Modules/Hardware/AddEditHardware/View/AddEditHardwareView.xaml.cs
generated_at: "2026-04-16T04:35:38.785908+00:00"
model: "Qwen/Qwen3-Coder-Next-FP8"
schema_version: 1
sha256: "0ee538e93daa667b"
---
# View
## Documentation: `AddEditHardwareView` (WPF View for Hardware Configuration)
---
### **1. Purpose**
The `AddEditHardwareView` class is the WPF UI view layer for configuring and editing hardware devices in the system. It implements the `IAddEditHardwareView` interface and `INotifyPropertyChanged` to support data binding, and is responsible for rendering hardware type selection, module management (add/remove), and dynamic UI updates based on database version and view model state. It acts as the presentation layer for the `AddEditHardwareViewModel`, coordinating user interactions (e.g., button clicks, selection changes, text input) with the underlying data model via event handlers and property synchronization.
---
### **2. Public Interface**
#### **Properties**
- **`public bool AllowStandin { get; }`**
Determines whether the SLICE6TreeView UI element should be visible. Returns `true` if `DataContext` is null or not an `IAddEditHardwareViewModel`; otherwise, delegates to `vm.AllowStandin`.
- **`public int ViewDbVersion { get; set; }`**
Gets or sets the database version used to filter available hardware types. Setting this clears the cached hardware type list (`_allDASTypes`) and refreshes the `cbHardwareTypes.ItemsSource`.
#### **Methods**
- **`public void Activated()`**
Called when the view is activated. Triggers a property change notification for `AllowStandin`, and if `vm.SLICE6TreeView` is non-null, assigns it to `SLICE6TreeView.Content`.
#### **Event Handlers (Private, but part of public behavior via XAML wiring)**
- **`private void btnRemoveModule_Click(object sender, RoutedEventArgs e)`**
Removes the module associated with the clicked buttons `DataContext` from its owning hardware, then notifies the view model of modification.
- **`private void btnAdd_Click(object sender, RoutedEventArgs e)`**
Adds a new module to the hardware associated with the clicked buttons `DataContext`, then notifies the view model of modification.
- **`private void cb_SelectionChanged(object sender, SelectionChangedEventArgs e)`**,
**`private void cb_Checked(object sender, RoutedEventArgs e)`**,
**`private void cb_Unchecked(object sender, RoutedEventArgs e)`**,
**`private void tb_TextChanged(object sender, TextChangedEventArgs e)`**
All invoke `vm.NotifyModified()` to signal that the underlying data has changed.
#### **Protected/Helper Methods (Not public API, but part of implementation)**
- **`protected bool SetProperty<T>(ref T storage, T value, string propertyName = null)`**
Implements `INotifyPropertyChanged` semantics: updates `storage` only if value differs, raises `PropertyChanged`, and returns `true` if changed.
- **`protected void OnPropertyChanged(string propertyName = null)`**
Raises the `PropertyChanged` event.
---
### **3. Invariants**
- **Thread Safety for Hardware Type Caching**:
`_allDASTypes` is populated and cleared under a `lock` on the static list. `AvailableDASType()` and `PopulateDASTypes()` use this lock to ensure thread-safe initialization and version-based filtering.
- **Database Version Dependency**:
The list of available hardware types (`_allDASTypes`) is *dynamically filtered* based on `ViewDbVersion`. Specific hardware types (e.g., `SLICE6_AIR_BR`, `SLICE6_AIR_TC`, `SLICE_PRO_CAN_FD`) are only included if `ConnectionDbVersion` meets or exceeds their respective version constants (`Constants.SLICE6AIR_BR_DB_VERSION`, etc.).
- **View Model Contract**:
The view assumes `DataContext` is an `IAddEditHardwareViewModel` (or `AddEditHardwareViewModel` in handlers). If not, operations silently exit (e.g., `vm.NotifyModified()` is not called).
- **Module Ownership**:
Module removal (`btnRemoveModule_Click`) requires the `DataContext` of the clicked control to be an `IAddEditHardwareDASModule` with a valid `OwningHardware` reference.
---
### **4. Dependencies**
#### **Imports / Dependencies Used**
- **`DTS.Common`**: Core types, including `Constants`, `DbOperations`, `EnumDescriptionTypeConverter`.
- **`DTS.Common.Converters`**: `EnumDescriptionTypeConverter` used for sorting hardware types by description.
- **`DTS.Common.Enums.Hardware`**: `HardwareTypes`, `SLICEPROSIMConfigurations`, `SLICETCConfigurations`, `RackSizes`.
- **`DTS.Common.Interface.Hardware.AddEditHardware`**: `IAddEditHardwareView`, `IAddEditHardwareViewModel`, `IAddEditHardwareDASModule`, `IAddEditHardwareHardware`.
- **WPF Framework**: `System.Windows`, `System.Windows.Controls`, `System.ComponentModel`.
#### **Assumed Dependencies**
- **`AddEditHardwareViewModel`**: Concrete implementation of `IAddEditHardwareViewModel`, used in handlers (e.g., `vm.NotifyModified()`).
- **XAML file `AddEditHardwareView.xaml`**: Defines UI controls like `cbHardwareTypes`, `cbSliceProSimConfigurations`, `SLICE6TreeView`, etc., which are referenced in code-behind.
- **`Constants` class**: Must define `SLICE6AIR_BR_DB_VERSION`, `SLICE_TC_DB_VERSION`, `SLICE_PRO_CAN_FD_DB_VERSION`, and `MINIMUM_LTS_DB_VERSION`.
---
### **5. Gotchas**
- **Static State Mutation on Version Change**:
Setting `ViewDbVersion` clears `_allDASTypes` *globally*, affecting all instances of `AddEditHardwareView` in the app domain. This is a shared static cache—changing version for one view resets hardware type availability for others.
- **Silent Failures on Invalid Contexts**:
Event handlers (`btnRemoveModule_Click`, `btnAdd_Click`, `cb_*`, `tb_TextChanged`) exit early if `DataContext` is not the expected type or if `ctrlView.DataContext` is not `AddEditHardwareViewModel`. No error is logged or thrown—behavior is silently skipped.
- **`AllowStandin` Logic is Inverted in Edge Cases**:
Returns `true` (i.e., *show* the tree view) when `DataContext` is null or not an `IAddEditHardwareViewModel`. This may be counterintuitive—typically, missing view model would imply *hiding* UI elements.
- **Hardware Type Sorting Relies on Enum Descriptions**:
`_allDASTypes.Sort()` uses `EnumDescriptionTypeConverter.GetEnumDescription()` for ordering. If descriptions are missing, empty, or non-unique, sorting may be inconsistent or throw.
- **No Validation on `ViewDbVersion`**:
`ViewDbVersion` accepts any `int`. If set to a value below `MINIMUM_LTS_DB_VERSION`, behavior is undefined (though `_allDASTypes` is cleared and repopulated using the provided version).
- **Hardcoded Configuration Arrays**:
`_availableSliceProSimConfigurations`, `_availableSliceTCConfigurations`, and `_availableRackSizes` are static and unversioned—no dynamic filtering based on database version is applied to these.
None identified beyond the above.

View File

@@ -0,0 +1,147 @@
---
source_files:
- DataPRO/Modules/Hardware/AddEditHardware/ViewModel/AddEditHardwareViewModel.cs
generated_at: "2026-04-16T04:36:54.084304+00:00"
model: "Qwen/Qwen3-Coder-Next-FP8"
schema_version: 1
sha256: "eb93c7718734fde3"
---
# ViewModel
## Documentation: `AddEditHardwareViewModel`
---
### 1. **Purpose**
This module implements the `AddEditHardwareViewModel` class, which serves as the view model for the Add/Edit Hardware UI flow. It encapsulates the logic for displaying, editing, and saving hardware configuration data (e.g., DAS units, SLICE6 devices), including validation, state management, and integration with other system modules (e.g., SLICE6 tree view, event aggregation, region navigation). It supports two operational modes: *adding* new hardware and *editing* existing hardware, and enforces constraints such as disallowing *StandIn* hardware in contexts where it is not permitted (e.g., data recorders). It acts as the intermediary between the UI (`IAddEditHardwareView`) and the underlying domain model (`IAddEditHardwareHardware`, `IISOHardware`), coordinating persistence and inter-module communication via Prism events.
---
### 2. **Public Interface**
#### `AddEditHardwareViewModel(IAddEditHardwareView view, IRegionManager regionManager, IEventAggregator eventAggregator, IUnityContainer unityContainer)`
- **Behavior**: Primary constructor. Initializes the view, sets up event subscriptions (`RaiseNotification`, `BusyIndicatorChangeNotification`), and assigns dependencies. Assigns `this` as the views `DataContext`.
#### `AddEditHardwareViewModel()`
- **Behavior**: Parameterless constructor required for XAML binding (e.g., design-time or Unity resolution fallback). Does *not* initialize dependencies.
#### `void SetSLICE6TreeView(ISLICE6TreeView treeView, IHardwareListViewModel treeViewModel)`
- **Behavior**: Injects references to the SLICE6 tree view and its view model. Required for SLICE6-specific operations (e.g., saving associations, reloading tree). May be called after construction.
#### `void Activated()`
- **Behavior**: Called when the view is activated. Enforces that `StandIn` is disabled if `AllowStandin` is `false` and the hardware instance is non-null.
#### `void SetHardware(IDASHardware hw, IISOHardware isoHW)`
- **Behavior**: Initializes or resets the `Hardware` property. If `hw` is `null`, creates a new `Model.Hardware` instance; otherwise, constructs a new `Model.Hardware` from the provided `hw` and `isoHW`.
#### `IISOHardware GetISOHardware()`
- **Behavior**: Converts the internal `Hardware` to an `IISOHardware`. If `Hardware.StandIn` is `true` and `SerialNumber` is not a valid GUID, generates a new GUID, updates both `Hardware.SerialNumber` and `isoHW.SerialNumber`, sets `FirstUseDate` to `null`, `IsFirstUseValid` to `true`, and `CalDate` to `DateTime.Today`.
#### `bool Validate(IISOHardware isoHW, ref List<string> errors, ref List<string> warnings, bool displayWindow, bool IsAdd)`
- **Behavior**: Performs validation on `isoHW`. Checks:
- Serial number validity (`ValidateSerialNumber`)
- Uniqueness of serial number *only if* `IsAdd` is `true` (via `Model.Hardware.CheckUniqueSN`)
- IP address validity (`ValidateIPAddress`)
- Appends error/warning messages to `errors`/`warnings`. Calls `PublishPageError` if `displayWindow` is `true`. Returns `false` if any validation fails.
#### `void PublishPageError(bool displayWindow, List<string> errors, List<string> warnings)`
- **Behavior**: If `displayWindow` is `true` and either `errors` or `warnings` is non-empty, publishes a `PageErrorEvent` with combined messages.
#### `void SaveSLICE6Associations()`
- **Behavior**: If `Hardware.HardwareType` is `SLICE6DB`, `SLICE6DB3`, or `SLICE6DB_InDummy`, calls `SLICE6TreeViewModel.SaveSLICE6Associations(Hardware.SerialNumber)`.
#### `void Save()`
- **Behavior**: Persists the current `Hardware` via `Model.Hardware.Save(...)`, passing `TestId`, and `model.IsAdd`. Then:
- Calls `SaveSLICE6Associations()`
- Publishes a `HardwareSavedEvent` with `(DASId, SerialNumber)`
- Calls `SLICE6TreeViewModel.LoadTreeView(SerialNumber)` if `SLICE6TreeViewModel` is non-null.
#### `void NotifyModified()`
- **Behavior**: If `NotificationsOn` is `true`, publishes a `PageModifiedEvent` with status `Modified`.
#### `void Cleanup()`, `Task CleanupAsync()`, `void Initialize()`, `void Initialize(object)`, `void Initialize(object, object)`, `Task InitializeAsync()`, `Task InitializeAsync(object)`, `void Unset()`
- **Behavior**: No-op stubs. Present to satisfy interface contracts (e.g., `IInitialize`, `ICleanup`), but contain no logic.
#### `void OnPropertyChanged(string propertyName)`
- **Behavior**: Raises the `PropertyChanged` event for the specified property.
#### `event PropertyChangedEventHandler PropertyChanged`
- **Behavior**: Standard `INotifyPropertyChanged` implementation.
#### Properties:
- `bool AllowStandin { get; set; } = true`
Controls whether *StandIn* hardware is permitted. Defaults to `true`. Set externally (e.g., `false` for data recorders).
- `IAddEditHardwareView View { get; set; }`
Reference to the associated view.
- `IAddEditHardwareHardware Hardware { get; set; }`
The current hardware instance. Setting it triggers property change notifications for `Hardware`, `SerialNumber`, `FirmwareVersion`, `IPAddress`, and calls `SLICE6TreeViewModel.LoadTreeView(...)`.
- `int? TestId { get; set; }`
Optional test context ID, used during save.
- `bool NotificationsOn { get; set; } = false`
Enables/disables `PageModifiedEvent` publishing.
- `bool IsBusy { get; set; }`
Bound to busy indicator UI. Set via `OnBusyIndicatorNotification`.
- `bool IsMenuIncluded { get; set; }`, `bool IsNavigationIncluded { get; set; }`
UI layout flags; trigger `OnPropertyChanged` on change.
- `ISLICE6TreeView SLICE6TreeView { get; private set; }`, `IHardwareListViewModel SLICE6TreeViewModel { get; private set; }`
References injected via `SetSLICE6TreeView`. May be `null`.
- `InteractionRequest<Notification> NotificationRequest { get; }`, `InteractionRequest<Confirmation> ConfirmationRequest { get; }`
Prism interaction requests used to show popups (e.g., notifications, confirmations).
---
### 3. **Invariants**
- `Hardware` is never `null`; defaults to `new Model.Hardware()` if `SetHardware(null, ...)` is called.
- `Hardware.StandIn` is forced to `false` during `Activated()` if `AllowStandin` is `false` and `Hardware` is non-null.
- `Hardware.SerialNumber` may be overwritten (replaced with a new GUID) in `GetISOHardware()` if `StandIn` is `true` and the current `SerialNumber` is not a valid GUID.
- `Validate(...)` only enforces serial number uniqueness (`CheckUniqueSN`) when `IsAdd` is `true`.
- `IsBusy` is updated synchronously on the publisher thread via `OnBusyIndicatorNotification(bool)`.
- `SLICE6TreeViewModel` may be `null`; all calls to it are guarded with `?.`.
---
### 4. **Dependencies**
#### Imports / Dependencies:
- **Prism Framework**: `IEventAggregator`, `IRegionManager`, `Unity`, `Prism.Events`, `Prism.Interactivity`, `Prism.Regions`.
- **Common Libraries**:
- `DTS.Common.Events.*` (e.g., `RaiseNotification`, `PageModifiedEvent`, `PageErrorEvent`, `HardwareSavedEvent`)
- `DTS.Common.Interface.Hardware.AddEditHardware` (`IAddEditHardwareView`, `IAddEditHardwareHardware`)
- `DTS.Common.Interface.DataRecorders` (`IDASHardware`, `IISOHardware`)
- `DTS.Common.Interface.DASFactory.Diagnostics` (`ISLICE6TreeView`)
- `DTS.Common.Interface.DASFactory.Diagnostics.HardwareList` (`IHardwareListViewModel`)
- `DTS.Common.Utilities.Logging` (`APILogger`)
- `DTS.Common.Interactivity` (`InteractionRequest<...>`)
- `DTS.Common.Enums.Hardware.HardwareTypes` (used in `SaveSLICE6Associations`)
- **Model Layer**: `Model.Hardware` (internal namespace, used for persistence, conversion, validation, and uniqueness checks).
#### Consumed By:
- `IAddEditHardwareView` (XAML view) binds to this view model.
- Other modules (e.g., `HardwareListViewModel`) may call `SetSLICE6TreeView(...)` to wire SLICE6 tree integration.
- Event subscribers for `PageModifiedEvent`, `PageErrorEvent`, `HardwareSavedEvent`.
---
### 5. **Gotchas**
- **Dual constructors**: The parameterless constructor is required for XAML but leaves dependencies (`_eventAggregator`, `_regionManager`, etc.) uninitialized. Calling methods like `Activated()` or `SetHardware(...)` without prior injection may cause `NullReferenceException`.
- **`GetISOHardware()` mutates state**: If `StandIn` is `true` and `SerialNumber` is not a GUID, it *modifies* `Hardware.SerialNumber` and `isoHW.SerialNumber` in-place. This side effect is not obvious from the method name.
- **`Validate(...)` only checks uniqueness on *add***: `CheckUniqueSN` is skipped during edit (`IsAdd == false`), even if the serial number was changed.
- **`SLICE6TreeViewModel.LoadTreeView(...)` is called on `Hardware` setter**: This may trigger expensive tree reloads even when `Hardware` is set to the same instance (e.g., via property binding updates).
- **`NotificationsOn` defaults to `false`**: `NotifyModified()` does nothing unless explicitly enabled. This may lead to missed “page modified” signals if forgotten.
- **`OnRaiseNotification` strips title from `NotificationContentEventArgs`**: The original `eventArgsWithTitle.Title` is used as the popup title, but the message content is reconstructed with an empty string for the third parameter (likely legacy or for compatibility).
- **No-op lifecycle methods**: `Initialize`, `Cleanup`, etc., are present but empty. Developers may assume they do work; they do not.
- **`IsAdd` is not stored in the view model**: It is passed only to `Validate(...)` and `Save(...)`. If the view model is reused across multiple add/edit operations, `IsAdd` must be tracked externally (e.g., via `parameter` or `model.IsAdd`).
None identified beyond the above.

View File

@@ -0,0 +1,112 @@
---
source_files:
- DataPRO/Modules/Hardware/HardwareList/HardwareListModule.cs
generated_at: "2026-04-16T04:36:26.091510+00:00"
model: "Qwen/Qwen3-Coder-Next-FP8"
schema_version: 1
sha256: "253455657d30760d"
---
# HardwareList
## Documentation: HardwareListModule
---
### 1. Purpose
The `HardwareListModule` is a Prism-based modular component responsible for registering core views and view models related to hardware inventory management within the applications UI framework. It integrates with Unity as the dependency injection container to expose singleton instances of interfaces such as `IHardwareListView`, `ISLICE6TreeView`, and `IHardwareListViewModel`, enabling modular UI composition and decoupled view-model binding. The module also contributes metadata (name, image, group, region) to the host applications module discovery and presentation system via assembly-level attributes.
---
### 2. Public Interface
#### `HardwareListModule` class
- **Namespace**: `HardwareList`
- **Inherits**: `IModule` (Prism)
- **Constructor**:
```csharp
public HardwareListModule(IUnityContainer unityContainer)
```
Injects the Unity container for later type registration.
- **`Initialize()`**:
```csharp
public void Initialize()
```
Registers the following view and view model types as *transient* (note: despite the comment, Unitys `RegisterType<TInterface, TImplementation>()` defaults to transient unless `ContainerControlledLifetimeManager` is specified):
- `IHardwareListView` → `HardwareListView`
- `ISLICE6TreeView` → `SLICE6TreeView`
- `IHardwareListOverdueView` → `HardwareListOverdueView`
- `IHardwareListSelectView` → `HardwareListSelectView`
- `IHardwareListViewModel` → `HardwareListViewModel`
- `IHardwareListReplaceView` → `HardwareListReplaceView`
- **`OnInitialized(IContainerProvider containerProvider)`**:
```csharp
public void OnInitialized(IContainerProvider containerProvider)
```
Empty implementation; no post-initialization logic.
- **`RegisterTypes(IContainerRegistry containerRegistry)`**:
```csharp
public void RegisterTypes(IContainerRegistry containerRegistry)
```
Delegates to `Initialize()`, which uses the injected `IUnityContainer` (not `containerRegistry`). *Note: This is likely a bug or legacy pattern—`containerRegistry` is unused.*
#### Assembly-level attributes
- **`HardwareListModuleNameAttribute`**
- **Usage**: `[assembly: HardwareListModuleName]`
- **Purpose**: Exposes the modules assembly name (`AssemblyNames.HardwareList.ToString()`) for runtime identification.
- **Key properties**:
- `AssemblyName`: Returns `"HardwareList"` (via `AssemblyNames.HardwareList`).
- `GetAttributeType()`: Returns `typeof(TextAttribute)`.
- **`HardwareListModuleImageAttribute`**
- **Usage**: `[assembly: HardwareListModuleImageAttribute]`
- **Purpose**: Supplies UI metadata (image, group, region) for display on the main screens module summary.
- **Key properties**:
- `AssemblyImage`: Loads image via `AssemblyInfo.GetImage("HardwareList")`.
- `AssemblyGroup`: Returns `"Prepare"` (via `eAssemblyGroups.Prepare`).
- `AssemblyRegion`: Returns `eAssemblyRegion.HardwareListRegion`.
- `AssemblyName`: Returns `"HardwareList"`.
---
### 3. Invariants
- **Module registration order**: Views/view models are registered during `Initialize()`; no guarantees about registration order relative to other modules (depends on Prisms module loading sequence).
- **Lifetime management**: All registrations use Unitys default transient lifetime (despite the comment claiming "singleton"). No singleton behavior is enforced.
- **Attribute constraints**:
- `HardwareListModuleNameAttribute` and `HardwareListModuleImageAttribute` are assembly-level, non-repeatable (`AllowMultiple = false`).
- `AssemblyRegion` must be `eAssemblyRegion.HardwareListRegion`.
- `AssemblyGroup` must be `eAssemblyGroups.Prepare`.
---
### 4. Dependencies
#### Dependencies *of* this module:
- **Prism.Modularity**: For `IModule` interface.
- **Unity**: For `IUnityContainer` and `IContainerRegistry` (though `RegisterTypes` uses Unity, not the Prism container registry).
- **DTS.Common** and **DTS.Common.Interface**: Specifically:
- `AssemblyNames.HardwareList` (enum)
- `AssemblyInfo.GetImage()`
- `eAssemblyGroups` and `eAssemblyRegion` enums
- **System.Windows.Media.Imaging**: For `BitmapImage` in `HardwareListModuleImageAttribute`.
#### Dependencies *on* this module:
- Host application likely depends on `HardwareListModule` to resolve hardware-related views (e.g., `IHardwareListView`) via DI.
- Other modules may depend on interfaces like `ISLICE6TreeView` or `IHardwareListViewModel` for composition.
---
### 5. Gotchas
- **`RegisterTypes` ignores `containerRegistry`**: The `RegisterTypes` method calls `Initialize()`, which uses the pre-injected `_unityContainer`. This contradicts Prisms recommended pattern (where `RegisterTypes` should use `containerRegistry`) and may cause issues if the module is loaded in a Prism container that does not share Unitys container instance.
- **Misleading comment**: The `Initialize()` methods comment claims registrations are "singleton", but Unitys `RegisterType<TInterface, TImplementation>()` without a lifetime manager is transient.
- **Attribute duplication**: Both `HardwareListModuleNameAttribute` and `HardwareListModuleImageAttribute` define `AssemblyName` identically, but only `HardwareListModuleImageAttribute` provides UI-relevant metadata.
- **No error handling**: `AssemblyInfo.GetImage()` may fail (e.g., missing image resource), but no fallback or logging is present in the attributes.
- **Unused `OnInitialized`**: The `OnInitialized` method is empty and unused—potential dead code.
- **Namespace `HardwareList`**: The namespace matches the module name, which may cause confusion with the `HardwareList` folder path or other similarly named components.
None identified from source alone beyond the above.

View File

@@ -0,0 +1,105 @@
---
source_files:
- DataPRO/Modules/Hardware/HardwareList/Converters/FirstUseDateConverter.cs
- DataPRO/Modules/Hardware/HardwareList/Converters/StandInFieldConverter.cs
generated_at: "2026-04-16T04:37:34.782938+00:00"
model: "Qwen/Qwen3-Coder-Next-FP8"
schema_version: 1
sha256: "aee017cd34357419"
---
# Converters
## Documentation: `HardwareList.Converters` Module
---
### 1. **Purpose**
This module provides WPF value converters for formatting and conditional display of hardware-related properties in UI-bound data grids or forms. Specifically, `FirstUseDateConverter` and `StandInFieldConverter` translate raw model data into user-friendly string representations (e.g., `"N/A"`, `"---"`, or actual `DateTime` values), handling edge cases such as missing, invalid, or inapplicable data based on hardware state (e.g., `StandIn` flag). These converters enable consistent, declarative UI formatting without cluttering view models with presentation logic.
---
### 2. **Public Interface**
#### `FirstUseDateConverter`
*Namespace:* `HardwareList.Converters`
*Implements:* `IValueConverter`
- **`Convert(object value, Type targetType, object parameter, CultureInfo culture)`**
- **Behavior:**
- If `value` is not a `HardareList.Model.HardwareModel`, returns `Strings.Table_NA`.
- If `model.IsFirstUseValid` is `false`, returns `Strings.NotApplicable`.
- If `model.FirstUseDate` is non-null, returns `model.FirstUseDate` (as `DateTime?`).
- Otherwise, returns `Strings.Table_NA`.
- **Return type:** `object` (typically `string` or `DateTime?`).
- **`ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)`**
- **Behavior:**
- If `value` is a `DateTime`, returns it.
- Otherwise, returns `Strings.Table_NA`.
- **Note:** This is a minimal reverse converter; it does not validate or parse strings.
- **Return type:** `object`.
---
#### `StandInFieldConverter`
*Namespace:* `HardwareList.Converters`
*Implements:* `IValueConverter`
- **`Convert(object value, Type targetType, object parameter, CultureInfo culture)`**
- **Behavior:**
- If `value` is not a `HardareList.Model.HardwareModel`, returns `Strings.Table_NA`.
- If `model.Hardware` does not implement `IISOHardware`, returns `string.Empty`.
- If `isoHW.StandIn` is `true`, returns `Strings.Table_NA`.
- If `parameter` is a `string` matching `"CalDueDate"`, `"CalDate"`, or `"Firmware"`, returns the corresponding property (`model.CalDueDate`, `model.CalDate`, or `model.Firmware`).
- Otherwise, returns `Strings.Table_NA`.
- **Return type:** `object` (typically `string`, `DateTime?`, or `object` depending on the requested field).
- **`ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)`**
- **Behavior:**
- If `value` is a `DateTime`, returns it.
- Otherwise, returns `Strings.Table_NA`.
- **Return type:** `object`.
---
### 3. **Invariants**
- **Type Safety:** Both converters expect the input `value` to be a `HardareList.Model.HardwareModel`. Failure to meet this results in fallback to `Strings.Table_NA`.
- **Null Handling:**
- `FirstUseDateConverter` treats `null` `FirstUseDate` as `"---"` (`Strings.Table_NA`), distinct from `IsFirstUseValid == false` which yields `"N/A"` (`Strings.NotApplicable`).
- `StandInFieldConverter` short-circuits to `Strings.Table_NA` if `isoHW.StandIn` is `true`, regardless of the requested field.
- **Parameter Dependency (StandInFieldConverter only):**
- The converters output depends critically on the `parameter` being a `string` matching one of the three known keys (`"CalDueDate"`, `"CalDate"`, `"Firmware"`). Any other parameter yields `Strings.Table_NA`.
- **No Validation on ConvertBack:** Both converters perform no validation or parsing in `ConvertBack`; they only pass through `DateTime` values or return `Strings.Table_NA`.
---
### 4. **Dependencies**
- **Internal Dependencies (from source):**
- `HardareList.Model.HardwareModel` (note: likely typo in namespace `HardareList` vs. `HardwareList`).
- `DTS.Common.Strings` (provides `Strings.Table_NA`, `Strings.NotApplicable`).
- `DTS.Common.Interface.DASFactory.Diagnostics.IISOHardware` (used in `StandInFieldConverter`).
- `System.Windows.Data.IValueConverter` (WPF base interface).
- **External Dependencies:**
- WPF framework (for `IValueConverter` usage in XAML).
- `DTS.Common` assembly (contains `Strings` and `IISOHardware`).
- **Depended Upon By:**
- UI layers (XAML bindings) referencing these converters in `DataGrid` columns or `TextBlock` bindings for hardware properties.
- No direct code dependencies inferred—converters are consumed via XAML markup extension or resource references.
---
### 5. **Gotchas**
- **Typo in Namespace:** The model type is referenced as `HardareList.Model.HardwareModel` (missing 'w' in "Hardware"), which may cause runtime binding failures if the actual namespace is `HardwareList`.
- **Ambiguous `parameter` Usage:** `StandInFieldConverter` relies on string literals for field selection (`"CalDueDate"`, etc.). Typos or case mismatches in XAML parameter values will silently fall back to `Strings.Table_NA`.
- **Inconsistent `ConvertBack` Behavior:** Both converters return `Strings.Table_NA` for non-`DateTime` inputs in `ConvertBack`, which may be misleading if the UI expects a `null` or `DateTime?` result (e.g., for nullable fields like `CalDueDate`).
- **No Handling for Invalid `IISOHardware` Cast:** In `StandInFieldConverter`, if `model.Hardware` is non-null but not `IISOHardware`, the converter returns `string.Empty`—a subtle distinction from `Strings.Table_NA` (`"---"`), which could cause visual inconsistency.
- **Missing Documentation for `Strings` Values:** While `Strings.Table_NA` and `Strings.NotApplicable` are used, their exact string values (e.g., `"---"` vs `"N/A"`) are not visible in this source and must be verified in `DTS.Common.Strings`.
*None identified beyond the above.*

View File

@@ -0,0 +1,270 @@
---
source_files:
- DataPRO/Modules/Hardware/HardwareList/Model/HardwareChannelAssignment.cs
- DataPRO/Modules/Hardware/HardwareList/Model/SLICE6TreeNode.cs
- DataPRO/Modules/Hardware/HardwareList/Model/Hardware.cs
generated_at: "2026-04-16T04:38:28.250792+00:00"
model: "Qwen/Qwen3-Coder-Next-FP8"
schema_version: 1
sha256: "e010e06b613fee2c"
---
# HardwareList.Model Module Documentation
## 1. Purpose
This module provides data models and persistence logic for representing and managing hardware devices (DAS units) in the DataPRO diagnostics system. It defines core entities (`HardwareChannelAssignment`, `SLICE6TreeNode`, `HardwareModel`) that model hardware topology, channel assignments, and device metadata. The module enables querying device hierarchies (e.g., SLICE6DB parent-child relationships), persisting association changes to the database, and exposing hardware properties for UI binding (via `INotifyPropertyChanged`). It serves as the data layer for the Hardware List view, supporting configuration, sorting, filtering, and calibration tracking.
## 2. Public Interface
### `HardwareChannelAssignment`
- **`HardwareChannelAssignment(string channelNumber, string sensor, string name)`**
Constructor. Initializes immutable properties with provided values. Represents a mapping between a hardware channel, its connected sensor type, and a user-defined name.
- **`string ChannelNumber { get; }`**
Channel identifier (e.g., "CH1", "A0").
- **`string Sensor { get; }`**
Type of sensor connected to the channel.
- **`string Name { get; }`**
User-assigned name for the channel.
---
### `SLICE6TreeNode`
- **`SLICE6TreeNode(int dasId, string serialNumber, int port, int number, int positionOnChain)`**
Constructor. Initializes properties for a SLICE6 device node in a tree structure.
- **`int DASId { get; set; }`**
Primary key ID from the DAS database table.
- **`string SerialNumber { get; set; }`**
Device serial number.
- **`int Port { get; set; }`**
Physical port number on the S6DB (distributor) to which the device is connected.
- **`string PortString { get; }`**
Readable string representation of `Port`; returns `"---"` if `Port < 0`.
- **`int Number { get; set; }`**
Order of the device on the S6DB (i.e., its position index among siblings).
- **`int PositionOnChain { get; set; }`**
Position of the device within its daisy-chain on a given port.
- **`string PositionOnChainString { get; }`**
Readable string representation of `PositionOnChain`; returns `"---"` if `PositionOnChain < 0`.
- **`static ISLICE6TreeNode[] GetAvailableTreeNodes(string serialNumberParent)`**
Queries the database for all SLICE6 devices *not* associated with `serialNumberParent`. Returns an array of `ISLICE6TreeNode` instances sorted by `SerialNumber`. Returns empty array if `serialNumberParent` is null/empty.
- **`static ISLICE6TreeNode[] GetTreeNodes(string serialNumberParent)`**
Queries the database for all SLICE6 devices *associated* with `serialNumberParent`. Returns an array of `ISLICE6TreeNode` instances sorted by `Number` (i.e., `PositionOnDistributor`). Returns empty array if `serialNumberParent` is null/empty.
- **`static void SwapNodes(string serialNumberA, string serialNumberB)`**
Swaps all child devices between two SLICE6DB units (`serialNumberA` and `serialNumberB`) in the database. *Note: There is a bug in the implementation—both `listA` and `listB` are associated to `serialNumberB` in the second `Associate` call, not `serialNumberA` and `serialNumberB` respectively.*
- **`static void SaveAssociations(string serialNumber, ISLICE6TreeNode[] attachedSLICE6)`**
Commits the current association state of SLICE6 devices to a parent SLICE6DB (`serialNumber`). First clears all existing associations for `serialNumber`, then updates each device in `attachedSLICE6` with its new `ParentDAS`, `PositionOnDistributor`, `PositionOnChain`, and `Port`.
---
### `HardwareModel`
- **`HardwareModel(IISOHardware d, ...)`**
Constructor. Populates properties from an `IISOHardware` instance and calculates derived values (e.g., `CalDueDate`, `ChannelCount`). Requires calibration period parameters per hardware type.
- **`int DASId { get; set; }`**
Database ID of the device.
- **`bool Disabled { get; set; }`**
Whether the device is disabled.
- **`string SerialNumber { get; set; }`**
Device serial number.
- **`string HardwareType { get; set; }`**
Localized string description of the hardware type (e.g., `"SLICE6_BASE"`).
- **`string ChannelCount { get; set; }`**
Human-readable string listing channel types and counts (e.g., `"8 Analog, 2 Digital In"`).
- **`bool HasIncludedChildren { get; set; }`**
Indicates if this device has child devices marked as `Included`.
- **`string Firmware { get; set; }`**
Firmware version string.
- **`double? MaxSampleRate { get; set; }`**
Maximum supported sample rate (Hz); `null` if unknown or not applicable.
- **`double TestSampleRate { get; set; }`**
Current test/sample rate selected for the device.
- **`double TestAAFilterRateHz { get; set; }`**
Anti-aliasing filter rate (Hz) corresponding to `TestSampleRate`.
- **`DateTime? CalDate { get; set; }`**
Last calibration date.
- **`DateTime? CalDueDate { get; set; }`**
Calculated calibration due date based on `CalDate` and hardware-specific period.
- **`string[] AvailableSampleRates { get; set; }`**
Array of available sample rate strings (e.g., `["1000", "2000"]`).
- **`string SelectedSampleRateItem { get; set; }`**
Currently selected sample rate string.
- **`int SelectedSampleRateIndex { get; set; }`**
Index of the current sample rate in `_availableSampleRates`. Setter updates `TestSampleRate` and `TestAAFilterRateHz`.
- **`object Hardware { get; set; }`**
Backing `IISOHardware` instance.
- **`int AnalogChannels { get; set; }`**
Number of analog input channels.
- **`int SquibChannels { get; set; }`**
Number of squib (explosive device) channels.
- **`int DigitalInChannels { get; set; }`**, **`int DigitalOutChannels { get; set; }`**, **`int UartChannels { get; set; }`**, **`int StreamOutChannels { get; set; }`**, **`int StreamInChannels { get; set; }`**, **`int CanChannels { get; set; }`**
Channel counts for respective interface types.
- **`string IPAddress { get; set; }`**
IP address or `"USB"` if connected via USB.
- **`bool Included { get; set; }`**
Whether the device is included in the current configuration.
- **`double DSPStreamingFilter { get; set; }`**
DSP streaming filter value.
- **`DTS.Common.ClockSyncProfile MasterProfile { get; set; }`**, **`DTS.Common.ClockSyncProfile SlaveProfile { get; set; }`**
Clock synchronization profiles (master/slave).
- **`bool IsClockMaster { get; set; }`**
Whether the device is configured as a clock master. Only valid if `IsClockedDAS` is true.
- **`bool IsClockedDAS { get; }`**
Returns `true` if the device type supports clocking (e.g., SLICE6, S6A_EthernetRecorder, TSR_AIR).
- **`byte PTPDomainID { get; set; }`**
PTP domain ID for precision time protocol.
- **`bool IsPTPSync { get; }`**
Returns `true` if PTP synchronization is active (E2E profile in use).
- **`bool MixedRates { get; set; }`**
Whether the device is part of a mixed-sample-rate configuration.
- **`bool IsDistributor { get; }`**
Returns `true` if the device is a distributor (e.g., SLICE6DB, SLICE_Distributor).
- **`bool IsBattery { get; }`**
Returns `true` if the device is a PowerPro.
- **`bool IsTSRAIR { get; }`**
Returns `true` if the device is a TSR_AIR or embedded sensor type.
- **`bool IncludedAndNotMixedRatesAndCompactOrNotDistributor { get; }`**, **`bool IncludedAndMixedRatesAndCompact { get; }`**
Derived UI flags for conditional rendering.
- **`string ParentDAS { get; set; }`**
Serial number of the parent device (distributor).
- **`int PositionOnChain { get; set; }`**, **`int PositionOnDistributor { get; set; }`**, **`int Port { get; set; }`**
Position metadata for hierarchical placement.
- **`bool HasTreeView { get; set; }`**
Indicates if a tree view should be shown for this device (e.g., for SLICE6DB).
- **`string SerialNumberDisplay { get; }`**
Display name: `SerialNumber` unless `StandIn` is true, in which case it returns the hardware type description.
- **`static IHardware[] GetAvailableSLICE6DB(string serialNumber)`**
Returns all SLICE6DB devices (including `SLICE6DB_InDummy`) not currently assigned to any parent, excluding `serialNumber`.
- **`void DetermineChannelCount(bool showCompact, IHardware[] allHardware)`**
Updates `ChannelCount` and `MaxSampleRate` based on device type and child devices. For distributors, calculates min sample rate among children if `showCompact` is true.
- **`void SetIncluded(bool bIncluded)`**, **`void SetMixedRates(bool mixedRates)`**
Updates state and fires property change notifications.
- **`bool Filter(string term)`**
Returns `true` if `SerialNumber`, `Firmware`, or `HardwareType` contains `term` (case-insensitive).
- **`class HardwareComparer : IComparer<IHardware>`**
Implements sorting for `IHardware` objects. Supports sorting by `HardwareListTags` (e.g., `SerialNumber`, `CalDate`, `FirstUseDate`). Handles nulls and `double?/DateTime?` comparisons. `FirstUseDate` sorts nulls last when valid.
---
## 3. Invariants
- **`SLICE6TreeNode`**
- `Port`, `Number`, and `PositionOnChain` must be non-negative integers for valid hardware placements. Negative values are represented as `"---"` in UI via `PortString`/`PositionOnChainString`.
- `GetAvailableTreeNodes` and `GetTreeNodes` only query devices with `Type = SLICE6_Base` and `Position ≠ 'Prototype'` (for `GetAvailableTreeNodes`).
- `SwapNodes` assumes all child devices of both parents are retrieved in one query and re-associated. *Bug: Both lists are associated to `serialNumberB`.*
- **`HardwareModel`**
- `CalDueDate` is derived from `CalDate` (or `FirstUseDate` if `IsFirstUseValid`) plus a hardware-specific calibration period.
- `MaxSampleRate` is `null` if `d.MaxSampleRate` is `<= 0` or `uint.MaxValue`.
- `IsClockedDAS` is determined by a fixed set of `HardwareTypes`.
- `Included` and `MixedRates` flags affect derived properties (`IncludedAndNotMixedRatesAndCompactOrNotDistributor`, `IncludedAndMixedRatesAndCompact`).
- `ChannelCount` for distributors is `"N/A"` if `showCompact` is false or no children exist.
- **General**
- All database operations use `DTS.Common.Storage.DbOperations.GetSQLCommand()` and explicitly dispose connections in `finally` blocks.
- `HardwareModel` instances are constructed with a non-null `HardwareListViewModel` (`_vm`) reference for event callbacks.
## 4. Dependencies
### Dependencies *of* this module:
- **`DTS.Common.*`**
- `DTS.Common.Base.BasePropertyChanged` (base class for `SLICE6TreeNode`)
- `DTS.Common.Storage.DbOperations` (database access)
- `DTS.Common.Enums.Hardware.HardwareTypes` (device type enumeration)
- `DTS.Common.Interface.DASFactory.Diagnostics.IISOHardware`, `IHardware` (hardware abstraction interfaces)
- `DTS.Common.Converters.EnumDescriptionTypeConverter` (localized enum descriptions)
- `DTS.Common.ClockSyncProfile` (clock sync profiles)
- **`HardwareList.Resources.StringResources`**
- Used for localized strings (e.g., `"Analog"`, `"USB"`, `"N/A"`).
### Dependencies *on* this module:
- **`HardwareList.HardwareListViewModel`**
- Passed into `HardwareModel` constructor; used for event callbacks (`FireSampleRate`, `FireClockMaster`, etc.).
- **UI Layer**
- `HardwareModel` properties (e.g., `Included`, `CalDueDate`, `ChannelCount`) are bound to views.
- `SLICE6TreeNode` is used to populate tree views for SLICE6DB hierarchies.
- **HardwareList Module**
- `HardwareList.Model` is the core data model for the `HardwareList` module.
## 5. Gotchas
- **`SLICE6TreeNode.SwapNodes` Bug**:
The `Associate` method is called twice—once for `listA` with `serialNumberB`, and again for `listB` *also* with `serialNumberB`. This means devices originally under `serialNumberB` are incorrectly moved to `serialNumberB` (no-op), and devices under `serialNumberA` are moved to `serialNumberB`, but the reverse move does not occur. The intended behavior is likely `Associate(serialNumberB, listA)` and `Associate(serialNumberA, listB)`.
- **`HardwareModel.CalDueDate` Calculation**:
Uses `FirstUseDate` only if `IsFirstUseValid` is true. If `FirstUseDate` is `null` and `IsFirstUseValid` is true, it defaults to `DateTime.Today`. This may cause unexpected recalculations if `FirstUseDate` is set later.
- **`HardwareModel.TestSampleRate` Setter Side Effect**:
Setting `TestSampleRate` triggers `OnPropertyChanged("SelectedSampleRateIndex")`, but the getter for `SelectedSampleRateIndex` re-computes `SelectedSampleRateItem` and calls `_vm.FireSampleRate`. This could cause redundant UI updates if `TestSampleRate` is set multiple times.
- **`HardwareModel.DetermineChannelCount` for Distributors**:
`MaxSampleRate` is recalculated as the *minimum* sample rate of child devices. If children have no sample rate (`null`), `ChannelCount` becomes `"N/A"` and `MaxSampleRate` is set to `null`. This may mask missing configuration.
- **`HardwareModel.Filter` Case Sensitivity**:
Filtering is case-insensitive (`term.ToLower()`), but `SerialNumberDisplay` uses `isoHW.StandIn` logic, which may cause display mismatches if `StandIn` is toggled dynamically.
- **`HardwareModel.Hardware` is `object`**:
The `Hardware` property is typed as `object`, requiring casting to `IISOHardware` for type-specific checks (e.g., `IsClockedDAS`, `IsDistributor`). This risks runtime errors if the underlying type is not `IISOHardware`.
- **`SLICE6TreeNode` SQL Injection Risk**:
`GetAvailableTreeNodes` uses string interpolation for `HardwareTypes.SLICE6_Base` in the `WHERE` clause (`[(int)HardwareTypes.SLICE6_Base]`). While the enum value is fixed, this pattern is fragile and error-prone.
- **`HardwareModel` Constructor Side Effects**:
The constructor calls `d.GetChannelsString(...)` and computes `CalDueDate` based on `d.DASTypeEnum`. If `Hardware` is `null` or `DASTypeEnum` is invalid, it throws `ArgumentOutOfRangeException`.
- **`HardwareComparer.NumericCompare` Logic**:
For `double`/`DateTime`, `a > b` returns `-1` (descending order), but the method returns `1` for all other cases. This may cause inconsistent sorting if types are mixed (e.g., `double` vs `DateTime`).

View File

@@ -0,0 +1,50 @@
---
source_files:
- DataPRO/Modules/Hardware/HardwareList/Properties/Settings.Designer.cs
- DataPRO/Modules/Hardware/HardwareList/Properties/AssemblyInfo.cs
generated_at: "2026-04-16T04:37:43.934636+00:00"
model: "Qwen/Qwen3-Coder-Next-FP8"
schema_version: 1
sha256: "5208913b7b0145de"
---
# Properties
## Documentation Page: HardwareList.Properties.Settings
### 1. Purpose
This module defines the application settings infrastructure for the `HardwareList` module within the DataPRO system. Specifically, it provides a strongly-typed, thread-safe singleton accessor (`Settings.Default`) for reading application-level configuration values stored in the standard .NET configuration system (e.g., `app.config` or `user.config`). It serves as the runtime interface to persisted settings but contains no user-defined settings properties itself—only the infrastructure class required to expose them.
### 2. Public Interface
The module exposes a single internal sealed class with the following public members:
- **`Settings.Default` (static property)**
- **Type**: `HardwareList.Properties.Settings`
- **Signature**: `public static Settings Default { get; }`
- **Behavior**: Returns the singleton instance of the `Settings` class. The instance is created via `ApplicationSettingsBase.Synchronized(...)`, ensuring thread-safe access to settings values. This is the *only* public entry point to the settings system in this file.
> **Note**: No user-defined settings properties (e.g., `string SomeSetting { get; set; }`) are declared in this file. Their absence indicates that either:
> - Settings are defined elsewhere (e.g., in `Settings.settings` designer file or `app.config`), or
> - This module is intentionally minimal and relies on external configuration sources.
### 3. Invariants
- The `defaultInstance` is lazily initialized on first access to `Settings.Default` and remains constant thereafter.
- Thread safety is guaranteed via `ApplicationSettingsBase.Synchronized(...)`, which wraps the instance in a `SyncRoot`-based synchronization mechanism.
- The class is `sealed` and `internal`, preventing external inheritance or instantiation.
- No validation or transformation logic is present in this file; settings values are assumed to be validated/typed by the underlying .NET configuration system at runtime.
### 4. Dependencies
- **Depends on**:
- `System.Configuration` (specifically `System.Configuration.ApplicationSettingsBase`)
- `System.Runtime.CompilerServices.CompilerGeneratedAttribute`
- `System.CodeDom.Compiler.GeneratedCodeAttribute`
- **Depended on by**:
- Other modules in the `HardwareList` assembly (e.g., code that reads settings via `Settings.Default.SomeProperty`, though *no such usage is visible in the provided source*).
- The .NET configuration system at runtime (via `app.config`/`user.config`), which must contain matching `<setting>` entries for any properties defined in `Settings.settings`.
### 5. Gotchas
- **Auto-generated file**: This file is auto-generated by the Visual Studio Settings Designer (`SettingsSingleFileGenerator`). Manual edits will be overwritten on regeneration.
- **No settings defined here**: Despite the class name `Settings`, this file contains *no property declarations*. Any settings used at runtime must be defined in the corresponding `Settings.settings` file (not provided) or in `app.config`.
- **Thread-safety caveat**: While `Synchronized()` ensures thread-safe *access*, it does *not* guarantee atomicity for compound operations (e.g., read-modify-write).
- **Versioning ambiguity**: Assembly version is fixed at `1.0.0.0` (with `AssemblyFileVersion` identical), which may complicate deployment or rollback if settings schema evolves.
- **COM visibility disabled**: `ComVisible(false)` means this module is not exposed to COM clients—intentional for a .NET-only module.

View File

@@ -0,0 +1,92 @@
---
source_files:
- DataPRO/Modules/Hardware/HardwareList/Resources/TranslateExtension.cs
- DataPRO/Modules/Hardware/HardwareList/Resources/StringResources.Designer.cs
generated_at: "2026-04-16T04:37:17.643250+00:00"
model: "Qwen/Qwen3-Coder-Next-FP8"
schema_version: 1
sha256: "41df486c1d53cd9a"
---
# Resources
## Documentation: `TranslateExtension` Markup Extension
---
### 1. Purpose
The `TranslateExtension` class is a WPF `MarkupExtension` used to enable localized string binding in XAML. It resolves a given string key at runtime by querying the `StringResources` strongly-typed resource class (which wraps the applications `.resx`-based resources), returning the corresponding localized value. If the key is missing or empty, it returns a consistent fallback string (`#stringnotfound#` or `#stringnotfound# <key>`), allowing UI elements to gracefully handle missing translations. This extension is essential for internationalization of the HardwareList modules UI.
---
### 2. Public Interface
#### `TranslateExtension` class
- **Namespace**: `HardwareList`
- **Base Type**: `System.Windows.Markup.MarkupExtension`
##### Constructor
```csharp
public TranslateExtension(string key)
```
- **Parameters**:
- `key` (`string`): The resource key used to look up a localized string in `StringResources`.
- **Behavior**: Stores the key for later resolution during `ProvideValue`.
##### Override
```csharp
public override object ProvideValue(IServiceProvider serviceProvider)
```
- **Parameters**:
- `serviceProvider` (`IServiceProvider`): WPF service provider (unused in current implementation).
- **Returns**:
- `string`: The localized string corresponding to `_key`, or a fallback string if the key is null/empty or not found.
- **Behavior**:
- If `_key` is `null` or empty → returns `"#stringnotfound#"`.
- Otherwise, calls `StringResources.ResourceManager.GetString(_key)`.
- If a matching resource exists → returns the string value.
- If no match → returns `"#stringnotfound# " + _key`.
> **Note**: The `MarkupExtensionReturnType` attribute indicates the extension always returns a `string`.
---
### 3. Invariants
- `_key` is immutable after construction (no setter or mutation).
- `StringResources.ResourceManager.GetString(key)` is assumed to be thread-safe (as per .NET `ResourceManager` behavior).
- The fallback string `#stringnotfound#` is **hardcoded** and must not be localized itself.
- Empty or null keys are treated identically and return the base fallback string (no key suffix).
- If a key exists in `StringResources.Designer.cs` but the underlying `.resx` file lacks the entry, `GetString` returns `null`, triggering the fallback.
---
### 4. Dependencies
#### Dependencies *on* this module:
- **WPF Framework**: Requires `System.Windows.Markup` and `System` (for `ResourceManager`, `IServiceProvider`).
- **`HardwareList.Resources.StringResources`**: This module depends on the auto-generated `StringResources` class for resource lookup.
- **XAML Parser**: Used via `MarkupExtension` mechanism in XAML (e.g., `{local:Translate KeyName}`).
#### Dependencies *of* this module:
- None beyond standard .NET libraries (`System`, `System.Windows`).
- `StringResources` is generated from `.resx` files (not visible here), but the module assumes its existence and structure.
---
### 5. Gotchas
- **No caching of resolved values**: Each `ProvideValue` call re-queries `ResourceManager.GetString`, which is acceptable but could be optimized if performance becomes critical.
- **Fallback format is not user-friendly**: The fallback `"#stringnotfound# <key>"` may appear in the UI if keys are missing—ensure translators or developers catch these during testing.
- **Case sensitivity**: Resource keys are case-sensitive (e.g., `"Add"``"add"`). A mismatch yields the fallback string.
- **Culture handling**: Uses the current UI culture (`CultureInfo.CurrentUICulture`) implicitly via `ResourceManager.GetString`, unless `StringResources.Culture` is explicitly set (which is possible but not done here).
- **No null-safety for `serviceProvider`**: While `serviceProvider` is unused, `ProvideValue` does not guard against null—though WPF guarantees non-null in normal usage.
- **Auto-generated resource class**: `StringResources.Designer.cs` is auto-generated; manual edits will be overwritten. Ensure keys used in `TranslateExtension` exist in the `.resx` file.
> **None identified from source alone.**

View File

@@ -0,0 +1,67 @@
---
source_files:
- DataPRO/Modules/Hardware/HardwareList/View/HardwareListOverdueView.xaml.cs
- DataPRO/Modules/Hardware/HardwareList/View/HardwareListReplaceView.xaml.cs
- DataPRO/Modules/Hardware/HardwareList/View/SLICE6TreeView.xaml.cs
- DataPRO/Modules/Hardware/HardwareList/View/HardwareListSelectView.xaml.cs
- DataPRO/Modules/Hardware/HardwareList/View/HardwareListView.xaml.cs
generated_at: "2026-04-16T04:38:01.309494+00:00"
model: "Qwen/Qwen3-Coder-Next-FP8"
schema_version: 1
sha256: "19f25015f9f12fa7"
---
# View
### **Purpose**
This module provides WPF view implementations for the hardware diagnostics hardware list feature, serving as the UI layer that binds to `IHardwareListViewModel` and related interfaces. It enables users to view, sort, filter, and manipulate hardware items—including overdue items, replaceable units, and SLICE6 associations—through a set of specialized views (`HardwareListView`, `HardwareListOverdueView`, `HardwareListReplaceView`, `HardwareListSelectView`, `SLICE6TreeView`). These views handle user interactions (e.g., column header clicks, button presses, tree node operations) and delegate business logic to the underlying view model, while also publishing `PageModifiedEvent` to signal state changes.
---
### **Public Interface**
All classes implement interfaces in the `DTS.Common.Interface.DASFactory.Diagnostics.HardwareList` namespace (e.g., `IHardwareListView`, `IHardwareListOverdueView`). They expose no public methods beyond their constructors; all behavior is driven via event handlers wired in XAML. The interfaces they implement are assumed to define the contract for view-model binding, but the *actual* public surface is minimal and consists solely of:
| Class | Constructor | Notes |
|-------|-------------|-------|
| `HardwareListOverdueView()` | `public HardwareListOverdueView()` | Initializes component; handles `ListViewHeader_Click` for sorting overdue items. |
| `HardwareListReplaceView()` | `public HardwareListReplaceView()` | Initializes component; handles `Replace_Click` to invoke `IHardwareListViewModel.Replace()`. |
| `SLICE6TreeView()` | `public SLICE6TreeView()` | Initializes component; handles `Remove_Click`, `Add_Click`, and `Swap_Click` to manage SLICE6 associations and publish `PageModifiedEvent`. |
| `HardwareListSelectView()` | `public HardwareListSelectView()` | Initializes component; provides `InitializeColumns(bool bSteamingTest)` to dynamically show/hide the `DSPStreamingColumn`. Also handles sorting, filtering, inclusion, and chain sample rate mixed button clicks. |
| `HardwareListView()` | `public HardwareListView()` | Initializes component; handles search, sorting, double-click (via `MouseDoubleClick`), and tree view popup invocation (`TreeviewButton_Click`). |
> **Note**: No public methods beyond constructors exist in the source. All functionality is exposed via private event handlers (`ListViewHeader_Click`, `Replace_Click`, etc.) bound in XAML.
---
### **Invariants**
- **View Model Contract**: All views assume their `DataContext` implements a specific interface (`IHardwareListViewModel`, `ISLICE6TreeNode`, or `IHardware`) and that required properties (e.g., `SelectedSLICE6`, `SelectedSLICE6DB`, `ShowCompact`) are non-null when used. Null checks are performed before use, but no fallback behavior is defined.
- **Event Publishing**: In `SLICE6TreeView`, after `Associate`, `UnAssociate`, or `Swap` operations, a `PageModifiedEvent` with status `Modified` is *always* published—regardless of whether the operation succeeded or the tree node was valid.
- **Column Management**: In `HardwareListSelectView.InitializeColumns`, the `CalDateColumn` index is used as a reference point for inserting `DSPStreamingColumn`; if `CalDateColumn` is not found (index < 0), index `0` is used as fallback.
- **Sorting Consistency**: All column header click handlers (`ListViewHeader_Click`, `GridViewColumnHeader_OnClick`, `GridViewColumnHeaderCheckBox_OnClick`) invoke `Sort(..., true)`, implying ascending sort order is hardcoded (or `true` indicates a toggle flag—source does not clarify).
- **Popup State**: In `HardwareListView.TreeviewButton_Click`, the `SLICE6TreeViewPopup` is explicitly closed before reassigning its `Child` and reopening—ensuring only one instance is active at a time.
---
### **Dependencies**
**External Dependencies (imports):**
- `System.Windows.*` (WPF core: `Controls`, `Data`, `Media`, `Input`)
- `DTS.Common.Interface.DASFactory.Diagnostics.HardwareList` — defines core interfaces: `IHardwareListOverdueView`, `IHardwareListReplaceView`, `ISLICE6TreeView`, `IHardwareListSelectView`, `IHardwareListView`, `IHardwareListViewModel`, `IHardware`, `ISLICE6TreeNode`.
- `DTS.Common.Controls` — provides custom controls like `GridViewColumnHeaderSearchable`, `GridViewColumnHeaderSelectable`, `Popup` (`SLICE6TreeViewPopup`).
- `DTS.Common.Utils` — utility methods: `Utils.FindChild<T>` (used in `HardwareListSelectView` and `HardwareListView` for tag resolution).
- `Prism.Ioc`, `Prism.Events` — used in `SLICE6TreeView` to resolve `IEventAggregator` and publish `PageModifiedEvent`.
**Consumed by:**
- The modules view model layer (`IHardwareListViewModel` implementations) — binds to these views via `DataContext`.
- Likely the main hardware list module shell (e.g., Prism module initialization) — instantiates and hosts these views.
---
### **Gotchas**
- **Typo in `InitializeColumns` parameter**: The parameter is named `bSteamingTest`, likely intended to be `bStreamingTest` (note missing 'r'). This may cause confusion or mismatches in downstream code.
- **Ambiguous sort flag**: All `Sort(..., true)` calls use a literal `true`. Without the interface definition or implementation, it is unclear whether this indicates ascending order, a toggle reset, or a secondary sort flag.
- **Redundant null checks**: In `HardwareListSelectView` and `HardwareListView`, `sender` is cast to `Control` before checking `control.DataContext`. This is safe but verbose; could be simplified with pattern matching (e.g., `if (sender is Control control && control.DataContext is IHardwareListViewModel vm)`).
- **EventAggregator resolution in SLICE6TreeView**: `ContainerLocator.Container.Resolve<IEventAggregator>()` is called *synchronously* on each `Add_Click`, `Remove_Click`, and `Swap_Click`. This is inefficient and violates Prism best practices (should be injected via constructor). No DI constructor is present, suggesting tight coupling to Prisms static locator.
- **Missing error handling**: All click handlers silently return on failed casts (e.g., `if (!(control.DataContext is IHardwareListViewModel vm)) { return; }`). No logging or user feedback occurs if expectations are violated.
- **`GetCurrentIndex` logic**: In `HardwareListView`, `GetCurrentIndex` iterates over all items and uses `VisualTreeHelper.GetDescendantBounds` and `IsMouseOverTarget` to determine the clicked item. This is computationally expensive for large lists and may be fragile if item containers are virtualized or not yet generated.
> **None identified from source alone.** → *Not applicable; multiple gotchas found.*

View File

@@ -0,0 +1,280 @@
---
source_files:
- DataPRO/Modules/Hardware/HardwareList/ViewModel/HardwareListViewModel.cs
generated_at: "2026-04-16T04:37:43.305054+00:00"
model: "Qwen/Qwen3-Coder-Next-FP8"
schema_version: 1
sha256: "529cbbf4accc9016"
---
# ViewModel
**Documentation: HardwareListViewModel.cs**
---
### 1. **Purpose**
The `HardwareListViewModel` class serves as the central MVVM ViewModel for the hardware list UI module in the DASFactory diagnostics system. It manages the presentation and interaction logic for hardware inventory—including filtering, sorting, selection, calibration status tracking, sample rate configuration, and SLICE6/SLICE6DB association management. It aggregates raw hardware data from `DTS.Common.ISO.Hardware.GetAllDAS`, wraps it in `HardwareModel` instances, and exposes structured collections (`Hardware`, `OverdueHardware`, `AvailableHardware`, etc.) to views. It also coordinates inter-view communication via Prisms `IEventAggregator`, handles user actions (e.g., editing, replacing, associating hardware), and enforces domain-specific rules such as parentchild DAS sample rate consistency and channel assignment tracking during hardware replacement.
---
### 2. **Public Interface**
All methods and properties are `public` unless otherwise noted. The class implements `IHardwareListViewModel` (inferred from `: IHardwareListViewModel`).
#### **Constructors**
- **`HardwareListViewModel(IHardwareListView view, IRegionManager regionManager, IEventAggregator eventAggregator, IUnityContainer unityContainer)`**
Initializes the ViewModel with required dependencies, sets up event subscriptions (`RaiseNotification`, `BusyIndicatorChangeNotification`), and initializes `SelectedHardwareItems` as an `ObservableCollection<IHardware>`.
#### **Public Methods**
- **`void LoadTreeView(string serialNumber)`**
Populates `SLICE6TreeNodes`, `AvailableSLICE6`, `SelectedSLICE6DB`, and `AvailableSLICE6DB` for the given SLICE6DB serial number using `SLICE6TreeNode.GetTreeNodes()` and `HardwareModel.GetAvailableSLICE6DB()`.
- **`void GetHardware(bool bIncludeModules, bool bIncludeOverdue, bool bIncludeBridges, int? testId, int? groupId)`**
Loads and processes hardware from `DTS.Common.ISO.Hardware.GetAllDAS()`, constructs `HardwareModel` instances, aggregates channel counts for parent DAS with child modules, and filters based on overdue status and inclusion flags. Stores results in `_allHardware`, then calls `Filter()` and `Sort()`.
- **`void SetTestSampleRates(Dictionary<string, double> testSampleRates)`**
Applies sample rates from `testSampleRates` to all hardware in `_allHardware`. If a rate is unavailable, uses the next highest available rate. Updates `TestSampleRate`, `SelectedSampleRateIndex`, and calls `SetDSPRate()` and `CheckForMixedDAS()`.
- **`void UpdateTestSampleRate(string childSerialNumber, double testSampleRate)`**
Updates sample rate and AAF rate for a specific child hardware (by `SerialNumber`), then updates DSP filter rate.
- **`void SetTestAAFRates(Dictionary<string, float> testAAFRates)`**
Applies AAF rates from `testAAFRates`. If missing for a hardware item, computes default via `GetAAFForHardware()` and logs a warning via `PageErrorEvent`.
- **`void UpdateTestAAFilterRate(string childSerialNumber, float testAAFilterRate)`**
Updates AAF rate for a specific hardware item.
- **`void SetTestClockMasters(Dictionary<string, bool> testClockMasters)`**
Sets `IsClockMaster` for hardware whose `SerialNumber` appears in the dictionary.
- **`void UpdateTestClockMaster(string childSerialNumber, bool testClockMaster)`**
Sets `IsClockMaster` for a specific hardware item.
- **`void SetTestPTPDomainIDs(Dictionary<string, byte> testPTPDomainIDs)`**
Sets `PTPDomainID` for hardware whose `SerialNumber` appears in the dictionary.
- **`void UpdateTestPTPDomainID(string childSerialNumber, byte ptpDomainId)`**
Sets `PTPDomainID` for a specific hardware item.
- **`void CheckForMixedDAS(string nonParentSerialNumber, double testSampleRate)`**
Ensures sample rate consistency between a child DAS and its parent. If siblings have differing rates, marks the parent as `MixedRates = true`; otherwise, aligns parent rate to child.
- **`void SetParentMixedRates(string parentDAS, bool mixedRates)`**
Sets `MixedRates` property on the parent DAS.
- **`void SetHasIncludedChildren()`**
Sets `HasIncludedChildren = true` for distributors that have at least one included child.
- **`bool AnyChildren(string distributorDAS)`**
Returns `true` if any included hardware has `ParentDAS == distributorDAS`.
- **`void Filter(object tag, string term)`**
Updates filter criteria for a specific field (`Fields` enum) and re-applies filtering.
- **`void Filter(string term)`**
Applies `_currentSearchTerm` and field-specific filters to `_allHardware`, populating `Hardware` and `OverdueHardware`. Handles compact view logic (hides rack modules under certain conditions) and recalculates channel counts.
- **`void Sort(object o, bool bColumnClick)`**
Sorts `Hardware` by field (`HardwareListTags`) and direction (toggle on repeated column click). Uses `HardwareComparer`.
- **`void SortOverdue(object o, bool bColumnClick)`**
Sorts `OverdueHardware` similarly.
- **`void SetIncluded(string[] serialNumbers, bool included)`**
Sets `Included` flag for hardware matching `serialNumbers` in the *filtered* `Hardware` list.
- **`void SetIncluded(int[] ids)`**
Sets `Included = true` for hardware matching `DASId` in `_allHardware`.
- **`void IncludeChildren(IHardware hardware)`**
Sets `Included` for all child modules (via `IsPseudoRackModule()`) of the given hardware to match its `Included` value.
- **`void RemoveMultipleButton(IHardware hardware)`**
Clears sample rate display (`TestSampleRate = 0`) and `MixedRates` flag for the given hardware.
- **`void Unset()`**
Resets all hardware collections, SLICE6 associations, and channel assignments; publishes `ListViewStatusEvent.Unloaded`.
- **`void ClearAllFilters()`**
Clears `_filterByField`.
- **`void Cleanup()` / `Task CleanupAsync()` / `void Initialize()` / `Task InitializeAsync()` / `void Activated()`**
No-op stubs (likely required by Prism interfaces).
- **`void SaveSLICE6Associations(string serialNumber)`**
Commits SLICE6 associations to DB via `SLICE6TreeNode.SaveAssociations()`. If `_swappedHardware` is set, swaps nodes first.
- **`void Associate(ISLICE6TreeNode node)`**
Adds a `SLICE6TreeNode` to `SLICE6TreeNodes`, assigns `Number`, `Port`, `PositionOnChain`, and removes from `AvailableSLICE6`.
- **`void Associate(IHardware node)`**
Sets `_swappedHardware`, reloads tree view for `node.SerialNumber`, and updates `AvailableSLICE6`/`SLICE6TreeNodes`.
- **`void UnAssociate(ISLICE6TreeNode node)`**
Removes `node` from `SLICE6TreeNodes`, renumbers remaining nodes, resets its metadata, and adds back to `AvailableSLICE6`.
- **`void Replace()`**
Commits hardware replacement: sets `ReplacementHardware.Included = true`, publishes `HardwareReplaceEvent`, and clears `HardwareToReplace`/`ReplacementHardware`.
- **`IHardware[] GetSelectedItems()`**
Returns `SelectedHardwareItems.ToArray()`.
- **`void SetCalPeriods(...)`**
Sets all `*CalPeriod` properties (e.g., `G5CalPeriod`, `SLICE6_CalPeriod`) for use in `HardwareModel` construction.
#### **Public Properties**
- **`IHardwareListView View`, `IHardwareListOverdueView OverdueView`, `IHardwareListSelectView SelectView`, `IHardwareListReplaceView ReplaceView`, `ISLICE6TreeView SLICE6TreeView`**
View interfaces bound to this ViewModel.
- **`InteractionRequest<Notification> NotificationRequest`, `InteractionRequest<Confirmation> ConfirmationRequest`**
Prism interaction triggers for modal dialogs.
- **`event PropertyChangedEventHandler PropertyChanged`**
Standard `INotifyPropertyChanged` implementation.
- **`IHardware[] Hardware`**
Filtered and sorted list of hardware for display.
- **`IHardware[] OverdueHardware`**
Hardware with `CalDueDate <= DateTime.Today`.
- **`IHardware[] AvailableHardware`**
Hardware suitable for replacement (excludes included items, matches `HardwareType`, respects rack size constraints).
- **`IHardware HardwareToReplace`, `IHardware ReplacementHardware`**
Current hardware being replaced and its candidate replacement.
- **`Model.HardwareChannelAssignment[] AssignedChannels`**
Channels assigned to `HardwareToReplace` (populated in `InitializeReplace()` and `PopulateAvailableHardware()`).
- **`ISLICE6TreeNode[] SLICE6TreeNodes`, `ISLICE6TreeNode[] AvailableSLICE6`**
Associated and available SLICE6 units for a given SLICE6DB.
- **`IHardware[] AvailableSLICE6DB`**
SLICE6DB units available for association.
- **`bool ShowCompact`**
Controls whether rack modules are hidden (default `true`). Triggers re-filtering and publishes `HardwareListShowCompactEvent`.
- **`ObservableCollection<IHardware> SelectedHardwareItems`**
Tracks selected hardware items; raises `HardwareListHardwareSelectedEvent` on change.
- **`bool IsBusy`**
Bound to busy indicator; set via `BusyIndicatorChangeNotification` event.
- **`bool IsDirty`**
Always `false`; not updated anywhere in source.
- **`string ListViewId => "HardwareListView"`**
Identifier for the view.
- **`int TDASCalPeriod`, `int G5CalPeriod`, ..., `int SLICE_PRO_CAN_FD_CalPeriod`**
Calibration period constants passed to `HardwareModel`.
- **`IStreamingFilterProfile StreamingDSPProfile`**
Used to compute `DSPStreamingFilter` via `GetDSPFilterRate()`.
#### **Internal/Protected Methods (Not Public Interface)**
- **`void FireAAFilterRate(...)`, `FireSampleRate(...)`, `FireClockMaster(...)`, `FireIncluded(...)`, `FirePTPDomainID(...)`**
Publish corresponding `HardwareListHardware*Event` instances.
- **`private void FireSelectionChanged()`**
Publishes `HardwareListHardwareSelectedEvent` with selected serial numbers.
- **`private void Hardware_PropertyChanged(...)`**
Handles `TestAAFilterRateHz` changes to call `SetDSPRate()`.
- **`private void SetDSPRate(HardwareModel hardware)`**, **`private void UpdateDSP(HardwareModel hardware)`**
Computes `DSPStreamingFilter` using `StreamingDSPProfile`.
- **`private double GetNextHighestAvailableSampleRate(...)`**
Helper for `SetTestSampleRates`.
- **`internal float GetAAFForHardware(IISOHardware h, int sampleRate)`**
Returns AAF rate based on DAS type (TDAS vs SLICE).
- **`private bool AnyMixedChildren(...)`**, **`private void PopulateAvailableHardware()`**, **`private void OnRaiseNotification(...)`, `OnBusyIndicatorNotification(...)`**
Internal helpers.
---
### 3. **Invariants**
- **Hardware Uniqueness**: `_allHardware` must contain no duplicate `SerialNumber`s. Duplicates are logged via `APILogger.Log()` during `GetHardware()`.
- **ParentChild Sample Rate Consistency**: For any child DAS with `ParentDAS` set, `CheckForMixedDAS()` ensures the parents `MixedRates` flag reflects whether any included siblings have differing `TestSampleRate`. If all children match, the parents rate is updated to match.
- **Calibration Overdue Logic**: `OverdueHardware` includes all hardware where `CalDueDate <= DateTime.Today`. This is recomputed on every `Filter()` call.
- **Channel Aggregation for Parent DAS**: When `bIncludeModules == false`, parent DAS channel counts (`AnalogChannels`, `SquibChannels`, etc.) are aggregated from included child modules. If a parent has only one analog channel, it is reset to `0` before adding child channels.
- **SLICE6 Association Integrity**: `SLICE6TreeNode.Number`, `Port`, and `PositionOnChain` are managed during `Associate()`/`UnAssociate()` to maintain ordering and uniqueness.
- **Replacement Hardware Constraints**: In `PopulateAvailableHardware()`, replacement hardware must match `HardwareType`. For `TDAS_Pro_Rack`, replacement must have `MaxModules >=` originals `MaxModules`.
- **Filtering Scope**: `Filter(string term)` operates on `_allHardware`, but `SetIncluded(string[])` operates on the *filtered* `Hardware` list.
---
### 4. **Dependencies**
#### **Imports/Usings**
- **Core**: `System.Collections.Generic`, `System.Linq`, `System.Threading.Tasks`, `System.ComponentModel`, `System.Collections.Specialized`.
- **Prism**: `Prism.Regions`, `Prism.Events`, `Unity` (`IUnityContainer`, `IRegionManager`, `IEventAggregator`).
- **Common Libraries**:
- `DTS.Common.Classes.Hardware`, `DTS.Common.Enums.Hardware`, `DTS.Common.Events.Hardware.HardwareList`
- `DTS.Common.Interface.DASFactory.Diagnostics.HardwareList` (e.g., `IHardwareListView`, `ISLICE6TreeNode`)
- `HardareList.Model` (e.g., `HardwareModel`, `HardwareChannelAssignment`)
- `DTS.Common.Interface.TestSetups.TestSetupsList` (`ITestSetup`)
- `DTS.Common.Utilities.Logging` (`APILogger`)
- `DTS.Common.Classes.DSP` (`IStreamingFilterProfile`)
- `DTS.Common.Interactivity` (`InteractionRequest<T>`)
#### **External Types Referenced**
- `IHardware`, `IISOHardware`, `HardwareModel`, `ISLICE6TreeNode`, `ISLICE6TreeView`, `ITestSetup`, `HardwareTypes`, `SerializableAAF.DAS_TYPE`, `DTS.Common.ClockSyncProfile`, `DTS.Common.ISO.Hardware`, `DFConstantsAndEnums.TSRAIR_ValidSampleRates`.
#### **Event Types Published/Consumed**
- **Consumed**: `RaiseNotification`, `BusyIndicatorChangeNotification`, `PageErrorEvent`.
- **Published**: `HardwareListEditHardwareEvent`, `HardwareListHardwareTestAAFilterRateEvent`, `HardwareListHardwareTestSampleRateEvent`, `HardwareListHardwareTestClockMasterEvent`, `HardwareListHardwareIncludedEvent`, `HardwareListHardwareSelectedEvent`, `HardwareListHardwareTestPTPDomainIDEvent`, `HardwareReplaceEvent`, `HardwareListShowCompactEvent`, `ListViewStatusEvent`.
#### **Dependents**
- Views (`IHardwareListView`, `IHardwareListOverdueView`, etc.) bind to this ViewModel.
- Other modules subscribe to its published events (e.g., `HardwareReplaceEvent`).
---
### 5. **Gotchas**
- **`IsDirty` is never set**: The property is declared but always `false`. This may indicate incomplete implementation or unused state tracking.
- **`HardwareFilter` uses `Fields` enum, but `Filter(string term)` uses `_currentSearchTerm` for global search**: Field-specific filters are stored in `_filterByField`, but the primary `Filter(string term)` method only uses `_currentSearchTerm`. This may cause confusion—field filters are only applied via `Filter(object tag, string term)`.
- **`SetTestSampleRates` silently overrides unavailable rates**: If a requested sample rate is not in `hardware._availableSampleRates`, it jumps to the next highest *without user confirmation*. This could mask configuration errors.
- **`GetAAFForHardware` uses `DASTypeEnum` to choose between `TDAS` and `SLICE` AAF profiles**: The `default` case assumes all non-TDAS hardware is SLICE, which may be incorrect for future hardware types.
- **`SLICE6TreeNode.Number` assignment assumes sequential numbering**: `node.Number = 1 + SLICE6TreeNodes.Length` may cause conflicts if nodes are added out-of-order or reloaded from persistent state.
- **`Hardware_PropertyChanged` only handles `TestAAFilterRateHz`**: Other property changes (e.g., `Included`, `TestSampleRate`) do not trigger DSP recalculation unless explicitly handled elsewhere (e.g., `SetTestSampleRates`).
- **`Unset()` does not clear `_dasIdToChannels`**: While `InitializeReplace()` clears it, `Unset()` does not. If `Unset()` is called mid-replace operation, stale channel assignments may persist.
- **`ShowCompact` triggers re-filtering but not re-sorting**: Changing `ShowCompact` calls `Filter()` but not `Sort()`, potentially leaving the list in an inconsistent order until the user re-sorts.
- **`SelectedHardwareItems.CollectionChanged` handler `SelectedHardwareItemsOnCollectionChanged` calls `FireSelectionChanged()`**: This may fire multiple times if items are added/removed in bulk (e.g., via `SetIncluded()`), though `SelectedItemsStatus.GetUpdating()` is checked in `FireSelectionChanged()` (source of `SelectedItemsStatus` not provided—behavior uncertain).
- **`GetHardware()` aggregates child channels only when `bIncludeModules == false`**: When `bIncludeModules == true`, parent DAS channel counts are *not* aggregated, leading to inconsistent channel counts depending on view mode.
- **`GetAAFForHardwareFunc` is a public property**: Allows external override of AAF computation logic, but no usage is shown in this file.
- **`IsEdit`, `IsMenuIncluded`, `IsNavigationIncluded` are exposed but never set in this file**: Their purpose is unclear without context from other modules.
- **Typo in namespace import**: `using HardareList.Model;` (missing 'd' in "Hardware")—likely a ReSharper suppression or legacy artifact.
- **`SLICE6TreeNode.SwapNodes()` and `SaveAssociations()` are called in `SaveSLICE6Associations()`**: The order (swap first, then save) may be critical for data integrity, but no error handling is visible.
- **`SelectedHardwareItems` is initialized as `new ObservableCollection<IHardware>()` but never cleared in `Unset()`**: `Unset()` reassigns `SelectedHardwareItems = null`? No—`Unset()` does not modify it. This may leave stale selections after unloading.
- **`Hardware` and `OverdueHardware` arrays are reassigned directly**: This bypasses `OnPropertyChanged` unless explicitly triggered (e.g., `OnPropertyChanged("Hardware")`), which is done—but only after sorting/filtering. Direct array mutation (e.g

View File

@@ -0,0 +1,85 @@
---
source_files:
- DataPRO/Modules/ISO/ExtraProperties/ExtraPropertiesModule.cs
generated_at: "2026-04-16T04:38:16.817195+00:00"
model: "Qwen/Qwen3-Coder-Next-FP8"
schema_version: 1
sha256: "02a142220d3db719"
---
# ExtraProperties
## Documentation: ExtraPropertiesModule
### 1. Purpose
The `ExtraPropertiesModule` is a Prism module responsible for registering the view and view model components for the *Extra Properties* feature within the applications UI. It integrates with the Unity dependency injection container to expose `IExtraPropertiesListView` and `IExtraPropertiesListViewModel` as singleton services, enabling modular, testable, and decoupled UI construction. Additionally, it contributes assembly-level metadata (name, image, group, region) via custom attributes (`ExtraPropertiesModuleNameAttribute`, `ExtraPropertiesModuleImageAttribute`) to support dynamic UI composition—specifically, for display on the main screens summary of available modules.
### 2. Public Interface
#### `ExtraPropertiesModule` class
- **`ExtraPropertiesModule(IUnityContainer unityContainer)`**
Constructor. Accepts a Unity container via dependency injection and stores it for later use in type registration.
- **`void Initialize()`**
Registers two types as singletons in the Unity container:
- `IExtraPropertiesListViewModel``ExtraPropertiesListViewModel`
- `IExtraPropertiesListView``ExtraPropertiesListView`
This method is called both directly during module initialization and via `RegisterTypes`.
- **`void OnInitialized(IContainerProvider containerProvider)`**
Currently empty; no logic implemented.
- **`void RegisterTypes(IContainerRegistry containerRegistry)`**
Delegates to `Initialize()` (despite receiving a `IContainerRegistry`, it uses the injected `IUnityContainer` instead).
#### `ExtraPropertiesModuleNameAttribute` class
- **`ExtraPropertiesModuleNameAttribute()` / `ExtraPropertiesModuleNameAttribute(string s)`**
Constructor; ignores the `string s` parameter. Sets `AssemblyName` to `AssemblyNames.ExtraProperties.ToString()`.
- **`string AssemblyName { get; }`**
Returns `"ExtraProperties"` (value of `AssemblyNames.ExtraProperties.ToString()`).
- **`Type GetAttributeType()`**
Returns `typeof(TextAttribute)`.
- **`string GetAssemblyName()`**
Returns `AssemblyName`.
#### `ExtraPropertiesModuleImageAttribute` class
- **`ExtraPropertiesModuleImageAttribute()` / `ExtraPropertiesModuleImageAttribute(string s)`**
Constructor; initializes `_img` by calling `AssemblyInfo.GetImage("ExtraProperties")`.
- **`BitmapImage AssemblyImage { get; }`**
Returns the image retrieved via `AssemblyInfo.GetImage("ExtraProperties")`.
- **`string AssemblyName { get; }`**
Returns `"ExtraProperties"`.
- **`string AssemblyGroup { get; }`**
Returns `"Prepare"` (value of `eAssemblyGroups.Prepare.ToString()`).
- **`eAssemblyRegion AssemblyRegion { get; }`**
Returns `eAssemblyRegion.ExtraPropertiesRegion`.
- **`Type GetAttributeType()`**
Returns `typeof(ImageAttribute)`.
- **`BitmapImage GetAssemblyImage()` / `string GetAssemblyName()` / `string GetAssemblyGroup()` / `eAssemblyRegion GetAssemblyRegion()`**
Public overrides returning the corresponding property values.
### 3. Invariants
- `AssemblyName` for both attributes is strictly `"ExtraProperties"` (derived from `AssemblyNames.ExtraProperties`).
- `AssemblyGroup` is strictly `"Prepare"` (derived from `eAssemblyGroups.Prepare`).
- `AssemblyRegion` is strictly `eAssemblyRegion.ExtraPropertiesRegion`.
- The `ExtraPropertiesListView` and `ExtraPropertiesListViewModel` types are registered as *singleton* instances in the Unity container during module initialization.
- Both attributes are assembly-level (`AttributeTargets.Assembly`), non-repeatable (`AllowMultiple = false`), and must be applied exactly once per assembly.
### 4. Dependencies
**Depends on:**
- `Unity` (via `IUnityContainer`, `Unity` namespace)
- `Prism.Modularity` (via `IModule`, `ModuleAttribute`)
- `Prism.Ioc` (via `IContainerRegistry`, `IContainerProvider`)
- `DTS.Common.Interface.ISO.ExtraProperties` (via `IExtraPropertiesListView`, `IExtraPropertiesListViewModel`)
- `DTS.Common` (via `AssemblyNames`, `eAssemblyGroups`, `eAssemblyRegion`, `AssemblyInfo`)
- `System.Windows.Media.Imaging` (via `BitmapImage`)
- `System.ComponentModel.Composition` (via `ExportAttribute`)
**Used by:**
- The Prism bootstrapper/container infrastructure (to discover and load `ExtraPropertiesModule` as an `IModule`).
- The UI composition layer (to retrieve module metadata—name, image, group, region—via reflection on the assembly attributes).
### 5. Gotchas
- **`RegisterTypes` ignores its parameter**: Despite receiving `IContainerRegistry`, `RegisterTypes` calls `Initialize()`, which uses the *injected* `IUnityContainer` instead. This tightly couples the module to Unity and breaks Prisms abstraction (e.g., it would fail if used with a different DI container).
- **Redundant attribute usage**: Both `ExtraPropertiesModuleNameAttribute` and `ExtraPropertiesModuleImageAttribute` are applied at the assembly level (via `[assembly: ...]`), but their constructors accept an unused `string` parameter—likely legacy or placeholder.
- **No error handling in image loading**: `AssemblyInfo.GetImage(...)` is called in the constructor and property getter of `ExtraPropertiesModuleImageAttribute`. If the image resource is missing or malformed, this could cause runtime exceptions during assembly loading or attribute enumeration.
- **`OnInitialized` is empty**: Suggests incomplete implementation or deferred logic.
- **No validation of view/view-model types**: Assumes `ExtraPropertiesListView` and `ExtraPropertiesListViewModel` exist and implement their respective interfaces. A mismatch would only surface at runtime during resolution.
- **No documentation for `AssemblyNames`, `eAssemblyGroups`, `eAssemblyRegion`, or `AssemblyInfo`**: These types are referenced but not defined in this file; their values and constraints are inferred solely from usage.

View File

@@ -0,0 +1,101 @@
---
source_files:
- DataPRO/Modules/ISO/ExtraProperties/Model/ExtraPropertyModel.cs
generated_at: "2026-04-16T04:39:00.347162+00:00"
model: "Qwen/Qwen3-Coder-Next-FP8"
schema_version: 1
sha256: "f8c9e5793048774d"
---
# Model
### **Purpose**
This module implements the `ExtraPropertyModel` class, a concrete data model for representing key-value pairs (e.g., ISO channel codes and names or user-defined properties) within a WPF-based UI, conforming to the `IExtraProperty` interface. It supports property change notifications via Prisms `BasePropertyChanged`, integrates with Prisms event aggregation system for cross-module communication (e.g., signaling page modifications or paste events), and provides a custom `PasteCommand` to handle clipboard paste operations with special handling for multi-line or multi-field text. Its role is to serve as the view-model backing for UI controls that edit extra properties in ISO data contexts.
---
### **Public Interface**
#### **`ExtraPropertyModel` class**
- **`public ExtraPropertyModel(IExtraProperty extraProperty)`**
Initializes a new instance by copying `Key` and `Value` from an existing `IExtraProperty` instance. Registers paste commands during construction.
- **`public ExtraPropertyModel()`**
Default constructor. Registers paste commands. `Key` and `Value` are initialized to `null`.
- **`public ExtraPropertyModel(KeyValuePair<string, string> extraProperty)`**
Initializes a new instance using a `KeyValuePair<string, string>`. Registers paste commands.
- **`public UIItemStatus ItemStatus { get; set; }`**
Gets or sets the UI status of the item (e.g., `None`, `Added`, `Modified`, `Deleted`). Backed by `SetProperty` for change notifications.
- **`public string Key { get; set; }`**
Gets or sets the code (e.g., ISO code or user code). Backed by `SetProperty`.
- **`public string Value { get; set; }`**
Gets or sets the associated name (e.g., ISO channel name or user channel name). Backed by `SetProperty`.
- **`public ICommand PasteCommand { get; set; }`**
Exposes the command bound to paste operations. Initialized to a `PasteCommandClass` instance with `PASTE_ID = "ExtraProperty"`.
- **`public const string PASTE_ID = "ExtraProperty"`**
Constant identifier used to distinguish paste operations originating from this model.
#### **`PasteCommandClass` class**
- **`public string Id { get; }`**
Gets the command ID passed during construction (e.g., `"ExtraProperty"`).
- **`public bool CanExecute(object parameter)`**
Always returns `true`.
- **`public void Execute(object parameter)`**
Handles paste logic:
- Validates `parameter` is a `TextBox`.
- Attempts to resolve `IExtraProperty` from `TextBox.DataContext`, falling back to `ChannelCodeBuilder` or `ChannelNameBuilder` contexts.
- Checks clipboard contains text.
- If clipboard text has exactly one line and contains no delimiters (`','`, `';'`, `'\t'`), publishes `PageModifiedEvent` and exits early (single-field paste is handled by `TextChanged`).
- Otherwise, clears `Key`/`Value` on the target `IExtraProperty` (a no-op assignment to trigger change tracking), then publishes `TextPastedEvent` with the raw text, target property, command ID, and `TextBox.Tag`.
- On exception, publishes `PageErrorEvent` with the exception message.
- **`public event EventHandler CanExecuteChanged`**
Required by `ICommand`, but never raised (no-op).
- **`public PasteCommandClass(string id)`**
Constructor storing `id` in `Id`.
---
### **Invariants**
- `Key` and `Value` may be `null`; no validation is enforced on their values.
- `ItemStatus` defaults to `UIItemStatus.None` and must be explicitly set by consumers.
- The `PasteCommand` is registered globally via `CommandManager.RegisterClassCommandBinding`, meaning it applies to *all* instances of `ExtraPropertyModel` and its subclasses.
- The `Paste` method (private) is never implemented — it is a stub. Actual paste behavior resides entirely in `PasteCommandClass.Execute`.
- `CanExecuteChanged` is never raised by `PasteCommandClass`, so WPF command bindings may not update UI state (e.g., button enablement) dynamically.
---
### **Dependencies**
- **Imports/Usings**:
- `DTS.Common.ISO.ExtraProperties` → Provides `IExtraProperty` interface.
- `DTS.Common.Controls` → Provides `ChannelCodeBuilder`, `ChannelNameBuilder` types.
- `DTS.Common.Enums` → Provides `UIItemStatus`.
- `DTS.Common.Events` → Provides `PageModifiedEvent`, `TextPastedEvent`, `PageErrorEvent`, and their argument types.
- `Prism.Ioc` → Provides `ContainerLocator` (for resolving `IEventAggregator`).
- `Prism.Events` → Provides `IEventAggregator`.
- **Depended upon**:
- `IExtraProperty` interface (consumed via constructor and paste logic).
- `PageModifiedEvent`, `TextPastedEvent`, `PageErrorEvent` (published by `PasteCommandClass`).
- `ContainerLocator.Container` (runtime dependency for event aggregation).
---
### **Gotchas**
- **`Paste` method is empty**: The private `Paste(object sender, ExecutedRoutedEventArgs e)` method is declared but has no implementation; all logic resides in `PasteCommandClass.Execute`. This is likely intentional (to satisfy `CommandBinding` requirements), but may confuse readers.
- **`CanExecuteChanged` is never raised**: `PasteCommandClass` implements `ICommand` but does not notify subscribers of `CanExecute` state changes, potentially causing stale UI (e.g., disabled paste buttons).
- **Ambiguous paste behavior**:
- Single-line, non-delimited text triggers `PageModifiedEvent` but *not* `TextPastedEvent`, while multi-line or delimited text triggers `TextPastedEvent` but *not* `PageModifiedEvent`. This asymmetry may lead to inconsistent state tracking.
- The "wipe out built-in effect" assignment (`extraProperty.Key = extraProperty.Key`) is a no-op and serves no functional purpose beyond triggering change notifications if the property setter is implemented non-trivially elsewhere.
- **Clipboard access without safety checks**: `Clipboard.GetText()` may throw exceptions (e.g., in sandboxed environments), but only generic `Exception` handling is present.
- **No null-safety for `tb.Tag`**: The `tb.Tag` value is passed directly in `TextPastedArgs` without null checks.
- **Tight coupling to Prism**: Reliance on `ContainerLocator.Container` for `IEventAggregator` makes unit testing difficult without Prism infrastructure.
- **No cleanup in constructors**: While the finalizer attempts to null `_key`/`_value`, this is unreliable and unnecessary in modern .NET (where `IDisposable` would be preferred if unmanaged resources were involved — none are evident here).

View File

@@ -0,0 +1,38 @@
---
source_files:
- DataPRO/Modules/ISO/ExtraProperties/Properties/AssemblyInfo.cs
generated_at: "2026-04-16T04:38:46.680275+00:00"
model: "Qwen/Qwen3-Coder-Next-FP8"
schema_version: 1
sha256: "928af9411c9cbe1b"
---
# Properties
## 1. Purpose
This module (`ExtraProperties`) is an assembly-level metadata configuration file for a proprietary .NET component within the `DataPRO/Modules/ISO/ExtraProperties` path. It defines standard assembly attributes (title, version, culture, COM visibility) but contains no application logic—its sole purpose is to declare metadata for the compiled assembly, primarily for versioning, identification, and COM interop control. It serves as infrastructure for build/deployment and runtime reflection, not for business logic.
## 2. Public Interface
**No public types, functions, classes, or methods are defined in this file.**
This file (`AssemblyInfo.cs`) contains only assembly-level attributes and does not declare any executable code or public API surface.
## 3. Invariants
- The assembly is **not visible to COM** (`ComVisible(false)`), meaning its types cannot be accessed via COM interop unless explicitly exposed elsewhere.
- The assembly version is fixed at `1.0.0.0` for both `AssemblyVersion` and `AssemblyFileVersion`.
- The `Guid` attribute (`cc693402-5f7c-4aaf-9dbe-5382b204c62b`) is reserved for the typelib ID if the assembly is ever exposed to COM.
- All attributes are applied at assembly scope (via `[assembly: ...]` syntax) and must be declared at the top level of the file (no per-type or nested attributes).
## 4. Dependencies
- **Depends on**:
- `System.Reflection` (for `AssemblyTitle`, `AssemblyVersion`, etc.)
- `System.Runtime.InteropServices` (for `ComVisible`, `Guid`)
- `System.Runtime.CompilerServices` (imported but unused in this file)
- **Depended on by**:
- Unknown from this file alone. As a metadata-only assembly, it is consumed implicitly by the .NET runtime and build tools (e.g., for strong naming, version resolution, reflection), but no explicit consumer is declared here.
## 5. Gotchas
- **No business logic**: This file is purely declarative; developers should not expect any runtime behavior or state management here.
- **COM visibility**: Though `ComVisible(false)` is set, if *any* types in this assembly *are* intended for COM exposure, they must be explicitly marked with `[ComVisible(true)]` at the type level—otherwise, they remain inaccessible to COM.
- **Versioning rigidity**: `AssemblyVersion("1.0.0.0")` is hardcoded with no wildcard (`*`), meaning build/revision numbers cannot auto-increment (unlike the commented-out `1.0.*` example).
- **Empty metadata fields**: `AssemblyDescription`, `AssemblyConfiguration`, `AssemblyCompany`, and `AssemblyTrademark` are all empty strings—this may impact tooling or installer behavior that relies on these fields.
- **None identified from source alone** regarding logic-specific quirks, as no logic exists in this file.

View File

@@ -0,0 +1,53 @@
---
source_files:
- DataPRO/Modules/ISO/ExtraProperties/Resources/TranslateExtension.cs
- DataPRO/Modules/ISO/ExtraProperties/Resources/StringResources.Designer.cs
generated_at: "2026-04-16T04:38:39.050309+00:00"
model: "Qwen/Qwen3-Coder-Next-FP8"
schema_version: 1
sha256: "d990e5734e630810"
---
# Resources
## 1. Purpose
`TranslateExtension` is a WPF `MarkupExtension` that enables declarative localization of UI strings in XAML by resolving resource keys to localized string values at runtime. It acts as a bridge between XAML markup and the applications strongly-typed resource system (`StringResources`), allowing developers to bind localized text directly in XAML using `{Translate key}` syntax. Its role is to centralize and simplify string localization, avoiding hardcoded strings and supporting culture-specific display via the underlying `ResourceManager`.
## 2. Public Interface
- **`TranslateExtension(string key)`**
Constructor. Initializes the extension with a resource key (`_key`) to look up. Throws no exceptions on invalid input; invalid keys are handled in `ProvideValue`.
- **`object ProvideValue(IServiceProvider serviceProvider)`**
Overrides `MarkupExtension.ProvideValue`. Performs the resource lookup:
- If `_key` is `null` or empty → returns `"#stringnotfound#"`.
- Otherwise, calls `StringResources.ResourceManager.GetString(_key)`.
- If a matching string is found → returns it.
- If not found → returns `"#stringnotfound# " + _key` (note the trailing space).
*Note:* The `IServiceProvider` parameter is unused; the method does not interact with the WPF service provider beyond satisfying the interface contract.
## 3. Invariants
- `_key` is immutable after construction (stored in a `readonly` field).
- The returned value is always a `string`.
- A missing or empty key **always** yields `"#stringnotfound#"`.
- A key with no corresponding resource entry **always** yields `"#stringnotfound# <key>"` (with a space before the key).
- No validation is performed on `_key` beyond null/empty checks; invalid keys (e.g., containing special characters) are passed directly to `ResourceManager.GetString`, which may return `null`.
- Thread-safety: Relies on `StringResources.ResourceManager`, which is documented as thread-safe for concurrent reads (standard `ResourceManager` behavior).
## 4. Dependencies
- **Depends on:**
- `System.Windows.Markup` (for `MarkupExtension` and `MarkupExtensionReturnType`).
- `ExtraProperties.Resources.StringResources` (strongly-typed resource class).
- `System.Resources.ResourceManager` (via `StringResources.ResourceManager`).
- **Depended on by:**
- XAML files in the `ExtraProperties` module (inferred from usage as a `MarkupExtension`).
- No direct programmatic callers are visible in the provided source; usage is exclusively via XAML markup.
## 5. Gotchas
- **Hardcoded placeholder:** The `"#stringnotfound#"` string is a literal constant—no external configuration or localization for this fallback exists.
- **No culture override support:** The extension does not expose or respect `StringResources.Culture`; it uses the current UI culture implicitly via `ResourceManager.GetString(string)` (which respects `Thread.CurrentThread.CurrentUICulture`).
- **Inconsistent error formatting:** Missing keys yield `"#stringnotfound# <key>"`, which may be visually jarring in UI (e.g., `"#stringnotfound# MyKey"`). This is likely intentional for debugging but could confuse end users.
- **No caching of resolved values:** Each `ProvideValue` call performs a fresh `ResourceManager.GetString` lookup. While `ResourceManager` caches internally, repeated use in dynamic UI (e.g., data templates) may incur minor overhead.
- **Auto-generated resource class:** `StringResources` is auto-generated; manual edits to `StringResources.Designer.cs` will be overwritten. Resource keys must match those in the corresponding `.resx` file(s).
- **No null-safety for `ResourceManager.GetString`:** The null-coalescing operator (`??`) handles `null` results, but if `ResourceManager` itself is misconfigured (e.g., wrong base name), `GetString` may throw—though this is unlikely in practice.
- **No support for parameterized strings:** The extension only resolves *static* keys. It does not support string formatting (e.g., `InvalidLine` expects `{0}` placeholders to be filled elsewhere, not via this extension).

View File

@@ -0,0 +1,79 @@
---
source_files:
- DataPRO/Modules/ISO/ExtraProperties/View/ExtraPropertiesListView.xaml.cs
generated_at: "2026-04-16T04:39:06.939358+00:00"
model: "Qwen/Qwen3-Coder-Next-FP8"
schema_version: 1
sha256: "35a6fb72ede64411"
---
# View
## Documentation: `ExtraPropertiesListView` Module
---
### **1. Purpose**
`ExtraPropertiesListView` is a WPF user control implementing the `IExtraPropertiesListView` interface to render and interact with a list of extra properties (key-value pairs) in the ISO module. It serves as the view layer in a MVVM pattern, handling UI events (sorting, filtering, selection, editing) and delegating logic to its bound `IExtraPropertiesListViewModel`. The control supports interactive column sorting (via header clicks or text clicks), filtering by column tag, real-time validation and modification tracking during inline editing of property keys and values, and selection synchronization with the view model.
---
### **2. Public Interface**
The class itself is `public partial class ExtraPropertiesListView : IExtraPropertiesListView`. It exposes no *public* methods or properties beyond those defined by the interface `IExtraPropertiesListView` (not shown in source), but its *event handlers* are the primary public-facing behavior surface. All handlers are private `RoutedEventHandler` or `KeyEventHandler` methods wired via XAML (not visible here, but implied by naming and usage).
| Member | Signature | Behavior |
|--------|-----------|----------|
| `ExtraPropertiesListView()` | `public ExtraPropertiesListView()` | Constructor; calls `InitializeComponent()` to load the associated XAML. |
| `GridViewColumnHeaderSearchable_OnSearch` | `private void GridViewColumnHeaderSearchable_OnSearch(object sender, RoutedEventArgs e)` | Extracts `searchTerm` from `e.OriginalSource` and `columnTag` from the `Tag` of the `GridViewColumnHeaderSearchable` sender, then invokes `viewModel.Filter(columnTag, searchTerm)`. |
| `GridViewColumnHeader_OnClick` | `private void GridViewColumnHeader_OnClick(object sender, RoutedEventArgs e)` | Extracts `columnTag` from the `Tag` of the `GridViewColumnHeaderSearchable` sender (or via `Utils.FindChild`), then invokes `vm?.Sort(columnTag, true)`. |
| `ExtraPropertyKeyTextBox_KeyDown` | `private void ExtraPropertyKeyTextBox_KeyDown(object sender, KeyEventArgs e)` | If `DataContext` is `ExtraPropertiesListViewModel` and the `TextBox`s `DataContext` is `IExtraProperty`, calls `vm.MarkModified(iep)`. |
| `ExtraPropertyKeyTextBox_TextChanged` | `private void ExtraPropertyKeyTextBox_TextChanged(object sender, TextChangedEventArgs e)` | Same context checks as above; calls `vm.MarkModified(iep)` and then `vm.Validate(ref notUsed1, ref notUsed2)` (with unused `List<string>` parameters). |
| `ExtraPropertyValueTextBox_KeyDown` | `private void ExtraPropertyValueTextBox_KeyDown(object sender, KeyEventArgs e)` | Same as `ExtraPropertyKeyTextBox_KeyDown`; calls `vm.MarkModified(iep)`. |
| `ExtraPropertyValueTextBox_TextChanged` | `private void ExtraPropertyValueTextBox_TextChanged(object sender, TextChangedEventArgs e)` | Same as `ExtraPropertyKeyTextBox_TextChanged`; calls `vm.MarkModified(iep)` and `vm.Validate(...)`. |
| `ExtraProperties_SelectionChanged` | `private void ExtraProperties_SelectionChanged(object sender, SelectionChangedEventArgs e)` | Collects selected `IExtraProperty` items from the `ListView`, then calls `vm.SetSelection(...)` with the array. |
| `ExtraPropertiesListView_PreviewMouseLeftButtonUp` | `private void ExtraPropertiesListView_PreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e)` | Performs hit-testing to detect clicks on column headers (`TextBlock`, `KeyColumnHeader`, or `ValueColumnHeader`) or descendants; if detected, calls `vm?.Sort(tag, true)` for the corresponding column. Also returns early if the click is on a `ScrollViewer`. |
> **Note**: Column header tags (`KeyColumnHeader.Tag`, `ValueColumnHeader.Tag`) are used as sort keys. Their values are assumed to be strings (e.g., `"Key"`, `"Value"`), inferred from usage in `PreviewMouseLeftButtonUp`.
---
### **3. Invariants**
- **DataContext Contract**: The `DataContext` must implement `IExtraPropertiesListViewModel` (or be `ExtraPropertiesListViewModel`, a concrete implementation). All event handlers cast `DataContext` to this interface or concrete type before use.
- **Item Type Contract**: Selected items in the `ListView` and `TextBox.DataContext` items must be of type `IExtraProperty`. Non-conforming items are silently skipped in `ExtraProperties_SelectionChanged`.
- **Validation Side Effect**: Every `TextChanged` event on key/value `TextBox`es triggers `vm.Validate(...)`, regardless of whether the text actually changed meaningfully.
- **Sorting Trigger**: Sorting is *always* invoked with `ascending: true` (hardcoded), regardless of previous sort state or direction.
- **Hit-Test Robustness**: The `PreviewMouseLeftButtonUp` handler performs multiple hit-tests (visual tree + input hit-test) to reliably detect clicks on headers despite nested visual elements (e.g., `Border`, `Rectangle`).
---
### **4. Dependencies**
#### **External Dependencies (from imports)**:
- `System.Collections.Generic`, `System.Windows.*`: Standard WPF and .NET types.
- `DTS.Common.Controls`: Contains `GridViewColumnHeaderSearchable` (custom control used for searchable column headers).
- `DTS.Common.Interface.ISO.ExtraProperties`: Defines `IExtraPropertiesListView`, `IExtraPropertiesListViewModel`, and `IExtraProperty`.
- `DTS.Common.Utils`: Provides `Utils.FindChild<T>` (used in `GridViewColumnHeader_OnClick` to locate `Tag` from nested elements).
#### **Internal Dependencies**:
- `ExtraProperties.Resources.StringResources`: Used for localized strings `"Key"` and `"Value"` (in `PreviewMouseLeftButtonUp`).
- `ExtraPropertiesListView.xaml`: The associated XAML file (not shown), which defines `ExtraPropertiesListViewLV`, `KeyColumnHeader`, `ValueColumnHeader`, and event bindings.
#### **Depended Upon By**:
- The module likely binds this view to an `ExtraPropertiesListViewModel` instance (or similar) via `DataContext`. No direct callers are visible, but the interface `IExtraPropertiesListView` implies integration into a larger ISO module UI.
---
### **5. Gotchas**
- **Unused `Validate` Parameters**: Both `TextChanged` handlers call `vm.Validate(ref notUsed1, ref notUsed2)` with newly allocated, unused `List<string>` variables. This suggests either incomplete validation reporting or legacy code where validation errors are ignored by the view.
- **Hardcoded Sort Direction**: `vm.Sort(..., true)` is called unconditionally with `ascending: true`. No logic exists to toggle sort direction (e.g., on repeated clicks), which may confuse users expecting standard UI behavior.
- **Redundant Hit-Testing**: The `PreviewMouseLeftButtonUp` handler performs two hit-tests (`VisualTreeHelper.HitTest` and `InputHitTest`) and checks multiple element types (`TextBlock`, `UIElement`, `ScrollViewer`, `KeyColumnHeader`, `ValueColumnHeader`). This complexity hints at prior instability in click detection.
- **Assumed `Tag` Type**: `columnTag` is used directly as a sort key in `vm.Sort(columnTag, ...)`. Its type is inferred from usage (likely `string`), but not enforced or documented in the source.
- **No Null Safety for `vm`**: Multiple calls use `vm?.Sort(...)` or `vm?.Filter(...)`, but `vm.MarkModified(...)` and `vm.SetSelection(...)` do *not* use null-conditional operators. If `DataContext` is null or wrong type, these will throw.
- **`KeyDown` vs `TextChanged` Duplication**: Both `KeyDown` and `TextChanged` handlers call `MarkModified` and `Validate`. This may cause redundant work or validation flicker if both events fire for a single edit (e.g., typing + Enter).
> **None identified from source alone.**
*(Note: While several potential issues are noted above, they are inferred from code structure and behavior—not documented quirks.)*

View File

@@ -0,0 +1,122 @@
---
source_files:
- DataPRO/Modules/ISO/ExtraProperties/ViewModel/ExtraPropertiesListViewModel.cs
generated_at: "2026-04-16T04:38:41.881863+00:00"
model: "Qwen/Qwen3-Coder-Next-FP8"
schema_version: 1
sha256: "d7dc80e73ad032ff"
---
# ViewModel
## **ExtraPropertiesListViewModel Documentation**
---
### **1. Purpose**
`ExtraPropertiesListViewModel` is a Prism-based ViewModel responsible for managing a list of key-value extra properties associated with a data page in the ISO module of the DataPRO application. It provides UI-agnostic data binding, sorting, filtering, clipboard operations (copy/paste), validation, and event-driven integration with the broader application via `IEventAggregator`. It serves as the intermediary between the `IExtraPropertiesListView` UI and the underlying `ExtraPropertyModel` data entities, enabling users to edit, sort, filter, and validate property lists (e.g., metadata, tags, or custom attributes) in a tabular UI.
---
### **2. Public Interface**
All members are defined in `ExtraPropertiesListViewModel`, which implements `IExtraPropertiesListViewModel` (inferred from interface usage). Only explicitly declared public or interface-implementing members are documented.
#### **Properties**
| Property | Type | Description |
|----------|------|-------------|
| `View` | `IExtraPropertiesListView` | Reference to the associated view; set externally. |
| `NotificationRequest` | `InteractionRequest<Notification>` | Prism MVVM Toolkit interaction request for showing non-blocking notifications. |
| `ConfirmationRequest` | `InteractionRequest<Confirmation>` | Prism MVVM Toolkit interaction request for showing confirmation dialogs. |
| `IsBusy` | `bool` | Gets/sets busy state; raises `PropertyChanged` for `"IsBusy"`. |
| `IsMenuIncluded` | `bool` | Gets/sets whether a context menu is included in the view; raises `PropertyChanged` for `"IsMenuIncluded"`. |
| `IsNavigationIncluded` | `bool` | Gets/sets whether navigation controls are included; raises `PropertyChanged` for `"IsNavigationIncluded"`. |
| `IsReadOnly` | `bool` | Gets/sets read-only mode (prevents editing); raises `PropertyChanged` for `"IsReadOnly"`. |
| `AllExtraProperties` | `List<IExtraProperty>` | Full list of all extra properties (including empty trailing row). |
| `ExtraProperties` | `ObservableCollection<IExtraProperty>` | Filtered/sorted view of `AllExtraProperties`, bound to UI. |
| `SelectedProperties` | `IExtraProperty[]` | **Throws `NotImplementedException`** — not implemented. |
| `Page` | `IDataPROPage` | The page this ViewModel is associated with (set via `SetPage`). |
| `Parent` | `object` | Parent object (set via `SetParent`). |
| `IsDirty` | `bool` | Declared but never set; always `false`. |
#### **Events**
| Event | Type | Description |
|-------|------|-------------|
| `PropertyChanged` | `PropertyChangedEventHandler` | Standard `INotifyPropertyChanged` event; raised via `OnPropertyChanged`. |
#### **Methods**
| Method | Signature | Description |
|--------|-----------|-------------|
| `OnPropertyChanged` | `void OnPropertyChanged(string propertyName)` | Raises `PropertyChanged`; if `propertyName == "ExtraProperties"`, publishes `ExtraPropertiesChangedEvent`. |
| `SetPage` | `void SetPage(IDataPROPage page)` | Sets `Page`. |
| `SetParent` | `void SetParent(object parent)` | Sets `Parent`. |
| `Cleanup` | `void Cleanup()` | No-op. |
| `CleanupAsync` | `Task CleanupAsync()` | Returns `Task.CompletedTask`. |
| `Initialize` / `InitializeAsync` | Multiple overloads (e.g., `void Initialize()`, `Task InitializeAsync(object parameter)`) | All are no-ops. |
| `Activated` | `void Activated()` | No-op. |
| `Filter` | `void Filter(object tag, string term)` | Sets search term for `"Key"` or `"Value"` (via `tag` string) and triggers `Filter()`. **Bug**: `"Value"` case incorrectly sets `_searchTermForField[Fields.Key]`. |
| `Sort` | `void Sort(object columnTag, bool columnClick)` | Sets sort field (`"Key"` or `"Value"`) and triggers `Sort(...)` + `Filter()`. |
| `Validate(ref List<string> errors)` | `bool Validate(ref List<string> errors)` | Calls internal `Validate(ref errors, ref warnings)`, returns `true` if no new errors added. |
| `SetExtraProperties` | `void SetExtraProperties(IList<IExtraProperty> properties)` | Replaces `AllExtraProperties` with copies of input properties, appends a new empty `ExtraPropertyModel`, resets sort/filter, and re-applies. |
| `CopySelected` | `void CopySelected()` | Copies selected items (`_selectedItems`) into `AllExtraProperties` (just before the trailing empty row), sorts, filters, and publishes `PageModifiedEvent`. |
| `DeleteSelected` | `void DeleteSelected()` | Removes selected items from both `ExtraProperties` and `AllExtraProperties`; ensures trailing empty row is preserved; publishes `PageModifiedEvent`. |
> **Note**: `SelectedProperties` is declared but throws `NotImplementedException`. Its usage is likely incomplete or deprecated.
---
### **3. Invariants**
- **Trailing Empty Row**: `AllExtraProperties` always ends with a single empty `ExtraPropertyModel` instance (key/value both empty/whitespace). This is enforced in:
- `SetExtraProperties` (adds one after copying input),
- `MarkModified` (adds one if last item modified),
- `DeleteSelected` (re-adds one if deleted).
- **Filtering Logic**: Empty rows (both key and value whitespace) are *always* included in `ExtraProperties` regardless of search term.
- **Sorting Behavior**: Empty rows are *always* sorted to the *bottom* of `AllExtraProperties` (via `PropertyComparer.Compare`).
- **Validation Rules**:
- Duplicate non-empty keys → error.
- Non-empty keys with empty/whitespace values → warning.
- **Event Subscription Hack**: `_bAddListeners` static flag ensures only the *second* instantiation of this ViewModel subscribes to `TextPastedEvent`. First instantiation (likely during app startup) skips subscription.
---
### **4. Dependencies**
#### **Imports / Dependencies Used**
- **Prism Framework**:
- `Prism.Events.IEventAggregator`, `Prism.Regions.IRegionManager`
- `Prism.Interactivity.InteractionRequest` (`Notification`, `Confirmation`)
- **Unity DI Container**: `IUnityContainer`
- **DataPRO Common Libraries**:
- `DTS.Common.Events.*` (e.g., `TextPastedEvent`, `PageModifiedEvent`, `PageSelectionChanged`)
- `DTS.Common.Interface.*` (`IDataPROPage`, `IExtraProperty`, `IExtraPropertiesListView`, `IExtraPropertiesListViewModel`)
- `DTS.Common.Utilities.NaturalStringComparer` (used in `PropertyComparer`)
- **Model Layer**:
- `ExtraProperties.Model.ExtraPropertyModel` (concrete implementation of `IExtraProperty`)
- **Resources**:
- `ExtraProperties.Resources.StringResources` (for error/warning messages)
#### **Consumers (Inferred)**
- `ExtraPropertiesListViewModel` is instantiated via Unity DI (due to `[PartCreationPolicy(CreationPolicy.Shared)]` and constructor injection).
- Likely consumed by `IExtraPropertiesListView` (WPF view) bound to this ViewModel.
- Subscribes to events published by other modules (e.g., `TextPastedEvent` from clipboard operations).
- Publishes `PageModifiedEvent`, `ExtraPropertiesChangedEvent`, and `PageSelectionChanged`.
---
### **5. Gotchas**
- **`SelectedProperties` is unimplemented**: Throws `NotImplementedException`. Any code expecting this property will crash.
- **`Filter` bug**: When filtering by `"Value"`, it incorrectly assigns the term to `_searchTermForField[Fields.Key]` instead of `Fields.Value`.
- **`_bAddListeners` hack**: Static boolean `_bAddListeners` controls `TextPastedEvent` subscription. First instantiation *does not* subscribe; only the second (and subsequent) do. This is fragile and may break if instantiation order changes.
- **`IsDirty` never set**: Property is declared but never assigned; always `false`.
- **`Sort`/`Filter` order**: `Sort` is called *before* `Filter` in `Filter(object, string)` and `Sort(object, bool)`, but `Filter()` is called *after* `Sort(...)` in `Paste`, `CopySelected`, and `DeleteSelected`. This is consistent but non-obvious.
- **Paste behavior**: `Paste` modifies `ExtraProperties` *in-place* (by index), but `AllExtraProperties` is not updated until `Sort`/`Filter` are called. This may cause inconsistency if accessed mid-operation.
- **Case sensitivity**: Sorting and filtering use `ToUpper()` + `NaturalStringComparer`, which may not match user expectations for case-insensitive comparisons (e.g., `"a"` and `"A"` sort as equal, but `"ä"` vs `"a"` may behave unexpectedly).
- **No null checks in `PropertyComparer`**: While `left == right` is handled, `a`/`b` could be `null` after assignment (e.g., if `left`/`right` are non-null but one becomes `null` after `SortAscending` swap logic). `null` checks exist but may not cover all paths.
- **`MarkModified` side effect**: Appends a new empty row *only* if the modified item is the last in `ExtraProperties`, but uses `ExtraProperties.Last()` — which is the *filtered* list — not `AllExtraProperties`. This may cause inconsistent behavior if filtering is active.
---
*Documentation generated from `ExtraPropertiesListViewModel.cs` (DataPRO/Modules/ISO/ExtraProperties/ViewModel/ExtraPropertiesListViewModel.cs).*

View File

@@ -0,0 +1,78 @@
---
source_files:
- DataPRO/Modules/InstallerCustomActions/Common/PreviousInstall.cs
generated_at: "2026-04-16T04:43:42.723638+00:00"
model: "Qwen/Qwen3-Coder-Next-FP8"
schema_version: 1
sha256: "d9773bfec96b878e"
---
# Common
### **Purpose**
This module provides utilities for detecting and retrieving information about previously installed versions of the *DataPRO* application during Windows Installer custom actions. Specifically, it locates the most recent *lower* version of DataPRO installed on the system (i.e., older than the version being installed) by querying the Windows Registry under `HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall` (and fallback to `Components`), enabling upgrade or migration logic in the installer. It is intended for use in Windows Installer custom actions to support version-aware installation scenarios.
---
### **Public Interface**
#### `static string GetMostRecentlyInstalledSubKeyName(Version installingVersion, out string mostRecentlyInstalledLowerVersion)`
- **Behavior**: Scans the registry under the `Uninstall` key (path defined by `Settings.Default.RegistrySoftwareInstalledProducts`) for installed products whose display name matches `Settings.Default.RegistryDataPRO`. Among those with a version *strictly less than* `installingVersion`, it returns the registry subkey name (`ProductCode` or similar identifier) of the *most recent* (i.e., highest) version.
- **Output parameter `mostRecentlyInstalledLowerVersion`**: Contains the string representation (e.g., `"1.2.3.4"`) of the highest version found that is less than `installingVersion`, or `string.Empty` if none found.
- **Returns**: The registry subkey name (e.g., `"DataPRO-abc123"`) of the most recent lower version, or `string.Empty` if no matching product is found or registry access fails.
#### `static string GetMostRecentlyInstalledPath(string mostRecentlyInstalledSubKeyName)`
- **Behavior**: Given a registry subkey name (typically obtained from `GetMostRecentlyInstalledSubKeyName`), this method attempts to resolve the installation path (`InstallLocation`) of that product.
- **Logic**:
1. First searches in `RegistrySoftwareInstalledProducts` (`Uninstall`), looking for the matching subkey and retrieving `InstallLocation` (`Settings.Default.RegistryInstallLocation`).
2. If not found, falls back to searching in `RegistrySoftwareInstalledComponents`, where the value named `mostRecentlyInstalledSubKeyName` is expected to hold a full path ending with `Settings.Default.RegistryDataPROExeConfig` (e.g., `"DataPRO.exe.config"`), from which the directory is extracted.
3. Appends `Settings.Default.RegistryDataPRO + "\\"` to the path *if* the path contains `Settings.Default.DTSSuite`, to ensure correct nesting (e.g., for suite-based installations).
- **Returns**: The resolved installation directory path (e.g., `"C:\Program Files\DTSSuite\DataPRO\\"`), or `string.Empty` if not found or invalid.
#### `static bool IsGreaterThan(this Version leftString, Version rightString)`
- **Behavior**: Extension method for `System.Version`. Returns `true` if `leftString` is greater than `rightString` (i.e., `leftString.CompareTo(rightString) > 0`).
#### `static bool IsLessThan(this Version leftString, Version rightString)`
- **Behavior**: Extension method for `System.Version`. Returns `true` if `leftString` is less than `rightString` (i.e., `leftString.CompareTo(rightString) < 0`).
---
### **Invariants**
- Only products with `DisplayName` equal to `Settings.Default.RegistryDataPRO` are considered.
- Only versions *strictly less than* the `installingVersion` are considered in `GetMostRecentlyInstalledSubKeyName`.
- The method `GetMostRecentlyInstalledSubKeyName` returns the *highest* version among qualifying products (not the most recently *installed* chronologically, but the highest version number).
- Registry access is performed exclusively on `RegistryHive.LocalMachine` with `RegistryView.Registry64`.
- Paths retrieved via `GetMostRecentlyInstalledPath` are normalized by stripping the trailing `Settings.Default.RegistryDataPROExeConfig` (e.g., `"DataPRO.exe.config"`) when sourced from the `Components` key.
- If a registry value is missing or evaluates to `"-1"` (as a string), it is treated as invalid and skipped.
---
### **Dependencies**
- **External**:
- `Microsoft.Win32.RegistryKey` (for registry access).
- `System.Version` (for version comparison).
- `System.Diagnostics.EventLog` (used internally for logging in `GetMostRecentlyInstalledPath`).
- **Internal**:
- `Common.Properties.Settings.Default`:
- `RegistrySoftwareInstalledProducts` (e.g., `"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall"`).
- `RegistrySoftwareInstalledComponents` (e.g., `"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Component Based Installation\\Components"`).
- `RegistryInstallProperties` (e.g., `"InstallProperties"` subkey).
- `RegistryDisplayName` (e.g., `"DisplayName"`).
- `RegistryDisplayVersion` (e.g., `"DisplayVersion"`).
- `RegistryInstallLocation` (e.g., `"InstallLocation"`).
- `RegistryDataPRO` (e.g., `"DataPRO"`).
- `RegistryDataPROExeConfig` (e.g., `"DataPRO.exe.config"`).
- `DTSSuite` (e.g., `"DTSSuite"`).
- **Used by**: Windows Installer custom actions (not visible in source, but implied by namespace `Installer.Common` and method naming).
---
### **Gotchas**
- **Hardcoded fallback to `"-1"`**: Registry values are read with `RegistryValueOptions.None`, and if the result is `"-1"` (string), it is treated as invalid. This assumes `"-1"` is used as a sentinel for missing/invalid values—a convention not guaranteed by Windows Installer or .NET.
- **No error handling for registry access**: If `OpenSubKey` or `GetValue` throws (e.g., due to permissions or corruption), the exception propagates unhandled. Logging in `GetMostRecentlyInstalledPath` uses `EventLog`, but only for informational paths, not errors.
- **Assumes 64-bit registry view only**: Uses `RegistryView.Registry64`, which may miss 32-bit installations on 64-bit systems (though `HKEY_LOCAL_MACHINE\SOFTWARE` redirection would apply).
- **Ambiguity in `mostRecentlyInstalledSubKeyName`**: The term "most recently installed" in the method name is misleading—it actually returns the *highest version*, not the one with the latest install timestamp.
- **Path normalization quirk**: The suffix stripping in `GetMostRecentlyInstalledPath` assumes `mostRecentlyInstalledSubKeyName` ends *exactly* with `RegistryDataPROExeConfig`. If the value is malformed or truncated, substring logic may yield incorrect paths.
- **No fallback for missing `InstallLocation`**: If `InstallLocation` is absent in `Uninstall`, and the `Components` lookup fails or yields an invalid path, the method returns `string.Empty` without indicating *why*.
- **Event log source must exist**: `log.Source = "DataPROInstaller"` assumes the event source is pre-registered; otherwise, `WriteEntry` may throw on first use (though this is rare in installer contexts).
- **No handling for `Version` parsing failures**: If `RegistryDisplayVersion` contains a non-parsable string (e.g., `"1.2.3-beta"`), `new Version(strThisVersion)` throws `FormatException`.

View File

@@ -0,0 +1,90 @@
---
source_files:
- DataPRO/Modules/InstallerCustomActions/Common/Properties/AssemblyInfo.cs
- DataPRO/Modules/InstallerCustomActions/Common/Properties/Settings.Designer.cs
generated_at: "2026-04-16T04:44:41.257169+00:00"
model: "Qwen/Qwen3-Coder-Next-FP8"
schema_version: 1
sha256: "3a215b4dad8b4fc8"
---
# Properties
## Documentation Page: `Installer.Common` Module
---
### 1. **Purpose**
This module (`Installer.Common`) is a shared .NET assembly containing configuration and metadata constants used across custom actions in the DataPRO Windows Installer infrastructure. Its primary role is to centralize registry path keys, value names, and application identifiers used during installation, upgrade, and uninstallation logic—specifically for querying and interacting with Windows Installer (MSI) metadata stored in the registry. It does *not* contain executable installer logic itself but provides stable, versioned configuration values to ensure consistency across installer components.
---
### 2. **Public Interface**
The module exposes **no public types** (classes, methods, or properties) beyond the auto-generated settings class `Common.Properties.Settings`. All other types are internal to the assembly (e.g., `AssemblyInfo` attributes are compile-time metadata, not runtime API surface).
#### `Common.Properties.Settings`
- **Type**: `internal sealed partial class Settings : ApplicationSettingsBase`
- **Access**: Public static property `Settings.Default` (read-only)
- **Behavior**: Provides application-scoped configuration values for registry paths and display names used during MSI operations.
##### Public Properties (read-only, application-scoped):
| Property Name | Type | Default Value | Description |
|---------------|------|---------------|-------------|
| `RegistrySoftwareInstalledProducts` | `string` | `"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\S-1-5-18\\Products"` | Registry path where MSI stores installed product data (per-user SID `S-1-5-18` = LocalSystem context). |
| `RegistryInstallProperties` | `string` | `"InstallProperties"` | Subkey name under a product path where install metadata resides. |
| `RegistryDisplayName` | `string` | `"DisplayName"` | Registry value name for the user-facing product name. |
| `RegistryDataPRO` | `string` | `"DataPRO"` | Subkey name used to identify DataPRO-specific registry entries (e.g., under `InstallProperties`). |
| `RegistryDisplayVersion` | `string` | `"DisplayVersion"` | Registry value name for the installed version string. |
| `RegistrySoftwareInstalledComponents` | `string` | `"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\S-1-5-18\\Components"` | Registry path where MSI stores component-to-product mapping. |
| `RegistryDataPROExeConfig` | `string` | `"DataPRO.exe.config"` | Registry value name (likely under install location) referencing the app config file. |
| `RegistryInstallLocation` | `string` | `"InstallLocation"` | Registry value name for the installation directory path. |
| `DTSSuite` | `string` | `"DTS.Suite"` | Identifier for the DTS suite (possibly used for feature grouping or upgrade detection). |
> **Note**: All properties are `ApplicationScopedSettingAttribute`, meaning their values are fixed at compile time and cannot be modified at runtime.
---
### 3. **Invariants**
- The registry paths use the **LocalSystem SID (`S-1-5-18`)** explicitly, implying these settings are intended for use in contexts where the installer runs with elevated (system) privileges (e.g., custom actions executing as `System`).
- Registry paths and value names are **hardcoded strings**—no dynamic resolution or runtime computation occurs.
- The `Settings.Default` instance is **thread-safe** (via `ApplicationSettingsBase.Synchronized`), but only for reading values; no write operations are supported (all settings are `ApplicationScoped`).
- The `RegistryDataPRO` value (`"DataPRO"`) is used as a *key* or *subkey name*, not a value—suggesting it may be part of a hierarchy like:
`...\Products\<ProductCode>\InstallProperties\DataPRO\...`
- Version information is **not exposed** via this module (assembly version is `1.0.0.0` but not used in logic).
---
### 4. **Dependencies**
#### Dependencies *of* this module:
- `System.Configuration` (for `ApplicationSettingsBase`, `ApplicationScopedSettingAttribute`, etc.)
- `System.Runtime.CompilerServices`, `System.CodeDom.Compiler`, `System.Diagnostics` (for attributes only)
#### Dependencies *on* this module:
- **Inferred consumers**: Other modules in `DataPRO/Modules/InstallerCustomActions/` (e.g., custom action DLLs) that need to read MSI registry metadata.
Example usage pattern (not in source, but implied):
```csharp
string productsPath = Common.Properties.Settings.Default.RegistrySoftwareInstalledProducts;
```
- Likely used in conjunction with Windows Installer APIs (e.g., `MsiEnumProducts`, `MsiGetProductInfo`) or direct registry access (`Microsoft.Win32.Registry`).
---
### 5. **Gotchas**
- **Hardcoded SID**: The use of `S-1-5-18` (LocalSystem) may break if installer logic runs under a different context (e.g., per-user install with non-elevated user). No fallback or SID resolution is present.
- **No versioning in settings**: The `AssemblyVersion` is `1.0.0.0` but the settings themselves are not versioned—changing a registry path here could silently break existing upgrade logic if not coordinated with installer versioning.
- **Auto-generated file warning**: `Settings.Designer.cs` explicitly warns that manual changes will be lost on regeneration (e.g., via Visual Studio designer). This implies the settings are managed in a `.settings` designer file (not visible here).
- **No null-safety**: Property getters return the raw registry value—no validation or defaulting is done. If a registry value is missing, callers must handle `null`.
- **Ambiguous `DTSSuite` usage**: The purpose of `"DTS.Suite"` is unclear from this module alone—it may be used as a feature ID, upgrade code prefix, or registry grouping key, but no evidence of its usage exists in the provided files.
> **None identified from source alone.** (Applied only if no issues found—here, several are inferred from structure and naming.)
---
**End of Documentation**

View File

@@ -0,0 +1,93 @@
---
source_files:
- DataPRO/Modules/InstallerCustomActions/DBConfiguration/MigrationStatus.cs
- DataPRO/Modules/InstallerCustomActions/DBConfiguration/DBConfig.cs
- DataPRO/Modules/InstallerCustomActions/DBConfiguration/CommonUtilities.cs
- DataPRO/Modules/InstallerCustomActions/DBConfiguration/DBTypeChoice.Designer.cs
generated_at: "2026-04-16T04:44:09.733583+00:00"
model: "Qwen/Qwen3-Coder-Next-FP8"
schema_version: 1
sha256: "34f445ff6d14ccf5"
---
# Documentation: DBConfiguration Module
## 1. Purpose
This module provides database configuration and initialization logic for the DataPRO application during installation and migration scenarios. It serves as a standalone executable (`DBConfiguration.exe`) that handles local SQL Server Express LocalDB instance management—including creation, attachment, and detachment of databases (`DataPRO` and `ISO`)—and supports multiple initialization modes (e.g., TSR AIR, Crash, Aero, migration from previous local DB). It also exposes a minimal `MigrationStatus` class for conveying progress during operations. The module is invoked by the installer (via command-line arguments) or standalone (for debugging/testing), and integrates with Windows Forms for interactive configuration when UI is enabled.
## 2. Public Interface
### `DBConfiguration.MigrationStatus`
- **`StatusTypes` enum**: Defines three status categories: `Status`, `MigrationStatus`, and `SourceDb`.
- **`StatusType` property (`StatusTypes`)**: Indicates the type of status being reported.
- **`StatusText` property (`string`)**: Contains the human-readable status message.
### `DBConfiguration.DBConfig`
- **`Main(string[] args)`**: Static entry point. Parses command-line arguments to determine execution mode (installer vs. standalone, UI vs. silent), and dispatches to either `DBTypeChoice` form (interactive) or `CommonUtilities.InitializeDbToTSRAIR()` (TSR AIR initialization). In installer mode, it hides the console window; in standalone command mode, it shows it.
### `DBConfiguration.CommonUtilities`
- **`InitializeDbToTSRAIR(string targetDir)`**: Initializes the database to TSR AIR settings. Performs the following sequence:
1. Calls `ConfigInitializationHelper.UpdateTSRAIRAppSettings(targetDir, true)` (not shown in source; assumed external).
2. Calls `Attach(targetDbDir, scriptsDir)` to attach existing databases.
3. Calls `DbOperations.Connection.Initialize(InitializationTypes.TSRAIR, targetDir)` (assumed external).
4. Calls `Detach(...)` to detach the migrated databases.
5. Shows a success message box.
- **`Attach(string targetDbDir, string scriptsDir)`**: Logs and sets migration status, then calls `InstallDatabase(targetDbDir, "DataPRO", scriptsDir)`.
- **`InstallDatabase(string dBdir, string dbName, string scriptsDir)`**: Performs full LocalDB instance setup:
- Sets connection properties (`Server = Settings.Default.LocalDbDataPROInstance`, `NTLMAuthentication = true`, `usingCentralizedDB = false`, `usingMSSQL = true`).
- Executes SQL LocalDB commands via `ProcessSqlLocalDbCommand(...)` to stop, delete, create, and start the LocalDB instance.
- Attaches `DataPRO.mdf` and `ISO.mdf` databases using `AttachOrDetachDatabase(...)` with `Settings.Default.AttachDBsbat`.
- Returns any error output from SQL commands.
- **`Detach(string sourceDbName, string targetDbDir, string scriptsDir)`**: Detaches the `sourceDbName` (typically `"DataPRO"`) and `ISO` databases using `AttachOrDetachDatabase(...)` with `Settings.Default.DetachDBsbat`. Logs status and shows warnings if errors occur.
- **`SetMigrationStatus(string migrationStatus, bool output = false)`**: Creates and returns a `MigrationStatus` object with `StatusType = StatusTypes.MigrationStatus` and the given `migrationStatus` text. Optionally writes to `Console.WriteLine`.
- **`ProcessSqlLocalDbCommand(string command)`**: Executes a command (e.g., `"start v14.0"`, `"create v14.0"`) against SQL Server LocalDB by:
- Resolving the LocalDB installation path via `GetSqlServerLocalDBPath()`.
- Invoking `sqllocaldb.exe` via `SqlCommandProcessor(...)`.
- Returns non-empty string on error (e.g., `"localdb not installed"`).
- **`GetSqlServerLocalDBPath()`**: Queries the registry (`HKLM\SOFTWARE\Microsoft\Microsoft SQL Server\LocalDB\Installed Versions`) to find the highest installed LocalDB version with a valid `SqlUserInstance.dll` path. Returns the path to the `Tools` directory (e.g., `C:\Program Files\Microsoft SQL Server\140\Tools\`).
- **`AttachOrDetachDatabase(string scriptsDir, string dbName, string sqlDbFileName, string sqlLogFileName, string attachOrDetach)`**: Invokes a batch script (e.g., `AttachDBs.bat`) via `BatchCommandProcessor(...)`. The batch script is expected to use `sqlcmd.exe` to execute `CREATE DATABASE ... FOR ATTACH`.
- **`SqlCommandProcessor(string sqlLocalDbExeFileName, string command)`**: Executes a command-line process (`sqllocaldb.exe`) asynchronously, capturing output via `OutputHandler`. Returns captured output if non-empty.
- **`BatchCommandProcessor(string batchFileName, string dbName, string sqlDbFileName, string sqlLogFileName, string fullSqlcmdPath)`**: Executes a batch file with arguments: `dbName`, quoted `dbFileName`, quoted `logFileName`, and quoted `sqlcmd.exe` path. Uses same async output capture mechanism.
> **Note**: `SetStatus(string status, bool output = false)` is private and used internally; not part of the public interface.
## 3. Invariants
- **LocalDB instance name**: Hardcoded to `"DataPRO"` in `InstallDatabase` and `Attach`. Cannot be changed during TSR AIR Go installation.
- **Database files**: Always expects `DataPRO.mdf`/`DataPRO.ldf` and `ISO.mdf`/`ISO.ldf` in `targetDbDir`.
- **Authentication**: Uses NTLM authentication (`DbOperations._usingNTLMAuthentication = true`) for all LocalDB operations.
- **Centralized DB flag**: `DbOperations._usingCentralizedDB` is explicitly set to `false` during LocalDB operations.
- **Console visibility**: In installer mode (`args.Length > 0` and `noUI != "STANDALONECMD"`), the console window is hidden (`SW_HIDE`). In standalone command mode (`args.Length == 2`), it is shown (`SW_SHOW`).
- **TSR AIR mode**: When `tsrAirGo == true`, the UI (`DBTypeChoice`) is skipped entirely.
- **Registry query**: Only queries 64-bit registry view (`RegistryView.Registry64`).
## 4. Dependencies
### External Dependencies (from imports/includes):
- `System`, `System.Windows.Forms`, `System.Diagnostics`, `System.IO`, `System.Text`, `Microsoft.Win32`
- `DTS.Common.Storage`, `DTS.Common.Enums`, `DTS.Common.Utilities`, `DTS.Common.Utils.Database`
- `DBConfiguration.Properties` (for `Settings.Default`)
### Internal Dependencies:
- `DBTypeChoice` (Windows Form class, defined in `DBTypeChoice.Designer.cs` and implied `DBTypeChoice.cs` not provided).
- `DbOperations` (static class with `Connection` and `_usingCentralizedDB`, `_usingMSSQL`, `_usingNTLMAuthentication` fields; not shown but referenced).
- `ConfigInitializationHelper` (static class with `UpdateTSRAIRAppSettings(...)` method; not shown).
- `Settings.Default`: Used extensively for strings (e.g., `LocalDbFolder`, `ScriptsFolder`, `LocalDbDataPROInstance`, `Mdf`, `LogLdf`, `AttachDBsbat`, `DetachDBsbat`, `StopDataProInstance`, `DeleteDataProInstance`, `CreateDataProInstance`, `StartDataProInstance`, `ISO`, `SqlServerLocalDbNotInstalled`, `Warning`, `InstallationStatus`, `TSRAIRGoInstallationCompletedSuccessfully`, `AttachingPrevLocalDb`, `DetachingLocalMigratedDb`, `DetachingLocalISODb`, `AttachDBsbat`, `DetachDBsbat`, `RegistrySoftwareMicrosoftMicrosoftSQLServerLocalDBInstalledVersions`, `InstanceAPIPath`, `SqlUserInstanceDll`, `LocalDB`, `Tools`, `SqlLocalDBExe`).
### Dependencies on this module:
- The installer (likely WiX or similar) invokes `DBConfig.Main(...)` with specific command-line arguments during installation.
- Other modules may rely on `CommonUtilities` for database setup logic (though only `InitializeDbToTSRAIR` is called from `DBConfig`).
## 5. Gotchas
- **Hardcoded database name**: `"DataPRO"` is hardcoded in `InstallDatabase` and `Attach`. Changing this requires updating multiple locations.
- **Registry path assumptions**: `GetSqlServerLocalDBPath()` assumes a specific registry path (`...\LocalDB\Installed Versions`) and that subkeys are version numbers (e.g., `"11.0"`, `"14.0"`). Failure to parse a subkey as a double silently skips it.
- **`SqlUserInstanceDll` check**: Only considers versions where the `InstanceAPIPath` value ends with `"SqlUserInstance.dll"`. If the path format changes, LocalDB resolution fails.
- **Console window toggling**: The console window is hidden/shown based on `args.Length` and `noUI` value. Misunderstanding the argument semantics may lead to unexpected UI behavior (e.g., window flashing).
- **`tsrAirGo` override**: When `tsrAirGo == true`, the entire `DBTypeChoice` form is skipped—even if `noUI != "TRUE"`. This may conflict with expectations if `noUI` is `"TRUE"` but `tsrAirGo` is also set.
- **Error handling**: Errors from SQL commands are returned as strings and displayed via `MessageBox.Show(...)`, but the method continues execution (e.g., `InstallDatabase` proceeds even if `ProcessSqlLocalDbCommand` returns non-empty). This may leave the system in a partially configured state.
- **`sb` static field**: `CommonUtilities.sb` is a static `StringBuilder` used for output capture. Concurrent calls to `SqlCommandProcessor` or `BatchCommandProcessor` (if ever introduced) would interfere with each other.
- **Missing implementation details**: Key dependencies like `DbOperations.Connection.Initialize(...)`, `ConfigInitializationHelper.UpdateTSRAIRAppSettings(...)`, and `Settings.Default` values are referenced but not defined in the provided source. Their behavior is inferred but not verifiable here.
- **No rollback logic**: If `Attach` succeeds but `Detach` fails, there is no cleanup or error recovery—databases remain attached until manually detached.
- **`ProcessSqlLocalDbCommand` return value**: Returns non-empty string on error, but callers treat *any* non-empty string as a warning (via `MessageBox.Show`) and continue. This may mask critical failures.

View File

@@ -0,0 +1,46 @@
---
source_files:
- DataPRO/Modules/InstallerCustomActions/DBConfiguration/Properties/AssemblyInfo.cs
- DataPRO/Modules/InstallerCustomActions/DBConfiguration/Properties/Resources.Designer.cs
generated_at: "2026-04-16T04:44:51.764845+00:00"
model: "Qwen/Qwen3-Coder-Next-FP8"
schema_version: 1
sha256: "f9b9065d14e86b8a"
---
# Properties
## Documentation: `DBConfiguration` Assembly
### 1. Purpose
This module is a .NET assembly named **DBConfiguration**, part of the `DataPRO/Modules/InstallerCustomActions` component hierarchy. Its role is to support database-related configuration tasks during Windows Installer custom actions—though the provided source files contain only metadata and auto-generated resource infrastructure, not the actual implementation logic. As such, this assembly serves as a placeholder or container for installer-time database setup operations (e.g., schema creation, connection string validation, or service account configuration), with the actual behavior residing in other modules or files not included here.
### 2. Public Interface
**No public API surface is exposed by this assembly.**
- The `AssemblyInfo.cs` file defines assembly-level attributes (e.g., `AssemblyTitle`, `AssemblyVersion`) but no types or methods.
- The `Resources.Designer.cs` file defines an internal, auto-generated class `DBConfiguration.Properties.Resources`. This class is **not public** (`internal class Resources`) and provides only strongly-typed resource accessors (`ResourceManager`, `Culture`) for localized strings. It does not expose any functional APIs beyond resource lookup infrastructure.
> ⚠️ **Note**: The actual installer custom action classes (e.g., classes inheriting from `System.Configuration.Install.Installer`) or database configuration logic are not present in the provided files and must be located elsewhere in the codebase.
### 3. Invariants
- The assembly is **not COM-visible** (`[assembly: ComVisible(false)]`), meaning its types cannot be accessed via COM interop unless explicitly exposed through other means (e.g., public classes with `[ComVisible(true)]`, which are absent here).
- The assembly version is fixed at `1.0.0.0` for both `AssemblyVersion` and `AssemblyFileVersion`.
- The `Resources` class is auto-generated and must be regenerated if the underlying `.resx` file changes (per the header comment in `Resources.Designer.cs`). Manual edits to `Resources.Designer.cs` will be overwritten.
- The `Guid` attribute (`a5087f45-0949-4e27-b367-ccb6556fc68d`) uniquely identifies this assemblys type library for COM registration purposes, though COM visibility is disabled.
### 4. Dependencies
- **Runtime dependencies**:
- `System.dll` (implicit, via `System.Reflection`, `System.Runtime.InteropServices`, `System.Resources`, `System.Globalization`).
- `System.Core.dll` (likely, for `System.CodeDom.Compiler`, `System.ComponentModel`, `System.Diagnostics`).
- **Internal dependencies**:
- This assembly likely depends on other modules in `DataPRO/Modules/InstallerCustomActions` (e.g., shared installer utilities or database access libraries), but no explicit references are declared in the provided files.
- **Consumers**:
- Presumably consumed by the Windows Installer (via custom action DLL registration) or by the `DataPRO` setup project.
- May be referenced by other `DataPRO` modules requiring database configuration during installation.
### 5. Gotchas
- **No functional code in provided files**: The assemblys purpose is inferred from naming and directory structure, but the actual database configuration logic is absent. Developers should not expect to find custom action entry points (e.g., `Install`, `Commit`, `Rollback`) here.
- **Resource class is internal**: While `Resources` provides localized string support, it is `internal`, meaning external consumers (e.g., other assemblies) cannot directly access it. Localization is likely used only within this assemblys implementation (which is not visible here).
- **Versioning rigidity**: The `AssemblyVersion` is hardcoded to `1.0.0.0` with no wildcard (`*`), meaning build/revision numbers cannot auto-increment. This may complicate deployment tracking if not managed externally.
- **Auto-generated code warning**: `Resources.Designer.cs` explicitly warns that manual changes will be lost on regeneration. Any localization adjustments must be made in the corresponding `.resx` file.
- **None identified from source alone.**

View File

@@ -0,0 +1,82 @@
---
source_files:
- DataPRO/Modules/InstallerCustomActions/LocalSQLDB/LocalDBPreparation.cs
- DataPRO/Modules/InstallerCustomActions/LocalSQLDB/LocalDBPrepare.cs
generated_at: "2026-04-16T04:44:18.702457+00:00"
model: "Qwen/Qwen3-Coder-Next-FP8"
schema_version: 1
sha256: "53877159cb79be1f"
---
# LocalDB Preparation Module Documentation
## 1. Purpose
This module implements a Windows Installer custom action responsible for preparing a local SQL Server Express LocalDB instance during installation of the DataPRO application. Specifically, it determines whether the installation targets a *local* or *centralized* database configuration, and if local, copies the default database files (`DataPRO.mdf` and `DataPRO.ldf`) from a previously installed version (if available) or from the current installation directory to a new location named according to the configured database name. It ensures the database files are present before the main installation completes, enabling the application to connect to a pre-populated local database.
## 2. Public Interface
### `LocalDBPreparation.Main(string[] args)`
- **Signature**: `static void Main(string[] args)`
- **Behavior**: Entry point for the custom action executable. Parses the first two arguments as `targetDir` (installation directory) and `productVersion` (version of the product being installed). Instantiates `LocalDBPrepare` with these values and invokes `PrepareDB()`. On any exception, displays an error message via `MessageBox.Show` and rethrows an exception to abort the installation.
### `LocalDBPrepare.PrepareDB()`
- **Signature**: `public bool PrepareDB()`
- **Behavior**: Orchestrates the database preparation logic:
1. Reads the new installations configuration file to determine the database type (`DBType`) and database name (`DBName`).
2. If `DBType` is `Centralized`, returns `false` immediately (no local DB preparation needed).
3. If the configured `DBName` matches the default (`Settings.Default.DataPRO`), returns `true` without copying (no rename needed).
4. Otherwise, constructs source and destination paths for `.mdf` and `.ldf` files.
5. Attempts to locate the most recently installed lower version using `Common.PreviousInstall.GetMostRecentlyInstalledSubKeyName` and `GetMostRecentlyInstalledPath`. If no prior version is found, returns `false`.
6. Copies `DataPRO.mdf` and `DataPRO.ldf` from the source path to the destination path (overwriting existing files).
7. Returns `true` upon successful copy.
> **Note**: The method is *not* thread-safe, as it uses static fields (`_targetDir`, `_installingVersion`) to store state.
## 3. Invariants
- **Configuration File Path**: The configuration file is expected at `<targetDir><RegistryDataPROExe>` (e.g., `targetDir + "DataPRO.exe"`), where `RegistryDataPROExe` is a string constant from `Settings.Default`.
- **Database File Naming**: Database files are always named `<DBName>.mdf` and `<DBName>.ldf`, where `DBName` is read from config or defaults to `Settings.Default.DataPRO`.
- **LocalDB Folder**: Database files reside in a subfolder named by `Settings.Default.LocalDbFolder` (e.g., `"LocalDB"`).
- **File Extension Constants**: `.mdf` and `.ldf` extensions are defined in `Settings.Default.Mdf` and `Settings.Default.LogLdf`, respectively.
- **DBType Parsing Fallback**: If `DBType` cannot be parsed from config, it defaults to `DbType.Local`.
- **Copy Source Priority**: If a prior installation exists, source files are taken from the prior installation directory; otherwise, they are taken from the current `targetDir`.
- **Return Value Semantics**:
- `true`: Local DB preparation completed successfully (including no-op case where DB name matches default).
- `false`: Either centralized DB mode, no prior installation found (when renaming is needed), or an early exit condition.
## 4. Dependencies
### External Dependencies (from imports):
- `System.Configuration` (`ConfigurationManager`, `SettingElementCollection`, etc.)
- `System.Data.SqlClient` (imported but *not used* in current code)
- `Microsoft.Win32` (likely for registry access via `Common.PreviousInstall`)
- `System.Security.Principal` (imported but *not used*)
- `System.Windows.Forms` (used only for `MessageBox.Show` in `Main`)
- `System.Threading` (imported but *not used*)
- `LocalSQLDB.Properties.Settings` (strongly-typed settings from `Settings.Designer.cs`)
### Internal Dependencies:
- `Common.PreviousInstall` (static class, not shown in source) — provides:
- `GetMostRecentlyInstalledSubKeyName(Version, out string)`
- `GetMostRecentlyInstalledPath(string subKeyName)`
- `Settings.Default` (strongly-typed settings) — relies on:
- `DataPRO`, `LocalDbFolder`, `Mdf`, `LogLdf`, `RegistryDataPROExe`, `ApplicationSettings`
### What Depends on This Module:
- Windows Installer (via custom action executable `LocalSQLDB.exe`, presumably invoked during install sequence).
- The DataPRO installer project (not shown) — this module is part of the `InstallerCustomActions` folder.
## 5. Gotchas
- **Static State in `LocalDBPrepare`**: Fields `_targetDir` and `_installingVersion` are `static`, meaning if multiple instances of `LocalDBPrepare` are created (e.g., in tests or concurrent invocations), they will share state — a potential source of race conditions or incorrect behavior. The class is instantiated once per run, but the design is fragile.
- **Hardcoded Default DB Name**: Logic assumes `Settings.Default.DataPRO` is the canonical default database name; renaming only occurs if the configured name differs.
- **Uncommented Code Paths**: Several lines of code are commented out (e.g., `//if (_newSettingsDictionary[ConfigSettings.DBCopy.ToString()])`), suggesting incomplete refactoring or legacy behavior. The current logic *always* falls back to copying from `targetDir` if no prior install exists — but the intent is unclear.
- **No Validation of File Existence**: `File.Copy` is called without verifying the source files exist first. If `sourceFileName` points to a non-existent file, a `FileNotFoundException` will be thrown and caught by the top-level `try/catch`, causing installation failure.
- **Exception Handling Obsfuscation**: The top-level `catch` in `Main` rethrows a *new* `Exception()` without preserving the original exception details (e.g., stack trace), making debugging difficult.
- **Enum Parsing Fragility**: `Enum.TryParse` for `DbType` is case-sensitive by default; if the config value is `"local"` (lowercase) but the enum expects `"Local"`, it will fail and default to `DbType.Local`. This may be intentional, but is not documented.
- **No Rollback on Partial Copy**: If copying the `.mdf` succeeds but the `.ldf` fails, the database files will be in an inconsistent state. No cleanup or rollback is attempted.
- **Assumes LocalDB Folder Exists**: The code constructs paths using `Settings.Default.LocalDbFolder` but does not ensure the folder exists before copying files. `File.Copy` will throw if the directory is missing.
- **Missing `using` for `System.IO`**: Though `System.IO.File.Copy` is used, `using System.IO;` is not declared — implying it is implicitly available (e.g., via other `using`s or project-level settings), but this is a potential portability issue.
None identified beyond those above.

View File

@@ -0,0 +1,60 @@
---
source_files:
- DataPRO/Modules/InstallerCustomActions/LocalSQLDB/Properties/AssemblyInfo.cs
- DataPRO/Modules/InstallerCustomActions/LocalSQLDB/Properties/Settings.Designer.cs
generated_at: "2026-04-16T04:45:12.575157+00:00"
model: "Qwen/Qwen3-Coder-Next-FP8"
schema_version: 1
sha256: "02e9f5ae4a239fa1"
---
# Properties
## Documentation: LocalSQLDB Module
### 1. Purpose
This module provides configuration and metadata for a local SQL Server database component used during Windows Installer custom actions in the DataPRO system. It does not contain executable installation logic itself but defines assembly identity and application-scoped settings that support database deployment operations—specifically, naming conventions and paths for database files (`.mdf`, `.ldf`) and registry keys. Its role is to centralize configuration constants used by other installer custom actions that interact with SQL Server Express or LocalDB instances.
### 2. Public Interface
This module exposes **no public types or methods**. It defines only internal configuration and assembly metadata:
- **`LocalSQLDB.Properties.Settings`** (internal, sealed class)
Auto-generated settings class (via `Settings.Designer.cs`) providing read-only, application-scoped configuration values. Accessible via `Settings.Default`.
Properties:
- `string RegistryDataPROExe``"DataPRO.exe"`
Registry key path or executable name used to locate the DataPRO application.
- `string ApplicationSettings``"applicationSettings"`
Subkey or section name under which application settings are stored.
- `string LocalDbFolder``"db"`
Relative folder name where database files are stored.
- `string Mdf``".mdf"`
File extension for primary database files.
- `string LogLdf``"_log.ldf"`
Suffix used for transaction log files (note: full filename is constructed externally as `<basename><LogLdf>`).
- `string DataPRO``"DataPRO"`
Base name for database files (e.g., `DataPRO.mdf`, `DataPRO_log.ldf`).
> **Note**: The `Settings` class is `internal` and not part of the public API surface. Its properties are only consumed by other modules in the same assembly or via reflection.
### 3. Invariants
- All settings are **application-scoped** and **read-only at runtime** (no user-scoped or mutable settings defined).
- File naming convention: Database files follow the pattern `<DataPRO><Mdf>` and log files follow `<DataPRO><LogLdf>` (e.g., `DataPRO.mdf`, `DataPRO_log.ldf`).
- `LocalDbFolder` is a relative subdirectory path; absolute paths are not used.
- The assembly is **not COM-visible** (`ComVisible(false)`), indicating it is intended for .NET-only consumption.
- Version is fixed at `1.0.0.0` (both `AssemblyVersion` and `AssemblyFileVersion`).
### 4. Dependencies
- **Depends on**:
- `System.Configuration` (for `ApplicationSettingsBase`, attributes like `ApplicationScopedSettingAttribute`)
- `System.Runtime.CompilerServices`, `System.CodeDom.Compiler`, `System.Diagnostics` (for code generation attributes)
- **Used by**:
- Other modules in the `InstallerCustomActions` solution folder (e.g., custom action DLLs that perform database installation/uninstallation).
- Likely consumed by installer projects (e.g., WiX, MSI) that reference this assembly for database file path resolution.
- **No external runtime dependencies** beyond .NET Framework 4.0+ (inferred from runtime version in `Settings.Designer.cs`).
### 5. Gotchas
- The `LogLdf` setting is a **suffix**, not a full filename—consumers must prepend the database name (e.g., `DataPRO` + `"_log.ldf"` = `"DataPRO_log.ldf"`). Confusing this with a full extension (e.g., assuming `".ldf"`) is a common mistake.
- `RegistryDataPROExe` is named misleadingly: it holds `"DataPRO.exe"` (a filename), not a registry path. Actual registry key construction is handled elsewhere.
- The `Settings` class is auto-generated and **should not be manually edited**—changes will be overwritten on regeneration.
- No validation logic is present in this module; invalid file paths or naming conflicts are not caught here.
- The assembly has no public entry points (e.g., no `CustomAction` classes defined here)—it is purely a configuration container.

View File

@@ -0,0 +1,87 @@
---
source_files:
- DataPRO/Modules/InstallerCustomActions/MigrateConfiguration/ConfigurationMigration.cs
generated_at: "2026-04-16T04:43:59.723876+00:00"
model: "Qwen/Qwen3-Coder-Next-FP8"
schema_version: 1
sha256: "499179ba93465fb0"
---
# MigrateConfiguration
## Documentation: `ConfigurationMigration.cs`
### 1. Purpose
This module implements a configuration migration mechanism for DataPRO installer custom actions. Its primary role is to preserve user- and application-specific settings from the most recently installed previous version of DataPRO when a new version is installed, ensuring continuity of configuration without overwriting user-modified values with fresh defaults. It operates during installation by reading the old configuration file (if present), comparing settings against the new defaults, and migrating only those that differ (with special handling for `DownloadFolder` to avoid reverting to outdated defaults). It also handles migration of license files (`.lic`) from previous installations.
---
### 2. Public Interface
The module is `internal static class ConfigurationMigration`. While not `public`, it exposes one method intended for use by the installer custom action infrastructure:
- **`UpdateConfigurationIfPossible(string targetDir, Version installingVersion, string setupExeDir, out string result)`**
*Purpose:* Orchestrates configuration migration.
*Behavior:*
- Determines the most recently installed previous version using `PreviousInstall.GetMostRecentlyInstalledSubKeyName`.
- Retrieves the installation path of that version via `PreviousInstall.GetMostRecentlyInstalledPath`.
- Calls `MigrateLicenseFile` to copy license files.
- Returns via `result` a status string indicating whether the config was updated, skipped, or failed.
- Does **not** migrate `ApplicationSettings` or `UserSettings` sections itself—this appears to be omitted in the active code (commented out in `Main`). Only license migration is performed in the current implementation.
> **Note:** The `Main(string[] args)` method is `private static` and serves as the entry point for the custom action. It parses command-line arguments (`targetDir`, `installingVersion`, `noUI`, `setupExeDir`), initializes event logging, and calls `UpdateConfigurationIfPossible`. It also shows a `MessageBox` with migration results if `noUI != "TRUE"`.
---
### 3. Invariants
- **Version ordering:** Migration only occurs if a *strictly older* version is detected (`installingVersion` must be greater than the previously installed version).
- **Path assumptions:**
- The old config file is assumed to reside at `<oldInstallPath>\DataPRO.exe` (via `StringResources.RegistryDataPROExe`).
- License files are searched up to **2 subdirectories deep** from either the current install directory (`setupExeDir`) or the old install path.
- **Setting migration logic:**
- A setting is migrated **only if**:
1. It exists in both old and new config files.
2. Its value in the old config differs from the *new default* (i.e., the value in the new config file before migration).
3. **Exception for `DownloadFolder`:** It is *not* migrated if the old value equals `StringResources.DataUpOneLevel` (the old default), to avoid reverting to outdated paths.
- **No partial migration of sections:** If `MigrateSettings` fails for either `UserSettings` or `ApplicationSettings`, the entire section is skipped.
- **License file detection:** A file is considered a DataPRO license only if it is a `.lic` file containing both `<License>` and `<LicenseAttributes>` XML elements.
---
### 4. Dependencies
**Internal dependencies (within module):**
- `StringResources` (from `MigrateConfiguration.Resources`) — provides string constants (e.g., `DownloadFolder`, `UserSettings`, `ApplicationSettings`, `DataUpOneLevel`, `DataUpTwoLevels`, `ImportArchiveUpTwoLevels`, `DTSPlugins`, etc.).
- `PreviousInstall` — used to query registry for previous installation metadata (`GetMostRecentlyInstalledSubKeyName`, `GetMostRecentlyInstalledPath`).
- `ConfigInitializationHelper` — used in `MigrateSettings` via `GetNewSettings` (not shown in this file; inferred from usage).
- `SettingElementCollection`, `SettingElement`, `ClientSettingsSection`, `Configuration` — from `System.Configuration`.
**External dependencies (imports):**
- `System.Configuration`
- `System.Windows.Forms` (for `MessageBox.Show`)
- `System.IO`
- `DTS.Common.Utilities`
- `Installer.Common`
**Depended upon by:**
- The Windows Installer custom action that invokes `ConfigurationMigration.Main(string[] args)` with command-line arguments.
---
### 5. Gotchas
- **Critical omission:** The `Main` method contains **commented-out code blocks** that were intended to:
- Pre-set `DownloadFolder` and `ImportArchiveFolder` to current defaults *before* migration.
- Call `MigrateUserSettings` and `MigrateAppSettings` (via `UpdateConfigurationIfPossible` or directly).
- Fix runtime module paths (`FixRunTimeModulesPath`).
**As written, only license migration is active.** Configuration settings (`UserSettings`, `ApplicationSettings`) are *not* migrated in the current implementation.
- **Hardcoded recursion depth:** `FindLicenseInPath` only searches 2 subdirectories deep (`subDirectoriesToCheck = 2`). Deeper nested license files will be missed.
- **Assumption of default install paths:** `GetOldSettings` assumes the old config file is at `<oldInstallPath>\DataPRO.exe`. If the previous installation used a custom path, migration will fail.
- **No rollback on failure:** If license copying fails, the error is reported but no cleanup or fallback occurs.
- **Event logging is non-functional:** The `EventLog.Source` is set to `"MySource"` (hardcoded), but the source `"DataPROInstaller"` is created earlier. This mismatch may cause logging failures.
- **`noUI` check is fragile:** `noUI != "TRUE"` is case-sensitive and exact. `"true"` or `"True"` would not suppress the UI.
- **`SettingElementCollection` mutability:** The code removes and re-adds `SettingElement` instances to `newSettings`. This assumes `SettingElementCollection` allows modification after `Configuration` load, which may be fragile depending on .NET version or config file locking.
- **Missing null checks:** `GetConfigSettings` accesses `configurationSectionGroup.Sections[0]` without verifying `Sections.Count > 0`, risking `IndexOutOfRangeException` if the section exists but is empty.
> **None identified from source alone** for *behavioral* quirks beyond the above — but the commented-out code strongly suggests this module is partially implemented or in a transitional state.

View File

@@ -0,0 +1,37 @@
---
source_files:
- DataPRO/Modules/InstallerCustomActions/MigrateConfiguration/Properties/AssemblyInfo.cs
generated_at: "2026-04-16T04:45:01.515164+00:00"
model: "Qwen/Qwen3-Coder-Next-FP8"
schema_version: 1
sha256: "9c70466a40d28903"
---
# Properties
## Documentation Page: `MigrateConfiguration` Assembly
### 1. Purpose
This module is an assembly named **`MigrateConfiguration`**, intended to support custom actions during installation processes—specifically, to handle migration of configuration data. Based on its placement in the `DataPRO/Modules/InstallerCustomActions/MigrateConfiguration/` directory structure, it serves as a dedicated component for configuration migration logic within a larger installer framework (likely Windows Installer-based, given the `CustomActions` context). The assembly itself contains no visible implementation code in the provided source file; it is purely an assembly metadata definition, suggesting the actual migration logic resides in other files (e.g., `CustomAction.cs`, `Migrator.cs`, etc.) not included here.
### 2. Public Interface
**No public types, functions, or classes are defined in this file.**
The provided source (`AssemblyInfo.cs`) contains only assembly-level attributes (e.g., title, version, COM visibility). It does not declare any public classes, interfaces, methods, or properties. Therefore, **no public interface elements can be documented from this file alone**.
### 3. Invariants
- The assembly is **not visible to COM** (`ComVisible(false)`), meaning it is not intended for interop with COM clients.
- The assembly version is fixed at `1.0.0.0` for both `AssemblyVersion` and `AssemblyFileVersion`.
- The `Guid` attribute (`c255c030-ef08-4974-8654-969e29ab3b77`) uniquely identifies the typelib for COM exposure (though COM visibility is disabled, this GUID is still defined and may be used internally or by tooling).
- The assembly title and product name are both `"MigrateConfiguration"`, indicating its intended role.
### 4. Dependencies
- **Runtime dependencies**: This file imports `System.Reflection`, `System.Runtime.CompilerServices`, and `System.Runtime.InteropServices`, indicating it relies on standard .NET reflection and COM interop namespaces.
- **Consumers**: Since this is an assembly metadata file, it does not directly declare dependencies on other modules. However, the *actual implementation* of the `MigrateConfiguration` assembly (in other, unprovided files) likely depends on installer-related libraries (e.g., `System.Configuration.Install`, Windows Installer XML (WiX) toolset, or custom installer action base classes).
- **Dependents**: Other modules in the `DataPRO/Modules/InstallerCustomActions/` hierarchy (e.g., a main installer project or bootstrapper) are expected to reference this assembly to invoke its custom actions.
### 5. Gotchas
- **No implementation logic is present in this file.** Developers may mistakenly assume this file contains migration logic; it is *only* metadata. Actual functionality resides elsewhere (e.g., in a `CustomAction` class in the same project).
- The assembly version is hardcoded to `1.0.0.0` with no auto-increment (`1.0.*` is commented out). This may lead to versioning issues if updates are deployed without manually bumping the version.
- `ComVisible(false)` is set, but a `Guid` is still provided. This is valid but unusual—ensure no legacy tooling expects COM visibility for this assembly.
- No licensing, security, or threading model attributes are declared (e.g., `STAThreadAttribute`), which may be relevant if the assembly hosts custom actions in a UI context.
- **None identified from source alone.** (Note: The above points are inferred from standard .NET conventions and the structure of `AssemblyInfo.cs`, not from explicit source behavior.)

View File

@@ -0,0 +1,93 @@
---
source_files:
- DataPRO/Modules/InstallerCustomActions/MigrateConfiguration/Resources/StringResources.Designer.cs
generated_at: "2026-04-16T04:45:05.933790+00:00"
model: "Qwen/Qwen3-Coder-Next-FP8"
schema_version: 1
sha256: "99758cb5d382b63b"
---
# Resources
## Documentation: `StringResources` Class (`DataPRO/Modules/InstallerCustomActions/MigrateConfiguration/Resources/StringResources.Designer.cs`)
---
### 1. Purpose
This module provides a strongly-typed, localized string resource accessor for the `MigrateConfiguration` installer custom action. It centralizes all user-facing messages related to configuration migration (e.g., status updates, warnings, errors) to support localization and maintain consistency across installer logic. The class is auto-generated from `.resx` resources and is not intended for manual modification.
---
### 2. Public Interface
All members are `internal` (not `public`), but are exposed as static properties for use within the same assembly. The class is named `StringResources` in the `MigrateConfiguration.Resources` namespace.
| Property | Type | Description |
|---------|------|-------------|
| `ResourceManager` | `System.Resources.ResourceManager` | Returns a cached `ResourceManager` instance for the `MigrateConfiguration.Resources.StringResources` resource set. Thread-safe after first access. |
| `Culture` | `System.Globalization.CultureInfo` | Gets or sets the UI culture used for resource lookups. Overrides the current thread's `CurrentUICulture` for this class. |
| `ApplicationSettings` | `string` | Returns `"applicationSettings"` — likely the config section name for application-level settings. |
| `ConfigDidNotNeedToBeUpdated` | `string` | Returns `"DataPRO.exe.config did not need to be updated."` |
| `ConfigMigrationStatus` | `string` | Returns `"Config migration status."` — likely a log header. |
| `ConfigWasUpdated` | `string` | Returns `"DataPRO.exe.config was updated from the {0} installation."` — format expects one argument (e.g., source version). |
| `DataPROWin7PropertiesSettings` | `string` | Returns `"DataPROWin7.Properties.Settings."` — likely the user settings section name. |
| `DataUpOneLevel` | `string` | Returns `"..\Data"` — relative path to data directory. |
| `DataUpTwoLevels` | `string` | Returns `"..\..\Data"` — relative path to data directory (two levels up). |
| `DownloadFolder` | `string` | Returns `"DownloadFolder"` — likely a config key name. |
| `DTSCommonCorePluginLibConfig` | `string` | Returns `"DTS.Common.Core.PluginLib.Config"` — likely a config section name. |
| `DTSPlugins` | `string` | Returns `"DTSPlugins"` — likely a config key name. |
| `DTSPluginsNeedsModification` | `string` | Returns `"The 'DTSPlugins' key in DataPRO.exe.config must be manually changed to '..//RunTimeModules'."` |
| `DTSViewerModules` | `string` | Returns `"DTSViewerModules"` — likely a config key name. |
| `FailedToCopyLicense` | `string` | Returns `"Failed to copy license."` |
| `ImportArchiveFolder` | `string` | Returns `"ImportArchiveFolder"` — likely a config key name. |
| `ImportArchiveUpTwoLevels` | `string` | Returns `"..\..\ImportArchive"` — relative path. |
| `InstallerLicenseFileFoundCopied` | `string` | Returns `"Installer license file found and copied."` |
| `KeyNotFound` | `string` | Returns `"DTSPlugins key not found: {0}."` — format expects one argument (e.g., key name). |
| `NewSettingsCouldNotBeFound` | `string` | Returns `"Warning: DataPRO.exe.config was not updated because config settings from new version of DataPRO could not be found: {0}; {1}."` — two arguments expected. |
| `NewSettingsCouldNotBeProcessed` | `string` | Returns `"Warning: DataPRO.exe.config was not updated because config settings from new version of DataPRO could not be processed.."` |
| `NoLicenseFound` | `string` | Returns `"No license found to copy."` |
| `OldLicenseFoundCopied` | `string` | Returns `"Old license found and copied."` |
| `OldSettingsCouldNotBeFound` | `string` | Returns `"Warning: DataPRO.exe.config was not updated because config settings from previously-installed version of DataPRO could not be found: {0}; {1}."` — two arguments expected. |
| `OldSettingsCouldNotBeProcessed` | `string` | Returns `"Warning: DataPRO.exe.config was not updated because config settings from previously-installed version of DataPRO could not be processed.."` |
| `RegistryDataPROExe` | `string` | Returns `"DataPRO.exe"` — likely a registry key name. |
| `RunTimeModules` | `string` | Returns `"RunTimeModules"` — likely a config key name (target value for `DTSPlugins`). |
| `SectionNotFound` | `string` | Returns `"DTS.Common.Core.PluginLib.Config section not found."` |
| `SettingNotFound` | `string` | Returns `"Configuration setting not found: {0}."` — format expects one argument (e.g., setting name). |
| `ThisSettingNeedsModification` | `string` | Returns `"The {0} setting in DataPRO.exe.config was not changed to {1}.."` — two arguments expected (old value, new value). |
| `UserSettings` | `string` | Returns `"userSettings"` — likely the config section name for user-level settings. |
> **Note**: All string properties are read-only and perform a lookup via `ResourceManager.GetString(...)`. None accept parameters directly; formatting is done by the caller.
---
### 3. Invariants
- The class is **thread-safe for read-only access** to `ResourceManager` (due to null-check-and-assign pattern in the getter), but `Culture` is not thread-safe when set concurrently.
- Resource keys (e.g., `"ApplicationSettings"`, `"DTSPlugins"`) are assumed to exist in the underlying `.resx` file; missing keys would cause a `MissingManifestResourceException` at runtime (not caught in this class).
- The class is **not meant to be instantiated**; the constructor is `internal` and only used by the runtime.
- All string values are **static after first access**; no runtime mutation of the returned strings occurs.
---
### 4. Dependencies
- **Depends on**:
- `System.Resources.ResourceManager`
- `System.Globalization.CultureInfo`
- `System.CodeDom.Compiler`, `System.Diagnostics`, `System.Runtime.CompilerServices`, `System.ComponentModel` (for attributes)
- The compiled assembly containing the `.resx` resources (same assembly as `StringResources` type).
- **Used by**:
- The `MigrateConfiguration` installer custom action module (inferred from namespace and file path).
- Likely consumed by other classes in `MigrateConfiguration` (e.g., custom action logic that logs or displays messages during config migration).
- **Not used by**:
- Runtime application code (outside installer context), as the namespace and path suggest installer-specific usage.
---
### 5. Gotchas
- **Auto-generated**: Manual edits will be overwritten. Changes must be made in the source `.resx` file.
- **No error handling**: Resource lookup failures (e.g., missing key) will throw exceptions at runtime; callers must handle or expect crashes.
- **Hardcoded paths**: Paths like `..\Data` and `..\..\Data` are hardcoded strings — their correctness depends on the installers working directory and deployment layout.
- **Inconsistent formatting**: Some messages include trailing periods (`.`), others do not (e.g., `ConfigDidNotNeedToBeUpdated` vs `ConfigMigrationStatus`).
- **Typo in path separator**: `DTSPluginsNeedsModification` uses `'..//RunTimeModules'` (double slash), which may be unintentional.
- **Ambiguous keys**: Several keys (e.g., `DownloadFolder`, `ImportArchiveFolder`) are likely config *keys*, not values — but the class provides no distinction. Callers must know the context.
- **No localization fallback logic**: If `Culture` is set to a language without resources, `ResourceManager` may fall back to invariant culture — behavior is standard but not explicit here.
> **None identified from source alone** beyond the above — no evidence of deprecated APIs, legacy workarounds, or known bugs beyond the noted inconsistencies.

View File

@@ -0,0 +1,59 @@
---
source_files:
- DataPRO/Modules/InstallerCustomActions/OpenFolder/App.xaml.cs
- DataPRO/Modules/InstallerCustomActions/OpenFolder/Folder.cs
- DataPRO/Modules/InstallerCustomActions/OpenFolder/MainWindow.xaml.cs
generated_at: "2026-04-16T04:43:41.781372+00:00"
model: "Qwen/Qwen3-Coder-Next-FP8"
schema_version: 1
sha256: "01467cfc72ba0a69"
---
# OpenFolder
## Documentation: `OpenFolder` Module
### 1. Purpose
The `OpenFolder` module is a minimal WPF application intended to serve as a custom action during installation, specifically to open the *Manuals* folder for the installed product. It acts as a standalone executable invoked by the installer (e.g., WiX or MSI), accepting a single command-line argument (likely a product-specific path or identifier) and delegating folder opening logic to `WindowsFolder.OpenManualsFolder`. Due to its role as an installer custom action, it prioritizes simplicity and failure resilience over user interaction—evidenced by its silent exception handling and lack of UI interaction in the `Main` entry point.
### 2. Public Interface
*No public types or methods are exposed.*
All classes (`App`, `MainWindow`, `Folder`) and the `Main` method are internal (`class` without `public` modifier, `private static void Main`). The module does not define any public API surface beyond being an executable entry point.
- **`OpenFolder.App`**
- *Type:* `partial class App : Application`
- *Behavior:* Standard WPF `Application` class; no custom logic beyond initialization. Used for application lifecycle management (e.g., startup/shutdown events), but none are implemented in the provided source.
- **`OpenFolder.MainWindow`**
- *Type:* `partial class MainWindow : Window`
- *Behavior:* WPF window class with a parameterless constructor that calls `InitializeComponent()`. No UI logic, event handlers, or data binding are defined in the source. Likely unused in the installer context, as execution begins at `Folder.Main`.
- **`OpenFolder.Folder.Main(string[] args)`**
- *Signature:* `private static void Main(string[] args)`
- *Behavior:* Entry point for the executable. Invokes `WindowsFolder.OpenManualsFolder(args[0])` with the first command-line argument. Any exceptions during execution are silently caught and ignored (no logging or error reporting).
### 3. Invariants
- **Command-line argument requirement:** The `Main` method assumes `args.Length ≥ 1`; accessing `args[0]` without bounds checking will throw an `IndexOutOfRangeException` if no arguments are provided.
- **Silent failure:** All exceptions in `Main` are suppressed; no indication of success/failure is returned to the caller (e.g., installer). Exit code is implicitly `0` (success), even if `OpenManualsFolder` fails.
- **No UI interaction:** The `MainWindow` is never shown or referenced in `Main`, confirming the module is designed to run headlessly as an installer custom action.
- **Dependency on external library:** Behavior relies entirely on `WindowsFolder.OpenManualsFolder`, whose contract (e.g., expected argument format, folder resolution logic) is defined elsewhere (in `DTS.Common.Classes.WindowsFolders`).
### 4. Dependencies
- **External dependency:**
- `DTS.Common.Classes.WindowsFolders.WindowsFolder` (from `DTS.Common.dll`): Provides the `OpenManualsFolder(string)` method. Its implementation determines the actual folder path resolution (e.g., using environment variables, registry keys, or installation paths).
- **WPF framework dependencies:**
- `System.Windows`, `System.Windows.Controls`, etc. (via `PresentationFramework`, `PresentationCore`, `WindowsBase`).
- **No internal dependencies:**
- No other modules or files in the codebase are referenced or imported.
- **Depended on by:**
- The installer (e.g., WiX `CustomAction` or MSI `CustomAction` table) that invokes this executable during installation. The installer is expected to pass the required argument (e.g., installation directory or product ID) to `args[0]`.
### 5. Gotchas
- **No argument validation:** The `Main` method directly accesses `args[0]` without checking `args.Length`, risking a crash if invoked without arguments.
- **Silent error suppression:** Exceptions (e.g., `IndexOutOfRangeException`, `IOException`, `SecurityException`) are caught and ignored, making debugging difficult. Installers relying on exit codes or logs will not detect failures.
- **Unused WPF components:** The `App.xaml`, `MainWindow.xaml`, and related WPF infrastructure are present but unused in the `Main` flow. This suggests the module may have evolved from a UI-based tool to a headless custom action, leaving dead code.
- **Ambiguous argument semantics:** The purpose of `args[0]` is not documented in the source. It is unclear whether it represents a base path, product ID, or configuration key—this must be inferred from `WindowsFolder.OpenManualsFolder`s implementation.
- **No explicit exit code:** The process exits with the default code (`0`) regardless of success/failure, which may mislead installers expecting non-zero codes on error.
*None identified from source alone.*
*(Note: The above "Gotchas" are derived from explicit code patterns; no external assumptions beyond the provided source are made.)*

View File

@@ -0,0 +1,79 @@
---
source_files:
- DataPRO/Modules/InstallerCustomActions/OpenFolder/Properties/Settings.Designer.cs
- DataPRO/Modules/InstallerCustomActions/OpenFolder/Properties/AssemblyInfo.cs
- DataPRO/Modules/InstallerCustomActions/OpenFolder/Properties/Resources.Designer.cs
generated_at: "2026-04-16T04:44:44.073191+00:00"
model: "Qwen/Qwen3-Coder-Next-FP8"
schema_version: 1
sha256: "e5c3297c1a5efb68"
---
# Properties
## Documentation: `OpenFolder` Module (Installer Custom Action)
---
### 1. **Purpose**
This module is a .NET assembly (`OpenFolder`) intended for use as a Windows Installer custom action, specifically to support opening a folder (likely during or after installation). It contains only auto-generated infrastructure files—no custom logic is present in the provided source. Its role is to define assembly metadata, strongly-typed settings (via `ApplicationSettingsBase`), and localized resources (via `ResourceManager`), serving as a supporting component in the larger `DataPRO` installer ecosystem.
---
### 2. **Public Interface**
The module exposes only auto-generated infrastructure types. No custom public APIs are defined in the provided files.
- **`OpenFolder.Properties.Settings`**
- *Type*: `internal sealed partial class Settings : ApplicationSettingsBase`
- *Behavior*: Provides a singleton `Default` property returning a thread-safe `Settings` instance. No custom settings properties are defined in the source—only the base infrastructure is present.
- *Note*: The class is `internal`, so it is not directly accessible outside the assembly unless exposed via another public type (not present here).
- **`OpenFolder.Properties.Resources`**
- *Type*: `internal sealed partial class Resources`
- *Behavior*: Provides strongly-typed access to localized resources via `ResourceManager` and `Culture` properties. No resource keys or values are defined in the source—only the infrastructure for resource lookup.
- *Note*: Also `internal`, and no public methods or properties beyond `ResourceManager` and `Culture` are exposed.
- **Assembly-level attributes** (via `AssemblyInfo.cs`)
- *Examples*:
- `AssemblyTitle("OpenFolder")`
- `AssemblyVersion("1.0.0.0")`
- `ComVisible(false)`
- `ThemeInfo(...)` for WPF resource location
- *Behavior*: These are metadata attributes used by the .NET runtime and tooling; they do not define executable behavior.
---
### 3. **Invariants**
- The `Settings.Default` property always returns a synchronized singleton instance (via `ApplicationSettingsBase.Synchronized`), ensuring thread-safe access.
- The `Resources.ResourceManager` is lazily initialized on first access and cached in a static field.
- The assembly is marked `ComVisible(false)`, meaning its types are not exposed to COM by default.
- No runtime validation or business logic is present in the provided files—no invariants beyond those of the base classes (`ApplicationSettingsBase`, `ResourceManager`) apply.
---
### 4. **Dependencies**
- **Dependencies *of* this module**:
- `System.Configuration` (for `ApplicationSettingsBase`)
- `System.Resources` (for `ResourceManager`, `Resources`)
- `System.Globalization` (for `CultureInfo`)
- `System.Windows` (for `ThemeInfo` attribute usage—though no WPF UI is evident here)
- `System.Runtime.CompilerServices`, `System.CodeDom.Compiler`, `System.Diagnostics`, `System.ComponentModel` (for attributes and tooling support)
- **Dependencies *on* this module**:
- Not inferable from the provided files. As a custom action module, it is likely referenced by an MSI project or installer build pipeline, but no such references appear in the source.
---
### 5. **Gotchas**
- **No custom logic present**: The module contains *only* auto-generated infrastructure. Any functional behavior (e.g., actually opening a folder) must reside in other files *not provided*—likely in a custom action class (e.g., `Installer.cs` or similar) in the same project.
- **`internal` visibility**: All public-facing types (`Settings`, `Resources`) are `internal`, meaning they cannot be accessed from outside the assembly unless explicitly exposed via `InternalsVisibleTo` (not present in `AssemblyInfo`).
- **Empty settings/resources**: The `Settings` class has no user-defined properties, and `Resources` has no defined resource members—suggesting either incomplete implementation or that these are placeholders for future use.
- **Auto-generated warning**: Both `Settings.Designer.cs` and `Resources.Designer.cs` explicitly warn that manual changes will be lost on regeneration. This implies the project relies on Visual Studios designer tooling for future edits.
- **Versioning**: Assembly version is hardcoded to `1.0.0.0` (with `AssemblyFileVersion` same), which may be intentional for installer stability or indicate a lack of version tracking discipline.
None identified beyond the above.

View File

@@ -0,0 +1,101 @@
---
source_files:
- DataPRO/Modules/InstallerCustomActions/RegAddProductCode/AddProductCode.cs
generated_at: "2026-04-16T04:43:28.721583+00:00"
model: "Qwen/Qwen3-Coder-Next-FP8"
schema_version: 1
sha256: "c22465a70e9ccf40"
---
# RegAddProductCode
## Documentation: `AddProductCode.cs` — Installer Custom Action for Registry Policy Configuration
---
### 1. Purpose
This module implements a Windows Installer custom action (`AddProductCode`) responsible for configuring Windows Installer security policies in the registry prior to or during DataPRO installation. Specifically, it enforces the `SecureRepairPolicy` setting and adds the DataPRO product code to the `SecureRepairWhitelist`, enabling the installer to perform repair operations on `DataPRO.exe` and its dependencies without being blocked by Windows Installers secure repair restrictions. It also validates architecture compatibility between the installer process (32- or 64-bit) and the operating system, terminating the installation with a user-facing error if a mismatch is detected (e.g., 32-bit installer on 64-bit OS), to prevent downstream failures such as incompatible SQL LocalDB version conflicts.
---
### 2. Public Interface
The class `AddProductCode` exposes only one public entry point:
#### `static int Main(string[] args)`
- **Signature**: `private static int Main(string[] args)`
- **Behavior**:
Entry point for the custom action. Parses `args[0]` as `architectureVersion` (`"x86"` or `"x64"`), logs environment details (process bitness, OS bitness), and performs architecture validation:
- If `architectureVersion == "x86"` and OS is 64-bit → shows error message and returns `1`.
- If `architectureVersion == "x64"` and OS is 32-bit → shows error message and returns `1`.
- Otherwise, calls `AddCodeToRegistry()` and returns `0` (success) or `1` (failure if registry write fails).
- Logging is performed via `EventLog.WriteEntry` under source `"DataPROInstaller"`.
> **Note**: Though declared `private`, this method is the *de facto* public entry point for the custom action as invoked by the Windows Installer (e.g., via `CustomAction` table). It is not called internally.
---
### 3. Invariants
- **Architecture Consistency**:
The installer process bitness must match the target OS bitness *relative to the requested architecture* (`args[0]`). Mismatches cause early termination with exit code `1`.
- **Registry Hive & View**:
All registry modifications target `HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\Installer` using `RegistryView.Registry64`, ensuring writes occur in the 64-bit view even on 64-bit systems (i.e., not redirected to `WOW6432Node`).
- **Policy Values**:
The following must be set:
- `SecureRepairPolicy` (DWORD) = `2` (enables secure repair for whitelisted products).
- `SecureRepairWhitelist\{C4889149-0CAF-44C1-B226-8F6E73684DF4}` (DWORD) = `0` (adds product code to whitelist).
- **Exit Codes**:
- `0`: Success (registry updated or already correct).
- `1`: Failure due to architecture mismatch or registry write error.
---
### 4. Dependencies
#### Imports / External Dependencies:
- `System.Diagnostics.EventLog` for installer logging.
- `Microsoft.Win32.RegistryKey`, `RegistryHive`, `RegistryView`, `RegistryValueKind` for registry access.
- `System.Windows.Forms.MessageBox` for user-facing error messages.
- `RegAddProductCode.Properties.Settings.Default` static configuration values:
- `Settings.Default.InstallerKey`: Registry path `"SOFTWARE\\Policies\\Microsoft\\Windows\\Installer"`
- `Settings.Default.SecureRepairPolicy`: Policy value name `"SecureRepairPolicy"`
- `Settings.Default.SecureRepairWhitelistKey`: Subkey path `"SOFTWARE\\Policies\\Microsoft\\Windows\\Installer\\SecureRepairWhitelist"`
- `Settings.Default.ProductCode`: Product code GUID `"{C4889149-0CAF-44C1-B226-8F6E73684DF4}"`
- `Settings.Default.MissingKey`: Format string for error messages (e.g., `"Registry key missing: {0}"`).
#### Usage:
- **Called by**: Windows Installer as a custom action (likely in a WiX or similar MSI project).
- **Depends on**:
- Administrative privileges (required to write to `HKLM\SOFTWARE\Policies\...`).
- `EventLog` source `"DataPROInstaller"` must exist or be creatable by the installer process.
---
### 5. Gotchas
- **Hardcoded Product Code**:
The product code `"{C4889149-0CAF-44C1-B226-8F6E73684DF4}"` is hardcoded in both `Settings.Default.ProductCode` and the whitelist logic. Changing the product code in the installer project requires updating this value manually—no dynamic injection is present.
- **Silent Failure Risk in 32-bit on 64-bit**:
The comment explains that allowing a 32-bit installer on 64-bit OS could cause the SQL LocalDB 2014 prerequisite to fail silently, leading to runtime DB version incompatibility. This is a *preventive guard*, but the fix is architectural (blocking 32-bit installers entirely on 64-bit OS), not a workaround.
- **Registry View Hardcoded to 64-bit**:
`RegistryView.Registry64` is used unconditionally—even on 32-bit OSes. While `OpenBaseKey` with `Registry64` on a 32-bit OS is safe (it falls back to the native view), this may be unintentional or legacy. No explicit fallback to `RegistryView.Registry32` exists.
- **No Rollback Handling**:
If `AddCodeToRegistry()` succeeds but the main installer fails later, the registry changes are *not* rolled back. The policy settings remain in place.
- **Commented-Out UI Error**:
The line `// MessageBox.Show(result);` is commented out in `Main()`, meaning registry errors are *only* logged to Event Log, not shown to the user. This may reduce visibility during silent installs.
- **No Exception Handling Granularity**:
`AddCodeToRegistry()` catches all exceptions generically and returns only the message string. Specific exceptions (e.g., `UnauthorizedAccessException`, `SecurityException`) are not differentiated.
- **Assumes Installer Runs with Admin Rights**:
The code assumes the custom action runs with elevated privileges. If not, registry writes will fail silently (or with generic error), and no fallback is implemented.
---
*End of documentation.*

View File

@@ -0,0 +1,75 @@
---
source_files:
- DataPRO/Modules/InstallerCustomActions/RegAddProductCode/Properties/AssemblyInfo.cs
- DataPRO/Modules/InstallerCustomActions/RegAddProductCode/Properties/Settings.Designer.cs
generated_at: "2026-04-16T04:44:25.291700+00:00"
model: "Qwen/Qwen3-Coder-Next-FP8"
schema_version: 1
sha256: "c5bd9c265d48c4b1"
---
# Properties
## Documentation: `RegAddProductCode` Module
### 1. Purpose
This module is a .NET-based Windows Installer custom action designed to register a product code in a specific Windows Registry location—primarily to support Windows Installers `SecureRepairPolicy` mechanism. It reads configuration settings (including registry key paths and a product code GUID) and writes the product code to the `SecureRepairWhitelist` registry subkey under the Windows Installer policies path. Its role is to ensure that a given product remains whitelisted for secure repair operations, a security feature introduced in Windows Installer to restrict which products may be repaired without elevated privileges.
### 2. Public Interface
No public *executable* API (e.g., `CustomAction` entry points) is visible in the provided source files. However, the module exposes the following *configuration* types and members:
- **`RegAddProductCode.Properties.Settings.Default`**
- **Type**: `RegAddProductCode.Properties.Settings` (singleton instance)
- **Behavior**: Provides application-scoped read-only access to configuration values defined in `Settings.settings`. This is the only public surface exposed via the generated settings class.
- **`RegAddProductCode.Properties.Settings.InstallerKey`**
- **Type**: `string`
- **Default Value**: `"SOFTWARE\\Policies\\Microsoft\\Windows\\Installer"`
- **Behavior**: Returns the base registry key path for Windows Installer policies.
- **`RegAddProductCode.Properties.Settings.MissingKey`**
- **Type**: `string`
- **Default Value**: `"No key at {0}"`
- **Behavior**: A format string template, likely intended for logging or error messages when a registry key is not found.
- **`RegAddProductCode.Properties.Settings.ProductCode`**
- **Type**: `string`
- **Default Value**: `"{C4889149-0CAF-44C1-B226-8F6E73684DF4}"`
- **Behavior**: Returns the product code GUID to be added to the whitelist.
- **`RegAddProductCode.Properties.Settings.SecureRepairPolicy`**
- **Type**: `string`
- **Default Value**: `"SecureRepairPolicy"`
- **Behavior**: The name of the registry value used to enable/disable secure repair policy.
- **`RegAddProductCode.Properties.Settings.SecureRepairWhitelistKey`**
- **Type**: `string`
- **Default Value**: `"SOFTWARE\\Policies\\Microsoft\\Windows\\Installer\\SecureRepairWhitelist"`
- **Behavior**: Returns the full registry path where whitelisted product codes are stored.
> **Note**: The actual custom action logic (e.g., `Install`/`Commit`/`Rollback` methods or `[CustomAction]`-attributed functions) is *not present* in the provided files and must reside in other source files (e.g., `CustomAction.cs`). This documentation is limited to what is exposed in the provided `AssemblyInfo.cs` and `Settings.Designer.cs`.
### 3. Invariants
- The `ProductCode` setting is expected to be a valid GUID string (format `{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}`), though no runtime validation is evident from the settings definition.
- The registry paths (`InstallerKey`, `SecureRepairWhitelistKey`) are hardcoded and must be valid Windows Registry paths (double-escaped backslashes in source reflect single escaping in the runtime string).
- Settings are *application-scoped* and read-only at runtime (no setters exposed); they are fixed at compile time.
- The `Settings.Default` instance is thread-safe via `ApplicationSettingsBase.Synchronized()`.
### 4. Dependencies
- **Runtime Dependencies**:
- `System.Configuration.dll` (for `ApplicationSettingsBase`, `ApplicationScopedSettingAttribute`, etc.)
- `System.dll` (for core types like `string`, `Attribute`, etc.)
- **Build/Deployment Dependencies**:
- This assembly is likely referenced by a Windows Installer (MSI) project or custom action project (e.g., WiX, InstallShield) as a custom action DLL.
- It depends on the Windows Installer service being available at runtime (to interact with registry policy keys).
- **Inferred Consumers**:
- An external installer project (e.g., `.wixproj`, `.vdproj`) that invokes this assembly as a custom action during installation/repair.
- The `RegAddProductCode` assembly itself is not referenced programmatically by other modules in the provided source.
### 5. Gotchas
- **Missing Custom Action Entry Point**: The provided files contain *no* `CustomAction` method definitions (e.g., no `[CustomAction]` attributes or `Session`-based logic). The actual behavior (reading settings and writing to registry) is not observable here—this modules *purpose* is inferred from naming and settings, but implementation details are absent.
- **Hardcoded Product Code**: The `ProductCode` is fixed at compile time (`{C4889149-0CAF-44C1-B226-8F6E73684DF4}`), meaning this assembly is not reusable for other products without recompilation.
- **Registry Path Escaping**: The `\\` in string literals (e.g., `"SOFTWARE\\\\Policies..."`) are *literal* backslashes in the compiled string (due to C# escaping), which is correct for registry paths, but could be confusing if misread.
- **No Error Handling in Settings**: The settings class provides no mechanism to validate or handle missing registry keys—error handling (e.g., for `MissingKey`) must be implemented elsewhere (e.g., in the custom action logic not shown).
- **No Versioning Strategy**: Assembly version is `1.0.0.0` for both `AssemblyVersion` and `AssemblyFileVersion`, suggesting minimal version discipline—could cause issues in side-by-side deployments.
- **None identified from source alone.** (Additional gotchas would require inspecting the actual custom action implementation.)

View File

@@ -0,0 +1,45 @@
---
source_files:
- DataPRO/Modules/InstallerCustomActions/WarnWindows11/WarnWindows11.cs
generated_at: "2026-04-16T04:43:22.817107+00:00"
model: "Qwen/Qwen3-Coder-Next-FP8"
schema_version: 1
sha256: "4bf07a16db262f9c"
---
# WarnWindows11
## 1. Purpose
This module provides a Windows Installer custom action that warns users during installation if the target system is running Windows 11. It executes as part of the installation sequence, checks the OS version by parsing the output of `systeminfo.exe`, and displays a modal warning message box if Windows 11 is detected—aimed at alerting users to potential compatibility concerns (as implied by the resource key `WARNING_WINDOWS11`). It exists to proactively inform users before proceeding with installation on an unsupported or untested platform.
## 2. Public Interface
- **`OSWarning.Main(string[] args)`**
*Signature:* `public static void Main(string[] args)`
*Behavior:* Entry point for the custom action. Launches `systeminfo.exe`, captures its standard output, and scans line-by-line for the substring `"MICROSOFT WINDOWS 11"` (case-insensitive). If found, displays a message box using `Properties.Resources.WARNING_WINDOWS11`. All exceptions are silently caught and ignored; no error reporting or logging occurs.
## 3. Invariants
- The process must successfully spawn `systeminfo.exe` and read its full output synchronously before proceeding.
- The OS detection relies *solely* on exact substring matching in `systeminfo.exe` output; no other version-checking mechanisms (e.g., `Environment.OSVersion`, registry queries) are used.
- The message box is shown *only* if the substring `"MICROSOFT WINDOWS 11"` appears anywhere in the output (case-insensitive).
- No return value or exit code is set; the method always exits normally (even on failure).
- The custom action assumes it runs in an interactive context (since `MessageBox.Show` requires user interaction); non-interactive execution (e.g., silent install) may hang or fail silently.
## 4. Dependencies
- **Runtime:** .NET Framework (uses `System.Windows.Forms.MessageBox`, `System.Diagnostics.Process`, `System` namespaces).
- **External executable:** `systeminfo.exe` (standard Windows utility; must be present on the target system).
- **Resources:** `Properties.Resources.WARNING_WINDOWS11` must be defined (string resource) in the same assembly; failure to define it would cause a compile-time error.
- **Caller:** Intended to be invoked as a Windows Installer custom action (likely deferred or immediate, though not specified here).
- **No external libraries** beyond the base .NET Framework.
## 5. Gotchas
- **Fragile OS detection:** Relies on `systeminfo.exe` output format, which may vary across Windows versions, locales, or system configurations (e.g., localized output like `"Microsoft Windows 11 Pro"` vs. `"Microsoft Windows 11"`).
- **Silent failure handling:** All exceptions (including `Win32Exception` if `systeminfo.exe` is missing, `InvalidOperationException` if process fails, or `SecurityException` if permissions are insufficient) are swallowed—no diagnostics or fallback behavior.
- **Blocking UI call:** `MessageBox.Show` blocks the installer thread; if invoked non-interactively (e.g., via `msiexec /quiet`), the installer may hang indefinitely waiting for user input.
- **No cancellation path:** The warning is informational only; the installation proceeds regardless of whether the user dismisses the message.
- **Performance:** Synchronous process execution and full output parsing may add latency to installation (though `systeminfo.exe` is typically fast).
- **No version validation:** Detects *any* Windows 11 variant (Home, Pro, etc.) but does not distinguish editions or build numbers.
- **Missing resource handling:** If `Properties.Resources.WARNING_WINDOWS11` is null or empty, the message box will show an empty dialog—no null check is performed.
- **Case-insensitivity is applied only to the search string, not the output:** The `line.ToUpper()` call ensures case-insensitive matching of `"MICROSOFT WINDOWS 11"`, but if `systeminfo.exe` output uses non-ASCII characters (e.g., accented letters), matching may still fail.
- **No cleanup of process resources beyond `WaitForExit()`:** While `using` ensures disposal of the `Process` object, there is no explicit handling of `StandardOutput` stream disposal (though `reader.ReadToEnd()` closes it implicitly).
*None identified from source alone.***Correction:** Several gotchas *are* apparent from the source (see above).

View File

@@ -0,0 +1,66 @@
---
source_files:
- DataPRO/Modules/InstallerCustomActions/WarnWindows11/Properties/Settings.Designer.cs
- DataPRO/Modules/InstallerCustomActions/WarnWindows11/Properties/AssemblyInfo.cs
- DataPRO/Modules/InstallerCustomActions/WarnWindows11/Properties/Resources.Designer.cs
generated_at: "2026-04-16T04:44:32.111058+00:00"
model: "Qwen/Qwen3-Coder-Next-FP8"
schema_version: 1
sha256: "136a291046e5df64"
---
# Properties
## Documentation: `WarnWindows11` Module
### 1. Purpose
This module provides a localized warning message used during SQL Server installation on Windows 11, alerting users to potential manual steps required due to OS-specific disk sector size constraints. It exists as a self-contained assembly intended for use in Windows Installer custom actions—specifically to surface a predefined warning string via resource lookup. The module does not contain executable logic beyond exposing the warning text; it is purely a resource container.
### 2. Public Interface
The module exposes no public *types* beyond internal auto-generated classes. However, the following public members are accessible *within the assembly* (and may be consumed by external callers via reflection or strong-named referencing, though not designed for direct public use):
- **`WarnWindows11.Properties.Settings.Default`**
- *Type:* `WarnWindows11.Properties.Settings` (singleton, sealed, derived from `ApplicationSettingsBase`)
- *Behavior:* Provides access to the application settings instance for this assembly. No custom settings are defined in the source—only the default singleton accessor is present.
- **`WarnWindows11.Properties.Resources.WARNING_WINDOWS11`**
- *Type:* `string` (read-only property)
- *Behavior:* Returns the localized warning string:
> *"Installation of Microsoft SQL Server on windows 11 may require some manual steps to run. See https://learn.microsoft.com/en-us/troubleshoot/sql/database-engine/database-file-operations/troubleshoot-os-4kb-disk-sector-size for more information, or contact DTS support for assistance."*
This is the only resource string defined and is the sole functional output of the module.
- **`WarnWindows11.Properties.Resources.ResourceManager`**
- *Type:* `System.Resources.ResourceManager` (read-only property)
- *Behavior:* Lazily initializes and returns a `ResourceManager` instance bound to the `"WarnWindows11.Properties.Resources"` base name within the current assembly.
- **`WarnWindows11.Properties.Resources.Culture`**
- *Type:* `System.Globalization.CultureInfo` (read/write property)
- *Behavior:* Allows overriding the threads `CurrentUICulture` for resource lookups. Defaults to `null`, meaning `ResourceManager` uses the current UI culture.
### 3. Invariants
- The `Settings.Default` property always returns the same singleton instance (enforced via `Synchronized()` and static field initialization).
- `Resources.WARNING_WINDOWS11` always returns the exact string literal defined in `Resources.resx` (as reflected in `Resources.Designer.cs`).
- The `ResourceManager` is initialized exactly once per AppDomain (lazy initialization with null-check).
- The assembly is non-`ComVisible` (`[ComVisible(false)]`), meaning its types are not exposed to COM by default.
- No runtime validation or conditional logic is present—the warning string is static and unconditionally returned.
### 4. Dependencies
- **Runtime Dependencies:**
- `System.Configuration` (for `ApplicationSettingsBase`)
- `System.Resources` (for `ResourceManager`, `Resources`)
- `System.Globalization` (for `CultureInfo`)
- `System.Windows` (referenced via `System.Windows.dll`, implied by `System.Windows` namespace usage in `AssemblyInfo.cs`; likely for WPF-based installer UI, though not directly used here)
- **Assembly Dependencies (inferred):**
- `WarnWindows11` assembly itself (self-contained).
- No external project or library dependencies are declared in the provided files.
- **Consumers (inferred):**
- Likely consumed by a Windows Installer custom action (e.g., in a `.wixproj` or custom action DLL) that displays this warning during SQL Server installation on Windows 11.
- May be referenced by other installer modules (e.g., `DataPRO.InstallerCustomActions`) via strong-named assembly reference.
### 5. Gotchas
- **No custom settings defined**: Though `Settings.Designer.cs` exists, the `Settings` class contains no user-defined properties—only the default accessor. Any expectation of configurable behavior (e.g., warning thresholds, URLs) is unfounded.
- **Hardcoded URL**: The warning string embeds a specific Microsoft support URL. If this URL changes or becomes stale, the warning becomes outdated and requires recompilation.
- **Case sensitivity in resource key**: The property `WARNING_WINDOWS11` corresponds to a resource key `"WARNING_WINDOWS11"` in the `.resx` file. Any mismatch in casing or spelling between `.resx` and the generated code would cause a runtime `MissingManifestResourceException`.
- **Auto-generated code**: Both `Settings.Designer.cs` and `Resources.Designer.cs` are auto-generated. Manual edits will be overwritten; changes must be made in the designer (`.resx`, `.settings`) or `.csproj` files.
- **No localization logic in source**: While `Culture` and `ResourceManager` are present, no `.resx` fallback or satellite assemblies are visible in the provided files. Localization is assumed but unverified from source alone.
- **Assembly version fixed at `1.0.0.0`**: Both `AssemblyVersion` and `FileVersion` are hardcoded to `1.0.0.0`, which may complicate versioning in deployment pipelines.

View File

@@ -0,0 +1,120 @@
---
source_files:
- DataPRO/Modules/Menu/HamburgerMenu/HamburgerMenuModule.cs
generated_at: "2026-04-16T04:48:16.508256+00:00"
model: "Qwen/Qwen3-Coder-Next-FP8"
schema_version: 1
sha256: "7a5beb8ec708c422"
---
# HamburgerMenu
## Documentation: HamburgerMenuModule
---
### 1. Purpose
The `HamburgerMenuModule` is a Prism module responsible for registering the view and view model for the applications hamburger menu UI component into the Unity dependency injection container. It enables modular composition of the UI by exposing the hamburger menu as a reusable, injectable component within the Prism-based application shell. The module also contributes metadata—specifically, an assembly name and image—used by the host application (e.g., for display on a main screen summary of available modules). It does not contain business logic but serves as a wiring layer for UI composition.
---
### 2. Public Interface
#### `HamburgerMenuModule` class
- **`HamburgerMenuModule(IUnityContainer unityContainer)`**
Constructor. Accepts a Unity container via dependency injection and stores it for later use in type registration.
- **`void Initialize()`**
Registers two types as singletons in the Unity container:
- `IHamburgerMenuView``HamburgerMenuView`
- `IHamburgerMenuViewModel``HamburgerMenuViewModel`
Uses `ContainerControlledLifetimeManager` to enforce singleton lifetime.
- **`void OnInitialized(IContainerProvider containerProvider)`**
Currently empty. No initialization logic beyond `Initialize()` is performed here.
- **`void RegisterTypes(IContainerRegistry containerRegistry)`**
Delegates to `Initialize()`. (Note: `IContainerRegistry` is Prisms abstraction; however, this implementation ignores it and uses the injected `IUnityContainer` directly.)
#### `HamburgerMenuModuleNameAttribute` class
- **`HamburgerMenuModuleNameAttribute()` / `HamburgerMenuModuleNameAttribute(string s)`**
Constructor. Sets `AssemblyName` to `AssemblyNames.HamburgerMenu.ToString()` (value inferred from `DTS.Common.Interface.Menu.HamburgerMenu` namespace usage).
- **`string AssemblyName { get; }`**
Returns `"HamburgerMenu"` (value of `AssemblyNames.HamburgerMenu.ToString()`).
- **`Type GetAttributeType()`**
Returns `typeof(TextAttribute)`.
- **`string GetAssemblyName()`**
Returns `AssemblyName`.
#### `HamburgerMenuModuleImageAttribute` class
- **`HamburgerMenuModuleImageAttribute()` / `HamburgerMenuModuleImageAttribute(string s)`**
Constructor. Loads the assembly image via `AssemblyInfo.GetImage("HamburgerMenu")`.
- **`BitmapImage AssemblyImage { get; }`**
Returns the image loaded by `AssemblyInfo.GetImage("HamburgerMenu")`.
- **`string AssemblyName { get; }`**
Returns `"HamburgerMenu"`.
- **`string AssemblyGroup { get; }`**
Returns `"Prepare"` (value of `eAssemblyGroups.Prepare.ToString()`).
- **`eAssemblyRegion AssemblyRegion { get; }`**
Returns `eAssemblyRegion.HamburgerMenuRegion`.
- **`Type GetAttributeType()`**
Returns `typeof(ImageAttribute)`.
- **`BitmapImage GetAssemblyImage()`**
Returns `AssemblyImage`.
- **`string GetAssemblyName()`**
Returns `AssemblyName`.
- **`string GetAssemblyGroup()`**
Returns `AssemblyGroup`.
- **`eAssemblyRegion GetAssemblyRegion()`**
Returns `AssemblyRegion`.
---
### 3. Invariants
- The module **must** be loaded after `DTS.Common` and `HamburgerMenu` assemblies are available (since it references `AssemblyNames.HamburgerMenu`, `AssemblyInfo`, `eAssemblyGroups`, and `eAssemblyRegion` from those).
- `IHamburgerMenuView` and `IHamburgerMenuViewModel` are registered as **singleton** instances; multiple resolutions return the same instance.
- The `AssemblyName` exposed via attributes is strictly `"HamburgerMenu"`.
- The `AssemblyGroup` is fixed to `"Prepare"`.
- The `AssemblyRegion` is fixed to `eAssemblyRegion.HamburgerMenuRegion`.
- The image is loaded once per attribute instance (via `AssemblyInfo.GetImage`) and cached in `_img`.
---
### 4. Dependencies
#### This module depends on:
- **Prism.Modularity** (`IModule`, `IContainerRegistry`, `IContainerProvider`)
- **Unity** (`IUnityContainer`, `Unity.Lifetime.ContainerControlledLifetimeManager`)
- **System.ComponentModel.Composition** (`[Export]`, `[Module]`)
- **System.Windows.Media.Imaging** (`BitmapImage`)
- **DTS.Common** (specifically `AssemblyNames`, `AssemblyInfo`, `eAssemblyGroups`, `eAssemblyRegion`)
- **DTS.Common.Interface.Menu.HamburgerMenu** (specifically `IHamburgerMenuView`, `IHamburgerMenuViewModel`)
- **Prism.Ioc** (`IContainerRegistry`, `IContainerProvider`)
#### This module is depended upon by:
- The host applications shell (e.g., `MainWindow.xaml` or a region manager) that resolves `IHamburgerMenuView` or uses the modules metadata (via attributes) to display the hamburger menu component in the UI.
- Any module or service that needs to inject `IHamburgerMenuView` or `IHamburgerMenuViewModel`.
---
### 5. Gotchas
- **`RegisterTypes` ignores `IContainerRegistry`**: Though `RegisterTypes` receives a `IContainerRegistry`, it calls `Initialize()`, which uses the injected `IUnityContainer`. This tightly couples the module to Unity and breaks Prisms container-agnostic design.
- **Redundant `OnInitialized` implementation**: The `OnInitialized` method is empty and unused; no post-registration logic is performed.
- **Attribute metadata is static**: `AssemblyImage`, `AssemblyName`, `AssemblyGroup`, and `AssemblyRegion` are computed once per attribute instance (in constructor or property getter), but not cached at the assembly level—repeated attribute usage may cause redundant `AssemblyInfo.GetImage` calls.
- **No error handling for image loading**: If `AssemblyInfo.GetImage("HamburgerMenu")` fails (e.g., missing resource), the exception propagates during attribute instantiation (e.g., at assembly load time), potentially breaking module discovery.
- **Missing documentation for `TextAttribute`/`ImageAttribute` base classes**: Their behavior (e.g., how `GetAttributeType()` is used) is not inferable from this source.
- **No validation of `IHamburgerMenuView`/`IHamburgerMenuViewModel` implementations**: Assumes they exist and are compatible with the DI container.
None identified beyond the above.

View File

@@ -0,0 +1,62 @@
---
source_files:
- DataPRO/Modules/Menu/HamburgerMenu/Model/MenuCommand.cs
generated_at: "2026-04-16T04:48:40.108913+00:00"
model: "Qwen/Qwen3-Coder-Next-FP8"
schema_version: 1
sha256: "d733624401ce5030"
---
# Model
### 1. **Purpose**
`MenuCommand` is a concrete implementation of `ICommand` used to wrap menu item selections in the Hamburger Menu module. It serves as a lightweight command handler that, when executed, notifies a registered callback (`MenuItemPressedDelegate`) with the menu items unique identifier (`Id`). Its purpose is to decouple UI menu interactions from business logic by translating WPF command execution into a domain-specific callback, enabling loose coupling between the menu UI and the rest of the system.
---
### 2. **Public Interface**
- **`MenuCommand(string id, MenuItemPressedDelegate menuItemPressed)`**
Constructor. Initializes the command with a unique `id` (string) and a delegate (`MenuItemPressedDelegate`) to invoke on execution.
- *Parameters*:
- `id`: A non-null string identifying the menu item.
- `menuItemPressed`: A delegate of type `MenuItemPressedDelegate` (defined in `DTS.Common.Interface.Menu.HamburgerMenu`) to be invoked with `id` when the command executes.
- **`bool CanExecute(object parameter)`**
Always returns `true`. Implements `ICommand.CanExecute`. The command is always executable regardless of the `parameter` value.
- **`void Execute(object parameter)`**
Invokes the `MenuItemPressed` delegate with the stored `Id`. Implements `ICommand.Execute`. The `parameter` is ignored.
- **`event EventHandler CanExecuteChanged`**
Implements `ICommand.CanExecuteChanged`. Declared but *never raised* — consumers should not rely on this event for change notifications.
---
### 3. **Invariants**
- `Id` is immutable after construction (declared `readonly`).
- `MenuItemPressed` delegate is non-null at construction (no null-check is performed; passing `null` will cause a `NullReferenceException` on `Execute`).
- `CanExecute` always returns `true`; no runtime conditions affect executability.
- `CanExecuteChanged` is declared but *never raised* — no external changes to `CanExecute` status are ever signaled.
- `Execute` ignores its `parameter` argument entirely.
---
### 4. **Dependencies**
- **Imports/References**:
- `DTS.Common.Interface.Menu.HamburgerMenu` — Provides the `MenuItemPressedDelegate` type (not defined in this file; assumed to be a delegate type in the referenced namespace).
- `System` and `System.Windows.Input` — For `EventHandler`, `ICommand`, and WPF command infrastructure.
- **Consumers**:
- Presumably instantiated by UI layer code (e.g., in a view model or menu builder) that maps menu items to `MenuCommand` instances.
- Depends on external code to supply the `MenuItemPressedDelegate` implementation (not visible in this file).
---
### 5. **Gotchas**
- **`CanExecuteChanged` is never raised** — This violates typical `ICommand` conventions (e.g., WPF command bindings may not update UI state if they rely on this event). If command executability *should* change dynamically, this implementation is incomplete.
- **No null-safety**: Passing `null` for `menuItemPressed` in the constructor will cause a `NullReferenceException` at `Execute` time.
- **`parameter` is unused** — `Execute` ignores its argument, which may cause issues if consumers expect parameter-based logic (e.g., passing context via `parameter`).
- **No validation of `id`** — No checks for `null` or empty `id`; while not explicitly causing failure, this may lead to ambiguous menu item identification downstream.
- **No thread-safety guarantees** — `CanExecuteChanged` event and delegate invocation are not synchronized.
None identified beyond the above.

Some files were not shown because too many files have changed in this diff Show More