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); }
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)); }
/// <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"); }
/// <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 ""; } }
/// <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; }
public void ReloadRuleSets(bool forceReload = false) { AvailableRuleSets = RuleSetHelper.LoadRuleSets(forceReload); }