// 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();
}
}
}