using System; using System.Xml.Serialization; using Newtonsoft.Json; using SabreTools.Core.Tools; namespace SabreTools.Core { /// /// Represents an item that's backed by a DictionaryBase item /// public abstract class ModelBackedItem : IEquatable { #region Comparision Methods /// public abstract bool Equals(ModelBackedItem? other); #endregion } /// /// Represents an item that's backed by a DictionaryBase item /// public abstract class ModelBackedItem : ModelBackedItem, IEquatable> where T : Models.Metadata.DictionaryBase { /// /// Internal model wrapped by this DatItem /// [JsonIgnore, XmlIgnore] protected T _internal; #region Constructors public ModelBackedItem() { _internal = (T)Activator.CreateInstance(typeof(T))!; } #endregion #region Accessors /// /// Get the value from a field based on the type provided /// /// Type of the value to get from the internal model /// Field to retrieve /// Value from the field, if possible public U? GetFieldValue(string? fieldName) { // Invalid field cannot be processed if (fieldName == null || !_internal.ContainsKey(fieldName)) return default; // Get the value based on the type return _internal.Read(fieldName); } /// /// Get the value from a field based on the type provided /// /// Field to retrieve /// Value from the field, if possible public bool? GetBoolFieldValue(string? fieldName) { // Invalid field cannot be processed if (fieldName == null || !_internal.ContainsKey(fieldName)) return default; // Get the value based on the type return _internal.ReadBool(fieldName); } /// /// Get the value from a field based on the type provided /// /// Field to retrieve /// Value from the field, if possible public double? GetDoubleFieldValue(string? fieldName) { // Invalid field cannot be processed if (fieldName == null || !_internal.ContainsKey(fieldName)) return default; // Try to parse directly double? doubleValue = _internal.ReadDouble(fieldName); if (doubleValue != null) return doubleValue; // Try to parse from the string string? stringValue = _internal.ReadString(fieldName); return NumberHelper.ConvertToDouble(stringValue); } /// /// Get the value from a field based on the type provided /// /// Field to retrieve /// Value from the field, if possible public long? GetInt64FieldValue(string? fieldName) { // Invalid field cannot be processed if (fieldName == null || !_internal.ContainsKey(fieldName)) return default; // Try to parse directly long? longValue = _internal.ReadLong(fieldName); if (longValue != null) return longValue; // Try to parse from the string string? stringValue = _internal.ReadString(fieldName); return NumberHelper.ConvertToInt64(stringValue); } /// /// Get the value from a field based on the type provided /// /// Field to retrieve /// Value from the field, if possible public string? GetStringFieldValue(string? fieldName) { // Invalid field cannot be processed if (fieldName == null || !_internal.ContainsKey(fieldName)) return default; // Get the value based on the type return _internal.ReadString(fieldName); } /// /// Get the value from a field based on the type provided /// /// Field to retrieve /// Value from the field, if possible public string[]? GetStringArrayFieldValue(string? fieldName) { // Invalid field cannot be processed if (fieldName == null || !_internal.ContainsKey(fieldName)) return default; // Get the value based on the type return _internal.ReadStringArray(fieldName); } /// /// Set the value from a field based on the type provided /// /// Type of the value to set in the internal model /// Field to set /// Value to set /// True if the value was set, false otherwise public bool SetFieldValue(string? fieldName, U? value) { // Invalid field cannot be processed if (fieldName == null) return false; // Set the value based on the type _internal[fieldName] = value; return true; } #endregion #region Comparision Methods /// public abstract bool Equals(ModelBackedItem? other); #endregion #region Manipulation /// /// Remove a field from the backing item /// public bool RemoveField(string? fieldName) { // If the item or field name are missing, we can't do anything if (_internal == null || string.IsNullOrEmpty(fieldName)) return false; // If the key doesn't exist, then it's already removed if (!_internal.ContainsKey(fieldName!)) return true; // Remove the key _internal.Remove(fieldName!); return true; } /// /// Replace a field from another ModelBackedItem /// public bool ReplaceField(ModelBackedItem? from, string? fieldName) { // If the items or field name are missing, we can't do anything if (from?._internal == null || _internal == null || string.IsNullOrEmpty(fieldName)) return false; // If the types of the items are not the same, we can't do anything if (from._internal.GetType() != _internal.GetType()) return false; // If the key doesn't exist in the source, we can't do anything if (!from._internal.ContainsKey(fieldName!)) return false; // Set the key _internal[fieldName!] = from._internal[fieldName!]; return true; } /// /// Set a field from the backing item /// public bool SetField(string? fieldName, object value) { // If the item or field name are missing, we can't do anything if (_internal == null || string.IsNullOrEmpty(fieldName)) return false; // Retrieve the list of valid fields for the item var constants = TypeHelper.GetConstants(_internal.GetType()); if (constants == null) return false; // Get the value that matches the field name provided string? realField = Array.Find(constants, c => string.Equals(c, fieldName, StringComparison.OrdinalIgnoreCase)); if (realField == null) return false; // Set the field with the new value _internal[realField] = value; return true; } #endregion } }