/// <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)));
        }
Пример #2
0
        /// <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);
            }
        }
Пример #3
0
 /// <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)));
 }
Пример #4
0
        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();
        }
Пример #5
0
 /// <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);
        }
Пример #7
0
        /// <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);
        }
Пример #8
0
        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);
        }
Пример #9
0
        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();
        }
Пример #10
0
        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));
            }
        }
Пример #11
0
        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();
        }
Пример #12
0
        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;
 }
Пример #14
0
        /// <inheritdoc/>
        public virtual bool Contains <TFact>(TFact fact) where TFact : IFact
        {
            IFactType factType = fact.GetFactType();

            return(ContainerList.Contains(fact, GetEqualityComparer()));
        }
Пример #15
0
        /// <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)));
        }
Пример #16
0
 /// <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)));
 }
Пример #17
0
 /// <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);
 }
Пример #19
0
 protected override Rule CreateFactRule(Func <IEnumerable <IFact>, ValueTask <IFact> > func, List <IFactType> inputFactTypes, IFactType outputFactType, FactWorkOption option)
 {
     throw new NotImplementedException();
 }
Пример #20
0
 /// <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);
        }
Пример #22
0
        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();
        }
Пример #23
0
 /// <inheritdoc/>
 public FactRule(Func <IEnumerable <IFact>, ValueTask <IFact> > funcAsync, List <IFactType> inputFactTypes, IFactType outputFactType, FactWorkOption option)
     : base(funcAsync, inputFactTypes, outputFactType, option)
 {
 }
Пример #24
0
        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;
            }
        }