// Author: Gockner, Simon // Created: 2020-01-27 // Copyright(c) 2020 SimonG. All Rights Reserved. using System; using System.Collections.Generic; using System.IO; using System.Reflection; using System.Threading; using System.Threading.Tasks; using GBase.Api; using GBase.Attributes; using GBase.Factories; using GBase.FileHandling.Factories; using GBase.Interfaces; using GBase.Interfaces.FileHandling; namespace GBase { /// /// A table /// public class GBaseTable : IGBaseTable { private readonly IFileHandler _fileHandler; private readonly IGBaseColumnFactory _gBaseColumnFactory; /// /// A table /// public GBaseTable(IFileHandlerFactory fileHandlerFactory, IGBaseColumnFactory gBaseColumnFactory) { _fileHandler = fileHandlerFactory.Create(); _gBaseColumnFactory = gBaseColumnFactory; Columns = new List(); Entries = new List(); INotifyGBaseEntryChanged.GBaseEntryChanged += OnGBaseEntryChanged; } /// /// The of the class that this represents /// public Type Type { get; private set; } /// /// The name of this /// public string Name { get; private set; } /// /// The s of this /// public List Columns { get; } /// /// The entries of this /// public List Entries { get; } /// /// Initialize this /// /// The of the class that this represents /// The name of this /// The path to the database files /// A to cancel the asynchronous operation /// True if successful, false if not public async Task Init(Type type, string name, string databasePath, CancellationToken cancellationToken) { Type = type; Name = name; string fileName = $"{name}.{GBase.GBASE_TABLE_FILE_EXTENSION}"; string path = Path.Combine(databasePath, fileName); await _fileHandler.Init(path, cancellationToken); //TODO: Init columns list depending on GBaseColumnAttributes set for this GBaseTable foreach (var property in type.GetProperties()) { GBaseColumnAttribute gBaseColumnAttribute = property.GetCustomAttribute(); if (gBaseColumnAttribute == null) continue; IGBaseColumn gBaseColumn = _gBaseColumnFactory.Create(); AddColumn(gBaseColumn); } return true; } /// /// Add a given to this /// /// The given /// True if successful, false if not public bool AddColumn(IGBaseColumn column) { if (Columns.Contains(column)) return false; Columns.Add(column); return true; } /// /// Remove a given from this /// /// The given /// True if successful, false if not public bool RemoveColumn(IGBaseColumn column) { if (!Columns.Contains(column)) return false; return Columns.Remove(column); } private bool AddEntry(object entry) //TODO: Write to file { Entries.Add(entry); return true; } private bool ModifyEntry(object entry, string propertyName, object value) //TODO: Write to file { PropertyInfo property = entry.GetType().GetProperty(propertyName); if (property == null) return false; property.SetValue(entry, value); return true; } private bool RemoveEntry(object entry) //TODO: remove from file { if (!Entries.Contains(entry)) return false; return Entries.Remove(entry); } /// /// A entry changed /// /// The entry (sender) /// The private void OnGBaseEntryChanged(object entry, GBaseEntryChangedEventArgs args) { //TODO: Might change, depending on #23 bool success; if (args == null) success = RemoveEntry(entry); else if (!Entries.Contains(entry)) success = AddEntry(entry); else success = ModifyEntry(entry, args.ColumnName, args.Value); if (!success) throw new Exception("Failed to handle EntryChanged"); //TODO: Decide what to do here } /// /// The method /// /// A to await public async ValueTask DisposeAsync() { await _fileHandler.DisposeAsync(); foreach (var column in Columns) { await column.DisposeAsync(); } Columns.Clear(); } } }