BadScript 2
Loading...
Searching...
No Matches
BadSettings.cs
Go to the documentation of this file.
1using System.Text;
2
3using Newtonsoft.Json.Linq;
4
5namespace BadScript2.Settings;
6
10public class BadSettings
11{
15 private readonly Dictionary<string, BadSettings> m_Properties;
16
20 private readonly string m_SourcePath;
21
22 public bool HasSourcePath => !string.IsNullOrEmpty(m_SourcePath);
23 public string SourcePath => m_SourcePath;
24
28 private object? m_Cache;
29
33 private bool m_IsDirty;
34
38 private JToken? m_Value;
39
44 public BadSettings(string sourcePath)
45 {
46 m_SourcePath = sourcePath;
47 m_Value = null;
48 m_IsDirty = true;
49 m_Properties = new Dictionary<string, BadSettings>();
50 }
51
57 public BadSettings(JToken? value, string sourcePath)
58 {
59 m_Value = value;
60 m_SourcePath = sourcePath;
61 m_IsDirty = true;
62 m_Properties = new Dictionary<string, BadSettings>();
63 }
64
70 public BadSettings(Dictionary<string, BadSettings> properties, string sourcePath)
71 {
72 m_Value = null;
73 m_IsDirty = true;
74 m_Properties = properties;
75 m_SourcePath = sourcePath;
76 foreach (KeyValuePair<string, BadSettings> kvp in m_Properties)
77 {
78 kvp.Value.OnValueChanged += PropertyValueChanged;
79 }
80 }
81
85 public IEnumerable<string> PropertyNames => m_Properties.Keys;
86
87 public event Action OnValueChanged = delegate { };
88
89 private void PropertyValueChanged()
90 {
91 m_IsDirty = true;
93 }
94
95 private void InvokeValueChanged()
96 {
98 }
99
104 public JToken? GetValue()
105 {
106 return m_Value;
107 }
108
114 public T? GetValue<T>()
115 {
116 if (!m_IsDirty)
117 {
118 return (T?)m_Cache;
119 }
120
121 if (m_Value == null)
122 {
123 return default;
124 }
125
126 T? v = m_Value.ToObject<T>();
127
128 m_Cache = v;
129 m_IsDirty = false;
130
131 return v;
132 }
133
138 public bool HasValue()
139 {
140 return m_Value != null;
141 }
142
148 private bool HasValue<T>()
149 {
150 if (m_Value?.Type == JTokenType.Array && !typeof(T).IsArray)
151 {
152 return false;
153 }
154
155 return m_Value != null && m_Value.ToObject<T>() != null;
156 }
157
163 public void SetValue(JToken? value, bool invokeOnChange = true)
164 {
165 m_Value = value;
166 if (invokeOnChange)
167 {
169 }
170 else
171 {
172 m_IsDirty = true;
173 }
174 }
175
180 private void SetValue(object? value)
181 {
182 SetValue(value == null ? JValue.CreateNull() : JToken.FromObject(value));
183 }
184
190 public bool HasProperty(string propertyName)
191 {
192 return m_Properties.ContainsKey(propertyName);
193 }
194
200 public BadSettings GetProperty(string propertyName)
201 {
202 return m_Properties[propertyName];
203 }
204
211 public void SetProperty(string propertyName, BadSettings value, bool invokeOnChange = true)
212 {
213 if (m_Properties.TryGetValue(propertyName, out BadSettings? old))
214 {
215 old.OnValueChanged -= PropertyValueChanged;
216 }
217
218 m_Properties[propertyName] = value;
219 if (invokeOnChange)
220 {
222 }
223 else
224 {
225 m_IsDirty = true;
226 }
227 }
228
234 public bool RemoveProperty(string propertyName, bool invokeOnChange = true)
235 {
236 if (m_Properties.TryGetValue(propertyName, out BadSettings? old))
237 {
238 old.OnValueChanged -= PropertyValueChanged;
239 }
240
241 bool r = m_Properties.Remove(propertyName);
242
243 if (invokeOnChange)
244 {
246 }
247 else
248 {
249 m_IsDirty = true;
250 }
251
252 return r;
253 }
254
255
261 public void Populate(bool invokeOnChanged, params BadSettings[] settings)
262 {
263 if (m_Value is JArray arr)
264 {
265 foreach (BadSettings setting in settings)
266 {
267 if (!setting.HasValue())
268 {
269 continue;
270 }
271
272 if (setting.GetValue() is JArray arr2)
273 {
274 foreach (JToken jToken in arr2)
275 {
276 arr.Add(jToken);
277 }
278 }
279 else
280 {
281 arr.Add(setting.GetValue() ?? JValue.CreateNull());
282 }
283 }
284 }
285
286 foreach (BadSettings setting in settings)
287 {
288 foreach (string propertyName in setting.PropertyNames)
289 {
290 if (HasProperty(propertyName))
291 {
292 GetProperty(propertyName).Populate(false, setting.GetProperty(propertyName));
293 }
294 else
295 {
296 SetProperty(propertyName, setting.GetProperty(propertyName), false);
297 }
298 }
299 }
300
301 if (invokeOnChanged)
302 {
304 }
305 else
306 {
307 m_IsDirty = true;
308 }
309 }
310
317 public T? FindProperty<T>(string propertyName) where T : class
318 {
319 BadSettings? settings = FindProperty(propertyName);
320
321 return settings?.GetValue<T>();
322 }
323
329 public BadSettings FindOrCreateProperty(string propertyPath)
330 {
331 string[] path = propertyPath.Split('.');
332 BadSettings current = this;
333
334 foreach (string s in path)
335 {
336 if (!current.HasProperty(s))
337 {
338 BadSettings se = new BadSettings(string.Empty);
339 current.SetProperty(s, se);
340 current = se;
341 }
342 else
343 {
344 current = current.GetProperty(s);
345 }
346 }
347
348 return current;
349 }
350
356 public BadSettings? FindProperty(string propertyPath)
357 {
358 string[] path = propertyPath.Split('.');
359 BadSettings current = this;
360
361 foreach (string s in path)
362 {
363 if (!current.HasProperty(s))
364 {
365 return null;
366 }
367
368 current = current.GetProperty(s);
369 }
370
371 return current;
372 }
373
378 public override string ToString()
379 {
380 if (HasValue())
381 {
382 return GetValue()?.ToString() ?? "NULL";
383 }
384
385 StringBuilder sb = new StringBuilder();
386
387 sb.AppendLine("{");
388
389 foreach (string propertyName in PropertyNames)
390 {
391 BadSettings s = GetProperty(propertyName);
392 string str = s.ToString().Replace("\n", "\n\t");
393 sb.AppendLine($" {propertyName}: {str}");
394 }
395
396 sb.AppendLine("}");
397
398 return sb.ToString();
399 }
400
412 private static string ResolveEnvironmentVariables(BadSettings root, BadSettings parent, string str)
413 {
414 for (int i = 0; i < str.Length; i++)
415 {
416 if (str[i] != '$' || i + 1 >= str.Length || str[i + 1] != '(')
417 {
418 continue;
419 }
420
421 int end = str.IndexOf(')', i + 2);
422
423 if (end == -1)
424 {
425 throw new Exception("Unclosed environment variable");
426 }
427
428 string envVar = str.Substring(i + 2, end - i - 2);
429
430 string? env = root.FindProperty<string>(envVar);
431
432 if (env == null)
433 {
434 env = parent.FindProperty<string>(envVar);
435
436 if (env == null)
437 {
438 throw new Exception($"Environment variable '{envVar}' not found");
439 }
440 }
441
442 str = str.Replace(str.Substring(i, end - i + 1), env);
443 i--;
444 }
445
446 return str;
447 }
448
454 {
455 ResolveEnvironmentVariables(root, root, root);
456 }
457
464 public static void ResolveEnvironmentVariables(BadSettings root, BadSettings settings, BadSettings parent)
465 {
466 if (settings.HasValue<string>())
467 {
468 string value = settings.GetValue<string>()!;
469
470 settings.SetValue(ResolveEnvironmentVariables(root, parent, value));
471 }
472 else if (settings.HasValue<string[]>())
473 {
474 string[] value = settings.GetValue<string[]>()!;
475
476 for (int i = 0; i < value.Length; i++)
477 {
478 value[i] = ResolveEnvironmentVariables(root, parent, value[i]);
479 }
480
481 settings.SetValue(value);
482 }
483
484 foreach (string propertyName in settings.PropertyNames)
485 {
486 ResolveEnvironmentVariables(root, settings.GetProperty(propertyName), settings);
487 }
488 }
489}
Public Api for the Settings System.
readonly Dictionary< string, BadSettings > m_Properties
The properties of the Current Settings Object.
void Populate(bool invokeOnChanged, params BadSettings[] settings)
Populates the current object with the settings provided.
readonly string m_SourcePath
The Source Path of the Settings Object.
BadSettings? FindProperty(string propertyPath)
Finds a property based on the property path relative to this object.
JToken? m_Value
The Json Token of the Settings Object.
IEnumerable< string > PropertyNames
The Property Names of the Settings Object.
BadSettings(JToken? value, string sourcePath)
Creates a new Settings Object from a Json Token.
object? m_Cache
Cache for the Serialized Value of the Settings.
bool m_IsDirty
Indicates if the current object is dirty and needs to be re-serialized.
override string ToString()
Returns a string representation of the current object.
void SetProperty(string propertyName, BadSettings value, bool invokeOnChange=true)
Sets the Property with the given Name.
void SetValue(JToken? value, bool invokeOnChange=true)
Sets the Json Token of the Current Settings Object.
bool HasValue()
Returns true if the Settings Object has a JToken Value.
static void ResolveEnvironmentVariables(BadSettings root)
Resolves Environment Variables in the current object.
T? GetValue< T >()
Returns a Deserialized Value of the Settings Object.
static string ResolveEnvironmentVariables(BadSettings root, BadSettings parent, string str)
Resolves Environment Variables in the current object.
BadSettings(Dictionary< string, BadSettings > properties, string sourcePath)
Creates a new Settings Object from a Dictionary of Properties.
bool HasValue< T >()
Returns true if the Settings Object can be Deserialized into the given Type.
BadSettings GetProperty(string propertyName)
Returns the Property with the given Name.
void SetValue(object? value)
Sets the Json Token of the Current Settings Object.
JToken? GetValue()
Returns the Json Token of the Settings Object.
BadSettings FindOrCreateProperty(string propertyPath)
Finds a property based on the property path relative to this object.
BadSettings(string sourcePath)
Creates a new empty Settings Object.
bool HasProperty(string propertyName)
Returns true if the Settings Object has the given Property.
bool RemoveProperty(string propertyName, bool invokeOnChange=true)
Removes the Property with the given Name.
T? FindProperty< T >(string propertyName)
Finds a property based on the property path relative to this object.
static void ResolveEnvironmentVariables(BadSettings root, BadSettings settings, BadSettings parent)
Resolves Environment Variables in the current object.
Contains the Settings Implementation.