// Copyright (c) 2015-2017 schick Informatik // Description: Hilfsklasse zur Bearbeitung der Antworten / HIS-Nord using System; using System.Collections.Generic; using System.Linq; using System.Xml.Linq; using bsmd.database; using log4net; namespace bsmd.hisnord { public class NSWResponse { private string _clientRequestId; private DateTime _receiveAt; private string _notificationId; private string _status; private string _visitId; private string _transitId; private Message.NotificationClass _notificationClass; private bool _isReset; private List _violations = new List(); private List _errors = new List(); private Guid? _messageCoreId; private ILog _log = LogManager.GetLogger(typeof(NSWResponse)); public NSWResponse(XElement xml) { XNamespace ns1 = "http://api.national-single-window.de/visitIdRequest"; XNamespace ns6 = "http://api.national-single-window.de/receipt"; XNamespace statusNS = "http://api.national-single-window.de/statusForClientRequestId"; XNamespace soap = "http://schemas.xmlsoap.org/soap/envelope/"; XNamespace ns15 = "http://api.national-single-window.de/visitIdResponse"; XNamespace ns16 = "http://api.national-single-window.de/transitIdResponse"; XNamespace resetNS = "http://api.national-single-window.de/reset"; XNamespace ladgNS = "http://api.national-single-window.de/ladg"; XNamespace hazaNS = "http://api.national-single-window.de/haza"; XNamespace hazdNS = "http://api.national-single-window.de/hazd"; XNamespace mdhNS = "http://api.national-single-window.de/mdh"; XNamespace agntNS = "http://api.national-single-window.de/agnt"; XNamespace vioNS = "http://api.national-single-window.de/violation"; XNamespace errNS = "http://api.national-single-window.de/error"; XNamespace secNS = "http://api.national-single-window.de/sec"; XNamespace statNS = "http://api.national-single-window.de/stat"; XNamespace noa_nodNS = "http://api.national-single-window.de/noanod"; XNamespace ataNS = "http://api.national-single-window.de/ata"; XNamespace atdNS = "http://api.national-single-window.de/atd"; XNamespace pobaNS = "http://api.national-single-window.de/poba"; XNamespace pobdNS = "http://api.national-single-window.de/pobd"; XNamespace nameNS = "http://api.national-single-window.de/name"; XNamespace tiefaNS = "http://api.national-single-window.de/tiefa"; XNamespace tiefdNS = "http://api.national-single-window.de/tiefd"; XNamespace bkraNS = "http://api.national-single-window.de/bkra"; XNamespace bkrdNS = "http://api.national-single-window.de/bkrd"; XNamespace infoNS = "http://api.national-single-window.de/info"; XNamespace servNS = "http://api.national-single-window.de/serv"; XNamespace pre72hNS = "http://api.national-single-window.de/pre72h"; XNamespace wasNS = "http://api.national-single-window.de/was"; XNamespace crewNS = "http://api.national-single-window.de/crew"; XNamespace pasNS = "http://api.national-single-window.de/pas"; XNamespace bpolNS = "http://api.national-single-window.de/bpol"; XNamespace towaNS = "http://api.national-single-window.de/towa"; XNamespace towdNS = "http://api.national-single-window.de/towd"; XNamespace cancelVisitNS = "http://api.national-single-window.de/visitIdCancelRequest"; XNamespace cancelTransitNS = "http://api.national-single-window.de/transitIdCancelRequest"; XName lookupName = "dontmatchmeplease"; XName idName = "ConveyanceCode"; var elem = xml.Descendants(idName); if (elem.Count() > 0) { Guid aGuid; if (Guid.TryParse(elem.FirstOrDefault()?.Value, out aGuid)) _messageCoreId = aGuid; else _log.WarnFormat("cannot parse ConveyanceCode {0}", elem.FirstOrDefault()); } else { _log.Warn("NSWResponse does not contain ConveyanceCode!!"); } XName meldeTypeName = "Meldetype"; var mElem = xml.Descendants(meldeTypeName); Message.NotificationClass? notificationClass = null; if(mElem.Count() > 0) { Message.NotificationClass tmpClass; if (Enum.TryParse(mElem.FirstOrDefault()?.Value, out tmpClass)) notificationClass = tmpClass; else { // könnte VISIT/TRANSIT Id Beantragung sein XName test = ns15 + "VisitIdResponse"; if (xml.Descendants(test).Count() > 0) { notificationClass = Message.NotificationClass.VISIT; } else { test = ns16 + "TransitIdResponse"; if (xml.Descendants(test).Count() > 0) notificationClass = Message.NotificationClass.TRANSIT; } if (!notificationClass.HasValue) { XName cancelVisit = cancelVisitNS + "CancelVisitIdResponse"; XName cancelTransit = cancelTransitNS + "CancelTransitIdResponse"; if (xml.Descendants(cancelVisit).Count() > 0) { lookupName = cancelVisit; notificationClass = Message.NotificationClass.STO; // HACK, es gibt keine Klasse für "Cancel" _log.WarnFormat("CANCEL VISIT, setting Not.Class to STO (experimental)"); _notificationClass = Message.NotificationClass.STO; } else if(xml.Descendants(cancelTransit).Count() > 0) { lookupName = cancelTransit; notificationClass = Message.NotificationClass.STO; // HACK, es gibt keine Klasse für "Cancel" _log.WarnFormat("CANCEL TRANSIT, setting Not.Class to STO (experimental)"); _notificationClass = Message.NotificationClass.STO; } else { _log.WarnFormat("NSWResponse does not contain Notification class"); } } } } // detect response type if(notificationClass.HasValue) { XName resetLookup = resetNS + "ResetResponse"; switch (notificationClass.Value) { case Message.NotificationClass.VISIT: lookupName = ns15 + "VisitIdResponse"; break; case Message.NotificationClass.TRANSIT: lookupName = ns16 + "TransitIdResponse"; break; case Message.NotificationClass.LADG: lookupName = ladgNS + "LADGResponse"; break; case Message.NotificationClass.HAZA: lookupName = hazaNS + "HAZAResponse"; break; case Message.NotificationClass.HAZD: lookupName = hazdNS + "HAZDResponse"; break; case Message.NotificationClass.MDH: lookupName = mdhNS + "MDHResponse"; break; case Message.NotificationClass.AGNT: lookupName = agntNS + "AGNTResponse"; break; case Message.NotificationClass.SEC: lookupName = secNS + "SECResponse"; break; case Message.NotificationClass.STAT: lookupName = statNS + "STATResponse"; break; case Message.NotificationClass.NOA_NOD: lookupName = noa_nodNS + "NOA_NODResponse"; break; case Message.NotificationClass.ATA: lookupName = ataNS + "ATAResponse"; break; case Message.NotificationClass.ATD: lookupName = atdNS + "ATDResponse"; break; case Message.NotificationClass.POBA: lookupName = pobaNS + "POBAResponse"; break; case Message.NotificationClass.POBD: lookupName = pobdNS + "POBDResponse"; break; case Message.NotificationClass.NAME: lookupName = nameNS + "NAMEResponse"; break; case Message.NotificationClass.TIEFA: lookupName = tiefaNS + "TIEFAResponse"; break; case Message.NotificationClass.TIEFD: lookupName = tiefdNS + "TIEFDResponse"; break; case Message.NotificationClass.BKRA: lookupName = bkraNS + "BKRAResponse"; break; case Message.NotificationClass.BKRD: lookupName = bkrdNS + "BKRDResponse"; break; case Message.NotificationClass.INFO: lookupName = infoNS + "INFOResponse"; break; case Message.NotificationClass.SERV: lookupName = servNS + "SERVResponse"; break; case Message.NotificationClass.PRE72H: lookupName = pre72hNS + "PRE72HResponse"; break; case Message.NotificationClass.WAS: lookupName = wasNS + "WASResponse"; break; case Message.NotificationClass.CREW: lookupName = crewNS + "CREWResponse"; break; case Message.NotificationClass.PAS: lookupName = pasNS + "PASResponse"; break; case Message.NotificationClass.BPOL: lookupName = bpolNS + "BPOLResponse"; break; case Message.NotificationClass.TOWA: lookupName = towaNS + "TOWAResponse"; break; case Message.NotificationClass.TOWD: lookupName = towdNS + "TOWDResponse"; break; default: break; } bool lookupMatch = (xml.Descendants(lookupName).Count() > 0); bool resetMatch = (xml.Descendants(resetLookup).Count() > 0); if(lookupMatch || resetMatch) { _isReset = resetMatch; _notificationClass = notificationClass.Value; // match found XName xname = ns6 + "ClientRequestId"; elem = xml.Descendants(xname); if (elem.Count() > 0) { _clientRequestId = elem.First()?.Value; } xname = ns6 + "ReceivedAt"; elem = xml.Descendants(xname); if(elem.Count() > 0) { DateTime.TryParse(elem.First()?.Value, out _receiveAt); } xname = ns6 + "NotificationId"; elem = xml.Descendants(xname); if (elem.Count() > 0) _notificationId = elem.First()?.Value; xname = ns6 + "Status"; elem = xml.Descendants(xname); if(elem.Count() > 0) { _status = elem.First()?.Value; } xname = ns6 + "VisitId"; elem = xml.Descendants(xname); if(elem.Count() > 0) { _visitId = elem.First()?.Value; } xname = ns6 + "TransitId"; elem = xml.Descendants(xname); if (elem.Count() > 0) { _transitId = elem.First()?.Value; } // check for violations ------------------------------------------- xname = ns6 + "Violation"; XName vCodeName = vioNS + "ViolationCode"; XName vTextName = vioNS + "ViolationText"; elem = xml.Descendants(xname); foreach(XElement anElem in elem) { MessageViolation mv = new MessageViolation(); int vCode = -1; if (!Int32.TryParse(anElem.Element(vCodeName).Value, out vCode)) _log.WarnFormat("cannot convert violation code to int: {0}", anElem.Element(vCodeName).Value); else mv.ViolationCode = vCode; mv.ViolationText = anElem.Element(vTextName).Value; _violations.Add(mv); } // check for errors ---------------------------------------------- xname = ns6 + "Error"; XName eCodeName = errNS + "ErrorCode"; XName eTextName = errNS + "ErrorText"; elem = xml.Descendants(xname); foreach (XElement anElem in elem) { MessageError me = new MessageError(); int eCode = -1; if (!Int32.TryParse(anElem.Element(eCodeName).Value, out eCode)) _log.WarnFormat("cannot convert error code to int: {0}", anElem.Element(eCodeName).Value); else me.ErrorCode = eCode; me.ErrorText = anElem.Element(eTextName).Value; _errors.Add(me); } } } } #region Properties public Guid? MessageCoreId { get { return _messageCoreId; } } public string ClientRequestId { get { return _clientRequestId; } } public DateTime? ReceiveAt { get { return _receiveAt; } } public string NotificationId { get { return _notificationId; } } public string Status { get { return this._status; } } public string VisitId { get { return this._visitId; } } public string TransitId { get { return this._transitId; } } public List Violations { get { return _violations; } } public List Errors { get { return _errors; } } public Message.NotificationClass NotificationClass { get { return this._notificationClass; } } public bool IsReset { get { return this._isReset; } } #endregion } }