public HistoricalEventViewableMethodForge(
     int streamNum,
     EventType eventType,
     MethodStreamSpec methodStreamSpec,
     MethodPollingViewableMeta metadata)
     : base(streamNum, eventType)
 {
     this.methodStreamSpec = methodStreamSpec;
     this.metadata = metadata;
 }
Beispiel #2
0
        public static HistoricalEventViewableMethodForge CreateMethodStatementView(
            int stream,
            MethodStreamSpec methodStreamSpec,
            StatementBaseInfo @base,
            StatementCompileTimeServices services)
        {
            var variableMetaData = services.VariableCompileTimeResolver.Resolve(methodStreamSpec.ClassName);
            MethodPollingExecStrategyEnum strategy;
            MethodInfo methodReflection = null;
            string eventTypeNameProvidedUDFOrScript = null;
            var contextName = @base.StatementSpec.Raw.OptionalContextName;
            var classpathImportService = services.ImportServiceCompileTime;

            // see if this is a script in the from-clause
            ExprNodeScript scriptExpression = null;
            if (methodStreamSpec.ClassName == null && methodStreamSpec.MethodName != null) {
                var script = services.ScriptCompileTimeResolver.Resolve(
                    methodStreamSpec.MethodName,
                    methodStreamSpec.Expressions.Count);
                if (script != null) {
                    scriptExpression = new ExprNodeScript(
                        services.Configuration.Compiler.Scripts.DefaultDialect,
                        script,
                        methodStreamSpec.Expressions);
                }
            }

            try {
                if (scriptExpression != null) {
                    eventTypeNameProvidedUDFOrScript = scriptExpression.EventTypeNameAnnotation;
                    strategy = MethodPollingExecStrategyEnum.TARGET_SCRIPT;
                    EPLValidationUtil.ValidateSimpleGetSubtree(
                        ExprNodeOrigin.METHODINVJOIN,
                        scriptExpression,
                        null,
                        false,
                        @base.StatementRawInfo,
                        services);
                }
                else if (variableMetaData != null) {
                    var variableName = variableMetaData.VariableName;
                    if (variableMetaData.OptionalContextName != null) {
                        if (contextName == null || !contextName.Equals(variableMetaData.OptionalContextName)) {
                            throw new ExprValidationException(
                                "Variable by name '" +
                                variableMetaData.VariableName +
                                "' has been declared for context '" +
                                variableMetaData.OptionalContextName +
                                "' and can only be used within the same context");
                        }

                        strategy = MethodPollingExecStrategyEnum.TARGET_VAR_CONTEXT;
                    }
                    else {
                        if (variableMetaData.IsConstant) {
                            strategy = MethodPollingExecStrategyEnum.TARGET_CONST;
                        }
                        else {
                            strategy = MethodPollingExecStrategyEnum.TARGET_VAR;
                        }
                    }

                    methodReflection = classpathImportService.ResolveNonStaticMethodOverloadChecked(
                        variableMetaData.Type,
                        methodStreamSpec.MethodName);
                }
                else if (methodStreamSpec.ClassName == null) { // must be either UDF or script
                    Pair<Type, ImportSingleRowDesc> udf;
                    try {
                        udf = classpathImportService.ResolveSingleRow(
                            methodStreamSpec.MethodName,
                            services.ClassProvidedExtension);
                    }
                    catch (ImportException ex) {
                        throw new ExprValidationException(
                            "Failed to find user-defined function '" + methodStreamSpec.MethodName + "': " + ex.Message,
                            ex);
                    }

                    methodReflection = classpathImportService.ResolveMethodOverloadChecked(
                        udf.First,
                        methodStreamSpec.MethodName);
                    eventTypeNameProvidedUDFOrScript = udf.Second.OptionalEventTypeName;
                    strategy = MethodPollingExecStrategyEnum.TARGET_CONST;
                }
                else {
                    methodReflection = classpathImportService.ResolveMethodOverloadChecked(
                        methodStreamSpec.ClassName,
                        methodStreamSpec.MethodName,
                        services.ClassProvidedExtension);
                    strategy = MethodPollingExecStrategyEnum.TARGET_CONST;
                }
            }
            catch (ExprValidationException) {
                throw;
            }
            catch (Exception e) {
                throw new ExprValidationException(e.Message, e);
            }

            Type methodProviderClass = null;
            Type beanClass;
            IDictionary<string, object> oaType = null;
            IDictionary<string, object> mapType = null;
            var isCollection = false;
            var isEnumerator = false;
            EventType eventType;
            EventType eventTypeWhenMethodReturnsEventBeans = null;
            var isStaticMethod = false;

            if (methodReflection != null) {
                methodProviderClass = methodReflection.DeclaringType;
                isStaticMethod = variableMetaData == null;

                // Determine object type returned by method
                beanClass = methodReflection.ReturnType;
                if (beanClass == typeof(void) || beanClass == typeof(void) || beanClass.IsBuiltinDataType()) {
                    throw new ExprValidationException(
                        "Invalid return type for static method '" +
                        methodReflection.Name +
                        "' of class '" +
                        methodStreamSpec.ClassName +
                        "', expecting a type");
                }

                if (methodReflection.ReturnType.IsArray &&
                    methodReflection.ReturnType.GetElementType() != typeof(EventBean)) {
                    beanClass = methodReflection.ReturnType.GetElementType();
                }

                isCollection = beanClass.IsGenericCollection() && !beanClass.IsGenericDictionary();
                Type collectionClass = null;
                if (isCollection) {
                    collectionClass = TypeHelper.GetGenericReturnType(methodReflection, true);
                    beanClass = collectionClass;
                }

                isEnumerator = beanClass.IsGenericEnumerator();
                Type enumerator = null;
                if (isEnumerator) {
                    enumerator = TypeHelper.GetGenericReturnType(methodReflection, true);
                    beanClass = enumerator;
                }

                // If the method returns a Map, look up the map type
                string mapTypeName = null;
                if (methodReflection.ReturnType.IsGenericDictionary() ||
                    methodReflection.ReturnType.IsArray &&
                    methodReflection.ReturnType.GetElementType().IsGenericDictionary() ||
                    isCollection && collectionClass.IsGenericDictionary() ||
                    isEnumerator && enumerator.IsGenericDictionary()) {
                    MethodMetadataDesc metadata;
                    if (variableMetaData != null) {
                        metadata = GetCheckMetadataVariable(
                            methodStreamSpec.MethodName,
                            variableMetaData,
                            classpathImportService,
                            typeof(IDictionary<string, object>));
                    }
                    else {
                        metadata = GetCheckMetadataNonVariable(
                            methodStreamSpec.MethodName,
                            methodStreamSpec.ClassName,
                            classpathImportService,
                            typeof(IDictionary<string, object>));
                    }

                    mapTypeName = metadata.TypeName;
                    mapType = (IDictionary<string, object>) metadata.TypeMetadata;
                }

                // If the method returns an Object[] or Object[][], look up the type information
                string oaTypeName = null;
                if (methodReflection.ReturnType == typeof(object[]) ||
                    methodReflection.ReturnType == typeof(object[][]) ||
                    isCollection && collectionClass == typeof(object[]) ||
                    isEnumerator && enumerator == typeof(object[])) {
                    MethodMetadataDesc metadata;
                    if (variableMetaData != null) {
                        metadata = GetCheckMetadataVariable(
                            methodStreamSpec.MethodName,
                            variableMetaData,
                            classpathImportService,
                            typeof(IDictionary<string, object>));
                    }
                    else {
                        metadata = GetCheckMetadataNonVariable(
                            methodStreamSpec.MethodName,
                            methodStreamSpec.ClassName,
                            classpathImportService,
                            typeof(IDictionary<string, object>));
                    }

                    oaTypeName = metadata.TypeName;
                    oaType = (IDictionary<string, object>) metadata.TypeMetadata;
                }

                // Determine event type from class and method name
                // If the method returns EventBean[], require the event type
                Func<EventTypeApplicationType, EventTypeMetadata> metadataFunction = apptype => {
                    var eventTypeName = services.EventTypeNameGeneratorStatement.GetAnonymousMethodHistorical(stream);
                    return new EventTypeMetadata(
                        eventTypeName,
                        @base.ModuleName,
                        EventTypeTypeClass.METHODPOLLDERIVED,
                        apptype,
                        NameAccessModifier.TRANSIENT,
                        EventTypeBusModifier.NONBUS,
                        false,
                        EventTypeIdPair.Unassigned());
                };
                if (methodReflection.ReturnType.IsArray &&
                    methodReflection.ReturnType.GetElementType() == typeof(EventBean) ||
                    isCollection && collectionClass == typeof(EventBean) ||
                    isEnumerator && enumerator == typeof(EventBean)) {
                    var typeName = methodStreamSpec.EventTypeName == null
                        ? eventTypeNameProvidedUDFOrScript
                        : methodStreamSpec.EventTypeName;
                    eventType = EventTypeUtility.RequireEventType(
                        "Method",
                        methodReflection.Name,
                        typeName,
                        services.EventTypeCompileTimeResolver);
                    eventTypeWhenMethodReturnsEventBeans = eventType;
                }
                else if (mapType != null) {
                    eventType = BaseNestableEventUtil.MakeMapTypeCompileTime(
                        metadataFunction.Invoke(EventTypeApplicationType.MAP),
                        mapType,
                        null,
                        null,
                        null,
                        null,
                        services.BeanEventTypeFactoryPrivate,
                        services.EventTypeCompileTimeResolver);
                    services.EventTypeCompileTimeRegistry.NewType(eventType);
                }
                else if (oaType != null) {
                    eventType = BaseNestableEventUtil.MakeOATypeCompileTime(
                        metadataFunction.Invoke(EventTypeApplicationType.OBJECTARR),
                        oaType,
                        null,
                        null,
                        null,
                        null,
                        services.BeanEventTypeFactoryPrivate,
                        services.EventTypeCompileTimeResolver);
                    services.EventTypeCompileTimeRegistry.NewType(eventType);
                }
                else {
                    var stem = services.BeanEventTypeStemService.GetCreateStem(beanClass, null);
                    eventType = new BeanEventType(
                        services.Container,
                        stem,
                        metadataFunction.Invoke(EventTypeApplicationType.CLASS),
                        services.BeanEventTypeFactoryPrivate,
                        null,
                        null,
                        null,
                        null);
                    services.EventTypeCompileTimeRegistry.NewType(eventType);
                }

                // the @type is only allowed in conjunction with EventBean return types
                if (methodStreamSpec.EventTypeName != null && eventTypeWhenMethodReturnsEventBeans == null) {
                    throw new ExprValidationException(EventTypeUtility.DisallowedAtTypeMessage());
                }
            }
            else {
                var eventTypeName = methodStreamSpec.EventTypeName == null
                    ? scriptExpression.EventTypeNameAnnotation
                    : methodStreamSpec.EventTypeName;
                eventType = EventTypeUtility.RequireEventType(
                    "Script",
                    scriptExpression.Script.Name,
                    eventTypeName,
                    services.EventTypeCompileTimeResolver);
            }

            // metadata
            var meta = new MethodPollingViewableMeta(
                methodProviderClass,
                isStaticMethod,
                mapType,
                oaType,
                strategy,
                isCollection,
                isEnumerator,
                variableMetaData,
                eventTypeWhenMethodReturnsEventBeans,
                scriptExpression);
            return new HistoricalEventViewableMethodForge(stream, eventType, methodStreamSpec, meta);
        }
        public static Pair<MethodTargetStrategyForge, MethodConversionStrategyForge> Plan(
            MethodPollingViewableMeta metadata,
            MethodInfo targetMethod,
            EventType eventType)
        {
            MethodTargetStrategyForge target = null;
            MethodConversionStrategyForge conversion = null;

            // class-based evaluation
            if (metadata.MethodProviderClass != null) {
                // Construct polling strategy as a method invocation
                MethodPollingExecStrategyEnum strategy = metadata.Strategy;
                VariableMetaData variable = metadata.Variable;
                if (variable == null) {
                    target = new MethodTargetStrategyStaticMethodForge(metadata.MethodProviderClass, targetMethod);
                }
                else {
                    target = new MethodTargetStrategyVariableForge(variable, targetMethod);
                }

                if (metadata.EventTypeEventBeanArray != null) {
                    conversion = new MethodConversionStrategyForge(
                        eventType,
                        typeof(MethodConversionStrategyEventBeans));
                }
                else if (metadata.OptionalMapType != null) {
                    if (targetMethod.ReturnType.IsArray) {
                        conversion = new MethodConversionStrategyForge(
                            eventType,
                            typeof(MethodConversionStrategyArrayMap));
                    }
                    else if (metadata.IsCollection) {
                        conversion = new MethodConversionStrategyForge(
                            eventType,
                            typeof(MethodConversionStrategyCollectionMap));
                    }
                    else if (metadata.IsIterator) {
                        conversion = new MethodConversionStrategyForge(
                            eventType,
                            typeof(MethodConversionStrategyIteratorMap));
                    }
                    else {
                        conversion = new MethodConversionStrategyForge(
                            eventType,
                            typeof(MethodConversionStrategyPlainMap));
                    }
                }
                else if (metadata.OptionalOaType != null) {
                    if (targetMethod.ReturnType == typeof(object[][])) {
                        conversion = new MethodConversionStrategyForge(
                            eventType,
                            typeof(MethodConversionStrategyArrayOA));
                    }
                    else if (metadata.IsCollection) {
                        conversion = new MethodConversionStrategyForge(
                            eventType,
                            typeof(MethodConversionStrategyCollectionOA));
                    }
                    else if (metadata.IsIterator) {
                        conversion = new MethodConversionStrategyForge(
                            eventType,
                            typeof(MethodConversionStrategyIteratorOA));
                    }
                    else {
                        conversion = new MethodConversionStrategyForge(
                            eventType,
                            typeof(MethodConversionStrategyPlainOA));
                    }
                }
                else {
                    if (targetMethod.ReturnType.IsArray) {
                        conversion = new MethodConversionStrategyForge(
                            eventType,
                            typeof(MethodConversionStrategyArrayPONO));
                    }
                    else if (metadata.IsCollection) {
                        conversion = new MethodConversionStrategyForge(
                            eventType,
                            typeof(MethodConversionStrategyCollectionPONO));
                    }
                    else if (metadata.IsIterator) {
                        conversion = new MethodConversionStrategyForge(
                            eventType,
                            typeof(MethodConversionStrategyIteratorPONO));
                    }
                    else {
                        conversion = new MethodConversionStrategyForge(
                            eventType,
                            typeof(MethodConversionStrategyPlainPONO));
                    }
                }
            }
            else {
                target = new MethodTargetStrategyScriptForge(metadata.ScriptExpression);
                conversion = new MethodConversionStrategyForge(eventType, typeof(MethodConversionStrategyScript));
            }

            return new Pair<MethodTargetStrategyForge, MethodConversionStrategyForge>(target, conversion);
        }