예제 #1
0
 public ExprDotForgeEnumMethodEval(
     ExprDotForgeEnumMethodBase forge,
     EnumEval enumEval,
     int enumEvalNumRequiredEvents)
 {
     this.forge = forge;
     this.enumEval = enumEval;
     this.enumEvalNumRequiredEvents = enumEvalNumRequiredEvents;
 }
예제 #2
0
        public void Init(
            int?streamOfProviderIfApplicable,
            EnumMethodEnum enumMethodEnum,
            String enumMethodUsedName,
            EPType typeInfo,
            IList <ExprNode> parameters,
            ExprValidationContext validationContext)
        {
            var eventTypeColl           = EPTypeHelper.GetEventTypeMultiValued(typeInfo);
            var eventTypeBean           = EPTypeHelper.GetEventTypeSingleValued(typeInfo);
            var collectionComponentType = EPTypeHelper.GetClassMultiValued(typeInfo);

            _enumMethodEnum      = enumMethodEnum;
            _enumMethodUsedName  = enumMethodUsedName;
            _streamCountIncoming = validationContext.StreamTypeService.EventTypes.Length;

            if (eventTypeColl == null && collectionComponentType == null && eventTypeBean == null)
            {
                throw new ExprValidationException(
                          "Invalid input for built-in enumeration method '" + enumMethodUsedName +
                          "', expecting collection of event-type or scalar values as input, received " +
                          EPTypeHelper.ToTypeDescriptive(typeInfo));
            }

            // compile parameter abstract for validation against available footprints
            var footprintProvided = DotMethodUtil.GetProvidedFootprint(parameters);

            // validate parameters
            DotMethodInputTypeMatcher inputTypeMatcher = new ProxyDotMethodInputTypeMatcher
            {
                ProcMatches = fp =>
                {
                    if (fp.Input == DotMethodFPInputEnum.EVENTCOLL && eventTypeBean == null && eventTypeColl == null)
                    {
                        return(false);
                    }
                    if (fp.Input == DotMethodFPInputEnum.SCALAR_ANY && collectionComponentType == null)
                    {
                        return(false);
                    }
                    return(true);
                }
            };

            var footprint = DotMethodUtil.ValidateParametersDetermineFootprint(
                enumMethodEnum.GetFootprints(), DotMethodTypeEnum.ENUM, enumMethodUsedName, footprintProvided,
                inputTypeMatcher);

            // validate input criteria met for this footprint
            if (footprint.Input != DotMethodFPInputEnum.ANY)
            {
                var message = "Invalid input for built-in enumeration method '" + enumMethodUsedName + "' and " +
                              footprint.Parameters.Length + "-parameter footprint, expecting collection of ";
                var received = " as input, received " + EPTypeHelper.ToTypeDescriptive(typeInfo);
                if (footprint.Input == DotMethodFPInputEnum.EVENTCOLL && eventTypeColl == null)
                {
                    throw new ExprValidationException(message + "events" + received);
                }
                if (footprint.Input.IsScalar() && collectionComponentType == null)
                {
                    throw new ExprValidationException(message + "values (typically scalar values)" + received);
                }
                if (footprint.Input == DotMethodFPInputEnum.SCALAR_NUMERIC && !collectionComponentType.IsNumeric())
                {
                    throw new ExprValidationException(message + "numeric values" + received);
                }
            }

            // manage context of this lambda-expression in regards to outer lambda-expression that may call this one.
            ExpressionResultCacheForEnumerationMethod enumerationMethodCache = validationContext.ExprEvaluatorContext.ExpressionResultCacheService.AllocateEnumerationMethod;

            enumerationMethodCache.PushStack(this);

            var bodiesAndParameters = new List <ExprDotEvalParam>();
            var count          = 0;
            var inputEventType = eventTypeBean ?? eventTypeColl;

            foreach (var node in parameters)
            {
                var bodyAndParameter = GetBodyAndParameter(
                    enumMethodUsedName, count++, node, inputEventType, collectionComponentType, validationContext,
                    bodiesAndParameters, footprint);
                bodiesAndParameters.Add(bodyAndParameter);
            }

            _enumEval = GetEnumEval(
                validationContext.EngineImportService, validationContext.EventAdapterService,
                validationContext.StreamTypeService, validationContext.StatementId, enumMethodUsedName,
                bodiesAndParameters, inputEventType, collectionComponentType, _streamCountIncoming,
                validationContext.IsDisablePropertyExpressionEventCollCache);
            _enumEvalNumRequiredEvents = _enumEval.StreamNumSize;

            // determine the stream ids of event properties asked for in the Evaluator(s)
            var streamsRequired = new HashSet <int>();
            var visitor         = new ExprNodeIdentifierCollectVisitor();

            foreach (var desc in bodiesAndParameters)
            {
                desc.Body.Accept(visitor);
                foreach (var ident in visitor.ExprProperties)
                {
                    streamsRequired.Add(ident.StreamId);
                }
            }
            if (streamOfProviderIfApplicable != null)
            {
                streamsRequired.Add(streamOfProviderIfApplicable.Value);
            }

            // We turn on caching if the stack is not empty (we are an inner lambda) and the dependency does not include the stream.
            var isInner = !enumerationMethodCache.PopLambda();

            if (isInner)
            {
                // If none of the properties that the current lambda uses comes from the ultimate Parent(s) or subsequent streams, then cache.
                var parents = enumerationMethodCache.GetStack();
                var found   = false;
                foreach (var req in streamsRequired)
                {
                    var first          = (ExprDotEvalEnumMethodBase)parents.First;
                    var parentIncoming = first._streamCountIncoming - 1;
                    var selfAdded      = _streamCountIncoming; // the one we use ourselfs
                    if (req > parentIncoming && req < selfAdded)
                    {
                        found = true;
                    }
                }
                _cache = !found;
            }
        }