378 lines
12 KiB
C#
378 lines
12 KiB
C#
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);
|
|
}
|
|
}
|
|
}
|
|
} |