diff --git a/MCTG/ConsoleApp/ConsoleApp.csproj b/MCTG/ConsoleApp/ConsoleApp.csproj
index 7e8ef62..dbc5e22 100644
--- a/MCTG/ConsoleApp/ConsoleApp.csproj
+++ b/MCTG/ConsoleApp/ConsoleApp.csproj
@@ -8,6 +8,7 @@
+
diff --git a/MCTG/ConsoleApp/Menu/MainMenu.cs b/MCTG/ConsoleApp/Menu/MainMenu.cs
index f26bdf0..8dcbb8b 100644
--- a/MCTG/ConsoleApp/Menu/MainMenu.cs
+++ b/MCTG/ConsoleApp/Menu/MainMenu.cs
@@ -1,4 +1,5 @@
using Model;
+using DataPersistence;
using System;
using System.Collections.Generic;
using System.Linq;
@@ -15,7 +16,7 @@ namespace ConsoleApp.Menu
public MainMenu(DataManager dataMgr)
: base("Main menu",
new Selector(
- new SearcherRecipe(dataMgr.AllRecipes), "Recipe search"),
+ new SearcherRecipe(new RecipeCollection("search", dataMgr.Data[nameof(Recipe)].Cast().ToArray())), "Recipe search"),
new Selector(
new ConnectionMenu(), "Connection"))
{ }
diff --git a/MCTG/ConsoleApp/MenuManager.cs b/MCTG/ConsoleApp/MenuManager.cs
index bbbf6d1..20cf567 100644
--- a/MCTG/ConsoleApp/MenuManager.cs
+++ b/MCTG/ConsoleApp/MenuManager.cs
@@ -1,5 +1,6 @@
using ConsoleApp.Menu;
using Model;
+using DataPersistence;
using System;
using System.Collections.Generic;
using System.Linq;
diff --git a/MCTG/ConsoleApp/Program.cs b/MCTG/ConsoleApp/Program.cs
index a60cdcd..65c6564 100644
--- a/MCTG/ConsoleApp/Program.cs
+++ b/MCTG/ConsoleApp/Program.cs
@@ -2,23 +2,34 @@
using ConsoleApp;
using ConsoleApp.Menu;
+using DataPersistence;
using Model;
-
+using System.Linq;
using System.Text;
Console.WriteLine("Hello, World!\n\n");
// TESTS:
+DataManager dataMgr = new DataManager(new Stubs());
+//DataManager dataMgr = new DataManager(new DataContractXML(xmlFolderPath: "../../../../DataPersistence/data"));
+//DataManager dataMgr = new DataManager(new DataContractJSON());
+
+//dataMgr.Serializer = new DataContractXML(xmlFolderPath: "../../../../DataPersistence/data");
+dataMgr.Serializer = new DataContractJSON();
-List recipeCollections = Stub.LoadRecipeCollection();
-RecipeCollection? allRecipe = recipeCollections.Find(x => x.Description.Equals("All"));
-if (allRecipe == null)
- throw new ArgumentException("Load AllRecipe in stub: can't find 'All'.");
+// /!\ here is an absolute path I put for testing purpose. It will only work on my computer so don't forget to change it whene you test.
+//dataMgr.Export(rc[2], "C:\\Users\\alex6\\Downloads\\recipe2.json");
+//dataMgr.Import("C:\\Users\\alex6\\Downloads\\recipe2.json");
-DataManager dataMgr = new DataManager(allRecipe);
+RecipeCollection rc = new RecipeCollection("All recipes", dataMgr.Data[nameof(Recipe)].Cast().ToArray());
+
+dataMgr.Save();
MenuManager menuMgr = new MenuManager(dataMgr);
menuMgr.Loop();
+
+// press any key to quit
+//Console.ReadKey();
diff --git a/MCTG/ConsoleApp/Stubs/Stub.cs b/MCTG/ConsoleApp/Stubs/Stub.cs
deleted file mode 100644
index 689a013..0000000
--- a/MCTG/ConsoleApp/Stubs/Stub.cs
+++ /dev/null
@@ -1,99 +0,0 @@
-using Model;
-using System;
-using System.Collections.Concurrent;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace ConsoleApp
-{
- internal struct Stub
- {
- public static List LoadRecipes()
- {
- List stub = new List();
- stub.AddRange(new[]
- {
- new Recipe(),
- new Recipe(
- title: "Cookies"),
- new Recipe(
- title: "Cookies", id: 23),
- new Recipe(
- title: "Cookies au chocolat", id: null),
- new Recipe(
- title: "", id: null),
- new Recipe(
- title: "", id: 24),
- new Recipe(
- title: "Cookies", id: 24,
- preparationSteps: new[]{
- new PreparationStep(1)
- }),
- new Recipe(
- title: "Cookies", id: 26,
- preparationSteps: new[]{
- new PreparationStep(1),
- new PreparationStep(2, "Faire cuire.")
- }),
- new Recipe(
- title: "Gateau à la crème",
- preparationSteps: new[]{
- new PreparationStep(1, "Ajouter les oeufs."),
- new PreparationStep(2, "Ajouter la farine."),
- new PreparationStep(3, "Mélanger le tout."),
- new PreparationStep(4, "Faire cuire 1h10 au four traditionnel.")
- }),
- new Recipe(
- title: "Gateau au chocolat",
- preparationSteps: new[]{
- new PreparationStep(1, "Ajouter les oeufs."),
- new PreparationStep(2, "Ajouter la farine."),
- new PreparationStep(2, "Ajouter 100g de chocolat fondu."),
- new PreparationStep(3, "Mélanger le tout."),
- new PreparationStep(4, "Faire cuire 45h au four traditionnel.")
- }),
- new Recipe(
- title: "Gateau aux cerises",
- preparationSteps: new[]{
- new PreparationStep(1, "Ajouter les oeufs."),
- new PreparationStep(2, "Ajouter la farine."),
- new PreparationStep(2, "Ajouter des morceaux de fraises découpées en petits carré"),
- new PreparationStep(3, "Mélanger le tout."),
- new PreparationStep(4, "Faire cuire 30min au four traditionnel.")
- }),
- });
- return stub;
- }
-
- public static List LoadRecipeCollection()
- {
- List stub = new List();
- stub.AddRange(new[]
- {
- new RecipeCollection("All", LoadRecipes().ToArray()),
- new RecipeCollection("Starters", LoadRecipes().FindAll(x => x.Id.Equals(23)).ToArray()),
- new RecipeCollection("Dishies", LoadRecipes().FindAll(x => x.Id.Equals(24)).ToArray()),
- new RecipeCollection("Desserts", LoadRecipes().FindAll(x => x.Id.Equals(26)).ToArray()),
- });
- return stub;
- }
-
-
- public static List ConstrucList()
- {
- List Users = new List();
-
- User Roger = new User("Roger", "Rabbit", "carotte@mail.fr");
- User Dylan = new User("d", "r", "dr@mail.fr");
- User Val = new User("V", "entin", "Valentin@mail.fr");
-
- Users.Add(Roger);
- Users.Add(Dylan);
- Users.Add(Val);
-
- return Users;
- }
- }
-}
diff --git a/MCTG/DataPersistence/DataContractJSON.cs b/MCTG/DataPersistence/DataContractJSON.cs
new file mode 100644
index 0000000..382a4eb
--- /dev/null
+++ b/MCTG/DataPersistence/DataContractJSON.cs
@@ -0,0 +1,111 @@
+using Model;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.Serialization;
+using System.Runtime.Serialization.Json;
+using System.Text;
+using System.Threading.Tasks;
+using System.Xml;
+using System.Xml.Linq;
+
+namespace DataPersistence
+{
+ ///
+ /// Define a serializer to manage JSON files.
+ ///
+ public class DataContractJSON : IDataManager
+ {
+ #region Attributes
+ private string _jsonFolderPath;
+ private DataContractJsonSerializerSettings _dataContractJsonSerializerSettings;
+ #endregion
+
+ #region Constructors
+ ///
+ /// Constructor of the DataContractJSON serializer.
+ ///
+ /// Give the default path where to load and save the data (by default is the current execution dir).
+ /// Give another set of DataContractJson serializer setting to write file
+ public DataContractJSON(string jsonFolderPath = "",
+ DataContractJsonSerializerSettings? dataContractJsonSerializerSettings = null)
+ {
+ _jsonFolderPath = jsonFolderPath;
+ if (dataContractJsonSerializerSettings is null)
+ _dataContractJsonSerializerSettings = new DataContractJsonSerializerSettings()
+ {
+ KnownTypes = new[] { typeof(Recipe) }
+ };
+ else
+ _dataContractJsonSerializerSettings = dataContractJsonSerializerSettings;
+ }
+ #endregion
+
+ #region IDataManager implementation
+ public void Export(T obj, string pathToExport)
+ where T : class
+ {
+ var jsonSerializer = new DataContractJsonSerializer(typeof(T), _dataContractJsonSerializerSettings);
+ using (FileStream stream = File.Create(Path.Combine(_jsonFolderPath, pathToExport)))
+ {
+ using (var jsonWriter = JsonReaderWriterFactory.CreateJsonWriter(
+ stream: stream,
+ encoding: System.Text.Encoding.UTF8,
+ ownsStream: false,
+ indent: true))
+ {
+ jsonSerializer.WriteObject(jsonWriter, obj);
+ }
+ }
+ }
+
+ public KeyValuePair Import(string pathToImport)
+ where T : class
+ {
+ T? obj;
+ var jsonSerializer = new DataContractJsonSerializer(typeof(T), _dataContractJsonSerializerSettings);
+ using (FileStream stream = File.OpenRead(Path.Combine(_jsonFolderPath, pathToImport)))
+ {
+ obj = jsonSerializer.ReadObject(stream) as T;
+ }
+
+ if (obj is null)
+ throw new ArgumentNullException("obj");
+
+ string typeName = typeof(T).Name;
+ return new KeyValuePair(typeName, obj);
+ }
+
+ public Dictionary> Load()
+ {
+ Dictionary>? elements = new Dictionary>();
+ var jsonSerializer = new DataContractJsonSerializer(typeof(Dictionary>), _dataContractJsonSerializerSettings);
+ using (FileStream stream = File.OpenRead(Path.Combine(_jsonFolderPath, "data.json")))
+ {
+ elements = jsonSerializer.ReadObject(stream) as Dictionary>;
+ }
+
+ if (elements is null)
+ throw new ArgumentNullException("elements");
+
+ return elements;
+ }
+
+ public void Save(Dictionary> elements)
+ {
+ var jsonSerializer = new DataContractJsonSerializer(typeof(Dictionary>), _dataContractJsonSerializerSettings);
+ using (FileStream stream = File.Create(Path.Combine(_jsonFolderPath, "data.json")))
+ {
+ using (var jsonWriter = JsonReaderWriterFactory.CreateJsonWriter(
+ stream: stream,
+ encoding: System.Text.Encoding.UTF8,
+ ownsStream: false,
+ indent: true))
+ {
+ jsonSerializer.WriteObject(jsonWriter, elements);
+ }
+ }
+ }
+ #endregion
+ }
+}
diff --git a/MCTG/DataPersistence/DataContractXML.cs b/MCTG/DataPersistence/DataContractXML.cs
new file mode 100644
index 0000000..3944c85
--- /dev/null
+++ b/MCTG/DataPersistence/DataContractXML.cs
@@ -0,0 +1,115 @@
+using Model;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.Serialization;
+using System.Text;
+using System.Threading.Tasks;
+using System.Xml;
+using System.Xml.Linq;
+
+namespace DataPersistence
+{
+ ///
+ /// Define a serializer to manage XML files.
+ ///
+ public class DataContractXML : IDataManager
+ {
+ #region Attributes
+ private string _xmlFolderPath;
+ private XmlWriterSettings _xmlWriterSettings;
+ private DataContractSerializerSettings _dataContractSerializerSettings;
+ #endregion
+
+ #region Constructors
+ ///
+ /// Constructor of a DataContractXML serializer.
+ ///
+ /// Give the default path where to load and save the data (by default is the current execution dir).
+ /// Give another set of XML setting to write file.
+ /// Give another set of DataContract serializer setting to write file
+ public DataContractXML(string xmlFolderPath = "",
+ XmlWriterSettings? xmlWriterSettings = null,
+ DataContractSerializerSettings? dataContractSerializerSettings = null)
+ {
+ _xmlFolderPath = xmlFolderPath;
+
+ if (xmlWriterSettings is null)
+ _xmlWriterSettings = new XmlWriterSettings() { Indent = true };
+ else
+ _xmlWriterSettings = xmlWriterSettings;
+
+ if (dataContractSerializerSettings is null)
+ _dataContractSerializerSettings = new DataContractSerializerSettings()
+ {
+ KnownTypes = new Type[] { typeof(Recipe) },
+ PreserveObjectReferences = true
+ };
+ else
+ _dataContractSerializerSettings = dataContractSerializerSettings;
+ }
+ #endregion
+
+ #region IDataManager implementation
+ public void Export(T obj, string pathToExport)
+ where T : class
+ {
+ bool restore = _dataContractSerializerSettings.PreserveObjectReferences;
+ _dataContractSerializerSettings.PreserveObjectReferences = false;
+ var serializer = new DataContractSerializer(typeof(T), _dataContractSerializerSettings);
+ using (TextWriter textWriter = File.CreateText(Path.Combine(_xmlFolderPath, pathToExport)))
+ {
+ using (XmlWriter xmlWriter = XmlWriter.Create(textWriter, _xmlWriterSettings))
+ {
+ serializer.WriteObject(xmlWriter, obj);
+ }
+ }
+ _dataContractSerializerSettings.PreserveObjectReferences = restore;
+ }
+
+ public KeyValuePair Import(string pathToImport)
+ where T : class
+ {
+ T? obj;
+ var serializer = new DataContractSerializer(typeof(T), _dataContractSerializerSettings);
+ using (Stream s = File.OpenRead(Path.Combine(_xmlFolderPath, pathToImport)))
+ {
+ obj = serializer.ReadObject(s) as T;
+ }
+
+ if (obj is null)
+ throw new ArgumentNullException("obj");
+
+ string typeName = typeof(T).Name;
+ return new KeyValuePair(typeName, obj);
+ }
+
+ public Dictionary> Load()
+ {
+ Dictionary>? elements;
+ var serializer = new DataContractSerializer(typeof(Dictionary>), _dataContractSerializerSettings);
+ using (Stream s = File.OpenRead(Path.Combine(_xmlFolderPath, "data.xml")))
+ {
+ elements = serializer.ReadObject(s) as Dictionary>;
+ }
+
+ if (elements is null)
+ throw new ArgumentNullException("elements");
+
+ return elements;
+ }
+
+ public void Save(Dictionary> elements)
+ {
+ var serializer = new DataContractSerializer(typeof(Dictionary>), _dataContractSerializerSettings);
+ using (TextWriter textWriter = File.CreateText(Path.Combine(_xmlFolderPath, "data.xml")))
+ {
+ using (XmlWriter xmlWriter = XmlWriter.Create(textWriter, _xmlWriterSettings))
+ {
+ serializer.WriteObject(xmlWriter, elements);
+ }
+ }
+ }
+ #endregion
+ }
+}
diff --git a/MCTG/DataPersistence/DataManager.cs b/MCTG/DataPersistence/DataManager.cs
new file mode 100644
index 0000000..a06d94d
--- /dev/null
+++ b/MCTG/DataPersistence/DataManager.cs
@@ -0,0 +1,81 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace DataPersistence
+{
+ ///
+ /// Define the manager of the data. This is where all the data are put, and where we call the loading and the saving of them.
+ ///
+ public class DataManager
+ {
+ #region Attributes & Properties
+ ///
+ /// The data manager injected that know how to serialize the data.
+ /// The setter is actually public for testing purpose. It will be private after.
+ /// See:
+ ///
+ public IDataManager Serializer { get; set; }
+
+ ///
+ /// The collection of all data. Each line of this dictionary has the type of the data as it key and the data for values.
+ ///
+ public Dictionary> Data { get; private set; }
+ #endregion
+
+ #region Constructors
+ ///
+ /// Constructor of the DataManager class. Take a IDataManager that will provide methods for the serialisation of the data.
+ ///
+ /// The data manager that know how to serialize a file.
+ public DataManager(IDataManager dataMgr)
+ {
+ Serializer = dataMgr;
+ Data = Serializer.Load();
+ }
+ #endregion
+
+ #region Methods
+ ///
+ /// Reload the data. Useful to update new data written in the save file.
+ /// See:
+ ///
+ public void Reload()
+ => Data = Serializer.Load();
+
+ ///
+ /// Save the data. Call the Save method of the serializer.
+ /// See:
+ ///
+ public void Save()
+ => Serializer.Save(Data);
+
+ ///
+ /// Import data from a file.
+ /// See:
+ ///
+ /// The type of data to import.
+ /// The path containing the name of the file created.
+ public void Import(string pathOfTheFile)
+ where T : class
+ {
+ KeyValuePair import = Serializer.Import(pathOfTheFile);
+ Data[import.Key].Add(import.Value);
+ }
+
+ ///
+ /// Export the data from the collection of data.
+ /// See:
+ ///
+ /// The type of data to export
+ /// The object to export
+ /// The path containing the name of the file created.
+ public void Export(T obj, string pathToExport)
+ where T : class
+ => Serializer.Export(obj, pathToExport);
+ #endregion
+ }
+}
diff --git a/MCTG/DataPersistence/DataPersistence.csproj b/MCTG/DataPersistence/DataPersistence.csproj
new file mode 100644
index 0000000..d5050a6
--- /dev/null
+++ b/MCTG/DataPersistence/DataPersistence.csproj
@@ -0,0 +1,17 @@
+
+
+
+ net7.0
+ enable
+ enable
+
+
+
+
+
+
+
+
+
+
+
diff --git a/MCTG/DataPersistence/IDataManager.cs b/MCTG/DataPersistence/IDataManager.cs
new file mode 100644
index 0000000..95209d8
--- /dev/null
+++ b/MCTG/DataPersistence/IDataManager.cs
@@ -0,0 +1,44 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace DataPersistence
+{
+ ///
+ /// Interface that define the methods of a data serializer.
+ ///
+ public interface IDataManager
+ {
+ ///
+ /// Save all the data in a file.
+ ///
+ /// The data to save.
+ void Save(Dictionary> elements);
+
+ ///
+ /// Load all the data from a file.
+ ///
+ /// The data loaded.
+ Dictionary> Load();
+
+ ///
+ /// Import an element to the collection of data.
+ ///
+ /// The type of the element to impoert
+ /// The path containing the name of the file.
+ /// A pair where the key is the entry in the data and the value is the value to add on this entry.
+ public KeyValuePair Import(string pathToImport)
+ where T : class;
+
+ ///
+ /// Export an element from the collection of data.
+ ///
+ /// The type of the exported object.
+ /// The object to export.
+ /// The path containing the name of the file created.
+ public void Export(T obj, string pathToExport)
+ where T : class;
+ }
+}
diff --git a/MCTG/DataPersistence/Stubs.cs b/MCTG/DataPersistence/Stubs.cs
new file mode 100644
index 0000000..cc09f39
--- /dev/null
+++ b/MCTG/DataPersistence/Stubs.cs
@@ -0,0 +1,112 @@
+using Model;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace DataPersistence
+{
+ ///
+ /// The subs class is a group of prefabricated object that can only be loaded. It only use is for testing.
+ ///
+ public class Stubs : IDataManager
+ {
+ public Dictionary> Load()
+ {
+ Dictionary> data = new Dictionary>
+ {
+ {
+ #region Data: Recipes
+ nameof(Recipe),
+ new List