Merge branch UniDataStorageWriter

This commit is contained in:
Marek Frniak 2026-04-12 10:49:16 +02:00
commit ef146efaf0
22 changed files with 2483 additions and 0 deletions

View File

@ -0,0 +1,53 @@
using System.Text;
namespace TBF.Rig.Output.DataStorage.UniDataStorageWriter
{
/// <summary>
/// Diagnostic result for writer source testing and write execution.
/// </summary>
public class WriterDiagnosticResult
{
public bool Success { get; set; }
public string Message { get; set; }
/// <summary>
/// Final resolved template/query/body actually executed by writer.
/// </summary>
public string ExecutedTemplate { get; set; }
public static WriterDiagnosticResult Ok(string message = null)
{
return new WriterDiagnosticResult
{
Success = true,
Message = message
};
}
public static WriterDiagnosticResult Fail(string message)
{
return new WriterDiagnosticResult
{
Success = false,
Message = message
};
}
public string ToDisplayDiag()
{
StringBuilder sb = new StringBuilder();
sb.AppendLine("Success: " + Success);
sb.AppendLine("Message: " + (string.IsNullOrWhiteSpace(Message) ? "<empty>" : Message));
if (!string.IsNullOrWhiteSpace(ExecutedTemplate))
{
sb.AppendLine("Executed template:");
sb.AppendLine(ExecutedTemplate);
}
return sb.ToString();
}
}
}

View File

@ -0,0 +1,51 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
namespace TBF.Rig.Output.DataStorage.UniDataStorageWriter
{
/// <summary>
/// Helper class to assign descriptions to enum values
/// </summary>
public class Description : Attribute
{
public string Text;
public Description(string t)
{
Text = t;
}
}
public static class GetDescription
{
/// Extension method for enum-s
public static string ToDescription(this Enum en)
{
Type type = en.GetType();
MemberInfo[] memInfo = type.GetMember(en.ToString());
if (memInfo != null && memInfo.Length > 0)
{
object[] attrs = memInfo[0].GetCustomAttributes(typeof(Description), false);
if (attrs != null && attrs.Length > 0)
return ((Description)attrs[0]).Text;
}
return en.ToString(); /// Return ToString() value in case there is no description
}
}
/// <summary>
/// Identifies the type of data storage
/// </summary>
public enum DataStorageType
{
RestApi,
Database,
Json,
Csv
}
}

View File

@ -0,0 +1,38 @@
///
/// Copyright (c) 2018 Sensus Slovensko a.s.
///
using System;
using System.Collections.Generic;
using TBF.Rig.Generic;
namespace TBF.Rig.Output.DataStorage.UniDataStorageWriter
{
/// <summary>
/// Factory component 'UniDataStorageWriter' implements more storing modules
/// Modules:
/// </summary>
public class Factory : IComponentFactory
{
public string ClassName { get { return GetType().Namespace.Substring(8); } } /// For backward compatibility
public override string ToString() { return ClassName; }
public IComponent DummyComponent() { return new Writer(new WriterCfg("UniDataStorageWriter", this)); }
public IComponent GetComponent(IComponentCfg cfg, IList<IComponent> components)
{
WriterCfg WriterCfg = cfg as WriterCfg;
if (WriterCfg == null)
throw new ArgumentException("Invalid config for UniDataStorageWriter");
return new Writer(WriterCfg);
}
public IComponentCfg DefaultConfig() { return new WriterCfg("UniDataStorageWriter", this); }
public IComponentCfg CmpntCfgFromCmpntEntity(Config.Entities.Component component)
{
return ComponentCfgBase.CreateFromDbEntity(WriterCfg.Serializer, component, this);
}
}
}

View File

@ -0,0 +1,59 @@
using System.Collections.Generic;
namespace TBF.Rig.Output.DataStorage.UniDataStorageWriter.Interfaces
{
/// <summary>
/// Request for write operation.
/// Contains batch of write items.
/// </summary>
public class DataWriteRequest
{
public DataWriteRequest()
{
InsertItems = new List<InsertWriteItem>();
UpdateItems = new List<UpdateWriteItem>();
Mode = WriteMode.Insert;
}
public string TargetName { get; set; }
public WriteMode Mode { get; set; }
public List<InsertWriteItem> InsertItems { get; private set; }
public List<UpdateWriteItem> UpdateItems { get; private set; }
}
public enum WriteMode
{
Insert,
Update,
Upsert,
Append
}
public class InsertWriteItem
{
public string ColumnName { get; set; }
public string Value { get; set; }
public override string ToString()
{
return $"{ColumnName} = {Value}";
}
}
public class UpdateWriteItem
{
public string WhereParameterName { get; set; }
public string WhereValue { get; set; }
public string SetParameterName { get; set; }
public string SetValue { get; set; }
public override string ToString()
{
return $"WHERE {WhereParameterName} = {WhereValue} -> SET {SetParameterName} = {SetValue}";
}
}
}

View File

@ -0,0 +1,15 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TBF.Rig.Output.DataStorage.UniDataStorageWriter.Interfaces;
namespace TBF.Rig.Output.DataStorage.UniDataStorageWriter
{
public interface IDataStorageWriter
{
WriterDiagnosticResult TestSource(bool validateOnly);
WriterDiagnosticResult WriteData(DataWriteRequest request);
}
}

View File

@ -0,0 +1,65 @@
using System;
namespace TBF.Rig.Input.DataStorage.UniDataStorageWriter.Searching
{
/// <summary>
/// Parsed representation of QueryTemplate expression.
/// Example:
/// SELECT [Password] WHERE [PcbId] = QUERYPARAM
/// </summary>
public class SearchOrderDefinition
{
/// <summary>
/// Column to be returned.
/// </summary>
public ColumnReference SelectColumn { get; set; }
/// <summary>
/// Column used for lookup.
/// </summary>
public ColumnReference WhereColumn { get; set; }
}
/// <summary>
/// Represents a column reference either by name or by zero-based index.
/// </summary>
public class ColumnReference
{
/// <summary>
/// Column name if referenced by [ColumnName].
/// </summary>
public string Name { get; set; }
/// <summary>
/// Zero-based column index if referenced by COLUMN(n).
/// </summary>
public int? Index { get; set; }
/// <summary>
/// Returns true if reference is by column name.
/// </summary>
public bool HasName
{
get { return !string.IsNullOrWhiteSpace(Name); }
}
/// <summary>
/// Returns true if reference is by column index.
/// </summary>
public bool HasIndex
{
get { return Index.HasValue; }
}
public override string ToString()
{
if (HasName)
return "[" + Name + "]";
if (HasIndex)
return "COLUMN(" + Index.Value + ")";
return "<undefined column reference>";
}
}
}

View File

@ -0,0 +1,87 @@
using System;
using System.Text.RegularExpressions;
using TBF.Rig.Input.DataStorage.UniDataStorageWriter.Searching;
namespace TBF.Rig.Input.DataStorage.UniDataStorageWriter
{
/// <summary>
/// Parses SQL-like QueryTemplate expressions.
/// Supported syntax:
/// SELECT [ReturnColumn] WHERE [MatchColumn] = QUERYPARAM
/// SELECT COLUMN(1) WHERE COLUMN(0) = QUERYPARAM
/// Mixed forms are also supported.
/// </summary>
public static class SearchOrderParser
{
private static readonly Regex FullPattern = new Regex(
@"^\s*SELECT\s+(?<select>\[[^\]]+\]|COLUMN\(\d+\))\s+WHERE\s+(?<where>\[[^\]]+\]|COLUMN\(\d+\))\s*=\s*QUERYPARAM\s*$",
RegexOptions.IgnoreCase | RegexOptions.Compiled);
private static readonly Regex NamedColumnPattern = new Regex(
@"^\[(?<name>[^\]]+)\]$",
RegexOptions.IgnoreCase | RegexOptions.Compiled);
private static readonly Regex IndexedColumnPattern = new Regex(
@"^COLUMN\((?<index>\d+)\)$",
RegexOptions.IgnoreCase | RegexOptions.Compiled);
/// <summary>
/// Parses QueryTemplate text into structured definition.
/// Throws if syntax is invalid.
/// </summary>
public static SearchOrderDefinition Parse(string searchOrder)
{
if (string.IsNullOrWhiteSpace(searchOrder))
throw new InvalidOperationException("QueryTemplate is empty.");
Match match = FullPattern.Match(searchOrder);
if (!match.Success)
{
throw new InvalidOperationException(
"Invalid QueryTemplate syntax. Expected: SELECT [ReturnColumn] WHERE [MatchColumn] = QUERYPARAM");
}
string selectToken = match.Groups["select"].Value;
string whereToken = match.Groups["where"].Value;
return new SearchOrderDefinition
{
SelectColumn = ParseColumnReference(selectToken),
WhereColumn = ParseColumnReference(whereToken)
};
}
/// <summary>
/// Parses one column reference token:
/// [ColumnName] or COLUMN(number)
/// </summary>
private static ColumnReference ParseColumnReference(string token)
{
if (string.IsNullOrWhiteSpace(token))
throw new InvalidOperationException("Column reference token is empty.");
Match nameMatch = NamedColumnPattern.Match(token);
if (nameMatch.Success)
{
return new ColumnReference
{
Name = nameMatch.Groups["name"].Value.Trim(),
Index = null
};
}
Match indexMatch = IndexedColumnPattern.Match(token);
if (indexMatch.Success)
{
return new ColumnReference
{
Name = null,
Index = int.Parse(indexMatch.Groups["index"].Value)
};
}
throw new InvalidOperationException(
"Invalid column reference '" + token + "'. Use [ColumnName] or COLUMN(number).");
}
}
}

View File

@ -0,0 +1,19 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace TBF.Rig.Output.DataStorage.UniDataStorageWriter
{
public static class StorageTypes
{
public const string RestApi = "REST_API";
public const string RemoteDatabase = "REMOTE_DATABASE";
public const string RemoteJson = "REMOTE_JSON";
public const string RemoteCsv = "REMOTE_CSV";
public const string LocalDatabase = "LOCAL_DATABASE";
public const string LocalJson = "LOCAL_JSON";
public const string LocalCsv = "LOCAL_CSV";
}
}

View File

@ -0,0 +1,58 @@
namespace TBF.Rig.Output.DataStorage.UniDataStorageWriter.UI
{
partial class xamplesForm
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.mainPanel = new System.Windows.Forms.Panel();
this.SuspendLayout();
//
// mainPanel
//
this.mainPanel.Dock = System.Windows.Forms.DockStyle.Fill;
this.mainPanel.Location = new System.Drawing.Point(0, 0);
this.mainPanel.Name = "mainPanel";
this.mainPanel.Size = new System.Drawing.Size(384, 161);
this.mainPanel.TabIndex = 0;
//
// xamplesForm
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(384, 161);
this.Controls.Add(this.mainPanel);
this.Name = "xamplesForm";
this.Text = "Examples";
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.Panel mainPanel;
}
}

View File

@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace TBF.Rig.Output.DataStorage.UniDataStorageWriter.UI
{
public partial class xamplesForm : Form
{
public xamplesForm()
{
InitializeComponent();
}
}
}

View File

@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="Writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceWriter how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the Writer can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View File

@ -0,0 +1,411 @@
using Common;
using System;
using System.Collections.Generic;
using System.Text;
using TBF.Rig.Generic;
using TBF.Rig.Output.DataStorage.UniDataStorageWriter.Interfaces;
using TBF.Rig.Output.DataStorage.UniDataStorageWriter.Writers;
namespace TBF.Rig.Output.DataStorage.UniDataStorageWriter.UI
{
/// <summary>
/// UI configuration control for UniDataStorageWriter.
/// Insert format: Column_Value
/// Update format: WhereName_WhereValue_SetName_SetValue
/// </summary>
public partial class WriterCfgCtrl : Configs.ConfigCtrlUtils, IComponentCfgCtrl
{
private readonly List<string> batchWriteLines = new List<string>();
public bool ShowMore { get { return false; } }
private WriterCfg config;
public IComponentCfg Config
{
get { return config as IComponentCfg; }
set
{
config = value as WriterCfg;
Redraw();
}
}
public WriterCfgCtrl()
{
InitializeComponent();
connectToDataSourceButton.Click += testByDataSourceButton_Click;
writeDataByParamAndTemplateButton.Click += writeDataByParamAndTemplateButton_Click;
buttonAddParam.Click += buttonAddParam_Click;
buttonRemoveParam.Click += buttonRemoveParam_Click;
writeModeComboBox.SelectedIndexChanged += writeModeComboBox_SelectedIndexChanged;
}
private void WriterCfgCtrl_Load(object sender, EventArgs e)
{
writeModeComboBox.Items.Clear();
writeModeComboBox.Items.Add(WriteMode.Insert.ToString());
writeModeComboBox.Items.Add(WriteMode.Update.ToString());
if (writeModeComboBox.Items.Count > 0)
writeModeComboBox.SelectedIndex = 0;
UpdateInputHint();
if (config != null)
Redraw();
}
public void Closing()
{
}
private void Redraw()
{
if (config == null)
return;
classNameLabel.Text = config.Factory.ClassName;
nameTextBox.Text = config.Name;
dataSourceTextBox.Text = config.DataSource;
writeTemplateTextBox.Text = config.QueryTemplate;
dataStorageTypeComboBox.Items.Clear();
ICollection<string> values = config.ParamValues(0);
if (values != null)
{
foreach (string item in values)
dataStorageTypeComboBox.Items.Add(item);
}
dataStorageTypeComboBox.Text = config.DataStorageType;
RefreshWriteParamsListBox();
}
public void Unlock()
{
nameTextBox.Enabled = true;
dataStorageTypeComboBox.Enabled = true;
dataSourceTextBox.Enabled = true;
writeTemplateTextBox.Enabled = true;
sourceTestResultTextBox.Enabled = true;
sourceTestResultTextBox.ReadOnly = true;
writeTestResultTextBox.Enabled = true;
writeTestResultTextBox.ReadOnly = true;
writeParamValueTextBox.Enabled = true;
listBoxWriteParams.Enabled = true;
buttonAddParam.Enabled = true;
buttonRemoveParam.Enabled = true;
writeModeComboBox.Enabled = true;
targetNameTextBox.Enabled = true;
}
public CfgUpdateFlags VerifyCfg(ref string message)
{
return CfgUpdateFlags.None;
}
public CfgUpdateFlags UpdateCfg()
{
CfgUpdateFlags flags = CfgUpdateFlags.None;
if (config == null)
return CfgUpdateFlags.Error;
if (config.Name != nameTextBox.Text)
{
config.Name = nameTextBox.Text;
flags |= (CfgUpdateFlags.AnyChange | CfgUpdateFlags.RestartRqrd);
}
flags |= UpdateDifferent(ref config.DataStorageType, dataStorageTypeComboBox.Text, CfgUpdateFlags.AnyChange | CfgUpdateFlags.RestartRqrd);
flags |= UpdateDifferent(ref config.DataSource, dataSourceTextBox.Text, CfgUpdateFlags.AnyChange | CfgUpdateFlags.RestartRqrd);
flags |= UpdateDifferent(ref config.QueryTemplate, writeTemplateTextBox.Text, CfgUpdateFlags.AnyChange | CfgUpdateFlags.RestartRqrd);
return flags;
}
private WriterCfg BuildTemporaryConfigFromUi()
{
WriterCfg tmpCfg = new WriterCfg(
string.IsNullOrWhiteSpace(nameTextBox.Text) ? "UniDataStorageWriter" : nameTextBox.Text,
config != null ? config.Factory : new Factory());
tmpCfg.DataStorageType = (dataStorageTypeComboBox.Text ?? string.Empty).Trim();
tmpCfg.DataSource = dataSourceTextBox.Text;
tmpCfg.QueryTemplate = writeTemplateTextBox.Text;
return tmpCfg;
}
private IDataStorageWriter CreateWriter(WriterCfg cfg)
{
switch ((cfg.DataStorageType ?? string.Empty).Trim())
{
case StorageTypes.RestApi:
return new RestApiWriter(cfg);
case StorageTypes.RemoteDatabase:
case StorageTypes.LocalDatabase:
return new DatabaseWriter(cfg);
case StorageTypes.RemoteJson:
case StorageTypes.LocalJson:
return new JsonWriter(cfg);
case StorageTypes.RemoteCsv:
case StorageTypes.LocalCsv:
return new CsvWriter(cfg);
default:
throw new NotSupportedException(
string.Format("Unsupported DataStorageType: '{0}'", cfg.DataStorageType));
}
}
private void testByDataSourceButton_Click(object sender, EventArgs e)
{
sourceTestResultTextBox.Clear();
try
{
WriterCfg cfg = BuildTemporaryConfigFromUi();
IDataStorageWriter writer = CreateWriter(cfg);
WriterDiagnosticResult result = writer.TestSource(true);
sourceTestResultTextBox.Text =
BuildDiagnosticHeader(cfg, "Source test") +
result.ToDisplayDiag();
}
catch (Exception ex)
{
sourceTestResultTextBox.Text = BuildExceptionText("Data source test failed", ex);
}
}
private void writeDataByParamAndTemplateButton_Click(object sender, EventArgs e)
{
writeTestResultTextBox.Clear();
try
{
if (batchWriteLines.Count == 0)
throw new InvalidOperationException("At least one batch test item must be provided.");
WriterCfg cfg = BuildTemporaryConfigFromUi();
IDataStorageWriter writer = CreateWriter(cfg);
DataWriteRequest request = BuildWriteRequest();
WriterDiagnosticResult result = writer.WriteData(request);
writeTestResultTextBox.Text =
BuildDiagnosticHeader(cfg, "Write test") +
(result != null ? result.ToDisplayDiag() : "<null>");
}
catch (Exception ex)
{
writeTestResultTextBox.Text = BuildExceptionText("WriteData test failed", ex);
}
}
private DataWriteRequest BuildWriteRequest()
{
DataWriteRequest request = new DataWriteRequest();
request.TargetName = (targetNameTextBox.Text ?? string.Empty).Trim();
WriteMode mode;
if (!Enum.TryParse(writeModeComboBox.Text, true, out mode))
mode = WriteMode.Insert;
request.Mode = mode;
foreach (string line in batchWriteLines)
{
if (mode == WriteMode.Insert)
{
request.InsertItems.Add(ParseInsertItem(line));
}
else if (mode == WriteMode.Update)
{
request.UpdateItems.Add(ParseUpdateItem(line));
}
}
return request;
}
private InsertWriteItem ParseInsertItem(string text)
{
if (string.IsNullOrWhiteSpace(text))
throw new InvalidOperationException("Insert item is empty.");
string[] parts = text.Split(';');
if (parts.Length != 2)
throw new InvalidOperationException("Insert format must be: Column;Value");
return new InsertWriteItem
{
ColumnName = parts[0].Trim(),
Value = parts[1].Trim()
};
}
private UpdateWriteItem ParseUpdateItem(string text)
{
if (string.IsNullOrWhiteSpace(text))
throw new InvalidOperationException("Update item is empty.");
string[] parts = text.Split(';');
if (parts.Length != 4)
throw new InvalidOperationException("Update format must be: WhereName;WhereValue;SetName;SetValue");
return new UpdateWriteItem
{
WhereParameterName = parts[0].Trim(),
WhereValue = parts[1].Trim(),
SetParameterName = parts[2].Trim(),
SetValue = parts[3].Trim()
};
}
private void buttonAddParam_Click(object sender, EventArgs e)
{
string text = writeParamValueTextBox.Text == null
? string.Empty
: writeParamValueTextBox.Text.Trim();
if (string.IsNullOrWhiteSpace(text))
return;
WriteMode mode;
if (!Enum.TryParse(writeModeComboBox.Text, true, out mode))
mode = WriteMode.Insert;
if (mode == WriteMode.Insert)
ParseInsertItem(text);
else if (mode == WriteMode.Update)
ParseUpdateItem(text);
batchWriteLines.Add(text);
writeParamValueTextBox.Clear();
RefreshWriteParamsListBox();
}
private void buttonRemoveParam_Click(object sender, EventArgs e)
{
int index = listBoxWriteParams.SelectedIndex;
if (index < 0 || index >= batchWriteLines.Count)
return;
batchWriteLines.RemoveAt(index);
RefreshWriteParamsListBox();
}
private void RefreshWriteParamsListBox()
{
listBoxWriteParams.Items.Clear();
for (int i = 0; i < batchWriteLines.Count; i++)
{
listBoxWriteParams.Items.Add(string.Format("{0}. {1}", i + 1, batchWriteLines[i]));
}
}
private void writeModeComboBox_SelectedIndexChanged(object sender, EventArgs e)
{
UpdateInputHint();
}
private void UpdateInputHint()
{
if (writeModeComboBox.Text == WriteMode.Insert.ToString())
{
labelParamValue.Text = "Insert: Column;Value";
writeParamValueTextBox.Text = "Column;Value";
}
else
{
labelParamValue.Text = "Update: WhereName;WhereValue;SetName;SetValue";
writeParamValueTextBox.Text = "WhereName;WhereValue;SetName;SetValue";
}
}
private string BuildDiagnosticHeader(WriterCfg cfg, string testName)
{
StringBuilder sb = new StringBuilder();
sb.AppendLine("=== " + testName + " ===");
sb.AppendLine("Storage type: " + StorageTypeToDisplayName(cfg.DataStorageType));
sb.AppendLine("Data source: " + Safe(cfg.DataSource));
sb.AppendLine("Write mode: " + Safe(writeModeComboBox.Text));
sb.AppendLine("Target name: " + Safe(targetNameTextBox.Text));
sb.AppendLine("Query template: " + Safe(cfg.QueryTemplate));
sb.AppendLine();
return sb.ToString();
}
private string BuildExceptionText(string title, Exception ex)
{
StringBuilder sb = new StringBuilder();
sb.AppendLine(title + ":");
sb.AppendLine(ex.Message);
Exception inner = ex.InnerException;
while (inner != null)
{
sb.AppendLine();
sb.AppendLine("Inner exception:");
sb.AppendLine(inner.Message);
inner = inner.InnerException;
}
return sb.ToString();
}
private string Safe(string text)
{
return string.IsNullOrWhiteSpace(text) ? "<empty>" : text;
}
private string StorageTypeToDisplayName(string storageType)
{
switch ((storageType ?? string.Empty).Trim())
{
case StorageTypes.RestApi:
return "REST API";
case StorageTypes.RemoteDatabase:
return "Remote database";
case StorageTypes.RemoteJson:
return "Remote JSON";
case StorageTypes.RemoteCsv:
return "Remote CSV";
case StorageTypes.LocalDatabase:
return "Local database";
case StorageTypes.LocalJson:
return "Local JSON";
case StorageTypes.LocalCsv:
return "Local CSV";
default:
return Safe(storageType);
}
}
}
}

View File

@ -0,0 +1,497 @@
///
/// Copyright (c) 2018 Sensus Slovensko a.s.
///
namespace TBF.Rig.Output.DataStorage.UniDataStorageWriter.UI
{
partial class WriterCfgCtrl
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Component Designer generated code
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
this.nameTextBox = new System.Windows.Forms.TextBox();
this.nameLabel = new System.Windows.Forms.Label();
this.classNameLabel = new System.Windows.Forms.Label();
this.dataStorageTypeLabel = new System.Windows.Forms.Label();
this.dataStorageTypeComboBox = new System.Windows.Forms.ComboBox();
this.groupBox1 = new System.Windows.Forms.GroupBox();
this.info2Button = new System.Windows.Forms.Button();
this.sourceTestResultTextBox = new System.Windows.Forms.TextBox();
this.connectToDataSourceButton = new System.Windows.Forms.Button();
this.backgroundWorker1 = new System.ComponentModel.BackgroundWorker();
this.groupBox2 = new System.Windows.Forms.GroupBox();
this.info4Button = new System.Windows.Forms.Button();
this.writeTestResultTextBox = new System.Windows.Forms.TextBox();
this.writeDataByParamAndTemplateButton = new System.Windows.Forms.Button();
this.backgroundWorker2 = new System.ComponentModel.BackgroundWorker();
this.groupBox3 = new System.Windows.Forms.GroupBox();
this.buttonRemoveParam = new System.Windows.Forms.Button();
this.buttonAddParam = new System.Windows.Forms.Button();
this.labelParamValue = new System.Windows.Forms.Label();
this.listBoxWriteParams = new System.Windows.Forms.ListBox();
this.writeParamValueTextBox = new System.Windows.Forms.TextBox();
this.info5Button = new System.Windows.Forms.Button();
this.backgroundWorker3 = new System.ComponentModel.BackgroundWorker();
this.contextMenuStrip1 = new System.Windows.Forms.ContextMenuStrip(this.components);
this.groupBox4 = new System.Windows.Forms.GroupBox();
this.label2 = new System.Windows.Forms.Label();
this.info1Button = new System.Windows.Forms.Button();
this.dataSourceLabel = new System.Windows.Forms.Label();
this.dataSourceTextBox = new System.Windows.Forms.TextBox();
this.groupBox5 = new System.Windows.Forms.GroupBox();
this.targetNameTextBox = new System.Windows.Forms.TextBox();
this.targetNameLabel = new System.Windows.Forms.Label();
this.writeModeComboBox = new System.Windows.Forms.ComboBox();
this.writeModeLabel = new System.Windows.Forms.Label();
this.label3 = new System.Windows.Forms.Label();
this.info3Button = new System.Windows.Forms.Button();
this.examples1Button = new System.Windows.Forms.Button();
this.writeTemplateTextBox = new System.Windows.Forms.TextBox();
this.writeTemplateLabel = new System.Windows.Forms.Label();
this.groupBox1.SuspendLayout();
this.groupBox2.SuspendLayout();
this.groupBox3.SuspendLayout();
this.groupBox4.SuspendLayout();
this.groupBox5.SuspendLayout();
this.SuspendLayout();
//
// nameTextBox
//
this.nameTextBox.Enabled = false;
this.nameTextBox.Location = new System.Drawing.Point(117, 32);
this.nameTextBox.Name = "nameTextBox";
this.nameTextBox.Size = new System.Drawing.Size(326, 20);
this.nameTextBox.TabIndex = 2;
//
// nameLabel
//
this.nameLabel.AutoSize = true;
this.nameLabel.Location = new System.Drawing.Point(5, 35);
this.nameLabel.Name = "nameLabel";
this.nameLabel.Size = new System.Drawing.Size(38, 13);
this.nameLabel.TabIndex = 1;
this.nameLabel.Text = "Name:";
//
// classNameLabel
//
this.classNameLabel.AutoSize = true;
this.classNameLabel.Location = new System.Drawing.Point(114, 10);
this.classNameLabel.Name = "classNameLabel";
this.classNameLabel.Size = new System.Drawing.Size(89, 13);
this.classNameLabel.TabIndex = 0;
this.classNameLabel.Text = "ComponentName";
//
// dataStorageTypeLabel
//
this.dataStorageTypeLabel.AutoSize = true;
this.dataStorageTypeLabel.Location = new System.Drawing.Point(5, 61);
this.dataStorageTypeLabel.Name = "dataStorageTypeLabel";
this.dataStorageTypeLabel.Size = new System.Drawing.Size(94, 13);
this.dataStorageTypeLabel.TabIndex = 5;
this.dataStorageTypeLabel.Text = "Data storage type:";
//
// dataStorageTypeComboBox
//
this.dataStorageTypeComboBox.Enabled = false;
this.dataStorageTypeComboBox.FormattingEnabled = true;
this.dataStorageTypeComboBox.Location = new System.Drawing.Point(117, 58);
this.dataStorageTypeComboBox.Name = "dataStorageTypeComboBox";
this.dataStorageTypeComboBox.Size = new System.Drawing.Size(326, 21);
this.dataStorageTypeComboBox.TabIndex = 9;
//
// groupBox1
//
this.groupBox1.Controls.Add(this.info2Button);
this.groupBox1.Controls.Add(this.sourceTestResultTextBox);
this.groupBox1.Controls.Add(this.connectToDataSourceButton);
this.groupBox1.Location = new System.Drawing.Point(8, 233);
this.groupBox1.Name = "groupBox1";
this.groupBox1.Size = new System.Drawing.Size(473, 422);
this.groupBox1.TabIndex = 15;
this.groupBox1.TabStop = false;
this.groupBox1.Text = "Data storage source testing";
//
// info2Button
//
this.info2Button.Location = new System.Drawing.Point(417, 23);
this.info2Button.Name = "info2Button";
this.info2Button.Size = new System.Drawing.Size(35, 23);
this.info2Button.TabIndex = 21;
this.info2Button.Text = "Info";
this.info2Button.UseVisualStyleBackColor = true;
//
// sourceTestResultTextBox
//
this.sourceTestResultTextBox.Enabled = false;
this.sourceTestResultTextBox.Location = new System.Drawing.Point(15, 47);
this.sourceTestResultTextBox.Multiline = true;
this.sourceTestResultTextBox.Name = "sourceTestResultTextBox";
this.sourceTestResultTextBox.ScrollBars = System.Windows.Forms.ScrollBars.Both;
this.sourceTestResultTextBox.Size = new System.Drawing.Size(437, 358);
this.sourceTestResultTextBox.TabIndex = 15;
//
// connectToDataSourceButton
//
this.connectToDataSourceButton.Location = new System.Drawing.Point(15, 19);
this.connectToDataSourceButton.Name = "connectToDataSourceButton";
this.connectToDataSourceButton.Size = new System.Drawing.Size(131, 23);
this.connectToDataSourceButton.TabIndex = 14;
this.connectToDataSourceButton.Text = "Connect to Data source";
this.connectToDataSourceButton.UseVisualStyleBackColor = true;
//
// groupBox2
//
this.groupBox2.Controls.Add(this.info4Button);
this.groupBox2.Controls.Add(this.writeTestResultTextBox);
this.groupBox2.Controls.Add(this.writeDataByParamAndTemplateButton);
this.groupBox2.Location = new System.Drawing.Point(487, 233);
this.groupBox2.Name = "groupBox2";
this.groupBox2.Size = new System.Drawing.Size(463, 422);
this.groupBox2.TabIndex = 16;
this.groupBox2.TabStop = false;
this.groupBox2.Text = "Complete write testing";
//
// info4Button
//
this.info4Button.Location = new System.Drawing.Point(417, 23);
this.info4Button.Name = "info4Button";
this.info4Button.Size = new System.Drawing.Size(35, 23);
this.info4Button.TabIndex = 22;
this.info4Button.Text = "Info";
this.info4Button.UseVisualStyleBackColor = true;
//
// writeTestResultTextBox
//
this.writeTestResultTextBox.Enabled = false;
this.writeTestResultTextBox.Location = new System.Drawing.Point(6, 48);
this.writeTestResultTextBox.Multiline = true;
this.writeTestResultTextBox.Name = "writeTestResultTextBox";
this.writeTestResultTextBox.ScrollBars = System.Windows.Forms.ScrollBars.Both;
this.writeTestResultTextBox.Size = new System.Drawing.Size(446, 357);
this.writeTestResultTextBox.TabIndex = 18;
//
// writeDataByParamAndTemplateButton
//
this.writeDataByParamAndTemplateButton.Location = new System.Drawing.Point(6, 19);
this.writeDataByParamAndTemplateButton.Name = "writeDataByParamAndTemplateButton";
this.writeDataByParamAndTemplateButton.Size = new System.Drawing.Size(206, 23);
this.writeDataByParamAndTemplateButton.TabIndex = 17;
this.writeDataByParamAndTemplateButton.Text = "Write data by param and template";
this.writeDataByParamAndTemplateButton.UseVisualStyleBackColor = true;
//
// groupBox3
//
this.groupBox3.Controls.Add(this.buttonRemoveParam);
this.groupBox3.Controls.Add(this.buttonAddParam);
this.groupBox3.Controls.Add(this.labelParamValue);
this.groupBox3.Controls.Add(this.listBoxWriteParams);
this.groupBox3.Controls.Add(this.writeParamValueTextBox);
this.groupBox3.Controls.Add(this.info5Button);
this.groupBox3.Location = new System.Drawing.Point(956, 87);
this.groupBox3.Name = "groupBox3";
this.groupBox3.Size = new System.Drawing.Size(316, 568);
this.groupBox3.TabIndex = 17;
this.groupBox3.TabStop = false;
this.groupBox3.Text = "Component interface testing";
//
// buttonRemoveParam
//
this.buttonRemoveParam.Location = new System.Drawing.Point(85, 69);
this.buttonRemoveParam.Name = "buttonRemoveParam";
this.buttonRemoveParam.Size = new System.Drawing.Size(75, 23);
this.buttonRemoveParam.TabIndex = 25;
this.buttonRemoveParam.Text = "Remove";
this.buttonRemoveParam.UseVisualStyleBackColor = true;
//
// buttonAddParam
//
this.buttonAddParam.Location = new System.Drawing.Point(6, 69);
this.buttonAddParam.Name = "buttonAddParam";
this.buttonAddParam.Size = new System.Drawing.Size(75, 23);
this.buttonAddParam.TabIndex = 24;
this.buttonAddParam.Text = "Add";
this.buttonAddParam.UseVisualStyleBackColor = true;
//
// labelParamValue
//
this.labelParamValue.AutoSize = true;
this.labelParamValue.Location = new System.Drawing.Point(6, 24);
this.labelParamValue.Name = "labelParamValue";
this.labelParamValue.Size = new System.Drawing.Size(107, 13);
this.labelParamValue.TabIndex = 23;
this.labelParamValue.Text = "Insert: Column_Value";
//
// listBoxWriteParams
//
this.listBoxWriteParams.FormattingEnabled = true;
this.listBoxWriteParams.Location = new System.Drawing.Point(9, 98);
this.listBoxWriteParams.Name = "listBoxWriteParams";
this.listBoxWriteParams.Size = new System.Drawing.Size(297, 459);
this.listBoxWriteParams.TabIndex = 22;
//
// writeParamValueTextBox
//
this.writeParamValueTextBox.Location = new System.Drawing.Point(9, 40);
this.writeParamValueTextBox.Name = "writeParamValueTextBox";
this.writeParamValueTextBox.Size = new System.Drawing.Size(297, 20);
this.writeParamValueTextBox.TabIndex = 21;
//
// info5Button
//
this.info5Button.Location = new System.Drawing.Point(271, 15);
this.info5Button.Name = "info5Button";
this.info5Button.Size = new System.Drawing.Size(35, 23);
this.info5Button.TabIndex = 20;
this.info5Button.Text = "Info";
this.info5Button.UseVisualStyleBackColor = true;
//
// contextMenuStrip1
//
this.contextMenuStrip1.Name = "contextMenuStrip1";
this.contextMenuStrip1.Size = new System.Drawing.Size(61, 4);
//
// groupBox4
//
this.groupBox4.Controls.Add(this.label2);
this.groupBox4.Controls.Add(this.info1Button);
this.groupBox4.Controls.Add(this.dataSourceLabel);
this.groupBox4.Controls.Add(this.dataSourceTextBox);
this.groupBox4.Location = new System.Drawing.Point(8, 87);
this.groupBox4.Name = "groupBox4";
this.groupBox4.Size = new System.Drawing.Size(473, 140);
this.groupBox4.TabIndex = 22;
this.groupBox4.TabStop = false;
this.groupBox4.Text = "Data storage source setting";
//
// label2
//
this.label2.AutoSize = true;
this.label2.Location = new System.Drawing.Point(6, 25);
this.label2.Name = "label2";
this.label2.Size = new System.Drawing.Size(106, 13);
this.label2.TabIndex = 22;
this.label2.Text = "Data storage source:";
//
// info1Button
//
this.info1Button.Location = new System.Drawing.Point(417, 14);
this.info1Button.Name = "info1Button";
this.info1Button.Size = new System.Drawing.Size(35, 23);
this.info1Button.TabIndex = 21;
this.info1Button.Text = "Info";
this.info1Button.UseVisualStyleBackColor = true;
//
// dataSourceLabel
//
this.dataSourceLabel.AutoSize = true;
this.dataSourceLabel.Location = new System.Drawing.Point(-123, 1);
this.dataSourceLabel.Name = "dataSourceLabel";
this.dataSourceLabel.Size = new System.Drawing.Size(68, 13);
this.dataSourceLabel.TabIndex = 18;
this.dataSourceLabel.Text = "Data source:";
//
// dataSourceTextBox
//
this.dataSourceTextBox.Enabled = false;
this.dataSourceTextBox.Location = new System.Drawing.Point(6, 38);
this.dataSourceTextBox.Multiline = true;
this.dataSourceTextBox.Name = "dataSourceTextBox";
this.dataSourceTextBox.ScrollBars = System.Windows.Forms.ScrollBars.Both;
this.dataSourceTextBox.Size = new System.Drawing.Size(446, 89);
this.dataSourceTextBox.TabIndex = 17;
//
// groupBox5
//
this.groupBox5.Controls.Add(this.targetNameTextBox);
this.groupBox5.Controls.Add(this.targetNameLabel);
this.groupBox5.Controls.Add(this.writeModeComboBox);
this.groupBox5.Controls.Add(this.writeModeLabel);
this.groupBox5.Controls.Add(this.label3);
this.groupBox5.Controls.Add(this.info3Button);
this.groupBox5.Controls.Add(this.examples1Button);
this.groupBox5.Controls.Add(this.writeTemplateTextBox);
this.groupBox5.Controls.Add(this.writeTemplateLabel);
this.groupBox5.Location = new System.Drawing.Point(487, 87);
this.groupBox5.Name = "groupBox5";
this.groupBox5.Size = new System.Drawing.Size(462, 140);
this.groupBox5.TabIndex = 23;
this.groupBox5.TabStop = false;
this.groupBox5.Text = "Write template setting";
//
// targetNameTextBox
//
this.targetNameTextBox.Enabled = false;
this.targetNameTextBox.Location = new System.Drawing.Point(252, 14);
this.targetNameTextBox.Name = "targetNameTextBox";
this.targetNameTextBox.Size = new System.Drawing.Size(80, 20);
this.targetNameTextBox.TabIndex = 30;
//
// targetNameLabel
//
this.targetNameLabel.AutoSize = true;
this.targetNameLabel.Location = new System.Drawing.Point(186, 18);
this.targetNameLabel.Name = "targetNameLabel";
this.targetNameLabel.Size = new System.Drawing.Size(70, 13);
this.targetNameLabel.TabIndex = 29;
this.targetNameLabel.Text = "Target name:";
//
// writeModeComboBox
//
this.writeModeComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.writeModeComboBox.Enabled = false;
this.writeModeComboBox.FormattingEnabled = true;
this.writeModeComboBox.Location = new System.Drawing.Point(75, 14);
this.writeModeComboBox.Name = "writeModeComboBox";
this.writeModeComboBox.Size = new System.Drawing.Size(105, 21);
this.writeModeComboBox.TabIndex = 28;
//
// writeModeLabel
//
this.writeModeLabel.AutoSize = true;
this.writeModeLabel.Location = new System.Drawing.Point(6, 18);
this.writeModeLabel.Name = "writeModeLabel";
this.writeModeLabel.Size = new System.Drawing.Size(64, 13);
this.writeModeLabel.TabIndex = 27;
this.writeModeLabel.Text = "Write mode:";
//
// label3
//
this.label3.AutoSize = true;
this.label3.Location = new System.Drawing.Point(6, 41);
this.label3.Name = "label3";
this.label3.Size = new System.Drawing.Size(78, 13);
this.label3.TabIndex = 26;
this.label3.Text = "Write template:";
//
// info3Button
//
this.info3Button.Location = new System.Drawing.Point(419, 14);
this.info3Button.Name = "info3Button";
this.info3Button.Size = new System.Drawing.Size(35, 23);
this.info3Button.TabIndex = 25;
this.info3Button.Text = "Info";
this.info3Button.UseVisualStyleBackColor = true;
//
// examples1Button
//
this.examples1Button.Location = new System.Drawing.Point(338, 14);
this.examples1Button.Name = "examples1Button";
this.examples1Button.Size = new System.Drawing.Size(75, 23);
this.examples1Button.TabIndex = 24;
this.examples1Button.Text = "Examples";
this.examples1Button.UseVisualStyleBackColor = true;
//
// writeTemplateTextBox
//
this.writeTemplateTextBox.Enabled = false;
this.writeTemplateTextBox.Location = new System.Drawing.Point(8, 57);
this.writeTemplateTextBox.Multiline = true;
this.writeTemplateTextBox.Name = "writeTemplateTextBox";
this.writeTemplateTextBox.ScrollBars = System.Windows.Forms.ScrollBars.Both;
this.writeTemplateTextBox.Size = new System.Drawing.Size(446, 70);
this.writeTemplateTextBox.TabIndex = 23;
//
// writeTemplateLabel
//
this.writeTemplateLabel.AutoSize = true;
this.writeTemplateLabel.Location = new System.Drawing.Point(-123, 6);
this.writeTemplateLabel.Name = "writeTemplateLabel";
this.writeTemplateLabel.Size = new System.Drawing.Size(78, 13);
this.writeTemplateLabel.TabIndex = 22;
this.writeTemplateLabel.Text = "Write template:";
//
// WriterCfgCtrl
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.Controls.Add(this.groupBox5);
this.Controls.Add(this.groupBox4);
this.Controls.Add(this.groupBox3);
this.Controls.Add(this.groupBox2);
this.Controls.Add(this.groupBox1);
this.Controls.Add(this.dataStorageTypeComboBox);
this.Controls.Add(this.dataStorageTypeLabel);
this.Controls.Add(this.nameTextBox);
this.Controls.Add(this.nameLabel);
this.Controls.Add(this.classNameLabel);
this.Name = "WriterCfgCtrl";
this.Size = new System.Drawing.Size(1280, 671);
this.Load += new System.EventHandler(this.WriterCfgCtrl_Load);
this.groupBox1.ResumeLayout(false);
this.groupBox1.PerformLayout();
this.groupBox2.ResumeLayout(false);
this.groupBox2.PerformLayout();
this.groupBox3.ResumeLayout(false);
this.groupBox3.PerformLayout();
this.groupBox4.ResumeLayout(false);
this.groupBox4.PerformLayout();
this.groupBox5.ResumeLayout(false);
this.groupBox5.PerformLayout();
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.TextBox nameTextBox;
private System.Windows.Forms.Label nameLabel;
private System.Windows.Forms.Label classNameLabel;
private System.Windows.Forms.Label dataStorageTypeLabel;
private System.Windows.Forms.ComboBox dataStorageTypeComboBox;
private System.Windows.Forms.GroupBox groupBox1;
private System.Windows.Forms.Button info2Button;
private System.Windows.Forms.TextBox sourceTestResultTextBox;
private System.Windows.Forms.Button connectToDataSourceButton;
private System.ComponentModel.BackgroundWorker backgroundWorker1;
private System.Windows.Forms.GroupBox groupBox2;
private System.Windows.Forms.Button info4Button;
private System.Windows.Forms.TextBox writeTestResultTextBox;
private System.Windows.Forms.Button writeDataByParamAndTemplateButton;
private System.ComponentModel.BackgroundWorker backgroundWorker2;
private System.Windows.Forms.GroupBox groupBox3;
private System.Windows.Forms.Button buttonRemoveParam;
private System.Windows.Forms.Button buttonAddParam;
private System.Windows.Forms.Label labelParamValue;
private System.Windows.Forms.ListBox listBoxWriteParams;
private System.Windows.Forms.TextBox writeParamValueTextBox;
private System.Windows.Forms.Button info5Button;
private System.ComponentModel.BackgroundWorker backgroundWorker3;
private System.Windows.Forms.ContextMenuStrip contextMenuStrip1;
private System.Windows.Forms.GroupBox groupBox4;
private System.Windows.Forms.Label label2;
private System.Windows.Forms.Button info1Button;
private System.Windows.Forms.Label dataSourceLabel;
private System.Windows.Forms.TextBox dataSourceTextBox;
private System.Windows.Forms.GroupBox groupBox5;
private System.Windows.Forms.TextBox targetNameTextBox;
private System.Windows.Forms.Label targetNameLabel;
private System.Windows.Forms.ComboBox writeModeComboBox;
private System.Windows.Forms.Label writeModeLabel;
private System.Windows.Forms.Label label3;
private System.Windows.Forms.Button info3Button;
private System.Windows.Forms.Button examples1Button;
private System.Windows.Forms.TextBox writeTemplateTextBox;
private System.Windows.Forms.Label writeTemplateLabel;
}
}

View File

@ -0,0 +1,135 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<metadata name="backgroundWorker1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
<metadata name="backgroundWorker2.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>179, 17</value>
</metadata>
<metadata name="backgroundWorker3.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>341, 17</value>
</metadata>
<metadata name="contextMenuStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>503, 17</value>
</metadata>
<metadata name="$this.TrayHeight" type="System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>44</value>
</metadata>
</root>

View File

@ -0,0 +1,113 @@
using Common;
using Config.Entities;
using System;
using System.Collections.Generic;
using TBF.Rig.Generic;
using TBF.Rig.Output.DataStorage.UniDataStorageWriter.Interfaces;
using TBF.Rig.Output.DataStorage.UniDataStorageWriter.Writers;
using TBF.Rig.Scales.MettlerToledo;
using static TBF.Rig.Output.DataStorage.UniDataStorageWriter.WriterCfg;
namespace TBF.Rig.Output.DataStorage.UniDataStorageWriter
{
/// <summary>
/// Main component that selects appropriate data writer based on configuration.
/// Acts as a dispatcher between different storage implementations.
/// </summary>
public class Writer : IComponent
{
private readonly WriterCfg cfg;
public Writer(WriterCfg cfg)
{
this.cfg = cfg ?? throw new ArgumentNullException(nameof(cfg));
}
public string Name { get { return cfg.Name; } }
public string ClassName { get { return cfg.ClassName; } }
public string ParentName { get { return cfg.ParentName; } }
public DebugMode DebugLevel { get { return cfg.DebugLevel; } }
public LogLevel LogLevel { get { return cfg.LogLevel; } }
public IComponentCfg Cfg { get { return cfg; } }
public IList<MeasurementCorrection> Corrections
{
get => throw new NotImplementedException();
set => throw new NotImplementedException();
}
public IList<Uncertainty> Uncertainties
{
get => throw new NotImplementedException();
set => throw new NotImplementedException();
}
/// <summary>
/// Executes write operation using the configured storage writer.
/// </summary>
public WriterDiagnosticResult WriteDataToStorage(DataWriteRequest request)
{
IDataStorageWriter writer = CreateWriter();
return writer.WriteData(request);
}
/// <summary>
/// Tests configured storage source using the selected writer.
/// </summary>
public WriterDiagnosticResult TestSource(bool validateOnly)
{
IDataStorageWriter writer = CreateWriter();
return writer.TestSource(validateOnly);
}
/// <summary>
/// Creates appropriate writer implementation based on selected storage type.
/// </summary>
private IDataStorageWriter CreateWriter()
{
string storageType = (cfg.DataStorageType ?? string.Empty).Trim();
switch (storageType)
{
case StorageTypes.RestApi:
return new RestApiWriter(cfg);
case StorageTypes.RemoteDatabase:
case StorageTypes.LocalDatabase:
return new DatabaseWriter(cfg);
case StorageTypes.RemoteJson:
case StorageTypes.LocalJson:
return new JsonWriter(cfg);
case StorageTypes.RemoteCsv:
case StorageTypes.LocalCsv:
return new CsvWriter(cfg);
default:
throw new NotSupportedException(
string.Format("Unsupported DataStorageType: '{0}'", cfg.DataStorageType));
}
}
public void Initialize()
{
throw new NotImplementedException();
}
public void StartChangeHandler()
{
throw new NotImplementedException();
}
public void StopChangeHandler()
{
throw new NotImplementedException();
}
}
}

View File

@ -0,0 +1,244 @@
///
/// Copyright (c) 2018 Sensus Slovensko a.s.
///
using System;
using System.Collections.Generic;
using System.Xml.Serialization;
using Common;
using Config.Entities;
using TBF.Rig.Generic;
using TBF.Resources;
using TBF.Rig.Output.DataStorage.UniDataStorageWriter.UI;
namespace TBF.Rig.Output.DataStorage.UniDataStorageWriter
{
///
/// Class and file name is preserved for backward compatibility
///
public class WriterCfg : ComponentCfgBase, Generic.IComponentCfg, IParamsProvider
{
public static XmlSerializer Serializer = XmlSerializer.FromTypes(new[] { typeof(WriterCfg) })[0];
public override XmlSerializer GetSerializer() { return Serializer; }
public IComponentCfgCtrl GetControl(IList<Config.Entities.Component> cmpntEntities) { return new WriterCfgCtrl(); }
/// <summary>
/// Internal storage type identifier.
/// </summary>
public string DataStorageType;
/// <summary>
/// Data source definition, e.g. file path, connection string, URL, etc.
/// </summary>
public string DataSource;
/// <summary>
/// Original field name preserved for backward compatibility.
/// For writer semantics this represents the write template.
/// </summary>
public string QueryTemplate;
/// <summary>
/// Writer-friendly alias for QueryTemplate.
/// This property is not serialized to keep backward compatibility with existing XML.
/// </summary>
[XmlIgnore]
public string WriteTemplate
{
get { return QueryTemplate; }
set { QueryTemplate = value; }
}
/// <summary>
/// Private parameterless constructor invoked by all other constructors.
/// </summary>
WriterCfg()
{
InitializeAll();
}
public WriterCfg(string name, IComponentFactory factory)
: this()
{
this.Name = name;
this.Factory = factory;
}
public string ComponentName
{
get { return Name; }
}
public void InitializeAll()
{
DataStorageType = string.Empty;
DataSource = string.Empty;
QueryTemplate = string.Empty;
}
private readonly string[] paramNames = new string[]
{
"Data Storage type",
"Data source",
"Query template",
};
public string ParamName(int i) { return paramNames[i]; }
public int ParamsCount() { return paramNames.Length; }
public ICollection<string> ParamValues(int i)
{
switch (i)
{
case 0:
return new string[]
{
StorageTypes.RestApi,
StorageTypes.RemoteDatabase,
StorageTypes.RemoteJson,
StorageTypes.RemoteCsv,
StorageTypes.LocalDatabase,
StorageTypes.LocalJson,
StorageTypes.LocalCsv,
};
case 1:
case 2:
default:
return null;
}
}
public string ToString(int i)
{
return string.Format(
"Name={0}, DataStorageType={1}",
Name,
DataStorageType);
}
public CfgUpdateFlags UpdateParam(int i, string strValue)
{
switch (i)
{
case 0:
DataStorageType = strValue;
return CfgUpdateFlags.RestartRqrd;
case 1:
DataSource = strValue;
return CfgUpdateFlags.RestartRqrd;
case 2:
QueryTemplate = strValue;
return CfgUpdateFlags.RestartRqrd;
default:
return CfgUpdateFlags.None;
}
}
public bool ValidateParam(int i, string strValue, out string message)
{
message = string.Empty;
strValue = strValue ?? string.Empty;
switch (i)
{
case 0:
if (string.IsNullOrWhiteSpace(strValue))
{
message = "Data storage type must be selected.";
return false;
}
return true;
case 1:
if (string.IsNullOrWhiteSpace(strValue))
{
message = "Data source must not be empty.";
return false;
}
return true;
case 2:
if (string.IsNullOrWhiteSpace(strValue))
{
message = "Query template must not be empty.";
return false;
}
return true;
default:
message = "Invalid parameter index.";
return false;
}
}
private void CopyContentTo(WriterCfg prms)
{
prms.DataStorageType = this.DataStorageType;
prms.DataSource = this.DataSource;
prms.QueryTemplate = this.QueryTemplate;
}
public IParamsProvider Clone()
{
WriterCfg pars = new WriterCfg();
CopyContentTo(pars);
return pars;
}
/// <summary>
/// Strongly typed helper for internal use.
/// </summary>
public WriterCfg ShallowCopy()
{
WriterCfg copy = new WriterCfg(this.Name, this.Factory);
CopyContentTo(copy);
return copy;
}
public bool UpdateEmbeddedDbEntity()
{
return true; /// =OK, do nothing
}
/// <summary>
/// Converts internal storage type identifier to user-friendly name.
/// </summary>
public static string StorageTypeToDisplayName(string storageType)
{
switch ((storageType ?? string.Empty).Trim())
{
case StorageTypes.RestApi:
return "REST API";
case StorageTypes.RemoteDatabase:
return "Remote database";
case StorageTypes.RemoteJson:
return "Remote JSON";
case StorageTypes.RemoteCsv:
return "Remote CSV";
case StorageTypes.LocalDatabase:
return "Local database";
case StorageTypes.LocalJson:
return "Local JSON";
case StorageTypes.LocalCsv:
return "Local CSV";
default:
return string.IsNullOrWhiteSpace(storageType) ? "<empty>" : storageType;
}
}
}
}

View File

@ -0,0 +1,215 @@
using System;
using System.IO;
using System.Linq;
using System.Text;
using TBF.Rig.Output.DataStorage.UniDataStorageWriter.Interfaces;
namespace TBF.Rig.Output.DataStorage.UniDataStorageWriter.Writers
{
/// <summary>
/// CSV writer implementation for UniDataStorageWriter.
///
/// Insert:
/// request.InsertItems define one output CSV row.
///
/// Update:
/// currently implemented as append-only audit/log style output,
/// because true in-place CSV row update requires read-modify-rewrite logic.
/// </summary>
public class CsvWriter : IDataStorageWriter
{
private readonly WriterCfg cfg;
public CsvWriter(WriterCfg cfg)
{
this.cfg = cfg ?? throw new ArgumentNullException(nameof(cfg));
}
/// <summary>
/// Validates access to CSV file (and optionally creates it).
/// </summary>
public WriterDiagnosticResult TestSource(bool validateOnly)
{
try
{
if (string.IsNullOrWhiteSpace(cfg.DataSource))
return Fail("CSV file path is not defined.");
string path = cfg.DataSource;
string directory = Path.GetDirectoryName(path);
if (!string.IsNullOrWhiteSpace(directory) && !Directory.Exists(directory))
{
if (validateOnly)
return Fail("Directory does not exist: " + directory);
Directory.CreateDirectory(directory);
}
if (!File.Exists(path))
{
if (validateOnly)
return Ok("File does not exist but path is valid.");
using (File.Create(path))
{
}
}
return Ok("CSV source is ready.");
}
catch (Exception ex)
{
return Fail("CSV source test failed: " + ex.Message);
}
}
/// <summary>
/// Writes data into CSV file using current request mode.
/// </summary>
public WriterDiagnosticResult WriteData(DataWriteRequest request)
{
if (request == null)
throw new ArgumentNullException(nameof(request));
WriterDiagnosticResult test = TestSource(false);
if (!test.Success)
return test;
try
{
switch (request.Mode)
{
case WriteMode.Insert:
return ExecuteInsert(request);
case WriteMode.Update:
return ExecuteUpdate(request);
default:
return Fail("CSV mode not supported: " + request.Mode);
}
}
catch (Exception ex)
{
return Fail("CSV write failed: " + ex.Message);
}
}
/// <summary>
/// Insert mode:
/// request.InsertItems define a single CSV row.
/// Example:
/// SerialNumber=SN001
/// Result=PASS
/// Produces:
/// SN001;PASS
///
/// Current implementation writes only values, not header names.
/// </summary>
private WriterDiagnosticResult ExecuteInsert(DataWriteRequest request)
{
if (request.InsertItems == null || request.InsertItems.Count == 0)
return Fail("No insert items provided.");
string delimiter = ";";
string[] values = request.InsertItems
.Select(i => EscapeCsvValue(i != null ? i.Value : null))
.ToArray();
string line = string.Join(delimiter, values);
File.AppendAllText(cfg.DataSource, line + Environment.NewLine, Encoding.UTF8);
return new WriterDiagnosticResult
{
Success = true,
Message = "CSV insert OK. Written 1 row.",
ExecutedTemplate = line
};
}
/// <summary>
/// Update mode:
/// CSV has no natural SQL-style row update, so current implementation writes
/// an audit/log style line for each update item.
///
/// Example input:
/// SerialNumber=SN001;Result=PASS
/// Produces:
/// UPDATE;SerialNumber;SN001;Result;PASS
/// </summary>
private WriterDiagnosticResult ExecuteUpdate(DataWriteRequest request)
{
if (request.UpdateItems == null || request.UpdateItems.Count == 0)
return Fail("No update items provided.");
string delimiter = ";";
StringBuilder sb = new StringBuilder();
foreach (UpdateWriteItem item in request.UpdateItems)
{
string line = string.Join(
delimiter,
EscapeCsvValue("UPDATE"),
EscapeCsvValue(item != null ? item.WhereParameterName : null),
EscapeCsvValue(item != null ? item.WhereValue : null),
EscapeCsvValue(item != null ? item.SetParameterName : null),
EscapeCsvValue(item != null ? item.SetValue : null));
File.AppendAllText(cfg.DataSource, line + Environment.NewLine, Encoding.UTF8);
sb.AppendLine(line);
}
return new WriterDiagnosticResult
{
Success = true,
Message = "CSV update log OK. Written rows: " + request.UpdateItems.Count,
ExecutedTemplate = sb.ToString().TrimEnd()
};
}
/// <summary>
/// Escapes one CSV value.
/// </summary>
private string EscapeCsvValue(string value)
{
if (value == null)
return string.Empty;
bool mustQuote =
value.Contains("\"") ||
value.Contains(";") ||
value.Contains(",") ||
value.Contains("\n") ||
value.Contains("\r");
if (value.Contains("\""))
value = value.Replace("\"", "\"\"");
if (mustQuote)
value = "\"" + value + "\"";
return value;
}
private WriterDiagnosticResult Ok(string msg)
{
return new WriterDiagnosticResult
{
Success = true,
Message = msg
};
}
private WriterDiagnosticResult Fail(string msg)
{
return new WriterDiagnosticResult
{
Success = false,
Message = msg
};
}
}
}

View File

@ -0,0 +1,145 @@
using System;
using System.Data.SqlClient;
using System.Linq;
using TBF.Rig.Output.DataStorage.UniDataStorageWriter.Interfaces;
namespace TBF.Rig.Output.DataStorage.UniDataStorageWriter.Writers
{
public class DatabaseWriter : IDataStorageWriter
{
private readonly WriterCfg cfg;
public DatabaseWriter(WriterCfg cfg)
{
this.cfg = cfg ?? throw new ArgumentNullException(nameof(cfg));
}
public WriterDiagnosticResult TestSource(bool validateOnly)
{
try
{
using (var conn = new SqlConnection(cfg.DataSource))
{
conn.Open();
if (!validateOnly)
{
using (var cmd = new SqlCommand("SELECT 1", conn))
cmd.ExecuteScalar();
}
}
return Ok("Database connection successful.");
}
catch (Exception ex)
{
return Fail("Database connection failed: " + ex.Message);
}
}
public WriterDiagnosticResult WriteData(DataWriteRequest request)
{
if (request == null)
throw new ArgumentNullException(nameof(request));
if (string.IsNullOrWhiteSpace(request.TargetName))
return Fail("TargetName (table) must be defined.");
switch (request.Mode)
{
case WriteMode.Insert:
return ExecuteInsert(request);
case WriteMode.Update:
return ExecuteUpdate(request);
default:
return Fail("Mode not supported: " + request.Mode);
}
}
private WriterDiagnosticResult ExecuteInsert(DataWriteRequest request)
{
if (request.InsertItems.Count == 0)
return Fail("No insert items.");
string[] columns = request.InsertItems.Select(i => i.ColumnName).ToArray();
string[] values = request.InsertItems.Select(i => ToSql(i.Value)).ToArray();
string sql = $"INSERT INTO {request.TargetName} ({string.Join(", ", columns)}) VALUES ({string.Join(", ", values)})";
return ExecuteSql(sql);
}
private WriterDiagnosticResult ExecuteUpdate(DataWriteRequest request)
{
if (request.UpdateItems.Count == 0)
return Fail("No update items.");
int total = 0;
string executed = "";
using (var conn = new SqlConnection(cfg.DataSource))
{
conn.Open();
foreach (var item in request.UpdateItems)
{
string sql = $"UPDATE {request.TargetName} " +
$"SET {item.SetParameterName} = {ToSql(item.SetValue)} " +
$"WHERE {item.WhereParameterName} = {ToSql(item.WhereValue)}";
using (var cmd = new SqlCommand(sql, conn))
{
total += cmd.ExecuteNonQuery();
}
executed += sql + Environment.NewLine;
}
}
return new WriterDiagnosticResult
{
Success = true,
Message = "Update OK. Rows: " + total,
ExecutedTemplate = executed
};
}
private WriterDiagnosticResult ExecuteSql(string sql)
{
using (var conn = new SqlConnection(cfg.DataSource))
{
conn.Open();
using (var cmd = new SqlCommand(sql, conn))
{
int rows = cmd.ExecuteNonQuery();
return new WriterDiagnosticResult
{
Success = true,
Message = "Insert OK. Rows: " + rows,
ExecutedTemplate = sql
};
}
}
}
private string ToSql(string val)
{
if (val == null) return "NULL";
return "'" + val.Replace("'", "''") + "'";
}
private WriterDiagnosticResult Ok(string msg)
{
return new WriterDiagnosticResult { Success = true, Message = msg };
}
private WriterDiagnosticResult Fail(string msg)
{
return new WriterDiagnosticResult { Success = false, Message = msg };
}
}
}

View File

@ -0,0 +1,54 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TBF.Rig.Output.DataStorage.UniDataStorageWriter.Interfaces;
namespace TBF.Rig.Output.DataStorage.UniDataStorageWriter.Writers
{
public class JsonWriter : IDataStorageWriter
{
private readonly WriterCfg cfg;
public JsonWriter(WriterCfg cfg)
{
this.cfg = cfg ?? throw new ArgumentNullException(nameof(cfg));
}
public object GetData(DataWriteRequest query)
{
if (string.IsNullOrWhiteSpace(cfg.DataSource))
throw new InvalidOperationException("JSON data source is empty.");
if (!File.Exists(cfg.DataSource))
throw new FileNotFoundException("JSON file not found.", cfg.DataSource);
string json = File.ReadAllText(cfg.DataSource);
// TODO: deserialize + filter
return json;
}
public WriterDiagnosticResult TestQuery(bool enableDiagnostics)
{
throw new NotImplementedException();
}
public WriterDiagnosticResult TestSource(bool enableDiagnostics)
{
throw new NotImplementedException();
}
WriterDiagnosticResult IDataStorageWriter.TestSource(bool validateOnly)
{
throw new NotImplementedException();
}
WriterDiagnosticResult IDataStorageWriter.WriteData(DataWriteRequest query)
{
throw new NotImplementedException();
}
}
}

View File

@ -0,0 +1,48 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TBF.Rig.Output.DataStorage.UniDataStorageWriter.Interfaces;
namespace TBF.Rig.Output.DataStorage.UniDataStorageWriter.Writers
{
public class RestApiWriter : IDataStorageWriter
{
private readonly WriterCfg cfg;
public RestApiWriter(WriterCfg cfg)
{
this.cfg = cfg ?? throw new ArgumentNullException(nameof(cfg));
}
public object GetData(DataWriteRequest query)
{
if (string.IsNullOrWhiteSpace(cfg.DataSource))
throw new InvalidOperationException("REST API data source is empty.");
// TODO: HTTP request
return null;
}
public WriterDiagnosticResult TestQuery(bool enableDiagnostics)
{
throw new NotImplementedException();
}
public WriterDiagnosticResult TestSource(bool enableDiagnostics)
{
throw new NotImplementedException();
}
WriterDiagnosticResult IDataStorageWriter.TestSource(bool validateOnly)
{
throw new NotImplementedException();
}
WriterDiagnosticResult IDataStorageWriter.WriteData(DataWriteRequest query)
{
throw new NotImplementedException();
}
}
}

View File

@ -92,6 +92,7 @@ namespace TBF.Rig
new Network.Camera.RoiForFixedStartKeyence.Factory(),
new Network.Comet.Ambient.Factory(),
new Network.RestAPI.Factory(),
new Output.DataStorage.UniDataStorageWriter.Factory(),
new Output.DB.DatabaseWriter.Factory(),
new Output.DB.ProductionTracing.Factory(),
new Output.DB.SaveDiverterCorrections.Factory(),

View File

@ -1048,6 +1048,32 @@
</Compile>
<Compile Include="Rig\Operations\LargeMessageBoxOp.cs" />
<Compile Include="Rig\Operations\ReturnGivenEventOp.cs" />
<Compile Include="Rig\Output\DataStorage\UniDataStorageWriter\Diagnostic\WriterDiagnosticResult.cs" />
<Compile Include="Rig\Output\DataStorage\UniDataStorageWriter\Enums.cs" />
<Compile Include="Rig\Output\DataStorage\UniDataStorageWriter\Factory.cs" />
<Compile Include="Rig\Output\DataStorage\UniDataStorageWriter\Interfaces\DataWriteRequest.cs" />
<Compile Include="Rig\Output\DataStorage\UniDataStorageWriter\Interfaces\IDataStorageWriter.cs" />
<Compile Include="Rig\Output\DataStorage\UniDataStorageWriter\StorageTypes.cs" />
<Compile Include="Rig\Output\DataStorage\UniDataStorageWriter\Writer.cs" />
<Compile Include="Rig\Output\DataStorage\UniDataStorageWriter\WriterCfg.cs" />
<Compile Include="Rig\Output\DataStorage\UniDataStorageWriter\Writers\CsvWriter .cs" />
<Compile Include="Rig\Output\DataStorage\UniDataStorageWriter\Writers\DatabaseWriter .cs" />
<Compile Include="Rig\Output\DataStorage\UniDataStorageWriter\Writers\JsonWriter.cs" />
<Compile Include="Rig\Output\DataStorage\UniDataStorageWriter\Writers\RestApiWriter.cs" />
<Compile Include="Rig\Output\DataStorage\UniDataStorageWriter\Searching\SearchOrderDefinition.cs" />
<Compile Include="Rig\Output\DataStorage\UniDataStorageWriter\Searching\SearchOrderParser.cs" />
<Compile Include="Rig\Output\DataStorage\UniDataStorageWriter\UI\ExamplesFrm.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="Rig\Output\DataStorage\UniDataStorageWriter\UI\ExamplesFrm.Designer.cs">
<DependentUpon>ExamplesFrm.cs</DependentUpon>
</Compile>
<Compile Include="Rig\Output\DataStorage\UniDataStorageWriter\UI\WriterCfgCtrl.cs">
<SubType>UserControl</SubType>
</Compile>
<Compile Include="Rig\Output\DataStorage\UniDataStorageWriter\UI\WriterCfgCtrl.designer.cs">
<DependentUpon>WriterCfgCtrl.cs</DependentUpon>
</Compile>
<Compile Include="Rig\Output\DB\DatabaseWriter\Factory.cs" />
<Compile Include="Rig\Output\DB\DatabaseWriter\WriteDBCfgCtrl.cs">
<SubType>UserControl</SubType>
@ -1420,6 +1446,7 @@
<SubType>UserControl</SubType>
</Compile>
<Compile Include="Rig\RegisterReaders\iPerlASICReader\IperlASICUniHeadTestCtrl.Designer.cs" />
<Compile Include="Rig\RegisterReaders\iPerlASICReader\IPerlCfg.cs" />
<Compile Include="Rig\RegisterReaders\iPerlASICReader\IPerlUniCfgCtrl.cs">
<SubType>UserControl</SubType>
</Compile>
@ -3478,6 +3505,14 @@
<EmbeddedResource Include="Rig\Operations\MessageBoxForm.resx">
<DependentUpon>MessageBoxForm.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Rig\Output\DataStorage\UniDataStorageWriter\UI\ExamplesFrm.resx">
<DependentUpon>ExamplesFrm.cs</DependentUpon>
<SubType>Designer</SubType>
</EmbeddedResource>
<EmbeddedResource Include="Rig\Output\DataStorage\UniDataStorageWriter\UI\WriterCfgCtrl.resx">
<DependentUpon>WriterCfgCtrl.cs</DependentUpon>
<SubType>Designer</SubType>
</EmbeddedResource>
<EmbeddedResource Include="Rig\Output\DB\DatabaseWriter\WriteDBCfgCtrl.resx" />
<EmbeddedResource Include="Rig\Output\DB\ProductionTracing\TracingCfgCtrl.resx">
<DependentUpon>TracingCfgCtrl.cs</DependentUpon>