private IRule <TModel> LoadLogic(string equationId) { StepTracer <LintTrace> trace = new StepTracer <LintTrace>(); StepTraceNode <LintTrace> root = trace.TraceFirst(new LintTrace(LintStatusOptions.Loading, "Loading Logic", equationId)); //Lint.... make sure we have everything we need first. Func <LogicDefine.Rule, StepTraceNode <LintTrace>, bool, IRule <TModel> > LoadRule = null; LoadRule = (rule, parentStep, inner) => { StepTraceNode <LintTrace> step = trace.TraceNext(parentStep, new LintTrace(LintStatusOptions.Inspecting, "Inspecting Rule", rule.Id)); IRule <TModel> toReturn = null; //if id is an equation, we are creating an expression //since we've formalized convention, we can just check that if (ConventionHelper.MatchesConvention(NamePrefixOptions.Equation, rule.Id, this.Configuration.Convention)) { LogicDefine.Equation eq = this.WorkflowManager.GetEquation(rule.Id); IRule <TModel> first = LoadRule(eq.First, step, true); IRule <TModel> second = LoadRule(eq.Second, step, true); toReturn = new Expression <TModel>(rule, eq.Condition, first, second, this, inner); } else { LogicDefine.Evaluator ev = this.WorkflowManager.GetEvaluator(rule.Id); toReturn = new Rule <TModel>(rule, this, inner); } return(toReturn); }; LogicDefine.Rule eqRule = equationId; IRule <TModel> loaded = LoadRule(eqRule, root, false); return(loaded); }
public List <LogicTest> LogicLint() { int id = 1; Func <int> newId = () => { return(id += 1); }; List <bool> tf = new List <bool>() { true, false }; Func <Equation, List <Rule> > getAllRulesForEquation = null; getAllRulesForEquation = (eq) => { List <Rule> rules = new List <Rule>(); //left hand side of equation if (ConventionHelper.MatchesConvention(NamePrefixOptions.Equation, eq.First.Id, this.configuration.Convention)) { Equation traverse = this.WorkflowManager.GetEquation(eq.First.Id); List <Rule> parsed = getAllRulesForEquation(traverse); rules = rules.Union(parsed, new RuleEqualityComparer()).ToList(); } else { if (!rules.Contains(eq.First, new RuleEqualityComparer())) { rules.Add((Rule)eq.First.Clone()); } } if (ConventionHelper.MatchesConvention(NamePrefixOptions.Equation, eq.Second.Id, this.configuration.Convention)) { Equation traverse = this.WorkflowManager.GetEquation(eq.Second.Id); List <Rule> parsed = getAllRulesForEquation(traverse); rules = rules.Union(parsed, new RuleEqualityComparer()).ToList(); } else { if (!rules.Contains(eq.Second, new RuleEqualityComparer())) { rules.Add((Rule)eq.Second.Clone()); } } string trueId = ConventionHelper.TrueEvaluator(this.configuration.Convention); return((from r in rules where r.Id != trueId select r).ToList()); }; Func <Stack <List <Case> >, List <Case> > mergeCases = null; mergeCases = (llc) => { List <Case> merged = llc.Pop(); if (llc.Count > 0) { List <Case> toMerge = mergeCases(llc); List <Case> newMerge = new List <Case>(); merged.ForEach(m => { toMerge.ForEach(g => { List <Rule> newCaseRules = new List <Rule>(from r in m.Rules select(Rule) r.Clone()); newCaseRules.AddRange(from r in g.Rules select(Rule) r.Clone()); Case newCase = new Case(newCaseRules); newMerge.Add(newCase); }); }); merged = newMerge; } return(merged); }; if (this.logicTests == default) { this.logicTests = new List <LogicTest>(); //get the root foreach (string rootEquationId in this.roots) { Stack <List <Case> > preMerge = new Stack <List <Case> >(); Equation root = this.WorkflowManager.GetEquation(rootEquationId); List <Rule> evalRules = getAllRulesForEquation(root); foreach (Rule evalRule in evalRules) { List <Case> evalRuleCases = new List <Case>(); if (evalRule.Context == null) { evalRuleCases.AddRange(from c in tf select new Case(new List <Rule>() { new Rule() { Context = evalRule.Context, Id = evalRule.Id, TrueCondition = c } })); } else { Stack <List <Case> > contextCases = new Stack <List <Case> >(); evalRule.Context.Keys.ForEach(k => { List <Case> cases = new List <Case>(); cases.AddRange(from c in tf select new Case(new List <Rule>() { new Rule() { Context = new Context(new List <string>() { k }, evalRule.Context.Name), Id = evalRule.Id, TrueCondition = c } })); contextCases.Push(cases); evalRuleCases = mergeCases(contextCases); contextCases.Push(evalRuleCases); }); var contextDef = this.WorkflowManager.GetContextDefinition(evalRule.Context.Name); if (contextDef.Validate == ValidateOptions.OneOf) { evalRuleCases.RemoveAll(c => c.Rules.Count(r => r.TrueCondition) != 1 && c.Rules.Any(r => r.TrueCondition)); } if (contextDef.Exclusive) { evalRuleCases.RemoveAll(c => c.Rules.Count(r => !r.TrueCondition) == c.Rules.Count() && c.Rules.Count == contextDef.Items.Count); } } preMerge.Push(evalRuleCases); } List <Case> finalCases = mergeCases(preMerge); LogicTest eqTest = new LogicTest(rootEquationId, true) { TestCases = finalCases }; this.logicTests.Add(eqTest); } } return(this.logicTests); }
public ArticulateActivity ArticulateFlow(bool removeConvention, bool verbose) { Func <WorkDefine.ActionRef, IArticulateActivity> createAction = (s) => { var actionDef = this.workflow.Actions.FirstOrDefault(g => g.Id == s.Id); ArticulateAction action = new ArticulateAction() { Id = s.Id, Literal = actionDef.Description }; if (s.Id == "*placeHolder") { return(new NothingAction()); } else { if (s.Input != null) { ArticulateContext articulateContext = new ArticulateContext() { Literal = "Input", Value = s.Input }; action.Context = articulateContext; } return(action); } }; ArticulateActivity toReturn = new ArticulateActivity(); string activityId = workflow.Id; activityId = $"{ConventionHelper.EnsureConvention(NamePrefixOptions.Activity, activityId, this.configuration.Convention)}.Main"; WorkDefine.Activity toArticulate = this.workflow.Activities.FirstOrDefault(g => g.Id == activityId); toReturn.Id = toArticulate.Id; Func <LogicDefine.Rule, IArticulateExpression> traverseExpression = null; traverseExpression = (x) => { IArticulateExpression buildExpression = null; if (ConventionHelper.MatchesConvention(NamePrefixOptions.Evaluator, x.Id, this.configuration.Convention)) { buildExpression = this.ArticulateEvaluator(x); } else { ArticulateExpression toBuild = new ArticulateExpression() { Id = x.Id }; LogicDefine.Equation eq = this.workflow.Equations.FirstOrDefault(g => g.Id == x.Id); toBuild.Condition = (eq.Condition == Logic.Operand.And) ? "and": "or"; Rule asRule = x.ShortHand; toBuild.TrueCondition = asRule.TrueCondition; toBuild.First = traverseExpression(eq.First); toBuild.Second = traverseExpression(eq.Second); buildExpression = toBuild; } return(buildExpression); }; Action <ArticulateActivity, WorkDefine.Activity> traverseActivity = null; traverseActivity = (a, d) => { if (d.Reactions != null && d.Reactions.Count() > 0) { a.Reactions = new List <ArticulateReaction>(); d.Reactions.ForEach(r => { //all logic at this point should be equations //if logic = true, then if = "Always". ArticulateReaction toAdd = new ArticulateReaction(); if (r.Logic == ConventionHelper.TrueEquation(this.configuration.Convention)) { toAdd.If = new TrueExpression(); } else { toAdd.If = traverseExpression(r.Logic); } WorkDefine.ActionRef aref = r.Work; if (ConventionHelper.MatchesConvention(NamePrefixOptions.Action, aref.Id, this.configuration.Convention)) { toAdd.Then = createAction(aref); } else { WorkDefine.Activity toTraverse = this.workflow.Activities.FirstOrDefault(g => g.Id == aref.Id); ArticulateActivity Then = new ArticulateActivity() { Id = aref.Id }; traverseActivity(Then, toTraverse); toAdd.Then = Then; } a.Reactions.Add(toAdd); }); } }; traverseActivity(toReturn, toArticulate); return(toReturn); }