-
Notifications
You must be signed in to change notification settings - Fork 0
Beep Data Management Engine (BeepDM)
Fahad Aldhubaib edited this page Jan 7, 2023
·
20 revisions
- IDMEEditor : Mother Class for all Below Classes.
- IDataSource: Class implementation of Beep DataSource.
- IETL: Extract,Transform and Load Module.
- IConfigEditor: Configuration Class that handles configuration loading/saving.
- IDataTypesHelper: Handles Data Type Mapping and Configurations.
- IUtil: Handles common Functions used by Engine.
- IAssemblyHandler: Handles Loading Assembly and Extracting needed Class implementations of (DataSources, Drivers, IDM_Addin, Extrensions, etc..).
- IErrorsInfo: Handles Error Handling.
- IDMLogger: Handles Logging.
- IJsonLoader: Handles Json Load/Save Files.
- IClassCreator: Creates Classes/Types of Data source Entities.
- IWorkFlowEditor: Data WorkFlows Manager.
- IWorkFlowStepEditor: Data WorkFlow Step/Stage Manager.
- IRuleParser: Data Rules Parsers used in Workflows.
- IRulesEditor: Data Rules Manager.
- Addin : Where you place all DLL that have "Addin" Interface (usercontrol, form,class,etc ..)
- AI : Where we store all AI scripts (user Later)
-
Config : Where we store all our configuration files needed to run Beep DM correctly.
- QueryList.json : Define all Queries types needed for getting meta data from any Datasource.
- DriversDefinitions.json : Define Drivers for Data Source that have no Drivers (like WebApi).
- ConnectionConfig.json : Define Drivers and DataSource Class that use them and other data (like icon).
- DataTypeMapping.json :Define the DataType and Column Type Mapping for DataSource to Datasource.
- DataConnections.json : Define Data Source Connections.
- ConnectionDrivers: Store all Data source drivers (oracle ,sqlite,sqlserver, etc)
- DataFiles : Primary strorage for Data Files needed for Project
- DataViews : A DataView is a Fedrated View of Different Data Source entities, you can compile. Json DataView File Stored Here.
- Entities : Temporary place to store Datasource Entities Descriptions.
- GFX : a place to Store Gfx and icons needed by Application.
- LoadingExtensions: hold Classe Implementation of "ILoadingExtension". add extra functionality and dynmicaly load other data classes in your Application not defined in engine.
- Mapping : place to Store Mapping Definitions for Datasource to other Datasource.
- OtherDLL : Place to Store other dll needed for your application.
- ProjectClasses : The primary Folder for Loading (DataSource Implementation,Addins,etc)
- ProjectData : Place to store files
- Scripts : Place to store scripts and logs
- WorkFlow : place to store Workflow definitions
- This Class has to initiated to start using the Platform
- All features in this class is a Plugin.
public IDMEEditor DMEEditor { get; set; }
public IConfigEditor Config_editor { get; set; }
public IDMLogger lg { get; set; }
public IUtil util { get; set; }
public IVisManager vis { get; set; }
public IErrorsInfo Erinfo { get; set; }
public IJsonLoader jsonLoader { get; set; }
public IAssemblyHandler LLoader { get; set; }
- So if you dont like any of out Implementations you can do your own.
- Below is our Implementation.
using Autofac;
using System.Linq;
using TheTechIdea.Beep;
using TheTechIdea.Logger;
using TheTechIdea.Beep.Workflow;
using TheTechIdea.Util;
using TheTechIdea.Tools;
using TheTechIdea.Beep.Editor;
using BeepEnterprize.Vis.Module;
using BeepEnterprize.Winform.Vis;
using TheTechIdea.Beep.ConfigUtil;
using System.Threading;
using TheTechIdea;
using System;
using TheTechIdea.Beep.Tools;
namespace BeepEnterprize.Winform
{
public class MainApp
{
private static IContainer Container { get; set; }
private static ContainerBuilder Builder { get; set; }
#region "System Components"
public IDMEEditor DMEEditor { get; set; }
public IConfigEditor Config_editor { get; set; }
public IDMLogger lg { get; set; }
public IUtil util { get; set; }
public IVisManager vis { get; set; }
public IErrorsInfo Erinfo { get; set; }
public IJsonLoader jsonLoader { get; set; }
public IAssemblyHandler LLoader { get; set; }
#endregion
CancellationTokenSource tokenSource;
CancellationToken token;
public static IContainer Configure() //ContainerBuilder builder
{
Builder = new ContainerBuilder();
Builder.RegisterType<ErrorsInfo>().As<IErrorsInfo>().SingleInstance();
Builder.RegisterType<DMLogger>().As<IDMLogger>().SingleInstance();
Builder.RegisterType<ConfigEditor>().As<IConfigEditor>().SingleInstance();
Builder.RegisterType<DMEEditor>().As<IDMEEditor>().SingleInstance();
Builder.RegisterType<Util>().As<IUtil>().SingleInstance();
Builder.RegisterType<VisManager>().As<IVisManager>().SingleInstance();
Builder.RegisterType<JsonLoader>().As<IJsonLoader>().SingleInstance();
Builder.RegisterType<AssemblyHandler>().As<IAssemblyHandler>().SingleInstance();
return Builder.Build();
}
public MainApp()
{
Container = Configure();
using (var scope = Container.BeginLifetimeScope())
{
Config_editor = scope.Resolve<IConfigEditor>();
LLoader = scope.Resolve<IAssemblyHandler>();
DMEEditor = scope.Resolve<IDMEEditor>();
vis = scope.Resolve<IVisManager>();
vis.Title = "Beep - The Data Plaform";
vis.IconUrl = "SimpleODM.ico";
// Show Image Log instead of above Text Title
//vis.LogoUrl = "dh3.png";
DMEEditor.AddLogMessage("Started Assembly Loader");
// Create A parameter object for Wait Form
PassedArgs p = new PassedArgs();
p.ParameterString1 = "Loading DLL's";
// Show Wait Form
vis.ShowWaitForm(p);
// Passing Message to WaitForm
vis.PasstoWaitForm(p);
// Prepare Async Data Notification from Assembly loader to WaitForm
tokenSource = new CancellationTokenSource();
token = tokenSource.Token;
var progress = new Progress<PassedArgs>(percent => {
p.ParameterString1 = percent.ParameterString1;
vis.PasstoWaitForm(p);
});
// Load Assemblies
LLoader.LoadAllAssembly(progress, token);
Config_editor.LoadedAssemblies = LLoader.Assemblies.Select(c => c.DllLib).ToList();
// Create Default Parameter object
DMEEditor.Passedarguments = new PassedArgs();
DMEEditor.Passedarguments.Objects = new System.Collections.Generic.List<ObjectItem>();
// Setup the Entry Screen
// the screen has to be in one the Addin DLL's loaded by the Assembly loader
// Config_editor.Config.SystemEntryFormName = @"MainForm";
Config_editor.Config.SystemEntryFormName = @"Frm_Main";
//AppDomain.CurrentDomain.FirstChanceException += (sender, eventArgs) =>
//{
// DMEEditor.AddLogMessage("Beep",eventArgs.Exception.ToString(),DateTime.Now,0,null,Errors.Failed);
//};
DMEEditor.AddLogMessage("Show Main Page");
// Show Beep Data Management System Tree
vis.BeepObjectsName = "Beep";
//vis.AppObjectsName = "App";
vis.IsBeepDataOn = true;
// Show or Hide Custome App Tree
vis.IsAppOn = false;
// This Flag for Showing Main Form
vis.IsShowingMainForm =true;
vis.ShowMainPage();
}
}
}
}
- Lets say you have another Implementation for the Log Module and Error Handler Module
- Change the following lines
Builder.RegisterType<YourLogger>().As<IDMLogger>().SingleInstance();
Builder.RegisterType<YourErrorsInfo>().As<IErrorsInfo>().SingleInstance();
...
...
...
- they will be initiated by Calling the Config Class Implementation in Line
Config_editor = scope.Resolve<IConfigEditor>();
- Create New Class Implementing "IDataSource".
- You can check or Change our Implementations of all DataSource here Beep Data Sources
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TheTechIdea.Beep.Vis;
using TheTechIdea.Beep.DataBase;
using TheTechIdea.Beep.Editor;
using TheTechIdea.Beep.Report;
using TheTechIdea.Logger;
using TheTechIdea.Util;
namespace TheTechIdea.Beep.Cloud
{
[AddinAttribute(Category = DatasourceCategory.CLOUD, DatasourceType = DataSourceType.WebService)]
public class AzureCloudCosmosDataSource : IDataSource
{
public event EventHandler<PassedArgs> PassEvent;
public DataSourceType DatasourceType { get ; set ; }
public DatasourceCategory Category { get ; set ; }
public IDataConnection Dataconnection { get ; set ; }
public string DatasourceName { get ; set ; }
public IErrorsInfo ErrorObject { get ; set ; }
public string Id { get ; set ; }
public IDMLogger Logger { get ; set ; }
public List<string> EntitiesNames { get ; set ; }
public List<EntityStructure> Entities { get; set; } = new List<EntityStructure>();
public IDMEEditor DMEEditor { get ; set ; }
public List<object> Records { get ; set ; }
public ConnectionState ConnectionStatus { get ; set ; }
public DataTable SourceEntityData { get ; set ; }
public virtual string ColumnDelimiter { get; set; } = "''";
public virtual string ParameterDelimiter { get; set; } = ":";
public int GetEntityIdx(string entityName)
{
if (Entities.Count > 0)
{
return Entities.FindIndex(p => p.EntityName.Equals(entityName, StringComparison.OrdinalIgnoreCase) || p.DatasourceEntityName.Equals(entityName, StringComparison.OrdinalIgnoreCase));
}
else
{
return -1;
}
}
public ConnectionState Openconnection()
{
throw new NotImplementedException();
}
public ConnectionState Closeconnection()
{
throw new NotImplementedException();
}
public bool CheckEntityExist(string EntityName)
{
throw new NotImplementedException();
}
public bool CreateEntityAs(EntityStructure entity)
{
throw new NotImplementedException();
}
public IErrorsInfo ExecuteSql(string sql)
{
throw new NotImplementedException();
}
public List<ChildRelation> GetChildTablesList(string tablename, string SchemaName, string Filterparamters)
{
throw new NotImplementedException();
}
public DataSet GetChildTablesListFromCustomQuery(string tablename, string customquery)
{
throw new NotImplementedException();
}
public List<string> GetEntitesList()
{
throw new NotImplementedException();
}
public Task<object> GetEntityDataAsync(string entityname, string filterstr)
{
throw new NotImplementedException();
}
public object GetEntity(string EntityName, List<AppFilter> filter)
{
throw new NotImplementedException();
}
public List<RelationShipKeys> GetEntityforeignkeys(string entityname, string SchemaName)
{
throw new NotImplementedException();
}
public EntityStructure GetEntityStructure(string EntityName, bool refresh)
{
throw new NotImplementedException();
}
public EntityStructure GetEntityStructure(EntityStructure fnd, bool refresh = false)
{
throw new NotImplementedException();
}
public DataTable GetEntityDataTable(string EntityName, string filterstr)
{
throw new NotImplementedException();
}
public Type GetEntityType(string EntityName)
{
throw new NotImplementedException();
}
public virtual IErrorsInfo UpdateEntity(string EntityName, object UploadDataRow)
{
throw new NotImplementedException();
}
public IErrorsInfo DeleteEntity(string EntityName, object DeletedDataRow)
{
throw new NotImplementedException();
}
public IErrorsInfo UpdateEntities(string EntityName, object UploadData, IProgress<PassedArgs> progress)
{
throw new NotImplementedException();
}
public object RunQuery( string qrystr)
{
throw new NotImplementedException();
}
public IErrorsInfo RunScript(ETLScriptDet dDLScripts)
{
throw new NotImplementedException();
}
public IErrorsInfo CreateEntities(List<EntityStructure> entities)
{
throw new NotImplementedException();
}
public List<ETLScriptDet> GetCreateEntityScript(List<EntityStructure> entities = null)
{
throw new NotImplementedException();
}
public IErrorsInfo InsertEntity(string EntityName, object InsertedData)
{
throw new NotImplementedException();
}
public Task<object> GetEntityAsync(string EntityName, List<AppFilter> Filter)
{
throw new NotImplementedException();
}
#region "dispose"
private bool disposedValue;
protected virtual void Dispose(bool disposing)
{
if (!disposedValue)
{
if (disposing)
{
// TODO: dispose managed state (managed objects)
}
// TODO: free unmanaged resources (unmanaged objects) and override finalizer
// TODO: set large fields to null
disposedValue = true;
}
}
// // TODO: override finalizer only if 'Dispose(bool disposing)' has code to free unmanaged resources
// ~RDBSource()
// {
// // Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method
// Dispose(disposing: false);
// }
public void Dispose()
{
// Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method
Dispose(disposing: true);
GC.SuppressFinalize(this);
}
#endregion
}
}
- Add if Needed DataSource Drivers in "ConnectionDrivers" Folder
- Create new Entry/Record in "ConnectionConfig.json" File for your DataSource. or use Beep Enterprize Winform Application
- Create a DataConnection Implementing IDataConnection Interface
- Example:
ConnectionDriversConfig driversConfig = new ConnectionDriversConfig();
driversConfig.version = p[1];
driversConfig.AdapterType = "System.Data.SqlClient" + "." + "SqlDataAdapter";
driversConfig.DbConnectionType = "System.Data.SqlClient" + "." + "SqlConnection";
driversConfig.CommandBuilderType = "System.Data.SqlClient" + "." + "SqlCommandBuilder";
driversConfig.DbTransactionType = "System.Data.SqlClient" + "." + "SqlTransaction";
driversConfig.PackageName = "System.Data.SqlClient";
driversConfig.DriverClass = "System.Data.SqlClient";
driversConfig.iconname = iconfile;
driversConfig.classHandler = SqlDataSourceClass;// Your IDataSource Implementation
driversConfig.DatasourceCategory = DatasourceCategory.RDBMS;
driversConfig.ConnectionString = connectionstringformat; //used to in DataConnection Object to replace Connection values
driversConfig.ADOType = true;
DMEEditor.ConfigEditor.DataDriversClasses.Add(driversConfig);
-
Add new DLL Created for your New DataSource Class and Connection Class to "ProjectClasses" Folder
-
Run "Connection Drivers" Module from Addin Tree in Application. Add new Record and Select Your Class From "Class Handler" Column.
-
Or Update File "ConnectionConfig.json" in the Config Folder in Application Folder. using
-
example how to implement and use DataSourceDriver ConnectionString to replace values for connection Parameters
public string ReplaceValueFromConnectionString()
{
string rep="";
if (string.IsNullOrWhiteSpace(DataSourceDriver.ConnectionString) == false )
{
rep = DataSourceDriver.ConnectionString.Replace("{Host}", ConnectionProp.Host);
rep = rep.Replace("{UserID}", ConnectionProp.UserID);
rep = rep.Replace("{Password}", ConnectionProp.Password);
rep = rep.Replace("{Database}", ConnectionProp.Database);
rep = rep.Replace("{Port}", ConnectionProp.Port.ToString());
if (rep.Contains("{Url}"))
{
rep = rep.Replace("{Url}", ConnectionProp.Url);
}
if (!string.IsNullOrEmpty(ConnectionProp.FilePath))
{
if (ConnectionProp.FilePath.StartsWith(".") || ConnectionProp.FilePath.Equals("./") || ConnectionProp.FilePath.Equals(".\\"))
{
ConnectionProp.FilePath = ConnectionProp.FilePath.Replace(".", DMEEditor.ConfigEditor.ExePath);
}
}
if (rep.Contains("{File}"))
{
rep = rep.Replace("{File}", Path.Combine(ConnectionProp.FilePath, ConnectionProp.FileName));
}
}
return rep;
}
- Create usercontrol,Form or Class Implementing "IDM_Addin".
- All IDM_Addin Implementation should have this attribute,Where "addinType" tells the Engine the type of Addin.
[AddinAttribute(Caption = "Copy Entity Manager", Name = "CopyEntityManager", misc = "ImportDataManager", addinType = AddinType.Class)]
public class CopyEntityManager : IDM_Addin
- Example of implementing the 2 Main Method in any Addin
public void Run(IPassedArgs pPassedarg) { // Run Method that Can used as standard call to implement Function using IPassedArgs as passed parameters } public void SetConfig(IDMEEditor pbl, IDMLogger plogger, IUtil putil, string[] args, IPassedArgs e, IErrorsInfo per) { DMEEditor = pbl; // The Mother Class is always Passed on , you will full access to the Engine and all Data Sources Passedarg = e; // IPassedArgs always used to Pass Arguments, Like DataSource Name Logger = plogger; ErrorObject = per; // Examples IDataSource dataSource = DMEEditor.GetDataSource(Passedarg.DatasourceName); if (dataSource != null) { dataSource.Openconnection(); } foreach(AssemblyClassDefinition cls in DMEEditor.ConfigEditor.DataSourcesClasses) { this.classHandlerComboBox.Items.Add(cls.className); } foreach (var item in Enum.GetValues(typeof(DatasourceCategory))) { DatasourceCategoryComboBox.Items.Add(item); } foreach (var item in Enum.GetValues(typeof(DataSourceType))) { DatasourceTypeComboBox.Items.Add(item); } }
- Example on how Call IDM_Addin
AddinAttribute attrib = new AddinAttribute();
if (DMEEditor.assemblyHandler.AddIns.Where(c => c.ObjectName.Equals(pagename, StringComparison.OrdinalIgnoreCase)).Any())
{
Type type = DMEEditor.assemblyHandler.AddIns.Where(c => c.ObjectName.Equals(pagename, StringComparison.OrdinalIgnoreCase)).FirstOrDefault().GetType();
attrib = (AddinAttribute)type.GetCustomAttribute(typeof(AddinAttribute), false);
if (attrib != null)
{
if (attrib.displayType == DisplayType.Popup)
{
displayType = DisplayType.Popup;
}
}
}
ErrorsandMesseges = new ErrorsInfo();
switch (attrib.addinType)
{
case AddinType.Form:
Type type = DMEEditor.assemblyHandler.AddIns.Where(c => c.ObjectName.Equals(pagename, StringComparison.OrdinalIgnoreCase)).FirstOrDefault().GetType(); //dllname.Remove(dllname.IndexOf(".")) + ".Forms." + pagename
form = (Form)Activator.CreateInstance(type);
if (form != null)
{
addin = (IDM_Addin)form;
if (e.Objects == null)
{
e.Objects = new List<ObjectItem>();
}
e.Objects.AddRange(CreateArgsParameterForVisUtil());
addin.SetConfig(pDMEEditor, DMEEditor.Logger, DMEEditor.Utilfunction, args, e, ErrorsandMesseges);
form.Text = addin.AddinName;
form.ShowDialog();
}
break;
case AddinType.Control:
Type type = DMEEditor.assemblyHandler.AddIns.Where(c => c.ObjectName.Equals(pagename, StringComparison.OrdinalIgnoreCase)).FirstOrDefault().GetType();
UserControl uc = (UserControl)Activator.CreateInstance(type);
if (uc != null)
{
addin = (IDM_Addin)uc;
if (e.Objects == null)
{
e.Objects = new List<ObjectItem>();
}
e.Objects.AddRange(CreateArgsParameterForVisUtil());
form.Text = addin.AddinName;
addin.SetConfig(pDMEEditor, DMEEditor.Logger, DMEEditor.Utilfunction, args, e, ErrorsandMesseges);
form.AddControl(uc,addin.AddinName);
form.Width = uc.Width + 50;
form.Height = uc.Height + 50;
uc.Dock = DockStyle.Fill;
form.Title = addin.AddinName;
form.PreClose -= Form_PreClose;
form.PreClose += Form_PreClose;
form.Show();
break;
case AddinType.Class:
RunAddinClass(pagename,DMEEditor, new string[] { }, Passedarguments);
break;
case AddinType.Page:
break;
case AddinType.Link:
break;
default:
break;
}
- Add Generated dll to Addin Folder or ProjectClasses and it will show in Addin Tree in Application.
- Also, all IDM_Addin Implementations will be stored under Assembly_handler Class in DMEditor.
- Create a Project with Class that Implement "LoadingExtensions"
- Add Created DLL's to LoadingExtensions Folder.
- This will allow Assembly_Handler Class to Load new Data Classes and Extensions.
- Example is Extension to Add new Classes for AI and App Builder in Beep Enterprize
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using TheTechIdea.Tools;
using TheTechIdea.Util;
namespace AssemblyLoader_AIandApps
{
internal class AssemblyLoaderExtension : ILoaderExtention
{
public IAssemblyHandler Loader { get; set; }
public AssemblyLoaderExtension(IAssemblyHandler ploader)
{
Loader = ploader;
}
public IErrorsInfo LoadAllAssembly()
{
ErrorsInfo er = new ErrorsInfo();
foreach (var item in Loader.Assemblies)
{
try
{
Type[] t;
Assembly asm = item.DllLib;
try
{
try
{
t = asm.GetTypes();
}
catch (Exception ex2)
{
try
{
t = asm.GetExportedTypes();
}
catch (Exception ex3)
{
t = null;
}
}
if (t != null)
{
foreach (var mytype in t) //asm.DefinedTypes
{
TypeInfo type = mytype.GetTypeInfo();
string[] p = asm.FullName.Split(new char[] { ',' });
p[1] = p[1].Substring(p[1].IndexOf("=") + 1);
Console.WriteLine(p[1]);
//-------------------------------------------------------
// Get IAppBuilder Definitions
if (type.ImplementedInterfaces.Contains(typeof(IAppBuilder)))
{
Loader.ConfigEditor.AppWritersClasses.Add(Loader.GetAssemblyClassDefinition(type, "IAppBuilder"));
}
}
}
}
catch (Exception ex)
{
}
}
catch (Exception ex)
{
}
}
return er;
}
public IErrorsInfo Scan()
{
ErrorsInfo er = new ErrorsInfo();
try
{
LoadAllAssembly();
er.Flag = Errors.Ok;
}
catch (Exception ex)
{
er.Ex = ex;
er.Flag = Errors.Failed;
er.Message = ex.Message;
}
return er;
}
}
}