Skip to content

Beep Data Management Engine (BeepDM)

Fahad Aldhubaib edited this page Jan 7, 2023 · 20 revisions

Main Components of Beep Engine (interfaces)

  1. IDMEEditor : Mother Class for all Below Classes.
  2. IDataSource: Class implementation of Beep DataSource.
  3. IETL: Extract,Transform and Load Module.
  4. IConfigEditor: Configuration Class that handles configuration loading/saving.
  5. IDataTypesHelper: Handles Data Type Mapping and Configurations.
  6. IUtil: Handles common Functions used by Engine.
  7. IAssemblyHandler: Handles Loading Assembly and Extracting needed Class implementations of (DataSources, Drivers, IDM_Addin, Extrensions, etc..).
  8. IErrorsInfo: Handles Error Handling.
  9. IDMLogger: Handles Logging.
  10. IJsonLoader: Handles Json Load/Save Files.
  11. IClassCreator: Creates Classes/Types of Data source Entities.
  12. IWorkFlowEditor: Data WorkFlows Manager.
  13. IWorkFlowStepEditor: Data WorkFlow Step/Stage Manager.
  14. IRuleParser: Data Rules Parsers used in Workflows.
  15. IRulesEditor: Data Rules Manager.

The Directory Structure for Every Beep Data Management Project has the following Directories

  1. Addin : Where you place all DLL that have "Addin" Interface (usercontrol, form,class,etc ..)
  2. AI : Where we store all AI scripts (user Later)
  3. 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.
  4. ConnectionDrivers: Store all Data source drivers (oracle ,sqlite,sqlserver, etc)
  5. DataFiles : Primary strorage for Data Files needed for Project
  6. DataViews : A DataView is a Fedrated View of Different Data Source entities, you can compile. Json DataView File Stored Here.
  7. Entities : Temporary place to store Datasource Entities Descriptions.
  8. GFX : a place to Store Gfx and icons needed by Application.
  9. LoadingExtensions: hold Classe Implementation of "ILoadingExtension". add extra functionality and dynmicaly load other data classes in your Application not defined in engine.
  10. Mapping : place to Store Mapping Definitions for Datasource to other Datasource.
  11. OtherDLL : Place to Store other dll needed for your application.
  12. ProjectClasses : The primary Folder for Loading (DataSource Implementation,Addins,etc)
  13. ProjectData : Place to store files
  14. Scripts : Place to store scripts and logs
  15. WorkFlow : place to store Workflow definitions

Lets get to the good part

Major Classes in the Platfrom

Image of Yaktocat

Mother Class DMEEditor

  • 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 Data Source

  • Create New Class Implementing "IDataSource".
  • You can check or Change our Implementations of all DataSource here Beep Data Sources

Example of IDataSource Implementation

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 New Data Source to Platform

  • 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 Beep Enterprize Configuration Menu

  • 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 New Addin

  • 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 Extension for Engine

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;
       }
   }
}