/// <inheritdoc/> /// <remarks>Additionally checks version compatibility.</remarks> public override bool CanExtractFact <TFactWork, TWantAction, TFactContainer>(IFactType factType, TFactWork factWork, IWantActionContext <TWantAction, TFactContainer> context) { if (factType.IsFactType <ISpecialFact>()) { return(base.CanExtractFact(factType, factWork, context)); } List <IFact> facts = context .Container .WhereFactsByFactType(factType, context.Cache) .ToList(); if (facts.Count == 0) { return(false); } var maxVersion = context.WantAction.InputFactTypes.GetVersionFact(context); if (maxVersion == null) { return(true); } return(facts.Exists(fact => fact.IsRelevantFactByVersioned(maxVersion))); }
/// <inheritdoc/> public virtual IFactType GetFactType <TFact>(TFact fact) where TFact : IFact { if (_cache.ContainsKey(fact)) { return(_cache[fact]); } if (_cache.Count > 64) { lock (_cache) if (_cache.Count > 64) { _cache.Remove(_cache.Keys.First()); } } lock (fact) { if (_cache.ContainsKey(fact)) { return(_cache[fact]); } IFactType factType = fact.GetFactType(); _cache.Add(fact, factType); return(factType); } }
/// <inheritdoc/> public virtual bool CanExtractFact <TFactWork, TWantAction, TFactContainer>(IFactType factType, TFactWork factWork, IWantActionContext <TWantAction, TFactContainer> context) where TFactWork : IFactWork where TWantAction : IWantAction where TFactContainer : IFactContainer { return(context.Container.Any(fact => context.Cache.GetFactType(fact).EqualsFactType(factType))); }
public void CannotDerivedOneFactFromOne2TestCase() { IFactType wantFact = GetFactType <Input6Fact>(); string expectedReason = $"Failed to derive one or more facts for the action ({wantFact.FactName})."; var expectedNeedFacts = new List <IFactType> { GetFactType <Input3Fact>(), GetFactType <Input5Fact>(), }; GivenCreateFactFactory() .AndAddRules(RuleCollectionHelper.GetRulesForNotAvailableInput6Fact()) .And("Want fact.", factory => factory.WantFacts((Input6Fact fact) => { })) .When("Derive facts.", factory => ExpectedDeriveException(() => factory.Derive())) .ThenAssertErrorDetail(ErrorCode.FactCannotDerived, expectedReason) .And("Check error", error => { DeriveErrorDetail detail = error.Details.First(); Assert.AreEqual(1, detail.RequiredFacts.Count, "A different amount of required facts was expected."); DeriveFactErrorDetail factDetail = detail.RequiredFacts.First(); Assert.IsTrue(wantFact.EqualsFactType(factDetail.RequiredFact), "They expected another fact to be required."); Assert.AreEqual(expectedNeedFacts.Count, factDetail.NeedFacts.Count, "Another number of missing facts expected."); List <IFactType> needFacts = factDetail.NeedFacts.ToList(); for (int i = 0; i < expectedNeedFacts.Count; i++) { Assert.IsTrue(expectedNeedFacts[i].EqualsFactType(needFacts[i]), "Another missing fact was expected."); } }) .Run(); }
/// <summary> /// Constructor. /// </summary> /// <param name="funcAsync">Func for calculate.</param> /// <param name="inputFactTypes">Information on input factacles rules.</param> /// <param name="outputFactType">Information on output fact.</param> /// <param name="option">Options for a rule.</param> /// <exception cref="ArgumentNullException"><paramref name="funcAsync"/> or <paramref name="outputFactType"/> is null.</exception> /// <exception cref="ArgumentException">The fact is requested at the input, which the rule calculates.</exception> protected FactRuleBase(Func <IEnumerable <IFact>, ValueTask <IFact> > funcAsync, List <IFactType> inputFactTypes, IFactType outputFactType, FactWorkOption option) : base(inputFactTypes, option) { _funcAsync = funcAsync ?? throw new ArgumentNullException(nameof(funcAsync)); ValidateParam(inputFactTypes, outputFactType); OutputFactType = outputFactType; }
internal static IVersionFact GetVersionFact <TWantAction, TFactContainer>(this IEnumerable <IFactType> factTypes, IWantActionContext <TWantAction, TFactContainer> context) where TWantAction : IWantAction where TFactContainer : IFactContainer { IFactType versionType = factTypes.SingleOrDefault(type => type.IsFactType <IVersionFact>()); return(versionType != null ? (IVersionFact)context.Container.First(fact => context.Cache.GetFactType(fact).EqualsFactType(versionType)) : null); }
/// <summary> /// Cannot is <typeparamref name="TFact"/>. /// </summary> /// <typeparam name="TFact">Type fact.</typeparam> /// <param name="type">Type fact info.</param> /// <param name="paramName">Parameter name.</param> /// <returns><paramref name="type"/>.</returns> public static IFactType CannotIsType <TFact>(this IFactType type, string paramName) where TFact : IFact { if (type.IsFactType <TFact>()) { throw new ArgumentException($"Parameter {paramName} should not be converted into {typeof(TFact).FullName}"); } return(type); }
private void InnerAdd <TFact>(TFact fact, IEqualityComparer <IFact> comparer) where TFact : IFact { IFactType factType = fact.GetFactType(); if (ContainerList.Contains(fact, comparer)) { throw CommonHelper.CreateException(ErrorCode.InvalidData, $"The fact container already contains '{factType.FactName}' fact."); } ContainerList.Add(fact); }
public void TwoFactsSameTypeCannotDeriveTestCase() { IFactType wantFact = GetFactType <Input4Fact>(); string expectedReason = $"Failed to derive one or more facts for the action ({wantFact.FactName})."; var setNeedFacts = new List <List <IFactType> > { new List <IFactType> { GetFactType <Input3Fact>(), }, new List <IFactType> { GetFactType <Input5Fact>(), }, }; GivenCreateFactFactory() .AndAddRules(RuleCollectionHelper.GetInputFactRules()) .And("Want fact.", factory => factory.WantFacts((Input4Fact fact) => { })) .And("Want fact.", factory => factory.WantFacts((Input4Fact fact) => { })) .When("Derive facts.", factory => ExpectedDeriveException(() => factory.Derive())) .ThenAssertErrorDetail(ErrorCode.FactCannotDerived, expectedReason) .AndAreEqual(error => error.Details.Count, 2, errorMessage: "Expceted another count details.") .And("Check error.", error => { foreach (var detail in error.Details) { Assert.AreEqual(setNeedFacts.Count, detail.RequiredFacts.Count, "A different amount of required facts was expected."); Assert.IsNotNull(detail.Container); List <DeriveFactErrorDetail> factDetails = detail.RequiredFacts.ToList(); for (int i = 0; i < setNeedFacts.Count; i++) { DeriveFactErrorDetail factDetail = factDetails[i]; Assert.IsTrue(wantFact.EqualsFactType(factDetail.RequiredFact), "They expected another fact to be required."); List <IFactType> expectedNeedFacts = setNeedFacts[i]; List <IFactType> needFacts = factDetail.NeedFacts.ToList(); for (int j = 0; i < expectedNeedFacts.Count; i++) { Assert.IsTrue(expectedNeedFacts[j].EqualsFactType(needFacts[j]), "Another missing fact was expected."); } } } }) .Run(); }
private void ValidateParam(List <IFactType> inputFactTypes, IFactType outputFactType) { if (outputFactType == null) { throw new ArgumentNullException(nameof(outputFactType)); } outputFactType.CannotIsType <ISpecialFact>(nameof(outputFactType)); if (InputFactTypes.Any(factType => factType.EqualsFactType(outputFactType))) { throw new ArgumentException("Cannot request a fact calculated according to the rule.", nameof(inputFactTypes)); } }
public void CompareFactTypeOneFactTestCase() { DateTimeFact fact = null; IFactType first = null; IFactType second = null; Given("Create fact.", () => { fact = new DateTimeFact(DateTime.Now); }) .When("Create fact info.", _ => { first = fact.GetFactType(); second = fact.GetFactType(); }) .Then("Compare factInfos.", () => Assert.IsTrue(first.EqualsFactType(second), "Actual information is the same.")) .Run(); }
public void FailedCompareFactTypeTowFactTestCase() { DateTimeFact firstFact = null; OtherFact secondFact = null; IFactType first = null; IFactType second = null; Given("Create fact.", () => { firstFact = new DateTimeFact(DateTime.Now); secondFact = new OtherFact(firstFact.Value); }) .When("Create fact info.", _ => { first = firstFact.GetFactType(); second = secondFact.GetFactType(); }) .Then("Compare factInfos", () => Assert.IsFalse(first.EqualsFactType(second), "Actual information is the same.")) .Run(); }
/// <summary> /// Contsructor. /// </summary> /// <param name="requiredFact">The fact that tried to derive.</param> /// <param name="needFacts">Facts that were not enough to derive.</param> public DeriveFactErrorDetail(IFactType requiredFact, IReadOnlyCollection <IFactType> needFacts) { RequiredFact = requiredFact; NeedFacts = needFacts; }
/// <inheritdoc/> public virtual bool Contains <TFact>(TFact fact) where TFact : IFact { IFactType factType = fact.GetFactType(); return(ContainerList.Contains(fact, GetEqualityComparer())); }
/// <summary> /// Get an array of facts of a specific type. /// </summary> /// <param name="facts">Facts.</param> /// <param name="factType">Required type.</param> /// <param name="cache">Cache (optional).</param> /// <returns></returns> public static IEnumerable <IFact> WhereFactsByFactType(this IEnumerable <IFact> facts, IFactType factType, IFactTypeCache cache) { Func <IFact, IFactType> getFactTypeFunc; if (cache != null) { getFactTypeFunc = cache.GetFactType; } else { getFactTypeFunc = fact => fact.GetFactType(); } return(facts.Where(fact => getFactTypeFunc(fact).EqualsFactType(factType))); }
/// <summary> /// The first fact of the same type. /// </summary> /// <typeparam name="TFact"></typeparam> /// <param name="facts">Fact list.</param> /// <param name="factType">Fact type.</param> /// <param name="cache">Cache.</param> /// <returns>Fact or null.</returns> public static TFact FirstFactByFactType <TFact>(this IEnumerable <TFact> facts, IFactType factType, IFactTypeCache cache) where TFact : IFact { return(facts.FirstOrDefault(fact => cache.GetFactType(fact).EqualsFactType(factType))); }
/// <inheritdoc/> protected override FactRule CreateFactRule(Func <IEnumerable <IFact>, ValueTask <IFact> > func, List <IFactType> inputFactTypes, IFactType outputFactType, FactWorkOption option) { return(new FactRule(func, inputFactTypes, outputFactType, option)); }
/// <summary> /// Searches for the first occurrence of a priority fact. /// </summary> /// <typeparam name="TFact">Type fact.</typeparam> /// <param name="facts">Fact list.</param> /// <param name="factType">Fact type of 'priority'.</param> /// <param name="cache">Cache.</param> /// <returns><see cref="IPriorityFact"/> fact or null.</returns> public static IPriorityFact FirstPriorityFactByFactType <TFact>(this IEnumerable <TFact> facts, IFactType factType, IFactTypeCache cache) where TFact : IFact { return(facts.FirstFactByFactType(factType, cache) as IPriorityFact); }
protected override Rule CreateFactRule(Func <IEnumerable <IFact>, ValueTask <IFact> > func, List <IFactType> inputFactTypes, IFactType outputFactType, FactWorkOption option) { throw new NotImplementedException(); }
/// <summary> /// Checks if a <paramref name="type"/> is fact <see cref="IBuildConditionFact"/> or <see cref="IRuntimeConditionFact"/>. /// </summary> /// <param name="type">Fact type.</param> /// <returns>True - <paramref name="type"/> is <see cref="IBuildConditionFact"/> or <see cref="IRuntimeConditionFact"/>.</returns> public static bool IsBuildOrRuntimeFact(this IFactType type) { return(type.IsFactType <IBuildConditionFact>() || type.IsFactType <IRuntimeConditionFact>()); }
/// <summary> /// Determines you can no longer consider the <paramref name="factType"/> necessary. /// </summary> /// <typeparam name="TFactRule">FactRole type.</typeparam> /// <typeparam name="TWantAction">WantAction type.</typeparam> /// <typeparam name="TFactContainer">FactContainer type.</typeparam> /// <param name="factType">Fact type info.</param> /// <param name="node"></param> /// <param name="context"></param> /// <param name="copatibleAllFinishedNodes"></param> /// <returns>True - may not be considered necessary</returns> private bool CanRemoveFromNeedFactTypes <TFactRule, TWantAction, TFactContainer>(IFactType factType, NodeByFactRule <TFactRule> node, IFactRulesContext <TFactRule, TWantAction, TFactContainer> context, Dictionary <NodeByFactRuleInfo <TFactRule>, NodeByFactRule <TFactRule> > copatibleAllFinishedNodes) where TFactRule : IFactRule where TWantAction : IWantAction where TFactContainer : IFactContainer { // Exclude condition special facts if (factType.IsFactType <IBuildConditionFact>()) { var nodeInfo = node.Info; if (nodeInfo.BuildSuccessConditions.Exists(fact => context.Cache.GetFactType(fact).EqualsFactType(factType))) { return(true); } else if (nodeInfo.BuildFailedConditions.Exists(fact => context.Cache.GetFactType(fact).EqualsFactType(factType))) { return(false); } var condition = Factory.CreateObject( type => type.CreateBuildConditionFact <IBuildConditionFact>(), factType ); if (condition.Condition(nodeInfo.Rule, context, _ => nodeInfo.CompatibleRules)) { nodeInfo.BuildSuccessConditions.Add(condition); return(true); } else { nodeInfo.BuildFailedConditions.Add(condition); return(false); } } else if (factType.IsFactType <IRuntimeConditionFact>()) { var nodeInfo = node.Info; if (nodeInfo.RuntimeConditions.Exists(fact => context.Cache.GetFactType(fact).EqualsFactType(factType))) { return(true); } var condition = Factory.CreateObject( type => type.CreateRuntimeConditionFact <IRuntimeConditionFact>(), factType ); condition.SetGetRelatedRulesFunc <TFactRule, TWantAction, TFactContainer>(GetRelatedRules, node.Info.Rule, context.FactRules); nodeInfo.RuntimeConditions.Add(condition); return(true); } else { // Exclude facts for which a solution has already been found. List <KeyValuePair <NodeByFactRuleInfo <TFactRule>, NodeByFactRule <TFactRule> > > finishedNodesForCurrentFact = copatibleAllFinishedNodes .Where(finishedNode => finishedNode.Key.Rule.OutputFactType.EqualsFactType(factType)) .ToList(); if (finishedNodesForCurrentFact.Count != 0) { node.Childs.Insert(0, finishedNodesForCurrentFact[0].Value); return(true); } } return(false); }
public void TwoFactsCannotDeriveTestCase() { IFactType wantFact1 = GetFactType <Input1Fact>(); string expectedReason1 = $"Failed to derive one or more facts for the action ({wantFact1.FactName})."; var setNeedFacts1 = new List <List <IFactType> > { new List <IFactType> { GetFactType <Input3Fact>(), }, }; IFactType wantFact2 = GetFactType <Input2Fact>(); string expectedReason2 = $"Failed to derive one or more facts for the action ({wantFact2.FactName})."; var setNeedFacts2 = new List <List <IFactType> > { new List <IFactType> { GetFactType <Input4Fact>(), }, }; GivenCreateFactFactory() .AndAddRules(new Collection { (Input3Fact fact) => new Input1Fact(fact.Value), (Input4Fact fact) => new Input2Fact(fact.Value) }) .And("Want fact1.", factory => factory.WantFacts((Input1Fact fact) => { })) .And("Want fact2.", factory => factory.WantFacts((Input2Fact fact) => { })) .When("Derive facts.", factory => ExpectedDeriveException(() => factory.Derive())) .ThenAssertErrorDetail(ErrorCode.FactCannotDerived, expectedReason1) .And("Check error detail 1.", error => { DeriveErrorDetail detail = error.Details.First(); Assert.AreEqual(setNeedFacts1.Count, detail.RequiredFacts.Count, "A different amount of required facts was expected."); List <DeriveFactErrorDetail> factDetails = detail.RequiredFacts.ToList(); for (int i = 0; i < setNeedFacts1.Count; i++) { DeriveFactErrorDetail factDetail = factDetails[i]; Assert.IsTrue(wantFact1.EqualsFactType(factDetail.RequiredFact), "They expected another fact to be required."); List <IFactType> expectedNeedFacts = setNeedFacts1[i]; List <IFactType> needFacts = factDetail.NeedFacts.ToList(); for (int j = 0; i < expectedNeedFacts.Count; i++) { Assert.IsTrue(expectedNeedFacts[j].EqualsFactType(needFacts[j]), "Another missing fact was expected."); } } }) .AndAssertErrorDetail(ErrorCode.FactCannotDerived, expectedReason2) .And("Check error detail.", error => { DeriveErrorDetail detail = error.Details.Skip(1).First(); Assert.AreEqual(setNeedFacts2.Count, detail.RequiredFacts.Count, "A different amount of required facts was expected."); List <DeriveFactErrorDetail> factDetails = detail.RequiredFacts.ToList(); for (int i = 0; i < setNeedFacts2.Count; i++) { DeriveFactErrorDetail factDetail = factDetails[i]; Assert.IsTrue(wantFact2.EqualsFactType(factDetail.RequiredFact), "They expected another fact to be required."); List <IFactType> expectedNeedFacts = setNeedFacts2[i]; List <IFactType> needFacts = factDetail.NeedFacts.ToList(); for (int j = 0; i < expectedNeedFacts.Count; i++) { Assert.IsTrue(expectedNeedFacts[j].EqualsFactType(needFacts[j]), "Another missing fact was expected."); } } }) .Run(); }
/// <inheritdoc/> public FactRule(Func <IEnumerable <IFact>, ValueTask <IFact> > funcAsync, List <IFactType> inputFactTypes, IFactType outputFactType, FactWorkOption option) : base(funcAsync, inputFactTypes, outputFactType, option) { }
internal static bool CanDeriveFact <TFactWork, TFactRule, TWantAction, TFactContainer>(IRuntimeConditionFact conditionFact, IFactType searchFactType, TFactWork factWork, IFactRulesContext <TFactRule, TWantAction, TFactContainer> context) where TFactWork : IFactWork where TFactRule : IFactRule where TWantAction : IWantAction where TFactContainer : IFactContainer { if (context.SingleEntity.CanExtractFact(searchFactType, factWork, context)) { return(true); } var rulesWithoutConditionFact = context.FactRules .FindAll(rule => rule.InputFactTypes .All(factType => !factType.EqualsFactType(context.Cache.GetFactType(conditionFact)))); var request = new BuildTreeForFactInfoRequest <TFactRule, TWantAction, TFactContainer> { WantFactType = searchFactType, Context = new FactRulesContext <TFactRule, TWantAction, TFactContainer> { Cache = context.Cache, Container = context.Container, FactRules = rulesWithoutConditionFact, SingleEntity = context.SingleEntity, TreeBuilding = context.TreeBuilding, WantAction = context.WantAction, Engine = context.Engine, }, }; try { return(context.TreeBuilding.TryBuildTreeForFactInfo(request, out var _, out var _)); } catch (InvalidDeriveOperationException ex) { if (ex.Details != null && ex.Details.Count == 1) { DeriveErrorDetail detail = ex.Details.First(); if (detail.Code == ErrorCode.RuleNotFound || detail.Code == ErrorCode.EmptyRuleCollection) { return(false); } } throw; } }