Cause: - ResultsWriter required a generic way to generate customer-specific XML result data from TBF measurement results. - The customer reference XML contains example runtime values and repeated result structures, so it cannot be used directly as the generated output. - TBF result variables must be explicitly mapped to destinations in the customer XML structure. - The generated XML result data must support two output targets: - direct creation of an XML file, - delivery of the XML payload to a Microsoft SQL stored procedure. - Preview generation must allow the XML structure and configured mappings to be verified without executing the production database write. - Increase revision to 3.9.3145.100. Solution: 1. Added XML reference analysis - Creates a clean base XML structure. - Extracts the repeating result prototype. - Prevents sample runtime values from the customer reference XML from leaking into generated results. 2. Added configurable TBF-to-XML result mapping - Allows explicit mapping of TBF result variables to customer XML destinations. - Supports one-time and repeating XML destinations. - Keeps the mapping independent of the semantic meaning of customer XML attribute names. 3. Added XML destination viewer and configurator - Shows the current mapping. - Highlights repeating destinations. - Identifies already used one-time destinations. 4. Added runtime XML result generation - Uses the configured TBF-to-XML mappings. - Uses measurement procedure result data. - Builds the output from the clean base XML and repeating XML prototype. - Generates repeated result records according to the executed measurement procedure. 5. Added simulation-based Preview request - Generates a complete XML payload using simulation values. - Allows XML structure and mapping verification before production execution. - Does not execute the production stored procedure. 6. Added direct XML file output support to UniDataStorageWriter - Supports File / .xml as a physical output target. - Creates the generated XML result file in the configured output directory. 7. Added Microsoft SQL stored-procedure XML output - Supports Microsoft SQL / StoredProcedure as a physical output target. - Passes the generated XML payload through the configured stored procedure parameter. 8. Added optional XML payload archiving - Allows generated XML payloads to be stored in the configured Payload archive. - Can be used together with the Microsoft SQL stored-procedure output. 9. Kept ResultsWriter independent of the physical output target - ResultsWriter generates the result payload. - UniDataStorageWriter decides how and where the payload is physically written. - The same ResultsWriter XML generation mechanism is therefore used for both XML file and MSSQL outputs. 10. Increased revision - Updated revision to 3.9.3145.100.
192 lines
4.8 KiB
C#
192 lines
4.8 KiB
C#
///
|
|
/// Copyright (c) 2026 Sensus Slovensko a.s.
|
|
///
|
|
|
|
using Results;
|
|
using Results.Forms;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Windows.Forms;
|
|
using TBF.Resources;
|
|
|
|
namespace TBF.Rig.Output.DB.ResultsWriter
|
|
{
|
|
/// <summary>
|
|
/// Configures ResultsWriter result items and optional XML destinations.
|
|
/// </summary>
|
|
public partial class ResultsWriterResultsDlg : Form
|
|
{
|
|
private string payloadTemplatePath;
|
|
|
|
public IList<WMeterRsltItemSpec> SelectedItems
|
|
{
|
|
set { resultsConfigCtrl.SelectedItems = value; }
|
|
get { return resultsConfigCtrl.SelectedItems; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets or sets the customer XML reference path.
|
|
/// </summary>
|
|
public string PayloadTemplatePath
|
|
{
|
|
get { return payloadTemplatePath; }
|
|
set { payloadTemplatePath = value; }
|
|
}
|
|
|
|
public ResultsWriterResultsDlg()
|
|
{
|
|
InitializeComponent();
|
|
|
|
Icon =
|
|
Properties.Resources.TBF_icon;
|
|
|
|
resultsConfigCtrl.SupressTestIDColumn =
|
|
true;
|
|
|
|
}
|
|
|
|
private void ResultsWriterResultsDlg_Load(
|
|
object sender,
|
|
EventArgs e)
|
|
{
|
|
Text =
|
|
"ResultsWriter configuration";
|
|
|
|
okButton.Text =
|
|
Strings.OkBtnText;
|
|
|
|
cancelButton.Text =
|
|
Strings.CancelBtnText;
|
|
|
|
resultsConfigCtrl.Unlocked =
|
|
true;
|
|
|
|
ConfigureCaptionEditor();
|
|
}
|
|
|
|
private void ConfigureCaptionEditor()
|
|
{
|
|
bool xmlMode =
|
|
!string.IsNullOrWhiteSpace(
|
|
PayloadTemplatePath);
|
|
|
|
if (!xmlMode)
|
|
{
|
|
resultsConfigCtrl.CaptionPicker =
|
|
null;
|
|
|
|
resultsConfigCtrl.CaptionColumnText =
|
|
"Caption";
|
|
|
|
return;
|
|
}
|
|
|
|
resultsConfigCtrl.CaptionPicker =
|
|
PickXmlDestination;
|
|
|
|
resultsConfigCtrl.CaptionColumnText =
|
|
"Destination [...]";
|
|
}
|
|
|
|
private string PickXmlDestination(
|
|
WMeterRsltItemSpec editedItem)
|
|
{
|
|
if (editedItem == null)
|
|
return null;
|
|
|
|
using (XmlDestinationPickerDlg dlg =
|
|
new XmlDestinationPickerDlg())
|
|
{
|
|
dlg.TemplatePath =
|
|
PayloadTemplatePath;
|
|
|
|
dlg.CurrentSourceName =
|
|
editedItem.Name;
|
|
|
|
dlg.CurrentDestinationPath =
|
|
editedItem.Caption;
|
|
|
|
dlg.ConfiguredMappings =
|
|
BuildConfiguredMappings(
|
|
editedItem);
|
|
|
|
if (dlg.ShowDialog(this) ==
|
|
DialogResult.OK)
|
|
{
|
|
return dlg.SelectedDestinationPath;
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
private IDictionary<string, IList<string>> BuildConfiguredMappings(
|
|
WMeterRsltItemSpec editedItem)
|
|
{
|
|
Dictionary<string, IList<string>> mappings =
|
|
new Dictionary<string, IList<string>>(
|
|
StringComparer.Ordinal);
|
|
|
|
if (resultsConfigCtrl.SelectedItems != null)
|
|
{
|
|
foreach (WMeterRsltItemSpec item
|
|
in resultsConfigCtrl.SelectedItems)
|
|
{
|
|
if (item == null ||
|
|
object.ReferenceEquals(
|
|
item,
|
|
editedItem) ||
|
|
string.IsNullOrWhiteSpace(
|
|
item.Caption))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
AddMapping(
|
|
mappings,
|
|
item.Caption,
|
|
item.Name);
|
|
}
|
|
}
|
|
|
|
return mappings;
|
|
}
|
|
|
|
private void AddMapping(
|
|
IDictionary<string, IList<string>> mappings,
|
|
string path,
|
|
string sourceName)
|
|
{
|
|
if (string.IsNullOrWhiteSpace(path))
|
|
return;
|
|
|
|
IList<string> names;
|
|
|
|
if (!mappings.TryGetValue(
|
|
path,
|
|
out names))
|
|
{
|
|
names =
|
|
new List<string>();
|
|
|
|
mappings.Add(
|
|
path,
|
|
names);
|
|
}
|
|
|
|
if (!names.Contains(sourceName))
|
|
names.Add(sourceName);
|
|
}
|
|
|
|
private void okButton_Click(
|
|
object sender,
|
|
EventArgs e)
|
|
{
|
|
DialogResult =
|
|
DialogResult.OK;
|
|
|
|
Close();
|
|
}
|
|
}
|
|
}
|