DFStorage.cs 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  1. using Newtonsoft.Json.Linq;
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Diagnostics.CodeAnalysis;
  5. namespace InABox.Core
  6. {
  7. /// <summary>
  8. /// Class to manage the storing of form data, including the separation of blob and form data.
  9. /// </summary>
  10. public class DFSaveStorage
  11. {
  12. public Dictionary<string, object?> FormData { get; private set; }
  13. public Dictionary<string, object?> BlobData { get; private set; }
  14. public DFSaveStorage()
  15. {
  16. FormData = new Dictionary<string, object?>();
  17. BlobData = new Dictionary<string, object?>();
  18. }
  19. public void AddValue(string key, object? value)
  20. {
  21. FormData.Add(key, value);
  22. }
  23. public void AddBlobValue(string key, object? value)
  24. {
  25. if(value != null)
  26. {
  27. var id = Guid.NewGuid().ToString();
  28. BlobData.Add(id, value);
  29. FormData.Add(key, id);
  30. }
  31. }
  32. public object? GetValue(string key) => FormData.GetValueOrDefault(key);
  33. public DFSaveStorageEntry GetEntry(string key)
  34. {
  35. return new DFSaveStorageEntry(this, key);
  36. }
  37. public DFLoadStorage ToLoadStorage()
  38. {
  39. return new DFLoadStorage(FormData, BlobData);
  40. }
  41. }
  42. public class DFSaveStorageEntry
  43. {
  44. private readonly DFSaveStorage storage;
  45. private readonly string key;
  46. public DFSaveStorageEntry(DFSaveStorage storage, string key)
  47. {
  48. this.storage = storage;
  49. this.key = key;
  50. }
  51. public object? GetValue() => storage.GetValue(key);
  52. public object? GetValue(string subKey) => storage.GetValue($"{key}.{subKey}");
  53. public void SetValue(object? value)
  54. {
  55. storage.AddValue(key, value);
  56. }
  57. public void AddValue(string subKey, object? value)
  58. {
  59. storage.AddValue($"{key}.{subKey}", value);
  60. }
  61. public void SetBlobValue(object? value)
  62. {
  63. storage.AddBlobValue(key, value);
  64. }
  65. public void AddBlobValue(string subKey, object? value)
  66. {
  67. storage.AddBlobValue($"{key}.{subKey}", value);
  68. }
  69. }
  70. public class DFLoadStorage
  71. {
  72. public Dictionary<string, object?> FormData { get; private set; } = new Dictionary<string, object?>();
  73. public DFLoadStorage(Dictionary<string, object?> formData, Dictionary<string, object?>? blobData)
  74. {
  75. Load(formData, blobData);
  76. }
  77. public void Load(Dictionary<string, object?> formData, Dictionary<string, object?>? blobData)
  78. {
  79. FormData = formData;
  80. if (blobData != null)
  81. {
  82. var updates = new List<Tuple<string, object?>>();
  83. foreach (var (key, value) in FormData)
  84. {
  85. if ((value is string str && blobData.TryGetValue(str, out var blob))
  86. || (value is Guid guid && blobData.TryGetValue(guid.ToString(), out blob)))
  87. {
  88. updates.Add(new Tuple<string, object?>(key, blob));
  89. }
  90. }
  91. foreach (var (key, value) in updates)
  92. {
  93. FormData[key] = value;
  94. }
  95. }
  96. }
  97. /// <summary>
  98. /// Get a value from the storage, returning <see langword="null"/> if the key does not exist.
  99. /// </summary>
  100. /// <param name="key"></param>
  101. /// <returns></returns>
  102. public object? GetValue(string key)
  103. {
  104. return FormData.GetValueOrDefault(key);
  105. }
  106. [return: MaybeNull]
  107. public T GetValue<T>(string key)
  108. {
  109. if(FormData.TryGetValue(key, out var value))
  110. {
  111. if(value is T t)
  112. {
  113. return t;
  114. }
  115. else if(value is string str)
  116. {
  117. if(Guid.TryParse(str, out var id))
  118. {
  119. if(id is T)
  120. {
  121. return (T)(object)id;
  122. }
  123. else
  124. {
  125. return default;
  126. }
  127. }
  128. try
  129. {
  130. return Serialization.Deserialize<T>(str, strict: true);
  131. }
  132. catch
  133. {
  134. return CoreUtils.ChangeType<T>(value);
  135. }
  136. }
  137. else if(value is JToken jToken)
  138. {
  139. return Serialization.Deserialize<T>(jToken);
  140. }
  141. else
  142. {
  143. return CoreUtils.ChangeType<T>(value);
  144. }
  145. }
  146. return default;
  147. }
  148. public bool HasValue(string key)
  149. {
  150. return FormData.ContainsKey(key);
  151. }
  152. public DFLoadStorageEntry GetEntry(string key)
  153. {
  154. return new DFLoadStorageEntry(this, key);
  155. }
  156. public IEnumerable<KeyValuePair<string, object?>> Items()
  157. {
  158. return FormData;
  159. }
  160. }
  161. public class DFLoadStorageEntry
  162. {
  163. private readonly DFLoadStorage storage;
  164. private readonly string key;
  165. public DFLoadStorageEntry(DFLoadStorage storage, string key)
  166. {
  167. this.storage = storage;
  168. this.key = key;
  169. }
  170. /// <summary>
  171. /// Gets the value from the storage entry, returning <see langword="null"/> if it does not exist.
  172. /// </summary>
  173. /// <param name="key"></param>
  174. /// <returns></returns>
  175. public object? GetValue()
  176. {
  177. return storage.GetValue(key);
  178. }
  179. [return: MaybeNull]
  180. public T GetValue<T>()
  181. {
  182. return storage.GetValue<T>(key);
  183. }
  184. /// <summary>
  185. /// Gets a sub-value from the storage entry, returning <see langword="null"/> if it does not exist.
  186. /// </summary>
  187. /// <param name="subKey"></param>
  188. /// <returns></returns>
  189. public object? GetValue(string subKey)
  190. {
  191. return storage.GetValue($"{key}.{subKey}");
  192. }
  193. [return: MaybeNull]
  194. public T GetValue<T>(string subKey)
  195. {
  196. return storage.GetValue<T>($"{key}.{subKey}");
  197. }
  198. public bool HasValue() => storage.HasValue(key);
  199. public bool HasValue(string subKey) => storage.HasValue($"{key}.{subKey}");
  200. public IEnumerable<KeyValuePair<string, object?>> SubItems()
  201. {
  202. var prefix = $"{key}.";
  203. foreach(var (key, value) in storage.Items())
  204. {
  205. if (key.StartsWith(prefix))
  206. {
  207. yield return new KeyValuePair<string, object?>(key[prefix.Length..], value);
  208. }
  209. }
  210. }
  211. }
  212. }