public bool DoesRuleMatch(RoutedItem rr, DestRule rule) { RoutedItemEx routedItem = (RoutedItemEx)rr; // Connection source, DestRule rule, DicomDataset dataSet //routedItem.sourceDicomFile?.Dataset //2017-10-09 sbh I was running into "hard to debug" npe so I broke out the logic for easier debugging //The idea here is to fail fast on rules and return false //If a rule field is specified it is "engaged" and must be satisfied //If a rule field is not specified ie null then it does not have to be satisfied //near future: We might like to introspect any rule class to make this more dynamic //all we need is a fieldmatch table between hl7 and DICOM and other sources //then we can introspect class or JSON and loop the specifiers and compare to match //otherwise the Rule class itself can grow ridiculously large. try { return(DoesRuleMatchImpl(routedItem, rule)); } catch (Exception e) { _logger.LogFullException(e); } return(false); }
private bool DoesRuleMatchImpl(RoutedItemEx routedItem, DestRule rule) { //rules requiring DICOM dataset if (routedItem.sourceDicomFile?.Dataset != null) { if (rule.modality != null) { if (routedItem.sourceDicomFile.Dataset.Contains(DicomTag.Modality)) { if (Regex.Matches(routedItem.sourceDicomFile.Dataset.GetValue <string>(DicomTag.Modality, 0), rule.modality, RegexOptions.IgnoreCase).Count == 0) { _logger.Log(LogLevel.Debug, $"rule {rule.name} fails because modality {rule.modality} !matches {routedItem.sourceDicomFile.Dataset.GetValue<string>(DicomTag.Modality, 0)}"); return(false); } } else { _logger.Log(LogLevel.Debug, $"rule {rule.name} fails because DicomTag.Modality missing."); return(false); } } if (rule.referringPhysician != null) { if (routedItem.sourceDicomFile.Dataset.Contains(DicomTag.ReferringPhysicianName)) { if (Regex.Matches(rule.referringPhysician, routedItem.sourceDicomFile.Dataset.GetValue <string>(DicomTag.ReferringPhysicianName, 0), RegexOptions.IgnoreCase).Count == 0) { _logger.Log(LogLevel.Debug, $"rule {rule.name} fails because referringPhysician {rule.referringPhysician} !matches {routedItem.sourceDicomFile.Dataset.GetValue<string>(DicomTag.ReferringPhysicianName, 0)}"); return(false); } } else { _logger.Log(LogLevel.Debug, $"rule {rule.name} fails because DicomTag.ReferringPhysicianName missing."); return(false); } } } if (rule.ruleTags != null && rule.ruleTags.Count > 0) { routedItem = (RoutedItemEx)_doTagsMatchService.DoTagsMatch(rule, routedItem); if (!routedItem.RuleMatch) { _logger.Log(LogLevel.Debug, $"rule {rule.name} fails because Tags {rule.ruleTags} !matches {routedItem.sourceDicomFile.Dataset}"); return(false); } } _logger.Log(LogLevel.Debug, $"rule {rule.name} id: {routedItem.id} succeeds!"); return(true); }
private RoutedItemEx Hl7Matching(RoutedItemEx ri, DestRule rule) { if (ri.sourceFileName == null || !ri.sourceFileName.EndsWith(".hl7")) { return(null); } foreach (Tag tag in rule.ruleTags) { var segments = ri.hl7.FindAll(e => e.Key == tag.tag.Split(",")[0]); var elementNum = int.Parse(tag.tag.Split(",")[1]); foreach (var segment in segments) { if (segment.Value.Count >= elementNum + 1) { var data = segment.Value[elementNum]; ri.matches.AddRange(Regex.Matches(data, tag.tagValue, RegexOptions.IgnoreCase)); if (ri.matches.Count == 0) { _logger.Log(LogLevel.Debug, $"rule {rule.name} fails this segment because data {data} !matches {tag.tagValue}"); } } } if (ri.matches.Count == 0) { if (!tag.tagValue.Equals("\\0*")) { _logger.Log(LogLevel.Debug, $"rule {rule.name} fails because {tag} missing. Use \"\\0*\" for tagValue if you want to include missing and null tag values."); return(ri); } } _logger.Log(LogLevel.Debug, $"rule {rule.name} succeeds in Tag Match!"); } return(null); }
/// <summary> /// Determines whether all tags specified in the rule are satisfied in the dataSet. If a tagValue can be anything but must be present, use "+." regex /// </summary> /// <param name="rule"></param> /// <param name="rr"></param> /// <returns></returns> public RoutedItem DoTagsMatch(DestRule rule, RoutedItem rr) { RoutedItemEx ri = (RoutedItemEx)rr; //dicom tag matching RoutedItemEx result = DicomMatching(ri, rule); if (result != null) { return(result); } result = Hl7Matching(ri, rule); if (result != null) { return(result); } ri.RuleMatch = true; return(ri); }
private RoutedItemEx DicomMatching(RoutedItemEx ri, DestRule rule) { var dataset = ri.sourceDicomFile?.Dataset; if (dataset == null) { return(null); } foreach (Tag tag in rule.ruleTags) { DicomTag dtTag = DicomTag.Parse(tag.tag); if (dataset.Contains(dtTag)) //if tagvalue can be null it doesn't have to exist { _logger.Log(LogLevel.Debug, $"tag {tag.tag} {dtTag} exists, now getting value..."); string tagValue = dataset.GetValue <string>(dtTag, 0); ri.matches.AddRange(Regex.Matches(tagValue, tag.tagValue, RegexOptions.IgnoreCase)); if (ri.matches.Count == 0) { _logger.Log(LogLevel.Debug, $"rule {rule.name} fails because tag.tagValue {tag.tagValue} !matches {tagValue}"); return(ri); } } else if (!tag.tagValue.Equals("\\0*")) { _logger.Log(LogLevel.Debug, $"rule {rule.name} fails because {dtTag} missing. Use \"\\0*\" for tagValue if you want to include missing and null tag values."); return(ri); } } _logger.Log(LogLevel.Debug, $"rule {rule.name} succeeds in Tag Match!"); return(null); }
public async Task <Priority> CheckAndDelayOnWaitConditions(RoutedItem ri) { RoutedItemEx routedItem = (RoutedItemEx)ri; var taskInfo = $"task: {routedItem.TaskID}"; /* * check and delay on wait conditions * DICOM TAG (0000,0700) * LOW = 0002H * MEDIUM = 0000H * HIGH = 0001H */ //Engage: Waits get engaged when DICOM Priority Tag detected, and get disengaged when done ushort priority = 3; try { if (routedItem.sourceDicomFile != null) { DicomDataset dataSet = routedItem.sourceDicomFile.Dataset; string uuid = null; try { if (dataSet.Contains(DicomTag.StudyInstanceUID)) { uuid = dataSet.GetValue <string>(DicomTag.StudyInstanceUID, 0); } } catch (DicomDataException e) { _logger.Log(LogLevel.Debug, $"{taskInfo} {uuid} has no StudyInstanceUID field. {e.Message} {e.StackTrace}"); } Profile currentProfile = _profileStorage.Current; try { if (dataSet.Contains(DicomTag.Priority)) { priority = dataSet.GetValue <ushort>(DicomTag.Priority, 0); } else { _logger.Log(LogLevel.Debug, $"{taskInfo} {uuid} has no priority field."); } } catch (DicomDataException e) { _logger.Log(LogLevel.Debug, $"{taskInfo} {uuid} has no priority field. {e.Message} {e.StackTrace}"); } if (priority < 3) { _logger.Log(LogLevel.Information, $"{taskInfo} {uuid} has priority {priority}."); if (priority.Equals(0x01)) { currentProfile.highWait = true; _logger.Log(LogLevel.Information, $"{taskInfo} {uuid} with high priority detected. Setting highWait flag."); } if (priority.Equals(0x00)) { currentProfile.mediumWait = true; _logger.Log(LogLevel.Information, $"{taskInfo} {uuid} with medium priority detected. Setting highWait flag."); } } //Wait on Condition: if (currentProfile.highWait || currentProfile.mediumWait) { //something important is in mid transfer so check and wait if med or low if (priority < 3 || priority.Equals(0x02)) { //low or no priority is subject to both highWait and mediumWait conditions if (currentProfile.highWait && !priority.Equals(0x01)) { _logger.Log(LogLevel.Information, $"{taskInfo} highWait causing {currentProfile.highWaitDelay}ms delay for DICOM {uuid} in thread:{System.Threading.Thread.CurrentThread}."); await Task.Delay(currentProfile.highWaitDelay, _taskManager.cts.Token).ConfigureAwait(false); } if (currentProfile.mediumWait && !priority.Equals(0x00) && !priority.Equals(0x01)) { _logger.Log(LogLevel.Information, $"{taskInfo} mediumWait causing {currentProfile.mediumWaitDelay}ms delay for DICOM {uuid} in thread:{System.Threading.Thread.CurrentThread}."); await Task.Delay(currentProfile.mediumWaitDelay, _taskManager.cts.Token).ConfigureAwait(false); } } else if (priority.Equals(0x00)) { //medium priority is subject to only highWait conditions if (currentProfile.highWait) { _logger.Log(LogLevel.Information, $"{taskInfo} highWait causing {currentProfile.highWaitDelay}ms delay for DICOM {uuid} in thread:{System.Threading.Thread.CurrentThread}."); await Task.Delay(currentProfile.highWaitDelay, _taskManager.cts.Token).ConfigureAwait(false); } } } } } catch (TaskCanceledException) { _logger.Log(LogLevel.Information, $"Task was canceled."); } catch (Exception e) { _logger.LogFullException(e); } return(_util.GetPriority(priority)); }
public RoutedItem Clone(RoutedItem Item) { Throw.IfNull(Item); RoutedItemEx ri = new RoutedItemEx { args = Item.args, attempts = Item.attempts, AccessionNumber = Item.AccessionNumber, box = Item.box, creationTimeUtc = Item.creationTimeUtc, cloudTaskResults = Item.cloudTaskResults.ToList(), Compress = Item.Compress, destDicomFile = _destDicomFile, destFileName = Item.destFileName, destFileType = Item.destFileType, dicomRequest = _dicomRequest, Error = Item.Error, fileCount = Item.fileCount, fileIndex = Item.fileIndex, from = Item.from, fromConnection = Item.fromConnection, hl7 = Item.hl7.ToList(), id = Item.id, InstanceID = Item.InstanceID, lastAccessTimeUtc = Item.lastAccessTimeUtc, //ri.lastAttempt = lastAttempt; lastWriteTimeUtc = Item.lastWriteTimeUtc, length = Item.length, name = Item.name, matches = Item.matches, MessageId = Item.MessageId, PatientID = Item.PatientID, PatientIDIssuer = Item.PatientIDIssuer, priority = Item.priority, request = Item.request, requestType = Item.requestType, resource = Item.resource, response = Item.response.ToList(), resultsTime = Item.resultsTime, RoutedItemMetaFile = Item.RoutedItemMetaFile, ruleDicomTag = _ruleDicomTag, ruleDicomTags = _ruleDicomTags, rules = _rules, Series = Item.Series, Sop = Item.Sop, sourceDicomFile = _sourceDicomFile, sourceFileName = Item.sourceFileName, sourceFileType = Item.sourceFileType, status = Item.status, startTime = Item.startTime, Study = Item.Study, StudyID = Item.StudyID, stream = _stream, TagData = Item.TagData, TaskID = Item.TaskID, to = Item.to, toConnections = Item.toConnections, type = Item.type }; return(ri); }