Exemple #1
0
        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);
        }
Exemple #2
0
        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);
        }