public void RuleSetHelper_FindAllIncludesUnderRoot()
        {
            // Arrange
            const string slnRoot     = @"X:\SolutionDir\";
            string       projectRoot = Path.Combine(slnRoot, @"Project\");
            string       sonarRoot   = Path.Combine(slnRoot, @"Sonar\");
            string       commonRoot  = Path.Combine(slnRoot, @"Common\");

            const string sonarRs1FileName      = "Sonar1.ruleset";
            const string sonarRs2FileName      = "Sonar2.ruleset";
            const string projectRsBaseFileName = "ProjectBase.ruleset";
            const string commonRs1FileName     = "SolutionCommon1.ruleset";
            const string commonRs2FileName     = "SolutionCommon2.ruleset";

            var sonarRs1      = TestRuleSetHelper.CreateTestRuleSet(sonarRoot, sonarRs1FileName);
            var sonarRs2      = TestRuleSetHelper.CreateTestRuleSet(sonarRoot, sonarRs2FileName);
            var projectBaseRs = TestRuleSetHelper.CreateTestRuleSet(projectRoot, projectRsBaseFileName);
            var commonRs1     = TestRuleSetHelper.CreateTestRuleSet(commonRoot, commonRs1FileName);
            var commonRs2     = TestRuleSetHelper.CreateTestRuleSet(commonRoot, commonRs2FileName);

            var inputRuleSet = TestRuleSetHelper.CreateTestRuleSet(projectRoot, "test.ruleset");

            AddRuleSetInclusion(inputRuleSet, projectBaseRs, useRelativePath: true);
            AddRuleSetInclusion(inputRuleSet, commonRs1, useRelativePath: true);
            AddRuleSetInclusion(inputRuleSet, commonRs2, useRelativePath: false);
            var expected1 = AddRuleSetInclusion(inputRuleSet, sonarRs1, useRelativePath: true);
            var expected2 = AddRuleSetInclusion(inputRuleSet, sonarRs2, useRelativePath: false);

            // Act
            RuleSetInclude[] actual = RuleSetHelper.FindAllIncludesUnderRoot(inputRuleSet, sonarRoot).ToArray();

            // Assert
            CollectionAssert.AreEquivalent(new[] { expected1, expected2 }, actual);
        }
Пример #2
0
        internal /*for testing purposes*/ bool TryUpdateExistingProjectRuleSet(string solutionRuleSetPath, string projectRuleSetRootFolder, string currentRuleSet, out string existingRuleSetPath, out RuleSet existingRuleSet)
        {
            existingRuleSetPath = null;
            existingRuleSet     = null;

            if (ShouldIgnoreConfigureRuleSetValue(currentRuleSet))
            {
                return(false);
            }

            existingRuleSetPath = PathHelper.ResolveRelativePath(currentRuleSet, projectRuleSetRootFolder);
            if (!PathHelper.IsPathRootedUnderRoot(existingRuleSetPath, projectRuleSetRootFolder))
            {
                // Not our file (i.e. absolute path to some other ruleset)
                existingRuleSetPath = null;
                return(false);
            }

            if (this.AlreadyUpdatedExistingRuleSetPaths.TryGetValue(existingRuleSetPath, out existingRuleSet))
            {
                return(true);
            }

            existingRuleSet = this.ruleSetSerializer.LoadRuleSet(existingRuleSetPath);
            if (existingRuleSet == null)
            {
                existingRuleSetPath = null;
                return(false);
            }

            RuleSetHelper.UpdateExistingProjectRuleSet(existingRuleSet, solutionRuleSetPath);
            this.AlreadyUpdatedExistingRuleSetPaths.Add(existingRuleSetPath, existingRuleSet);
            return(true);
        }
        public void RuleSetHelper_FindInclude_ArgChecks()
        {
            RuleSet rs = new RuleSet("Name", @"c:\path.ruleset");

            Exceptions.Expect <ArgumentNullException>(() => RuleSetHelper.FindInclude(null, rs));
            Exceptions.Expect <ArgumentNullException>(() => RuleSetHelper.FindInclude(rs, null));
        }
Пример #4
0
        /// <summary>
        /// Attempts to fix the conflicts by ensuring that the server ruleset is included with the expected Include Action
        /// </summary>
        /// <returns>Whether all conflicts were resolved</returns>
        private bool TryResolveIncludeConflicts(RuleSet baselineRuleSet, RuleSet targetRuleSet)
        {
            Debug.Assert(baselineRuleSet != null);
            Debug.Assert(targetRuleSet != null);
            Debug.Assert(!string.IsNullOrWhiteSpace(baselineRuleSet.FilePath));
            Debug.Assert(!string.IsNullOrWhiteSpace(targetRuleSet.FilePath));

            RuleSetHelper.UpdateExistingProjectRuleSet(targetRuleSet, baselineRuleSet.FilePath);
            RuleConflictInfo conflicts1stAttempt = this.FindConflictsCore(baselineRuleSet, targetRuleSet);

            return(!conflicts1stAttempt.HasConflicts);
        }
        public void RuleSetHelper_RemoveAllIncludesUnderRoot()
        {
            // Arrange
            const string slnRoot     = @"X:\SolutionDir\";
            string       projectRoot = Path.Combine(slnRoot, @"Project\");
            string       sonarRoot   = Path.Combine(slnRoot, @"Sonar\");
            string       commonRoot  = Path.Combine(slnRoot, @"Common\");

            const string sonarRs1FileName      = "Sonar1.ruleset";
            const string sonarRs2FileName      = "Sonar2.ruleset";
            const string projectRsBaseFileName = "ProjectBase.ruleset";
            const string commonRs1FileName     = "SolutionCommon1.ruleset";
            const string commonRs2FileName     = "SolutionCommon2.ruleset";

            var sonarRs1      = TestRuleSetHelper.CreateTestRuleSet(sonarRoot, sonarRs1FileName);
            var sonarRs2      = TestRuleSetHelper.CreateTestRuleSet(sonarRoot, sonarRs2FileName);
            var projectBaseRs = TestRuleSetHelper.CreateTestRuleSet(projectRoot, projectRsBaseFileName);
            var commonRs1     = TestRuleSetHelper.CreateTestRuleSet(commonRoot, commonRs1FileName);
            var commonRs2     = TestRuleSetHelper.CreateTestRuleSet(commonRoot, commonRs2FileName);

            var inputRuleSet = TestRuleSetHelper.CreateTestRuleSet(projectRoot, "test.ruleset");

            AddRuleSetInclusion(inputRuleSet, projectBaseRs, useRelativePath: true);
            AddRuleSetInclusion(inputRuleSet, commonRs1, useRelativePath: true);
            AddRuleSetInclusion(inputRuleSet, commonRs2, useRelativePath: false);
            AddRuleSetInclusion(inputRuleSet, sonarRs1, useRelativePath: true);
            AddRuleSetInclusion(inputRuleSet, sonarRs2, useRelativePath: false);

            var expectedRuleSet = TestRuleSetHelper.CreateTestRuleSet(projectRoot, "test.ruleset");

            AddRuleSetInclusion(expectedRuleSet, projectBaseRs, useRelativePath: true);
            AddRuleSetInclusion(expectedRuleSet, commonRs1, useRelativePath: true);
            AddRuleSetInclusion(expectedRuleSet, commonRs2, useRelativePath: false);

            // Act
            RuleSetHelper.RemoveAllIncludesUnderRoot(inputRuleSet, sonarRoot);

            // Assert
            RuleSetAssert.AreEqual(expectedRuleSet, inputRuleSet);
        }
        public void RuleSetHelper_FindInclude()
        {
            // Arrange
            RuleSet target = TestRuleSetHelper.CreateTestRuleSet(@"c:\Solution\SomeFolder\fullFilePath.ruleset");
            RuleSet sourceWithRelativeInclude = TestRuleSetHelper.CreateTestRuleSet(@"c:\fullFilePath.ruleset");
            string  relativeInclude           = @"Solution\SomeFolder\fullFilePath.ruleset".ToLowerInvariant(); // Catch casing errors

            sourceWithRelativeInclude.RuleSetIncludes.Add(new RuleSetInclude(relativeInclude, RuleAction.Error));
            RuleSet sourceWithAbsoluteInclude = TestRuleSetHelper.CreateTestRuleSet(@"c:\fullFilePath.ruleset");
            string  absoluteInclude           = target.FilePath.ToUpperInvariant(); // Catch casing errors

            sourceWithAbsoluteInclude.RuleSetIncludes.Add(new RuleSetInclude(absoluteInclude, RuleAction.Warning));
            RuleSetInclude include;

            // Case 1: Relative include
            // Act
            include = RuleSetHelper.FindInclude(sourceWithRelativeInclude, target);

            // Assert
            StringComparer.OrdinalIgnoreCase.Equals(include.FilePath, relativeInclude).Should().BeTrue($"Unexpected include {include.FilePath} instead of {relativeInclude}");

            // Case 2: Absolute include
            // Act
            include = RuleSetHelper.FindInclude(sourceWithAbsoluteInclude, target);

            // Assert
            StringComparer.OrdinalIgnoreCase.Equals(include.FilePath, absoluteInclude).Should().BeTrue($"Unexpected include {include.FilePath} instead of {absoluteInclude}");

            // Case 3: No includes at all
            // Act
            include = RuleSetHelper.FindInclude(target, target);
            // Assert
            include.Should().BeNull("No includes at all");

            // Case 4: No includes from source to target
            // Act
            include = RuleSetHelper.FindInclude(sourceWithRelativeInclude, sourceWithAbsoluteInclude);
            // Assert
            include.Should().BeNull("No includes from source to target");
        }
        public void RuleSetHelper_UpdateExistingProjectRuleSet()
        {
            // Arrange
            const string existingProjectRuleSetPath = @"X:\MySolution\ProjectOne\proj1.ruleset";
            const string existingInclude            = @"..\SolutionRuleSets\sonarqube1.ruleset";

            const string newSolutionRuleSetPath = @"X:\MySolution\SolutionRuleSets\sonarqube2.ruleset";
            const string expectedInclude        = @"..\SolutionRuleSets\sonarqube2.ruleset";

            var existingProjectRuleSet = TestRuleSetHelper.CreateTestRuleSet(existingProjectRuleSetPath);

            existingProjectRuleSet.RuleSetIncludes.Add(new RuleSetInclude(existingInclude, RuleAction.Default));

            var expectedRuleSet = TestRuleSetHelper.CreateTestRuleSet(existingProjectRuleSetPath);

            expectedRuleSet.RuleSetIncludes.Add(new RuleSetInclude(expectedInclude, RuleAction.Default));

            // Act
            RuleSetHelper.UpdateExistingProjectRuleSet(existingProjectRuleSet, newSolutionRuleSetPath);

            // Assert
            RuleSetAssert.AreEqual(expectedRuleSet, existingProjectRuleSet, "Update should delete previous solution rulesets, and replace them with a new one provide");
        }
Пример #8
0
        /// <summary>
        /// Retrieve the list of clinical problems for a patient encounter.
        /// </summary>
        /// <param name="id">encounter id</param>
        /// <returns>An xml serializtion string of a list of clinical problems</returns>
        string IDecisionSupportService.RetrieveProblemList(int id)
        {
            var encounter = db.EncounterContextItemDefinitionFind(id);
            if (encounter == null)
                return "";
            try
            {
                var list = new List<ClinicalProblemInstanceSimpleObject>();

                foreach (var instance in AssociationHelper.SearchClinicalProblemInstance(encounter, db))
                {

                    var simpleObject = new ClinicalProblemInstanceSimpleObject()
                    {                        
                        Reports = new List<KeyValuePair<string, string>>(),
                        Facts = new List<string>(),
                        OrderSet = new List<string>(),
                        History = new List<string>()
                    };

                    simpleObject.Id = instance.Id;
                    simpleObject.Priority = instance.Priority;
                    simpleObject.State = instance.State;
                    if(instance.ClinicalProblemDefinition!=null && string.IsNullOrEmpty(instance.ClinicalProblemDefinition.Name)==false)
                        simpleObject.Name = instance.ClinicalProblemDefinition.Name;
                    if(instance.ChangeRecord!=null && instance.ChangeRecord.Count()>0)
                        simpleObject.TimeStamp = instance.ChangeRecord.ElementAt(0).TimeStamp.Value;
                    if (instance.ClinicalProblemDefinition != null && instance.ClinicalProblemDefinition.TriggerRule != null)
                        simpleObject.TriggerRule = RuleSetHelper.GetLaymanConditionString(instance.ClinicalProblemDefinition.TriggerRule.RuleSet);

                    foreach (var fact in instance.Facts)
                    {
                        var factString = string.IsNullOrEmpty(fact.ContextItemDefinition.ReferenceRange) ?
                            fact.ContextItemDefinition.Name + " = " + fact.ValueString() :
                            fact.ContextItemDefinition.Name + " = " + fact.ValueString() + " (参考范围:" + fact.ContextItemDefinition.ReferenceRange + ")";
                        simpleObject.Facts.Add(factString);
                    }

                    foreach (var report in instance.Reports)
                    {
                        simpleObject.Reports.Add(new KeyValuePair<string, string>(report.TimeStamp + " " + report.ReportType, report.URL));
                    }

                    // Don't need to show history for now.
                    //foreach (var record in instance.ChangeRecord)
                    //{
                    //    simpleObject.History.Add();
                    //}

                    int count = 0;
                    foreach (var order in db.MedicalOrderSet)
                    {
                        simpleObject.OrderContextItemDefinitionAdd(order.Name);
                        if (count++ > 10)
                            break;
                    }

                    list.Add(simpleObject);
                }                

                var obj = list as object;
                return SerializationHelper.Serialize(ref obj);
            }
            catch
            {
                return "";
            }
        }
Пример #9
0
        /// <summary>
        /// Innter Implemention of I/F Notify():
        /// void IDecisionSupportService.Notify(int id)
        /// </summary>
        /// <param name="id">event id</param>
        /// <returns>log items.
        /// For each log keypair, DateTime is timestamp, string is log content.</returns>
        public IEnumerable<KeyValuePair<DateTime, string>> Notify(int id)
        {
            var log = new List<KeyValuePair<DateTime, string>>();
            var sw = Stopwatch.StartNew();
            log.Add(new KeyValuePair<DateTime, string>(DateTime.Now, "[BEGIN]"));
            log.Add(new KeyValuePair<DateTime, string>(DateTime.Now, "Call I/F Notify(" + id + ")"));

            // TODO: Search EMR db and construct event, report, encounter, etc. in CDS db

            var evt = db.Event.Find(id);
            if (evt == null)
            {
                log.Add(new KeyValuePair<DateTime, string>(DateTime.Now, "Event with specified id doesnot exist. Exit funciton now."));
                return log;
            }

            var encounter = evt.Encounter;
            if (encounter == null)
            {
                log.Add(new KeyValuePair<DateTime, string>(DateTime.Now, "Associated encounter doesnot exist. Exit funciton now."));
                return log;
            }

            // Collect abnormal facts from the event
            //            
            var abnormalFacts = new List<Fact>();
            var relatedProblemInstances = new List<ClinicalProblemInstance>();
            var solvedSuspectProblemInstances = new List<ClinicalProblemInstance>();
            foreach (var x in evt.Report)
            {
                // Get facts from report and update to profile.
                var facts = (new FactServiceMocker()).GetFactsFromReportMock(x.Id, db).ToList();
                // TODO: var facts = factService.GetFactsFromReport(x.URL).ToList();
                facts.ForEach(y =>
                {
                    db.UpdateFactCache(encounter.Id, y);
                    if (y.ContextItemDefinition.Type == EnumContextItemType.ClinicalProblem.ToString() && y.IsAbnormal == false)
                    {
                        var instance = db.ClinicalProblemInstance.FirstOrDefault(z => z.State == EnumProblemState.New.ToString() && z.ClinicalProblemDefinition.Name == y.ContextItemDefinition.Name);
                        if (instance != null)
                        {
                            solvedSuspectProblemInstances.Add(instance);
                        }
                    }

                    // collect related problem instances associated with the fact. Later, use Distinct() to get full list.
                    foreach (var z in db.ClinicalProblemInstance)
                    {
                        if ((z.State == EnumProblemState.New.ToString() ||
                            z.State == EnumProblemState.ResolvedSuspected.ToString()) &&
                            z.ClinicalProblemDefinition.ContextItemDefinition.Contains(y.ContextItemDefinition, new PropertyComparer<ContextItemDefinition>("Id")))
                        {
                            relatedProblemInstances.Add(z);
                        }
                    }

                    // Collect abnormal facts as triggers
                    if (y.IsAbnormal == true)
                    {
                        abnormalFacts.Add(y);
                    }
                });
            };

            // Update problems that are suspected no longer existing.
            solvedSuspectProblemInstances.Distinct(new PropertyComparer<ClinicalProblemInstance>("Id")).ToList().ForEach(x =>
            {
                db.UpdateProblemState(x.Id, EnumProblemState.ResolvedSuspected.ToString(), EnumProblemStateChangeReason.CDS.ToString(), CurrentUser);
            });

            // Update related active problems with new report, for tracking.
            relatedProblemInstances.Distinct(new PropertyComparer<ClinicalProblemInstance>("Id")).ToList().ForEach(x =>
            {
                var result = ReEvaluate(x.Id);
                if (result.HasValue)
                {
                    if (result.Value == false)
                    {
                        db.UpdateProblemState(x.Id, EnumProblemState.ResolvedSuspected.ToString(), EnumProblemStateChangeReason.CDS.ToString(),CurrentUser);
                    }
                    else
                    {
                        db.UpdateProblemState(x.Id, x.State, EnumProblemStateChangeReason.CDS.ToString(),CurrentUser);
                    }
                }
            });

            if (abnormalFacts.Count <= 0)
            {
                log.Add(new KeyValuePair<DateTime, string>(DateTime.Now, "No abnormal facts were detected. Exit funciton now."));
                return log;
            }

            log.Add(new KeyValuePair<DateTime, string>(DateTime.Now, ""));
            log.Add(new KeyValuePair<DateTime, string>(DateTime.Now, abnormalFacts.Count + " abnormal facts were detected:"));
            abnormalFacts.ForEach(x =>
            {
                log.Add(new KeyValuePair<DateTime, string>(DateTime.Now, x.ContextItemDefinition.Name + " = " + x.ValueString()));
            });
            log.Add(new KeyValuePair<DateTime, string>(DateTime.Now, ""));

            var triggerFacts = new List<Fact>();
            abnormalFacts.ForEach(x =>
            {
                if (x.ContextItemDefinition.Type==EnumContextItemType.ClinicalProblem.ToString()) // The fact itself is a problem. e.g. the fact comes from a diagnosis event.
                {
                    int ID = db.CreateClinicalProblemInstance(x.ContextItemDefinition.Name, encounter.Id, false);
                    if (ID != -1)
                    {
                        db.UpdateProblemState(ID, EnumProblemState.New.ToString(), EnumProblemStateChangeReason.CDS.ToString(), CurrentUser, true);
                        log.Add(new KeyValuePair<DateTime, string>(DateTime.Now, "!!! New Problem[" + x.ContextItemDefinition.Name + "] is detected directly from fact[" + x.ContextItemDefinition.Name + "=" + x.ValueString() + "]. (the fact itself is a problem)"));
                    }
                }
                else // The fact needs reasoning by rule engine to generate problem.
                {
                    triggerFacts.Add(x);
                }
            });

            //
            // Get candidate problems by abnormal facts
            //
            var candidateProblems = GetCandidateProblems(triggerFacts);

            if (candidateProblems.Count() <= 0)
            {
                log.Add(new KeyValuePair<DateTime, string>(DateTime.Now, "No candidate problems were detected. Exit function now."));
                return log;
            }

            log.Add(new KeyValuePair<DateTime, string>(DateTime.Now, ""));
            log.Add(new KeyValuePair<DateTime, string>(DateTime.Now, candidateProblems.Count() + " candidate problems were detected:"));
            candidateProblems.ToList().ForEach(x =>
            {
                log.Add(new KeyValuePair<DateTime, string>(DateTime.Now, x.Name));
            });
            log.Add(new KeyValuePair<DateTime, string>(DateTime.Now, ""));


            //
            // Construct reasoning context for candidate problems
            //
            IEnumerable<ClinicalProblemDefinition> filteredProblems;
            Context reasoningContext;
            ConstructReasoningContext(encounter, candidateProblems, out filteredProblems, out reasoningContext);

            if (filteredProblems.Count() <= 0)
            {
                log.Add(new KeyValuePair<DateTime, string>(DateTime.Now, "Lacking reasoning facts for all candidate problems. Exit function now."));
                return log;
            }

            log.Add(new KeyValuePair<DateTime, string>(DateTime.Now, ""));
            log.Add(new KeyValuePair<DateTime, string>(DateTime.Now, "After checking data availability, " + filteredProblems.Count() + " problems can go through rule engine:"));
            filteredProblems.ToList().ForEach(x =>
            {
                log.Add(new KeyValuePair<DateTime, string>(DateTime.Now, x.Name));
            });
            log.Add(new KeyValuePair<DateTime, string>(DateTime.Now, ""));
            log.Add(new KeyValuePair<DateTime, string>(DateTime.Now, "Reasoning context contains: " + reasoningContext.GetAllKeys().Count() + " items:"));
            foreach (var x in reasoningContext.GetAllKeys())
            {
                log.Add(new KeyValuePair<DateTime, string>(DateTime.Now, x + " = " + reasoningContext.GetValue(x)));
            }
            log.Add(new KeyValuePair<DateTime, string>(DateTime.Now, ""));

            //
            // Reason by Rule Engine
            //
            var triggeredProblems = Reason(filteredProblems, reasoningContext);

            if (triggeredProblems != null && triggeredProblems.Count() > 0)
            {
                triggeredProblems.ToList().ForEach(x =>
                {
                    int ID = db.CreateClinicalProblemInstance(x, encounter.Id, true);
                    if (relatedProblemInstances.Any(y => y.Id == ID) == false // means the problem state is already updated above
                        && ID != -1)
                    {
                        db.UpdateProblemState(ID, EnumProblemState.New.ToString(), EnumProblemStateChangeReason.CDS.ToString(), CurrentUser);
                        var instance = db.ClinicalProblemInstance.Find(ID);
                        if (instance != null && instance.TriggerRule != null && string.IsNullOrEmpty(instance.TriggerRule.RuleSet) == false)
                            log.Add(new KeyValuePair<DateTime, string>(DateTime.Now, "!!! New Problem[" + x + "] is detected from rule[" + RuleSetHelper.GetLaymanConditionString(instance.TriggerRule.RuleSet) + "]."));
                    }
                });
            }

            sw.Stop();
            log.Add(new KeyValuePair<DateTime, string>(DateTime.Now, ""));
            log.Add(new KeyValuePair<DateTime, string>(DateTime.Now, "This I/F call consumes " + sw.ElapsedMilliseconds + " ms"));
            log.Add(new KeyValuePair<DateTime, string>(DateTime.Now, "[END]"));

            return log;
        }
Пример #10
0
 public void ReloadRuleSets(bool forceReload = false)
 {
     AvailableRuleSets = RuleSetHelper.LoadRuleSets(forceReload);
 }