/// <inheritdoc/> public virtual TFactRuleCollection ValidateAndGetRules <TFactRule, TFactRuleCollection>(TFactRuleCollection ruleCollection) where TFactRule : IFactRule where TFactRuleCollection : IFactRuleCollection <TFactRule> { // Get a copy of the rules if (ruleCollection == null) { throw CommonHelper.CreateDeriveException(ErrorCode.InvalidData, "Rules cannot be null."); } IFactRuleCollection <TFactRule> rulesCopy = ruleCollection.Copy(); if (rulesCopy == null) { throw CommonHelper.CreateDeriveException(ErrorCode.InvalidData, "IFactRuleCollection.Copy method return null."); } if (rulesCopy.Equals(ruleCollection)) { throw CommonHelper.CreateDeriveException(ErrorCode.InvalidData, "IFactRuleCollection.Copy method return original rule collection."); } if (!(rulesCopy is TFactRuleCollection rules)) { throw CommonHelper.CreateDeriveException(ErrorCode.InvalidData, "IFactRuleCollection.Copy method returned a different type of rules."); } rules.IsReadOnly = true; return(rules); }
/// <summary> /// Synchronize tree levels with years ready for calculation. /// </summary> /// <typeparam name="TFactRule">FatcRule type.</typeparam> /// <typeparam name="TWantAction">WantAction type.</typeparam> /// <typeparam name="TFactContainer">FactContainer type.</typeparam> /// <param name="treeByFactRule">Tree whose levels you want to synchronize.</param> /// <param name="level">The level at which to start synchronization.</param> /// <param name="finishedNodes"></param> /// <returns>True - managed to sync root level</returns> private bool TrySyncTreeLevelsAndFinishedNodes <TFactRule, TWantAction, TFactContainer>(TreeByFactRule <TFactRule, TWantAction, TFactContainer> treeByFactRule, int level, Dictionary <NodeByFactRuleInfo <TFactRule>, NodeByFactRule <TFactRule> > finishedNodes) where TFactRule : IFactRule where TWantAction : IWantAction where TFactContainer : IFactContainer { if (level < 0) { return(true); } var context = treeByFactRule.Context; List <NodeByFactRule <TFactRule> > currentLevel = treeByFactRule.Levels[level]; var finishedNodesInCurrentLevel = new Dictionary <NodeByFactRuleInfo <TFactRule>, NodeByFactRule <TFactRule> >(); foreach (var node in currentLevel) { TFactRule rule = node.Info.Rule; IFactRuleCollection <TFactRule> finishedRules = context .FactRules .FindAll(r => finishedNodes.Any(n => n.Key.Rule.EqualsWork(r, context.WantAction, context.Container))); IFactRuleCollection <TFactRule> copabilitiesFinishedRules = rule.GetCompatibleRulesEx(finishedRules, context); if (rule.InputFactTypes.Count == 0) { finishedNodesInCurrentLevel.Add(node.Info, node); } else if (node.Info.RequiredFactTypes.All(requiredFactType => !requiredFactType.IsBuildOrRuntimeFact() && copabilitiesFinishedRules.Any(r => r.OutputFactType.EqualsFactType(requiredFactType)))) { finishedNodesInCurrentLevel.Add(node.Info, node); } else if (copabilitiesFinishedRules.Any(r => r.EqualsWork(rule, context.WantAction, context.Container))) { finishedNodesInCurrentLevel.Add(node.Info, node); } } if (finishedNodesInCurrentLevel.IsNullOrEmpty()) { return(false); } SyncTreeLevelAndFinishedNodes(currentLevel, finishedNodesInCurrentLevel, context); foreach (var finishedNode in finishedNodesInCurrentLevel) { if (finishedNodes.Keys.Any(nodeInfo => nodeInfo.Rule.EqualsWork(finishedNode.Key.Rule, context.WantAction, context.Container))) { continue; } finishedNodes.Add(finishedNode.Key, finishedNode.Value); } return(TrySyncTreeLevelsAndFinishedNodes(treeByFactRule, level - 1, finishedNodes)); }
/// <inheritdoc/> public virtual bool TryGetRelatedRules <TFactRule, TWantAction, TFactContainer>(IWantActionContext <TWantAction, TFactContainer> context, out IFactRuleCollection <TFactRule> relatedRules) where TFactRule : IFactRule where TWantAction : IWantAction where TFactContainer : IFactContainer { relatedRules = null; if (_relatedRules is IFactRuleCollection <TFactRule> result) { relatedRules = result; return(true); } if (_getRelatedRulesFunc is Func <TFactRule, IFactRuleCollection <TFactRule>, IWantActionContext <TWantAction, TFactContainer>, IFactRuleCollection <TFactRule> > getRelatedRulesFunc && _rules is IFactRuleCollection <TFactRule> rules && _rule is TFactRule rule) { relatedRules = getRelatedRulesFunc(rule, rules, context); _relatedRules = relatedRules; return(true); } return(false); }
/// <inheritdoc/> public void SetGetRelatedRulesFunc <TFactRule, TWantAction, TFactContainer>(Func <TFactRule, IFactRuleCollection <TFactRule>, IWantActionContext <TWantAction, TFactContainer>, IFactRuleCollection <TFactRule> > getRelatedRulesFunc, TFactRule rule, IFactRuleCollection <TFactRule> rules) where TFactRule : IFactRule where TWantAction : IWantAction where TFactContainer : IFactContainer { _getRelatedRulesFunc = getRelatedRulesFunc; _rules = rules; _rule = rule; }
internal static IFactRuleCollection <TFactRule> GetCompatibleRulesEx <TFactWork, TFactRule, TWantAction, TFactContainer>(this TFactWork target, IFactRuleCollection <TFactRule> rules, IWantActionContext <TWantAction, TFactContainer> context) where TFactWork : IFactWork where TFactRule : IFactRule where TWantAction : IWantAction where TFactContainer : IFactContainer { return(context.SingleEntity.GetCompatibleRules(target, rules, context)); }
/// <inheritdoc/> /// <remarks>Additionally checks version compatibility.</remarks> public override IFactRuleCollection <TFactRule> GetCompatibleRules <TFactWork, TFactRule, TWantAction, TFactContainer>(TFactWork target, IFactRuleCollection <TFactRule> factRules, IWantActionContext <TWantAction, TFactContainer> context) { var result = base.GetCompatibleRules(target, factRules, context); var maxVersion = context.WantAction.InputFactTypes.GetVersionFact(context); if (maxVersion == null) { return(result); } return(result.FindAll(rule => rule.CompatibleRule(maxVersion, context))); }
/// <inheritdoc/> public virtual IFactRuleCollection <TFactRule> GetCompatibleRules <TFactWork, TFactRule, TWantAction, TFactContainer>(TFactWork target, IFactRuleCollection <TFactRule> factRules, IWantActionContext <TWantAction, TFactContainer> context) where TFactWork : IFactWork where TFactRule : IFactRule where TWantAction : IWantAction where TFactContainer : IFactContainer { return(factRules); }
internal static bool CanDeriveFact <TFactWork, TFactRule, TWantAction, TFactContainer>(IBuildConditionFact conditionFact, IFactType searchFactType, TFactWork factWork, IFactRuleCollection <TFactRule> compatibleRules, IWantActionContext <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 = compatibleRules .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; } }