示例#1
0
        public void TestNodeGetSet()
        {
            FilterHandle exprOne = new SupportFilterHandle();

            // Check pre-conditions
            Assert.IsTrue(_testNode.NodeRWLock != null);
            Assert.IsFalse(_testNode.Contains(exprOne));
            Assert.AreEqual(0, _testNode.FilterCallbackCount);
            Assert.AreEqual(0, _testNode.Indizes.Count);
            Assert.IsTrue(_testNode.IsEmpty());

            _testNode.Add(exprOne);

            // Check after add
            Assert.IsTrue(_testNode.Contains(exprOne));
            Assert.AreEqual(1, _testNode.FilterCallbackCount);
            Assert.IsFalse(_testNode.IsEmpty());

            // Add an indexOne
            EventType            eventType  = SupportEventTypeFactory.CreateBeanType(typeof(SupportBean));
            FilterSpecLookupable lookupable = new FilterSpecLookupable("IntPrimitive", eventType.GetGetter("IntPrimitive"), eventType.GetPropertyType("IntPrimitive"), false);
            FilterParamIndexBase indexOne   = new SupportFilterParamIndex(lookupable);

            _testNode.Add(indexOne);

            // Check after add
            Assert.AreEqual(1, _testNode.Indizes.Count);
            Assert.AreEqual(indexOne, _testNode.Indizes.FirstOrDefault());

            // Check removes
            Assert.IsTrue(_testNode.Remove(exprOne));
            Assert.IsFalse(_testNode.IsEmpty());
            Assert.IsFalse(_testNode.Remove(exprOne));
            Assert.IsTrue(_testNode.Remove(indexOne));
            Assert.IsFalse(_testNode.Remove(indexOne));
            Assert.IsTrue(_testNode.IsEmpty());
        }
 public MyGetterUpdateListener(EventType eventType)
 {
     symbolGetter = eventType.GetGetter("Symbol");
     volumeGetter = eventType.GetGetter("Volume");
 }
示例#3
0
 private FilterSpecLookupable MakeLookupable(String fieldName, EventType eventType)
 {
     return(new FilterSpecLookupable(fieldName, eventType.GetGetter(fieldName), eventType.GetPropertyType(fieldName), false));
 }
示例#4
0
        /// <summary>
        /// Ctor.
        /// </summary>
        /// <param name="eventType">to render</param>
        /// <param name="stack">the stack of properties to avoid looping</param>
        /// <param name="options">rendering options</param>
        public RendererMeta(EventType eventType, Stack <EventTypePropertyPair> stack, RendererMetaOptions options)
        {
            var gettersSimple  = new List <GetterPair>();
            var gettersIndexed = new List <GetterPair>();
            var gettersMapped  = new List <GetterPair>();
            var gettersNested  = new List <NestedGetterPair>();

            var descriptors = eventType.PropertyDescriptors;

            foreach (EventPropertyDescriptor desc in descriptors)
            {
                String propertyName = desc.PropertyName;

                if ((!desc.IsIndexed) && (!desc.IsMapped) && (!desc.IsFragment))
                {
                    var getter = eventType.GetGetter(propertyName);
                    if (getter == null)
                    {
                        log.Warn("No getter returned for event type '" + eventType.Name + "' and property '" +
                                 propertyName + "'");
                        continue;
                    }
                    gettersSimple.Add(new GetterPair(getter, propertyName,
                                                     OutputValueRendererFactory.GetOutputValueRenderer(
                                                         desc.PropertyType, options)));
                }

                if (desc.IsIndexed && !desc.RequiresIndex && (!desc.IsFragment))
                {
                    var getter = eventType.GetGetter(propertyName);
                    if (getter == null)
                    {
                        log.Warn("No getter returned for event type '" + eventType.Name + "' and property '" +
                                 propertyName + "'");
                        continue;
                    }
                    gettersIndexed.Add(new GetterPair(getter, propertyName,
                                                      OutputValueRendererFactory.GetOutputValueRenderer(
                                                          desc.PropertyType, options)));
                }

                if (desc.IsMapped && !desc.RequiresMapKey && (!desc.IsFragment))
                {
                    var getter = eventType.GetGetter(propertyName);
                    if (getter == null)
                    {
                        log.Warn("No getter returned for event type '" + eventType.Name + "' and property '" +
                                 propertyName + "'");
                        continue;
                    }
                    gettersMapped.Add(new GetterPair(getter, propertyName,
                                                     OutputValueRendererFactory.GetOutputValueRenderer(
                                                         desc.PropertyType, options)));
                }

                if (desc.IsFragment)
                {
                    var getter       = eventType.GetGetter(propertyName);
                    var fragmentType = eventType.GetFragmentType(propertyName);
                    if (getter == null)
                    {
                        log.Warn("No getter returned for event type '" + eventType.Name + "' and property '" +
                                 propertyName + "'");
                        continue;
                    }
                    if (fragmentType == null)
                    {
                        log.Warn("No fragment type returned for event type '" + eventType.Name + "' and property '" +
                                 propertyName + "'");
                        continue;
                    }

                    var pair = new EventTypePropertyPair(fragmentType.FragmentType, propertyName);
                    if ((options.PreventLooping && stack.Contains(pair)))
                    {
                        continue; // prevent looping behavior on self-references
                    }

                    stack.Push(pair);
                    var fragmentMetaData = new RendererMeta(fragmentType.FragmentType, stack, options);
                    stack.Pop();

                    gettersNested.Add(new NestedGetterPair(getter, propertyName, fragmentMetaData,
                                                           fragmentType.IsIndexed));
                }
            }

            gettersSimple.Sort((gp1, gp2) => gp1.Name.CompareTo(gp2.Name));
            gettersIndexed.Sort((gp1, gp2) => gp1.Name.CompareTo(gp2.Name));
            gettersMapped.Sort((gp1, gp2) => gp1.Name.CompareTo(gp2.Name));
            gettersNested.Sort((gp1, gp2) => gp1.Name.CompareTo(gp2.Name));

            simpleProperties = gettersSimple.ToArray();
            indexProperties  = gettersIndexed.ToArray();
            mappedProperties = gettersMapped.ToArray();
            nestedProperties = gettersNested.ToArray();
        }
 private FilterSpecLookupable MakeLookupable(String fieldName) {
     return new FilterSpecLookupable(fieldName, _testEventType.GetGetter(fieldName), _testEventType.GetPropertyType(fieldName), false);
 }
 private static FilterSpecLookupable MakeLookupable(EventType eventType, String fieldName)
 {
     return(new FilterSpecLookupable(fieldName, eventType.GetGetter(fieldName), eventType.GetPropertyType(fieldName)));
 }
示例#7
0
        public IntervalOpImpl(DatetimeMethodEnum method, String methodNameUse, StreamTypeService streamTypeService, IList <ExprNode> expressions)
        {
            ExprEvaluator evaluatorEndTimestamp = null;
            Type          timestampType;

            if (expressions[0] is ExprStreamUnderlyingNode)
            {
                var und = (ExprStreamUnderlyingNode)expressions[0];
                _parameterStreamNum = und.StreamId;
                EventType type = streamTypeService.EventTypes[_parameterStreamNum];
                _parameterPropertyStart = type.StartTimestampPropertyName;
                if (_parameterPropertyStart == null)
                {
                    throw new ExprValidationException("For date-time method '" + methodNameUse + "' the first parameter is event type '" + type.Name + "', however no timestamp property has been defined for this event type");
                }

                timestampType = type.GetPropertyType(_parameterPropertyStart);
                EventPropertyGetter getter = type.GetGetter(_parameterPropertyStart);
                _evaluatorTimestamp = new ExprEvaluatorStreamLongProp(_parameterStreamNum, getter);

                if (type.EndTimestampPropertyName != null)
                {
                    _parameterPropertyEnd = type.EndTimestampPropertyName;
                    EventPropertyGetter getterEndTimestamp = type.GetGetter(type.EndTimestampPropertyName);
                    evaluatorEndTimestamp = new ExprEvaluatorStreamLongProp(_parameterStreamNum, getterEndTimestamp);
                }
                else
                {
                    _parameterPropertyEnd = _parameterPropertyStart;
                }
            }
            else
            {
                _evaluatorTimestamp = expressions[0].ExprEvaluator;
                timestampType       = _evaluatorTimestamp.ReturnType;

                String unresolvedPropertyName = null;
                if (expressions[0] is ExprIdentNode)
                {
                    var identNode = (ExprIdentNode)expressions[0];
                    _parameterStreamNum     = identNode.StreamId;
                    _parameterPropertyStart = identNode.ResolvedPropertyName;
                    _parameterPropertyEnd   = _parameterPropertyStart;
                    unresolvedPropertyName  = identNode.UnresolvedPropertyName;
                }

                if (!_evaluatorTimestamp.ReturnType.IsDateTime())
                {
                    // ident node may represent a fragment
                    if (unresolvedPropertyName != null)
                    {
                        var propertyDesc = ExprIdentNodeUtil.GetTypeFromStream(
                            streamTypeService, unresolvedPropertyName, false, true);
                        if (propertyDesc.First.FragmentEventType != null)
                        {
                            EventType type = propertyDesc.First.FragmentEventType.FragmentType;
                            _parameterPropertyStart = type.StartTimestampPropertyName;
                            if (_parameterPropertyStart == null)
                            {
                                throw new ExprValidationException("For date-time method '" + methodNameUse + "' the first parameter is event type '" + type.Name + "', however no timestamp property has been defined for this event type");
                            }

                            timestampType = type.GetPropertyType(_parameterPropertyStart);
                            EventPropertyGetter getterFragment       = streamTypeService.EventTypes[_parameterStreamNum].GetGetter(unresolvedPropertyName);
                            EventPropertyGetter getterStartTimestamp = type.GetGetter(_parameterPropertyStart);
                            _evaluatorTimestamp = new ExprEvaluatorStreamLongPropFragment(_parameterStreamNum, getterFragment, getterStartTimestamp);

                            if (type.EndTimestampPropertyName != null)
                            {
                                _parameterPropertyEnd = type.EndTimestampPropertyName;
                                EventPropertyGetter getterEndTimestamp = type.GetGetter(type.EndTimestampPropertyName);
                                evaluatorEndTimestamp = new ExprEvaluatorStreamLongPropFragment(_parameterStreamNum, getterFragment, getterEndTimestamp);
                            }
                            else
                            {
                                _parameterPropertyEnd = _parameterPropertyStart;
                            }
                        }
                    }
                    else
                    {
                        throw new ExprValidationException("For date-time method '" + methodNameUse + "' the first parameter expression returns '" + _evaluatorTimestamp.ReturnType.FullName + "', however requires a DateTime or Long-type return value or event (with timestamp)");
                    }
                }
            }

            IntervalComputer intervalComputer = IntervalComputerFactory.Make(method, expressions);

            // evaluation without end timestamp
            var timestampTypeBoxed = timestampType != null?timestampType.GetBoxedType() : timestampType;

            if (evaluatorEndTimestamp == null)
            {
                if (timestampTypeBoxed == typeof(DateTime?) || timestampTypeBoxed == typeof(DateTimeOffset?))
                {
                    _intervalOpEval = new IntervalOpEvalCal(intervalComputer);
                }
                else if (timestampTypeBoxed == typeof(long?))
                {
                    _intervalOpEval = new IntervalOpEvalLong(intervalComputer);
                }
                else
                {
                    throw new ArgumentException("Invalid interval first parameter type '" + timestampType + "'");
                }
            }
            else
            {
                if (timestampTypeBoxed == typeof(DateTime?) || timestampTypeBoxed == typeof(DateTimeOffset?))
                {
                    _intervalOpEval = new IntervalOpEvalCalWithEnd(intervalComputer, evaluatorEndTimestamp);
                }
                else if (timestampTypeBoxed == typeof(long?))
                {
                    _intervalOpEval = new IntervalOpEvalLongWithEnd(intervalComputer, evaluatorEndTimestamp);
                }
                else
                {
                    throw new ArgumentException("Invalid interval first parameter type '" + timestampType + "'");
                }
            }
        }
示例#8
0
        public override ExprNode Validate(ExprValidationContext validationContext)
        {
            // rewrite expression into a table-access expression
            if (validationContext.StreamTypeService.HasTableTypes)
            {
                ExprTableIdentNode tableIdentNode = validationContext.TableService.GetTableIdentNode(validationContext.StreamTypeService, _unresolvedPropertyName, _streamOrPropertyName);
                if (tableIdentNode != null)
                {
                    return(tableIdentNode);
                }
            }

            string unescapedPropertyName = PropertyParser.UnescapeBacktick(_unresolvedPropertyName);
            Pair <PropertyResolutionDescriptor, string> propertyInfoPair = ExprIdentNodeUtil.GetTypeFromStream(validationContext.StreamTypeService, unescapedPropertyName, _streamOrPropertyName, false);

            _resolvedStreamName = propertyInfoPair.Second;
            int  streamNum    = propertyInfoPair.First.StreamNum;
            Type propertyType = propertyInfoPair.First.PropertyType;

            _resolvedPropertyName = propertyInfoPair.First.PropertyName;
            EventPropertyGetter propertyGetter;

            try {
                propertyGetter = propertyInfoPair.First.StreamEventType.GetGetter(_resolvedPropertyName);
            }
            catch (PropertyAccessException ex) {
                throw new ExprValidationException("Property '" + _unresolvedPropertyName + "' is not valid: " + ex.Message, ex);
            }

            if (propertyGetter == null)
            {
                throw new ExprValidationException("Property getter returned was invalid for property '" + _unresolvedPropertyName + "'");
            }

            var audit = AuditEnum.PROPERTY.GetAudit(validationContext.Annotations);

            if (audit != null)
            {
                _evaluator = new ExprIdentNodeEvaluatorLogging(streamNum, propertyGetter, propertyType, this, _resolvedPropertyName, validationContext.StatementName, validationContext.StreamTypeService.EngineURIQualifier);
            }
            else
            {
                _evaluator = new ExprIdentNodeEvaluatorImpl(streamNum, propertyGetter, propertyType, this);
            }

            // if running in a context, take the property value from context
            if (validationContext.ContextDescriptor != null && !validationContext.IsFilterExpression)
            {
                EventType fromType            = validationContext.StreamTypeService.EventTypes[streamNum];
                string    contextPropertyName = validationContext.ContextDescriptor.ContextPropertyRegistry.GetPartitionContextPropertyName(fromType, _resolvedPropertyName);
                if (contextPropertyName != null)
                {
                    EventType contextType = validationContext.ContextDescriptor.ContextPropertyRegistry.ContextEventType;
                    _evaluator = new ExprIdentNodeEvaluatorContext(streamNum, contextType.GetPropertyType(contextPropertyName), contextType.GetGetter(contextPropertyName));
                }
            }
            return(null);
        }
示例#9
0
 public FragmentTypeEval(int streamId, EventType eventType, string resolvedPropertyName)
 {
     _streamId     = streamId;
     _getter       = eventType.GetGetter(resolvedPropertyName);
     _fragmentType = eventType.GetFragmentType(resolvedPropertyName).FragmentType.Name;
 }
示例#10
0
        internal static Type[] ValidateContextDesc(String contextName, ContextDetailPartitioned segmentedSpec)
        {
            if (segmentedSpec.Items.IsEmpty())
            {
                throw new ExprValidationException("Empty list of partition items");
            }

            // verify properties exist
            foreach (ContextDetailPartitionItem item in segmentedSpec.Items)
            {
                EventType type = item.FilterSpecCompiled.FilterForEventType;
                foreach (String property in item.PropertyNames)
                {
                    EventPropertyGetter getter = type.GetGetter(property);
                    if (getter == null)
                    {
                        throw new ExprValidationException(
                                  "For context '" + contextName + "' property name '" + property + "' not found on type " +
                                  type.Name);
                    }
                }
            }

            // verify property number and types compatible
            ContextDetailPartitionItem firstItem = segmentedSpec.Items[0];

            if (segmentedSpec.Items.Count > 1)
            {
                // verify the same filter event type is only listed once

                for (int i = 0; i < segmentedSpec.Items.Count; i++)
                {
                    var compareTo = segmentedSpec.Items[i].FilterSpecCompiled.FilterForEventType;

                    for (int j = 0; j < segmentedSpec.Items.Count; j++)
                    {
                        if (i == j)
                        {
                            continue;
                        }

                        var compareFrom = segmentedSpec.Items[j].FilterSpecCompiled.FilterForEventType;
                        if (compareFrom == compareTo)
                        {
                            throw new ExprValidationException(
                                      "For context '" + contextName + "' the event type '" + compareFrom.Name +
                                      "' is listed twice");
                        }
                        if (EventTypeUtility.IsTypeOrSubTypeOf(compareFrom, compareTo) ||
                            EventTypeUtility.IsTypeOrSubTypeOf(compareTo, compareFrom))
                        {
                            throw new ExprValidationException(
                                      "For context '" + contextName + "' the event type '" + compareFrom.Name +
                                      "' is listed twice: Event type '" +
                                      compareFrom.Name + "' is a subtype or supertype of event type '" + compareTo.Name + "'");
                        }
                    }
                }

                // build property type information
                var names      = new String[firstItem.PropertyNames.Count];
                var types      = new Type[firstItem.PropertyNames.Count];
                var typesBoxed = new Type[firstItem.PropertyNames.Count];
                for (int i = 0; i < firstItem.PropertyNames.Count; i++)
                {
                    String property = firstItem.PropertyNames[i];
                    names[i]      = property;
                    types[i]      = firstItem.FilterSpecCompiled.FilterForEventType.GetPropertyType(property);
                    typesBoxed[i] = types[i].GetBoxedType();
                }

                // compare property types and numbers
                for (int item = 1; item < segmentedSpec.Items.Count; item++)
                {
                    ContextDetailPartitionItem nextItem = segmentedSpec.Items[item];

                    // compare number of properties
                    if (nextItem.PropertyNames.Count != types.Length)
                    {
                        throw new ExprValidationException(
                                  string.Format(
                                      "For context '{0}' expected the same number of property names for each event type, found {1} properties for event type '{2}' and {3} properties for event type '{4}'",
                                      contextName,
                                      types.Length,
                                      firstItem.FilterSpecCompiled.FilterForEventType.Name,
                                      nextItem.PropertyNames.Count,
                                      nextItem.FilterSpecCompiled.FilterForEventType.Name));
                    }

                    // compare property types
                    for (int i = 0; i < nextItem.PropertyNames.Count; i++)
                    {
                        String property = nextItem.PropertyNames[i];
                        var    type     =
                            nextItem.FilterSpecCompiled.FilterForEventType.GetPropertyType(property).GetBoxedType();
                        var typeBoxed = type.GetBoxedType();
                        var left      = TypeHelper.IsSubclassOrImplementsInterface(typeBoxed, typesBoxed[i]);
                        var right     = TypeHelper.IsSubclassOrImplementsInterface(typesBoxed[i], typeBoxed);
                        if (typeBoxed != typesBoxed[i] && !left && !right)
                        {
                            throw new ExprValidationException(
                                      string.Format(
                                          "For context '{0}' for context '{0}' found mismatch of property types, property '{1}' of type '{2}' compared to property '{3}' of type '{4}'",
                                          contextName,
                                          names[i],
                                          TypeHelper.GetTypeNameFullyQualPretty(types[i]),
                                          property,
                                          TypeHelper.GetTypeNameFullyQualPretty(typeBoxed)));
                        }
                    }
                }
            }

            var propertyTypes = new Type[firstItem.PropertyNames.Count];

            for (int i = 0; i < firstItem.PropertyNames.Count; i++)
            {
                String property = firstItem.PropertyNames[i];
                propertyTypes[i] = firstItem.FilterSpecCompiled.FilterForEventType.GetPropertyType(property);
            }
            return(propertyTypes);
        }
示例#11
0
        private ExprFilterSpecLookupable MakeLookupable(string fieldName)
        {
            SupportExprEventEvaluator eval = new SupportExprEventEvaluator(testEventType.GetGetter(fieldName));

            return(new ExprFilterSpecLookupable(fieldName, eval, null, testEventType.GetPropertyType(fieldName), false, null));
        }
示例#12
0
        public EventPropertyGetter GetGetter(String propertyName)
        {
            RevisionPropertyTypeDesc desc = _propertyDesc.Get(propertyName);

            if (desc != null)
            {
                return(desc.RevisionGetter);
            }

            // dynamic property names note allowed
            if (propertyName.IndexOf('?') != -1)
            {
                return(null);
            }

            // see if this is a nested property
            int index = ASTUtil.UnescapedIndexOfDot(propertyName);

            if (index == -1)
            {
                Property prop = PropertyParser.ParseAndWalk(propertyName);
                if (prop is SimpleProperty)
                {
                    // there is no such property since it wasn't found earlier
                    return(null);
                }
                String atomic = null;
                if (prop is IndexedProperty)
                {
                    var indexedprop = (IndexedProperty)prop;
                    atomic = indexedprop.PropertyNameAtomic;
                }
                if (prop is MappedProperty)
                {
                    var indexedprop = (MappedProperty)prop;
                    atomic = indexedprop.PropertyNameAtomic;
                }
                desc = _propertyDesc.Get(atomic);
                if (desc == null)
                {
                    return(null);
                }
                if (!(desc.PropertyType is Type))
                {
                    return(null);
                }
                var nestedClass     = (Type)desc.PropertyType;
                var complexProperty = (BeanEventType)_eventAdapterService.AddBeanType(nestedClass.Name, nestedClass, false, false, false);
                return(prop.GetGetter(complexProperty, _eventAdapterService));
            }

            // Map event types allow 2 types of properties inside:
            //   - a property that is a Java object is interrogated via bean property getters and BeanEventType
            //   - a property that is a Map itself is interrogated via map property getters

            // Take apart the nested property into a map key and a nested value class property name
            String propertyMap    = ASTUtil.UnescapeDot(propertyName.Substring(0, index));
            String propertyNested = propertyName.Substring(index + 1);

            desc = _propertyDesc.Get(propertyMap);
            if (desc == null)
            {
                return(null);  // prefix not a known property
            }

            // only nested classes supported for revision event types since deep property information not currently exposed by EventType
            if (desc.PropertyType is Type)
            {
                // ask the nested class to resolve the property
                Type                simpleClass     = (Type)desc.PropertyType;
                EventType           nestedEventType = _eventAdapterService.AddBeanType(simpleClass.FullName, simpleClass, false, false, false);
                EventPropertyGetter nestedGetter    = nestedEventType.GetGetter(propertyNested);
                if (nestedGetter == null)
                {
                    return(null);
                }

                // construct getter for nested property
                return(new RevisionNestedPropertyGetter(desc.RevisionGetter, nestedGetter, _eventAdapterService));
            }
            else
            {
                return(null);
            }
        }
示例#13
0
        public MapEventPropertyGetter GetGetterMap(Map optionalMapPropTypes, EventAdapterService eventAdapterService)
        {
            var getters           = new List <EventPropertyGetter>();
            var currentDictionary = optionalMapPropTypes;

            int count = 0;

            for (var it = Properties.EnumerateWithLookahead(); it.HasNext();)
            {
                count++;
                Property property = it.Next();

                // manufacture a getter for getting the item out of the map
                EventPropertyGetter getter = property.GetGetterMap(currentDictionary, eventAdapterService);
                if (getter == null)
                {
                    return(null);
                }
                getters.Add(getter);

                var @base        = (PropertyBase)property;
                var propertyName = @base.PropertyNameAtomic;

                // For the next property if there is one, check how to property type is defined
                if (!it.HasNext())
                {
                    continue;
                }

                if (currentDictionary != null)
                {
                    // check the type that this property will return
                    Object propertyReturnType = currentDictionary.Get(propertyName);

                    if (propertyReturnType == null)
                    {
                        currentDictionary = null;
                    }
                    if (propertyReturnType != null)
                    {
                        if (propertyReturnType is Map)
                        {
                            currentDictionary = (Map)propertyReturnType;
                        }
                        else if (ReferenceEquals(propertyReturnType, typeof(Map)))
                        {
                            currentDictionary = null;
                        }
                        else if (propertyReturnType is String)
                        {
                            String nestedName = propertyReturnType.ToString();
                            bool   isArray    = EventTypeUtility.IsPropertyArray(nestedName);
                            if (isArray)
                            {
                                nestedName = EventTypeUtility.GetPropertyRemoveArray(nestedName);
                            }

                            EventType innerType = eventAdapterService.GetEventTypeByName(nestedName);
                            if (innerType == null)
                            {
                                return(null);
                            }

                            String remainingProps           = ToPropertyEPL(Properties, count);
                            EventPropertyGetter getterInner = innerType.GetGetter(remainingProps);
                            if (getterInner == null)
                            {
                                return(null);
                            }

                            getters.Add(getterInner);
                            break; // the single getter handles the rest
                        }
                        else if (propertyReturnType is EventType)
                        {
                            var innerType      = (EventType)propertyReturnType;
                            var remainingProps = ToPropertyEPL(Properties, count);
                            var getterInner    = innerType.GetGetter(remainingProps);
                            if (getterInner == null)
                            {
                                return(null);
                            }

                            getters.Add(getterInner);
                            break; // the single getter handles the rest
                        }
                        else
                        {
                            // treat the return type of the map property as an object
                            var returnType = (Type)propertyReturnType;
                            if (!returnType.IsArray)
                            {
                                BeanEventType beanType =
                                    eventAdapterService.BeanEventTypeFactory.CreateBeanType(returnType.Name, returnType,
                                                                                            false, false, false);
                                String remainingProps           = ToPropertyEPL(Properties, count);
                                EventPropertyGetter getterInner = beanType.GetGetter(remainingProps);
                                if (getterInner == null)
                                {
                                    return(null);
                                }
                                getters.Add(getterInner);
                                break; // the single getter handles the rest
                            }
                            else
                            {
                                Type          componentType = returnType.GetElementType();
                                BeanEventType beanType      = eventAdapterService.BeanEventTypeFactory.CreateBeanType(
                                    componentType.Name, componentType, false, false, false);
                                String remainingProps           = ToPropertyEPL(Properties, count);
                                EventPropertyGetter getterInner = beanType.GetGetter(remainingProps);
                                if (getterInner == null)
                                {
                                    return(null);
                                }
                                getters.Add(getterInner);
                                break; // the single pono getter handles the rest
                            }
                        }
                    }
                }
            }

            var hasNonmapGetters = false;

            for (int i = 0; i < getters.Count; i++)
            {
                if (!(getters[i] is MapEventPropertyGetter))
                {
                    hasNonmapGetters = true;
                }
            }
            if (!hasNonmapGetters)
            {
                return(new MapNestedPropertyGetterMapOnly(getters, eventAdapterService));
            }
            else
            {
                return(new MapNestedPropertyGetterMixedType(getters, eventAdapterService));
            }
        }
示例#14
0
        public DTLocalEvaluator GetEvaluator(
            IList <CalendarOp> calendarOps,
            TimeZoneInfo timeZone,
            Type inputType,
            EventType inputEventType,
            ReformatOp reformatOp,
            IntervalOp intervalOp)
        {
            if (inputEventType == null)
            {
                if (reformatOp != null)
                {
                    if (inputType.GetBoxedType() == typeof(DateTime?))
                    {
                        if (calendarOps.IsEmpty())
                        {
                            return(new DTLocalEvaluatorDateTimeReformat(reformatOp));
                        }
                        return(new DTLocalEvaluatorDateTimeOpsReformat(calendarOps, reformatOp, timeZone));
                    }
                    if (inputType.GetBoxedType() == typeof(DateTimeOffset?))
                    {
                        if (calendarOps.IsEmpty())
                        {
                            return(new DTLocalEvaluatorDateTimeReformat(reformatOp));
                        }
                        return(new DTLocalEvaluatorDateTimeOpsReformat(calendarOps, reformatOp, timeZone));
                    }
                    if (inputType.GetBoxedType() == typeof(long?))
                    {
                        if (calendarOps.IsEmpty())
                        {
                            return(new DTLocalEvaluatorLongReformat(reformatOp));
                        }
                        return(new DTLocalEvaluatorLongOpsReformat(calendarOps, reformatOp, timeZone));
                    }
                }
                else if (intervalOp != null)
                {
                    if (inputType.GetBoxedType() == typeof(DateTime?))
                    {
                        if (calendarOps.IsEmpty())
                        {
                            return(new DTLocalEvaluatorDateTimeInterval(intervalOp));
                        }
                        return(new DTLocalEvaluatorDateTimeOpsInterval(calendarOps, intervalOp, timeZone));
                    }
                    if (inputType.GetBoxedType() == typeof(DateTimeOffset?))
                    {
                        if (calendarOps.IsEmpty())
                        {
                            return(new DTLocalEvaluatorDateTimeInterval(intervalOp));
                        }
                        return(new DTLocalEvaluatorDateTimeOpsInterval(calendarOps, intervalOp, timeZone));
                    }
                    if (inputType.GetBoxedType() == typeof(long?))
                    {
                        if (calendarOps.IsEmpty())
                        {
                            return(new DTLocalEvaluatorLongInterval(intervalOp));
                        }
                        return(new DTLocalEvaluatorLongOpsInterval(calendarOps, intervalOp, timeZone));
                    }
                }
                else
                {
                    // only calendar ops, nothing else
                    if (inputType.GetBoxedType() == typeof(DateTime?))
                    {
                        return(new DTLocalEvaluatorCalOpsDateTime(calendarOps, timeZone));
                    }
                    if (inputType.GetBoxedType() == typeof(DateTimeOffset?))
                    {
                        return(new DTLocalEvaluatorCalOpsDateTime(calendarOps, timeZone));
                    }
                    if (inputType.GetBoxedType() == typeof(long?))
                    {
                        return(new DTLocalEvaluatorCalOpsLong(calendarOps, timeZone));
                    }
                }
                throw new ArgumentException("Invalid input type '" + inputType + "'");
            }

            var getter           = inputEventType.GetGetter(inputEventType.StartTimestampPropertyName);
            var getterResultType = inputEventType.GetPropertyType(inputEventType.StartTimestampPropertyName);

            if (reformatOp != null)
            {
                var inner = GetEvaluator(calendarOps, timeZone, getterResultType, null, reformatOp, null);
                return(new DTLocalEvaluatorBeanReformat(getter, inner));
            }
            if (intervalOp == null)
            {
                // only calendar ops
                var inner = GetEvaluator(calendarOps, timeZone, getterResultType, null, null, null);
                return(new DTLocalEvaluatorBeanCalOps(getter, inner));
            }

            // have interval ops but no end timestamp
            if (inputEventType.EndTimestampPropertyName == null)
            {
                var inner = GetEvaluator(calendarOps, timeZone, getterResultType, null, null, intervalOp);
                return(new DTLocalEvaluatorBeanIntervalNoEndTS(getter, inner));
            }

            // interval ops and have end timestamp
            var getterEndTimestamp = inputEventType.GetGetter(inputEventType.EndTimestampPropertyName);
            var intervalComp       =
                (DTLocalEvaluatorIntervalComp)GetEvaluator(calendarOps, timeZone, getterResultType, null, null, intervalOp);

            return(new DTLocalEvaluatorBeanIntervalWithEnd(getter, getterEndTimestamp, intervalComp));
        }
示例#15
0
        private static void AssertEventTypeDefault(EventType eventType)
        {
            var expected = new [] { "TheString","BoolBoxed","IntPrimitive","LongPrimitive","DoublePrimitive","EnumValue" };
            var propertyNames = eventType.PropertyNames;
            EPAssertionUtil.AssertEqualsAnyOrder(expected, propertyNames);
            Assert.AreEqual(typeof(string), eventType.GetPropertyType("TheString"));
            Assert.AreEqual(typeof(bool?), eventType.GetPropertyType("BoolBoxed"));
            Assert.AreEqual(typeof(int?), eventType.GetPropertyType("IntPrimitive"));
            Assert.AreEqual(typeof(long?), eventType.GetPropertyType("LongPrimitive"));
            Assert.AreEqual(typeof(double?), eventType.GetPropertyType("DoublePrimitive"));
            Assert.AreEqual(typeof(SupportEnum?), eventType.GetPropertyType("EnumValue"));
            foreach (var expectedProp in expected) {
                Assert.IsNotNull(eventType.GetGetter(expectedProp));
                Assert.IsTrue(eventType.IsProperty(expectedProp));
            }

            CollectionAssert.AreEquivalent(
                new EventPropertyDescriptor[] {
                    new EventPropertyDescriptor(
                        "TheString",
                        typeof(string),
                        typeof(char),
                        false,
                        false,
                        true,
                        false,
                        false),
                    new EventPropertyDescriptor(
                        "BoolBoxed",
                        typeof(bool?),
                        null,
                        false,
                        false,
                        false,
                        false,
                        false),
                    new EventPropertyDescriptor(
                        "IntPrimitive",
                        typeof(int?),
                        null,
                        false,
                        false,
                        false,
                        false,
                        false),
                    new EventPropertyDescriptor(
                        "LongPrimitive",
                        typeof(long?),
                        null,
                        false,
                        false,
                        false,
                        false,
                        false),
                    new EventPropertyDescriptor(
                        "DoublePrimitive",
                        typeof(double?),
                        null,
                        false,
                        false,
                        false,
                        false,
                        false),
                    new EventPropertyDescriptor(
                        "EnumValue",
                        typeof(SupportEnum?),
                        null,
                        false,
                        false,
                        false,
                        false,
                        false)
                },
                eventType.PropertyDescriptors);
        }
示例#16
0
        public override ExprNode Validate(ExprValidationContext validationContext)
        {
            // validate all parameters
            ExprNodeUtility.Validate(ExprNodeOrigin.DOTNODEPARAMETER, _chainSpec, validationContext);

            // determine if there are enumeration method expressions in the chain
            bool hasEnumerationMethod = false;

            foreach (ExprChainedSpec chain in _chainSpec)
            {
                if (EnumMethodEnumExtensions.IsEnumerationMethod(chain.Name))
                {
                    hasEnumerationMethod = true;
                    break;
                }
            }

            // determine if there is an implied binding, replace first chain element with evaluation node if there is
            if (validationContext.StreamTypeService.HasTableTypes &&
                validationContext.TableService != null &&
                _chainSpec.Count > 1 && _chainSpec[0].IsProperty)
            {
                Pair <ExprNode, IList <ExprChainedSpec> > tableNode = validationContext.TableService.GetTableNodeChainable(validationContext.StreamTypeService, _chainSpec, validationContext.MethodResolutionService.EngineImportService);
                if (tableNode != null)
                {
                    ExprNode node = ExprNodeUtility.GetValidatedSubtree(ExprNodeOrigin.DOTNODE, tableNode.First, validationContext);
                    if (tableNode.Second.IsEmpty())
                    {
                        return(node);
                    }
                    _chainSpec.Clear();
                    _chainSpec.AddAll(tableNode.Second);
                    AddChildNode(node);
                }
            }

            // The root node expression may provide the input value:
            //   Such as "window(*).doIt(...)" or "(select * from Window).doIt()" or "prevwindow(sb).doIt(...)", in which case the expression to act on is a child expression
            //
            StreamTypeService streamTypeService = validationContext.StreamTypeService;

            if (ChildNodes.Length != 0)
            {
                // the root expression is the first child node
                ExprNode      rootNode          = ChildNodes[0];
                ExprEvaluator rootNodeEvaluator = rootNode.ExprEvaluator;

                // the root expression may also provide a lambda-function input (GetEnumerator<EventBean>)
                // Determine collection-type and evaluator if any for root node
                ExprDotEnumerationSource enumSrc = ExprDotNodeUtility.GetEnumerationSource(rootNode, validationContext.StreamTypeService, validationContext.EventAdapterService, validationContext.StatementId, hasEnumerationMethod, validationContext.IsDisablePropertyExpressionEventCollCache);

                EPType typeInfo;
                if (enumSrc.ReturnType == null)
                {
                    typeInfo = EPTypeHelper.SingleValue(rootNodeEvaluator.ReturnType);        // not a collection type, treat as scalar
                }
                else
                {
                    typeInfo = enumSrc.ReturnType;
                }

                ExprDotNodeRealizedChain evals = ExprDotNodeUtility.GetChainEvaluators(enumSrc.StreamOfProviderIfApplicable, typeInfo, _chainSpec, validationContext, _isDuckTyping, new ExprDotNodeFilterAnalyzerInputExpr());
                _exprEvaluator = new ExprDotEvalRootChild(hasEnumerationMethod, this, rootNodeEvaluator, enumSrc.Enumeration, typeInfo, evals.Chain, evals.ChainWithUnpack, false);
                return(null);
            }

            // No root node, and this is a 1-element chain i.e. "something(param,...)".
            // Plug-in single-row methods are not handled here.
            // Plug-in aggregation methods are not handled here.
            if (_chainSpec.Count == 1)
            {
                ExprChainedSpec spec = _chainSpec[0];
                if (spec.Parameters.IsEmpty())
                {
                    throw HandleNotFound(spec.Name);
                }

                // single-parameter can resolve to a property
                Pair <PropertyResolutionDescriptor, string> propertyInfoPair = null;
                try {
                    propertyInfoPair = ExprIdentNodeUtil.GetTypeFromStream(streamTypeService, spec.Name, streamTypeService.HasPropertyAgnosticType, false);
                }
                catch (ExprValidationPropertyException) {
                    // fine
                }

                // if not a property then try built-in single-row non-grammar functions
                if (propertyInfoPair == null && string.Equals(spec.Name, EngineImportServiceConstants.EXT_SINGLEROW_FUNCTION_TRANSPOSE, StringComparison.OrdinalIgnoreCase))
                {
                    if (spec.Parameters.Count != 1)
                    {
                        throw new ExprValidationException("The " + EngineImportServiceConstants.EXT_SINGLEROW_FUNCTION_TRANSPOSE + " function requires a single parameter expression");
                    }
                    _exprEvaluator = new ExprDotEvalTransposeAsStream(_chainSpec[0].Parameters[0].ExprEvaluator);
                }
                else if (spec.Parameters.Count != 1)
                {
                    throw HandleNotFound(spec.Name);
                }
                else
                {
                    if (propertyInfoPair == null)
                    {
                        throw new ExprValidationException("Unknown single-row function, aggregation function or mapped or indexed property named '" + spec.Name + "' could not be resolved");
                    }
                    _exprEvaluator       = GetPropertyPairEvaluator(spec.Parameters[0].ExprEvaluator, propertyInfoPair, validationContext);
                    _streamNumReferenced = propertyInfoPair.First.StreamNum;
                }
                return(null);
            }

            // handle the case where the first chain spec element is a stream name.
            ExprValidationException prefixedStreamNumException = null;
            int prefixedStreamNumber = PrefixedStreamName(_chainSpec, validationContext.StreamTypeService);

            if (prefixedStreamNumber != -1)
            {
                ExprChainedSpec specAfterStreamName = _chainSpec[1];

                // Attempt to resolve as property
                Pair <PropertyResolutionDescriptor, string> propertyInfoPair = null;
                try {
                    string propName = _chainSpec[0].Name + "." + specAfterStreamName.Name;
                    propertyInfoPair = ExprIdentNodeUtil.GetTypeFromStream(streamTypeService, propName, streamTypeService.HasPropertyAgnosticType, false);
                }
                catch (ExprValidationPropertyException) {
                    // fine
                }
                if (propertyInfoPair != null)
                {
                    if (specAfterStreamName.Parameters.Count != 1)
                    {
                        throw HandleNotFound(specAfterStreamName.Name);
                    }
                    _exprEvaluator       = GetPropertyPairEvaluator(specAfterStreamName.Parameters[0].ExprEvaluator, propertyInfoPair, validationContext);
                    _streamNumReferenced = propertyInfoPair.First.StreamNum;
                    return(null);
                }

                // Attempt to resolve as event-underlying object instance method
                EventType eventType = validationContext.StreamTypeService.EventTypes[prefixedStreamNumber];
                Type      type      = eventType.UnderlyingType;

                IList <ExprChainedSpec> remainderChain = new List <ExprChainedSpec>(_chainSpec);
                remainderChain.RemoveAt(0);

                ExprValidationException methodEx = null;
                ExprDotEval[]           underlyingMethodChain = null;
                try {
                    EPType typeInfo = EPTypeHelper.SingleValue(type);
                    underlyingMethodChain = ExprDotNodeUtility.GetChainEvaluators(prefixedStreamNumber, typeInfo, remainderChain, validationContext, false, new ExprDotNodeFilterAnalyzerInputStream(prefixedStreamNumber)).ChainWithUnpack;
                }
                catch (ExprValidationException ex) {
                    methodEx = ex;
                    // expected - may not be able to find the methods on the underlying
                }

                ExprDotEval[]           eventTypeMethodChain = null;
                ExprValidationException enumDatetimeEx       = null;
                try {
                    EPType typeInfo = EPTypeHelper.SingleEvent(eventType);
                    ExprDotNodeRealizedChain chain = ExprDotNodeUtility.GetChainEvaluators(prefixedStreamNumber, typeInfo, remainderChain, validationContext, false, new ExprDotNodeFilterAnalyzerInputStream(prefixedStreamNumber));
                    eventTypeMethodChain           = chain.ChainWithUnpack;
                    _exprDotNodeFilterAnalyzerDesc = chain.FilterAnalyzerDesc;
                }
                catch (ExprValidationException ex) {
                    enumDatetimeEx = ex;
                    // expected - may not be able to find the methods on the underlying
                }

                if (underlyingMethodChain != null)
                {
                    _exprEvaluator       = new ExprDotEvalStreamMethod(this, prefixedStreamNumber, underlyingMethodChain);
                    _streamNumReferenced = prefixedStreamNumber;
                }
                else if (eventTypeMethodChain != null)
                {
                    _exprEvaluator       = new ExprDotEvalStreamEventBean(this, prefixedStreamNumber, eventTypeMethodChain);
                    _streamNumReferenced = prefixedStreamNumber;
                }

                if (_exprEvaluator != null)
                {
                    return(null);
                }
                else
                {
                    if (ExprDotNodeUtility.IsDatetimeOrEnumMethod(remainderChain[0].Name))
                    {
                        prefixedStreamNumException = enumDatetimeEx;
                    }
                    else
                    {
                        prefixedStreamNumException = new ExprValidationException("Failed to solve '" + remainderChain[0].Name + "' to either a date-time or enumeration method, an event property or a method on the event underlying object: " + methodEx.Message, methodEx);
                    }
                }
            }

            // There no root node, in this case the classname or property name is provided as part of the chain.
            // Such as "MyClass.myStaticLib(...)" or "mycollectionproperty.doIt(...)"
            //
            IList <ExprChainedSpec> modifiedChain = new List <ExprChainedSpec>(_chainSpec);
            ExprChainedSpec         firstItem     = modifiedChain.Pluck(0);

            Pair <PropertyResolutionDescriptor, string> propertyInfoPairX = null;

            try {
                propertyInfoPairX = ExprIdentNodeUtil.GetTypeFromStream(streamTypeService, firstItem.Name, streamTypeService.HasPropertyAgnosticType, true);
            }
            catch (ExprValidationPropertyException) {
                // not a property
            }

            // If property then treat it as such
            if (propertyInfoPairX != null)
            {
                string    propertyName = propertyInfoPairX.First.PropertyName;
                int       streamId     = propertyInfoPairX.First.StreamNum;
                EventType streamType   = streamTypeService.EventTypes[streamId];
                EPType    typeInfo;
                ExprEvaluatorEnumeration enumerationEval = null;
                EPType              inputType;
                ExprEvaluator       rootNodeEvaluator = null;
                EventPropertyGetter getter;

                if (firstItem.Parameters.IsEmpty())
                {
                    getter = streamType.GetGetter(propertyInfoPairX.First.PropertyName);

                    ExprDotEnumerationSourceForProps propertyEval = ExprDotNodeUtility.GetPropertyEnumerationSource(
                        propertyInfoPairX.First.PropertyName, streamId, streamType, hasEnumerationMethod, validationContext.IsDisablePropertyExpressionEventCollCache);
                    typeInfo          = propertyEval.ReturnType;
                    enumerationEval   = propertyEval.Enumeration;
                    inputType         = propertyEval.ReturnType;
                    rootNodeEvaluator = new PropertyExprEvaluatorNonLambda(streamId, getter, propertyInfoPairX.First.PropertyType);
                }
                else
                {
                    // property with parameter - mapped or indexed property
                    EventPropertyDescriptor desc = EventTypeUtility.GetNestablePropertyDescriptor(streamTypeService.EventTypes[propertyInfoPairX.First.StreamNum], firstItem.Name);
                    if (firstItem.Parameters.Count > 1)
                    {
                        throw new ExprValidationException("Property '" + firstItem.Name + "' may not be accessed passing 2 or more parameters");
                    }
                    ExprEvaluator paramEval = firstItem.Parameters[0].ExprEvaluator;
                    typeInfo  = EPTypeHelper.SingleValue(desc.PropertyComponentType);
                    inputType = typeInfo;
                    getter    = null;
                    if (desc.IsMapped)
                    {
                        if (paramEval.ReturnType != typeof(string))
                        {
                            throw new ExprValidationException("Parameter expression to mapped property '" + propertyName + "' is expected to return a string-type value but returns " + paramEval.ReturnType.GetTypeNameFullyQualPretty());
                        }
                        EventPropertyGetterMapped mappedGetter = propertyInfoPairX.First.StreamEventType.GetGetterMapped(propertyInfoPairX.First.PropertyName);
                        if (mappedGetter == null)
                        {
                            throw new ExprValidationException("Mapped property named '" + propertyName + "' failed to obtain getter-object");
                        }
                        rootNodeEvaluator = new PropertyExprEvaluatorNonLambdaMapped(streamId, mappedGetter, paramEval, desc.PropertyComponentType);
                    }
                    if (desc.IsIndexed)
                    {
                        if (paramEval.ReturnType.GetBoxedType() != typeof(int?))
                        {
                            throw new ExprValidationException("Parameter expression to mapped property '" + propertyName + "' is expected to return a Integer-type value but returns " + paramEval.ReturnType.GetTypeNameFullyQualPretty());
                        }
                        EventPropertyGetterIndexed indexedGetter = propertyInfoPairX.First.StreamEventType.GetGetterIndexed(propertyInfoPairX.First.PropertyName);
                        if (indexedGetter == null)
                        {
                            throw new ExprValidationException("Mapped property named '" + propertyName + "' failed to obtain getter-object");
                        }
                        rootNodeEvaluator = new PropertyExprEvaluatorNonLambdaIndexed(streamId, indexedGetter, paramEval, desc.PropertyComponentType);
                    }
                }
                if (typeInfo == null)
                {
                    throw new ExprValidationException("Property '" + propertyName + "' is not a mapped or indexed property");
                }

                // try to build chain based on the input (non-fragment)
                ExprDotNodeRealizedChain           evals;
                ExprDotNodeFilterAnalyzerInputProp filterAnalyzerInputProp = new ExprDotNodeFilterAnalyzerInputProp(propertyInfoPairX.First.StreamNum, propertyInfoPairX.First.PropertyName);
                bool rootIsEventBean = false;
                try {
                    evals = ExprDotNodeUtility.GetChainEvaluators(streamId, inputType, modifiedChain, validationContext, _isDuckTyping, filterAnalyzerInputProp);
                }
                catch (ExprValidationException ex) {
                    // try building the chain based on the fragment event type (i.e. A.after(B) based on A-configured start time where A is a fragment)
                    FragmentEventType fragment = propertyInfoPairX.First.FragmentEventType;
                    if (fragment == null)
                    {
                        throw;
                    }

                    EPType fragmentTypeInfo;
                    if (fragment.IsIndexed)
                    {
                        fragmentTypeInfo = EPTypeHelper.CollectionOfEvents(fragment.FragmentType);
                    }
                    else
                    {
                        fragmentTypeInfo = EPTypeHelper.SingleEvent(fragment.FragmentType);
                    }

                    rootIsEventBean   = true;
                    evals             = ExprDotNodeUtility.GetChainEvaluators(propertyInfoPairX.First.StreamNum, fragmentTypeInfo, modifiedChain, validationContext, _isDuckTyping, filterAnalyzerInputProp);
                    rootNodeEvaluator = new PropertyExprEvaluatorNonLambdaFragment(streamId, getter, fragment.FragmentType.UnderlyingType);
                }

                _exprEvaluator = new ExprDotEvalRootChild(hasEnumerationMethod, this, rootNodeEvaluator, enumerationEval, inputType, evals.Chain, evals.ChainWithUnpack, !rootIsEventBean);
                _exprDotNodeFilterAnalyzerDesc = evals.FilterAnalyzerDesc;
                _streamNumReferenced           = propertyInfoPairX.First.StreamNum;
                _rootPropertyName = propertyInfoPairX.First.PropertyName;
                return(null);
            }

            // If variable then resolve as such
            string contextNameVariable = validationContext.VariableService.IsContextVariable(firstItem.Name);

            if (contextNameVariable != null)
            {
                throw new ExprValidationException("Method invocation on context-specific variable is not supported");
            }
            VariableReader variableReader = validationContext.VariableService.GetReader(firstItem.Name, EPStatementStartMethodConst.DEFAULT_AGENT_INSTANCE_ID);

            if (variableReader != null)
            {
                EPType typeInfo;
                ExprDotStaticMethodWrap wrap;
                if (variableReader.VariableMetaData.VariableType.IsArray)
                {
                    typeInfo = EPTypeHelper.CollectionOfSingleValue(variableReader.VariableMetaData.VariableType.GetElementType());
                    wrap     = new ExprDotStaticMethodWrapArrayScalar(variableReader.VariableMetaData.VariableName, variableReader.VariableMetaData.VariableType.GetElementType());
                }
                else if (variableReader.VariableMetaData.EventType != null)
                {
                    typeInfo = EPTypeHelper.SingleEvent(variableReader.VariableMetaData.EventType);
                    wrap     = null;
                }
                else
                {
                    typeInfo = EPTypeHelper.SingleValue(variableReader.VariableMetaData.VariableType);
                    wrap     = null;
                }

                ExprDotNodeRealizedChain evals = ExprDotNodeUtility.GetChainEvaluators(null, typeInfo, modifiedChain, validationContext, false, new ExprDotNodeFilterAnalyzerInputStatic());
                _exprEvaluator = new ExprDotEvalVariable(this, variableReader, wrap, evals.ChainWithUnpack);
                return(null);
            }

            // try resolve as enumeration class with value
            object enumconstant = TypeHelper.ResolveIdentAsEnumConst(firstItem.Name, validationContext.MethodResolutionService, null, false);

            if (enumconstant != null)
            {
                // try resolve method
                ExprChainedSpec methodSpec = modifiedChain[0];
                string          enumvalue  = firstItem.Name;
                ExprNodeUtilResolveExceptionHandler handler = new ProxyExprNodeUtilResolveExceptionHandler
                {
                    ProcHandle = ex => new ExprValidationException("Failed to resolve method '" + methodSpec.Name + "' on enumeration value '" + enumvalue + "': " + ex.Message),
                };
                EventType wildcardType            = validationContext.StreamTypeService.EventTypes.Length != 1 ? null : validationContext.StreamTypeService.EventTypes[0];
                ExprNodeUtilMethodDesc methodDesc = ExprNodeUtility.ResolveMethodAllowWildcardAndStream(enumconstant.GetType().Name, enumconstant.GetType(), methodSpec.Name, methodSpec.Parameters, validationContext.MethodResolutionService, validationContext.EventAdapterService, validationContext.StatementId, wildcardType != null, wildcardType, handler, methodSpec.Name, validationContext.TableService);

                // method resolved, hook up
                modifiedChain.RemoveAt(0);        // we identified this piece
                ExprDotStaticMethodWrap optionalLambdaWrap = ExprDotStaticMethodWrapFactory.Make(methodDesc.ReflectionMethod, validationContext.EventAdapterService, modifiedChain);
                EPType typeInfo = optionalLambdaWrap != null ? optionalLambdaWrap.TypeInfo : EPTypeHelper.SingleValue(methodDesc.FastMethod.ReturnType);

                ExprDotNodeRealizedChain evals = ExprDotNodeUtility.GetChainEvaluators(null, typeInfo, modifiedChain, validationContext, false, new ExprDotNodeFilterAnalyzerInputStatic());
                _exprEvaluator = new ExprDotEvalStaticMethod(validationContext.StatementName, firstItem.Name, methodDesc.FastMethod,
                                                             methodDesc.ChildEvals, false, optionalLambdaWrap, evals.ChainWithUnpack, false, enumconstant);
                return(null);
            }

            // if prefixed by a stream name, we are giving up
            if (prefixedStreamNumException != null)
            {
                throw prefixedStreamNumException;
            }

            // If class then resolve as class
            ExprChainedSpec secondItem = modifiedChain.Pluck(0);

            bool      allowWildcard  = validationContext.StreamTypeService.EventTypes.Length == 1;
            EventType streamZeroType = null;

            if (validationContext.StreamTypeService.EventTypes.Length > 0)
            {
                streamZeroType = validationContext.StreamTypeService.EventTypes[0];
            }

            ExprNodeUtilMethodDesc method = ExprNodeUtility.ResolveMethodAllowWildcardAndStream(firstItem.Name, null, secondItem.Name, secondItem.Parameters, validationContext.MethodResolutionService, validationContext.EventAdapterService, validationContext.StatementId, allowWildcard, streamZeroType, new ExprNodeUtilResolveExceptionHandlerDefault(firstItem.Name + "." + secondItem.Name, false), secondItem.Name, validationContext.TableService);

            bool isConstantParameters = method.IsAllConstants && _isUDFCache;

            _isReturnsConstantResult = isConstantParameters && modifiedChain.IsEmpty();

            // this may return a pair of null if there is no lambda or the result cannot be wrapped for lambda-function use
            ExprDotStaticMethodWrap optionalLambdaWrapX = ExprDotStaticMethodWrapFactory.Make(method.ReflectionMethod, validationContext.EventAdapterService, modifiedChain);
            EPType typeInfoX = optionalLambdaWrapX != null ? optionalLambdaWrapX.TypeInfo : EPTypeHelper.SingleValue(method.ReflectionMethod.ReturnType);

            ExprDotNodeRealizedChain evalsX = ExprDotNodeUtility.GetChainEvaluators(null, typeInfoX, modifiedChain, validationContext, false, new ExprDotNodeFilterAnalyzerInputStatic());

            _exprEvaluator = new ExprDotEvalStaticMethod(validationContext.StatementName, firstItem.Name, method.FastMethod, method.ChildEvals, isConstantParameters, optionalLambdaWrapX, evalsX.ChainWithUnpack, false, null);
            return(null);
        }