static RuleTreeRoot BuildTree(RuleTreeType treeType) { var nodes = GetTreeNodes(treeType, treeType.Input, 0); if (nodes == null || nodes.Length == 0) { return(null); } return(new RuleTreeRoot(nodes, treeType)); }
public RuleTreeRoot(IRuleTreeNode[] children, RuleTreeType treeType) { this.children = children; this.treeType = treeType; Debug.Assert(treeType != null); Debug.Assert(children != null && children.Length > 0); Debug.Assert(children.All(c => (c is RuleTreeLeaf && ((RuleTreeLeaf)c).Rule.Input == treeType.Input) || (c is RuleTreeBranch && ((RuleTreeBranch)c).Rule.Input == treeType.Input) )); }
//TODO: proper job scheduler and discarding superseded jobs public static void QueueAnalysis <T> (T input, RuleTreeType treeType, Action <IList <Result> > callback) { ThreadPool.QueueUserWorkItem(delegate { try { var results = Analyze(input, treeType); callback(results); } catch (Exception ex) { LoggingService.LogError("Error in analysis service", ex); } }); }
public static IList <Result> Analyze <T> (T input, RuleTreeType treeType) { Debug.Assert(typeof(T) == AnalysisExtensions.GetType(treeType.Input)); var tree = AnalysisExtensions.GetAnalysisTree(treeType); if (tree == null) { return(RuleTreeLeaf.Empty); } //force to analyze immediately by evaluating into a list return(tree.Analyze(input).ToList()); }
public static IEnumerable <Result> Analyze <T> (T input, RuleTreeType treeType, CancellationToken cancellationToken = default(CancellationToken)) { Debug.Assert(typeof(T) == AnalysisExtensions.GetType(treeType.Input)); var tree = AnalysisExtensions.GetAnalysisTree(treeType); if (tree == null) { return(RuleTreeLeaf.Empty); } //force to analyze immediately by evaluating into a list return(tree.Analyze(input, cancellationToken).ToList()); }
//recursively builds the rule tree for branches that terminate in leaves (rules with result outputs) static IRuleTreeNode[] GetTreeNodes(RuleTreeType treeType, string input, int depth) { var addinNodes = rulesByInput.Get(input); if (addinNodes == null) { return(null); } var validNodes = addinNodes.Where(n => n.Supports(treeType.FileExtension)).ToList(); if (validNodes.Count == 0) { return(null); } var list = new List <IRuleTreeNode> (); foreach (var n in validNodes) { //leaf node, return directly if (n.Output == RuleTreeLeaf.TYPE) { list.Add(new RuleTreeLeaf(n)); continue; } if (depth > 50) { throw new InvalidOperationException("Analysis tree too deep. Check for circular dependencies " + n.GetErrSource()); } //get the nodes that will handle the output - by recursively calling this var childNodes = GetTreeNodes(treeType, n.Output, depth + 1); //if no child nodes are returned, don't even return this, because its output won't be used if (childNodes == null || childNodes.Length == 0) { continue; } list.Add(new RuleTreeBranch(childNodes, n)); } return(list.ToArray()); }
// Gets an analysis tree from the cache, or creates one. // Cache may have null value if there were no nodes for the type. public static RuleTreeRoot GetAnalysisTree(RuleTreeType treeType) { RuleTreeRoot tree; if (analysisTreeCache.TryGetValue(treeType, out tree)) { return(tree); } analysisTreeCache [treeType] = tree = BuildTree(treeType); #if DEBUG_ANALYSIS_TREE if (tree != null) { Console.WriteLine(tree.GetTreeStructure()); } #endif return(tree); }
public RuleTreeRoot (IRuleTreeNode[] children, RuleTreeType treeType) { this.children = children; this.treeType = treeType; Debug.Assert (treeType != null); Debug.Assert (children != null && children.Length > 0); Debug.Assert (children.All (c => (c is RuleTreeLeaf && ((RuleTreeLeaf)c).Rule.Input == treeType.Input) || (c is RuleTreeBranch && ((RuleTreeBranch)c).Rule.Input == treeType.Input) )); }
public static Task <IEnumerable <Result> > QueueAnalysis <T> (T input, RuleTreeType treeType, CancellationToken cancellationToken = default(CancellationToken)) { return(Task.Factory.StartNew(() => Analyze(input, treeType, cancellationToken), cancellationToken)); }