You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

120 lines
3.5 KiB

  1. using IPA.Logging;
  2. using Newtonsoft.Json;
  3. using Newtonsoft.Json.Linq;
  4. using System;
  5. using System.Collections.Specialized;
  6. using System.ComponentModel;
  7. using System.IO;
  8. namespace IPA.Config.ConfigProviders
  9. {
  10. [Config.Type("json")]
  11. internal class JsonConfigProvider : IConfigProvider
  12. {
  13. public static void RegisterConfig()
  14. {
  15. Config.Register<JsonConfigProvider>();
  16. }
  17. private JObject jsonObj;
  18. // TODO: create a wrapper that allows empty object creation
  19. public dynamic Dynamic => jsonObj;
  20. public bool HasChanged { get; private set; }
  21. public bool InMemoryChanged { get; set; }
  22. public DateTime LastModified => File.GetLastWriteTime(Filename);
  23. private string _filename;
  24. public string Filename
  25. {
  26. get => _filename;
  27. set
  28. {
  29. if (_filename != null)
  30. throw new InvalidOperationException("Can only assign to Filename once");
  31. _filename = value;
  32. }
  33. }
  34. public void Load()
  35. {
  36. Logger.config.Debug($"Loading file {Filename}");
  37. var fileInfo = new FileInfo(Filename);
  38. if (fileInfo.Exists)
  39. {
  40. string json = File.ReadAllText(fileInfo.FullName);
  41. try
  42. {
  43. jsonObj = JObject.Parse(json);
  44. }
  45. catch (Exception e)
  46. {
  47. Logger.config.Error($"Error parsing JSON in file {Filename}; resetting to empty JSON");
  48. Logger.config.Error(e);
  49. jsonObj = new JObject();
  50. File.WriteAllText(fileInfo.FullName, JsonConvert.SerializeObject(jsonObj, Formatting.Indented));
  51. }
  52. }
  53. else
  54. {
  55. jsonObj = new JObject();
  56. }
  57. SetupListeners();
  58. InMemoryChanged = true;
  59. }
  60. private void SetupListeners()
  61. {
  62. jsonObj.PropertyChanged += JsonObj_PropertyChanged;
  63. jsonObj.ListChanged += JsonObj_ListChanged;
  64. jsonObj.CollectionChanged += JsonObj_CollectionChanged;
  65. }
  66. private void JsonObj_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
  67. {
  68. HasChanged = true;
  69. InMemoryChanged = true;
  70. }
  71. private void JsonObj_ListChanged(object sender, ListChangedEventArgs e)
  72. {
  73. HasChanged = true;
  74. InMemoryChanged = true;
  75. }
  76. private void JsonObj_PropertyChanged(object sender, PropertyChangedEventArgs e)
  77. {
  78. HasChanged = true;
  79. InMemoryChanged = true;
  80. }
  81. public T Parse<T>()
  82. {
  83. if (jsonObj == null)
  84. return default(T);
  85. return jsonObj.ToObject<T>();
  86. }
  87. public void Save()
  88. {
  89. Logger.config.Debug($"Saving file {Filename}");
  90. if (!Directory.Exists(Path.GetDirectoryName(Filename)))
  91. Directory.CreateDirectory(Path.GetDirectoryName(Filename) ?? throw new InvalidOperationException());
  92. File.WriteAllText(Filename, JsonConvert.SerializeObject(jsonObj, Formatting.Indented));
  93. HasChanged = false;
  94. }
  95. public void Store<T>(T obj)
  96. {
  97. jsonObj = JObject.FromObject(obj);
  98. SetupListeners();
  99. HasChanged = true;
  100. InMemoryChanged = true;
  101. }
  102. }
  103. }