Files

477 lines
20 KiB
C#
Raw Permalink Normal View History

2026-04-17 14:55:32 -04:00
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Windows;
using DTS.Common.Base;
using DTS.Common.Storage;
using DTS.Common.ISO;
using DTS.Common.DataModel;
namespace DataPROWin7.DataModel
{
/// <summary>
/// a custom channel is a wrapper for MMEPossibleChannels that are defined by the user rather than ISO13499
/// they have mirror tables to the actual db and let us define new channels without disrupting the existing 1so13499 db
/// </summary>
public class CustomChannel : BasePropertyChanged, IComparable<CustomChannel>
{
private const string defaultDefaultFilterClass = "P";
#region Properties
public MMEPossibleChannels Channel { get; private set; }
public string TypeString
{
get => Channel.Type;
set { Channel.SetType(value); OnPropertyChanged("TypeString"); }
}
private MMETestObjects _testObject;
public MMETestObjects TestObject
{
get => _testObject;
set { SetProperty(ref _testObject, value, "TestObject"); if (null != Channel && null != value) { Channel.Set_Test_Object(value.Test_Object); } }
}
private MMEPositions _position;
public MMEPositions Position
{
get => _position;
set { SetProperty(ref _position, value, "Position"); if (null != Channel && null != value) { Channel.Set_Position(value.Position); } }
}
private MMETransducerMainLocation _mainLocation;
public MMETransducerMainLocation MainLocation
{
get => _mainLocation;
set { SetProperty(ref _mainLocation, value, "MainLocation"); if (null != Channel && null != value) { Channel.Set_Main_Loc(value.Trans_Main_Loc); } }
}
private MMEFineLocations1 _finLoc1;
public MMEFineLocations1 FinLoc1
{
get => _finLoc1;
set { SetProperty(ref _finLoc1, value, "FinLoc1"); if (null != Channel && null != value) { Channel.Set_Fine_Loc_1(value.Fine_Loc_1); } }
}
private MMEFineLocations2 _finLoc2;
public MMEFineLocations2 FinLoc2
{
get => _finLoc2;
set { SetProperty(ref _finLoc2, value, "FinLoc2"); if (null != Channel && null != value) { Channel.Set_Fine_Loc_2(value.FINE_LOC_2); } }
}
private MMEFineLocations3 _finLoc3;
public MMEFineLocations3 FinLoc3
{
get => _finLoc3;
set { SetProperty(ref _finLoc3, value, "FinLoc3"); if (null != Channel && null != value) { Channel.Set_Fine_Loc_3(value.FINE_LOC_3); } }
}
private MMEPhysicalDimensions _physicalDimension;
public MMEPhysicalDimensions PhysicalDimension
{
get => _physicalDimension;
set { SetProperty(ref _physicalDimension, value, "PhysicalDimension"); if (null != Channel && null != value) { Channel.Set_Physical_Dimension(value.Physical_Dimension); } }
}
private MMEDirections _direction;
public MMEDirections Direction
{
get => _direction;
set { SetProperty(ref _direction, value, "Direction"); if (null != Channel && null != value) { Channel.Set_Direction(value.Direction); } }
}
private MMEFilterClasses _filterClass;
public MMEFilterClasses FilterClass
{
get => _filterClass;
set { SetProperty(ref _filterClass, value, "FilterClass"); if (null != Channel && null != value) { Channel.Set_Default_Filter_Class(value.Filter_Class); } }
}
#endregion Properties
public string Text1
{
get => Channel.Text_L1;
set
{
var name = value;
System.Diagnostics.Trace.Assert(name?.Length < 250, "Channel text is too long");
Channel.SetText1(name);
OnPropertyChanged("Text1");
}
}
public string Remarks
{
get => Channel.Remarks;
set
{
Channel.SetRemarks(value);
OnPropertyChanged("Remarks");
}
}
public CustomChannel()
{
Channel = new MMEPossibleChannels(-1, "", "", "", "", "", "", "", "", "", "", "", "", 0, DateTime.Now, "", false, "", "", DateTime.MinValue, "", "", (int)MMEPossibleChannels.MMEChannelTypes.SQL);
_filterClass = ApplicationProperties.IsoDb.GetFilterClassByIso("A");
}
private readonly List<ISO13499FileDb.ExpiredISOFieldException> _expiredErrors = new List<ISO13499FileDb.ExpiredISOFieldException>();
/// <summary>
/// these are any errors detected during loading of the custom channel
/// as custom channels are reliant on the ISO13499 mdb, it is possible for it to have been updated and for things to have been removed or expired
/// </summary>
public ISO13499FileDb.ExpiredISOFieldException[] ExpiredErrors => _expiredErrors.ToArray();
public CustomChannel(MMEPossibleChannels channel, bool newChannel = true)
{
Channel = newChannel ? new MMEPossibleChannels(channel) : channel;
_direction = ApplicationProperties.IsoDb.GetDirectionByIso(channel.Direction);
_filterClass = ApplicationProperties.IsoDb.GetFilterClassByIso(channel.Default_Filter_Class) ??
ApplicationProperties.IsoDb.GetFilterClassByIso(defaultDefaultFilterClass);
_finLoc1 = ApplicationProperties.IsoDb.GetFineLocation1ByIso(channel.Fine_Loc_1);
_finLoc2 = ApplicationProperties.IsoDb.GetFineLocation2ByIso(channel.Fine_Loc_2);
_finLoc3 = ApplicationProperties.IsoDb.GetFineLocation3ByIso(channel.Fine_Loc_3);
try { _mainLocation = ApplicationProperties.IsoDb.GetMainLocationByIso(channel.Trans_Main_Loc); }
catch (ISO13499FileDb.ExpiredISOFieldException ex) { _expiredErrors.Add(ex); }
_physicalDimension = ApplicationProperties.IsoDb.GetPhysicalDimensionByIso(channel.Physical_Dimension);
_position = ApplicationProperties.IsoDb.GetPositionByISO(channel.Position);
_testObject = ApplicationProperties.IsoDb.GetTestObjectByIso(channel.Test_Object);
}
public void Commit(bool bNotify)
{
if (null == Channel)
{
Channel = new MMEPossibleChannels(-1, TypeString, TestObject.Test_Object, Position.Position, MainLocation?.Trans_Main_Loc, FinLoc1.Fine_Loc_1,
FinLoc2.FINE_LOC_2, FinLoc3.FINE_LOC_3, PhysicalDimension.Physical_Dimension, Direction?.Direction, FilterClass?.Filter_Class,
Text1, Text1, 1, DateTime.Now, Remarks, false, "", "", DateTime.Now, string.Format("created in DataPRO by {0}", ApplicationProperties.CurrentUser.UserName),
"", (int)MMEPossibleChannels.MMEChannelTypes.SQL);
}
else
{
Channel = new MMEPossibleChannels(Channel.Id, TypeString, TestObject.Test_Object, Position.Position, MainLocation?.Trans_Main_Loc, FinLoc1.Fine_Loc_1,
FinLoc2.FINE_LOC_2, FinLoc3.FINE_LOC_3, PhysicalDimension.Physical_Dimension, Direction?.Direction, FilterClass?.Filter_Class,
Text1, Text1, 1, DateTime.Now, Remarks, false, "", "", DateTime.Now, string.Format("updated in DataPRO by {0}", ApplicationProperties.CurrentUser.UserName),
"", (int)MMEPossibleChannels.MMEChannelTypes.SQL);
}
ApplicationProperties.IsoDb.Commit(Channel, bNotify);
}
public MMEPossibleChannels GetISOChannelForCommit()
{
if (null == Channel)
{
Channel = new MMEPossibleChannels(-1, TypeString, TestObject.Test_Object, Position.Position, MainLocation.Trans_Main_Loc, FinLoc1.Fine_Loc_1,
FinLoc2.FINE_LOC_2, FinLoc3.FINE_LOC_3, PhysicalDimension.Physical_Dimension, Direction.Direction, FilterClass.Filter_Class,
Text1, Text1, 1, DateTime.Now, Remarks, false, "", "", DateTime.Now, string.Format("created in DataPRO by {0}", ApplicationProperties.CurrentUser.UserName),
"", (int)MMEPossibleChannels.MMEChannelTypes.SQL);
}
else
{
Channel = new MMEPossibleChannels(Channel.Id, TypeString, TestObject.Test_Object, Position.Position, MainLocation.Trans_Main_Loc, FinLoc1.Fine_Loc_1,
FinLoc2.FINE_LOC_2, FinLoc3.FINE_LOC_3, PhysicalDimension.Physical_Dimension, Direction.Direction, FilterClass.Filter_Class,
Text1, Text1, 1, DateTime.Now, Remarks, false, "", "", DateTime.Now, string.Format("updated in DataPRO by {0}", ApplicationProperties.CurrentUser.UserName),
"", (int)MMEPossibleChannels.MMEChannelTypes.SQL);
}
return Channel;
}
public int CompareTo(CustomChannel other)
{
return Equals(this, other) ? 0 : string.Compare(Text1, other.Text1, StringComparison.Ordinal);
}
public string ISOCode => TestObject.Test_Object + Position.Position + MainLocation.Trans_Main_Loc + FinLoc1.Fine_Loc_1 + FinLoc2.FINE_LOC_2 +
FinLoc3.FINE_LOC_3 + PhysicalDimension.Physical_Dimension + Direction.Direction + FilterClass.Filter_Class;
}
public class CustomChannelList : BasePropertyChanged
{
public enum Tags
{
AllChannels
}
private static readonly object LockObject = new object();
private static CustomChannelList _list;
public static CustomChannelList List
{
get
{
lock (LockObject)
{
if (null == _list)
{
_list = new CustomChannelList();
}
}
return _list;
}
}
public void ReloadAll()
{
lock (LockObject)
{
List._listChannels = null;
//var app = Application.Current as App;
//if (app == null){ return; }
ApplicationProperties.IsoDb?.RefreshAllData();
List.PopulateChannelsIfNecessary(false);
}
}
/// <summary>
/// returns true if found, for a given isocode and/or channel id
/// returns false otherwise
/// </summary>
/// <param name="isocode"></param>
/// <returns></returns>
public bool IsChannelExists(string isocode)
{
lock (LockObject)
{
PopulateChannelsIfNecessary(false);
return ApplicationProperties.IsoDb.ContainsPossibleChannelWithISOCode(isocode);
}
}
public bool IsChannelExists(string isocode, long id)
{
if (id == -1) { return IsChannelExists(isocode); }
lock (LockObject)
{
PopulateChannelsIfNecessary(false);
if (_dictChannels.ContainsKey(isocode)) { return _dictChannels[isocode].Channel.Id != id; }
//still need to check isocode isn't in regular iso channels.
return ApplicationProperties.IsoDb.ContainsPossibleChannelWithISOCode(isocode);
}
}
/// <summary>
/// returns a custom channel if found, for a given isocode
/// returns null otherwise
/// </summary>
/// <param name="isocode"></param>
/// <returns></returns>
public CustomChannel GetChannelByISOCode(string isocode, bool careAboutTestTimeFields)
{
lock (LockObject)
{
PopulateChannelsIfNecessary(careAboutTestTimeFields);
return _dictChannels.ContainsKey(isocode) ? _dictChannels[isocode] : null;
}
}
public CustomChannel GetChannelByFullISOCode(string isocode)
{
lock (LockObject)
{
PopulateChannelsIfNecessary(false);
if (_dictChannels.ContainsKey(isocode))
{
return _dictChannels[isocode];
}
var isocodeWithQuestionMarks = isocode.Substring(0, 15) + "?";
return DictChannelsContainsChannel(isocode, isocodeWithQuestionMarks) ? _dictChannels[isocodeWithQuestionMarks] : null;
}
}
private bool DictChannelsContainsChannel(string isocode, string isocodeWithQuestionMarks)
{
if (!_dictChannels.ContainsKey(isocodeWithQuestionMarks)) return false;
var temp = _dictChannels[isocodeWithQuestionMarks];
return temp.FilterClass.Filter_Class == isocode.Substring(15, 1);
}
/// <summary>
/// returns a channel given a name, this should _ONLY_ be used in
/// NON-ISO mode, as in other modes the name may not unique
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
public CustomChannel GetChannelByName(string name)
{
lock (LockObject)
{
var ch = from c in AllChannels.AsParallel() where c.Channel.Text_L1 == name select c;
return ch.Any() ? ch.First() : null;
}
}
public CustomChannel GetChannel(long id)
{
lock (LockObject)
{
PopulateChannelsIfNecessary(false);
var ch = from c in AllChannels where c.Channel.Id == id select c;
var customChannels = ch as CustomChannel[] ?? ch.ToArray();
return customChannels.Any() ? customChannels[0] : null;
}
}
private CustomChannelList()
{
}
private Dictionary<string, CustomChannel> _dictChannels;
private List<CustomChannel> _listChannels;
public CustomChannel[] AllChannels
{
get
{
PopulateChannelsIfNecessary(false);
return _listChannels.ToArray();
}
}
/// <summary>
/// loads all calculated channels, if necessary
/// </summary>
private void PopulateChannelsIfNecessary(bool careAboutTestTimeFields)
{
lock (LockObject)
{
if (null != _listChannels) return;
_listChannels = new List<CustomChannel>();
_dictChannels = new Dictionary<string, CustomChannel>();
foreach (var channel in ApplicationProperties.IsoDb.GetSQLPossibleChannels())
{
var ch = new CustomChannel(channel);
var iso = IsoCodeStatics.GetString(ch.Channel, careAboutTestTimeFields);
if (_dictChannels.ContainsKey(iso)) continue;
_listChannels.Add(ch);
_dictChannels[iso] = ch;
}
_listChannels.Sort();
}
}
public void Delete(CustomChannel[] channels)
{
lock (LockObject)
{
var idx = 0;
IDbCommand iCmd = null;
try
{
foreach (var channel in channels)
{
for (var i = _listChannels.Count - 1; i >= 0; i--)
{
if (_listChannels[i].Channel.Id == channel.Channel.Id)
{
_listChannels.RemoveAt(i);
if (null == iCmd)
{
iCmd = DbOperations.GetSQLCommand(true);
iCmd.CommandText = DbOperations.BEGIN_STATEMENT;
}
iCmd.CommandText += $"DELETE FROM [{DbOperations.MMETables.MMEPossibleChannelsTable}] WHERE [{DbOperations.MMETables.MMEPossibleChannelsFields.ID}]=@{idx}_1;";
DbOperations.CreateParam(iCmd,
$"@{idx}_1",
SqlDbType.NVarChar,
channel.Channel.Id);
idx++;
if (0 == idx % 2000)
{
iCmd.CommandText += DbOperations.COMMIT_STATEMENT;
DbOperations.Connection.ExecuteCommand(iCmd);
iCmd.Connection.Dispose();
iCmd.Dispose();
iCmd = null;
}
break;
}
}
if (_dictChannels.ContainsKey(channel.Text1))
{
_dictChannels.Remove(channel.ISOCode);
}
}
}
finally
{
if (null != iCmd)
{
iCmd.CommandText += DbOperations.COMMIT_STATEMENT;
DbOperations.Connection.ExecuteCommand(iCmd);
iCmd.Connection.Dispose();
iCmd.Dispose();
}
}
}
}
public void UpdateAll()
{
lock (LockObject)
{
_listChannels = null;
_dictChannels = null;
ApplicationProperties.IsoDb.RefreshAllData();
}
OnPropertyChanged("AllChannels");
}
/// <summary>
/// this is a custom bulk insert of channels
/// it doesn't do the validation (make sure channels don't already exist)
/// and the clean the ordinary commit does (get the new id #)
/// so ... it's good for bulk, but make sure to call updateall so the ids are updated
/// </summary>
/// <param name="channels"></param>
public void Commit(CustomChannel[] channels)
{
MMEPossibleChannels.Commit(channels.Select(ch => ch.GetISOChannelForCommit()).ToArray());
}
public void Commit(CustomChannel channel) { Commit(channel, true, true); }
public void Commit(CustomChannel channel, bool bDoLookForExistingNameCheck, bool bNotify)
{
PopulateChannelsIfNecessary(false);
var bFound = false;
//don't consider the test fields when getting isocode (filter, position, test object)
var key = IsoCodeStatics.GetString(channel.Channel, false);
if (bDoLookForExistingNameCheck)
{
if (_dictChannels.ContainsKey(key))
{
bFound = true;
channel.Channel.SetId(_dictChannels[key].Channel.Id);
}
}
if (bFound && !bNotify)
{
//bypass the ordinary commit as it will attempt to do an insert
//and we just want to do an update.
//I'm abusing the bNotify flag above to limit the scope of my changes as I know it's
//false in batch updates where we aren't updating the list with every commit which is where the problem exists.
//see http://fogbugz/fogbugz/default.asp?6713 2016-03-14
channel.Channel.Commit();
}
else { channel.Commit(bNotify); }
if (bNotify)
{
lock (LockObject)
{
_listChannels = null;
_dictChannels = null;
}
OnPropertyChanged("AllChannels");
}
else
{
if (!bFound)
{
lock (LockObject)
{
_listChannels.Add(channel);
_dictChannels[key] = channel;
}
}
}
}
}
}