Validation now runs async and hopefully solves the problem of some users where the app got unresponsive in the meantime
This commit is contained in:
parent
a1f6e6c113
commit
5932630635
@ -17,6 +17,7 @@ using ENI2.EditControls;
|
|||||||
using System.Windows.Input;
|
using System.Windows.Input;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using ENI2.SheetDisplayControls;
|
using ENI2.SheetDisplayControls;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace ENI2
|
namespace ENI2
|
||||||
{
|
{
|
||||||
@ -34,6 +35,9 @@ namespace ENI2
|
|||||||
// private readonly Dictionary<Message.NotificationClass, string> messageClassControlDict = new Dictionary<Message.NotificationClass, string>();
|
// private readonly Dictionary<Message.NotificationClass, string> messageClassControlDict = new Dictionary<Message.NotificationClass, string>();
|
||||||
private readonly object messageListLock = new object();
|
private readonly object messageListLock = new object();
|
||||||
private readonly HighlightService highlightService = new HighlightService();
|
private readonly HighlightService highlightService = new HighlightService();
|
||||||
|
private readonly object validationLock = new object();
|
||||||
|
private Task<ValidationResult> activeValidationTask = null;
|
||||||
|
private bool pendingShowMessages = false;
|
||||||
|
|
||||||
// Referenzen für Fehler/Violation Dialoge (können, müssen aber nicht offen bleiben)
|
// Referenzen für Fehler/Violation Dialoge (können, müssen aber nicht offen bleiben)
|
||||||
protected ErrorListDialog _errorListDialog = null;
|
protected ErrorListDialog _errorListDialog = null;
|
||||||
@ -703,7 +707,13 @@ namespace ENI2
|
|||||||
|
|
||||||
private void DetailControl_RequestSendValidation()
|
private void DetailControl_RequestSendValidation()
|
||||||
{
|
{
|
||||||
this.Validate(false, out _, out List<MessageError> errorList);
|
DetailControl_RequestSendValidationAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
private async void DetailControl_RequestSendValidationAsync()
|
||||||
|
{
|
||||||
|
ValidationResult result = await ValidateAndApplyAsync(false);
|
||||||
|
List<MessageError> errorList = result.Errors;
|
||||||
|
|
||||||
foreach (Message aMessage in this._messages)
|
foreach (Message aMessage in this._messages)
|
||||||
{
|
{
|
||||||
@ -777,22 +787,61 @@ namespace ENI2
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DetailControl_RequestValidate(bool showDialog)
|
private async void DetailControl_RequestValidate(bool showDialog)
|
||||||
{
|
{
|
||||||
this.Validate(showDialog, out _, out _);
|
await ValidateAndApplyAsync(showDialog);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Validate(bool showMessages, out List<MessageViolation> vViolations, out List<MessageError> vErrors)
|
private async Task<ValidationResult> ValidateAndApplyAsync(bool showMessages)
|
||||||
{
|
{
|
||||||
vViolations = new List<MessageViolation>();
|
Task<ValidationResult> validationTask = null;
|
||||||
vErrors = new List<MessageError>();
|
lock (validationLock)
|
||||||
|
{
|
||||||
|
if (activeValidationTask != null && !activeValidationTask.IsCompleted)
|
||||||
|
{
|
||||||
|
if (showMessages)
|
||||||
|
pendingShowMessages = true;
|
||||||
|
validationTask = activeValidationTask;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pendingShowMessages = showMessages;
|
||||||
|
activeValidationTask = ValidateAndApplyCoreAsync();
|
||||||
|
validationTask = activeValidationTask;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: clear highlighting
|
return await validationTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<ValidationResult> ValidateAndApplyCoreAsync()
|
||||||
|
{
|
||||||
Util.UIHelper.SetBusyState();
|
Util.UIHelper.SetBusyState();
|
||||||
|
ApplyCrewEffectsWarningSuppression();
|
||||||
|
|
||||||
|
List<Message> messagesSnapshot = _messages.ToList();
|
||||||
|
ValidationResult result = await Task.Run(() => ValidateCore(messagesSnapshot));
|
||||||
|
|
||||||
|
bool showMessages;
|
||||||
|
lock (validationLock)
|
||||||
|
{
|
||||||
|
showMessages = pendingShowMessages;
|
||||||
|
pendingShowMessages = false;
|
||||||
|
activeValidationTask = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
ApplyValidationResult(result, showMessages);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ValidationResult ValidateCore(List<Message> messagesSnapshot)
|
||||||
|
{
|
||||||
|
List<MessageViolation> vViolations = new List<MessageViolation>();
|
||||||
|
List<MessageError> vErrors = new List<MessageError>();
|
||||||
|
Dictionary<Message, MessageValidationCounts> counts = new Dictionary<Message, MessageValidationCounts>();
|
||||||
|
|
||||||
RuleEngine ruleEngine = new RuleEngine();
|
RuleEngine ruleEngine = new RuleEngine();
|
||||||
foreach (Message aMessage in _messages)
|
foreach (Message aMessage in messagesSnapshot)
|
||||||
{
|
{
|
||||||
if (!aMessage.EvaluateForValidation(this.Core.IsTransit)) continue;
|
if (!aMessage.EvaluateForValidation(this.Core.IsTransit)) continue;
|
||||||
|
|
||||||
@ -800,20 +849,13 @@ namespace ENI2
|
|||||||
List<MessageViolation> violations = new List<MessageViolation>();
|
List<MessageViolation> violations = new List<MessageViolation>();
|
||||||
ruleEngine.ValidateMessage(aMessage, out errors, out violations);
|
ruleEngine.ValidateMessage(aMessage, out errors, out violations);
|
||||||
|
|
||||||
if (errors.Count > 0)
|
MessageValidationCounts messageCounts = new MessageValidationCounts
|
||||||
aMessage.ErrorCount = errors.Count;
|
|
||||||
else
|
|
||||||
aMessage.ErrorCount = null;
|
|
||||||
if (violations.Count > 0)
|
|
||||||
{
|
{
|
||||||
aMessage.ViolationCount = violations.Count;
|
ErrorCount = errors.Count > 0 ? (int?)errors.Count : null,
|
||||||
aMessage.PositionViolationCount = violations.Count(v => !v.Identifier.IsNullOrEmpty());
|
ViolationCount = violations.Count > 0 ? (int?)violations.Count : null,
|
||||||
}
|
PositionViolationCount = violations.Count > 0 ? (int?)violations.Count(v => !v.Identifier.IsNullOrEmpty()) : null
|
||||||
else
|
};
|
||||||
{
|
counts[aMessage] = messageCounts;
|
||||||
aMessage.ViolationCount = null;
|
|
||||||
aMessage.PositionViolationCount = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
string messageGroup = this.MessageGroupForMessage(aMessage);
|
string messageGroup = this.MessageGroupForMessage(aMessage);
|
||||||
|
|
||||||
@ -831,20 +873,20 @@ namespace ENI2
|
|||||||
|
|
||||||
#region 12.11.18 / 6.3.21 / 23.5.22 / 26.10.24: globale Plausi-Prüfungen
|
#region 12.11.18 / 6.3.21 / 23.5.22 / 26.10.24: globale Plausi-Prüfungen
|
||||||
|
|
||||||
Message crewaMessage = _messages.Find(message => message.MessageNotificationClass == Message.NotificationClass.CREWA);
|
Message crewaMessage = messagesSnapshot.Find(message => message.MessageNotificationClass == Message.NotificationClass.CREWA);
|
||||||
Message crewdMessage = _messages.Find(message => message.MessageNotificationClass == Message.NotificationClass.CREWD);
|
Message crewdMessage = messagesSnapshot.Find(message => message.MessageNotificationClass == Message.NotificationClass.CREWD);
|
||||||
Message pasaMessage = _messages.Find(message => message.MessageNotificationClass == Message.NotificationClass.PASA);
|
Message pasaMessage = messagesSnapshot.Find(message => message.MessageNotificationClass == Message.NotificationClass.PASA);
|
||||||
Message pasdMessage = _messages.Find(message => message.MessageNotificationClass == Message.NotificationClass.PASD);
|
Message pasdMessage = messagesSnapshot.Find(message => message.MessageNotificationClass == Message.NotificationClass.PASD);
|
||||||
Message pobaMessage = _messages.Find(message => message.MessageNotificationClass == Message.NotificationClass.POBA);
|
Message pobaMessage = messagesSnapshot.Find(message => message.MessageNotificationClass == Message.NotificationClass.POBA);
|
||||||
Message pobdMessage = _messages.Find(message => message.MessageNotificationClass == Message.NotificationClass.POBD);
|
Message pobdMessage = messagesSnapshot.Find(message => message.MessageNotificationClass == Message.NotificationClass.POBD);
|
||||||
Message secMessage = _messages.Find(message => message.MessageNotificationClass == Message.NotificationClass.SEC);
|
Message secMessage = messagesSnapshot.Find(message => message.MessageNotificationClass == Message.NotificationClass.SEC);
|
||||||
Message noanodMessage = _messages.Find(message => message.MessageNotificationClass == Message.NotificationClass.NOA_NOD);
|
Message noanodMessage = messagesSnapshot.Find(message => message.MessageNotificationClass == Message.NotificationClass.NOA_NOD);
|
||||||
Message mdhMessage = _messages.Find(message => message.MessageNotificationClass == Message.NotificationClass.MDH);
|
Message mdhMessage = messagesSnapshot.Find(message => message.MessageNotificationClass == Message.NotificationClass.MDH);
|
||||||
Message was_rcptMessage = _messages.Find(message => message.MessageNotificationClass == Message.NotificationClass.WAS_RCPT);
|
Message was_rcptMessage = messagesSnapshot.Find(message => message.MessageNotificationClass == Message.NotificationClass.WAS_RCPT);
|
||||||
Message wasMessage = _messages.Find(message => message.MessageNotificationClass == Message.NotificationClass.WAS);
|
Message wasMessage = messagesSnapshot.Find(message => message.MessageNotificationClass == Message.NotificationClass.WAS);
|
||||||
Message servMessage = _messages.Find(message => message.MessageNotificationClass == Message.NotificationClass.SERV);
|
Message servMessage = messagesSnapshot.Find(message => message.MessageNotificationClass == Message.NotificationClass.SERV);
|
||||||
Message statMessage = _messages.Find(message => message.MessageNotificationClass == Message.NotificationClass.STAT);
|
Message statMessage = messagesSnapshot.Find(message => message.MessageNotificationClass == Message.NotificationClass.STAT);
|
||||||
Message pre72hMessage = _messages.Find(message => message.MessageNotificationClass == Message.NotificationClass.PRE72H);
|
Message pre72hMessage = messagesSnapshot.Find(message => message.MessageNotificationClass == Message.NotificationClass.PRE72H);
|
||||||
|
|
||||||
#region CREW / PAS Count Plausibility
|
#region CREW / PAS Count Plausibility
|
||||||
|
|
||||||
@ -984,22 +1026,6 @@ namespace ENI2
|
|||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region 4.1.23 no CREW effects warning for DE
|
|
||||||
if (crewaMessage != null)
|
|
||||||
{
|
|
||||||
MessageViolation mv = crewaMessage.ViolationList.Find((x) => x.PropertyName.Equals("Effects") && (x.ViolationCode == (int)ValidationCode.TRUNCATE));
|
|
||||||
if ((mv != null) && !Core.IsDK)
|
|
||||||
crewaMessage.ViolationList.Remove(mv);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(crewdMessage != null)
|
|
||||||
{
|
|
||||||
MessageViolation mvd = crewdMessage.ViolationList.Find((x) => x.PropertyName.Equals("Effects") && (x.ViolationCode == (int)ValidationCode.TRUNCATE));
|
|
||||||
if ((mvd != null) && !Core.IsDK)
|
|
||||||
crewdMessage.ViolationList.Remove(mvd);
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region WAS_RCPT double numbers
|
#region WAS_RCPT double numbers
|
||||||
|
|
||||||
Dictionary<string, string> identDict = new Dictionary<string, string>();
|
Dictionary<string, string> identDict = new Dictionary<string, string>();
|
||||||
@ -1337,17 +1363,8 @@ namespace ENI2
|
|||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
foreach (MessageError me in vErrors)
|
|
||||||
{
|
|
||||||
this.highlightService.HighlightError(me, this.GetContainerForMessageGroupName(me.MessageGroupName));
|
|
||||||
}
|
|
||||||
foreach (MessageViolation mv in vViolations)
|
|
||||||
{
|
|
||||||
this.highlightService.HighlightViolation(mv, this.GetContainerForMessageGroupName(mv.MessageGroupName));
|
|
||||||
}
|
|
||||||
|
|
||||||
// "neue" regelbasierte Validierung: Hier werden die einzelnen Regeln geprüft.
|
// "neue" regelbasierte Validierung: Hier werden die einzelnen Regeln geprüft.
|
||||||
bsmd.database.ValidationRule.PrepareNameLookupDict(this.Core, this._messages);
|
bsmd.database.ValidationRule.PrepareNameLookupDict(this.Core, messagesSnapshot);
|
||||||
|
|
||||||
List<bsmd.database.ValidationRule> validationRules = DBManager.Instance.GetValidationRules();
|
List<bsmd.database.ValidationRule> validationRules = DBManager.Instance.GetValidationRules();
|
||||||
|
|
||||||
@ -1374,10 +1391,34 @@ namespace ENI2
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return new ValidationResult(vViolations, vErrors, counts);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ApplyValidationResult(ValidationResult result, bool showMessages)
|
||||||
|
{
|
||||||
|
// TODO: clear highlighting
|
||||||
|
foreach (KeyValuePair<Message, MessageValidationCounts> entry in result.Counts)
|
||||||
|
{
|
||||||
|
Message aMessage = entry.Key;
|
||||||
|
MessageValidationCounts messageCounts = entry.Value;
|
||||||
|
aMessage.ErrorCount = messageCounts.ErrorCount;
|
||||||
|
aMessage.ViolationCount = messageCounts.ViolationCount;
|
||||||
|
aMessage.PositionViolationCount = messageCounts.PositionViolationCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (MessageError me in result.Errors)
|
||||||
|
{
|
||||||
|
this.highlightService.HighlightError(me, this.GetContainerForMessageGroupName(me.MessageGroupName));
|
||||||
|
}
|
||||||
|
foreach (MessageViolation mv in result.Violations)
|
||||||
|
{
|
||||||
|
this.highlightService.HighlightViolation(mv, this.GetContainerForMessageGroupName(mv.MessageGroupName));
|
||||||
|
}
|
||||||
|
|
||||||
if (showMessages)
|
if (showMessages)
|
||||||
{
|
{
|
||||||
// Show error and violation dialog
|
// Show error and violation dialog
|
||||||
if (vErrors.Count > 0)
|
if (result.Errors.Count > 0)
|
||||||
{
|
{
|
||||||
if(this._errorListDialog == null)
|
if(this._errorListDialog == null)
|
||||||
{
|
{
|
||||||
@ -1392,10 +1433,10 @@ namespace ENI2
|
|||||||
{
|
{
|
||||||
this._errorListDialog.BringUp();
|
this._errorListDialog.BringUp();
|
||||||
}
|
}
|
||||||
this._errorListDialog.Errors = vErrors;
|
this._errorListDialog.Errors = result.Errors;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (vViolations.Count > 0)
|
if (result.Violations.Count > 0)
|
||||||
{
|
{
|
||||||
if(this._violationListDialog == null)
|
if(this._violationListDialog == null)
|
||||||
{
|
{
|
||||||
@ -1410,17 +1451,58 @@ namespace ENI2
|
|||||||
{
|
{
|
||||||
this._violationListDialog.BringUp();
|
this._violationListDialog.BringUp();
|
||||||
}
|
}
|
||||||
_violationListDialog.Violations = vViolations;
|
_violationListDialog.Violations = result.Violations;
|
||||||
}
|
}
|
||||||
|
|
||||||
if((vErrors.Count == 0) && (vViolations.Count == 0))
|
if((result.Errors.Count == 0) && (result.Violations.Count == 0))
|
||||||
{
|
{
|
||||||
MessageBox.Show(Properties.Resources.textValidationOK, Properties.Resources.textValidation, MessageBoxButton.OK, MessageBoxImage.Information);
|
MessageBox.Show(Properties.Resources.textValidationOK, Properties.Resources.textValidation, MessageBoxButton.OK, MessageBoxImage.Information);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void ApplyCrewEffectsWarningSuppression()
|
||||||
|
{
|
||||||
|
// 4.1.23 no CREW effects warning for DE
|
||||||
|
Message crewaMessage = _messages.Find(message => message.MessageNotificationClass == Message.NotificationClass.CREWA);
|
||||||
|
Message crewdMessage = _messages.Find(message => message.MessageNotificationClass == Message.NotificationClass.CREWD);
|
||||||
|
|
||||||
|
if (crewaMessage != null)
|
||||||
|
{
|
||||||
|
MessageViolation mv = crewaMessage.ViolationList.Find((x) => x.PropertyName.Equals("Effects") && (x.ViolationCode == (int)ValidationCode.TRUNCATE));
|
||||||
|
if ((mv != null) && !Core.IsDK)
|
||||||
|
crewaMessage.ViolationList.Remove(mv);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(crewdMessage != null)
|
||||||
|
{
|
||||||
|
MessageViolation mvd = crewdMessage.ViolationList.Find((x) => x.PropertyName.Equals("Effects") && (x.ViolationCode == (int)ValidationCode.TRUNCATE));
|
||||||
|
if ((mvd != null) && !Core.IsDK)
|
||||||
|
crewdMessage.ViolationList.Remove(mvd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private sealed class ValidationResult
|
||||||
|
{
|
||||||
|
internal ValidationResult(List<MessageViolation> violations, List<MessageError> errors, Dictionary<Message, MessageValidationCounts> counts)
|
||||||
|
{
|
||||||
|
Violations = violations;
|
||||||
|
Errors = errors;
|
||||||
|
Counts = counts;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal List<MessageViolation> Violations { get; }
|
||||||
|
internal List<MessageError> Errors { get; }
|
||||||
|
internal Dictionary<Message, MessageValidationCounts> Counts { get; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private sealed class MessageValidationCounts
|
||||||
|
{
|
||||||
|
internal int? ErrorCount { get; set; }
|
||||||
|
internal int? ViolationCount { get; set; }
|
||||||
|
internal int? PositionViolationCount { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
private void _errorListDialog_RefreshClicked()
|
private void _errorListDialog_RefreshClicked()
|
||||||
{
|
{
|
||||||
DetailControl_RequestValidate(true);
|
DetailControl_RequestValidate(true);
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user