diff --git a/.idea/.idea.GBase/.idea/encodings.xml b/.idea/.idea.GBase/.idea/encodings.xml
deleted file mode 100644
index df87cf9..0000000
--- a/.idea/.idea.GBase/.idea/encodings.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-
-
-
-
\ No newline at end of file
diff --git a/GBase.sln.DotSettings b/GBase.sln.DotSettings
index 976aca6..cb097b1 100644
--- a/GBase.sln.DotSettings
+++ b/GBase.sln.DotSettings
@@ -2,5 +2,6 @@
Author: $USER_NAME$
Created: $CREATED_YEAR$-$CREATED_MONTH$-$CREATED_DAY$
Copyright(c) $CREATED_YEAR$ SimonG. All Rights Reserved.
+ <Policy Inspect="True" Prefix="" Suffix="" Style="AA_BB" /><Policy Inspect="True" Prefix="" Suffix="" Style="AA_BB" /><Policy Inspect="True" Prefix="_" Suffix="" Style="aaBb" />
\ No newline at end of file
diff --git a/GBase/Attributes/GBaseTableAttribute.cs b/GBase/Attributes/GBaseTableAttribute.cs
index 078e9f6..df332f8 100644
--- a/GBase/Attributes/GBaseTableAttribute.cs
+++ b/GBase/Attributes/GBaseTableAttribute.cs
@@ -13,6 +13,11 @@ namespace GBase.Attributes
[AttributeUsage(AttributeTargets.Class)]
public class GBaseTableAttribute : Attribute //TODO: Decide how to handle enums (as table or their own type)
{
+ public GBaseTableAttribute(string folderName)
+ {
+ FolderName = folderName;
+ }
+ public string FolderName { get; }
}
}
\ No newline at end of file
diff --git a/GBase/DataHandling/Cache/XmlDataHandlerCache.cs b/GBase/DataHandling/Cache/XmlDataHandlerCache.cs
index 43d7883..e6db2a2 100644
--- a/GBase/DataHandling/Cache/XmlDataHandlerCache.cs
+++ b/GBase/DataHandling/Cache/XmlDataHandlerCache.cs
@@ -4,7 +4,9 @@
using System;
using System.Collections.Generic;
+using System.IO;
using System.Linq;
+using System.Threading;
using System.Threading.Tasks;
using GBase.DataHandling.Cache.Factories;
using GBase.Interfaces.DataHandling.Cache;
@@ -103,9 +105,11 @@ namespace GBase.DataHandling.Cache
///
/// The that implements the property
/// The of the property
+ ///
/// The name of the property
+ ///
/// An with all the values for the property
- public async Task> TryGetValues(string propertyName)
+ public async Task> TryGetValues(FileStream file, string propertyName, CancellationToken cancellationToken)
{
IXmlDataHandlerCacheEntry entry = _cache.FirstOrDefault(e => e.Type == typeof(T));
IDataHandlerCachePropertyEntry property = entry?.Properties.FirstOrDefault(p => p.PropertyName.Equals(propertyName));
@@ -114,7 +118,7 @@ namespace GBase.DataHandling.Cache
if (!property.IsInitialized) //initialize property by reading the values from the xml
{
- List values = (await _xmlDataReader.Read(propertyName))?.ToList();
+ List values = (await _xmlDataReader.Read(file, propertyName, cancellationToken))?.ToList();
if (values != null)
{
foreach (TProperty value in values.Where(value => !property.Values.Any(v => v.Equals(value))))
diff --git a/GBase/DataHandling/Exceptions/InvalidXmlFileException.cs b/GBase/DataHandling/Exceptions/InvalidXmlFileException.cs
new file mode 100644
index 0000000..adfc8fc
--- /dev/null
+++ b/GBase/DataHandling/Exceptions/InvalidXmlFileException.cs
@@ -0,0 +1,17 @@
+// Author: Gockner, Simon
+// Created: 2020-11-09
+// Copyright(c) 2020 SimonG. All Rights Reserved.
+
+using System;
+
+namespace GBase.DataHandling.Exceptions
+{
+ public class InvalidXmlFileException : Exception
+ {
+ public InvalidXmlFileException(string message)
+ : base(message)
+ {
+
+ }
+ }
+}
\ No newline at end of file
diff --git a/GBase/DataHandling/Factories/IDataHandlerFactory.cs b/GBase/DataHandling/Factories/IDataHandlerFactory.cs
new file mode 100644
index 0000000..2d0413d
--- /dev/null
+++ b/GBase/DataHandling/Factories/IDataHandlerFactory.cs
@@ -0,0 +1,13 @@
+// Author: Simon Gockner
+// Created: 2020-09-19
+// Copyright(c) 2020 SimonG. All Rights Reserved.
+
+using GBase.Interfaces.DataHandling;
+
+namespace GBase.DataHandling.Factories
+{
+ public interface IDataHandlerFactory
+ {
+ IDataHandler Create();
+ }
+}
\ No newline at end of file
diff --git a/GBase/DataHandling/Factories/IXmlDataReaderFactory.cs b/GBase/DataHandling/Factories/IXmlDataReaderFactory.cs
index 3670de9..ad11818 100644
--- a/GBase/DataHandling/Factories/IXmlDataReaderFactory.cs
+++ b/GBase/DataHandling/Factories/IXmlDataReaderFactory.cs
@@ -14,8 +14,7 @@ namespace GBase.DataHandling.Factories
///
/// Creates an
///
- /// The path to the xml file
/// A newly created instance of the implementation for
- IXmlDataReader Create(string path);
+ IXmlDataReader Create();
}
}
\ No newline at end of file
diff --git a/GBase/DataHandling/Factories/IXmlDataWriterFactory.cs b/GBase/DataHandling/Factories/IXmlDataWriterFactory.cs
index 3c17344..53eb50b 100644
--- a/GBase/DataHandling/Factories/IXmlDataWriterFactory.cs
+++ b/GBase/DataHandling/Factories/IXmlDataWriterFactory.cs
@@ -14,9 +14,7 @@ namespace GBase.DataHandling.Factories
///
/// Creates an
///
- /// The path to the xml file
- /// The root element name of the xml file
/// A newly created instance of the implementation for
- IXmlDataWriter Create(string path, string rootElementName);
+ IXmlDataWriter Create();
}
}
\ No newline at end of file
diff --git a/GBase/DataHandling/Factories/Pool/IPoolItemFactory.cs b/GBase/DataHandling/Factories/Pool/IPoolItemFactory.cs
new file mode 100644
index 0000000..5fb24c6
--- /dev/null
+++ b/GBase/DataHandling/Factories/Pool/IPoolItemFactory.cs
@@ -0,0 +1,13 @@
+// Author: Simon Gockner
+// Created: 2020-09-19
+// Copyright(c) 2020 SimonG. All Rights Reserved.
+
+using GBase.Interfaces.DataHandling.Pool;
+
+namespace GBase.DataHandling.Factories.Pool
+{
+ public interface IPoolItemFactory
+ {
+ IPoolItem Create(T item);
+ }
+}
\ No newline at end of file
diff --git a/GBase/DataHandling/Factories/Pool/IPoolRequestFactory.cs b/GBase/DataHandling/Factories/Pool/IPoolRequestFactory.cs
new file mode 100644
index 0000000..3f1e51e
--- /dev/null
+++ b/GBase/DataHandling/Factories/Pool/IPoolRequestFactory.cs
@@ -0,0 +1,13 @@
+// Author: Simon Gockner
+// Created: 2020-09-19
+// Copyright(c) 2020 SimonG. All Rights Reserved.
+
+using GBase.Interfaces.DataHandling.Pool;
+
+namespace GBase.DataHandling.Factories.Pool
+{
+ public interface IPoolRequestFactory
+ {
+ IPoolRequest Create(object requester);
+ }
+}
\ No newline at end of file
diff --git a/GBase/DataHandling/Factories/Pool/PoolItemFactory.cs b/GBase/DataHandling/Factories/Pool/PoolItemFactory.cs
new file mode 100644
index 0000000..e6bd04e
--- /dev/null
+++ b/GBase/DataHandling/Factories/Pool/PoolItemFactory.cs
@@ -0,0 +1,14 @@
+// Author: Simon Gockner
+// Created: 2020-09-19
+// Copyright(c) 2020 SimonG. All Rights Reserved.
+
+using GBase.DataHandling.Pool;
+using GBase.Interfaces.DataHandling.Pool;
+
+namespace GBase.DataHandling.Factories.Pool
+{
+ public class PoolItemFactory : IPoolItemFactory
+ {
+ public IPoolItem Create(T item) => new PoolItem(item);
+ }
+}
\ No newline at end of file
diff --git a/GBase/DataHandling/Pool/DataHandlerPool.cs b/GBase/DataHandling/Pool/DataHandlerPool.cs
new file mode 100644
index 0000000..8438d04
--- /dev/null
+++ b/GBase/DataHandling/Pool/DataHandlerPool.cs
@@ -0,0 +1,101 @@
+// Author: Simon Gockner
+// Created: 2020-09-18
+// Copyright(c) 2020 SimonG. All Rights Reserved.
+
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+using GBase.DataHandling.Factories;
+using GBase.DataHandling.Factories.Pool;
+using GBase.Interfaces.DataHandling;
+using GBase.Interfaces.DataHandling.Pool;
+
+namespace GBase.DataHandling.Pool
+{
+ public class DataHandlerPool : IDataHandlerPool
+ {
+ private readonly int _availableDataHandlers;
+ private readonly IPoolItemFactory _poolItemFactory;
+ private readonly IPoolRequestFactory _poolRequestFactory;
+ private readonly IDataHandlerFactory _dataHandlerFactory;
+
+ private readonly List> _pool;
+ private readonly List _waitingRequesters;
+
+ public DataHandlerPool(int availableDataHandlers,
+ IPoolItemFactory poolItemFactory,
+ IPoolRequestFactory poolRequestFactory,
+ IDataHandlerFactory dataHandlerFactory)
+ {
+ _availableDataHandlers = availableDataHandlers;
+ _poolItemFactory = poolItemFactory;
+ _poolRequestFactory = poolRequestFactory;
+ _dataHandlerFactory = dataHandlerFactory;
+
+ _pool = new List>();
+ _waitingRequesters = new List();
+ }
+
+ public async Task RequestDataHandler(object requester, bool overwrite, CancellationToken cancellationToken)
+ {
+ if (_pool.All(i => i.InUse) && _pool.Count == _availableDataHandlers) //no free dataHandlers available
+ return await WaitForDataHandler(requester, cancellationToken);
+ else if (_pool.All(i => i.InUse)) //every existing dataHandler is used -> create a new one
+ return CreateDataHandler(overwrite);
+ else //there are unused dataHandlers existing
+ return GetDataHandler();
+ }
+
+ private async Task WaitForDataHandler(object requester, CancellationToken cancellationToken)
+ {
+ IDataHandler dataHandler = null;
+ IPoolRequest request = _poolRequestFactory.Create(requester);
+
+ while (dataHandler == null)
+ {
+ if (_waitingRequesters.Contains(request) && _waitingRequesters.IndexOf(request) == 0) //request is in list and is first
+ {
+ if (_pool.Any(i => !i.InUse))
+ dataHandler = GetDataHandler();
+ else
+ await Task.Delay(1000, cancellationToken);
+ }
+ else if (_waitingRequesters.Contains(request)) //request is in list but not first
+ await Task.Delay(1000, cancellationToken);
+ else
+ _waitingRequesters.Add(request);
+ }
+
+ _waitingRequesters.Remove(request);
+
+ return dataHandler;
+ }
+
+ private IDataHandler CreateDataHandler(bool overwrite)
+ {
+ IPoolItem item = _poolItemFactory.Create(_dataHandlerFactory.Create());
+ item.Item.Init(overwrite);
+ _pool.Add(item);
+
+ item.InUse = true;
+ return item.Item;
+ }
+
+ private IDataHandler GetDataHandler()
+ {
+ IPoolItem item = _pool.First(i => !i.InUse);
+
+ item.InUse = true;
+ return item.Item;
+ }
+
+ public async ValueTask DisposeAsync()
+ {
+ while (_waitingRequesters.Any())
+ {
+ await Task.Delay(1000);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/GBase/DataHandling/Pool/PoolItem.cs b/GBase/DataHandling/Pool/PoolItem.cs
new file mode 100644
index 0000000..90fd4e9
--- /dev/null
+++ b/GBase/DataHandling/Pool/PoolItem.cs
@@ -0,0 +1,19 @@
+// Author: Simon Gockner
+// Created: 2020-09-19
+// Copyright(c) 2020 SimonG. All Rights Reserved.
+
+using GBase.Interfaces.DataHandling.Pool;
+
+namespace GBase.DataHandling.Pool
+{
+ public class PoolItem : IPoolItem
+ {
+ public PoolItem(T item)
+ {
+ Item = item;
+ }
+
+ public T Item { get; }
+ public bool InUse { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/GBase/DataHandling/Pool/PoolRequest.cs b/GBase/DataHandling/Pool/PoolRequest.cs
new file mode 100644
index 0000000..9a565fe
--- /dev/null
+++ b/GBase/DataHandling/Pool/PoolRequest.cs
@@ -0,0 +1,18 @@
+// Author: Simon Gockner
+// Created: 2020-09-19
+// Copyright(c) 2020 SimonG. All Rights Reserved.
+
+using GBase.Interfaces.DataHandling.Pool;
+
+namespace GBase.DataHandling.Pool
+{
+ public class PoolRequest : IPoolRequest
+ {
+ public PoolRequest(object requester)
+ {
+ Requester = requester;
+ }
+
+ public object Requester { get; }
+ }
+}
\ No newline at end of file
diff --git a/GBase/DataHandling/XmlDataHandler.cs b/GBase/DataHandling/XmlDataHandler.cs
index 6c79de3..34948f6 100644
--- a/GBase/DataHandling/XmlDataHandler.cs
+++ b/GBase/DataHandling/XmlDataHandler.cs
@@ -5,12 +5,15 @@
using System;
using System.Collections;
using System.Collections.Generic;
+using System.IO;
using System.Linq;
+using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
using GBase.DataHandling.Cache.Factories;
using GBase.DataHandling.Factories;
using GBase.Helpers;
+using GBase.Interfaces;
using GBase.Interfaces.DataHandling;
using GBase.Interfaces.DataHandling.Xml;
using GBase.Interfaces.DataHandling.Xml.Cache;
@@ -46,18 +49,15 @@ namespace GBase.DataHandling
/// A that handles its data in an xml file
///
/// The path to the xml file
- /// The root element name of the xml file
/// The factory
/// The factory
/// The factory
- public XmlDataHandler(string path,
- string rootElementName,
- IXmlDataReaderFactory xmlDataReaderFactory,
+ public XmlDataHandler(IXmlDataReaderFactory xmlDataReaderFactory,
IXmlDataWriterFactory xmlDataWriterFactory,
IXmlDataHandlerCacheFactory xmlDataHandlerCacheFactory)
{
- _xmlDataWriter = xmlDataWriterFactory.Create(path, rootElementName);
- _xmlDataReader = xmlDataReaderFactory.Create(path);
+ _xmlDataWriter = xmlDataWriterFactory.Create();
+ _xmlDataReader = xmlDataReaderFactory.Create();
_cache = xmlDataHandlerCacheFactory.Create(_xmlDataReader);
}
@@ -66,35 +66,58 @@ namespace GBase.DataHandling
/// Initialize the
///
/// If true an existing value is overwritten, if false an additional value is added
- /// A to cancel the async operation
/// Returns true if successful, false if not
- public async Task Init(bool overwrite, CancellationToken cancellationToken)
+ public bool Init(bool overwrite)
{
if (_isInitialized)
return false;
_overwrite = overwrite;
- if (!await _xmlDataWriter.Init(cancellationToken))
- return false;
+ _isInitialized = true;
+ return true;
+ }
- if (!await _xmlDataReader.Init(cancellationToken))
+ public async Task AddEntry(T entry, IGBaseTable table, FileStream entryFile, CancellationToken cancellationToken)
+ {
+ if (!await _xmlDataWriter.InitFile(entryFile, table.Type.Name, cancellationToken))
return false;
- _isInitialized = true;
+ foreach (var column in table.Columns)
+ {
+ //TODO: Set value for each column
+ PropertyInfo property = entry.GetType().GetProperty(column.Name);
+ if (property == null)
+ continue; //TODO: What to do in this case? (Shouldn't really happen...)
+
+ string valueString;
+ if (property.PropertyType != typeof(string) && property.GetValue(entry) is IEnumerable enumerable)
+ valueString = enumerable.ToGBaseString();
+ else
+ valueString = property.GetValue(entry).ToString();
+
+ await _xmlDataWriter.Write(entryFile, property.Name, valueString, property.PropertyType, _overwrite, cancellationToken);
+ }
return true;
}
+ public Task RemoveEntry(T entry)
+ {
+ throw new NotImplementedException();
+ }
+
///
/// Set the value for the given property
///
/// The that implements the property
/// The of the property
+ ///
/// The name of the property
/// The value to set
+ ///
/// A to await
- public async Task SetValue(string propertyName, TProperty value)
+ public async Task SetValue(FileStream entryFile, string propertyName, TProperty value, CancellationToken cancellationToken)
{
if (value == null)
return;
@@ -106,7 +129,7 @@ namespace GBase.DataHandling
valueString = value.ToString();
await _cache.SetValue(propertyName, value, _overwrite);
- await _xmlDataWriter.Write(propertyName, valueString, _overwrite);
+ await _xmlDataWriter.Write(entryFile, propertyName, valueString, _overwrite, cancellationToken);
}
///
@@ -114,10 +137,12 @@ namespace GBase.DataHandling
///
/// The of the property
/// The of the property
+ ///
/// The name of the property
/// The value to set
+ ///
/// A to await
- public async Task RemoveValue(string propertyName, TProperty value)
+ public async Task RemoveValue(FileStream entryFile, string propertyName, TProperty value, CancellationToken cancellationToken)
{
if (value == null)
return;
@@ -129,7 +154,7 @@ namespace GBase.DataHandling
valueString = value.ToString();
await _cache.TryRemoveValue(propertyName, value);
- await _xmlDataWriter.Remove(propertyName, valueString);
+ await _xmlDataWriter.Remove(entryFile, propertyName, valueString, cancellationToken);
}
///
@@ -137,11 +162,13 @@ namespace GBase.DataHandling
///
/// The that implements the property
/// The of the property
+ ///
/// The name of the property
+ ///
/// The value for the given property
- public async Task GetValue(string propertyName)
+ public async Task GetValue(FileStream file, string propertyName, CancellationToken cancellationToken)
{
- IEnumerable enumerable = await GetValues(propertyName);
+ IEnumerable enumerable = await GetValues(file, propertyName, cancellationToken);
return enumerable == null ? default : enumerable.FirstOrDefault();
}
@@ -150,25 +177,17 @@ namespace GBase.DataHandling
///
/// The that implements the property
/// The of the property
+ ///
/// The name of the property
+ ///
/// An with all the values for the property
- public async Task> GetValues(string propertyName)
+ public async Task> GetValues(FileStream file, string propertyName, CancellationToken cancellationToken)
{
- IEnumerable cachedValues = await _cache.TryGetValues(propertyName);
+ IEnumerable cachedValues = await _cache.TryGetValues(file, propertyName, cancellationToken);
if (cachedValues != null)
return cachedValues;
- return await _xmlDataReader.Read(propertyName);
- }
-
- ///
- /// Dispose used resources asynchronously
- ///
- /// A to await
- public async ValueTask DisposeAsync()
- {
- await _xmlDataReader.DisposeAsync();
- await _xmlDataWriter.DisposeAsync();
+ return await _xmlDataReader.Read(file, propertyName, cancellationToken);
}
}
}
\ No newline at end of file
diff --git a/GBase/DataHandling/XmlDataReader.cs b/GBase/DataHandling/XmlDataReader.cs
index 03b7396..e83ba65 100644
--- a/GBase/DataHandling/XmlDataReader.cs
+++ b/GBase/DataHandling/XmlDataReader.cs
@@ -10,6 +10,7 @@ using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Xml.Linq;
+using GBase.DataHandling.Exceptions;
using GBase.Helpers;
using GBase.Interfaces.DataHandling;
using GBase.Interfaces.DataHandling.Xml;
@@ -21,65 +22,34 @@ namespace GBase.DataHandling
///
public class XmlDataReader : IXmlDataReader
{
- private readonly FileStream _file;
- private XDocument _xmlDocument;
- private XElement _rootElement;
-
- private bool _isInitialized;
- private CancellationToken _cancellationToken;
-
- ///
- /// A that reads from a xml file
- ///
- /// The path to the xml file
- public XmlDataReader(string path)
- {
- _file = File.Open(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
- }
-
- ///
- /// Initialize the
- ///
- /// A to cancel the async operation
- /// Returns true if successful, false if not
- /// No root element found
- public async Task Init(CancellationToken cancellationToken)
- {
- if (_isInitialized)
- return false;
-
- _cancellationToken = cancellationToken;
- _xmlDocument = await XDocument.LoadAsync(_file, LoadOptions.None, _cancellationToken);
-
- _rootElement = _xmlDocument.Root;
- if (_rootElement == null)
- throw new Exception("No root element found.");
-
- _isInitialized = true;
-
- return true;
- }
-
///
/// Read the data of a property
///
/// The
/// The of the property
+ ///
/// The name of the property
+ ///
/// The data of the given property, null if no data found
///
/// Invalid found for the read object
- public async Task> Read(string propertyName)
+ public async Task> Read(FileStream file, string propertyName, CancellationToken cancellationToken)
//TODO: Read currently doesn't work for newly added items -> probably because file was loaded before new items were added; is probably not a problem -> cache
{
string typeName = typeof(T).FullName;
if (typeName == null)
throw new ArgumentNullException(nameof(typeName));
+ XDocument xmlDocument = await XDocument.LoadAsync(file, LoadOptions.None, cancellationToken);
+ file.Seek(0, SeekOrigin.Begin); //reset stream to it's beginning to be able to save it
+
return await Task.Run(() =>
{
- XElement typeElement = _rootElement.Element(typeName);
- XElement propertyElement = typeElement?.Element(propertyName);
+ XElement rootElement = xmlDocument.Root;
+ if (rootElement == null)
+ throw new InvalidXmlFileException("No root element is set.");
+
+ XElement propertyElement = rootElement.Element(propertyName);
XAttribute propertyTypeAttribute = propertyElement?.Attribute(XmlDataHandler.VALUE_TYPE_ATTRIBUTE_NAME);
if (propertyTypeAttribute == null)
return null;
@@ -98,16 +68,7 @@ namespace GBase.DataHandling
return values.Select(Enumerables.ConvertToGBaseEnumerable).ToList();
return values.Select(value => (TProperty)Convert.ChangeType(value, typeof(TProperty))).ToList();
- }, _cancellationToken);
- }
-
- ///
- /// Dispose used resources asynchronously
- ///
- /// A to await
- public async ValueTask DisposeAsync()
- {
- await _file.DisposeAsync();
+ }, cancellationToken);
}
}
}
\ No newline at end of file
diff --git a/GBase/DataHandling/XmlDataWriter.cs b/GBase/DataHandling/XmlDataWriter.cs
index 3799f0b..31cfc74 100644
--- a/GBase/DataHandling/XmlDataWriter.cs
+++ b/GBase/DataHandling/XmlDataWriter.cs
@@ -8,6 +8,7 @@ using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Xml.Linq;
+using GBase.DataHandling.Exceptions;
using GBase.Interfaces.DataHandling;
using GBase.Interfaces.DataHandling.Xml;
@@ -18,115 +19,96 @@ namespace GBase.DataHandling
///
public class XmlDataWriter : IXmlDataWriter
{
- private readonly string _rootElementName;
- private readonly FileStream _file;
-
- private XDocument _xmlDocument;
- private XElement _rootElement;
-
- private bool _isInitialized;
- private CancellationToken _cancellationToken;
-
- ///
- /// A that writes to an xml file
- ///
- /// The path to the xml file
- /// The root element name of the xml file
- public XmlDataWriter(string path, string rootElementName)
- {
- _rootElementName = rootElementName;
- _file = File.Open(path, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.Read);
- }
-
///
/// Initialize the
///
+ ///
+ ///
/// A to cancel the async operation
/// Returns true if successful, false if not
/// No root element found
- public async Task Init(CancellationToken cancellationToken)
+ public async Task InitFile(FileStream file, string rootElementName, CancellationToken cancellationToken)
{
- if (_isInitialized)
- return false;
+ //if the xml file isn't empty, return
+ if (file.Length > 3) //> 3 because of BOM
+ return true; //TODO: Don't return bool?
+
+ XDocument xmlDocument = new XDocument();
+ xmlDocument.Add(new XElement(rootElementName));
+ file.Seek(0, SeekOrigin.Begin); //reset stream to it's beginning to be able to save it
+ await xmlDocument.SaveAsync(file, SaveOptions.OmitDuplicateNamespaces, cancellationToken);
- _cancellationToken = cancellationToken;
- //if the xml file is empty, write the root element
- if (_file.Length <= 3) //<= 3 because of BOM
- {
- _xmlDocument = new XDocument();
- _xmlDocument.Add(new XElement(_rootElementName));
- _file.Seek(0, SeekOrigin.Begin); //reset stream to it's beginning to be able to save it
- await _xmlDocument.SaveAsync(_file, SaveOptions.OmitDuplicateNamespaces, cancellationToken);
- }
- else
- {
- _xmlDocument = await XDocument.LoadAsync(_file, LoadOptions.None, _cancellationToken);
- }
-
- _rootElement = _xmlDocument.Root;//?.Element(_rootElementName);
- if (_rootElement == null)
- throw new Exception("No root element found.");
-
- _isInitialized = true;
return true;
}
///
/// Write the data of a property
///
- /// The that implements the property
+ /// The
/// The of the property
+ ///
+ /// The name of the property
+ /// The value of the property
+ /// If true an existing value is overwritten, if false an additional value is added
+ ///
+ /// A to await
+ public async Task Write(FileStream file, string propertyName, string value, bool overwrite, CancellationToken cancellationToken) =>
+ await Write(file, propertyName, value, typeof(TProperty), overwrite, cancellationToken);
+
+ ///
+ /// Write the data of a property
+ ///
+ /// The that implements the property
+ ///
/// The name of the property
/// The value of the property
+ ///
/// If true an existing value is overwritten, if false an additional value is added
+ ///
/// A to await
///
- public async Task Write(string propertyName, string value, bool overwrite)
+ /// No root element is set
+ public async Task Write(FileStream file, string propertyName, string value, Type propertyType, bool overwrite, CancellationToken cancellationToken)
{
string typeName = typeof(T).FullName;
if (typeName == null)
throw new ArgumentNullException(nameof(typeName));
-
- _file.Seek(0, SeekOrigin.Begin); //reset stream to it's beginning to be able to save it
-
- XElement typeElement = _rootElement.Element(typeName);
- if (typeElement != null) //type element already exists
+
+ file.Seek(0, SeekOrigin.Begin); //reset stream to it's beginning to be able to save it
+ XDocument xmlDocument = await XDocument.LoadAsync(file, LoadOptions.None, cancellationToken);
+ file.Seek(0, SeekOrigin.Begin); //reset stream to it's beginning to be able to save it
+
+ XElement rootElement = xmlDocument.Root;
+ if (rootElement == null)
+ throw new InvalidXmlFileException("No root element is set.");
+
+ XElement propertyElement = rootElement.Element(propertyName);
+ if (propertyElement != null) //property element already exists
{
- XElement propertyElement = typeElement.Element(propertyName);
- if (propertyElement != null) //property element already exists
+ XElement valueElement = propertyElement.Element(XmlDataHandler.VALUE_ELEMENT_NAME);
+ if (valueElement != null && overwrite) //value element exists and overwrite is true
{
- XElement valueElement = propertyElement.Element(XmlDataHandler.VALUE_ELEMENT_NAME);
- if (valueElement != null && overwrite) //value element exists and overwrite is true
- {
- valueElement.Value = value; //overwrite existing value
- }
- else if (!overwrite && propertyElement.Elements(XmlDataHandler.VALUE_ELEMENT_NAME).Any(v => v.Value.Equals(value))) //no overwrite and same value exists already
- {
- XElement sameValueElement = propertyElement.Elements(XmlDataHandler.VALUE_ELEMENT_NAME).First(v => v.Value.Equals(value));
- sameValueElement.Remove(); //remove the already existing value from its current position
- propertyElement.AddFirst(sameValueElement); //add it as the first element again
- }
- else //no value element exists or overwrite is false
- propertyElement.AddFirst(new XElement(XmlDataHandler.VALUE_ELEMENT_NAME) { Value = value }); //add a new value element
+ valueElement.Value = value; //overwrite existing value
}
- else //property element doesn't exist
+ else if (!overwrite && propertyElement.Elements(XmlDataHandler.VALUE_ELEMENT_NAME).Any(v => v.Value.Equals(value))) //no overwrite and same value exists already
{
- propertyElement = new XElement(propertyName, new XElement(XmlDataHandler.VALUE_ELEMENT_NAME) { Value = value }); //create the new property element with the value element
- propertyElement.SetAttributeValue(XmlDataHandler.VALUE_TYPE_ATTRIBUTE_NAME, typeof(TProperty).FullName); //add the property type attribute
-
- typeElement.Add(propertyElement); //create new property element with the value element
+ XElement sameValueElement = propertyElement.Elements(XmlDataHandler.VALUE_ELEMENT_NAME).First(v => v.Value.Equals(value));
+ sameValueElement.Remove(); //remove the already existing value from its current position
+ propertyElement.AddFirst(sameValueElement); //add it as the first element again
}
+ else //no value element exists or overwrite is false
+ propertyElement.AddFirst(new XElement(XmlDataHandler.VALUE_ELEMENT_NAME) { Value = value }); //add a new value element
}
- else //type element doesn't exist
+ else //property element doesn't exist
{
- XElement propertyElement = new XElement(propertyName, new XElement(XmlDataHandler.VALUE_ELEMENT_NAME) { Value = value }); //create the new property element with the value element
- propertyElement.SetAttributeValue(XmlDataHandler.VALUE_TYPE_ATTRIBUTE_NAME, typeof(TProperty).FullName); //add the property type attribute
+ propertyElement = new XElement(propertyName, new XElement(XmlDataHandler.VALUE_ELEMENT_NAME) { Value = value }); //create the new property element with the value element
+ propertyElement.SetAttributeValue(XmlDataHandler.VALUE_TYPE_ATTRIBUTE_NAME, propertyType.FullName); //add the property type attribute
- _rootElement.Add(new XElement(typeName, propertyElement)); //create a new type element with the new property element
+ rootElement.Add(propertyElement); //create new property element with the value element
}
//TODO: check if whole file is overwritten (probably) -> performance issues for large files?
- await _xmlDocument.SaveAsync(_file, SaveOptions.OmitDuplicateNamespaces, _cancellationToken); //save the document with the added elements
+ await xmlDocument.SaveAsync(file, SaveOptions.OmitDuplicateNamespaces, cancellationToken); //save the document with the added elements
}
///
@@ -134,19 +116,27 @@ namespace GBase.DataHandling
///
/// The of the property
/// The of the property
+ ///
/// The name of the property
/// The value to set
+ ///
/// A to await
///
- public async Task Remove(string propertyName, string value)
+ /// No root element is set
+ public async Task Remove(FileStream file, string propertyName, string value, CancellationToken cancellationToken)
{
string typeName = typeof(T).FullName;
if (typeName == null)
throw new ArgumentNullException(nameof(typeName));
- _file.Seek(0, SeekOrigin.Begin); //reset stream to it's beginning to be able to save it
+ XDocument xmlDocument = await XDocument.LoadAsync(file, LoadOptions.None, cancellationToken);
+ file.Seek(0, SeekOrigin.Begin); //reset stream to it's beginning to be able to save it
- XElement typeElement = _rootElement.Element(typeName);
+ XElement rootElement = xmlDocument.Root;
+ if (rootElement == null)
+ throw new InvalidXmlFileException("No root element is set.");
+
+ XElement typeElement = rootElement.Element(typeName);
XElement propertyElement = typeElement?.Element(propertyName);
XElement valueElement = propertyElement?.Elements(XmlDataHandler.VALUE_ELEMENT_NAME).FirstOrDefault(e => e.Value.Equals(value));
if (valueElement == null)
@@ -155,17 +145,7 @@ namespace GBase.DataHandling
valueElement.Remove();
//TODO: check if whole file is overwritten (probably) -> performance issues for large files?
- await _xmlDocument.SaveAsync(_file, SaveOptions.OmitDuplicateNamespaces, _cancellationToken); //save the document with the added elements
- }
-
- ///
- /// Dispose used resources asynchronously
- ///
- /// A to await
- public async ValueTask DisposeAsync()
- {
- await _xmlDocument.SaveAsync(_file, SaveOptions.None, _cancellationToken);
- await _file.DisposeAsync();
+ await xmlDocument.SaveAsync(file, SaveOptions.OmitDuplicateNamespaces, cancellationToken); //save the document with the added elements
}
}
}
\ No newline at end of file
diff --git a/GBase/Exceptions/InvalidTableTypeException.cs b/GBase/Exceptions/InvalidTableTypeException.cs
new file mode 100644
index 0000000..9be6013
--- /dev/null
+++ b/GBase/Exceptions/InvalidTableTypeException.cs
@@ -0,0 +1,27 @@
+// Author: Simon Gockner
+// Created: 2020-09-18
+// Copyright(c) 2020 SimonG. All Rights Reserved.
+
+using System;
+using GBase.Api;
+
+namespace GBase.Exceptions
+{
+ ///
+ /// that the passed table type doesn't implement "/>
+ ///
+ public class InvalidTableTypeException : Exception
+ {
+ ///
+ /// that the passed table type doesn't implement "/>
+ ///
+ /// The table type
+ public InvalidTableTypeException(Type type)
+ : base($"Table type ({type}) doesn't implement {nameof(INotifyGBaseEntryChanged)}.")
+ {
+ Type = type;
+ }
+
+ public Type Type { get; }
+ }
+}
\ No newline at end of file
diff --git a/GBase/Exceptions/MissingTableException.cs b/GBase/Exceptions/MissingTableException.cs
new file mode 100644
index 0000000..78af97c
--- /dev/null
+++ b/GBase/Exceptions/MissingTableException.cs
@@ -0,0 +1,23 @@
+// Author: Gockner, Simon
+// Created: 2020-09-18
+// Copyright(c) 2020 SimonG. All Rights Reserved.
+
+using System;
+
+namespace GBase.Exceptions
+{
+ ///
+ /// that the table for the given is missing
+ ///
+ public class MissingTableException : Exception
+ {
+ ///
+ /// that the table for the given is missing
+ ///
+ public MissingTableException()
+ : base($"There is no table for type {typeof(T)}.")
+ {
+
+ }
+ }
+}
\ No newline at end of file
diff --git a/GBase/Factories/GBaseTableFactory.cs b/GBase/Factories/GBaseTableFactory.cs
new file mode 100644
index 0000000..d20772d
--- /dev/null
+++ b/GBase/Factories/GBaseTableFactory.cs
@@ -0,0 +1,45 @@
+// Author: Simon Gockner
+// Created: 2020-09-18
+// Copyright(c) 2020 SimonG. All Rights Reserved.
+
+using System;
+using GBase.FileHandling.Factories;
+using GBase.Interfaces;
+using GBase.Interfaces.DataHandling.Pool;
+using GBase.Interfaces.FileHandling;
+
+namespace GBase.Factories
+{
+ ///
+ /// Factory for the
+ ///
+ public class GBaseTableFactory : IGBaseTableFactory
+ {
+ private readonly IFileHandlerFactory _fileHandlerFactory;
+ private readonly IDataHandlerPool _dataHandlerPool;
+ private readonly IGBaseColumnFactory _gBaseColumnFactory;
+
+ ///
+ /// Factory for the
+ ///
+ /// Factory for the
+ ///
+ /// Factory for the
+ public GBaseTableFactory(IFileHandlerFactory fileHandlerFactory, IDataHandlerPool dataHandlerPool, IGBaseColumnFactory gBaseColumnFactory)
+ {
+ _fileHandlerFactory = fileHandlerFactory;
+ _dataHandlerPool = dataHandlerPool;
+ _gBaseColumnFactory = gBaseColumnFactory;
+ }
+
+ ///
+ /// Creates an
+ ///
+ /// A newly created instance of the implementation for
+ public IGBaseTable Create(Type type)
+ {
+ Type gBaseTableType = typeof(GBaseTable<>).MakeGenericType(type);
+ return (IGBaseTable) Activator.CreateInstance(gBaseTableType, _fileHandlerFactory, _dataHandlerPool, _gBaseColumnFactory);
+ }
+ }
+}
\ No newline at end of file
diff --git a/GBase/Factories/IGBaseColumnFactory.cs b/GBase/Factories/IGBaseColumnFactory.cs
index 46f5b4c..7bd39ed 100644
--- a/GBase/Factories/IGBaseColumnFactory.cs
+++ b/GBase/Factories/IGBaseColumnFactory.cs
@@ -16,6 +16,6 @@ namespace GBase.Factories
/// Creates an
///
/// A newly created instance of the implementation for
- IGBaseColumn Create();
+ IGBaseColumn Create(string name);
}
}
\ No newline at end of file
diff --git a/GBase/Factories/IGBaseTableFactory.cs b/GBase/Factories/IGBaseTableFactory.cs
index 43792c0..11c8554 100644
--- a/GBase/Factories/IGBaseTableFactory.cs
+++ b/GBase/Factories/IGBaseTableFactory.cs
@@ -3,6 +3,7 @@
// Copyright(c) 2020 SimonG. All Rights Reserved.
+using System;
using GBase.Interfaces;
namespace GBase.Factories
@@ -16,6 +17,6 @@ namespace GBase.Factories
/// Creates an
///
/// A newly created instance of the implementation for
- IGBaseTable Create();
+ IGBaseTable Create(Type type);
}
}
\ No newline at end of file
diff --git a/GBase/FileHandling/Exceptions/FileNotExistingException.cs b/GBase/FileHandling/Exceptions/FileNotExistingException.cs
new file mode 100644
index 0000000..2981ec1
--- /dev/null
+++ b/GBase/FileHandling/Exceptions/FileNotExistingException.cs
@@ -0,0 +1,17 @@
+// Author: Gockner, Simon
+// Created: 2020-11-10
+// Copyright(c) 2020 SimonG. All Rights Reserved.
+
+using System;
+
+namespace GBase.FileHandling.Exceptions
+{
+ public class FileNotExistingException : Exception
+ {
+ public FileNotExistingException()
+ : base($"File for the given type {typeof(T)} is not existing.")
+ {
+
+ }
+ }
+}
\ No newline at end of file
diff --git a/GBase/FileHandling/FileHandler.cs b/GBase/FileHandling/FileHandler.cs
index 468fe12..4e1d396 100644
--- a/GBase/FileHandling/FileHandler.cs
+++ b/GBase/FileHandling/FileHandler.cs
@@ -2,13 +2,13 @@
// Created: 2020-02-12
// Copyright(c) 2020 SimonG. All Rights Reserved.
-using System;
using System.Collections.Generic;
+using System.IO;
+using System.Linq;
using System.Threading;
using System.Threading.Tasks;
-using GBase.DataHandling.Factories;
-using GBase.Interfaces.DataHandling;
-using GBase.Interfaces.DataHandling.Xml;
+using GBase.FileHandling.Exceptions;
+using GBase.Interfaces;
using GBase.Interfaces.FileHandling;
namespace GBase.FileHandling
@@ -18,22 +18,22 @@ namespace GBase.FileHandling
///
public class FileHandler : IFileHandler
{
- private readonly IXmlDataHandlerFactory _dataHandlerFactory;
-
+ ///
+ /// The file extension for all GBase tables
+ ///
+ public const string GBASE_TABLE_FILE_EXTENSION = "gb";
+
+ private readonly List _files;
+ private string _path;
+
///
/// Internal file handler
///
- /// Factory for the
- public FileHandler(IXmlDataHandlerFactory xmlDataHandlerFactory)
+ public FileHandler()
{
- _dataHandlerFactory = xmlDataHandlerFactory;
+ _files = new List();
}
- ///
- /// The of this
- ///
- private IDataHandler DataHandler { get; set; }
-
///
/// Initialize this
///
@@ -42,60 +42,48 @@ namespace GBase.FileHandling
/// True if successful, false if not
public async Task Init(string path, CancellationToken cancellationToken)
{
- DataHandler = _dataHandlerFactory.Create();
-
- bool success = await DataHandler.Init(false, cancellationToken);
- return success;
+ _path = path;
+ return true; //TODO: initialize existing files
}
- ///
- /// Set the value for the given property
- ///
- /// The of the property
- /// The of the property
- /// The name of the property
- /// The value to set
- /// A to await
- public async Task SetValue(string propertyName, TProperty value)
+ public IGBaseFile CreateEntryFile(T entry, IGBaseTable table)
{
- await DataHandler.SetValue(propertyName, value);
- }
+ string directoryPath = Path.Combine(_path, table.FolderName);
+
+ //create directory if it doesn't exist
+ Directory.CreateDirectory(directoryPath);
+
+ //create new entry file
+ string filePath = $"{Path.Combine(directoryPath, entry.ToString())}.{GBASE_TABLE_FILE_EXTENSION}";
+ FileStream entryFile = File.Open(filePath, FileMode.OpenOrCreate, FileAccess.ReadWrite); //TODO: Stream has to be disposed
+
+ IGBaseFile file = new GBaseFile(entry, entryFile, filePath);
+ _files.Add(file);
- ///
- /// Remove the value for the given property
- ///
- /// The of the property
- /// The of the property
- /// The name of the property
- /// The value to set
- /// A to await
- public async Task RemoveValue(string propertyName, TProperty value)
- {
- await DataHandler.RemoveValue(propertyName, value);
+ return file.UseFile();
}
- ///
- /// Get the value for the given property, if multiple values are set the first is returned
- ///
- /// The of the property
- /// The of the property
- /// The name of the property
- /// The value for the given property
- public async Task GetValue(string propertyName)
+ public async Task DeleteEntryFile(T entry)
{
- return await DataHandler.GetValue(propertyName);
+ IGBaseFile file = _files.FirstOrDefault(f => f.Entry.Equals(entry));
+ if (file == default)
+ return false;
+
+ await file.File.DisposeAsync();
+ File.Delete(file.FilePath);
+ return true;
}
- ///
- /// Get all the values that are set for the given property
- ///
- /// The of the property
- /// The of the property
- /// The name of the property
- /// An with all the values for the property
- public async Task> GetValues(string propertyName)
+ public async Task RequestEntryFile(T entry)
{
- return await DataHandler.GetValues(propertyName);
+ IGBaseFile file = _files.FirstOrDefault(f => f.Entry.Equals(entry));
+ if (file == default)
+ throw new FileNotExistingException();
+
+ if (file.InUse)
+ await Task.Delay(1000);
+
+ return file.UseFile();
}
///
@@ -104,7 +92,15 @@ namespace GBase.FileHandling
/// A to await
public async ValueTask DisposeAsync()
{
- await DataHandler.DisposeAsync();
+ while (_files.Any(f => f.InUse))
+ {
+ await Task.Delay(1000);
+ }
+
+ foreach (var file in _files)
+ {
+ await file.File.DisposeAsync();
+ }
}
}
}
\ No newline at end of file
diff --git a/GBase/FileHandling/GBaseFile.cs b/GBase/FileHandling/GBaseFile.cs
new file mode 100644
index 0000000..aaf0f56
--- /dev/null
+++ b/GBase/FileHandling/GBaseFile.cs
@@ -0,0 +1,32 @@
+// Author: Gockner, Simon
+// Created: 2020-11-10
+// Copyright(c) 2020 SimonG. All Rights Reserved.
+
+using System.IO;
+using GBase.Interfaces.FileHandling;
+
+namespace GBase.FileHandling
+{
+ public class GBaseFile : IGBaseFile
+ {
+ public GBaseFile(object entry, FileStream file, string filePath)
+ {
+ Entry = entry;
+ File = file;
+ FilePath = filePath;
+ }
+
+ public object Entry { get; }
+ public FileStream File { get; }
+ public string FilePath { get; }
+ public bool InUse { get; private set; }
+
+ public IGBaseFile UseFile()
+ {
+ InUse = true;
+ return this;
+ }
+
+ public void Dispose() => InUse = false;
+ }
+}
\ No newline at end of file
diff --git a/GBase/GBase.cs b/GBase/GBase.cs
index 0bf717e..eba244f 100644
--- a/GBase/GBase.cs
+++ b/GBase/GBase.cs
@@ -9,6 +9,7 @@ using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
using GBase.Attributes;
+using GBase.Exceptions;
using GBase.Factories;
using GBase.Interfaces;
using GBase.Interfaces.Settings;
@@ -20,11 +21,6 @@ namespace GBase
///
public class GBase : IGBase
{
- ///
- /// The file extension for all GBase tables
- ///
- public const string GBASE_TABLE_FILE_EXTENSION = "gb"; //TODO: Find correct place for this const
-
private readonly IGBaseTableFactory _gBaseTableFactory;
///
@@ -74,8 +70,8 @@ namespace GBase
if (gBaseTableAttribute == null)
continue;
- IGBaseTable gBaseTable = _gBaseTableFactory.Create();
- await gBaseTable.Init(type, type.Name, Settings.DatabasePath, cancellationToken);
+ IGBaseTable gBaseTable = _gBaseTableFactory.Create(type);
+ await gBaseTable.Init(type, Settings.DatabasePath, gBaseTableAttribute.FolderName, cancellationToken);
AddTable(gBaseTable);
}
@@ -93,13 +89,23 @@ namespace GBase
if (Tables.Contains(table))
return false;
- if (Tables.Any(t => t.Name.Equals(table.Name)))
+ if (Tables.Any(t => t.FolderName.Equals(table.FolderName)))
return false;
Tables.Add(table);
return true;
}
+ public IGBaseTable GetTable()
+ {
+ if (Tables.OfType>().Any())
+ return Tables.OfType>().First();
+
+ throw new MissingTableException();
+ // //TODO: This probably doesn't work, because even though t.Type : T, IGBaseTable !: IGBaseTable
+ // return (IGBaseTable) Convert.ChangeType(Tables.FirstOrDefault(t => typeof(T).IsAssignableFrom(t.Type)), typeof(IGBaseTable)); //TestMe
+ }
+
///
/// Removes a given from this
///
@@ -113,6 +119,43 @@ namespace GBase
return Tables.Remove(table);
}
+ public async Task AddEntry(T entry, CancellationToken cancellationToken)
+ {
+ IGBaseTable table = GetTable();
+ if (table == null)
+ throw new MissingTableException();
+
+ return await table.AddEntry(entry, cancellationToken);
+ }
+
+ public async Task SetValue(T entry, string propertyName, TProperty value, CancellationToken cancellationToken)
+ {
+ IGBaseTable table = GetTable();
+ if (table == null)
+ throw new MissingTableException();
+
+ await table.SetValue(entry, propertyName, value, cancellationToken);
+ }
+
+ public async Task GetValue(T entry, string propertyName, CancellationToken cancellationToken)
+ {
+ IGBaseTable table = GetTable();
+ if (table == null)
+ throw new MissingTableException();
+
+ return await table.GetValue(entry, propertyName, cancellationToken);
+ }
+
+ public async Task> GetValues(T entry, string propertyName, CancellationToken cancellationToken)
+ {
+ IGBaseTable table = GetTable();
+ if (table == null)
+ throw new MissingTableException();
+
+ return await table.GetValues(entry, propertyName, cancellationToken);
+ }
+
+
///
/// Dispose used resources asynchronously
///
diff --git a/GBase/GBase.xml b/GBase/GBase.xml
index 2945813..d9641b4 100644
--- a/GBase/GBase.xml
+++ b/GBase/GBase.xml
@@ -87,13 +87,15 @@
The value to set
A to await
-
+
Try to get values from the cache for the given property
The that implements the propertyThe of the property
+
The name of the property
+
An with all the values for the property
@@ -163,11 +165,10 @@
Factory for the
-
+
Creates an
- The path to the xml file
A newly created instance of the implementation for
@@ -175,12 +176,10 @@
Factory for the
-
+
Creates an
- The path to the xml file
- The root element name of the xml file
A newly created instance of the implementation for
@@ -198,152 +197,142 @@
The attribute name of the value attribute
-
+
A that handles its data in an xml file
The path to the xml file
- The root element name of the xml file
The factory
The factory
The factory
-
+
Initialize the
If true an existing value is overwritten, if false an additional value is added
- A to cancel the async operation
Returns true if successful, false if not
-
+
Set the value for the given property
The that implements the propertyThe of the property
+
The name of the property
The value to set
+
A to await
-
+
Remove the value for the given property
The of the propertyThe of the property
+
The name of the property
The value to set
+
A to await
-
+
Get the value for the given property, if multiple values are set the first is returned
The that implements the propertyThe of the property
+
The name of the property
+
The value for the given property
-
+
Get all the values that are set for the given property
The that implements the propertyThe of the property
+
The name of the property
+
An with all the values for the property
-
-
- Dispose used resources asynchronously
-
- A to await
-
A that reads from a xml file
-
-
- A that reads from a xml file
-
- The path to the xml file
-
-
-
- Initialize the
-
- A to cancel the async operation
- Returns true if successful, false if not
- No root element found
-
-
+
Read the data of a property
The The of the property
+
The name of the property
+
The data of the given property, null if no data foundInvalid found for the read object
-
-
- Dispose used resources asynchronously
-
- A to await
-
A that writes to a xml file
-
-
- A that writes to an xml file
-
- The path to the xml file
- The root element name of the xml file
-
-
+
Initialize the
+
+
A to cancel the async operation
Returns true if successful, false if notNo root element found
-
+
Write the data of a property
- The that implements the property
+ The The of the property
+
The name of the property
The value of the property
If true an existing value is overwritten, if false an additional value is added
+
+ A to await
+
+
+
+ Write the data of a property
+
+ The that implements the property
+
+ The name of the property
+ The value of the property
+
+ If true an existing value is overwritten, if false an additional value is added
+
A to await
+ No root element is set
-
+
Remove the value for the given property
The of the propertyThe of the property
+
The name of the property
The value to set
+
A to await
-
-
-
- Dispose used resources asynchronously
-
- A to await
+ No root element is set
@@ -361,12 +350,52 @@
The of the passed interface
+
+
+ that the passed table type doesn't implement "/>
+
+
+
+
+ that the passed table type doesn't implement "/>
+
+ The table type
+
+
+
+ that the table for the given is missing
+
+
+
+
+ that the table for the given is missing
+
+
+
+
+ Factory for the
+
+
+
+
+ Factory for the
+
+ Factory for the
+
+ Factory for the
+
+
+
+ Creates an
+
+ A newly created instance of the implementation for
+
Factory for the
-
+
Creates an
@@ -389,7 +418,7 @@
Factory for the
-
+
Creates an
@@ -411,15 +440,14 @@
Internal file handler
-
+
- Internal file handler
+ The file extension for all GBase tables
- Factory for the
-
+
- The of this
+ Internal file handler
@@ -430,44 +458,6 @@
A to cancel the asynchronous operation
True if successful, false if not
-
-
- Set the value for the given property
-
- The of the property
- The of the property
- The name of the property
- The value to set
- A to await
-
-
-
- Remove the value for the given property
-
- The of the property
- The of the property
- The name of the property
- The value to set
- A to await
-
-
-
- Get the value for the given property, if multiple values are set the first is returned
-
- The of the property
- The of the property
- The name of the property
- The value for the given property
-
-
-
- Get all the values that are set for the given property
-
- The of the property
- The of the property
- The name of the property
- An with all the values for the property
-
Dispose used resources asynchronously
@@ -479,11 +469,6 @@
The base class of the GBase database
-
-
- The file extension for all GBase tables
-
-
The base class of the GBase database
@@ -540,7 +525,7 @@
A column of a
-
+
A column of a
@@ -551,91 +536,96 @@
A to await
-
+
+
+ GBase object that supplies inheriting classes with methods to get data from a
+
+
+
+
+ GBase object that allows conversion from
+
+ No table for is existing
+
+
+
+ Initialize this from a given
+
+ The given
+
+
A table
-
+
A table
+
+ The
+
-
+
The of the class that this represents
-
+
The name of this
-
+
The s of this
-
+
The entries of this
-
+
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
-
+
Add a given to this
The given True if successful, false if not
-
+
Remove a given from this
The given True if successful, false if not
-
+
Add an entry that implements to this
The entry implementing
+
True if successful, false if not
-
+
Remove an entry that implements from this
The entry implementing True if successful, false if not
-
-
- Modify the property of a given entry with the given value
-
- The entry
- The name of the property
- The new value to set
- True if successful, false if not
-
-
-
- A entry changed
-
- The entry (sender)
- The
-
-
+
The method
@@ -707,13 +697,15 @@
The value to set
A to await
-
+
Try to get values from the cache for the given property
The that implements the propertyThe of the property
+
The name of the property
+
An with all the values for the property
@@ -756,50 +748,57 @@
Interface for data handlers to implement
-
+
Initialize the
If true an existing value is overwritten, if false an additional value is added
- A to cancel the async operation
Returns true if successful, false if not
-
+
Set the value for the given property
The of the propertyThe of the property
+
The name of the property
The value to set
+
A to await
-
+
Remove the value for the given property
The of the propertyThe of the property
+
The name of the property
The value to set
+
A to await
-
+
Get the value for the given property, if multiple values are set the first is returned
The of the propertyThe of the property
+
The name of the property
+
The value for the given property
-
+
Get all the values that are set for the given property
The of the propertyThe of the property
+
The name of the property
+
An with all the values for the property
@@ -807,20 +806,15 @@
Interface for data readers to implement
-
-
- Initialize the
-
- A to cancel the async operation
- Returns true if successful, false if not
-
-
+
Read the data of a property
The The of the property
+
The name of the property
+
The data of the given property, null if no data found
@@ -828,32 +822,51 @@
Interface for data writers to implement
-
+
Initialize the
+
+
A to cancel the async operation
Returns true if successful, false if not
-
+
Write the data of a property
The The of the property
+
The name of the property
The value of the property
If true an existing value is overwritten, if false an additional value is added
+
A to await
-
+
+
+ Write the data of a property
+
+ The
+
+ The name of the property
+ The value of the property
+
+ If true an existing value is overwritten, if false an additional value is added
+
+ A to await
+
+
Remove the value for the given property
The of the propertyThe of the property
+
The name of the property
The value to set
+
A to await
@@ -899,44 +912,6 @@
A to cancel the asynchronous operation
True if successful, false if not
-
-
- Set the value for the given property
-
- The of the property
- The of the property
- The name of the property
- The value to set
- A to await
-
-
-
- Remove the value for the given property
-
- The of the property
- The of the property
- The name of the property
- The value to set
- A to await
-
-
-
- Get the value for the given property, if multiple values are set the first is returned
-
- The of the property
- The of the property
- The name of the property
- The value for the given property
-
-
-
- Get all the values that are set for the given property
-
- The of the property
- The of the property
- The name of the property
- An with all the values for the property
-
The base class of the GBase database
@@ -985,6 +960,26 @@
A column of a
+
+
+ The entries of this
+
+
+
+
+ Add an entry that implements to this
+
+ The entry implementing
+
+ True if successful, false if not
+
+
+
+ Remove an entry that implements from this
+
+ The entry implementing
+ True if successful, false if not
+
A table
@@ -995,7 +990,7 @@
The of the class that this represents
-
+
The name of this
@@ -1005,19 +1000,15 @@
The s of this
-
-
- The entries of this
-
-
Initialize this
The of the class that this represents
- The name of this
- /// The path to the database files
+ The path to the database files
+
A to cancel the asynchronous operation
+ ///
True if successful, false if not
@@ -1034,20 +1025,6 @@
The given True if successful, false if not
-
-
- Add an entry that implements to this
-
- The entry implementing
- True if successful, false if not
-
-
-
- Remove an entry that implements from this
-
- The entry implementing
- True if successful, false if not
-
Settings of a instance
diff --git a/GBase/GBaseColumn.cs b/GBase/GBaseColumn.cs
index ee3f45b..25d2da2 100644
--- a/GBase/GBaseColumn.cs
+++ b/GBase/GBaseColumn.cs
@@ -16,10 +16,12 @@ namespace GBase
///
/// A column of a
///
- public GBaseColumn()
+ public GBaseColumn(string name)
{
-
+ Name = name;
}
+
+ public string Name { get; }
///
/// The method
diff --git a/GBase/GBaseObject.cs b/GBase/GBaseObject.cs
new file mode 100644
index 0000000..2711bed
--- /dev/null
+++ b/GBase/GBaseObject.cs
@@ -0,0 +1,47 @@
+// Author: Gockner, Simon
+// Created: 2020-09-18
+// Copyright(c) 2020 SimonG. All Rights Reserved.
+
+using System.Collections.Generic;
+using System.Threading;
+using System.Threading.Tasks;
+using GBase.Api;
+using GBase.Exceptions;
+using GBase.Interfaces;
+
+namespace GBase
+{
+ ///
+ /// GBase object that supplies inheriting classes with methods to get data from a
+ ///
+ public abstract class GBaseObject : IGBaseObject
+ {
+ private readonly IGBaseTable _gBaseTable;
+
+ ///
+ /// GBase object that allows conversion from
+ ///
+ /// No table for is existing
+ protected GBaseObject(IGBase gBase)
+ {
+ _gBaseTable = gBase.GetTable();
+ if (_gBaseTable == null)
+ throw new MissingTableException();
+ }
+
+ protected async Task SetValue(T @this, string propertyName, TProperty value, CancellationToken cancellationToken) =>
+ await _gBaseTable.SetValue(@this, propertyName, value, cancellationToken);
+
+ protected async Task GetValue(T @this, string propertyName, CancellationToken cancellationToken) =>
+ await _gBaseTable.GetValue(@this, propertyName, cancellationToken);
+
+ protected async Task> GetValues(T @this, string propertyName, CancellationToken cancellationToken) =>
+ await _gBaseTable.GetValues(@this, propertyName, cancellationToken);
+
+ ///
+ /// Initialize this from a given
+ ///
+ /// The given
+ public abstract void InitializeFromString(string @string);
+ }
+}
\ No newline at end of file
diff --git a/GBase/GBaseTable.cs b/GBase/GBaseTable.cs
index 887f8d8..644e0fe 100644
--- a/GBase/GBaseTable.cs
+++ b/GBase/GBaseTable.cs
@@ -4,7 +4,6 @@
using System;
using System.Collections.Generic;
-using System.IO;
using System.Linq;
using System.Reflection;
using System.Threading;
@@ -14,6 +13,8 @@ using GBase.Attributes;
using GBase.Factories;
using GBase.FileHandling.Factories;
using GBase.Interfaces;
+using GBase.Interfaces.DataHandling;
+using GBase.Interfaces.DataHandling.Pool;
using GBase.Interfaces.FileHandling;
namespace GBase
@@ -21,21 +22,26 @@ namespace GBase
///
/// A table
///
- public class GBaseTable : IGBaseTable
+ public class GBaseTable : IGBaseTable
{
private readonly IFileHandler _fileHandler;
+ private readonly IDataHandlerPool _dataHandlerPool;
private readonly IGBaseColumnFactory _gBaseColumnFactory;
///
/// A table
///
- public GBaseTable(IFileHandlerFactory fileHandlerFactory, IGBaseColumnFactory gBaseColumnFactory)
+ ///
+ /// The
+ ///
+ public GBaseTable(IFileHandlerFactory fileHandlerFactory, IDataHandlerPool dataHandlerPool, IGBaseColumnFactory gBaseColumnFactory)
{
_fileHandler = fileHandlerFactory.Create();
+ _dataHandlerPool = dataHandlerPool;
_gBaseColumnFactory = gBaseColumnFactory;
Columns = new List();
- Entries = new List
/// The given
/// True if successful, false if not
- public bool RemoveColumn(IGBaseColumn column)
+ public bool RemoveColumn(IGBaseColumn column) //TODO: if a column is removed, it has to be removed from every entry file as well
{
if (!Columns.Contains(column))
return false;
@@ -122,11 +125,15 @@ namespace GBase
/// Add an entry that implements to this
///
/// The entry implementing
+ ///
/// True if successful, false if not
- public bool AddEntry(INotifyGBaseEntryChanged entry) //TODO: Write to file
+ public async Task AddEntry(T entry, CancellationToken cancellationToken)
{
Entries.Add(entry);
- entry.GBaseEntryChanged += OnGBaseEntryChanged;
+
+ using IGBaseFile file = _fileHandler.CreateEntryFile(entry, this);
+ IDataHandler dataHandler = await _dataHandlerPool.RequestDataHandler(this, false, cancellationToken);
+ await dataHandler.AddEntry(entry, this, file.File, cancellationToken);
return true;
}
@@ -136,41 +143,35 @@ namespace GBase
///
/// The entry implementing
/// True if successful, false if not
- public bool RemoveEntry(INotifyGBaseEntryChanged entry) //TODO: remove from file
+ public async Task RemoveEntry(T entry)
{
if (!Entries.Contains(entry))
return false;
- entry.GBaseEntryChanged -= OnGBaseEntryChanged;
+ await _fileHandler.DeleteEntryFile(entry);
return Entries.Remove(entry);
}
- ///
- /// Modify the property of a given entry with the given value
- ///
- /// The entry
- /// The name of the property
- /// The new value to set
- /// True if successful, false if not
- private bool ModifyEntry(object entry, string propertyName, object value) //TODO: Write to file
+ public async Task SetValue(T entry, string propertyName, TProperty value, CancellationToken cancellationToken)
{
- //don't need to change value of property in `Entries` list, the instance is saved there, any property change is already changed there as well
- return true;
+ using IGBaseFile file = await _fileHandler.RequestEntryFile(entry);
+ IDataHandler dataHandler = await _dataHandlerPool.RequestDataHandler(this, false, CancellationToken.None);
+ await dataHandler.SetValue(file.File, propertyName, value, cancellationToken);
}
- ///
- /// A entry changed
- ///
- /// The entry (sender)
- /// The
- private void OnGBaseEntryChanged(object entry, GBaseEntryChangedEventArgs args)
+ public async Task GetValue(T entry, string propertyName, CancellationToken cancellationToken)
{
- //TODO: Might change, depending on #23
- bool success = ModifyEntry(entry, args.ColumnName, args.Value);
-
- if (!success)
- throw new Exception("Failed to handle EntryChanged"); //TODO: Decide what to do here
+ using IGBaseFile file = await _fileHandler.RequestEntryFile(entry);
+ IDataHandler dataHandler = await _dataHandlerPool.RequestDataHandler(this, false, CancellationToken.None);
+ return await dataHandler.GetValue(file.File, propertyName, cancellationToken);
+ }
+
+ public async Task> GetValues(T entry, string propertyName, CancellationToken cancellationToken)
+ {
+ using IGBaseFile file = await _fileHandler.RequestEntryFile(entry);
+ IDataHandler dataHandler = await _dataHandlerPool.RequestDataHandler(this, false, CancellationToken.None);
+ return await dataHandler.GetValues(file.File, propertyName, cancellationToken);
}
///
@@ -180,6 +181,7 @@ namespace GBase
public async ValueTask DisposeAsync()
{
await _fileHandler.DisposeAsync();
+ await _dataHandlerPool.DisposeAsync();
foreach (var column in Columns)
{
@@ -188,9 +190,9 @@ namespace GBase
Columns.Clear();
- foreach (var entry in Entries.OfType().ToList())
+ foreach (var entry in Entries.ToList())
{
- RemoveEntry(entry);
+ await RemoveEntry(entry);
}
Entries.Clear();
diff --git a/GBase/Installers/DataHandlingInstaller.cs b/GBase/Installers/DataHandlingInstaller.cs
index cd523e5..134ccee 100644
--- a/GBase/Installers/DataHandlingInstaller.cs
+++ b/GBase/Installers/DataHandlingInstaller.cs
@@ -7,8 +7,13 @@ using GBase.DataHandling;
using GBase.DataHandling.Cache;
using GBase.DataHandling.Cache.Factories;
using GBase.DataHandling.Factories;
+using GBase.DataHandling.Factories.Pool;
+using GBase.DataHandling.Pool;
+using GBase.Interfaces.DataHandling;
+using GBase.Interfaces.DataHandling.Pool;
using GBase.Interfaces.DataHandling.Xml;
using GBase.Interfaces.DataHandling.Xml.Cache;
+using LightweightIocContainer;
using LightweightIocContainer.Interfaces;
using LightweightIocContainer.Interfaces.Installers;
@@ -22,16 +27,22 @@ namespace GBase.Installers
///
public void Install(IIocContainer container)
{
- container.Register();
- container.Register();
- container.Register();
+ container.Register();
+ container.Register();
+ container.Register();
//cache
container.Register();
container.Register();
container.Register();
+ //pool
+ container.Register(Lifestyle.Singleton).WithParameters(10);
+ container.Register();
+ container.RegisterFactory();
+
//factories
+ container.RegisterFactory();
container.RegisterFactory();
container.RegisterFactory();
container.RegisterFactory();
diff --git a/GBase/Installers/GBaseInstaller.cs b/GBase/Installers/GBaseInstaller.cs
index 9ace16d..902e7cd 100644
--- a/GBase/Installers/GBaseInstaller.cs
+++ b/GBase/Installers/GBaseInstaller.cs
@@ -19,12 +19,11 @@ namespace GBase.Installers
public void Install(IIocContainer container)
{
container.Register();
- container.Register();
container.Register();
//factories
container.RegisterFactory();
- container.RegisterFactory();
+ container.Register(); //TODO: Once LightweightIocContainer can handle open generic registrations this can be changed back again
container.RegisterFactory();
}
}
diff --git a/GBase/Interfaces/DataHandling/Cache/IDataHandlerCache.cs b/GBase/Interfaces/DataHandling/Cache/IDataHandlerCache.cs
index e02a452..9bcba60 100644
--- a/GBase/Interfaces/DataHandling/Cache/IDataHandlerCache.cs
+++ b/GBase/Interfaces/DataHandling/Cache/IDataHandlerCache.cs
@@ -4,6 +4,8 @@
using System;
using System.Collections.Generic;
+using System.IO;
+using System.Threading;
using System.Threading.Tasks;
namespace GBase.Interfaces.DataHandling.Cache
@@ -39,8 +41,10 @@ namespace GBase.Interfaces.DataHandling.Cache
///
/// The that implements the property
/// The of the property
+ ///
/// The name of the property
+ ///
/// An with all the values for the property
- Task> TryGetValues(string propertyName);
+ Task> TryGetValues(FileStream file, string propertyName, CancellationToken cancellationToken);
}
}
\ No newline at end of file
diff --git a/GBase/Interfaces/DataHandling/IDataHandler.cs b/GBase/Interfaces/DataHandling/IDataHandler.cs
index cc600be..afab835 100644
--- a/GBase/Interfaces/DataHandling/IDataHandler.cs
+++ b/GBase/Interfaces/DataHandling/IDataHandler.cs
@@ -4,6 +4,7 @@
using System;
using System.Collections.Generic;
+using System.IO;
using System.Threading;
using System.Threading.Tasks;
@@ -12,52 +13,63 @@ namespace GBase.Interfaces.DataHandling
///
/// Interface for data handlers to implement
///
- public interface IDataHandler : IAsyncDisposable
+ public interface IDataHandler
{
///
/// Initialize the
///
/// If true an existing value is overwritten, if false an additional value is added
- /// A to cancel the async operation
/// Returns true if successful, false if not
- Task Init(bool overwrite, CancellationToken cancellationToken);
+ bool Init(bool overwrite);
+
+ Task AddEntry(T entry, IGBaseTable table, FileStream entryFile, CancellationToken cancellationToken);
+
+ Task RemoveEntry(T entry);
///
/// Set the value for the given property
///
/// The of the property
/// The of the property
+ ///
/// The name of the property
/// The value to set
+ ///
/// A to await
- Task SetValue(string propertyName, TProperty value);
+ Task SetValue(FileStream entryFile, string propertyName, TProperty value, CancellationToken cancellationToken);
///
/// Remove the value for the given property
///
/// The of the property
/// The of the property
+ ///
/// The name of the property
/// The value to set
+ ///
/// A to await
- Task RemoveValue(string propertyName, TProperty value);
+ Task RemoveValue(FileStream entryFile, string propertyName, TProperty value, CancellationToken cancellationToken);
///
/// Get the value for the given property, if multiple values are set the first is returned
///
/// The of the property
/// The of the property
+ ///
/// The name of the property
+ ///
/// The value for the given property
- Task GetValue(string propertyName);
+ Task GetValue(FileStream file, string propertyName, CancellationToken cancellationToken);
///
/// Get all the values that are set for the given property
///
/// The of the property
/// The of the property
+ ///
/// The name of the property
+ ///
/// An with all the values for the property
- Task> GetValues(string propertyName);
+ Task> GetValues(FileStream file, string propertyName, CancellationToken cancellationToken);
}
}
\ No newline at end of file
diff --git a/GBase/Interfaces/DataHandling/IDataReader.cs b/GBase/Interfaces/DataHandling/IDataReader.cs
index e6d34da..cacdfb5 100644
--- a/GBase/Interfaces/DataHandling/IDataReader.cs
+++ b/GBase/Interfaces/DataHandling/IDataReader.cs
@@ -4,6 +4,7 @@
using System;
using System.Collections.Generic;
+using System.IO;
using System.Threading;
using System.Threading.Tasks;
@@ -12,22 +13,17 @@ namespace GBase.Interfaces.DataHandling
///
/// Interface for data readers to implement
///
- public interface IDataReader : IAsyncDisposable
+ public interface IDataReader
{
- ///
- /// Initialize the
- ///
- /// A to cancel the async operation
- /// Returns true if successful, false if not
- Task Init(CancellationToken cancellationToken);
-
///
/// Read the data of a property
///
/// The
/// The of the property
+ ///
/// The name of the property
+ ///
/// The data of the given property, null if no data found
- Task> Read(string propertyName);
+ Task> Read(FileStream file, string propertyName, CancellationToken cancellationToken);
}
}
\ No newline at end of file
diff --git a/GBase/Interfaces/DataHandling/IDataWriter.cs b/GBase/Interfaces/DataHandling/IDataWriter.cs
index c049b66..98ffef4 100644
--- a/GBase/Interfaces/DataHandling/IDataWriter.cs
+++ b/GBase/Interfaces/DataHandling/IDataWriter.cs
@@ -3,6 +3,7 @@
// Copyright(c) 2020 SimonG. All Rights Reserved.
using System;
+using System.IO;
using System.Threading;
using System.Threading.Tasks;
@@ -11,34 +12,53 @@ namespace GBase.Interfaces.DataHandling
///
/// Interface for data writers to implement
///
- public interface IDataWriter : IAsyncDisposable
+ public interface IDataWriter
{
///
/// Initialize the
///
+ ///
+ ///
/// A to cancel the async operation
/// Returns true if successful, false if not
- Task Init(CancellationToken cancellationToken);
+ Task InitFile(FileStream file, string rootElementName, CancellationToken cancellationToken);
///
/// Write the data of a property
///
/// The
/// The of the property
+ ///
/// The name of the property
/// The value of the property
/// If true an existing value is overwritten, if false an additional value is added
+ ///
/// A to await
- Task Write(string propertyName, string value, bool overwrite);
+ Task Write(FileStream file, string propertyName, string value, bool overwrite, CancellationToken cancellationToken);
+
+ ///
+ /// Write the data of a property
+ ///
+ /// The
+ ///
+ /// The name of the property
+ /// The value of the property
+ ///
+ /// If true an existing value is overwritten, if false an additional value is added
+ ///
+ /// A to await
+ Task Write(FileStream file, string propertyName, string value, Type propertyType, bool overwrite, CancellationToken cancellationToken);
///
/// Remove the value for the given property
///
/// The of the property
/// The of the property
+ ///
/// The name of the property
/// The value to set
+ ///
/// A to await
- Task Remove(string propertyName, string value);
+ Task Remove(FileStream file, string propertyName, string value, CancellationToken cancellationToken);
}
}
\ No newline at end of file
diff --git a/GBase/Interfaces/DataHandling/Pool/IDataHandlerPool.cs b/GBase/Interfaces/DataHandling/Pool/IDataHandlerPool.cs
new file mode 100644
index 0000000..ccece22
--- /dev/null
+++ b/GBase/Interfaces/DataHandling/Pool/IDataHandlerPool.cs
@@ -0,0 +1,15 @@
+// Author: Simon Gockner
+// Created: 2020-09-18
+// Copyright(c) 2020 SimonG. All Rights Reserved.
+
+using System;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace GBase.Interfaces.DataHandling.Pool
+{
+ public interface IDataHandlerPool : IAsyncDisposable
+ {
+ Task RequestDataHandler(object requester, bool overwrite, CancellationToken cancellationToken);
+ }
+}
\ No newline at end of file
diff --git a/GBase/Interfaces/DataHandling/Pool/IPoolItem.cs b/GBase/Interfaces/DataHandling/Pool/IPoolItem.cs
new file mode 100644
index 0000000..8cdb3d9
--- /dev/null
+++ b/GBase/Interfaces/DataHandling/Pool/IPoolItem.cs
@@ -0,0 +1,12 @@
+// Author: Simon Gockner
+// Created: 2020-09-19
+// Copyright(c) 2020 SimonG. All Rights Reserved.
+
+namespace GBase.Interfaces.DataHandling.Pool
+{
+ public interface IPoolItem
+ {
+ T Item { get; }
+ bool InUse { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/GBase/Interfaces/DataHandling/Pool/IPoolRequest.cs b/GBase/Interfaces/DataHandling/Pool/IPoolRequest.cs
new file mode 100644
index 0000000..6e36e93
--- /dev/null
+++ b/GBase/Interfaces/DataHandling/Pool/IPoolRequest.cs
@@ -0,0 +1,14 @@
+// Author: Simon Gockner
+// Created: 2020-09-19
+// Copyright(c) 2020 SimonG. All Rights Reserved.
+
+using System;
+using System.Threading.Tasks;
+
+namespace GBase.Interfaces.DataHandling.Pool
+{
+ public interface IPoolRequest
+ {
+ object Requester { get; }
+ }
+}
\ No newline at end of file
diff --git a/GBase/Interfaces/FileHandling/IFileHandler.cs b/GBase/Interfaces/FileHandling/IFileHandler.cs
index 9e33882..0e9ca47 100644
--- a/GBase/Interfaces/FileHandling/IFileHandler.cs
+++ b/GBase/Interfaces/FileHandling/IFileHandler.cs
@@ -3,7 +3,6 @@
// Copyright(c) 2020 SimonG. All Rights Reserved.
using System;
-using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
@@ -22,42 +21,10 @@ namespace GBase.Interfaces.FileHandling
/// True if successful, false if not
Task Init(string path, CancellationToken cancellationToken);
- ///
- /// Set the value for the given property
- ///
- /// The of the property
- /// The of the property
- /// The name of the property
- /// The value to set
- /// A to await
- Task SetValue(string propertyName, TProperty value);
+ IGBaseFile CreateEntryFile(T entry, IGBaseTable table);
- ///
- /// Remove the value for the given property
- ///
- /// The of the property
- /// The of the property
- /// The name of the property
- /// The value to set
- /// A to await
- Task RemoveValue(string propertyName, TProperty value);
+ Task DeleteEntryFile(T entry);
- ///
- /// Get the value for the given property, if multiple values are set the first is returned
- ///
- /// The of the property
- /// The of the property
- /// The name of the property
- /// The value for the given property
- Task GetValue(string propertyName);
-
- ///
- /// Get all the values that are set for the given property
- ///
- /// The of the property
- /// The of the property
- /// The name of the property
- /// An with all the values for the property
- Task> GetValues(string propertyName);
+ Task RequestEntryFile(T entry);
}
}
\ No newline at end of file
diff --git a/GBase/Interfaces/FileHandling/IGBaseFile.cs b/GBase/Interfaces/FileHandling/IGBaseFile.cs
new file mode 100644
index 0000000..9904130
--- /dev/null
+++ b/GBase/Interfaces/FileHandling/IGBaseFile.cs
@@ -0,0 +1,19 @@
+// Author: Gockner, Simon
+// Created: 2020-11-10
+// Copyright(c) 2020 SimonG. All Rights Reserved.
+
+using System;
+using System.IO;
+
+namespace GBase.Interfaces.FileHandling
+{
+ public interface IGBaseFile : IDisposable
+ {
+ object Entry { get; }
+ FileStream File { get; }
+ string FilePath { get; }
+ bool InUse { get; }
+
+ IGBaseFile UseFile();
+ }
+}
\ No newline at end of file
diff --git a/GBase/Interfaces/IGBase.cs b/GBase/Interfaces/IGBase.cs
index 614211a..74b571c 100644
--- a/GBase/Interfaces/IGBase.cs
+++ b/GBase/Interfaces/IGBase.cs
@@ -48,11 +48,19 @@ namespace GBase.Interfaces
/// True if successful, false if not
bool AddTable(IGBaseTable table);
+ IGBaseTable GetTable();
+
///
/// Removes a given from this
///
/// The given
/// True if successful, false if not
bool RemoveTable(IGBaseTable table);
+
+ Task AddEntry(T entry, CancellationToken cancellationToken);
+
+ Task SetValue(T entry, string propertyName, TProperty value, CancellationToken cancellationToken);
+ Task GetValue(T entry, string propertyName, CancellationToken cancellationToken);
+ Task> GetValues(T entry, string propertyName, CancellationToken cancellationToken);
}
}
\ No newline at end of file
diff --git a/GBase/Interfaces/IGBaseColumn.cs b/GBase/Interfaces/IGBaseColumn.cs
index d78a691..59cd728 100644
--- a/GBase/Interfaces/IGBaseColumn.cs
+++ b/GBase/Interfaces/IGBaseColumn.cs
@@ -11,6 +11,6 @@ namespace GBase.Interfaces
///
public interface IGBaseColumn : IAsyncDisposable //TODO: Make column generic (generic type is type of the value of the column?)?
{
-
+ string Name { get; }
}
}
\ No newline at end of file
diff --git a/GBase/Interfaces/IGBaseTable.cs b/GBase/Interfaces/IGBaseTable.cs
index 613c0af..277c1c5 100644
--- a/GBase/Interfaces/IGBaseTable.cs
+++ b/GBase/Interfaces/IGBaseTable.cs
@@ -10,6 +10,38 @@ using GBase.Api;
namespace GBase.Interfaces
{
+ public interface IGBaseTable : IGBaseTable
+ {
+ ///
+ /// The entries of this
+ ///
+ List Entries { get; }
+
+ ///
+ /// Add an entry that implements to this
+ ///
+ /// The entry implementing
+ ///
+ /// True if successful, false if not
+ Task AddEntry(T entry, CancellationToken cancellationToken);
+
+
+ //T GetEntry(T entry); //TODO: This doesn't make sense... (passing instance of T to get the same instance back...)
+
+ ///
+ /// Remove an entry that implements from this
+ ///
+ /// The entry implementing
+ /// True if successful, false if not
+ Task RemoveEntry(T entry);
+
+ Task SetValue(T entry, string propertyName, TProperty value, CancellationToken cancellationToken);
+
+ Task GetValue(T entry, string propertyName, CancellationToken cancellationToken);
+
+ Task> GetValues(T entry, string propertyName, CancellationToken cancellationToken);
+ }
+
///
/// A table
///
@@ -23,27 +55,23 @@ namespace GBase.Interfaces
///
/// The name of this
///
- string Name { get; }
+ string FolderName { get; }
///
/// The s of this
///
List Columns { get; }
- ///
- /// The entries of this
- ///
- List Entries { get; }
-
///
/// Initialize this
///
/// The of the class that this represents
- /// The name of this
- /// /// The path to the database files
+ /// The path to the database files
+ ///
/// A to cancel the asynchronous operation
+ /// ///
/// True if successful, false if not
- Task Init(Type type, string name, string databasePath, CancellationToken cancellationToken);
+ Task Init(Type type, string databasePath, string folderName, CancellationToken cancellationToken);
///
/// Add a given to this
@@ -58,19 +86,5 @@ namespace GBase.Interfaces
/// The given
/// True if successful, false if not
bool RemoveColumn(IGBaseColumn column);
-
- ///
- /// Add an entry that implements to this
- ///
- /// The entry implementing
- /// True if successful, false if not
- bool AddEntry(INotifyGBaseEntryChanged entry);
-
- ///
- /// Remove an entry that implements from this
- ///
- /// The entry implementing
- /// True if successful, false if not
- bool RemoveEntry(INotifyGBaseEntryChanged entry);
}
}
\ No newline at end of file
diff --git a/GBaseStructure.md b/GBaseStructure.md
new file mode 100644
index 0000000..14e8c1b
--- /dev/null
+++ b/GBaseStructure.md
@@ -0,0 +1,41 @@
+# GBase Structure
+
+```md
+- GBase
+ |
+ +-GBaseTable
+ |
+ |
+ +-GBaseTable
+ |
+ +-GBaseColumn--GBaseColumn--GBaseColumn
+ +-GBaseEntry
+ +-GBaseEntry
+```
+
+## Terminology
+
+| GBase Terminology | C# equivalent |
+|-------------------|---------------|
+| GBaseTable | Type |
+| GBaseColumn | Property |
+| GBaseEntry | Instance |
+
+## File Structure
+
+```c#
+public class Model
+{
+ private readonly IGBase _gBase;
+
+ public
+}
+```
+
+## Process
+
+### StartUp
+
+### GetValue
+
+### SetValue
diff --git a/Test.GBase/DataHandling/XmlDataHandlerLocalIntegrationTest.cs b/Test.GBase/DataHandling/XmlDataHandlerLocalIntegrationTest.cs
index 72f4459..db09cfc 100644
--- a/Test.GBase/DataHandling/XmlDataHandlerLocalIntegrationTest.cs
+++ b/Test.GBase/DataHandling/XmlDataHandlerLocalIntegrationTest.cs
@@ -3,6 +3,7 @@
// Copyright(c) 2020 SimonG. All Rights Reserved.
using System;
+using System.IO;
using System.Threading;
using System.Threading.Tasks;
using GBase.DataHandling;
@@ -27,12 +28,12 @@ namespace Test.GBase.DataHandling
Assert.Pass(); //Remove this assert.pass() if you want to run this test locally
Mock dataWriterFactoryMock = new Mock();
- dataWriterFactoryMock.Setup(w => w.Create(It.IsAny(), It.IsAny()))
- .Returns((string path, string rootElementName) => new XmlDataWriter(path, rootElementName));
+ dataWriterFactoryMock.Setup(w => w.Create())
+ .Returns(new XmlDataWriter());
Mock dataReaderFactoryMock = new Mock();
- dataReaderFactoryMock.Setup(r => r.Create(It.IsAny()))
- .Returns((string path) => new XmlDataReader(path));
+ dataReaderFactoryMock.Setup(r => r.Create())
+ .Returns(new XmlDataReader());
Mock dataHandlerCachePropertyEntryFactoryMock = new Mock();
dataHandlerCachePropertyEntryFactoryMock.Setup(p => p.Create(It.IsAny(), It.IsAny()))
@@ -48,21 +49,22 @@ namespace Test.GBase.DataHandling
.Returns((IXmlDataReader xmlDataReader) =>
new XmlDataHandlerCache(xmlDataReader, dataHandlerCacheEntryFactoryMock.Object, dataHandlerCachePropertyEntryFactoryMock.Object));
- IXmlDataHandler xmlDataHandler = new XmlDataHandler("TestXml.xml", "Properties", dataReaderFactoryMock.Object, dataWriterFactoryMock.Object,
- dataHandlerCacheFactoryMock.Object);
+ IXmlDataHandler xmlDataHandler = new XmlDataHandler(dataReaderFactoryMock.Object, dataWriterFactoryMock.Object, dataHandlerCacheFactoryMock.Object);
- await xmlDataHandler.Init(false, new CancellationToken());
- //
+ xmlDataHandler.Init(false);
+
+ FileStream file = null; //FixMe: init this correctly if you want to run this test
+
//await xmlDataHandler.SetValue(nameof(TestProperty), TestProperty);
//await xmlDataHandler.SetValue(nameof(TestProperty), "empty");
- await xmlDataHandler.SetValue(nameof(TestProperty), "test");
+ await xmlDataHandler.SetValue(file, nameof(TestProperty), "test", new CancellationToken());
//await xmlDataHandler.SetValue(nameof(TestProperty), "OverwrittenString");
//
- await xmlDataHandler.SetValue(nameof(TestInt), 1);
+ await xmlDataHandler.SetValue(file, nameof(TestInt), 1, new CancellationToken());
//await xmlDataHandler.SetValue(nameof(TestInt), 2);
//await xmlDataHandler.SetValue(nameof(TestInt), 3);
- TestProperty = await xmlDataHandler.GetValue(nameof(TestProperty));
- TestInt = await xmlDataHandler.GetValue(nameof(TestInt));
+ TestProperty = await xmlDataHandler.GetValue(file, nameof(TestProperty), new CancellationToken());
+ TestInt = await xmlDataHandler.GetValue(file, nameof(TestInt), new CancellationToken());
}
}
}
\ No newline at end of file
diff --git a/Test.GBase/DataHandling/XmlDataHandlerTest.cs b/Test.GBase/DataHandling/XmlDataHandlerTest.cs
index 699aede..475d5b8 100644
--- a/Test.GBase/DataHandling/XmlDataHandlerTest.cs
+++ b/Test.GBase/DataHandling/XmlDataHandlerTest.cs
@@ -19,104 +19,45 @@ namespace Test.GBase.DataHandling
public class XmlDataHandlerTest
{
[Test]
- public async Task TestInit()
+ public void TestInit()
{
Mock xmlDataReaderMock = new Mock();
- xmlDataReaderMock.Setup(r => r.Init(It.IsAny())).ReturnsAsync(true);
-
Mock xmlDataReaderFactoryMock = new Mock();
- xmlDataReaderFactoryMock.Setup(r => r.Create(It.IsAny())).Returns(xmlDataReaderMock.Object);
+ xmlDataReaderFactoryMock.Setup(r => r.Create()).Returns(xmlDataReaderMock.Object);
Mock xmlDataWriterMock = new Mock();
- xmlDataWriterMock.Setup(w => w.Init(It.IsAny())).ReturnsAsync(true);
-
- Mock xmlDataWriterFactoryMock = new Mock();
- xmlDataWriterFactoryMock.Setup(w => w.Create(It.IsAny(), It.IsAny())).Returns(xmlDataWriterMock.Object);
-
- Mock xmlDataHandlerCacheMock = new Mock();
- Mock xmlDataHandlerCacheFactoryMock = new Mock();
- xmlDataHandlerCacheFactoryMock.Setup(c => c.Create(It.IsAny