public void TestVariableAnalysis() { var patternTests = new String[][] { new[] { "A", "[A]", "[]" }, new[] { "A B", "[A, B]", "[]" }, new[] { "A B*", "[A]", "[B]" }, new[] { "A B B", "[A]", "[B]" }, new[] { "A B A", "[B]", "[A]" }, new[] { "A B+ C", "[A, C]", "[B]" }, new[] { "A B?", "[A, B]", "[]" }, new[] { "(A B)* C", "[C]", "[A, B]" }, new[] { "D (A B)+ (G H)? C", "[D, G, H, C]", "[A, B]" }, new[] { "A B | A C", "[A, B, C]", "[]" }, new[] { "(A B*) | (A+ C)", "[C]", "[B, A]" }, new[] { "(A | B) | (C | A)", "[A, B, C]", "[]" }, }; for (int i = 0; i < patternTests.Length; i++) { String pattern = patternTests[i][0]; String expression = "select * from MyEvent.win:keepall() match_recognize (" + " partition by TheString measures A.TheString as a_string pattern ( " + pattern + ") define A as (A.value = 1) )"; EPLTreeWalkerListener walker = SupportParserHelper.ParseAndWalkEPL(expression); StatementSpecRaw raw = walker.GetStatementSpec(); RowRegexExprNode parent = raw.MatchRecognizeSpec.Pattern; var singles = new FIFOHashSet <String>(); var multiples = new FIFOHashSet <String>(); EventRowRegexHelper.RecursiveInspectVariables(parent, false, singles, multiples); String @out = "Failed in :" + pattern + " result is : single " + singles.Render() + " multiple " + multiples.Render(); Assert.AreEqual(patternTests[i][1], singles.Render(), @out); Assert.AreEqual(patternTests[i][2], multiples.Render(), @out); } }
public VariantPropertyDesc ResolveProperty(String propertyName, EventType[] variants) { bool existsInAll = true; Type commonType = null; bool mustCoerce = false; for (int i = 0; i < variants.Length; i++) { Type type = variants[i].GetPropertyType(propertyName); //.GetBoxedType(); if (type == null) { existsInAll = false; continue; } if (commonType == null) { commonType = type; continue; } // compare types if (type == commonType) { continue; } if (type.GetBoxedType() == commonType.GetBoxedType()) { commonType = commonType.GetBoxedType(); continue; } // coercion if (type.IsNumeric()) { if (TypeHelper.CanCoerce(type, commonType)) { mustCoerce = true; continue; } if (TypeHelper.CanCoerce(commonType, type)) { mustCoerce = true; commonType = type; } } else if (commonType == typeof(Object)) { continue; } // common interface or base class else if (!type.IsBuiltinDataType()) { var supersForType = new FIFOHashSet <Type>(); TypeHelper.GetBase(type, supersForType); supersForType.Remove(typeof(Object)); if (supersForType.Contains(commonType)) { continue; // type, or : common type } if (TypeHelper.IsSubclassOrImplementsInterface(commonType, type)) { commonType = type; // common type : type continue; } // find common interface or type both implement var supersForCommonType = new FIFOHashSet <Type>(); TypeHelper.GetBase(commonType, supersForCommonType); supersForCommonType.Remove(typeof(Object)); // Take common classes first, ignoring interfaces bool found = false; foreach (Type superClassType in supersForType) { if (!superClassType.IsInterface && (supersForCommonType.Contains(superClassType))) { break; } } if (found) { continue; } // Take common interfaces foreach (var superClassType in supersForType) { if (superClassType.IsInterface && supersForCommonType.Contains(superClassType)) { commonType = superClassType; found = true; break; } } } commonType = typeof(Object); } if (!existsInAll) { return(null); } if (commonType == null) { return(null); } // property numbers should start at zero since the serve as array index var assignedPropertyNumber = currentPropertyNumber; currentPropertyNumber++; propertyGetterCache.AddGetters(assignedPropertyNumber, propertyName); EventPropertyGetter getter; if (mustCoerce) { SimpleTypeCaster caster = SimpleTypeCasterFactory.GetCaster(null, commonType); getter = new ProxyEventPropertyGetter { ProcGet = eventBean => { var variant = (VariantEvent)eventBean; var propertyGetter = propertyGetterCache.GetGetter(assignedPropertyNumber, variant.UnderlyingEventBean.EventType); if (propertyGetter == null) { return(null); } var value = propertyGetter.Get(variant.UnderlyingEventBean); if (value == null) { return(value); } return(caster.Invoke(value)); }, ProcGetFragment = eventBean => null, ProcIsExistsProperty = eventBean => { var variant = (VariantEvent)eventBean; var propertyGetter = propertyGetterCache.GetGetter(assignedPropertyNumber, variant.UnderlyingEventBean.EventType); if (propertyGetter == null) { return(false); } return(propertyGetter.IsExistsProperty(variant.UnderlyingEventBean)); } }; } else { getter = new ProxyEventPropertyGetter { ProcGet = eventBean => { var variant = (VariantEvent)eventBean; var propertyGetter = propertyGetterCache.GetGetter(assignedPropertyNumber, variant.UnderlyingEventBean.EventType); if (propertyGetter == null) { return(null); } return(propertyGetter.Get(variant.UnderlyingEventBean)); }, ProcGetFragment = eventBean => null, ProcIsExistsProperty = eventBean => { var variant = (VariantEvent)eventBean; var propertyGetter = propertyGetterCache.GetGetter(assignedPropertyNumber, variant.UnderlyingEventBean.EventType); if (propertyGetter == null) { return(false); } return(propertyGetter.IsExistsProperty(variant.UnderlyingEventBean)); } }; } return(new VariantPropertyDesc(commonType, getter, true)); }
/// <summary>Check cyclic dependency and determine processing order for the given graph. </summary> /// <param name="graph">is represented as child nodes that have one or more parent nodes that they are dependent on</param> /// <returns>set of parent and child nodes in order such that no node's dependency is not satisfiedby a prior nodein the set </returns> /// <throws>GraphCircularDependencyException if a dependency has been detected</throws> public static ICollection <String> GetTopDownOrder(IDictionary <String, ICollection <String> > graph) { var circularDependency = GetFirstCircularDependency(graph); if (circularDependency != null) { throw new GraphCircularDependencyException("Circular dependency detected between " + circularDependency.Render()); } var reversedGraph = new Dictionary <String, ICollection <String> >(); // Reversed the graph - build a list of children per parent foreach (var entry in graph) { var parents = entry.Value; var child = entry.Key; foreach (var parent in parents) { var childList = reversedGraph.Get(parent); if (childList == null) { childList = new FIFOHashSet <String>(); reversedGraph.Put(parent, childList); } childList.Add(child); } } // Determine all root nodes, which are those without parent var roots = new SortedSet <String>(); foreach (var parents in graph.Values) { if (parents == null) { continue; } foreach (String parent in parents) { // node not itself a child if (!graph.ContainsKey(parent)) { roots.Add(parent); } } } // for each root, recursively add its child nodes, this becomes the default order ICollection <String> graphFlattened = new FIFOHashSet <String>(); foreach (String root in roots) { RecusiveAdd(graphFlattened, root, reversedGraph); } // now walk down the default order and for each node ensure all parents are created ICollection <String> created = new FIFOHashSet <String>(); ICollection <String> removeList = new HashSet <String>(); while (graphFlattened.IsNotEmpty()) { removeList.Clear(); foreach (String node in graphFlattened) { if (!RecursiveParentsCreated(node, created, graph)) { continue; } created.Add(node); removeList.Add(node); } graphFlattened.RemoveAll(removeList); } return(created); }