git_bsmd/nsw/Source/bsmd.hisnord/Response.cs

196 lines
11 KiB
C#

// Copyright (c) 2015-2017 schick Informatik
// Description: Bearbeitung von Antworten (dateibasiert..)
using bsmd.database;
using System;
using System.Collections.Generic;
using System.IO;
using log4net;
using System.Xml.Linq;
namespace bsmd.hisnord
{
public class Response
{
private static ILog _log = LogManager.GetLogger(typeof(Response));
public static void ReadAnswers()
{
foreach (string answerFile in Directory.GetFiles(Properties.Settings.Default.AnswerDir))
{
bool isOK = true;
// Informationen aus dem Dateinamen
// Meldetyp_Referenz_ID_Timestamp.xml
string bareFileName = Path.GetFileNameWithoutExtension(answerFile);
string[] fileNameElems = bareFileName.Split('_');
if (fileNameElems.Length < 4)
{
_log.WarnFormat("ANSWER file {0}.xml has an invalid file name", bareFileName);
isOK = false;
}
else
{
int prozessStatus;
if (!Int32.TryParse(fileNameElems[fileNameElems.Length - 1], out prozessStatus))
{
_log.WarnFormat("ANSWER file {0}.xml has no process status at the end (2..6)", bareFileName);
isOK = false;
}
else
{
long timestampMilliSecs;
if (!Int64.TryParse(fileNameElems[fileNameElems.Length - 2], out timestampMilliSecs))
{
_log.WarnFormat("ANSWER file {0}.xml has no readable timestamp", bareFileName);
isOK = false;
}
else
{
string refId = fileNameElems[fileNameElems.Length - 3];
string meldeTyp = fileNameElems[fileNameElems.Length - 4];
if (fileNameElems.Length == 5)
meldeTyp = string.Format("{0}_{1}", fileNameElems[fileNameElems.Length - 5], meldeTyp);
// TODO: klären was man hier liest: reguläre Antwort oder Schnittstellenfehler
// XML Linq statt Serialisierung
try
{
XElement xml = XElement.Load(answerFile);
// declare Namespaces
XNamespace ns1 = "http://api.national-single-window.de/visitIdRequest";
XNamespace ns6 = "http://api.national-single-window.de/receipt";
//XNamespace ns15 = "http://api.national-single-window.de/statusForClientRequestId";
XNamespace soap = "http://schemas.xmlsoap.org/soap/envelope/";
XNamespace ns15 = "http://api.national-single-window.de/visitIdResponse";
if (xml.Name == "SystemError")
{
// Fehlernachricht
SystemError systemError = SystemError.createFromXml(xml);
if (systemError != null)
{
MessageCore aCore = DBManager.Instance.GetMessageCoreById(systemError.MessageCoreId);
if (aCore != null)
{
_log.InfoFormat("SystemError received for Core [{0}], IMO {1} ETA {2}: {3}", aCore.Id, aCore.IMO, aCore.ETADisplay, systemError.ErrorMessage);
}
else
{
_log.WarnFormat("SystemError received for unknown core {0}: {1}", systemError.MessageCoreId, systemError.ErrorMessage);
}
// trotzdem immer speichern
DBManager.Instance.Save(systemError);
}
}
else
{
// NSW Rückmeldung
NSWResponse nswResponse = new NSWResponse(xml);
// Rückmeldung auswerten
if (nswResponse.MessageCoreId.HasValue)
{
MessageCore core = DBManager.Instance.GetMessageCoreById(nswResponse.MessageCoreId.Value);
if (core != null)
{
List<Message> messages = DBManager.Instance.GetMessagesForCore(core, DBManager.MessageLoad.ALL);
if(nswResponse.NotificationClass == Message.NotificationClass.VISIT)
{
if ((nswResponse.Status == "ACCEPTED") && !nswResponse.VisitId.IsNullOrEmpty())
core.VisitId = nswResponse.VisitId;
}
if(nswResponse.NotificationClass == Message.NotificationClass.TRANSIT)
{
if ((nswResponse.Status == "ACCEPTED") && !nswResponse.TransitId.IsNullOrEmpty())
core.TransitId = nswResponse.TransitId;
}
core.BSMDStatusInternal = MessageCore.BSMDStatus.RESPONDED;
DBManager.Instance.Save(core);
// now find the message that was meant..
foreach (Message aMessage in messages)
{
if (aMessage.MessageNotificationClass == nswResponse.NotificationClass)
{
if (nswResponse.Status != null)
{
bool isAccepted = (nswResponse.Status == "ACCEPTED");
aMessage.Status = isAccepted ? Message.MessageStatus.ACCEPTED : Message.MessageStatus.REJECTED;
aMessage.InternalStatus = isAccepted ? Message.BSMDStatus.CONFIRMED : Message.BSMDStatus.ERROR;
DBManager.Instance.Save(aMessage);
}
#region Error / Violation handling
foreach (MessageError existingError in aMessage.ErrorList)
DBManager.Instance.Delete(existingError);
foreach (MessageViolation existingViolation in aMessage.ViolationList)
DBManager.Instance.Delete(existingViolation);
foreach (MessageError messageError in nswResponse.Errors)
{
messageError.MessageHeaderId = aMessage.Id.Value;
messageError.MessageHeader = aMessage;
DBManager.Instance.Save(messageError);
}
foreach (MessageViolation messageViolation in nswResponse.Violations)
{
messageViolation.MessageHeaderId = aMessage.Id.Value;
messageViolation.MessageHeader = aMessage;
DBManager.Instance.Save(messageViolation);
}
#endregion
}
}
}
else
{
_log.ErrorFormat("cannot find core for id {0}", nswResponse.MessageCoreId);
}
}
else
{
_log.ErrorFormat("received response without suitable conveyance code, request id {0}", nswResponse.ClientRequestId);
isOK = false;
}
}
}
catch(Exception ex)
{
_log.WarnFormat("Exception deserializing ANSWER file: {0}", ex.ToString());
isOK = false;
}
}
}
}
if(isOK)
{
// archive file
File.Move(answerFile, Path.Combine(Properties.Settings.Default.AnswerArchiveDir, Path.GetFileName(answerFile)));
}
else
{
// save in separate folder (to look at it later?)
File.Move(answerFile, Path.Combine(Properties.Settings.Default.AnswerCorruptDir, Path.GetFileName(answerFile)));
}
}
}
}
}