using System; using System.Collections.Generic; using System.Linq; using System.Runtime.Serialization; using System.Data.SqlClient; using System.Data; using System.ComponentModel; using DTS.Common.Interface.GroupTemplate; using DTS.Common.Storage; using DTS.Common.Utilities.Logging; namespace DTS.Common.ISO { public class TestObjectTemplateChannel : INotifyPropertyChanged, IGroupTemplateChannel, IComparable { #region INotifyPropertyChanged public event PropertyChangedEventHandler PropertyChanged; protected bool SetProperty(ref T storage, T value, string propertyName = null) { if (Equals(storage, value)) return false; storage = value; OnPropertyChanged(propertyName); return true; } protected void OnPropertyChanged(string propertyName = null) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } #endregion #region constants and enums public const string NONISOCHANNELTYPE = "NONISO"; public const string SEPARATOR = "_X_"; public const string TEST_SPECIFIC_DOUT = "TSD_"; public enum ReferenceChannelTypes { IMPLICIT, EXPLICIT, NOVALUE }; public enum DataSourceTypes { Transducer, Calculation, Camera, Simulation, Parameter }; public enum DataStatusTypes { OK, ChannelFailed, MeaninglessData, NoData, QuestionableData, ScalingFactorApplied, SystemFailed, LinearisedData, NOVALUE } public enum StandardChannelProperties { NameOfTheChannel, DisplayOrder } #endregion #region properties public bool Custom => null == Channel || Channel.MMEChannelType == (int)MMEPossibleChannels.MMEChannelTypes.SQL; public int DisplayOrder { get => Convert.ToInt32(_channelProperties[StandardChannelProperties.DisplayOrder.ToString()].Value, System.Globalization.CultureInfo.InvariantCulture); set { _channelProperties[StandardChannelProperties.DisplayOrder.ToString()].Value = value.ToString(System.Globalization.CultureInfo.InvariantCulture); OnPropertyChanged("DisplayOrder"); } } public int TemplateChannelId { get; set; } public string NameOfTheChannel { get { var s = _channelProperties[StandardChannelProperties.NameOfTheChannel.ToString()].Value as string; if (!string.IsNullOrWhiteSpace(s) && s != DataStatusTypes.NOVALUE.ToString()) return s; if (Name.StartsWith(TEST_SPECIFIC_DOUT)) { return $"(Digital Output Setting){Name}"; } return Name; } set { _channelProperties[StandardChannelProperties.NameOfTheChannel.ToString()].Value = value; OnPropertyChanged("NameOfTheChannel"); } } public string Name { get { var tokens = Channel.Text_L1.Split(new[] { SEPARATOR }, StringSplitOptions.None); return tokens.Last(); } } public TestObjectTemplate Template { get; private set; } private readonly List _channelPropertyNames = new List(); private Dictionary _channelProperties = new Dictionary(); public MMEPossibleChannels Channel { get; private set; } public bool LocalOnly { get; set; } public string ISOCode => null != Channel ? IsoCodeStatics.GetString(Channel, false) : "????????????????"; #endregion #region methods public bool Filter(string term) { if (Name.ToLower().Contains(term.ToLower())) { return true; } if (NameOfTheChannel.ToLower().Contains(term.ToLower())) { return true; } return false; } protected object GetProperty(string name, object defaultValue) { if (!_channelProperties.ContainsKey(name)) { _channelProperties[name] = new ChannelProperty(name, defaultValue); } return _channelProperties[name].Value; } protected void SetProperty(string name, object value) { if (!_channelProperties.ContainsKey(name)) { _channelProperties[name] = new ChannelProperty(name, value); } else { _channelProperties[name].Value = value; } OnPropertyChanged("name"); // ? variable name instead of "name" } public void SetChannel(MMEPossibleChannels channel) { Channel = channel; } public void SetDisplayText(string objectSerial, string channelNumber, string text) { var name = text; // In either case we will eventually split this display text to parse out "text", so dont allow separator System.Diagnostics.Trace.Assert(!(name.Contains(SEPARATOR) || objectSerial.Contains(SEPARATOR) || channelNumber.Contains(SEPARATOR)), "SetDisplayText fed invalid characters"); if (string.IsNullOrEmpty(objectSerial) && string.IsNullOrEmpty(channelNumber)) { // custom ISO channel name creation. no need for special sparator Channel.SetText1($"{name}"); } else { if (name?.Length > Constants.MAX_USER_CHANNEL_NAME_LENGTH) { name = name.Substring(0, Constants.MAX_USER_CHANNEL_NAME_LENGTH); } // Non ISO custom channel name creation Channel.SetText1(string.Format("{0}{1}{2}{1}{3}", objectSerial, SEPARATOR, channelNumber, name)); } } public void SetID(long id) { Channel = new MMEPossibleChannels(Channel); Channel.SetId(id); } public override string ToString() { return null != Channel ? $"{Name}({Channel.Id})" : Name; } private void AddStandardProperties() { if (null != _channelProperties) { _channelProperties.Clear(); _channelProperties = null; } _channelProperties = new Dictionary(); var scp = Enum.GetValues(typeof(StandardChannelProperties)).Cast().ToArray(); foreach (var p in scp) { ChannelProperty cp; switch (p) { case StandardChannelProperties.DisplayOrder: cp = new ChannelProperty(p.ToString(), "-1"); break; case StandardChannelProperties.NameOfTheChannel: cp = new ChannelProperty("Name of the channel", "NOVALUE"); break; default: cp = new ChannelProperty(p.ToString(), "NOVALUE"); break; } _channelProperties.Add(p.ToString(), cp); } } public void SetTemplate(TestObjectTemplate template) { Template = template; } #endregion #region Required private bool _bRequired; /// /// Required channel property raises the OnRequiredChanged event /// public bool Required { get => _bRequired; set { _bRequired = value; OnRequiredChanged(new RequiredChangedEventArgs { NewValue = value }); SetProperty(ref _bRequired, value, "Required"); } } /// /// Event and event handler provide "client" side functionality /// to add required channels to the list /// See also RequiredChangedEventArgs class /// public event EventHandler RequiredChanged; public virtual void OnRequiredChanged(RequiredChangedEventArgs e) { RequiredChanged?.Invoke(this, e); } public int CompareTo(TestObjectTemplateChannel other) { if (null == other) { return 1; } if (Equals(other)) { return 0; } var displayOrder = DisplayOrder.CompareTo(other.DisplayOrder); if (0 == displayOrder) { var channelId = Channel.Id.CompareTo(other.Channel.Id); return 0 == channelId ? string.Compare(Name, other.Name, StringComparison.Ordinal) : channelId; } return displayOrder; } #endregion Required #region constructors and initializers public TestObjectTemplateChannel(DataRow dr, TestObjectTemplate template, ref ISO13499FileDb db) { Template = template; AddStandardProperties(); TemplateChannelId = Convert.ToInt32(dr["TemplateChannelId"]); _channelProperties[StandardChannelProperties.NameOfTheChannel.ToString()].Value = (string)dr["NameOfTheChannel"]; _channelProperties[StandardChannelProperties.DisplayOrder.ToString()].Value = -1; if (!DBNull.Value.Equals(dr["DisplayOrder"])) { _channelProperties[StandardChannelProperties.DisplayOrder.ToString()].Value = Convert .ToInt32(dr["DisplayOrder"]).ToString(System.Globalization.CultureInfo.InvariantCulture); } else { DisplayOrder = -1; } _bRequired = Convert.ToBoolean(dr["Required"]); LocalOnly = Convert.ToBoolean(dr["LocalOnly"]); var channelId = Convert.ToInt64(dr["MMEChannelId"]); var channelType = Convert.ToInt32(dr["MMEChannelType"]); Channel = db.GetPossibleChannel(channelId, channelType); } public TestObjectTemplateChannel(TestObjectTemplateChannel copy, TestObjectTemplate template) { TemplateChannelId = copy.TemplateChannelId; LocalOnly = copy.LocalOnly; _bRequired = copy.Required; Channel = new MMEPossibleChannels(copy.Channel); _channelProperties = new Dictionary(); using (var e = copy._channelProperties.GetEnumerator()) { while (e.MoveNext()) { _channelProperties[e.Current.Key] = new ChannelProperty(e.Current.Value); } } _channelPropertyNames = new List(copy._channelPropertyNames.ToArray()); Template = template; } public TestObjectTemplateChannel(MMEPossibleChannels channel) { Channel = channel; AddStandardProperties(); DisplayOrder = -1; var scp = Enum.GetValues(typeof(StandardChannelProperties)).Cast().ToArray(); foreach (var p in scp) { switch (p) { //case StandardChannelProperties.DisplayOrder: _channelProperties[StandardChannelProperties.DisplayOrder.ToString()].Value = Convert.ToInt32(Channel.Id).ToString(System.Globalization.CultureInfo.InvariantCulture); break; case StandardChannelProperties.NameOfTheChannel: break; } } } #endregion #region Unused Properties/meta data public string LaboratoryCode { get => DataStatusTypes.NOVALUE.ToString(); set { } } public string CustomerChannelCode { get => DataStatusTypes.NOVALUE.ToString(); set { } } public string ChannelCode { get => DataStatusTypes.NOVALUE.ToString(); set { } } public string Comments1 { get => DataStatusTypes.NOVALUE.ToString(); set { } } public string Location { get => DataStatusTypes.NOVALUE.ToString(); set { } } public string Dimension { get => DataStatusTypes.NOVALUE.ToString(); set { } } public string Direction { get => DataStatusTypes.NOVALUE.ToString(); set { } } public string ChannelFrequencyClass { get => DataStatusTypes.NOVALUE.ToString(); set { } } public string Unit { get => DataStatusTypes.NOVALUE.ToString(); set { } } public string ReferenceSystem { get => DataStatusTypes.NOVALUE.ToString(); set { } } public string TestObjectNumber { get => DataStatusTypes.NOVALUE.ToString(); set { } } public string TransducerType { get => DataStatusTypes.NOVALUE.ToString(); set { } } public string TransducerId { get => DataStatusTypes.NOVALUE.ToString(); set { } } public string PreFilterType { get => DataStatusTypes.NOVALUE.ToString(); set { } } public string CutOffFrequency { get => DataStatusTypes.NOVALUE.ToString(); set { } } public string ChannelAmplitudeClass { get => DataStatusTypes.NOVALUE.ToString(); set { } } public ReferenceChannelTypes ReferenceChannel { get => ReferenceChannelTypes.NOVALUE; set { } } public string ReferenceChannelName { get => DataStatusTypes.NOVALUE.ToString(); set { } } public DataSourceTypes DataSource { get => DataSourceTypes.Parameter; set { } } public DataStatusTypes DataStatus { get => DataStatusTypes.NOVALUE; set { } } public string SamplingInterval { get => DataStatusTypes.NOVALUE.ToString(); set { } } public string BitResolution { get => DataStatusTypes.NOVALUE.ToString(); set { } } public string TimeOfFirstSample { get => DataStatusTypes.NOVALUE.ToString(); set { } } public string NumberOfSamples { get => DataStatusTypes.NOVALUE.ToString(); set { } } public string OffsetPostTest { get => DataStatusTypes.NOVALUE.ToString(); set { } } public string TransducerNaturalFrequency { get => DataStatusTypes.NOVALUE.ToString(); set { } } public string TransducerDampingRatio { get => DataStatusTypes.NOVALUE.ToString(); set { } } public string Comments2 { get => DataStatusTypes.NOVALUE.ToString(); set { } } public string FirstGlobalMaximumValue { get => DataStatusTypes.NOVALUE.ToString(); set { } } public string TimeOfMaximumValue { get => DataStatusTypes.NOVALUE.ToString(); set { } } public string FirstGlobalMinimumValue { get => DataStatusTypes.NOVALUE.ToString(); set { } } public string TimeOfMinimumValue { get => DataStatusTypes.NOVALUE.ToString(); set { } } public string StartOffsetInterval { get => DataStatusTypes.NOVALUE.ToString(); set { } } public string EndOffsetInterval { get => DataStatusTypes.NOVALUE.ToString(); set { } } #endregion //TODO: move to separate class public class ChannelProperty : ISerializable { public string Name { get; } public object Value { get; set; } = "NOVALUE"; public ChannelProperty(ChannelProperty copy) { Name = copy.Name; Value = copy.Value; } public ChannelProperty(string name, object value) { Name = name; Value = value; } public void GetObjectData(SerializationInfo info, StreamingContext context) { info.AddValue("PropertyName", Name); info.AddValue("PropertyValue", Value, Value.GetType()); } } } public class RequiredChangedEventArgs : EventArgs { public bool NewValue { get; set; } } }