using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace IRIGCh10 { /// /// this is the base class for sections in the TMATS document /// each section is made of a bunch of attributes and values /// /// public abstract class TMATSSection where T : Enum { private Dictionary _values = new Dictionary(); /// /// Sets the given tag to a given value /// /// /// public void SetValue(T tag, string value) => _values[tag] = value; /// /// returns given value for a given tag /// value will be null if value was never set /// /// /// public string GetValue(T tag) => _values.ContainsKey(tag)?_values[tag]: null; /// /// sets a given tag to a given date, or an empty string if date is null /// /// /// public void SetDate(T tag, DateTime? value) { if (null == value) { SetValueWithLength(tag, string.Empty); } var dt = (DateTime) value; SetValueWithLength(tag, $"{dt.Month:00}-{dt.Day:00}-{dt.Year:0000}"); } /// /// gets a date for a tag, or null if date isn't set /// /// /// public DateTime? GetDate(T tag) { var value = GetValue(tag); if( string.IsNullOrWhiteSpace(value) ){ return null; } if (DateTime.TryParseExact(value, "MM-DD-YYYY", System.Globalization.CultureInfo.InvariantCulture, System.Globalization.DateTimeStyles.None, out var dt)) { return dt; } return null; } /// /// gets a int value for tag, or null if tag was never set /// /// /// public int? GetIntOrNull(T tag) { var val = GetValue(tag); if( string.IsNullOrWhiteSpace(val)){ return null; } if (int.TryParse(val, out var iTmp)) { return iTmp; } return null; } /// /// sets tag value /// /// /// public void SetIntOrNull(T tag, int? val) { if (null == val) { SetValueWithLength(tag, string.Empty); } else { SetValueWithLength(tag, ((int) val).ToString()); } } /// /// originally designed to check the length of values against the max length in spec /// however no longer checks length as max length is just a suggestion in the spec... /// /// /// public void SetValueWithLength(T tag, string value) { var maxLength = MaxLengthDecoder.GetMaxLength(tag); //apprently maxlength is just a suggestion ... //if (maxLength < value.Length) //{ // throw new FormatException($"{tag.ToString()} must be {maxLength} characters or less"); //} SetValue(tag, value); } /// /// returns all fields in the section for the tmats document /// /// public virtual string Serialize() { var tags = Enum.GetValues(typeof(T)).Cast().ToArray(); var sb = new StringBuilder(); foreach (var tag in tags) { var s = Serialize(tag); if( string.IsNullOrWhiteSpace(s)){ continue; } sb.AppendLine(s); } return sb.ToString(); } /// /// some attributes have to be associated with a number, like P-x\N:1 where x is /// the channel number, this keeps track of the number for all attributes /// private int _number = -1; private AttributeIdentifiers _attribute = AttributeIdentifiers.GeneralInformation; /// /// serializes just one tag/value to a string /// /// /// protected string Serialize(T tag) { var value = GetValue(tag); if( string.IsNullOrWhiteSpace(value)){ return null; } var attrib = DescriptionDecoder.GetDescription(tag); var attributeIdentifier = DescriptionDecoder.GetDescription(_attribute); if (_number < 0) { return $"{attributeIdentifier}\\{attrib}:{value};"; } return $"{attributeIdentifier}-{_number}\\{attrib}:{value};"; } /// /// generic constructor for attributes which don't need to be associated with a number, /// like General Information /// public TMATSSection() { } /// /// constructor for attributes that are associated with a specific number, like PCM /// being associated with a channel number /// /// /// public TMATSSection(AttributeIdentifiers attribute, int number) { _attribute = attribute; _number = number; } } }