// // Class: Response // Current CLR: 4.0.30319.34209 // System: Microsoft Visual Studio 10.0 // Author: dani // Created: 3/1/2015 8:12:08 PM // // Copyright (c) 2015 Informatikbüro Daniel Schick. All rights reserved. using System; using System.Collections.Generic; using bsmd.database; using log4net; using System.IO; using System.Xml.Serialization; namespace bsmd.dbh { public class Response { private static readonly ILog _log = LogManager.GetLogger("dbh Response"); public static void ProcessResponse(string VisitId, string TransitId, DateTime Timestamp, string SenderReference, response.RootType Type, bsmd.dbh.response.Message[] Messages, bsmd.dbh.response.RootReportingClassesFull ReportingClassesFull, bsmd.dbh.response.RootReportingClassesPartial ReportingClassesPartial, bsmd.dbh.response.RootReportingClassesError ReportingClassesError, bsmd.dbh.response.RootReportingClassesResetted ReportingClassesResetted, bsmd.dbh.response.RootReportingClassesNoChanges ReportingClassesNoChanges, string connectionString) { /* XmlSerializer serializer = new XmlSerializer(typeof(response.Root)); using(StringWriter textWriter = new StringWriter()) { serializer.Serialize(textWriter, aResponse); _log.Debug(textWriter.ToString()); } */ // _log.Debug(aResponse.Serialize()); if (DBManager.Instance.Connect(connectionString)) { _log.DebugFormat("Start PROCESS, Timestamp: {0}", Timestamp); if (!Guid.TryParseExact(SenderReference, "N", out Guid messageId)) { _log.WarnFormat("SenderReference {0} is not a guid, skipping message processing!", SenderReference); return; } DatabaseEntity dbEntity = DBManager.Instance.GetMessageById(messageId); Message aMessage = dbEntity as Message; if (aMessage != null) { _log.InfoFormat("Message type {0} found for SenderReference {1}", ((Message)dbEntity).MessageNotificationClassDisplay, messageId); foreach (MessageError existingError in aMessage.ErrorList) DBManager.Instance.Delete(existingError); } if (dbEntity == null) { MessageCore aCore = DBManager.Instance.GetMessageCoreById(messageId); if ((aCore != null) && (Type == response.RootType.CANCEL)) { _log.InfoFormat("Cancel confirmation received for {0} ({1})", aCore.Id, aCore.DisplayId); aCore.BSMDStatusInternal = MessageCore.BSMDStatus.RESPONDED; aCore.Cancelled = true; DBManager.Instance.Save(aCore); return; } } if (dbEntity == null) { _log.WarnFormat("Message / Core with ID {0} not found in database, skipping", messageId); return; } if (!(dbEntity is Message) && (Type != dbh.response.RootType.CANCEL)) { _log.WarnFormat("SenderReference DB Entity Object is no MessageHeader, aborting ({0})", dbEntity.GetType()); return; } switch (Type) { case dbh.response.RootType.VISIT: _log.InfoFormat("Visit-Id received: {0}", VisitId ?? "??!"); if(!VisitId.IsNullOrEmpty()) aMessage.MessageCore.VisitId = VisitId; aMessage.MessageCore.BSMDStatusInternal = MessageCore.BSMDStatus.PREPARE; aMessage.SendSuccess = true; DBManager.Instance.Save(aMessage.MessageCore); aMessage.InternalStatus = Message.BSMDStatus.CONFIRMED; DBManager.Instance.Save(aMessage); break; case dbh.response.RootType.TRANSIT: _log.InfoFormat("Transit-Id received: {0}", TransitId ?? "??!"); aMessage.MessageCore.TransitId = TransitId; aMessage.MessageCore.BSMDStatusInternal = MessageCore.BSMDStatus.PREPARE; aMessage.SendSuccess = true; DBManager.Instance.Save(aMessage.MessageCore); aMessage.InternalStatus = Message.BSMDStatus.CONFIRMED; DBManager.Instance.Save(aMessage); break; case dbh.response.RootType.RESET: // Die Liste ist auch bei erfolgtem RESET offenbar immer NULL... //if ((ReportingClassesResetted != null) && (ReportingClassesResetted.Count > 0)) // das Mapping stimmt bei uns natürlich so nicht, aber da die Nachrichten einzeln gehen sollte es trotzdem funktionieren // (int) ReportingClassesResetted[0].ReportingClass[0] == (int)aMessage.MessageNotificationClass) //{ //_log.InfoFormat("RESET response received for {0}", ReportingClassesResetted[0].ReportingClass[0]); aMessage.Reset = true; aMessage.SendSuccess = false; // zurücksetzen des "grünen Punkts" im ENI-2 aMessage.InternalStatus = Message.BSMDStatus.CONFIRMED; //} break; case dbh.response.RootType.DATA: if(ReportingClassesFull?.ReportingClass.Length > 0) { // this was successful, save status to MessageHeader aMessage.SendSuccess = true; aMessage.InternalStatus = Message.BSMDStatus.CONFIRMED; aMessage.Status = Message.MessageStatus.ACCEPTED; _log.InfoFormat("full message class accepted"); } if (ReportingClassesPartial?.ReportingClass.Length > 0) { // this was successful, save status to MessageHeader aMessage.SendSuccess = true; aMessage.InternalStatus = Message.BSMDStatus.ERROR; aMessage.Status = Message.MessageStatus.ACCEPTED; _log.InfoFormat("partial message class accepted"); } if (ReportingClassesError?.ReportingClass.Length > 0) { // this was successful, save status to MessageHeader aMessage.SendSuccess = true; aMessage.InternalStatus = Message.BSMDStatus.ERROR; aMessage.Status = Message.MessageStatus.ACCEPTED; _log.InfoFormat("message class accepted but error"); } if(ReportingClassesNoChanges?.ReportingClass.Length > 0) { // this was successful, yet unnecessary ;-) aMessage.SendSuccess = true; aMessage.InternalStatus = Message.BSMDStatus.CONFIRMED; aMessage.Status = Message.MessageStatus.ACCEPTED; _log.InfoFormat("message accepted, data was unchanged"); } bool isReset = false; if(ReportingClassesResetted?.ReportingClass.Length > 0) { aMessage.SendSuccess = false; aMessage.InternalStatus = Message.BSMDStatus.CONFIRMED; aMessage.Status = Message.MessageStatus.ACCEPTED; isReset = true; _log.InfoFormat("RESET successful for message"); } if (isReset && !aMessage.Reset) aMessage.Reset = isReset; // check the whole thing for completion MessageCore core = DBManager.Instance.GetMessageCoreById(aMessage.MessageCoreId.Value); bool stillSomethingSent = false; foreach(Message message in DBManager.Instance.GetMessagesForCore(core, DBManager.MessageLoad.ALL)) { if (aMessage.Id.Value == message.Id.Value) continue; if(message.InternalStatus == Message.BSMDStatus.SENT) { stillSomethingSent = true; break; } } if(!stillSomethingSent && (core.BSMDStatusInternal == MessageCore.BSMDStatus.SENT)) { core.BSMDStatusInternal = MessageCore.BSMDStatus.RESPONDED; DBManager.Instance.Save(core); } break; } if (Messages != null) { // Status zu den jeweiligen Nachrichten. Bei uns sollte die Anzahl hier immer 1 sein, da wir die Dinger // einzeln verschicken. for (int i = 0; i < Messages.Length; i++) { _log.InfoFormat("message {0} type {1}: {2}", i, Messages[i].Type, Messages[i].Text ?? "null"); bool hasCode = Int32.TryParse(Messages[i].ID, out int code); switch (Messages[i].Type) { case dbh.response.RootMessageType.ERROR: MessageError error = new MessageError(); error.ErrorText = Messages[i].Text; if (hasCode) error.ErrorCode = code; _log.WarnFormat("Error received for {0}: {1}", Messages[i].Type, error.ErrorText); error.MessageHeaderId = aMessage.Id.Value; aMessage.InternalStatus = Message.BSMDStatus.ERROR; aMessage.StatusInfo = string.Format("Id:{0} Loc:{1} - {2}", Messages[i].ID, Messages[i].Location, Messages[i].Text); DBManager.Instance.Save(error); aMessage.SendSuccess = false; break; case dbh.response.RootMessageType.VIOLATION: MessageViolation violation = new MessageViolation(); violation.ViolationText = Messages[i].Text; if (hasCode) violation.ViolationCode = code; _log.WarnFormat("Violation received for {0}: {1}", Messages[i].Type, violation.ViolationText); violation.MessageHeaderId = aMessage.Id.Value; aMessage.InternalStatus = Message.BSMDStatus.VIOLATION; aMessage.StatusInfo = string.Format("Id:{0} Loc:{1} - {2}", Messages[i].ID, Messages[i].Location, Messages[i].Text); aMessage.SendSuccess = true; DBManager.Instance.Save(violation); break; case dbh.response.RootMessageType.WARNING: _log.InfoFormat("WARNING received for {0}: {1}", Messages[i].Type, Messages[i].Text); aMessage.StatusInfo = string.Format("Id:{0} Loc:{1} - {2}", Messages[i].ID, Messages[i].Location, Messages[i].Text); aMessage.SendSuccess = true; break; case dbh.response.RootMessageType.INFO: default: _log.InfoFormat("INFO received for {0}: {1}", Messages[i].Type, Messages[i].Text); aMessage.StatusInfo = string.Format("Id:{0} Loc:{1} - {2}", Messages[i].ID, Messages[i].Location, Messages[i].Text); aMessage.SendSuccess = true; break; } if (aMessage.Reset) aMessage.SendSuccess = false; // Send flag zurücksetzen } } aMessage.ReceivedAt = DateTime.Now; DBManager.Instance.Save(aMessage); DBManager.Instance.Disconnect(); } else { _log.Fatal("cannot connect to database"); } } } }