示例#1
0
        public ExprDotNodeForgeRootChild(
            ExprDotNodeImpl parent,
            FilterExprAnalyzerAffector filterExprAnalyzerAffector,
            int? streamNumReferenced,
            string rootPropertyName,
            bool hasEnumerationMethod,
            ExprForge rootNodeForge,
            ExprEnumerationForge rootLambdaEvaluator,
            EPType typeInfo,
            ExprDotForge[] forgesIteratorEventBean,
            ExprDotForge[] forgesUnpacking,
            bool checkedUnpackEvent)
        {
            Parent = parent;
            FilterExprAnalyzerAffector = filterExprAnalyzerAffector;
            StreamNumReferenced = streamNumReferenced;
            RootPropertyName = rootPropertyName;
            if (rootLambdaEvaluator != null) {
                if (typeInfo is EventMultiValuedEPType eventMultiValuedEpType) {
                    innerForge = new InnerDotEnumerableEventCollectionForge(
                        rootLambdaEvaluator,
                        eventMultiValuedEpType.Component);
                }
                else if (typeInfo is EventEPType eventEpType) {
                    innerForge = new InnerDotEnumerableEventBeanForge(
                        rootLambdaEvaluator,
                        eventEpType.EventType);
                }
                else {
                    innerForge = new InnerDotEnumerableScalarCollectionForge(
                        rootLambdaEvaluator,
                        ((ClassMultiValuedEPType) typeInfo).Component);
                }
            }
            else {
                if (checkedUnpackEvent) {
                    innerForge = new InnerDotScalarUnpackEventForge(rootNodeForge);
                }
                else {
                    var returnType = rootNodeForge.EvaluationType;
                    if (hasEnumerationMethod && returnType.IsArray) {
                        if (returnType.GetElementType().CanNotBeNull()) {
                            innerForge = new InnerDotArrPrimitiveToCollForge(rootNodeForge);
                        }
                        else {
                            innerForge = new InnerDotArrObjectToCollForge(rootNodeForge);
                        }
                    }
                    else if (hasEnumerationMethod && returnType.IsGenericCollection()) {
                        innerForge = new InnerDotCollForge(rootNodeForge);
                    }
                    else {
                        innerForge = new InnerDotScalarForge(rootNodeForge);
                    }
                }
            }

            this.forgesUnpacking = forgesUnpacking;
            this.forgesIteratorEventBean = forgesIteratorEventBean;
        }
示例#2
0
        public ExprDotNodeForgeStream(
            ExprDotNodeImpl parent,
            FilterExprAnalyzerAffector filterExprAnalyzerAffector,
            int streamNumber,
            EventType eventType,
            ExprDotForge[] evaluators,
            bool method)
        {
            this.parent = parent;
            FilterExprAnalyzerAffector = filterExprAnalyzerAffector;
            StreamNumber = streamNumber;
            EventType = eventType;
            Evaluators = evaluators;
            this.method = method;

            var last = evaluators[evaluators.Length - 1];
            if (!method) {
                if (last.TypeInfo is ClassMultiValuedEPType) {
                    EvaluationType = EPTypeHelper.GetClassMultiValuedContainer(last.TypeInfo).GetBoxedType();
                }
                else {
                    EvaluationType = EPTypeHelper.GetClassSingleValued(last.TypeInfo).GetBoxedType();
                }
            }
            else {
                EvaluationType = EPTypeHelper.GetNormalizedClass(last.TypeInfo).GetBoxedType();
            }
        }
示例#3
0
 public ExprDotDTMethodDesc(
     ExprDotForge forge,
     EPType returnType,
     FilterExprAnalyzerAffector intervalFilterDesc)
 {
     this.forge = forge;
     this.returnType = returnType;
     this.intervalFilterDesc = intervalFilterDesc;
 }
示例#4
0
 public ExprDotNodeRealizedChain(
     ExprDotForge[] chain,
     ExprDotForge[] chainWithUnpack,
     FilterExprAnalyzerAffector filterAnalyzerDesc)
 {
     Chain = chain;
     ChainWithUnpack = chainWithUnpack;
     FilterAnalyzerDesc = filterAnalyzerDesc;
 }
示例#5
0
        public override ExprNode Validate(ExprValidationContext validationContext)
        {
            // check for plannable methods: these are validated according to different rules
            var appDotMethod = GetAppDotMethod(validationContext.IsFilterExpression);

            if (appDotMethod != null)
            {
                return(appDotMethod);
            }

            // validate all parameters
            ExprNodeUtility.Validate(ExprNodeOrigin.DOTNODEPARAMETER, _chainSpec, validationContext);

            // determine if there are enumeration method expressions in the chain
            var hasEnumerationMethod = _chainSpec
                                       .Any(chain => chain.Name.IsEnumerationMethod());

            // 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)
            {
                var tableNode = validationContext.TableService.GetTableNodeChainable(
                    validationContext.StreamTypeService, _chainSpec, validationContext.EngineImportService);
                if (tableNode != null)
                {
                    var 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
            //
            var streamTypeService = validationContext.StreamTypeService;

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

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

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

                var evalsX =
                    ExprDotNodeUtility.GetChainEvaluators(
                        enumSrc.StreamOfProviderIfApplicable, typeInfoX, _chainSpec, validationContext, _isDuckTyping,
                        new ExprDotNodeFilterAnalyzerInputExpr());
                _exprEvaluator = new ExprDotEvalRootChild(
                    hasEnumerationMethod, this, rootNodeEvaluator, enumSrc.Enumeration, typeInfoX, evalsX.Chain,
                    evalsX.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.
            Pair <PropertyResolutionDescriptor, string> propertyInfoPair;

            if (_chainSpec.Count == 1)
            {
                var spec = _chainSpec[0];
                if (spec.Parameters.IsEmpty())
                {
                    throw HandleNotFound(spec.Name);
                }

                // single-parameter can resolve to a property
                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.InvariantCultureIgnoreCase))
                {
                    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;
            var    prefixedStreamNumber = PrefixedStreamName(_chainSpec, validationContext.StreamTypeService);
            EPType typeInfo;

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

                // Attempt to resolve as property
                propertyInfoPair = null;
                try
                {
                    var 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
                var eventType = validationContext.StreamTypeService.EventTypes[prefixedStreamNumber];
                var type      = eventType.UnderlyingType;

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

                ExprValidationException methodEx = null;
                ExprDotEval[]           underlyingMethodChain = null;
                try
                {
                    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
                {
                    typeInfo = EPTypeHelper.SingleEvent(eventType);
                    var chain = ExprDotNodeUtility.GetChainEvaluators(
                        prefixedStreamNumber, typeInfo, remainderChain, validationContext, false,
                        new ExprDotNodeFilterAnalyzerInputStream(prefixedStreamNumber));
                    eventTypeMethodChain        = chain.ChainWithUnpack;
                    _filterExprAnalyzerAffector = 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(...)"
            //
            var modifiedChain = new List <ExprChainedSpec>(_chainSpec);
            var firstItem     = modifiedChain.DeleteAt(0);

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

            // If property then treat it as such
            ExprDotNodeRealizedChain evals;

            if (propertyInfoPair != null)
            {
                var propertyName = propertyInfoPair.First.PropertyName;
                var streamId     = propertyInfoPair.First.StreamNum;
                var streamType   = streamTypeService.EventTypes[streamId];
                ExprEvaluatorEnumeration enumerationEval = null;
                EPType              inputType;
                ExprEvaluator       rootNodeEvaluator = null;
                EventPropertyGetter getter;

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

                    var propertyEval = ExprDotNodeUtility.GetPropertyEnumerationSource(
                        propertyInfoPair.First.PropertyName, streamId, streamType, hasEnumerationMethod,
                        validationContext.IsDisablePropertyExpressionEventCollCache);
                    typeInfo          = propertyEval.ReturnType;
                    enumerationEval   = propertyEval.Enumeration;
                    inputType         = propertyEval.ReturnType;
                    rootNodeEvaluator = new PropertyExprEvaluatorNonLambda(
                        streamId, getter, propertyInfoPair.First.PropertyType);
                }
                else
                {
                    // property with parameter - mapped or indexed property
                    var desc =
                        EventTypeUtility.GetNestablePropertyDescriptor(
                            streamTypeService.EventTypes[propertyInfoPair.First.StreamNum], firstItem.Name);
                    if (firstItem.Parameters.Count > 1)
                    {
                        throw new ExprValidationException(
                                  "Property '" + firstItem.Name + "' may not be accessed passing 2 or more parameters");
                    }

                    var 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.GetCleanName());
                        }

                        var mappedGetter =
                            propertyInfoPair.First.StreamEventType.GetGetterMapped(propertyInfoPair.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.IsNotInt32())
                        {
                            throw new ExprValidationException(
                                      "Parameter expression to mapped property '" + propertyName +
                                      "' is expected to return a int?-type value but returns " +
                                      paramEval.ReturnType.GetCleanName());
                        }

                        var indexedGetter =
                            propertyInfoPair.First.StreamEventType.GetGetterIndexed(propertyInfoPair.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)
                var filterAnalyzerInputProp = new ExprDotNodeFilterAnalyzerInputProp(
                    propertyInfoPair.First.StreamNum, propertyInfoPair.First.PropertyName);
                var rootIsEventBean = false;
                try
                {
                    evals = ExprDotNodeUtility.GetChainEvaluators(
                        streamId, inputType, modifiedChain, validationContext, _isDuckTyping, filterAnalyzerInputProp);
                }
                catch (ExprValidationException)
                {
                    // 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)
                    var fragment = propertyInfoPair.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(
                        propertyInfoPair.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);
                _filterExprAnalyzerAffector = evals.FilterAnalyzerDesc;
                _streamNumReferenced        = propertyInfoPair.First.StreamNum;
                _rootPropertyName           = propertyInfoPair.First.PropertyName;
                return(null);
            }

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

            if (contextNameVariable != null)
            {
                throw new ExprValidationException("Method invocation on context-specific variable is not supported");
            }

            var variableReader = validationContext.VariableService.GetReader(
                firstItem.Name, EPStatementStartMethodConst.DEFAULT_AGENT_INSTANCE_ID);

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

                var evalsX = ExprDotNodeUtility.GetChainEvaluators(
                    null, typeInfoX, modifiedChain, validationContext, false,
                    new ExprDotNodeFilterAnalyzerInputStatic());
                _exprEvaluator = new ExprDotEvalVariable(this, variableReader, wrap, evalsX.ChainWithUnpack);
                return(null);
            }

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

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

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

                var evalsX = ExprDotNodeUtility.GetChainEvaluators(
                    null, typeInfoX, modifiedChain, validationContext, false,
                    new ExprDotNodeFilterAnalyzerInputStatic());
                _exprEvaluator = new ExprDotEvalStaticMethod(
                    validationContext.StatementName, firstItem.Name,
                    methodDesc.FastMethod,
                    methodDesc.ChildEvals,
                    false, optionalLambdaWrapX, evalsX.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
            var secondItem = modifiedChain.DeleteAt(0);

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

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

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

            var 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
            var optionalLambdaWrap = ExprDotStaticMethodWrapFactory.Make(
                method.ReflectionMethod, validationContext.EventAdapterService, modifiedChain, null);

            typeInfo = optionalLambdaWrap != null
                ? optionalLambdaWrap.TypeInfo
                : EPTypeHelper.SingleValue(method.ReflectionMethod.ReturnType);

            evals = ExprDotNodeUtility.GetChainEvaluators(
                null, typeInfo, modifiedChain, validationContext, false, new ExprDotNodeFilterAnalyzerInputStatic());
            _exprEvaluator = new ExprDotEvalStaticMethod(
                validationContext.StatementName, firstItem.Name, method.FastMethod, method.ChildEvals,
                isConstantParameters, optionalLambdaWrap, evals.ChainWithUnpack, false, null);
            return(null);
        }
示例#6
0
        public static ExprDotEvalDTMethodDesc ValidateMake(
            StreamTypeService streamTypeService,
            Deque <ExprChainedSpec> chainSpecStack,
            DatetimeMethodEnum dtMethod,
            String dtMethodName,
            EPType inputType,
            IList <ExprNode> parameters,
            ExprDotNodeFilterAnalyzerInput inputDesc,
            TimeZoneInfo timeZone,
            TimeAbacus timeAbacus)
        {
            // verify input
            String message = "Date-time enumeration method '" + dtMethodName +
                             "' requires either a DateTime, DateTimeEx or long value as input or events of an event type that declares a timestamp property";

            if (inputType is EventEPType)
            {
                if (((EventEPType)inputType).EventType.StartTimestampPropertyName == null)
                {
                    throw new ExprValidationException(message);
                }
            }
            else
            {
                if (!(inputType is ClassEPType || inputType is NullEPType))
                {
                    throw new ExprValidationException(message + " but received " + inputType.ToTypeDescriptive());
                }
                if (inputType is ClassEPType)
                {
                    ClassEPType classEPType = (ClassEPType)inputType;
                    if (!TypeHelper.IsDateTime(classEPType.Clazz))
                    {
                        throw new ExprValidationException(
                                  message + " but received " + classEPType.Clazz.GetCleanName());
                    }
                }
            }

            IList <CalendarOp> calendarOps       = new List <CalendarOp>();
            ReformatOp         reformatOp        = null;
            IntervalOp         intervalOp        = null;
            DatetimeMethodEnum currentMethod     = dtMethod;
            IList <ExprNode>   currentParameters = parameters;
            String             currentMethodName = dtMethodName;

            // drain all calendar ops
            FilterExprAnalyzerAffector filterAnalyzerDesc = null;

            while (true)
            {
                // handle the first one only if its a calendar op
                var evaluators = GetEvaluators(currentParameters);
                var opFactory  = currentMethod.MetaData().OpFactory;

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

                // validate parameters
                DotMethodUtil.ValidateParametersDetermineFootprint(
                    currentMethod.Footprints(),
                    DotMethodTypeEnum.DATETIME,
                    currentMethodName, footprintProvided,
                    DotMethodInputTypeMatcherImpl.DEFAULT_ALL);

                if (opFactory is CalendarOpFactory)
                {
                    CalendarOp calendarOp = ((CalendarOpFactory)opFactory).GetOp(currentMethod, currentMethodName, currentParameters, evaluators);
                    calendarOps.Add(calendarOp);
                }
                else if (opFactory is ReformatOpFactory)
                {
                    reformatOp = ((ReformatOpFactory)opFactory).GetOp(timeZone, timeAbacus, currentMethod, currentMethodName, currentParameters);

                    // compile filter analyzer information if there are no calendar ops in the chain
                    if (calendarOps.IsEmpty())
                    {
                        filterAnalyzerDesc = reformatOp.GetFilterDesc(streamTypeService.EventTypes, currentMethod, currentParameters, inputDesc);
                    }
                    else
                    {
                        filterAnalyzerDesc = null;
                    }
                }
                else if (opFactory is IntervalOpFactory)
                {
                    intervalOp = ((IntervalOpFactory)opFactory).GetOp(streamTypeService, currentMethod, currentMethodName, currentParameters, timeZone, timeAbacus);

                    // compile filter analyzer information if there are no calendar ops in the chain
                    if (calendarOps.IsEmpty())
                    {
                        filterAnalyzerDesc = intervalOp.GetFilterDesc(streamTypeService.EventTypes, currentMethod, currentParameters, inputDesc);
                    }
                    else
                    {
                        filterAnalyzerDesc = null;
                    }
                }
                else
                {
                    throw new IllegalStateException("Invalid op factory class " + opFactory);
                }

                // see if there is more
                if (chainSpecStack.IsEmpty() || !DatetimeMethodEnumExtensions.IsDateTimeMethod(chainSpecStack.First.Name))
                {
                    break;
                }

                // pull next
                var next = chainSpecStack.RemoveFirst();
                currentMethod     = DatetimeMethodEnumExtensions.FromName(next.Name);
                currentParameters = next.Parameters;
                currentMethodName = next.Name;

                if ((reformatOp != null || intervalOp != null))
                {
                    throw new ExprValidationException("Invalid input for date-time method '" + next.Name + "'");
                }
            }

            ExprDotEval dotEval;
            EPType      returnType;

            dotEval = new ExprDotEvalDT(
                calendarOps, timeZone, timeAbacus, reformatOp, intervalOp,
                EPTypeHelper.GetClassSingleValued(inputType),
                EPTypeHelper.GetEventTypeSingleValued(inputType));
            returnType = dotEval.TypeInfo;
            return(new ExprDotEvalDTMethodDesc(dotEval, returnType, filterAnalyzerDesc));
        }
示例#7
0
        public static ExprDotNodeRealizedChain GetChainEvaluators(
            int?streamOfProviderIfApplicable,
            EPType inputType,
            IList <ExprChainedSpec> chainSpec,
            ExprValidationContext validationContext,
            bool isDuckTyping,
            ExprDotNodeFilterAnalyzerInput inputDesc)
        {
            var                        methodEvals        = new List <ExprDotEval>();
            var                        currentInputType   = inputType;
            EnumMethodEnum?            lastLambdaFunc     = null;
            var                        lastElement        = chainSpec.IsEmpty() ? null : chainSpec[chainSpec.Count - 1];
            FilterExprAnalyzerAffector filterAnalyzerDesc = null;

            var chainSpecStack = new ArrayDeque <ExprChainedSpec>(chainSpec);

            while (!chainSpecStack.IsEmpty())
            {
                var chainElement = chainSpecStack.RemoveFirst();
                lastLambdaFunc = null;  // reset

                // compile parameters for chain element
                var paramEvals = new ExprEvaluator[chainElement.Parameters.Count];
                var paramTypes = new Type[chainElement.Parameters.Count];
                for (var i = 0; i < chainElement.Parameters.Count; i++)
                {
                    paramEvals[i] = chainElement.Parameters[i].ExprEvaluator;
                    paramTypes[i] = paramEvals[i].ReturnType;
                }

                // check if special 'size' method
                if (currentInputType is ClassMultiValuedEPType)
                {
                    var type = (ClassMultiValuedEPType)currentInputType;
                    if ((chainElement.Name.ToLower() == "size") && paramTypes.Length == 0 && Equals(lastElement, chainElement))
                    {
                        var sizeExpr = new ExprDotEvalArraySize();
                        methodEvals.Add(sizeExpr);
                        currentInputType = sizeExpr.TypeInfo;
                        continue;
                    }
                    if ((chainElement.Name.ToLower() == "get") && paramTypes.Length == 1 && paramTypes[0].IsInt32())
                    {
                        var componentType = type.Component;
                        var get           = new ExprDotEvalArrayGet(paramEvals[0], componentType);
                        methodEvals.Add(get);
                        currentInputType = get.TypeInfo;
                        continue;
                    }
                }

                // determine if there is a matching method
                var matchingMethod = false;
                var methodTarget   = GetMethodTarget(currentInputType);
                if (methodTarget != null)
                {
                    try
                    {
                        GetValidateMethodDescriptor(methodTarget, chainElement.Name, chainElement.Parameters, validationContext);
                        matchingMethod = true;
                    }
                    catch (ExprValidationException)
                    {
                        // expected
                    }
                }

                // resolve lambda
                if (chainElement.Name.IsEnumerationMethod() && (!matchingMethod || methodTarget.IsArray || methodTarget.IsImplementsInterface(typeof(ICollection <object>))))
                {
                    var enumerationMethod = EnumMethodEnumExtensions.FromName(chainElement.Name);
                    var eval = TypeHelper.Instantiate <ExprDotEvalEnumMethod>(enumerationMethod.GetImplementation());
                    eval.Init(streamOfProviderIfApplicable, enumerationMethod, chainElement.Name, currentInputType, chainElement.Parameters, validationContext);
                    currentInputType = eval.TypeInfo;
                    if (currentInputType == null)
                    {
                        throw new IllegalStateException("Enumeration method '" + chainElement.Name + "' has not returned type information");
                    }
                    methodEvals.Add(eval);
                    lastLambdaFunc = enumerationMethod;
                    continue;
                }

                // resolve datetime
                if (chainElement.Name.IsDateTimeMethod() && (!matchingMethod || methodTarget == typeof(DateTimeOffset?)))
                {
                    var datetimeMethod = DatetimeMethodEnumExtensions.FromName(chainElement.Name);
                    var datetimeImpl   = ExprDotEvalDTFactory.ValidateMake(
                        validationContext.StreamTypeService, chainSpecStack, datetimeMethod, chainElement.Name,
                        currentInputType, chainElement.Parameters, inputDesc,
                        validationContext.EngineImportService.TimeZone,
                        validationContext.EngineImportService.TimeAbacus);
                    currentInputType = datetimeImpl.ReturnType;
                    if (currentInputType == null)
                    {
                        throw new IllegalStateException("Date-time method '" + chainElement.Name + "' has not returned type information");
                    }
                    methodEvals.Add(datetimeImpl.Eval);
                    filterAnalyzerDesc = datetimeImpl.IntervalFilterDesc;
                    continue;
                }

                // try to resolve as property if the last method returned a type
                if (currentInputType is EventEPType)
                {
                    var inputEventType = ((EventEPType)currentInputType).EventType;
                    var type           = inputEventType.GetPropertyType(chainElement.Name);
                    var getter         = inputEventType.GetGetter(chainElement.Name);
                    if (type != null && getter != null)
                    {
                        var noduck = new ExprDotEvalProperty(getter, EPTypeHelper.SingleValue(type.GetBoxedType()));
                        methodEvals.Add(noduck);
                        currentInputType = EPTypeHelper.SingleValue(EPTypeHelper.GetClassSingleValued(noduck.TypeInfo));
                        continue;
                    }
                }

                // Finally try to resolve the method
                if (methodTarget != null)
                {
                    try
                    {
                        // find descriptor again, allow for duck typing
                        var desc       = GetValidateMethodDescriptor(methodTarget, chainElement.Name, chainElement.Parameters, validationContext);
                        var fastMethod = desc.FastMethod;
                        paramEvals = desc.ChildEvals;

                        ExprDotEval eval;
                        if (currentInputType is ClassEPType)
                        {
                            // if followed by an enumeration method, convert array to collection
                            if (fastMethod.ReturnType.IsArray && !chainSpecStack.IsEmpty() && chainSpecStack.First.Name.IsEnumerationMethod())
                            {
                                eval = new ExprDotMethodEvalNoDuckWrapArray(validationContext.StatementName, fastMethod, paramEvals);
                            }
                            else
                            {
                                eval = new ExprDotMethodEvalNoDuck(validationContext.StatementName, fastMethod, paramEvals);
                            }
                        }
                        else
                        {
                            eval = new ExprDotMethodEvalNoDuckUnderlying(validationContext.StatementName, fastMethod, paramEvals);
                        }
                        methodEvals.Add(eval);
                        currentInputType = eval.TypeInfo;
                    }
                    catch (Exception e)
                    {
                        if (!isDuckTyping)
                        {
                            throw new ExprValidationException(e.Message, e);
                        }
                        else
                        {
                            var duck = new ExprDotMethodEvalDuck(validationContext.StatementName, validationContext.EngineImportService, chainElement.Name, paramTypes, paramEvals);
                            methodEvals.Add(duck);
                            currentInputType = duck.TypeInfo;
                        }
                    }
                    continue;
                }

                var message = "Could not find event property, enumeration method or instance method named '" +
                              chainElement.Name + "' in " + currentInputType.ToTypeDescriptive();
                throw new ExprValidationException(message);
            }

            var intermediateEvals = methodEvals.ToArray();

            if (lastLambdaFunc != null)
            {
                ExprDotEval finalEval = null;
                if (currentInputType is EventMultiValuedEPType)
                {
                    var mvType        = (EventMultiValuedEPType)currentInputType;
                    var tableMetadata = validationContext.TableService.GetTableMetadataFromEventType(mvType.Component);
                    if (tableMetadata != null)
                    {
                        finalEval = new ExprDotEvalUnpackCollEventBeanTable(mvType.Component, tableMetadata);
                    }
                    else
                    {
                        finalEval = new ExprDotEvalUnpackCollEventBean(mvType.Component);
                    }
                }
                else if (currentInputType is EventEPType)
                {
                    var epType        = (EventEPType)currentInputType;
                    var tableMetadata = validationContext.TableService.GetTableMetadataFromEventType(epType.EventType);
                    if (tableMetadata != null)
                    {
                        finalEval = new ExprDotEvalUnpackBeanTable(epType.EventType, tableMetadata);
                    }
                    else
                    {
                        finalEval = new ExprDotEvalUnpackBean(epType.EventType);
                    }
                }
                if (finalEval != null)
                {
                    methodEvals.Add(finalEval);
                }
            }

            var unpackingEvals = methodEvals.ToArray();

            return(new ExprDotNodeRealizedChain(intermediateEvals, unpackingEvals, filterAnalyzerDesc));
        }
示例#8
0
        public static ExprDotDTMethodDesc ValidateMake(
            StreamTypeService streamTypeService,
            Deque<Chainable> chainSpecStack,
            DatetimeMethodDesc dtMethod,
            string dtMethodName,
            EPType inputType,
            IList<ExprNode> parameters,
            ExprDotNodeFilterAnalyzerInput inputDesc,
            TimeAbacus timeAbacus,
            TableCompileTimeResolver tableCompileTimeResolver,
            ImportServiceCompileTime importService,
            StatementRawInfo statementRawInfo)
        {
            // verify input
            var message = "Date-time enumeration method '" +
                          dtMethodName +
                          "' requires either a DateTimeEx, DateTimeOffset, DateTime, or long value as input or events of an event type that declares a timestamp property";
            if (inputType is EventEPType eventEpType) {
                if (eventEpType.EventType.StartTimestampPropertyName == null) {
                    throw new ExprValidationException(message);
                }
            }
            else {
                if (!(inputType is ClassEPType || inputType is NullEPType)) {
                    throw new ExprValidationException(
                        message + " but received " + inputType.ToTypeDescriptive());
                }

                if (inputType is ClassEPType classEpType) {
                    if (!TypeHelper.IsDateTime(classEpType.Clazz)) {
                        throw new ExprValidationException(
                            message + " but received " + classEpType.Clazz.CleanName());
                    }
                }
            }

            IList<CalendarForge> calendarForges = new List<CalendarForge>();
            ReformatForge reformatForge = null;
            IntervalForge intervalForge = null;
            var currentMethod = dtMethod;
            var currentParameters = parameters;
            var currentMethodName = dtMethodName;

            // drain all calendar op
            FilterExprAnalyzerAffector filterAnalyzerDesc = null;
            while (true) {
                // handle the first one only if its a calendar op
                var forges = GetForges(currentParameters);
                var opFactory = currentMethod.ForgeFactory;

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

                // validate parameters
                var footprintFound = DotMethodUtil.ValidateParametersDetermineFootprint(
                    currentMethod.Footprints,
                    DotMethodTypeEnum.DATETIME,
                    currentMethodName,
                    footprintProvided,
                    DotMethodInputTypeMatcherImpl.DEFAULT_ALL);

                if (opFactory is CalendarForgeFactory calendarForgeFactory) {
                    var calendarForge = calendarForgeFactory.GetOp(
                        currentMethod,
                        currentMethodName,
                        currentParameters,
                        forges);
                    calendarForges.Add(calendarForge);
                }
                else if (opFactory is ReformatForgeFactory reformatForgeFactory) {
                    reformatForge = reformatForgeFactory.GetForge(
                        inputType,
                        timeAbacus,
                        currentMethod,
                        currentMethodName,
                        currentParameters);

                    // compile filter analyzer information if there are no calendar op in the chain
                    if (calendarForges.IsEmpty()) {
                        filterAnalyzerDesc = reformatForge.GetFilterDesc(
                            streamTypeService.EventTypes,
                            currentMethod,
                            currentParameters,
                            inputDesc);
                    }
                    else {
                        filterAnalyzerDesc = null;
                    }
                }
                else if (opFactory is IntervalForgeFactory intervalForgeFactory) {
                    intervalForge = intervalForgeFactory.GetForge(
                        streamTypeService,
                        currentMethod,
                        currentMethodName,
                        currentParameters,
                        timeAbacus,
                        tableCompileTimeResolver);

                    // compile filter analyzer information if there are no calendar op in the chain
                    if (calendarForges.IsEmpty()) {
                        filterAnalyzerDesc = intervalForge.GetFilterDesc(
                            streamTypeService.EventTypes,
                            currentMethod,
                            currentParameters,
                            inputDesc);
                    }
                }
                else if (opFactory is DTMPluginForgeFactory dtmPluginForgeFactory) {
                    var usageDesc = new DateTimeMethodValidateContext(
                        footprintFound,
                        streamTypeService,
                        currentMethod,
                        currentParameters,
                        statementRawInfo);
                    var ops = dtmPluginForgeFactory.Validate(usageDesc);
                    if (ops == null) {
                        throw new ExprValidationException(
                            "Plug-in datetime method provider " + dtmPluginForgeFactory.GetType() + " returned a null-value for the operations");
                    }

                    var input = EPTypeHelper.GetClassSingleValued(inputType);
                    if (ops is DateTimeMethodOpsModify dateTimeMethodOpsModify) {
                        calendarForges.Add(new DTMPluginValueChangeForge(input, dateTimeMethodOpsModify, usageDesc.CurrentParameters));
                    }
                    else if (ops is DateTimeMethodOpsReformat dateTimeMethodOpsReformat) {
                        reformatForge = new DTMPluginReformatForge(input, dateTimeMethodOpsReformat, usageDesc.CurrentParameters);
                    }
                    else {
                        throw new ExprValidationException("Plug-in datetime method ops " + ops.GetType() + " is not recognized");
                    }

                    // no action
                }
                else {
                    throw new IllegalStateException("Invalid op factory class " + opFactory);
                }

                // see if there is more
                if (chainSpecStack.IsEmpty() || !DatetimeMethodResolver.IsDateTimeMethod(chainSpecStack.First.GetRootNameOrEmptyString(), importService)) {
                    break;
                }

                // pull next
                var next = chainSpecStack.RemoveFirst();
                currentMethodName = next.GetRootNameOrEmptyString();
                currentMethod = DatetimeMethodResolver.FromName(currentMethodName, importService);
                currentParameters = next.GetParametersOrEmpty();

                if (reformatForge != null || intervalForge != null) {
                    throw new ExprValidationException("Invalid input for date-time method '" + currentMethodName + "'");
                }
            }

            var dotForge = new ExprDotDTForge(
                calendarForges,
                timeAbacus,
                reformatForge,
                intervalForge,
                inputType.GetClassSingleValued(),
                inputType.GetEventTypeSingleValued());
            var returnType = dotForge.TypeInfo;
            return new ExprDotDTMethodDesc(dotForge, returnType, filterAnalyzerDesc);
        }
示例#9
0
 public ExprDotEvalDTMethodDesc(ExprDotEval eval, EPType returnType, FilterExprAnalyzerAffector intervalFilterDesc)
 {
     Eval               = eval;
     ReturnType         = returnType;
     IntervalFilterDesc = intervalFilterDesc;
 }
示例#10
0
        public static ExprDotNodeRealizedChain GetChainEvaluators(
            int? streamOfProviderIfApplicable,
            EPType inputType,
            IList<ExprChainedSpec> chainSpec,
            ExprValidationContext validationContext,
            bool isDuckTyping,
            ExprDotNodeFilterAnalyzerInput inputDesc)
        {
            IList<ExprDotForge> methodForges = new List<ExprDotForge>();
            var currentInputType = inputType;
            EnumMethodEnum? lastLambdaFunc = null;
            var lastElement = chainSpec.IsEmpty() ? null : chainSpec[chainSpec.Count - 1];
            FilterExprAnalyzerAffector filterAnalyzerDesc = null;

            Deque<ExprChainedSpec> chainSpecStack = new ArrayDeque<ExprChainedSpec>(chainSpec);
            while (!chainSpecStack.IsEmpty()) {
                var chainElement = chainSpecStack.RemoveFirst();
                lastLambdaFunc = null; // reset

                // compile parameters for chain element
                var paramForges = new ExprForge[chainElement.Parameters.Count];
                var paramTypes = new Type[chainElement.Parameters.Count];
                for (var i = 0; i < chainElement.Parameters.Count; i++) {
                    paramForges[i] = chainElement.Parameters[i].Forge;
                    paramTypes[i] = paramForges[i].EvaluationType;
                }

                // check if special 'size' method
                if (currentInputType is ClassMultiValuedEPType) {
                    var type = (ClassMultiValuedEPType) currentInputType;
                    if (chainElement.Name.Equals("size", StringComparison.InvariantCultureIgnoreCase) &&
                        paramTypes.Length == 0 &&
                        lastElement == chainElement) {
                        var sizeExpr = new ExprDotForgeArraySize();
                        methodForges.Add(sizeExpr);
                        currentInputType = sizeExpr.TypeInfo;
                        continue;
                    }

                    if (chainElement.Name.Equals("get", StringComparison.InvariantCultureIgnoreCase) &&
                        paramTypes.Length == 1 &&
                        Boxing.GetBoxedType(paramTypes[0]) == typeof(int?)) {
                        var componentType = Boxing.GetBoxedType(type.Component);
                        var get = new ExprDotForgeArrayGet(paramForges[0], componentType);
                        methodForges.Add(get);
                        currentInputType = get.TypeInfo;
                        continue;
                    }
                }

                // determine if there is a matching method
                var matchingMethod = false;
                var methodTarget = GetMethodTarget(currentInputType);
                if (methodTarget != null) {
                    try {
                        GetValidateMethodDescriptor(
                            methodTarget,
                            chainElement.Name,
                            chainElement.Parameters,
                            validationContext);
                        matchingMethod = true;
                    }
                    catch (ExprValidationException) {
                        // expected
                    }
                }

                if (EnumMethodEnumExtensions.IsEnumerationMethod(chainElement.Name) &&
                    (!matchingMethod || methodTarget.IsArray || methodTarget.IsGenericCollection())) {
                    var enumerationMethod = EnumMethodEnumExtensions.FromName(chainElement.Name);
                    if (enumerationMethod == null) {
                        throw new EPException("unable to determine enumeration method from name");
                    }

                    var eval = TypeHelper.Instantiate<ExprDotForgeEnumMethod>(
                        enumerationMethod.Value.GetImplementation());
                    eval.Init(
                        streamOfProviderIfApplicable,
                        enumerationMethod.Value,
                        chainElement.Name,
                        currentInputType,
                        chainElement.Parameters,
                        validationContext);
                    currentInputType = eval.TypeInfo;
                    if (currentInputType == null) {
                        throw new IllegalStateException(
                            "Enumeration method '" + chainElement.Name + "' has not returned type information");
                    }

                    methodForges.Add(eval);
                    lastLambdaFunc = enumerationMethod;
                    continue;
                }

                // resolve datetime
                if (DatetimeMethodEnumHelper.IsDateTimeMethod(chainElement.Name) &&
                    (!matchingMethod ||
                     methodTarget == typeof(DateTimeEx) ||
                     methodTarget == typeof(DateTimeOffset) ||
                     methodTarget == typeof(DateTime))) {
                    var dateTimeMethod = DatetimeMethodEnumHelper.FromName(chainElement.Name);
                    var datetimeImpl = ExprDotDTFactory.ValidateMake(
                        validationContext.StreamTypeService,
                        chainSpecStack,
                        dateTimeMethod,
                        chainElement.Name,
                        currentInputType,
                        chainElement.Parameters,
                        inputDesc,
                        validationContext.ImportService.TimeAbacus,
                        null,
                        validationContext.TableCompileTimeResolver);
                    currentInputType = datetimeImpl.ReturnType;
                    if (currentInputType == null) {
                        throw new IllegalStateException(
                            "Date-time method '" + chainElement.Name + "' has not returned type information");
                    }

                    methodForges.Add(datetimeImpl.Forge);
                    filterAnalyzerDesc = datetimeImpl.IntervalFilterDesc;
                    continue;
                }

                // try to resolve as property if the last method returned a type
                if (currentInputType is EventEPType) {
                    var inputEventType = (EventTypeSPI) ((EventEPType) currentInputType).EventType;
                    var type = inputEventType.GetPropertyType(chainElement.Name);
                    var getter = inputEventType.GetGetterSPI(chainElement.Name);
                    if (type != null && getter != null) {
                        var noduck = new ExprDotForgeProperty(
                            getter,
                            EPTypeHelper.SingleValue(Boxing.GetBoxedType(type)));
                        methodForges.Add(noduck);
                        currentInputType = EPTypeHelper.SingleValue(EPTypeHelper.GetClassSingleValued(noduck.TypeInfo));
                        continue;
                    }
                }

                // Finally try to resolve the method
                if (methodTarget != null) {
                    try {
                        // find descriptor again, allow for duck typing
                        var desc = GetValidateMethodDescriptor(
                            methodTarget,
                            chainElement.Name,
                            chainElement.Parameters,
                            validationContext);
                        paramForges = desc.ChildForges;
                        ExprDotForge forge;
                        if (currentInputType is ClassEPType) {
                            // if followed by an enumeration method, convert array to collection
                            if (desc.ReflectionMethod.ReturnType.IsArray &&
                                !chainSpecStack.IsEmpty() &&
                                EnumMethodEnumExtensions.IsEnumerationMethod(chainSpecStack.First.Name)) {
                                forge = new ExprDotMethodForgeNoDuck(
                                    validationContext.StatementName,
                                    desc.ReflectionMethod,
                                    paramForges,
                                    ExprDotMethodForgeNoDuck.DuckType.WRAPARRAY);
                            }
                            else {
                                forge = new ExprDotMethodForgeNoDuck(
                                    validationContext.StatementName,
                                    desc.ReflectionMethod,
                                    paramForges,
                                    ExprDotMethodForgeNoDuck.DuckType.PLAIN);
                            }
                        }
                        else {
                            forge = new ExprDotMethodForgeNoDuck(
                                validationContext.StatementName,
                                desc.ReflectionMethod,
                                paramForges,
                                ExprDotMethodForgeNoDuck.DuckType.UNDERLYING);
                        }

                        methodForges.Add(forge);
                        currentInputType = forge.TypeInfo;
                    }
                    catch (Exception e) {
                        if (!isDuckTyping) {
                            throw new ExprValidationException(e.Message, e);
                        }

                        var duck = new ExprDotMethodForgeDuck(
                            validationContext.StatementName,
                            validationContext.ImportService,
                            chainElement.Name,
                            paramTypes,
                            paramForges);
                        methodForges.Add(duck);
                        currentInputType = duck.TypeInfo;
                    }

                    continue;
                }

                var message = "Could not find event property, enumeration method or instance method named '" +
                                 chainElement.Name +
                                 "' in " +
                                 EPTypeHelper.ToTypeDescriptive(currentInputType);
                throw new ExprValidationException(message);
            }

            var intermediateEvals = methodForges.ToArray();

            if (lastLambdaFunc != null) {
                ExprDotForge finalEval = null;
                if (currentInputType is EventMultiValuedEPType) {
                    var mvType = (EventMultiValuedEPType) currentInputType;
                    var tableMetadata =
                        validationContext.TableCompileTimeResolver.ResolveTableFromEventType(mvType.Component);
                    if (tableMetadata != null) {
                        finalEval = new ExprDotForgeUnpackCollEventBeanTable(mvType.Component, tableMetadata);
                    }
                    else {
                        finalEval = new ExprDotForgeUnpackCollEventBean(mvType.Component);
                    }
                }
                else if (currentInputType is EventEPType) {
                    var epType = (EventEPType) currentInputType;
                    var tableMetadata =
                        validationContext.TableCompileTimeResolver.ResolveTableFromEventType(epType.EventType);
                    if (tableMetadata != null) {
                        finalEval = new ExprDotForgeUnpackBeanTable(epType.EventType, tableMetadata);
                    }
                    else {
                        finalEval = new ExprDotForgeUnpackBean(epType.EventType);
                    }
                }

                if (finalEval != null) {
                    methodForges.Add(finalEval);
                }
            }

            var unpackingForges = methodForges.ToArray();
            return new ExprDotNodeRealizedChain(intermediateEvals, unpackingForges, filterAnalyzerDesc);
        }
示例#11
0
        public static ExprDotNodeRealizedChain GetChainEvaluators(
            int?streamOfProviderIfApplicable,
            EPType inputType,
            IList <Chainable> chainSpec,
            ExprValidationContext validationContext,
            bool isDuckTyping,
            ExprDotNodeFilterAnalyzerInput inputDesc)
        {
            var                        methodForges       = new List <ExprDotForge>();
            var                        currentInputType   = inputType;
            EnumMethodDesc             lastLambdaFunc     = null;
            var                        lastElement        = chainSpec.IsEmpty() ? null : chainSpec[chainSpec.Count - 1];
            FilterExprAnalyzerAffector filterAnalyzerDesc = null;

            Deque <Chainable> chainSpecStack = new ArrayDeque <Chainable>(chainSpec);

            while (!chainSpecStack.IsEmpty())
            {
                var chainElement     = chainSpecStack.RemoveFirst();
                var parameters       = chainElement.GetParametersOrEmpty();
                var chainElementName = chainElement.GetRootNameOrEmptyString();
                var last             = chainSpecStack.IsEmpty();
                lastLambdaFunc = null;                 // reset

                // compile parameters for chain element
                var paramForges = new ExprForge[parameters.Count];
                var paramTypes  = new Type[parameters.Count];
                for (var i = 0; i < parameters.Count; i++)
                {
                    paramForges[i] = parameters[i].Forge;
                    paramTypes[i]  = paramForges[i].EvaluationType;
                }

                // check if special 'size' method
                if (currentInputType is ClassMultiValuedEPType)
                {
                    var type = (ClassMultiValuedEPType)currentInputType;
                    if (string.Equals(chainElementName, "size", StringComparison.InvariantCultureIgnoreCase) &&
                        paramTypes.Length == 0 &&
                        lastElement == chainElement)
                    {
                        ExprDotForge size;
                        var          containerType = ((ClassMultiValuedEPType)currentInputType).Container;
                        if (containerType.IsArray)
                        {
                            size = new ExprDotForgeSizeArray();
                        }
                        else
                        {
                            size = new ExprDotForgeSizeCollection();
                        }

                        methodForges.Add(size);
                        currentInputType = size.TypeInfo;
                        continue;
                    }

                    if (string.Equals(chainElementName, "get", StringComparison.InvariantCultureIgnoreCase) &&
                        paramTypes.Length == 1 &&
                        paramTypes[0].GetBoxedType() == typeof(int?))
                    {
                        ExprDotForge get;
                        var          componentType = type.Component.GetBoxedType();
                        if (type.Container.IsArray)
                        {
                            get = new ExprDotForgeGetArray(paramForges[0], componentType);
                        }
                        else
                        {
                            get = new ExprDotForgeGetCollection(paramForges[0], componentType);
                        }

                        methodForges.Add(get);
                        currentInputType = get.TypeInfo;
                        continue;
                    }

                    if (chainElement is ChainableArray && type.Container.IsArray)
                    {
                        var array     = (ChainableArray)chainElement;
                        var typeInfo  = currentInputType;
                        var indexExpr = ChainableArray.ValidateSingleIndexExpr(
                            array.Indexes,
                            () => "operation on type " + typeInfo.ToTypeDescriptive());
                        var componentType = type.Component.GetBoxedType();
                        var get           = new ExprDotForgeGetArray(indexExpr.Forge, componentType);
                        methodForges.Add(get);
                        currentInputType = get.TypeInfo;
                        continue;
                    }
                }

                // determine if there is a matching method or property
                var methodTarget   = GetMethodTarget(currentInputType);
                var matchingMethod = false;
                if (methodTarget != null && (!(chainElement is ChainableArray)))
                {
                    try {
                        GetValidateMethodDescriptor(methodTarget, chainElementName, parameters, validationContext);
                        matchingMethod = true;
                    }
                    catch (ExprValidationException) {
                        // expected
                    }
                }

                if (EnumMethodResolver.IsEnumerationMethod(chainElementName, validationContext.ImportService) &&
                    (!matchingMethod || methodTarget.IsArray || methodTarget.IsGenericCollection()))
                {
                    var enumerationMethod = EnumMethodResolver.FromName(chainElementName, validationContext.ImportService);
                    if (enumerationMethod == null)
                    {
                        throw new EPException("unable to determine enumeration method from name");
                    }

                    var eval = enumerationMethod.Factory.Invoke(chainElement.GetParametersOrEmpty().Count);
                    if (currentInputType is ClassEPType classEpType && classEpType.Clazz.IsGenericCollection() && !classEpType.Clazz.IsArray)
                    {
                        currentInputType = EPTypeHelper.CollectionOfSingleValue(typeof(object), null);
                    }

                    eval.Init(streamOfProviderIfApplicable, enumerationMethod, chainElementName, currentInputType, parameters, validationContext);
                    currentInputType = eval.TypeInfo;
                    if (currentInputType == null)
                    {
                        throw new IllegalStateException("Enumeration method '" + chainElementName + "' has not returned type information");
                    }

                    methodForges.Add(eval);
                    lastLambdaFunc = enumerationMethod;
                    continue;
                }

                // resolve datetime
                if (DatetimeMethodResolver.IsDateTimeMethod(chainElementName, validationContext.ImportService) &&
                    (!matchingMethod ||
                     methodTarget == typeof(DateTimeEx) ||
                     methodTarget == typeof(DateTimeOffset) ||
                     methodTarget == typeof(DateTime)))
                {
                    var datetimeMethod = DatetimeMethodResolver.FromName(chainElementName, validationContext.ImportService);
                    var datetimeImpl   = ExprDotDTFactory.ValidateMake(
                        validationContext.StreamTypeService,
                        chainSpecStack,
                        datetimeMethod,
                        chainElementName,
                        currentInputType,
                        parameters,
                        inputDesc,
                        validationContext.ImportService.TimeAbacus,
                        validationContext.TableCompileTimeResolver,
                        validationContext.ImportService,
                        validationContext.StatementRawInfo);
                    currentInputType = datetimeImpl.ReturnType;
                    if (currentInputType == null)
                    {
                        throw new IllegalStateException(
                                  "Date-time method '" + chainElementName + "' has not returned type information");
                    }

                    methodForges.Add(datetimeImpl.Forge);
                    filterAnalyzerDesc = datetimeImpl.IntervalFilterDesc;
                    continue;
                }

                // try to resolve as property if the last method returned a type
                if (currentInputType is EventEPType)
                {
                    if (chainElement is ChainableArray)
                    {
                        throw new ExprValidationException("Could not perform array operation on type " + currentInputType.ToTypeDescriptive());
                    }

                    var          inputEventType = (EventTypeSPI)((EventEPType)currentInputType).EventType;
                    var          type           = inputEventType.GetPropertyType(chainElementName);
                    var          getter         = inputEventType.GetGetterSPI(chainElementName);
                    var          fragmentType   = inputEventType.GetFragmentType(chainElementName);
                    ExprDotForge forge;
                    if (type != null && getter != null)
                    {
                        if (fragmentType == null || last)
                        {
                            forge            = new ExprDotForgeProperty(getter, EPTypeHelper.SingleValue(type.GetBoxedType()));
                            currentInputType = forge.TypeInfo;
                        }
                        else
                        {
                            if (!fragmentType.IsIndexed)
                            {
                                currentInputType = EPTypeHelper.SingleEvent(fragmentType.FragmentType);
                            }
                            else
                            {
                                currentInputType = EPTypeHelper.ArrayOfEvents(fragmentType.FragmentType);
                            }

                            forge = new ExprDotForgePropertyFragment(getter, currentInputType);
                        }

                        methodForges.Add(forge);
                        continue;
                    }
                }

                if (currentInputType is EventMultiValuedEPType eventMultiValuedEpType && chainElement is ChainableArray chainableArray)
                {
                    var inputEventType = (EventTypeSPI)eventMultiValuedEpType.Component;
                    var typeInfo       = currentInputType;
                    var indexExpr      = ChainableArray.ValidateSingleIndexExpr(
                        chainableArray.Indexes,
                        () => "operation on type " + typeInfo.ToTypeDescriptive());
                    currentInputType = EPTypeHelper.SingleEvent(inputEventType);
                    var forge = new ExprDotForgeEventArrayAtIndex(currentInputType, indexExpr);
                    methodForges.Add(forge);
                    continue;
                }

                // Finally try to resolve the method
                if (methodTarget != null && !(chainElement is ChainableArray))
                {
                    try {
                        // find descriptor again, allow for duck typing
                        var desc = GetValidateMethodDescriptor(methodTarget, chainElementName, parameters, validationContext);
                        paramForges = desc.ChildForges;
                        ExprDotForge forge;
                        if (currentInputType is ClassEPType)
                        {
                            // if followed by an enumeration method, convert array to collection
                            if (desc.ReflectionMethod.ReturnType.IsArray &&
                                !chainSpecStack.IsEmpty() &&
                                EnumMethodResolver.IsEnumerationMethod(chainSpecStack.First.GetRootNameOrEmptyString(), validationContext.ImportService))
                            {
                                forge = new ExprDotMethodForgeNoDuck(
                                    validationContext.StatementName,
                                    desc.ReflectionMethod,
                                    paramForges,
                                    ExprDotMethodForgeNoDuck.DuckType.WRAPARRAY);
                            }
                            else
                            {
                                forge = new ExprDotMethodForgeNoDuck(
                                    validationContext.StatementName,
                                    desc.ReflectionMethod,
                                    paramForges,
                                    ExprDotMethodForgeNoDuck.DuckType.PLAIN);
                            }
                        }
                        else
                        {
                            forge = new ExprDotMethodForgeNoDuck(
                                validationContext.StatementName,
                                desc.ReflectionMethod,
                                paramForges,
                                ExprDotMethodForgeNoDuck.DuckType.UNDERLYING);
                        }

                        methodForges.Add(forge);
                        currentInputType = forge.TypeInfo;
                    }
                    catch (Exception e) {
                        if (!isDuckTyping)
                        {
                            throw new ExprValidationException(e.Message, e);
                        }

                        var duck = new ExprDotMethodForgeDuck(
                            validationContext.StatementName,
                            validationContext.ImportService,
                            chainElementName,
                            paramTypes,
                            paramForges);
                        methodForges.Add(duck);
                        currentInputType = duck.TypeInfo;
                    }

                    continue;
                }

                string message;
                if (!(chainElement is ChainableArray))
                {
                    message = "Could not find event property or method named '" + chainElementName + "' in " + currentInputType.ToTypeDescriptive();
                }
                else
                {
                    message = "Could not perform array operation on type " + currentInputType.ToTypeDescriptive();
                }

                throw new ExprValidationException(message);
            }

            var intermediateEvals = methodForges.ToArray();

            if (lastLambdaFunc != null)
            {
                ExprDotForge finalEval = null;
                if (currentInputType is EventMultiValuedEPType mvType)
                {
                    var tableMetadata = validationContext.TableCompileTimeResolver.ResolveTableFromEventType(mvType.Component);
                    if (tableMetadata != null)
                    {
                        finalEval = new ExprDotForgeUnpackCollEventBeanTable(mvType.Component, tableMetadata);
                    }
                    else
                    {
                        finalEval = new ExprDotForgeUnpackCollEventBean(mvType.Component);
                    }
                }
                else if (currentInputType is EventEPType epType)
                {
                    var tableMetadata = validationContext.TableCompileTimeResolver.ResolveTableFromEventType(epType.EventType);
                    if (tableMetadata != null)
                    {
                        finalEval = new ExprDotForgeUnpackBeanTable(epType.EventType, tableMetadata);
                    }
                    else
                    {
                        finalEval = new ExprDotForgeUnpackBean(epType.EventType);
                    }
                }

                if (finalEval != null)
                {
                    methodForges.Add(finalEval);
                }
            }

            var unpackingForges = methodForges.ToArray();

            return(new ExprDotNodeRealizedChain(intermediateEvals, unpackingForges, filterAnalyzerDesc));
        }