Merge branch UniDataStorageReader
This commit is contained in:
commit
0b429ffbc2
@ -0,0 +1,76 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace TBF.Rig.Input.DataStorage.UniDataStorageReader
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents result of source/query diagnostic.
|
||||
/// </summary>
|
||||
public class ReaderDiagnosticResult
|
||||
{
|
||||
/// <summary>
|
||||
/// Indicates whether the diagnostic operation was successful.
|
||||
/// </summary>
|
||||
public bool Success { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Short summary message.
|
||||
/// </summary>
|
||||
public string Message { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Optional detailed diagnostic log lines.
|
||||
/// </summary>
|
||||
public List<string> Diagnostics { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Optional payload returned by the diagnostic.
|
||||
/// Example: header columns, file lines count, found index, etc.
|
||||
/// </summary>
|
||||
public object Data { get; set; }
|
||||
|
||||
public static ReaderDiagnosticResult SuccessResult(string message = "OK")
|
||||
{
|
||||
return new ReaderDiagnosticResult
|
||||
{
|
||||
Success = true,
|
||||
Message = message
|
||||
};
|
||||
}
|
||||
|
||||
public static ReaderDiagnosticResult Failure(string message)
|
||||
{
|
||||
return new ReaderDiagnosticResult
|
||||
{
|
||||
Success = false,
|
||||
Message = message
|
||||
};
|
||||
}
|
||||
|
||||
public ReaderDiagnosticResult()
|
||||
{
|
||||
Diagnostics = new List<string>();
|
||||
}
|
||||
|
||||
public string ToDisplayDiag()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
if (Diagnostics != null && Diagnostics.Count > 0)
|
||||
{
|
||||
foreach (string line in Diagnostics)
|
||||
{
|
||||
sb.AppendLine(line);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(Message))
|
||||
sb.AppendLine();
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(Message))
|
||||
sb.AppendLine(Message);
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
51
TBF/Rig/Input/DataStorage/UniDataStorageReader/Enums.cs
Normal file
51
TBF/Rig/Input/DataStorage/UniDataStorageReader/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.Input.DataStorage.UniDataStorageReader
|
||||
{
|
||||
/// <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/Input/DataStorage/UniDataStorageReader/Factory.cs
Normal file
38
TBF/Rig/Input/DataStorage/UniDataStorageReader/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.Input.DataStorage.UniDataStorageReader
|
||||
{
|
||||
/// <summary>
|
||||
/// Factory component 'UniDataStorageReader' 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 Reader(new ReaderCfg("UniDataStorageReader", this)); }
|
||||
|
||||
public IComponent GetComponent(IComponentCfg cfg, IList<IComponent> components)
|
||||
{
|
||||
ReaderCfg readerCfg = cfg as ReaderCfg;
|
||||
if (readerCfg == null)
|
||||
throw new ArgumentException("Invalid config for UniDataStorageReader");
|
||||
|
||||
return new Reader(readerCfg);
|
||||
}
|
||||
|
||||
public IComponentCfg DefaultConfig() { return new ReaderCfg("UniDataStorageReader", this); }
|
||||
|
||||
public IComponentCfg CmpntCfgFromCmpntEntity(Config.Entities.Component component)
|
||||
{
|
||||
return ComponentCfgBase.CreateFromDbEntity(ReaderCfg.Serializer, component, this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,17 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace TBF.Rig.Input.DataStorage.UniDataStorageReader
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents query input for data storage readers.
|
||||
/// Each value is used to execute the same query template once.
|
||||
/// A single-item list represents a single query.
|
||||
/// </summary>
|
||||
public class DataQuery
|
||||
{
|
||||
/// <summary>
|
||||
/// Parameter values used for repeated execution of the same query template.
|
||||
/// </summary>
|
||||
public List<string> QueryParams { get; } = new List<string>();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,17 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace TBF.Rig.Input.DataStorage.UniDataStorageReader
|
||||
{
|
||||
public interface IDataStorageReader
|
||||
{
|
||||
object GetData(DataQuery query);
|
||||
|
||||
ReaderDiagnosticResult TestSource(bool enableDiagnostics);
|
||||
|
||||
ReaderDiagnosticResult TestQuery(bool enableDiagnostics);
|
||||
}
|
||||
}
|
||||
93
TBF/Rig/Input/DataStorage/UniDataStorageReader/Reader.cs
Normal file
93
TBF/Rig/Input/DataStorage/UniDataStorageReader/Reader.cs
Normal file
@ -0,0 +1,93 @@
|
||||
using Common;
|
||||
using Config.Entities;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using TBF.Rig.Generic;
|
||||
using TBF.Rig.Input.DataStorage.UniDataStorageReader.Readers;
|
||||
using TBF.Rig.Scales.MettlerToledo;
|
||||
using static TBF.Rig.Input.DataStorage.UniDataStorageReader.ReaderCfg;
|
||||
|
||||
namespace TBF.Rig.Input.DataStorage.UniDataStorageReader
|
||||
{
|
||||
/// <summary>
|
||||
/// Main component that selects appropriate data reader based on configuration.
|
||||
/// Acts as a dispatcher between different storage implementations.
|
||||
/// </summary>
|
||||
public class Reader : IComponent
|
||||
{
|
||||
private readonly ReaderCfg cfg;
|
||||
|
||||
public Reader(ReaderCfg 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(); }
|
||||
|
||||
public object GetDataFromStorageByParameter(DataQuery query)
|
||||
{
|
||||
string storageType = (cfg.DataStorageType ?? string.Empty).Trim();
|
||||
|
||||
IDataStorageReader reader;
|
||||
|
||||
switch (storageType)
|
||||
{
|
||||
case StorageTypes.RestApi:
|
||||
reader = new RestApiReader(cfg);
|
||||
break;
|
||||
|
||||
case StorageTypes.RemoteDatabase:
|
||||
case StorageTypes.LocalDatabase:
|
||||
reader = new DatabaseReader(cfg);
|
||||
break;
|
||||
|
||||
case StorageTypes.RemoteJson:
|
||||
case StorageTypes.LocalJson:
|
||||
reader = new JsonReader(cfg);
|
||||
break;
|
||||
|
||||
case StorageTypes.RemoteCsv:
|
||||
case StorageTypes.LocalCsv:
|
||||
reader = new CsvReader(cfg);
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new NotSupportedException(
|
||||
$"Unsupported DataStorageType: '{cfg.DataStorageType}'");
|
||||
}
|
||||
|
||||
return reader.GetData(query);
|
||||
}
|
||||
|
||||
public void Initialize()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void StartChangeHandler()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void StopChangeHandler()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
169
TBF/Rig/Input/DataStorage/UniDataStorageReader/ReaderCfg.cs
Normal file
169
TBF/Rig/Input/DataStorage/UniDataStorageReader/ReaderCfg.cs
Normal file
@ -0,0 +1,169 @@
|
||||
///
|
||||
/// 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;
|
||||
|
||||
namespace TBF.Rig.Input.DataStorage.UniDataStorageReader
|
||||
{
|
||||
///
|
||||
/// Class and file name is preserved for backward compatibility
|
||||
///
|
||||
public class ReaderCfg : ComponentCfgBase, Generic.IComponentCfg, IParamsProvider
|
||||
{
|
||||
public static XmlSerializer Serializer = XmlSerializer.FromTypes(new[] { typeof(ReaderCfg) })[0];
|
||||
public override XmlSerializer GetSerializer() { return Serializer; }
|
||||
|
||||
public IComponentCfgCtrl GetControl(IList<Config.Entities.Component> cmpntEntities) { return new ReaderCfgCtrl(); }
|
||||
|
||||
|
||||
public string DataStorageType;
|
||||
public string DataSource;
|
||||
public string QueryTemplate;
|
||||
|
||||
|
||||
/// Private parameterless constructor invoked by all other (public) constructors
|
||||
ReaderCfg()
|
||||
{
|
||||
InitializeAll();
|
||||
}
|
||||
|
||||
public ReaderCfg(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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
void CopyContentTo(ReaderCfg prms)
|
||||
{
|
||||
prms.DataStorageType = this.DataStorageType;
|
||||
prms.DataSource = this.DataSource;
|
||||
prms.QueryTemplate = this.QueryTemplate;
|
||||
}
|
||||
|
||||
public IParamsProvider Clone()
|
||||
{
|
||||
ReaderCfg pars = new ReaderCfg();
|
||||
CopyContentTo(pars);
|
||||
return pars;
|
||||
}
|
||||
|
||||
public bool UpdateEmbeddedDbEntity()
|
||||
{
|
||||
return true; /// =OK, do nothing
|
||||
}
|
||||
|
||||
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";
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,345 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using TBF.Rig.Input.DataStorage.UniDataStorageReader.Searching;
|
||||
|
||||
namespace TBF.Rig.Input.DataStorage.UniDataStorageReader.Readers
|
||||
{
|
||||
/// <summary>
|
||||
/// Reader implementation for CSV-based data source.
|
||||
/// </summary>
|
||||
public class CsvReader : IDataStorageReader
|
||||
{
|
||||
private string resolvedPath;
|
||||
private string[] loadedLines;
|
||||
private string[] loadedHeaders;
|
||||
|
||||
private readonly ReaderCfg cfg;
|
||||
|
||||
public CsvReader(ReaderCfg cfg)
|
||||
{
|
||||
this.cfg = cfg ?? throw new ArgumentNullException(nameof(cfg));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads data from CSV and returns matched row data.
|
||||
/// Executes the same query template for each value in DataQuery.QueryParams.
|
||||
/// </summary>
|
||||
public object GetData(DataQuery query)
|
||||
{
|
||||
if (query == null)
|
||||
throw new ArgumentNullException(nameof(query));
|
||||
|
||||
ReaderDiagnosticResult connectResult = ConnectToSource(true);
|
||||
if (!connectResult.Success)
|
||||
throw new InvalidOperationException(connectResult.Message);
|
||||
|
||||
ReaderDiagnosticResult searchResult = ExecuteQuery(query, true);
|
||||
if (!searchResult.Success)
|
||||
throw new InvalidOperationException(searchResult.Message);
|
||||
|
||||
return searchResult;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests whether the CSV source can be resolved, opened and read.
|
||||
/// </summary>
|
||||
public ReaderDiagnosticResult TestSource(bool enableDiagnostics)
|
||||
{
|
||||
return ConnectToSource(enableDiagnostics);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests whether the configured query columns exist in the CSV source.
|
||||
/// </summary>
|
||||
public ReaderDiagnosticResult TestQuery(bool enableDiagnostics)
|
||||
{
|
||||
ReaderDiagnosticResult connectResult = ConnectToSource(enableDiagnostics);
|
||||
if (!connectResult.Success)
|
||||
return connectResult;
|
||||
|
||||
ReaderDiagnosticResult result = new ReaderDiagnosticResult();
|
||||
|
||||
try
|
||||
{
|
||||
Log(result, enableDiagnostics, "Starting QueryTemplate validation.");
|
||||
|
||||
SearchOrderDefinition definition = SearchOrderParser.Parse(cfg.QueryTemplate);
|
||||
|
||||
Log(result, enableDiagnostics, "QueryTemplate parsed successfully.");
|
||||
Log(result, enableDiagnostics, "Select column: " + definition.SelectColumn);
|
||||
Log(result, enableDiagnostics, "Where column: " + definition.WhereColumn);
|
||||
|
||||
int selectIndex = ResolveColumnIndex(loadedHeaders, definition.SelectColumn);
|
||||
int whereIndex = ResolveColumnIndex(loadedHeaders, definition.WhereColumn);
|
||||
|
||||
Log(result, enableDiagnostics, "Resolved select column index: " + selectIndex);
|
||||
Log(result, enableDiagnostics, "Resolved where column index: " + whereIndex);
|
||||
|
||||
result.Success = true;
|
||||
result.Message = "QueryTemplate validation finished successfully.";
|
||||
result.Data = null;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
result.Success = false;
|
||||
result.Message = ex.Message;
|
||||
result.Data = null;
|
||||
|
||||
Log(result, enableDiagnostics, "ERROR: " + ex.Message);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Opens the CSV source, validates its existence and loads its content.
|
||||
/// </summary>
|
||||
public ReaderDiagnosticResult ConnectToSource(bool enableDiagnostics)
|
||||
{
|
||||
ReaderDiagnosticResult result = new ReaderDiagnosticResult();
|
||||
|
||||
try
|
||||
{
|
||||
Log(result, enableDiagnostics, "Starting CSV source connection test.");
|
||||
|
||||
if (string.IsNullOrWhiteSpace(cfg.DataSource))
|
||||
throw new InvalidOperationException("CSV data source is empty.");
|
||||
|
||||
Log(result, enableDiagnostics, "Input data source: " + cfg.DataSource);
|
||||
|
||||
resolvedPath = Path.GetFullPath(cfg.DataSource);
|
||||
Log(result, enableDiagnostics, "Resolved full path: " + resolvedPath);
|
||||
|
||||
Log(result, enableDiagnostics, "Checking whether the file exists.");
|
||||
if (!File.Exists(resolvedPath))
|
||||
throw new FileNotFoundException("CSV file was not found.", resolvedPath);
|
||||
|
||||
Log(result, enableDiagnostics, "CSV file exists.");
|
||||
|
||||
Log(result, enableDiagnostics, "Reading CSV file.");
|
||||
loadedLines = File.ReadAllLines(resolvedPath);
|
||||
|
||||
if (loadedLines == null || loadedLines.Length == 0)
|
||||
throw new InvalidOperationException("CSV file is empty.");
|
||||
|
||||
Log(result, enableDiagnostics, "CSV line count: " + loadedLines.Length);
|
||||
|
||||
loadedHeaders = SplitCsvLine(loadedLines[0]);
|
||||
if (loadedHeaders == null || loadedHeaders.Length == 0)
|
||||
throw new InvalidOperationException("CSV header is empty.");
|
||||
|
||||
Log(result, enableDiagnostics, "CSV header loaded successfully.");
|
||||
Log(result, enableDiagnostics, "Header column count: " + loadedHeaders.Length);
|
||||
|
||||
result.Success = true;
|
||||
result.Message = "CSV source connection finished successfully.";
|
||||
result.Data = loadedLines;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
result.Success = false;
|
||||
result.Message = ex.Message;
|
||||
result.Data = null;
|
||||
|
||||
Log(result, enableDiagnostics, "ERROR: " + ex.Message);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Executes the configured query for all provided parameter values.
|
||||
/// </summary>
|
||||
private ReaderDiagnosticResult ExecuteQuery(DataQuery query, bool enableDiagnostics)
|
||||
{
|
||||
ReaderDiagnosticResult result = new ReaderDiagnosticResult();
|
||||
|
||||
try
|
||||
{
|
||||
Log(result, enableDiagnostics, "Starting QueryTemplate execution.");
|
||||
|
||||
if (query == null)
|
||||
throw new InvalidOperationException("DataQuery is null.");
|
||||
|
||||
if (query.QueryParams == null || query.QueryParams.Count == 0)
|
||||
throw new InvalidOperationException("DataQuery.QueryParams is empty.");
|
||||
|
||||
if (loadedLines == null || loadedLines.Length == 0)
|
||||
throw new InvalidOperationException("CSV source is not connected.");
|
||||
|
||||
if (loadedHeaders == null || loadedHeaders.Length == 0)
|
||||
throw new InvalidOperationException("CSV header is not loaded.");
|
||||
|
||||
SearchOrderDefinition definition = SearchOrderParser.Parse(cfg.QueryTemplate);
|
||||
|
||||
Log(result, enableDiagnostics, "QueryTemplate parsed successfully.");
|
||||
Log(result, enableDiagnostics, "Select column: " + definition.SelectColumn);
|
||||
Log(result, enableDiagnostics, "Where column: " + definition.WhereColumn);
|
||||
|
||||
int selectIndex = ResolveColumnIndex(loadedHeaders, definition.SelectColumn);
|
||||
int whereIndex = ResolveColumnIndex(loadedHeaders, definition.WhereColumn);
|
||||
|
||||
Log(result, enableDiagnostics, "Resolved select column index: " + selectIndex);
|
||||
Log(result, enableDiagnostics, "Resolved where column index: " + whereIndex);
|
||||
Log(result, enableDiagnostics, "Query parameter count: " + query.QueryParams.Count);
|
||||
|
||||
List<string> matchedValues = new List<string>();
|
||||
int matchCount = 0;
|
||||
|
||||
for (int paramIndex = 0; paramIndex < query.QueryParams.Count; paramIndex++)
|
||||
{
|
||||
string queryValue = (query.QueryParams[paramIndex] ?? string.Empty).Trim();
|
||||
|
||||
Log(result, enableDiagnostics, string.Format("=== Query item {0} ===", paramIndex + 1));
|
||||
Log(result, enableDiagnostics, "QueryParam: " + queryValue);
|
||||
|
||||
bool found = false;
|
||||
|
||||
for (int lineIndex = 1; lineIndex < loadedLines.Length; lineIndex++)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(loadedLines[lineIndex]))
|
||||
continue;
|
||||
|
||||
string[] values = SplitCsvLine(loadedLines[lineIndex]);
|
||||
|
||||
if (whereIndex >= values.Length)
|
||||
continue;
|
||||
|
||||
string currentValue = (values[whereIndex] ?? string.Empty).Trim();
|
||||
|
||||
if (string.Equals(currentValue, queryValue, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
string returnValue = selectIndex < values.Length
|
||||
? values[selectIndex]
|
||||
: string.Empty;
|
||||
|
||||
Log(result, enableDiagnostics, "Match found at line index: " + lineIndex);
|
||||
Log(result, enableDiagnostics, "Returned value: " + returnValue);
|
||||
|
||||
matchedValues.Add(returnValue);
|
||||
matchCount++;
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found)
|
||||
{
|
||||
Log(result, enableDiagnostics, "No matching row found.");
|
||||
}
|
||||
}
|
||||
|
||||
if (query.QueryParams.Count == 1)
|
||||
{
|
||||
result.Data = matchedValues.Count > 0 ? (object)matchedValues[0] : null;
|
||||
result.Message = matchedValues.Count > 0 ? "Value found." : "No match found.";
|
||||
}
|
||||
else
|
||||
{
|
||||
result.Data = matchedValues;
|
||||
result.Message = string.Format(
|
||||
"Batch query finished. Matches found: {0} of {1}.",
|
||||
matchCount,
|
||||
query.QueryParams.Count);
|
||||
}
|
||||
|
||||
result.Success = true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
result.Success = false;
|
||||
result.Message = ex.Message;
|
||||
result.Data = null;
|
||||
|
||||
Log(result, enableDiagnostics, "ERROR: " + ex.Message);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Finds zero-based index of the requested column in CSV header.
|
||||
/// </summary>
|
||||
private int FindColumnIndex(string[] headers, string columnName)
|
||||
{
|
||||
for (int i = 0; i < headers.Length; i++)
|
||||
{
|
||||
if (string.Equals(
|
||||
(headers[i] ?? string.Empty).Trim(),
|
||||
(columnName ?? string.Empty).Trim(),
|
||||
StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Splits CSV line by common separators.
|
||||
/// Simple implementation without quoted-separator support.
|
||||
/// </summary>
|
||||
private string[] SplitCsvLine(string line)
|
||||
{
|
||||
if (string.IsNullOrEmpty(line))
|
||||
return new string[0];
|
||||
|
||||
if (line.Contains(","))
|
||||
return line.Split(',');
|
||||
|
||||
if (line.Contains(";"))
|
||||
return line.Split(';');
|
||||
|
||||
if (line.Contains("\t"))
|
||||
return line.Split('\t');
|
||||
|
||||
return new[] { line };
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Appends a diagnostic line if diagnostics are enabled.
|
||||
/// </summary>
|
||||
private void Log(ReaderDiagnosticResult result, bool enableDiagnostics, string message)
|
||||
{
|
||||
if (!enableDiagnostics || result == null)
|
||||
return;
|
||||
|
||||
result.Diagnostics.Add(message);
|
||||
}
|
||||
|
||||
private int ResolveColumnIndex(string[] headers, ColumnReference columnRef)
|
||||
{
|
||||
if (columnRef == null)
|
||||
throw new InvalidOperationException("Column reference is null.");
|
||||
|
||||
if (columnRef.HasIndex)
|
||||
{
|
||||
int index = columnRef.Index.Value;
|
||||
|
||||
if (index < 0 || index >= headers.Length)
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
string.Format("Column index {0} is out of range. Header column count: {1}.", index, headers.Length));
|
||||
}
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
if (columnRef.HasName)
|
||||
{
|
||||
int index = FindColumnIndex(headers, columnRef.Name);
|
||||
if (index < 0)
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
string.Format("Column '{0}' was not found in CSV header.", columnRef.Name));
|
||||
}
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
throw new InvalidOperationException("Column reference is not defined.");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,245 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using System.Data.SqlClient;
|
||||
using System.Reflection;
|
||||
using TBF.Rig.Input.DataStorage.UniDataStorageReader.Searching;
|
||||
using TBF.Rig.Input.DataStorage.UniDataStorageReader.Searching.Database;
|
||||
|
||||
namespace TBF.Rig.Input.DataStorage.UniDataStorageReader.Readers
|
||||
{
|
||||
/// <summary>
|
||||
/// Reader implementation for SQL Server based data source.
|
||||
/// DataSource = SQL Server connection string
|
||||
/// QueryTemplate = SQL query containing QUERYPARAM placeholder
|
||||
/// </summary>
|
||||
public class DatabaseReader : IDataStorageReader
|
||||
{
|
||||
private readonly ReaderCfg cfg;
|
||||
|
||||
public ReaderDiagnosticResult TestSource(bool enableDiagnostics)
|
||||
{
|
||||
ReaderDiagnosticResult result = new ReaderDiagnosticResult();
|
||||
|
||||
try
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(cfg.DataSource))
|
||||
{
|
||||
result.Success = false;
|
||||
result.Message = "Data source is empty.";
|
||||
return result;
|
||||
}
|
||||
|
||||
if (enableDiagnostics)
|
||||
result.Diagnostics.Add("Opening SQL connection...");
|
||||
|
||||
using (SqlConnection connection = new SqlConnection(cfg.DataSource))
|
||||
{
|
||||
connection.Open();
|
||||
|
||||
if (enableDiagnostics)
|
||||
result.Diagnostics.Add("Connection opened successfully.");
|
||||
|
||||
using (SqlCommand command = new SqlCommand("SELECT 1", connection))
|
||||
{
|
||||
object val = command.ExecuteScalar();
|
||||
|
||||
if (enableDiagnostics)
|
||||
result.Diagnostics.Add("Test query executed. Result=" + val);
|
||||
}
|
||||
}
|
||||
|
||||
result.Success = true;
|
||||
result.Message = "Connection to SQL Server OK.";
|
||||
return result;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
result.Success = false;
|
||||
result.Message = "Failed to connect to SQL Server.";
|
||||
|
||||
if (enableDiagnostics)
|
||||
result.Diagnostics.Add(ex.ToString());
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
public ReaderDiagnosticResult TestQuery(bool enableDiagnostics)
|
||||
{
|
||||
ReaderDiagnosticResult result = new ReaderDiagnosticResult();
|
||||
|
||||
try
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(cfg.QueryTemplate))
|
||||
{
|
||||
result.Success = false;
|
||||
result.Message = "Query template is empty.";
|
||||
return result;
|
||||
}
|
||||
|
||||
string sql = PrepareSqlText(cfg.QueryTemplate);
|
||||
|
||||
if (enableDiagnostics)
|
||||
{
|
||||
result.Diagnostics.Add("Original template:");
|
||||
result.Diagnostics.Add(cfg.QueryTemplate);
|
||||
|
||||
result.Diagnostics.Add("Prepared SQL:");
|
||||
result.Diagnostics.Add(sql);
|
||||
}
|
||||
|
||||
using (SqlConnection connection = new SqlConnection(cfg.DataSource))
|
||||
using (SqlCommand command = new SqlCommand(sql, connection))
|
||||
{
|
||||
// dummy parameter
|
||||
command.Parameters.AddWithValue("@value", "TEST");
|
||||
|
||||
if (enableDiagnostics)
|
||||
result.Diagnostics.Add("Parameter @value = TEST");
|
||||
|
||||
connection.Open();
|
||||
|
||||
object val = command.ExecuteScalar();
|
||||
|
||||
if (enableDiagnostics)
|
||||
result.Diagnostics.Add("Query executed successfully.");
|
||||
|
||||
result.Data = val; // môže byť null → OK
|
||||
}
|
||||
|
||||
result.Success = true;
|
||||
result.Message = "Query executed successfully.";
|
||||
return result;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
result.Success = false;
|
||||
result.Message = "Query execution failed.";
|
||||
|
||||
if (enableDiagnostics)
|
||||
result.Diagnostics.Add(ex.ToString());
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
public DatabaseReader(ReaderCfg cfg)
|
||||
{
|
||||
this.cfg = cfg ?? throw new ArgumentNullException(nameof(cfg));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads data from SQL Server and returns matched data.
|
||||
/// If query returns 1 column, scalar value is returned.
|
||||
/// If query returns multiple columns, Dictionary<string, object> is returned.
|
||||
/// </summary>
|
||||
public object GetData(DataQuery query)
|
||||
{
|
||||
if (query == null)
|
||||
throw new ArgumentNullException(nameof(query));
|
||||
|
||||
ReaderDiagnosticResult connectResult = ConnectToSource(true);
|
||||
if (!connectResult.Success)
|
||||
throw new InvalidOperationException(connectResult.Message);
|
||||
|
||||
string sqlText = PrepareSqlText(cfg.QueryTemplate);
|
||||
object queryValue = ExtractQueryValue(query);
|
||||
|
||||
using (SqlConnection connection = new SqlConnection(cfg.DataSource))
|
||||
using (SqlCommand command = new SqlCommand(sqlText, connection))
|
||||
{
|
||||
AddQueryParameters(command, queryValue);
|
||||
|
||||
connection.Open();
|
||||
|
||||
using (SqlDataReader reader = command.ExecuteReader(CommandBehavior.SingleRow))
|
||||
{
|
||||
DatabaseSearchResult result = new DatabaseSearchResult();
|
||||
result.Query = sqlText;
|
||||
|
||||
if (!reader.Read())
|
||||
{
|
||||
result.Found = false;
|
||||
return result;
|
||||
}
|
||||
|
||||
result.Found = true;
|
||||
|
||||
for (int i = 0; i < reader.FieldCount; i++)
|
||||
{
|
||||
object value = reader.GetValue(i);
|
||||
result.Values[reader.GetName(i)] = value == DBNull.Value ? null : value;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Validates database connectivity and basic query readiness.
|
||||
/// </summary>
|
||||
public ReaderDiagnosticResult ConnectToSource(bool validateExistence)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(cfg.DataSource))
|
||||
return ReaderDiagnosticResult.Failure("Data source must not be empty.");
|
||||
|
||||
if (string.IsNullOrWhiteSpace(cfg.QueryTemplate))
|
||||
return ReaderDiagnosticResult.Failure("Query template must not be empty.");
|
||||
|
||||
try
|
||||
{
|
||||
using (SqlConnection connection = new SqlConnection(cfg.DataSource))
|
||||
{
|
||||
connection.Open();
|
||||
|
||||
if (validateExistence)
|
||||
{
|
||||
using (SqlCommand command = new SqlCommand("SELECT 1", connection))
|
||||
{
|
||||
command.ExecuteScalar();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ReaderDiagnosticResult.SuccessResult();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return ReaderDiagnosticResult.Failure(
|
||||
string.Format("Failed to connect to SQL Server data source. {0}", ex.Message));
|
||||
}
|
||||
}
|
||||
|
||||
private static string PrepareSqlText(string queryTemplate)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(queryTemplate))
|
||||
throw new ArgumentException("Query template must not be empty.", nameof(queryTemplate));
|
||||
|
||||
if (!queryTemplate.Contains("QUERYPARAM"))
|
||||
throw new InvalidOperationException("Query template must contain QUERYPARAM placeholder.");
|
||||
|
||||
return queryTemplate.Replace("QUERYPARAM", "@value");
|
||||
}
|
||||
|
||||
private static void AddQueryParameters(SqlCommand command, object queryValue)
|
||||
{
|
||||
command.Parameters.Clear();
|
||||
|
||||
SqlParameter parameter = command.Parameters.Add("@value", SqlDbType.Variant);
|
||||
parameter.Value = queryValue ?? DBNull.Value;
|
||||
}
|
||||
|
||||
private static object ExtractQueryValue(DataQuery query)
|
||||
{
|
||||
if (query == null)
|
||||
throw new ArgumentNullException(nameof(query));
|
||||
|
||||
if (query.QueryParams == null || query.QueryParams.Count == 0)
|
||||
throw new InvalidOperationException("DataQuery does not contain any query parameter.");
|
||||
|
||||
return query.QueryParams[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,43 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace TBF.Rig.Input.DataStorage.UniDataStorageReader.Readers
|
||||
{
|
||||
public class JsonReader : IDataStorageReader
|
||||
{
|
||||
private readonly ReaderCfg cfg;
|
||||
|
||||
public JsonReader(ReaderCfg cfg)
|
||||
{
|
||||
this.cfg = cfg ?? throw new ArgumentNullException(nameof(cfg));
|
||||
}
|
||||
|
||||
public object GetData(DataQuery 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 ReaderDiagnosticResult TestQuery(bool enableDiagnostics)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public ReaderDiagnosticResult TestSource(bool enableDiagnostics)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,37 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace TBF.Rig.Input.DataStorage.UniDataStorageReader.Readers
|
||||
{
|
||||
public class RestApiReader : IDataStorageReader
|
||||
{
|
||||
private readonly ReaderCfg cfg;
|
||||
|
||||
public RestApiReader(ReaderCfg cfg)
|
||||
{
|
||||
this.cfg = cfg ?? throw new ArgumentNullException(nameof(cfg));
|
||||
}
|
||||
|
||||
public object GetData(DataQuery query)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(cfg.DataSource))
|
||||
throw new InvalidOperationException("REST API data source is empty.");
|
||||
|
||||
// TODO: HTTP request
|
||||
return null;
|
||||
}
|
||||
|
||||
public ReaderDiagnosticResult TestQuery(bool enableDiagnostics)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public ReaderDiagnosticResult TestSource(bool enableDiagnostics)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,22 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace TBF.Rig.Input.DataStorage.UniDataStorageReader.Searching.Csv
|
||||
{
|
||||
public class CsvSearchResult
|
||||
{
|
||||
public bool Found { get; set; }
|
||||
public string FilePath { get; set; }
|
||||
public string HeaderLine { get; set; }
|
||||
public string MatchedLine { get; set; }
|
||||
public Dictionary<string, string> Values { get; set; }
|
||||
|
||||
public CsvSearchResult()
|
||||
{
|
||||
Values = new Dictionary<string, string>();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,20 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace TBF.Rig.Input.DataStorage.UniDataStorageReader.Searching.Database
|
||||
{
|
||||
public class DatabaseSearchResult
|
||||
{
|
||||
public bool Found { get; set; }
|
||||
public string Query { get; set; }
|
||||
public Dictionary<string, object> Values { get; set; }
|
||||
|
||||
public DatabaseSearchResult()
|
||||
{
|
||||
Values = new Dictionary<string, object>();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,65 @@
|
||||
using System;
|
||||
|
||||
namespace TBF.Rig.Input.DataStorage.UniDataStorageReader.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.UniDataStorageReader.Searching;
|
||||
|
||||
namespace TBF.Rig.Input.DataStorage.UniDataStorageReader
|
||||
{
|
||||
/// <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).");
|
||||
}
|
||||
}
|
||||
}
|
||||
58
TBF/Rig/Input/DataStorage/UniDataStorageReader/UI/ExamplesFrm.Designer.cs
generated
Normal file
58
TBF/Rig/Input/DataStorage/UniDataStorageReader/UI/ExamplesFrm.Designer.cs
generated
Normal file
@ -0,0 +1,58 @@
|
||||
namespace TBF.Rig.Input.DataStorage.UniDataStorageReader.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.Input.DataStorage.UniDataStorageReader.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="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>
|
||||
</root>
|
||||
@ -0,0 +1,378 @@
|
||||
using Common;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using TBF.Rig.Generic;
|
||||
using TBF.Rig.Input.DataStorage.UniDataStorageReader.Readers;
|
||||
using TBF.Rig.Input.DataStorage.UniDataStorageReader.Searching.Database;
|
||||
using static TBF.Rig.Input.DataStorage.UniDataStorageReader.ReaderCfg;
|
||||
|
||||
namespace TBF.Rig.Input.DataStorage.UniDataStorageReader
|
||||
{
|
||||
/// <summary>
|
||||
/// UI configuration control for UniDataStorageReader.
|
||||
/// Provides testing capabilities for data source and query execution.
|
||||
/// </summary>
|
||||
public partial class ReaderCfgCtrl : Configs.ConfigCtrlUtils, IComponentCfgCtrl
|
||||
{
|
||||
private readonly List<string> batchQueryParamValues = new List<string>();
|
||||
|
||||
public bool ShowMore { get { return false; } }
|
||||
|
||||
private ReaderCfg config;
|
||||
|
||||
public IComponentCfg Config
|
||||
{
|
||||
get { return config as IComponentCfg; }
|
||||
set
|
||||
{
|
||||
config = value as ReaderCfg;
|
||||
Redraw();
|
||||
}
|
||||
}
|
||||
|
||||
public ReaderCfgCtrl()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
connectToDataSourceButton.Click += testByDataSourceButton_Click;
|
||||
getDataByQueryParamAndTemplateButton.Click += getDataByQueryParamAndTemplateButton_Click;
|
||||
buttonAddParam.Click += buttonAddParam_Click;
|
||||
buttonRemoveParam.Click += buttonRemoveParam_Click;
|
||||
}
|
||||
|
||||
private void ReaderCfgCtrl_Load(object sender, EventArgs e)
|
||||
{
|
||||
if (config == null) return;
|
||||
Redraw();
|
||||
}
|
||||
|
||||
public void Closing()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Refreshes UI with current configuration values.
|
||||
/// </summary>
|
||||
private void Redraw()
|
||||
{
|
||||
if (config == null) return;
|
||||
|
||||
classNameLabel.Text = config.Factory.ClassName;
|
||||
nameTextBox.Text = config.Name;
|
||||
dataSourceTextBox.Text = config.DataSource;
|
||||
queryTemplateTextBox.Text = config.QueryTemplate;
|
||||
|
||||
var values = config.ParamValues(0);
|
||||
|
||||
dataStorageTypeComboBox.Items.Clear();
|
||||
|
||||
if (values != null)
|
||||
{
|
||||
foreach (var item in values)
|
||||
{
|
||||
dataStorageTypeComboBox.Items.Add(item);
|
||||
}
|
||||
}
|
||||
|
||||
dataStorageTypeComboBox.Text = config.DataStorageType;
|
||||
RefreshQueryParamsListBox();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Enables editing controls.
|
||||
/// </summary>
|
||||
public void Unlock()
|
||||
{
|
||||
nameTextBox.Enabled = true;
|
||||
dataStorageTypeComboBox.Enabled = true;
|
||||
dataSourceTextBox.Enabled = true;
|
||||
queryTemplateTextBox.Enabled = true;
|
||||
|
||||
textBox1.Enabled = true;
|
||||
textBox1.ReadOnly = true;
|
||||
|
||||
textBox2.Enabled = true;
|
||||
textBox2.ReadOnly = true;
|
||||
|
||||
queryParamValueTextBox.Enabled = true;
|
||||
listBoxQueryParams.Enabled = true;
|
||||
buttonAddParam.Enabled = true;
|
||||
buttonRemoveParam.Enabled = true;
|
||||
}
|
||||
|
||||
public CfgUpdateFlags VerifyCfg(ref string message)
|
||||
{
|
||||
return CfgUpdateFlags.None;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Applies changes from UI into configuration.
|
||||
/// </summary>
|
||||
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, queryTemplateTextBox.Text, CfgUpdateFlags.AnyChange | CfgUpdateFlags.RestartRqrd);
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Builds temporary configuration from UI.
|
||||
/// Used by test actions so saved configuration is not required.
|
||||
/// </summary>
|
||||
private ReaderCfg BuildTemporaryConfigFromUi()
|
||||
{
|
||||
ReaderCfg tmpCfg = new ReaderCfg(
|
||||
string.IsNullOrWhiteSpace(nameTextBox.Text) ? "UniDataStorageReader" : nameTextBox.Text,
|
||||
config != null ? config.Factory : new Factory());
|
||||
|
||||
tmpCfg.DataStorageType = (dataStorageTypeComboBox.Text ?? string.Empty).Trim();
|
||||
tmpCfg.DataSource = dataSourceTextBox.Text;
|
||||
tmpCfg.QueryTemplate = queryTemplateTextBox.Text;
|
||||
|
||||
return tmpCfg;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates appropriate reader implementation based on selected storage type.
|
||||
/// </summary>
|
||||
private IDataStorageReader CreateReader(ReaderCfg cfg)
|
||||
{
|
||||
switch ((cfg.DataStorageType ?? string.Empty).Trim())
|
||||
{
|
||||
case StorageTypes.RestApi:
|
||||
return new RestApiReader(cfg);
|
||||
|
||||
case StorageTypes.RemoteDatabase:
|
||||
case StorageTypes.LocalDatabase:
|
||||
return new DatabaseReader(cfg);
|
||||
|
||||
case StorageTypes.RemoteJson:
|
||||
case StorageTypes.LocalJson:
|
||||
return new JsonReader(cfg);
|
||||
|
||||
case StorageTypes.RemoteCsv:
|
||||
case StorageTypes.LocalCsv:
|
||||
return new CsvReader(cfg);
|
||||
|
||||
default:
|
||||
throw new NotSupportedException(
|
||||
string.Format("Unsupported DataStorageType: '{0}'", cfg.DataStorageType));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calls reader diagnostic for source validation and displays the result.
|
||||
/// </summary>
|
||||
private void testByDataSourceButton_Click(object sender, EventArgs e)
|
||||
{
|
||||
textBox1.Clear();
|
||||
|
||||
try
|
||||
{
|
||||
ReaderCfg tmpCfg = BuildTemporaryConfigFromUi();
|
||||
IDataStorageReader reader = CreateReader(tmpCfg);
|
||||
|
||||
ReaderDiagnosticResult result = reader.TestSource(true);
|
||||
|
||||
textBox1.Text = BuildDiagnosticHeader(tmpCfg, "Source test") + result.ToDisplayDiag();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
textBox1.Text = BuildExceptionText("Data source test failed", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Executes query using values from the batch list only.
|
||||
/// </summary>
|
||||
private void getDataByQueryParamAndTemplateButton_Click(object sender, EventArgs e)
|
||||
{
|
||||
textBox2.Clear();
|
||||
|
||||
try
|
||||
{
|
||||
if (batchQueryParamValues.Count == 0)
|
||||
throw new InvalidOperationException("At least one batch test value must be provided.");
|
||||
|
||||
ReaderCfg tmpCfg = BuildTemporaryConfigFromUi();
|
||||
IDataStorageReader reader = CreateReader(tmpCfg);
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.Append(BuildDiagnosticHeader(tmpCfg, "Query test"));
|
||||
|
||||
foreach (var value in batchQueryParamValues)
|
||||
{
|
||||
DataQuery query = new DataQuery();
|
||||
query.QueryParams.Add(value);
|
||||
|
||||
object queryResult = reader.GetData(query);
|
||||
|
||||
sb.AppendLine("--- Param: " + value + " ---");
|
||||
|
||||
if (queryResult is DatabaseSearchResult dbResult)
|
||||
{
|
||||
sb.AppendLine("Found: " + dbResult.Found);
|
||||
sb.AppendLine("Query: " + dbResult.Query);
|
||||
|
||||
if (dbResult.Values != null && dbResult.Values.Count > 0)
|
||||
{
|
||||
sb.AppendLine("Returned values:");
|
||||
|
||||
foreach (var kvp in dbResult.Values)
|
||||
sb.AppendLine(kvp.Key + " = " + (kvp.Value ?? "<null>"));
|
||||
}
|
||||
}
|
||||
else if (queryResult is ReaderDiagnosticResult diagResult)
|
||||
{
|
||||
sb.AppendLine(diagResult.ToDisplayDiag());
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.AppendLine(queryResult != null ? queryResult.ToString() : "<null>");
|
||||
}
|
||||
|
||||
sb.AppendLine();
|
||||
}
|
||||
|
||||
textBox2.Text = sb.ToString();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
textBox2.Text = BuildExceptionText("GetData test failed", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a single batch test value into the list.
|
||||
/// </summary>
|
||||
private void buttonAddParam_Click(object sender, EventArgs e)
|
||||
{
|
||||
string value = queryParamValueTextBox.Text?.Trim();
|
||||
|
||||
if (string.IsNullOrWhiteSpace(value))
|
||||
return;
|
||||
|
||||
batchQueryParamValues.Add(value);
|
||||
queryParamValueTextBox.Clear();
|
||||
RefreshQueryParamsListBox();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes the selected batch test value from the list.
|
||||
/// </summary>
|
||||
private void buttonRemoveParam_Click(object sender, EventArgs e)
|
||||
{
|
||||
int index = listBoxQueryParams.SelectedIndex;
|
||||
if (index < 0 || index >= batchQueryParamValues.Count)
|
||||
return;
|
||||
|
||||
batchQueryParamValues.RemoveAt(index);
|
||||
RefreshQueryParamsListBox();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Refreshes ListBox content and shows line numbering.
|
||||
/// </summary>
|
||||
private void RefreshQueryParamsListBox()
|
||||
{
|
||||
listBoxQueryParams.Items.Clear();
|
||||
|
||||
for (int i = 0; i < batchQueryParamValues.Count; i++)
|
||||
{
|
||||
listBoxQueryParams.Items.Add(string.Format("{0}. {1}", i + 1, batchQueryParamValues[i]));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Builds common header for diagnostic output.
|
||||
/// </summary>
|
||||
private string BuildDiagnosticHeader(ReaderCfg 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("Query template: " + Safe(cfg.QueryTemplate));
|
||||
sb.AppendLine();
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Builds exception text including inner exceptions.
|
||||
/// </summary>
|
||||
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();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns safe printable text for diagnostics.
|
||||
/// </summary>
|
||||
private string Safe(string text)
|
||||
{
|
||||
return string.IsNullOrWhiteSpace(text) ? "<empty>" : text;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts internal storage type identifier to user-friendly name.
|
||||
/// </summary>
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
453
TBF/Rig/Input/DataStorage/UniDataStorageReader/UI/ReaderCfgCtrl.designer.cs
generated
Normal file
453
TBF/Rig/Input/DataStorage/UniDataStorageReader/UI/ReaderCfgCtrl.designer.cs
generated
Normal file
@ -0,0 +1,453 @@
|
||||
///
|
||||
/// Copyright (c) 2018 Sensus Slovensko a.s.
|
||||
///
|
||||
namespace TBF.Rig.Input.DataStorage.UniDataStorageReader
|
||||
{
|
||||
partial class ReaderCfgCtrl
|
||||
{
|
||||
/// <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
|
||||
|
||||
/// <summary>
|
||||
/// Required method for Designer support - do not modify
|
||||
/// the contents of this method with the code editor.
|
||||
/// </summary>
|
||||
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.textBox1 = 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.textBox2 = new System.Windows.Forms.TextBox();
|
||||
this.getDataByQueryParamAndTemplateButton = 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.listBoxQueryParams = new System.Windows.Forms.ListBox();
|
||||
this.queryParamValueTextBox = 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.label3 = new System.Windows.Forms.Label();
|
||||
this.info3Button = new System.Windows.Forms.Button();
|
||||
this.examples1Button = new System.Windows.Forms.Button();
|
||||
this.queryTemplateTextBox = new System.Windows.Forms.TextBox();
|
||||
this.queryTemplateLabel = 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(83, 13);
|
||||
this.classNameLabel.TabIndex = 0;
|
||||
this.classNameLabel.Text = "ComonentName";
|
||||
//
|
||||
// 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.textBox1);
|
||||
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;
|
||||
//
|
||||
// textBox1
|
||||
//
|
||||
this.textBox1.Enabled = false;
|
||||
this.textBox1.Location = new System.Drawing.Point(15, 47);
|
||||
this.textBox1.Multiline = true;
|
||||
this.textBox1.Name = "textBox1";
|
||||
this.textBox1.ScrollBars = System.Windows.Forms.ScrollBars.Both;
|
||||
this.textBox1.Size = new System.Drawing.Size(437, 358);
|
||||
this.textBox1.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.textBox2);
|
||||
this.groupBox2.Controls.Add(this.getDataByQueryParamAndTemplateButton);
|
||||
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 query 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;
|
||||
//
|
||||
// textBox2
|
||||
//
|
||||
this.textBox2.Enabled = false;
|
||||
this.textBox2.Location = new System.Drawing.Point(6, 48);
|
||||
this.textBox2.Multiline = true;
|
||||
this.textBox2.Name = "textBox2";
|
||||
this.textBox2.ScrollBars = System.Windows.Forms.ScrollBars.Both;
|
||||
this.textBox2.Size = new System.Drawing.Size(446, 357);
|
||||
this.textBox2.TabIndex = 18;
|
||||
//
|
||||
// getDataByQueryParamAndTemplateButton
|
||||
//
|
||||
this.getDataByQueryParamAndTemplateButton.Location = new System.Drawing.Point(6, 19);
|
||||
this.getDataByQueryParamAndTemplateButton.Name = "getDataByQueryParamAndTemplateButton";
|
||||
this.getDataByQueryParamAndTemplateButton.Size = new System.Drawing.Size(206, 23);
|
||||
this.getDataByQueryParamAndTemplateButton.TabIndex = 17;
|
||||
this.getDataByQueryParamAndTemplateButton.Text = "Get data by query param and template";
|
||||
this.getDataByQueryParamAndTemplateButton.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.listBoxQueryParams);
|
||||
this.groupBox3.Controls.Add(this.queryParamValueTextBox);
|
||||
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(166, 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(75, 13);
|
||||
this.labelParamValue.TabIndex = 23;
|
||||
this.labelParamValue.Text = "Query params:";
|
||||
//
|
||||
// listBoxQueryParams
|
||||
//
|
||||
this.listBoxQueryParams.FormattingEnabled = true;
|
||||
this.listBoxQueryParams.Location = new System.Drawing.Point(6, 98);
|
||||
this.listBoxQueryParams.Name = "listBoxQueryParams";
|
||||
this.listBoxQueryParams.Size = new System.Drawing.Size(154, 459);
|
||||
this.listBoxQueryParams.TabIndex = 22;
|
||||
//
|
||||
// queryParamValueTextBox
|
||||
//
|
||||
this.queryParamValueTextBox.Location = new System.Drawing.Point(6, 40);
|
||||
this.queryParamValueTextBox.Name = "queryParamValueTextBox";
|
||||
this.queryParamValueTextBox.Size = new System.Drawing.Size(154, 20);
|
||||
this.queryParamValueTextBox.TabIndex = 21;
|
||||
//
|
||||
// info5Button
|
||||
//
|
||||
this.info5Button.Location = new System.Drawing.Point(125, 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(71, 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.label3);
|
||||
this.groupBox5.Controls.Add(this.info3Button);
|
||||
this.groupBox5.Controls.Add(this.examples1Button);
|
||||
this.groupBox5.Controls.Add(this.queryTemplateTextBox);
|
||||
this.groupBox5.Controls.Add(this.queryTemplateLabel);
|
||||
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 = "Query template setting";
|
||||
//
|
||||
// label3
|
||||
//
|
||||
this.label3.AutoSize = true;
|
||||
this.label3.Location = new System.Drawing.Point(6, 22);
|
||||
this.label3.Name = "label3";
|
||||
this.label3.Size = new System.Drawing.Size(81, 13);
|
||||
this.label3.TabIndex = 26;
|
||||
this.label3.Text = "Query 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;
|
||||
//
|
||||
// queryTemplateTextBox
|
||||
//
|
||||
this.queryTemplateTextBox.Enabled = false;
|
||||
this.queryTemplateTextBox.Location = new System.Drawing.Point(8, 38);
|
||||
this.queryTemplateTextBox.Multiline = true;
|
||||
this.queryTemplateTextBox.Name = "queryTemplateTextBox";
|
||||
this.queryTemplateTextBox.ScrollBars = System.Windows.Forms.ScrollBars.Both;
|
||||
this.queryTemplateTextBox.Size = new System.Drawing.Size(446, 89);
|
||||
this.queryTemplateTextBox.TabIndex = 23;
|
||||
//
|
||||
// queryTemplateLabel
|
||||
//
|
||||
this.queryTemplateLabel.AutoSize = true;
|
||||
this.queryTemplateLabel.Location = new System.Drawing.Point(-123, 6);
|
||||
this.queryTemplateLabel.Name = "queryTemplateLabel";
|
||||
this.queryTemplateLabel.Size = new System.Drawing.Size(81, 13);
|
||||
this.queryTemplateLabel.TabIndex = 22;
|
||||
this.queryTemplateLabel.Text = "Query template:";
|
||||
//
|
||||
// ReaderCfgCtrl
|
||||
//
|
||||
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 = "ReaderCfgCtrl";
|
||||
this.Size = new System.Drawing.Size(1135, 671);
|
||||
this.Load += new System.EventHandler(this.ReaderCfgCtrl_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 textBox1;
|
||||
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 textBox2;
|
||||
private System.Windows.Forms.Button getDataByQueryParamAndTemplateButton;
|
||||
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 listBoxQueryParams;
|
||||
private System.Windows.Forms.TextBox queryParamValueTextBox;
|
||||
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.Label label3;
|
||||
private System.Windows.Forms.Button info3Button;
|
||||
private System.Windows.Forms.Button examples1Button;
|
||||
private System.Windows.Forms.TextBox queryTemplateTextBox;
|
||||
private System.Windows.Forms.Label queryTemplateLabel;
|
||||
}
|
||||
}
|
||||
@ -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>
|
||||
@ -159,7 +159,7 @@ namespace TBF.Rig.Output.DB.DatabaseWriter
|
||||
this.Controls.Add(this.nameTextBox);
|
||||
this.Controls.Add(this.nameLabel);
|
||||
this.Controls.Add(this.classNameLabel);
|
||||
this.Name = "WriteDbCfgCtrl";
|
||||
this.Name = "WriteDBCfgCtrl";
|
||||
this.Size = new System.Drawing.Size(450, 250);
|
||||
this.Load += new System.EventHandler(this.WriterCfgCtrl_Load);
|
||||
this.ResumeLayout(false);
|
||||
|
||||
@ -11,6 +11,9 @@ using TBF.Resources;
|
||||
|
||||
namespace TBF.Rig.Output.FileWriters.IperlLogger
|
||||
{
|
||||
///
|
||||
/// 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];
|
||||
|
||||
@ -92,6 +92,7 @@ namespace TBF.Rig
|
||||
new Network.Camera.RoiForFixedStartKeyence.Factory(),
|
||||
new Network.Comet.Ambient.Factory(),
|
||||
new Network.RestAPI.Factory(),
|
||||
new Input.DataStorage.UniDataStorageReader.Factory(),
|
||||
new Output.DataStorage.UniDataStorageWriter.Factory(),
|
||||
new Output.DB.DatabaseWriter.Factory(),
|
||||
new Output.DB.ProductionTracing.Factory(),
|
||||
|
||||
@ -721,6 +721,33 @@
|
||||
<Compile Include="Rig\Hart\Nivotrack\Nivotrack.cs" />
|
||||
<Compile Include="Rig\Hart\Nivotrack\NivotrackCfg.cs" />
|
||||
<Compile Include="Rig\HeatMetersPath.cs" />
|
||||
<Compile Include="Rig\Input\DataStorage\UniDataStorageReader\Diagnostic\ReaderDiagnosticResult.cs" />
|
||||
<Compile Include="Rig\Input\DataStorage\UniDataStorageReader\Enums.cs" />
|
||||
<Compile Include="Rig\Input\DataStorage\UniDataStorageReader\Factory.cs" />
|
||||
<Compile Include="Rig\Input\DataStorage\UniDataStorageReader\Interfaces\DataQuery.cs" />
|
||||
<Compile Include="Rig\Input\DataStorage\UniDataStorageReader\Interfaces\IDataStorageReader.cs" />
|
||||
<Compile Include="Rig\Input\DataStorage\UniDataStorageReader\Reader.cs" />
|
||||
<Compile Include="Rig\Input\DataStorage\UniDataStorageReader\Searching\Csv\CsvSearchResult.cs" />
|
||||
<Compile Include="Rig\Input\DataStorage\UniDataStorageReader\Searching\Database\DatabaseSearchResult.cs" />
|
||||
<Compile Include="Rig\Input\DataStorage\UniDataStorageReader\UI\ExamplesFrm.cs">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Rig\Input\DataStorage\UniDataStorageReader\UI\ExamplesFrm.Designer.cs">
|
||||
<DependentUpon>ExamplesFrm.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Rig\Input\DataStorage\UniDataStorageReader\UI\ReaderCfgCtrl.cs">
|
||||
<SubType>UserControl</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Rig\Input\DataStorage\UniDataStorageReader\UI\ReaderCfgCtrl.designer.cs">
|
||||
<DependentUpon>ReaderCfgCtrl.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Rig\Input\DataStorage\UniDataStorageReader\ReaderCfg.cs" />
|
||||
<Compile Include="Rig\Input\DataStorage\UniDataStorageReader\Readers\CsvReader .cs" />
|
||||
<Compile Include="Rig\Input\DataStorage\UniDataStorageReader\Readers\DatabaseReader .cs" />
|
||||
<Compile Include="Rig\Input\DataStorage\UniDataStorageReader\Readers\JsonReader .cs" />
|
||||
<Compile Include="Rig\Input\DataStorage\UniDataStorageReader\Readers\RestApiReader .cs" />
|
||||
<Compile Include="Rig\Input\DataStorage\UniDataStorageReader\Searching\SearchOrderDefinition.cs" />
|
||||
<Compile Include="Rig\Input\DataStorage\UniDataStorageReader\Searching\SearchOrderParser.cs" />
|
||||
<Compile Include="Rig\Keithley\Multimeter_2010_RS232\Factory.cs" />
|
||||
<Compile Include="Rig\Keithley\Multimeter_2010_RS232\Multimeter.cs" />
|
||||
<Compile Include="Rig\Keithley\Multimeter_2010_RS232\MultimeterCfg.cs" />
|
||||
@ -1078,7 +1105,9 @@
|
||||
<Compile Include="Rig\Output\DB\DatabaseWriter\WriteDBCfgCtrl.cs">
|
||||
<SubType>UserControl</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Rig\Output\DB\DatabaseWriter\WriteDBCfgCtrl.designer.cs" />
|
||||
<Compile Include="Rig\Output\DB\DatabaseWriter\WriteDBCfgCtrl.designer.cs">
|
||||
<DependentUpon>WriteDBCfgCtrl.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Rig\Output\DB\DatabaseWriter\WriterCfg.cs" />
|
||||
<Compile Include="Rig\Output\DB\DatabaseWriter\WritingToDB.cs" />
|
||||
<Compile Include="Rig\Output\DB\ProductionTracing\Tracing.cs" />
|
||||
@ -3424,6 +3453,12 @@
|
||||
<EmbeddedResource Include="Rig\Dummy\RegValve\RegulValveCfgCtrl.resx">
|
||||
<DependentUpon>RegulValveCfgCtrl.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="Rig\Input\DataStorage\UniDataStorageReader\UI\ExamplesFrm.resx">
|
||||
<DependentUpon>ExamplesFrm.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="Rig\Input\DataStorage\UniDataStorageReader\UI\ReaderCfgCtrl.resx">
|
||||
<DependentUpon>ReaderCfgCtrl.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="Rig\Keithley\Multimeter_2010_RS232\MultimeterCfgCtrl.resx">
|
||||
<DependentUpon>MultimeterCfgCtrl.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
@ -3513,7 +3548,9 @@
|
||||
<DependentUpon>WriterCfgCtrl.cs</DependentUpon>
|
||||
<SubType>Designer</SubType>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="Rig\Output\DB\DatabaseWriter\WriteDBCfgCtrl.resx" />
|
||||
<EmbeddedResource Include="Rig\Output\DB\DatabaseWriter\WriteDBCfgCtrl.resx">
|
||||
<DependentUpon>WriteDBCfgCtrl.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="Rig\Output\DB\ProductionTracing\TracingCfgCtrl.resx">
|
||||
<DependentUpon>TracingCfgCtrl.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
|
||||
@ -739,7 +739,7 @@
|
||||
<value>processTabPageCtrl</value>
|
||||
</data>
|
||||
<data name=">>processTabPageCtrl.Type" xml:space="preserve">
|
||||
<value>TBF.UI.Process.ProcessTabPageCtrl, TBF, Version=3.9.2149.4, Culture=neutral, PublicKeyToken=null</value>
|
||||
<value>TBF.UI.Process.ProcessTabPageCtrl, TBF, Version=3.9.3001.1, Culture=neutral, PublicKeyToken=null</value>
|
||||
</data>
|
||||
<data name=">>processTabPageCtrl.Parent" xml:space="preserve">
|
||||
<value>processTabPage</value>
|
||||
@ -817,7 +817,7 @@
|
||||
<value>resultsTabPageCtrl</value>
|
||||
</data>
|
||||
<data name=">>resultsTabPageCtrl.Type" xml:space="preserve">
|
||||
<value>TBF.UI.ResultsMI.ResultsTabPageCtrl, TBF, Version=3.9.2149.4, Culture=neutral, PublicKeyToken=null</value>
|
||||
<value>TBF.UI.ResultsMI.ResultsTabPageCtrl, TBF, Version=3.9.3001.1, Culture=neutral, PublicKeyToken=null</value>
|
||||
</data>
|
||||
<data name=">>resultsTabPageCtrl.Parent" xml:space="preserve">
|
||||
<value>resultsTabPage</value>
|
||||
@ -871,7 +871,7 @@
|
||||
<value>graphsTabPageCtrl</value>
|
||||
</data>
|
||||
<data name=">>graphsTabPageCtrl.Type" xml:space="preserve">
|
||||
<value>TBF.UI.Graphs.GraphsTabPageCtrl, TBF, Version=3.9.2149.4, Culture=neutral, PublicKeyToken=null</value>
|
||||
<value>TBF.UI.Graphs.GraphsTabPageCtrl, TBF, Version=3.9.3001.1, Culture=neutral, PublicKeyToken=null</value>
|
||||
</data>
|
||||
<data name=">>graphsTabPageCtrl.Parent" xml:space="preserve">
|
||||
<value>graphsTabPage</value>
|
||||
@ -925,7 +925,7 @@
|
||||
<value>eventLogsTabPageCtrl</value>
|
||||
</data>
|
||||
<data name=">>eventLogsTabPageCtrl.Type" xml:space="preserve">
|
||||
<value>TBF.UI.EventLogs.EventLogsTabPageCtrl, TBF, Version=3.9.2149.4, Culture=neutral, PublicKeyToken=null</value>
|
||||
<value>TBF.UI.EventLogs.EventLogsTabPageCtrl, TBF, Version=3.9.3001.1, Culture=neutral, PublicKeyToken=null</value>
|
||||
</data>
|
||||
<data name=">>eventLogsTabPageCtrl.Parent" xml:space="preserve">
|
||||
<value>eventLogsTabPage</value>
|
||||
@ -979,7 +979,7 @@
|
||||
<value>calendarTabPageCtrl</value>
|
||||
</data>
|
||||
<data name=">>calendarTabPageCtrl.Type" xml:space="preserve">
|
||||
<value>TBF.UI.Calendar.CalendarTabPageCtrl, TBF, Version=3.9.2149.4, Culture=neutral, PublicKeyToken=null</value>
|
||||
<value>TBF.UI.Calendar.CalendarTabPageCtrl, TBF, Version=3.9.3001.1, Culture=neutral, PublicKeyToken=null</value>
|
||||
</data>
|
||||
<data name=">>calendarTabPageCtrl.Parent" xml:space="preserve">
|
||||
<value>calendarTabPage</value>
|
||||
@ -1033,7 +1033,7 @@
|
||||
<value>picturesTabPageCtrl</value>
|
||||
</data>
|
||||
<data name=">>picturesTabPageCtrl.Type" xml:space="preserve">
|
||||
<value>TBF.UI.Camera.PicturesTabPageCtrl, TBF, Version=3.9.2149.4, Culture=neutral, PublicKeyToken=null</value>
|
||||
<value>TBF.UI.Camera.PicturesTabPageCtrl, TBF, Version=3.9.3001.1, Culture=neutral, PublicKeyToken=null</value>
|
||||
</data>
|
||||
<data name=">>picturesTabPageCtrl.Parent" xml:space="preserve">
|
||||
<value>picturesTabPage</value>
|
||||
|
||||
6
TBF/UI/Settings/DatabaseSettingsDlg.Designer.cs
generated
6
TBF/UI/Settings/DatabaseSettingsDlg.Designer.cs
generated
@ -89,10 +89,10 @@ namespace TBF.UI.Settings
|
||||
resources.ApplyResources(this.benchNameTextBox, "benchNameTextBox");
|
||||
this.benchNameTextBox.Name = "benchNameTextBox";
|
||||
//
|
||||
// connectionStringLabel
|
||||
// dataSourceLabel
|
||||
//
|
||||
resources.ApplyResources(this.connectionStringLabel, "connectionStringLabel");
|
||||
this.connectionStringLabel.Name = "connectionStringLabel";
|
||||
resources.ApplyResources(this.connectionStringLabel, "dataSourceLabel");
|
||||
this.connectionStringLabel.Name = "dataSourceLabel";
|
||||
//
|
||||
// configDbConnectionStringTextBox
|
||||
//
|
||||
|
||||
Loading…
Reference in New Issue
Block a user