Merge branch UniDataStorageWriter
This commit is contained in:
commit
ef146efaf0
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
51
TBF/Rig/Output/DataStorage/UniDataStorageWriter/Enums.cs
Normal file
51
TBF/Rig/Output/DataStorage/UniDataStorageWriter/Enums.cs
Normal 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
|
||||
}
|
||||
}
|
||||
38
TBF/Rig/Output/DataStorage/UniDataStorageWriter/Factory.cs
Normal file
38
TBF/Rig/Output/DataStorage/UniDataStorageWriter/Factory.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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}";
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
@ -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>";
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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).");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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";
|
||||
}
|
||||
}
|
||||
58
TBF/Rig/Output/DataStorage/UniDataStorageWriter/UI/ExamplesFrm.Designer.cs
generated
Normal file
58
TBF/Rig/Output/DataStorage/UniDataStorageWriter/UI/ExamplesFrm.Designer.cs
generated
Normal 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;
|
||||
}
|
||||
}
|
||||
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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>
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
497
TBF/Rig/Output/DataStorage/UniDataStorageWriter/UI/WriterCfgCtrl.designer.cs
generated
Normal file
497
TBF/Rig/Output/DataStorage/UniDataStorageWriter/UI/WriterCfgCtrl.designer.cs
generated
Normal 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;
|
||||
}
|
||||
}
|
||||
@ -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>
|
||||
113
TBF/Rig/Output/DataStorage/UniDataStorageWriter/Writer.cs
Normal file
113
TBF/Rig/Output/DataStorage/UniDataStorageWriter/Writer.cs
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
244
TBF/Rig/Output/DataStorage/UniDataStorageWriter/WriterCfg.cs
Normal file
244
TBF/Rig/Output/DataStorage/UniDataStorageWriter/WriterCfg.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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 };
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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(),
|
||||
|
||||
@ -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>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user