stattdessen wird ein open command gesendet. Gleichzeitig wird die Ausgabe nicht mehr zum Ende gelesen sondern per Events abgefragt. Die Hoffnung ist hier, dass der Prozess nicht mehr auf dem ReadToEnd() blockiert, wobei das nie bestätigt werden konnte.
204 lines
9.6 KiB
C#
204 lines
9.6 KiB
C#
// Copyright (c) 2020-present schick Informatik
|
|
// Description: Verarbeitung von empfangenen Rückmeldungen
|
|
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Text.RegularExpressions;
|
|
using System.Threading.Tasks;
|
|
using System.Xml.Serialization;
|
|
using log4net;
|
|
using bsmd.database;
|
|
|
|
namespace bsmd.dbh
|
|
{
|
|
internal static class ResponseUtil
|
|
{
|
|
private static readonly ILog _log = LogManager.GetLogger(typeof(ResponseUtil));
|
|
private static readonly Regex _regexFilename = new Regex(@".*NSW\.DBH\.BSMD(MAERSK)?\.(.*)\.xml");
|
|
|
|
internal static bool Read(string inputFile)
|
|
{
|
|
bool result = false;
|
|
if(!inputFile.EndsWith(".xml", StringComparison.OrdinalIgnoreCase))
|
|
{
|
|
_log.ErrorFormat("no xml file: {0}", inputFile);
|
|
return result;
|
|
}
|
|
|
|
Match m = _regexFilename.Match(inputFile);
|
|
if(!m.Success) {
|
|
_log.WarnFormat("returned file doesn't follow naming convention NSW.DBH.BSMD(MAERSK)?.*:{0}", inputFile);
|
|
return result;
|
|
}
|
|
|
|
// Achtung! Die laufende Nummer der rücklaufenden Datei ist _nicht_ dieselbe und kann zur Identifikation der Meldeklasse
|
|
// nicht verwendet werden
|
|
|
|
string fileSeqString = m.Groups[2].Value;
|
|
|
|
if(!Int32.TryParse(fileSeqString, out int fileSeqNum))
|
|
{
|
|
_log.ErrorFormat("matched file sequence number couldn't be parsed: {0}", fileSeqString);
|
|
return result;
|
|
}
|
|
|
|
bsmd.dbh.Response.Root root = null;
|
|
try
|
|
{
|
|
XmlSerializer serializer = new XmlSerializer(typeof(bsmd.dbh.Response.Root));
|
|
using (Stream s = new FileStream(inputFile, FileMode.Open))
|
|
{
|
|
root = (bsmd.dbh.Response.Root) serializer.Deserialize(s);
|
|
}
|
|
|
|
Message sentMessage = null;
|
|
MessageCore aCore = null;
|
|
|
|
if(Guid.TryParse(root.SenderReference, out Guid refGuid))
|
|
{
|
|
// load message(s?) by file seq string
|
|
sentMessage = DBManager.Instance.GetMessageById(refGuid) as Message;
|
|
if (sentMessage == null)
|
|
{
|
|
_log.ErrorFormat("cannot find a message for file sequence number {0}", fileSeqNum);
|
|
return result;
|
|
}
|
|
|
|
aCore = DBManager.Instance.GetMessageCoreById(sentMessage.MessageCoreId.Value);
|
|
if (aCore == null)
|
|
{
|
|
_log.ErrorFormat("There is no core with id {0}", sentMessage.MessageCoreId.Value);
|
|
return result;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
_log.ErrorFormat("sender ref {0} is no guid", root.SenderReference);
|
|
return result;
|
|
}
|
|
|
|
switch(root.Type)
|
|
{
|
|
case Response.RootType.VISIT:
|
|
if (aCore.VisitId.IsNullOrEmpty() && !root.VisitId.IsNullOrEmpty())
|
|
{
|
|
aCore.VisitId = root.VisitId;
|
|
sentMessage.SendSuccess = true;
|
|
sentMessage.Status = Message.MessageStatus.ACCEPTED;
|
|
sentMessage.InternalStatus = Message.BSMDStatus.CONFIRMED;
|
|
_log.InfoFormat("Received Visit-Id {0} for core {1}", root.VisitId, aCore.Id);
|
|
}
|
|
break;
|
|
case Response.RootType.TRANSIT:
|
|
if (aCore.TransitId.IsNullOrEmpty() && !root.TransitId.IsNullOrEmpty())
|
|
{
|
|
aCore.TransitId = root.TransitId;
|
|
sentMessage.SendSuccess = true;
|
|
sentMessage.Status = Message.MessageStatus.ACCEPTED;
|
|
sentMessage.InternalStatus = Message.BSMDStatus.CONFIRMED;
|
|
_log.InfoFormat("Received Transit-Id {0} for core {1}", root.TransitId, aCore.Id);
|
|
}
|
|
break;
|
|
case Response.RootType.DATA:
|
|
if(root.ReportingClassesFull?.ReportingClass.Length > 0)
|
|
{
|
|
_log.InfoFormat("Message {0} confirmed (full), {1} messages", sentMessage.MessageNotificationClassDisplay, root.Messages?.Length);
|
|
sentMessage.SendSuccess = true;
|
|
sentMessage.Status = Message.MessageStatus.ACCEPTED;
|
|
sentMessage.InternalStatus = Message.BSMDStatus.CONFIRMED;
|
|
}
|
|
if (root.ReportingClassesPartial?.ReportingClass.Length > 0)
|
|
{
|
|
_log.WarnFormat("Message {0} confirmed (partial), {1} messages", sentMessage.MessageNotificationClassDisplay, root.Messages?.Length);
|
|
sentMessage.SendSuccess = true;
|
|
sentMessage.Status = Message.MessageStatus.ACCEPTED;
|
|
sentMessage.InternalStatus = Message.BSMDStatus.VIOLATION;
|
|
}
|
|
if (root.ReportingClassesError?.ReportingClass.Length > 0)
|
|
{
|
|
_log.ErrorFormat("Message {0} rejected, {1} messages", sentMessage.MessageNotificationClassDisplay, root.Messages?.Length);
|
|
sentMessage.SendSuccess = false;
|
|
sentMessage.Status = Message.MessageStatus.REJECTED;
|
|
sentMessage.InternalStatus = Message.BSMDStatus.ERROR;
|
|
sentMessage.StatusInfo = "Errors reported";
|
|
}
|
|
break;
|
|
case Response.RootType.RESET:
|
|
if(root.ReportingClassesResetted?.ReportingClass.Length > 0)
|
|
{
|
|
_log.InfoFormat("Message {0} RESET confirmed, {1} messages", sentMessage.MessageNotificationClassDisplay, root.Messages.Length);
|
|
sentMessage.SendSuccess = false; // bestätigter Reset setzt grünen Buppel zurück
|
|
sentMessage.Status = Message.MessageStatus.ACCEPTED;
|
|
sentMessage.InternalStatus = Message.BSMDStatus.CONFIRMED;
|
|
}
|
|
break;
|
|
case Response.RootType.CANCEL:
|
|
_log.InfoFormat("Core {0} CANCEL confirmed", aCore.DisplayId);
|
|
aCore.BSMDStatusInternal = MessageCore.BSMDStatus.RESPONDED;
|
|
break;
|
|
}
|
|
|
|
// "alte" Meldungen entfernen
|
|
foreach (MessageError existingError in sentMessage.ErrorList)
|
|
DBManager.Instance.Delete(existingError);
|
|
|
|
foreach (MessageViolation existingViolation in sentMessage.ViolationList)
|
|
DBManager.Instance.Delete(existingViolation);
|
|
|
|
if (root.Messages != null)
|
|
{
|
|
foreach (Response.RootMessage rootMessage in root.Messages)
|
|
{
|
|
_log.InfoFormat("Message[{0}]: {1} {2} {3}", rootMessage.ID, rootMessage.Type, rootMessage.Location, rootMessage.Text);
|
|
switch (rootMessage.Type)
|
|
{
|
|
case Response.RootMessageType.ERROR:
|
|
MessageError me = new MessageError();
|
|
me.MessageHeaderId = sentMessage.Id.Value;
|
|
me.MessageHeader = sentMessage;
|
|
me.ErrorText = rootMessage.Text;
|
|
DBManager.Instance.Save(me);
|
|
break;
|
|
case Response.RootMessageType.VIOLATION:
|
|
MessageViolation mv = new MessageViolation();
|
|
mv.MessageHeaderId = sentMessage.Id.Value;
|
|
mv.MessageHeader = sentMessage;
|
|
mv.ViolationText = rootMessage.Text;
|
|
DBManager.Instance.Save(mv);
|
|
break;
|
|
case Response.RootMessageType.XSD_ERROR:
|
|
// TODO
|
|
break;
|
|
case Response.RootMessageType.INFO:
|
|
// TODO
|
|
break;
|
|
case Response.RootMessageType.WARNING:
|
|
// TODO
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
DBManager.Instance.Save(sentMessage);
|
|
|
|
if (!(aCore.Cancelled ?? false))
|
|
aCore.BSMDStatusInternal = MessageCore.BSMDStatus.RESPONDED;
|
|
|
|
DBManager.Instance.Save(aCore);
|
|
result = true;
|
|
}
|
|
|
|
catch(Exception ex)
|
|
{
|
|
_log.ErrorFormat("Failed to deserialize return message: {0}", ex.Message);
|
|
return result;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
}
|
|
}
|