using com.sun.xml.@internal.rngom.ast.builder; using InABox.Core; using InABox.Scripting; using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.IO; using System.Linq; using System.Reflection; using System.Text; namespace PRSDesktop { public class CreateTableArgs { public Stream Stream { get; set; } public CreateTableArgs(Stream stream) { Stream = stream; } } public class LoadDataArgs { public Stream Stream { get; set; } public CoreTable Table { get; set; } public LoadDataArgs(Stream stream, CoreTable table) { Stream = stream; Table = table; } } public class CustomImporterSettings : BaseObject { [ScriptEditor] public string Script { get; set; } public CustomImporterSettings() { Script = ""; } public string DefaultScript() { return @"using System; using System.Collections.Generic; using System.Linq; using System.Runtime; using System.Windows; using System.Windows.Media; using InABox.Core; using InABox.Scripting; using Comal.Classes; using PRSDesktop; public class Module { // Initialise a table with the necessary columns. public CoreTable? CreateTable(CreateTableArgs args) { var table = new CoreTable(); table.Columns.Add(new CoreColumn { ColumnName = ..., DataType = typeof(string) }); return table; } public void LoadData(LoadDataArgs args) { // Read data from args.Stream; // Add it to the results with: // // var row = args.Table.NewRow(); // args.Table.Rows.Add(row); // } }"; } } public class CustomImporter : SettingsImporter where T : Entity, IRemotable, IPersistent, new() { #region Script private ScriptDocument? _script; private ScriptDocument? Script { get { EnsureScript(); return _script; } } private object? _scriptObject; private object ScriptObject { get { EnsureScript(); return _scriptObject; } } [MemberNotNull(nameof(_scriptObject), nameof(_createTableMethod), nameof(_loadDataMethod))] private void EnsureScript() { if(_script is null) { if (!Settings.Script.IsNullOrWhiteSpace()) { _script = new ScriptDocument(Settings.Script); if (!_script.Compile()) { throw new Exception("Script in Custom Importer failed to compile!"); } _scriptObject = _script.GetObject() ?? throw new Exception("Error in Custom Importer script."); _createTableMethod = _script.GetMethod(methodName: "CreateTable") ?? throw new Exception("CreateTable() not provided"); _loadDataMethod = _script.GetMethod(methodName: "LoadData") ?? throw new Exception("LoadData(LoadDataArgs args) not provided"); } else { throw new Exception("No script provided for custom importer."); } } } private MethodInfo? _createTableMethod; private MethodInfo? _loadDataMethod; private MethodInfo CreateTableMethod { get { EnsureScript(); return _createTableMethod; } } private MethodInfo LoadDataMethod { get { EnsureScript(); return _loadDataMethod; } } #endregion private CoreTable? _table; private bool _loaded; private Stream? _stream; private int rowIdx; public override void Close() { _table = null; _loaded = false; _stream = null; } public override bool MoveNext() { EnsureData(); ++rowIdx; return rowIdx < _table.Rows.Count; } public override bool Open(Stream stream) { _stream = stream; return true; } [MemberNotNullWhen(true, nameof(_table))] public override bool ReadHeader() { if (_stream is null) { throw new Exception("Cannot read header before Open() is called."); } var args = new CreateTableArgs(_stream); _table = CreateTableMethod.Invoke(ScriptObject, new object[] { args }) as CoreTable; if(_table is not null) { Fields = _table.Columns.Select(x => x.ColumnName).ToArray(); return true; } else { return false; } } [MemberNotNull(nameof(_table))] private void EnsureData() { if (_table is null) { if (!ReadHeader()) { throw new Exception("Failed to read header."); } } if (!_loaded) { if (_stream is null) { throw new Exception("Cannot import before Open() is called."); } LoadDataMethod.Invoke(ScriptObject, new object?[] { new LoadDataArgs(_stream, _table) }); _loaded = true; rowIdx = -1; } } public override Dictionary ReadLine() { EnsureData(); var row = _table.Rows[rowIdx]; return _table.Columns.ToDictionary( x => x.ColumnName, x => row[x.ColumnName]?.ToString() ?? ""); } } }