private FileBeginEndProcessor GetBeginEndProcessor(DataFlowOpInitializeContext context,
                                                           int outputPort)
        {
            var portEventType = _factory.OutputPortTypes[outputPort];
            var writeables    = EventTypeUtility.GetWriteableProperties(portEventType, false);
            var writeableList = new List <WriteablePropertyDescriptor>();
            EventBeanManufacturer manufacturer;

            if (_propertyNameFile != null)
            {
                var writeableFile = EventTypeUtility.FindWritable(_propertyNameFile, writeables);
                if (writeableFile == null || writeableFile.PropertyType != typeof(string))
                {
                    throw new EPException("Failed to find writable String-type property '" + _propertyNameFile + "', is the property read-only?");
                }

                writeableList.Add(writeableFile);
            }

            try {
                manufacturer = EventTypeUtility.GetManufacturer(
                    portEventType,
                    writeableList.ToArray(),
                    context.AgentInstanceContext.ImportServiceRuntime,
                    false,
                    context.AgentInstanceContext.EventTypeAvroHandler)
                               .GetManufacturer(context.AgentInstanceContext.EventBeanTypedEventFactory);
            }
            catch (EventBeanManufactureException e) {
                throw new EPException("Event type '" + portEventType.Name + "' cannot be written to: " + e.Message, e);
            }

            return(new FileBeginEndProcessorGeneralPurpose(manufacturer));
        }
Exemple #2
0
        private void RunAssertion(
            RegressionEnvironment env,
            string epl,
            Consumer <object> underlyingAssertion)
        {
            env.CompileDeploy("@public @name('schema') " + epl);

            var type = (EventTypeSPI)env.Deployment.GetDeployment(env.DeploymentId("schema")).Statements[0].EventType;

            var writables = EventTypeUtility.GetWriteableProperties(type, true, true);
            var props     = new WriteablePropertyDescriptor[2];

            props[0] = FindProp(writables, "P1");
            props[1] = FindProp(writables, "P2");

            var spi = (EPRuntimeSPI)env.Runtime;
            EventBeanManufacturer manufacturer;

            var forge = EventTypeUtility.GetManufacturer(
                type,
                props,
                spi.ServicesContext.ImportServiceRuntime,
                true,
                spi.ServicesContext.EventTypeAvroHandler);

            manufacturer = forge.GetManufacturer(spi.ServicesContext.EventBeanTypedEventFactory);

            var @event = manufacturer.Make(new object[] { "a", 1 });

            underlyingAssertion.Invoke(@event.Underlying);
            Assert.AreSame(@event.EventType, type);

            var underlying = manufacturer.MakeUnderlying(new object[] { "a", 1 });

            underlyingAssertion.Invoke(underlying);

            env.UndeployAll();
        }
        public static SelectExprProcessorForge Make(
            EventType[] eventTypes,
            SelectExprForgeContext selectExprForgeContext,
            int streamNumber,
            EventType targetType,
            ExprNode[] exprNodes,
            ImportServiceCompileTime importService,
            string statementName)
        {
            var oaResultType = (ObjectArrayEventType) targetType;
            var oaStreamType = (ObjectArrayEventType) eventTypes[streamNumber];

            // (A) fully assignment-compatible: same number, name and type of fields, no additional expressions: Straight repackage
            if (oaResultType.IsDeepEqualsConsiderOrder(oaStreamType) && selectExprForgeContext.ExprForges.Length == 0) {
                return new OAInsertProcessorSimpleRepackage(selectExprForgeContext, streamNumber, targetType);
            }

            // (B) not completely assignable: find matching properties
            var writables = EventTypeUtility.GetWriteableProperties(oaResultType, true, false);
            IList<Item> items = new List<Item>();
            IList<WriteablePropertyDescriptor> written = new List<WriteablePropertyDescriptor>();

            // find the properties coming from the providing source stream
            foreach (var writeable in writables) {
                var propertyName = writeable.PropertyName;

                var hasIndexSource = oaStreamType.PropertiesIndexes.TryGetValue(propertyName, out var indexSource);
                var hasIndexTarget = oaResultType.PropertiesIndexes.TryGetValue(propertyName, out var indexTarget);
                if (hasIndexSource) {
                    var setOneType = oaStreamType.Types.Get(propertyName);
                    var setTwoType = oaResultType.Types.Get(propertyName);
                    var setTwoTypeFound = oaResultType.Types.ContainsKey(propertyName);
                    var message = BaseNestableEventUtil.ComparePropType(
                        propertyName,
                        setOneType,
                        setTwoType,
                        setTwoTypeFound,
                        oaResultType.Name);
                    if (message != null) {
                        throw new ExprValidationException(message.Message, message);
                    }

                    items.Add(new Item(indexTarget, indexSource, null, null));
                    written.Add(writeable);
                }
            }

            // find the properties coming from the expressions of the select clause
            var count = written.Count;
            for (var i = 0; i < selectExprForgeContext.ExprForges.Length; i++) {
                var columnName = selectExprForgeContext.ColumnNames[i];
                var forge = selectExprForgeContext.ExprForges[i];
                var exprNode = exprNodes[i];

                var writable = FindWritable(columnName, writables);
                if (writable == null) {
                    throw new ExprValidationException(
                        "Failed to find column '" + columnName + "' in target type '" + oaResultType.Name + "'");
                }

                TypeWidenerSPI widener;
                try {
                    widener = TypeWidenerFactory.GetCheckPropertyAssignType(
                        ExprNodeUtilityPrint.ToExpressionStringMinPrecedenceSafe(exprNode),
                        exprNode.Forge.EvaluationType,
                        writable.PropertyType,
                        columnName,
                        false,
                        null,
                        statementName);
                }
                catch (TypeWidenerException ex) {
                    throw new ExprValidationException(ex.Message, ex);
                }

                items.Add(new Item(count, -1, forge, widener));
                written.Add(writable);
                count++;
            }

            // make manufacturer
            var itemsArr = items.ToArray();
            EventBeanManufacturerForge manufacturer;
            try {
                manufacturer = EventTypeUtility.GetManufacturer(
                    oaResultType,
                    written.ToArray(),
                    importService,
                    true,
                    selectExprForgeContext.EventTypeAvroHandler);
            }
            catch (EventBeanManufactureException e) {
                throw new ExprValidationException("Failed to write to type: " + e.Message, e);
            }

            return new OAInsertProcessorAllocate(streamNumber, itemsArr, manufacturer, targetType);
        }
Exemple #4
0
        private static ParseMakePropertiesDesc SetupProperties(bool requireOneMatch,
                                                               string[] propertyNamesOffered,
                                                               EventType outputEventType,
                                                               StatementContext statementContext,
                                                               string dateFormat)
        {
            var writeables = EventTypeUtility.GetWriteableProperties(outputEventType, false, false);

            IList <int> indexesList = new List <int>();
            IList <SimpleTypeParser>            parserList    = new List <SimpleTypeParser>();
            IList <WriteablePropertyDescriptor> writablesList = new List <WriteablePropertyDescriptor>();

            for (var i = 0; i < propertyNamesOffered.Length; i++)
            {
                var  propertyName = propertyNamesOffered[i];
                Type propertyType;
                try {
                    propertyType = outputEventType.GetPropertyType(propertyName);
                }
                catch (PropertyAccessException ex) {
                    throw new EPException("Invalid property name '" + propertyName + "': " + ex.Message, ex);
                }

                if (propertyType == null)
                {
                    continue;
                }

                SimpleTypeParser parser;
                if (propertyType.IsDateTime() && !propertyType.IsInt64())
                {
                    var dateTimeFormat = dateFormat != null
                                                ? DateTimeFormat.For(dateFormat)
                                                : DateTimeFormat.ISO_DATE_TIME;

                    if (propertyType == typeof(DateTime?))
                    {
                        parser = new ProxySimpleTypeParser(
                            text => (dateTimeFormat.Parse(text)?.DateTime)?.DateTime);
                    }
                    else if (propertyType == typeof(DateTime))
                    {
                        parser = new ProxySimpleTypeParser(
                            text => dateTimeFormat.Parse(text).DateTime.DateTime);
                    }
                    else if (propertyType == typeof(DateTimeOffset?))
                    {
                        parser = new ProxySimpleTypeParser(
                            text => dateTimeFormat.Parse(text)?.DateTime);
                    }
                    else if (propertyType == typeof(DateTimeOffset))
                    {
                        parser = new ProxySimpleTypeParser(
                            text => dateTimeFormat.Parse(text).DateTime);
                    }
                    else
                    {
                        parser = new ProxySimpleTypeParser(
                            text => dateTimeFormat.Parse(text));
                    }
                }
                else
                {
                    parser = SimpleTypeParserFactory.GetParser(propertyType);
                }

                var writable = EventTypeUtility.FindWritable(propertyName, writeables);
                if (writable == null)
                {
                    continue;
                }

                indexesList.Add(i);
                parserList.Add(parser);
                writablesList.Add(writable);
            }

            if (indexesList.IsEmpty() && requireOneMatch)
            {
                throw new EPException(
                          "Failed to match any of the properties " +
                          CompatExtensions.RenderAny(propertyNamesOffered) +
                          " to the event type properties of event type '" +
                          outputEventType.Name +
                          "'");
            }

            var parsers   = parserList.ToArray();
            var writables = writablesList.ToArray();
            var indexes   = CollectionUtil.IntArray(indexesList);
            EventBeanManufacturer manufacturer;

            try {
                manufacturer = EventTypeUtility.GetManufacturer(
                    outputEventType,
                    writables,
                    statementContext.ImportServiceRuntime,
                    false,
                    statementContext.EventTypeAvroHandler)
                               .GetManufacturer(statementContext.EventBeanTypedEventFactory);
            }
            catch (EventBeanManufactureException e) {
                throw new EPException("Event type '" + outputEventType.Name + "' cannot be written to: " + e.Message, e);
            }

            return(new ParseMakePropertiesDesc(indexes, parsers, manufacturer));
        }
        private static SelectExprProcessorForge InitializeJoinWildcardInternal(
            EventType eventType,
            ISet<WriteablePropertyDescriptor> writables,
            string[] streamNames,
            EventType[] streamTypes,
            string statementName,
            ImportServiceCompileTime importService,
            EventTypeAvroHandler eventTypeAvroHandler)
        {
            var typeWidenerCustomizer = eventTypeAvroHandler.GetTypeWidenerCustomizer(eventType);
            IList<WriteablePropertyDescriptor> writablePropertiesList = new List<WriteablePropertyDescriptor>();
            IList<ExprForge> forgesList = new List<ExprForge>();
            IList<TypeWidenerSPI> widenersList = new List<TypeWidenerSPI>();

            // loop over all columns selected, if any
            for (var i = 0; i < streamNames.Length; i++) {
                WriteablePropertyDescriptor selectedWritable = null;
                TypeWidenerSPI widener = null;

                foreach (var desc in writables) {
                    if (!desc.PropertyName.Equals(streamNames[i])) {
                        continue;
                    }

                    try {
                        widener = TypeWidenerFactory.GetCheckPropertyAssignType(
                            streamNames[i],
                            streamTypes[i].UnderlyingType,
                            desc.PropertyType,
                            desc.PropertyName,
                            false,
                            typeWidenerCustomizer,
                            statementName);
                    }
                    catch (TypeWidenerException ex) {
                        throw new ExprValidationException(ex.Message, ex);
                    }

                    selectedWritable = desc;
                    break;
                }

                if (selectedWritable == null) {
                    var message = "Stream underlying object for stream '" +
                                  streamNames[i] +
                                  "' could not be assigned to any of the properties of the underlying type (missing column names, event property or setter method?)";
                    throw new ExprValidationException(message);
                }

                ExprForge forge = new ExprForgeStreamUnderlying(i, streamTypes[i].UnderlyingType);

                // add
                writablePropertiesList.Add(selectedWritable);
                forgesList.Add(forge);
                widenersList.Add(widener);
            }

            // assign
            var writableProperties = writablePropertiesList.ToArray();
            var exprForges = forgesList.ToArray();
            var wideners = widenersList.ToArray();

            EventBeanManufacturerForge eventManufacturer;
            try {
                eventManufacturer = EventTypeUtility.GetManufacturer(
                    eventType,
                    writableProperties,
                    importService,
                    false,
                    eventTypeAvroHandler);
            }
            catch (EventBeanManufactureException e) {
                throw new ExprValidationException(e.Message, e);
            }

            return new SelectExprInsertNativeWidening(eventType, eventManufacturer, exprForges, wideners);
        }
        public static SelectExprProcessorForge GetInsertUnderlyingNonJoin(
            EventType eventType,
            bool isUsingWildcard,
            StreamTypeService typeService,
            ExprForge[] forges,
            string[] columnNames,
            object[] expressionReturnTypes,
            InsertIntoDesc insertIntoDesc,
            string[] columnNamesAsProvided,
            bool allowNestableTargetFragmentTypes,
            string statementName,
            ImportServiceCompileTime importService,
            EventTypeAvroHandler eventTypeAvroHandler)
        {
            // handle single-column coercion to underlying, i.e. "insert into MapDefinedEvent select doSomethingReturnMap() from MyEvent"
            if (expressionReturnTypes.Length == 1 &&
                expressionReturnTypes[0] is Type &&
                insertIntoDesc.ColumnNames.IsEmpty() &&
                columnNamesAsProvided[0] == null) {

                var resultType = (Type) expressionReturnTypes[0];
                var compatible = (eventType is BaseNestableEventType || eventType is AvroSchemaEventType) &&
                                 TypeHelper.IsSubclassOrImplementsInterface(resultType, eventType.UnderlyingType);
                compatible = compatible | (eventType is JsonEventType && resultType == typeof(string));

                if (compatible) {
                    if (eventType is MapEventType) {
                        return new SelectExprInsertNativeExpressionCoerceMap(eventType, forges[0]);
                    }

                    if (eventType is ObjectArrayEventType) {
                        return new SelectExprInsertNativeExpressionCoerceObjectArray(eventType, forges[0]);
                    }

                    if (eventType is AvroSchemaEventType) {
                        return new SelectExprInsertNativeExpressionCoerceAvro(eventType, forges[0]);
                    }

                    if (eventType is JsonEventType) {
                        return new SelectExprInsertNativeExpressionCoerceJson(eventType, forges[0]);
                    }

                    throw new IllegalStateException("Unrecognized event type " + eventType);
                }
            }

            // handle special case where the target type has no properties and there is a single "null" value selected
            if (eventType.PropertyDescriptors.Count == 0 &&
                columnNames.Length == 1 &&
                columnNames[0].Equals("null") &&
                expressionReturnTypes[0] == null &&
                !isUsingWildcard) {
                EventBeanManufacturerForge eventManufacturer;
                try {
                    eventManufacturer = EventTypeUtility.GetManufacturer(
                        eventType,
                        new WriteablePropertyDescriptor[0],
                        importService,
                        true,
                        eventTypeAvroHandler);
                }
                catch (EventBeanManufactureException e) {
                    throw new ExprValidationException(e.Message, e);
                }

                return new SelectExprInsertNativeNoEval(eventType, eventManufacturer);
            }

            // handle writing to defined columns
            var writableProps = EventTypeUtility.GetWriteableProperties(eventType, false, false);
            var isEligible = CheckEligible(eventType, writableProps, allowNestableTargetFragmentTypes);
            if (!isEligible) {
                return null;
            }

            try {
                return InitializeSetterManufactor(
                    eventType,
                    writableProps,
                    isUsingWildcard,
                    typeService,
                    forges,
                    columnNames,
                    expressionReturnTypes,
                    statementName,
                    importService,
                    eventTypeAvroHandler);
            }
            catch (ExprValidationException ex) {
                if (!(eventType is BeanEventType)) {
                    throw;
                }

                // Try constructor injection
                try {
                    return InitializeCtorInjection(
                        (BeanEventType) eventType,
                        forges,
                        expressionReturnTypes,
                        importService);
                }
                catch (ExprValidationException) {
                    if (writableProps.IsEmpty()) {
                        throw;
                    }

                    throw ex;
                }
            }
        }
        private static SelectExprProcessorForge InitializeSetterManufactor(
            EventType eventType,
            ISet<WriteablePropertyDescriptor> writables,
            bool isUsingWildcard,
            StreamTypeService typeService,
            ExprForge[] expressionForges,
            string[] columnNames,
            object[] expressionReturnTypes,
            string statementName,
            ImportServiceCompileTime importService,
            EventTypeAvroHandler eventTypeAvroHandler)
        {
            var typeWidenerCustomizer = eventTypeAvroHandler.GetTypeWidenerCustomizer(eventType);
            IList<WriteablePropertyDescriptor> writablePropertiesList = new List<WriteablePropertyDescriptor>();
            IList<ExprForge> forgesList = new List<ExprForge>();
            IList<TypeWidenerSPI> widenersList = new List<TypeWidenerSPI>();

            // loop over all columns selected, if any
            for (var i = 0; i < columnNames.Length; i++) {
                WriteablePropertyDescriptor selectedWritable = null;
                TypeWidenerSPI widener = null;
                var forge = expressionForges[i];

                foreach (var desc in writables) {
                    if (!desc.PropertyName.Equals(columnNames[i])) {
                        continue;
                    }

                    var columnType = expressionReturnTypes[i];
                    if (columnType == null) {
                        try {
                            TypeWidenerFactory.GetCheckPropertyAssignType(
                                columnNames[i],
                                null,
                                desc.PropertyType,
                                desc.PropertyName,
                                false,
                                typeWidenerCustomizer,
                                statementName);
                        }
                        catch (TypeWidenerException ex) {
                            throw new ExprValidationException(ex.Message, ex);
                        }
                    }
                    else if (columnType is EventType) {
                        var columnEventType = (EventType) columnType;
                        var returnType = columnEventType.UnderlyingType;
                        try {
                            widener = TypeWidenerFactory.GetCheckPropertyAssignType(
                                columnNames[i],
                                columnEventType.UnderlyingType,
                                desc.PropertyType,
                                desc.PropertyName,
                                false,
                                typeWidenerCustomizer,
                                statementName);
                        }
                        catch (TypeWidenerException ex) {
                            throw new ExprValidationException(ex.Message, ex);
                        }

                        // handle evaluator returning an event
                        if (TypeHelper.IsSubclassOrImplementsInterface(returnType, desc.PropertyType)) {
                            selectedWritable = desc;
                            widener = new ProxyTypeWidenerSPI {
                                ProcWidenResultType = () => desc.PropertyType,
                                ProcWiden = input => {
                                    if (input is EventBean eventBean) {
                                        return eventBean.Underlying;
                                    }

                                    return input;
                                },

                                ProcWidenCodegen = (
                                    expression,
                                    codegenMethodScope,
                                    codegenClassScope) => {
                                    var method = codegenMethodScope
                                        .MakeChild(typeof(object), typeof(TypeWidenerSPI), codegenClassScope)
                                        .AddParam(typeof(object), "input")
                                        .Block
                                        .IfCondition(InstanceOf(Ref("input"), typeof(EventBean)))
                                        .BlockReturn(
                                            ExprDotName(Cast(typeof(EventBean), Ref("input")), "Underlying"))
                                        .MethodReturn(Ref("input"));
                                    return LocalMethodBuild(method).Pass(expression).Call();
                                }
                            };
                            continue;
                        }

                        // find stream
                        var streamNum = 0;
                        for (var j = 0; j < typeService.EventTypes.Length; j++) {
                            if (typeService.EventTypes[j] == columnEventType) {
                                streamNum = j;
                                break;
                            }
                        }

                        forge = new ExprForgeStreamUnderlying(
                            streamNum,
                            typeService.EventTypes[streamNum].UnderlyingType);
                    }
                    else if (columnType is EventType[]) {
                        // handle case where the select-clause contains an fragment array
                        var columnEventType = ((EventType[]) columnType)[0];
                        var componentReturnType = columnEventType.UnderlyingType;
                        var arrayReturnType = componentReturnType.MakeArrayType();

                        var allowObjectArrayToCollectionConversion = eventType is AvroSchemaEventType;
                        try {
                            widener = TypeWidenerFactory.GetCheckPropertyAssignType(
                                columnNames[i],
                                arrayReturnType,
                                desc.PropertyType,
                                desc.PropertyName,
                                allowObjectArrayToCollectionConversion,
                                typeWidenerCustomizer,
                                statementName);
                        }
                        catch (TypeWidenerException ex) {
                            throw new ExprValidationException(ex.Message, ex);
                        }

                        var inner = forge;
                        forge = new ExprForgeStreamWithInner(inner, componentReturnType);
                    }
                    else if (!(columnType is Type columnAsType)) {
                        var message = "Invalid assignment of column '" +
                                      columnNames[i] +
                                      "' of type '" +
                                      columnType +
                                      "' to event property '" +
                                      desc.PropertyName +
                                      "' typed as '" +
                                      desc.PropertyType.CleanName() +
                                      "', column and parameter types mismatch";
                        throw new ExprValidationException(message);
                    }
                    else {
                        try {
                            widener = TypeWidenerFactory.GetCheckPropertyAssignType(
                                columnNames[i],
                                (Type) columnType,
                                desc.PropertyType,
                                desc.PropertyName,
                                false,
                                typeWidenerCustomizer,
                                statementName);
                        }
                        catch (TypeWidenerException ex) {
                            throw new ExprValidationException(ex.Message, ex);
                        }
                    }

                    selectedWritable = desc;
                    break;
                }

                if (selectedWritable == null) {
                    var message = "Column '" +
                                  columnNames[i] +
                                  "' could not be assigned to any of the properties of the underlying type (missing column names, event property, setter method or constructor?)";
                    throw new ExprValidationException(message);
                }

                // add
                writablePropertiesList.Add(selectedWritable);
                forgesList.Add(forge);
                widenersList.Add(widener);
            }

            // handle wildcard
            if (isUsingWildcard) {
                var sourceType = typeService.EventTypes[0];
                foreach (var eventPropDescriptor in sourceType.PropertyDescriptors) {
                    if (eventPropDescriptor.IsRequiresIndex || eventPropDescriptor.IsRequiresMapKey) {
                        continue;
                    }

                    WriteablePropertyDescriptor selectedWritable = null;
                    TypeWidenerSPI widener = null;
                    ExprForge forge = null;

                    foreach (var writableDesc in writables) {
                        if (!writableDesc.PropertyName.Equals(eventPropDescriptor.PropertyName)) {
                            continue;
                        }

                        try {
                            widener = TypeWidenerFactory.GetCheckPropertyAssignType(
                                eventPropDescriptor.PropertyName,
                                eventPropDescriptor.PropertyType,
                                writableDesc.PropertyType,
                                writableDesc.PropertyName,
                                false,
                                typeWidenerCustomizer,
                                statementName);
                        }
                        catch (TypeWidenerException ex) {
                            throw new ExprValidationException(ex.Message, ex);
                        }

                        selectedWritable = writableDesc;

                        var propertyName = eventPropDescriptor.PropertyName;
                        var getter = ((EventTypeSPI) sourceType).GetGetterSPI(propertyName);
                        forge = new ExprForgeStreamWithGetter(getter);
                        break;
                    }

                    if (selectedWritable == null) {
                        var message = "Event property '" +
                                      eventPropDescriptor.PropertyName +
                                      "' could not be assigned to any of the properties of the underlying type (missing column names, event property, setter method or constructor?)";
                        throw new ExprValidationException(message);
                    }

                    writablePropertiesList.Add(selectedWritable);
                    forgesList.Add(forge);
                    widenersList.Add(widener);
                }
            }

            // assign
            var writableProperties = writablePropertiesList.ToArray();
            var exprForges = forgesList.ToArray();
            var wideners = widenersList.ToArray();

            EventBeanManufacturerForge eventManufacturer;
            try {
                eventManufacturer = EventTypeUtility.GetManufacturer(
                    eventType,
                    writableProperties,
                    importService,
                    false,
                    eventTypeAvroHandler);
            }
            catch (EventBeanManufactureException e) {
                throw new ExprValidationException(e.Message, e);
            }
            
            if (eventManufacturer == null) {
                return null;
            }

            return new SelectExprInsertNativeWidening(eventType, eventManufacturer, exprForges, wideners);
        }
        public static PropertyEvaluatorForge MakeEvaluator(
            PropertyEvalSpec spec,
            EventType sourceEventType,
            string optionalSourceStreamName,
            StatementRawInfo rawInfo,
            StatementCompileTimeServices services)
        {
            var length = spec.Atoms.Count;
            var containedEventForges = new ContainedEventEvalForge[length];
            var fragmentEventTypes = new FragmentEventType[length];
            var currentEventType = sourceEventType;
            var whereClauses = new ExprForge[length];

            IList<EventType> streamEventTypes = new List<EventType>();
            IList<string> streamNames = new List<string>();
            IDictionary<string, int> streamNameAndNumber = new Dictionary<string, int>().WithNullKeySupport();
            IList<string> expressionTexts = new List<string>();

            streamEventTypes.Add(sourceEventType);
            streamNames.Add(optionalSourceStreamName);
            streamNameAndNumber.Put(optionalSourceStreamName, 0);
            expressionTexts.Add(sourceEventType.Name);

            IList<SelectClauseElementCompiled> cumulativeSelectClause = new List<SelectClauseElementCompiled>();
            for (var i = 0; i < length; i++) {
                var atom = spec.Atoms[i];
                ContainedEventEvalForge containedEventEval = null;
                string expressionText = null;
                EventType streamEventType = null;
                FragmentEventType fragmentEventType = null;

                // Resolve directly as fragment event type if possible
                if (atom.SplitterExpression is ExprIdentNode) {
                    var propertyName = ((ExprIdentNode) atom.SplitterExpression).FullUnresolvedName;
                    fragmentEventType = currentEventType.GetFragmentType(propertyName);
                    if (fragmentEventType != null) {
                        var getter = ((EventTypeSPI) currentEventType).GetGetterSPI(propertyName);
                        if (getter != null) {
                            containedEventEval = new ContainedEventEvalGetterForge(getter);
                            expressionText = propertyName;
                            streamEventType = fragmentEventType.FragmentType;
                        }
                    }
                }

                // evaluate splitter expression
                if (containedEventEval == null) {
                    ExprNodeUtilityValidate.ValidatePlainExpression(
                        ExprNodeOrigin.CONTAINEDEVENT,
                        atom.SplitterExpression);

                    var availableTypes = streamEventTypes.ToArray();
                    var availableStreamNames = streamNames.ToArray();
                    var isIStreamOnly = new bool[streamNames.Count];
                    isIStreamOnly.Fill(true);
                    StreamTypeService streamTypeService = new StreamTypeServiceImpl(
                        availableTypes,
                        availableStreamNames,
                        isIStreamOnly,
                        false,
                        false);
                    var validationContext = new ExprValidationContextBuilder(streamTypeService, rawInfo, services)
                        .WithAllowBindingConsumption(true)
                        .Build();
                    var validatedExprNode = ExprNodeUtilityValidate.GetValidatedSubtree(
                        ExprNodeOrigin.CONTAINEDEVENT,
                        atom.SplitterExpression,
                        validationContext);

                    // determine result type
                    if (atom.OptionalResultEventType == null) {
                        throw new ExprValidationException(
                            "Missing @type(name) declaration providing the event type name of the return type for expression '" +
                            ExprNodeUtilityPrint.ToExpressionStringMinPrecedenceSafe(atom.SplitterExpression) +
                            "'");
                    }

                    streamEventType = services.EventTypeCompileTimeResolver.GetTypeByName(atom.OptionalResultEventType);
                    if (streamEventType == null) {
                        throw new ExprValidationException(
                            "Event type by name '" + atom.OptionalResultEventType + "' could not be found");
                    }

                    var returnType = validatedExprNode.Forge.EvaluationType;

                    // when the expression returns an array, allow array values to become the column of the single-column event type
                    if (returnType.IsArray &&
                        streamEventType.PropertyNames.Length == 1 &&
                        !(streamEventType is JsonEventType) && // since json string-array should not become itself the property
                        TypeHelper.IsSubclassOrImplementsInterface(
                            returnType.GetElementType().GetBoxedType(),
                            streamEventType.GetPropertyType(streamEventType.PropertyNames[0]).GetBoxedType())) {
                        var writables = EventTypeUtility.GetWriteableProperties(streamEventType, false, false);
                        if (writables != null && !writables.IsEmpty()) {
                            try {
                                var manufacturer = EventTypeUtility.GetManufacturer(
                                    streamEventType,
                                    new[] {writables.First()},
                                    services.ImportServiceCompileTime,
                                    false,
                                    services.EventTypeAvroHandler);
                                containedEventEval = new ContainedEventEvalArrayToEventForge(
                                    validatedExprNode.Forge,
                                    manufacturer);
                            }
                            catch (EventBeanManufactureException e) {
                                throw new ExprValidationException(
                                    "Event type '" + streamEventType.Name + "' cannot be populated: " + e.Message,
                                    e);
                            }
                        }
                        else {
                            throw new ExprValidationException(
                                "Event type '" + streamEventType.Name + "' cannot be written to");
                        }
                    }
                    else if (returnType.IsArray &&
                             returnType.GetElementType() == typeof(EventBean)) {
                        containedEventEval = new ContainedEventEvalEventBeanArrayForge(validatedExprNode.Forge);
                    }
                    else {
                        // check expression result type against eventtype expected underlying type
                        if (returnType.IsArray) {
                            if (!(streamEventType is JsonEventType)) {
                                if (!TypeHelper.IsSubclassOrImplementsInterface(
                                    returnType.GetElementType(),
                                    streamEventType.UnderlyingType)) {
                                    throw new ExprValidationException(
                                        "Event type '" +
                                        streamEventType.Name +
                                        "' underlying type " +
                                        streamEventType.UnderlyingType.CleanName() +
                                        " cannot be assigned a value of type " +
                                        returnType.CleanName());
                                }
                            }
                            else {
                                if (returnType.GetElementType() != typeof(string)) {
                                    throw new ExprValidationException(
                                        "Event type '" +
                                        streamEventType.Name +
                                        "' requires string-type array and cannot be assigned from value of type " +
                                        returnType.CleanName());
                                }
                            }
                        }
                        else if (GenericExtensions.IsGenericEnumerable(returnType) || 
                                 TypeHelper.IsImplementsInterface<System.Collections.IEnumerable>(returnType)) {
                            // fine, assumed to return the right type
                        }
                        else {
                            throw new ExprValidationException(
                                "Return type of expression '" +
                                ExprNodeUtilityPrint.ToExpressionStringMinPrecedenceSafe(atom.SplitterExpression) +
                                "' is '" +
                                returnType.Name +
                                "', expected an Iterable or array result");
                        }

                        containedEventEval = new ContainedEventEvalExprNodeForge(
                            validatedExprNode.Forge,
                            streamEventType);
                    }

                    expressionText = ExprNodeUtilityPrint.ToExpressionStringMinPrecedenceSafe(validatedExprNode);
                    fragmentEventType = new FragmentEventType(streamEventType, true, false);
                }

                // validate where clause, if any
                streamEventTypes.Add(streamEventType);
                streamNames.Add(atom.OptionalAsName);
                streamNameAndNumber.Put(atom.OptionalAsName, i + 1);
                expressionTexts.Add(expressionText);

                if (atom.OptionalWhereClause != null) {
                    var whereTypes = streamEventTypes.ToArray();
                    var whereStreamNames = streamNames.ToArray();
                    var isIStreamOnly = new bool[streamNames.Count];
                    isIStreamOnly.Fill(true);
                    StreamTypeService streamTypeService = new StreamTypeServiceImpl(
                        whereTypes,
                        whereStreamNames,
                        isIStreamOnly,
                        false,
                        false);
                    var validationContext = new ExprValidationContextBuilder(streamTypeService, rawInfo, services)
                        .WithAllowBindingConsumption(true)
                        .Build();
                    var whereClause = ExprNodeUtilityValidate.GetValidatedSubtree(
                        ExprNodeOrigin.CONTAINEDEVENT,
                        atom.OptionalWhereClause,
                        validationContext);
                    whereClauses[i] = whereClause.Forge;
                }

                // validate select clause
                if (atom.OptionalSelectClause != null && !atom.OptionalSelectClause.SelectExprList.IsEmpty()) {
                    var whereTypes = streamEventTypes.ToArray();
                    var whereStreamNames = streamNames.ToArray();
                    var isIStreamOnly = new bool[streamNames.Count];
                    isIStreamOnly.Fill(true);
                    StreamTypeService streamTypeService = new StreamTypeServiceImpl(
                        whereTypes,
                        whereStreamNames,
                        isIStreamOnly,
                        false,
                        false);
                    var validationContext = new ExprValidationContextBuilder(streamTypeService, rawInfo, services)
                        .WithAllowBindingConsumption(true)
                        .Build();

                    foreach (var raw in atom.OptionalSelectClause.SelectExprList) {
                        if (raw is SelectClauseStreamRawSpec) {
                            var rawStreamSpec = (SelectClauseStreamRawSpec) raw;
                            if (!streamNames.Contains(rawStreamSpec.StreamName)) {
                                throw new ExprValidationException(
                                    "Property rename '" + rawStreamSpec.StreamName + "' not found in path");
                            }

                            var streamSpec = new SelectClauseStreamCompiledSpec(
                                rawStreamSpec.StreamName,
                                rawStreamSpec.OptionalAsName);
                            var streamNumber = streamNameAndNumber.Get(rawStreamSpec.StreamName);
                            streamSpec.StreamNumber = streamNumber;
                            cumulativeSelectClause.Add(streamSpec);
                        }
                        else if (raw is SelectClauseExprRawSpec) {
                            var exprSpec = (SelectClauseExprRawSpec) raw;
                            var exprCompiled = ExprNodeUtilityValidate.GetValidatedSubtree(
                                ExprNodeOrigin.CONTAINEDEVENT,
                                exprSpec.SelectExpression,
                                validationContext);
                            var resultName = exprSpec.OptionalAsName;
                            if (resultName == null) {
                                resultName = ExprNodeUtilityPrint.ToExpressionStringMinPrecedenceSafe(exprCompiled);
                            }

                            cumulativeSelectClause.Add(
                                new SelectClauseExprCompiledSpec(
                                    exprCompiled,
                                    resultName,
                                    exprSpec.OptionalAsName,
                                    exprSpec.IsEvents));

                            var isMinimal = ExprNodeUtilityValidate.IsMinimalExpression(exprCompiled);
                            if (isMinimal != null) {
                                throw new ExprValidationException(
                                    "Expression in a property-selection may not utilize " + isMinimal);
                            }
                        }
                        else if (raw is SelectClauseElementWildcard) {
                            // wildcards are stream selects: we assign a stream name (any) and add a stream wildcard select
                            var streamNameAtom = atom.OptionalAsName;
                            if (streamNameAtom == null) {
                                streamNameAtom = UuidGenerator.Generate();
                            }

                            var streamSpec = new SelectClauseStreamCompiledSpec(streamNameAtom, atom.OptionalAsName);
                            var streamNumber = i + 1;
                            streamSpec.StreamNumber = streamNumber;
                            cumulativeSelectClause.Add(streamSpec);
                        }
                        else {
                            throw new IllegalStateException("Unknown select clause item:" + raw);
                        }
                    }
                }

                currentEventType = fragmentEventType.FragmentType;
                fragmentEventTypes[i] = fragmentEventType;
                containedEventForges[i] = containedEventEval;
            }

            if (cumulativeSelectClause.IsEmpty()) {
                if (length == 1) {
                    return new PropertyEvaluatorSimpleForge(
                        containedEventForges[0],
                        fragmentEventTypes[0],
                        whereClauses[0],
                        expressionTexts[0]);
                }

                return new PropertyEvaluatorNestedForge(
                    containedEventForges,
                    fragmentEventTypes,
                    whereClauses,
                    expressionTexts.ToArray());
            }

            {
                var fragmentEventTypeIsIndexed = new bool[fragmentEventTypes.Length];
                for (var i = 0; i < fragmentEventTypes.Length; i++) {
                    fragmentEventTypeIsIndexed[i] = fragmentEventTypes[i].IsIndexed;
                }

                var accumulative = new PropertyEvaluatorAccumulativeForge(
                    containedEventForges,
                    fragmentEventTypeIsIndexed,
                    whereClauses,
                    expressionTexts);

                var whereTypes = streamEventTypes.ToArray();
                var whereStreamNames = streamNames.ToArray();
                var isIStreamOnly = new bool[streamNames.Count];
                isIStreamOnly.Fill(true);
                StreamTypeService streamTypeService = new StreamTypeServiceImpl(
                    whereTypes,
                    whereStreamNames,
                    isIStreamOnly,
                    false,
                    false);

                var cumulativeSelectArr = cumulativeSelectClause.ToArray();
                var args = new SelectProcessorArgs(
                    cumulativeSelectArr,
                    null,
                    false,
                    null,
                    null,
                    streamTypeService,
                    null,
                    false,
                    rawInfo.Annotations,
                    rawInfo,
                    services);
                var selectExprDesc = SelectExprProcessorFactory.GetProcessor(args, null, false);

                return new PropertyEvaluatorSelectForge(selectExprDesc, accumulative);
            }
        }
Exemple #9
0
        private DataFlowOpForgeInitializeResult InitializeTypeDeclared(
            DataFlowOpOutputPort port,
            DataFlowOpForgeInitializeContext context)
        {
            produceEventBean = port.OptionalDeclaredType != null && !port.OptionalDeclaredType.IsUnderlying;

            // compile properties to populate
            outputEventType = port.OptionalDeclaredType.EventType;
            var props = allProperties.Keys;
            props.RemoveAll(PARAMETER_PROPERTIES);
            var writables = SetupProperties(props.ToArray(), outputEventType);
            try {
                eventBeanManufacturer = EventTypeUtility.GetManufacturer(
                    outputEventType,
                    writables,
                    context.Services.ImportServiceCompileTime,
                    false,
                    context.Services.EventTypeAvroHandler);
            }
            catch (EventBeanManufactureException e) {
                throw new ExprValidationException(
                    "Cannot manufacture event for the provided type '" + outputEventType.Name + "': " + e.Message,
                    e);
            }

            var index = 0;
            evaluatorForges = new ExprForge[writables.Length];
            var typeWidenerCustomizer =
                context.Services.EventTypeAvroHandler.GetTypeWidenerCustomizer(outputEventType);
            foreach (var writable in writables) {
                object providedProperty = allProperties.Get(writable.PropertyName);
                var exprNode = (ExprNode) providedProperty;
                var validated = EPLValidationUtil.ValidateSimpleGetSubtree(
                    ExprNodeOrigin.DATAFLOWBEACON,
                    exprNode,
                    null,
                    false,
                    context.Base.StatementRawInfo,
                    context.Services);
                TypeWidenerSPI widener;
                try {
                    widener = TypeWidenerFactory.GetCheckPropertyAssignType(
                        ExprNodeUtilityPrint.ToExpressionStringMinPrecedenceSafe(validated),
                        validated.Forge.EvaluationType,
                        writable.PropertyType,
                        writable.PropertyName,
                        false,
                        typeWidenerCustomizer,
                        context.Base.StatementName);
                }
                catch (TypeWidenerException e) {
                    throw new ExprValidationException("Failed for property '" + writable.PropertyName + "'", e);
                }

                if (widener != null) {
                    evaluatorForges[index] = new ExprEvalWithTypeWidener(widener, validated, writable.PropertyType);
                }
                else {
                    evaluatorForges[index] = validated.Forge;
                }

                index++;
            }

            return null;
        }
        public FileSourceLineUnformatted(
            FileSourceFactory factory,
            DataFlowOpInitializeContext context,
            AdapterInputSource inputSource,
            string filenameOrUri,
            string propertyNameLine,
            string propertyNameFile)
        {
            _factory          = factory;
            _inputSource      = inputSource;
            _filenameOrUri    = filenameOrUri;
            _propertyNameLine = propertyNameLine;
            _propertyNameFile = propertyNameFile;

            var outputEventType  = factory.OutputEventType;
            var statementContext = context.AgentInstanceContext.StatementContext;

            if ((outputEventType.PropertyNames.Length != 1 || outputEventType.PropertyDescriptors[0].PropertyType != typeof(string)) &&
                propertyNameLine == null)
            {
                throw new ArgumentException(
                          "Expecting an output event type that has a single property that is of type string, or alternatively specify the 'propertyNameLine' parameter");
            }

            if (outputEventType is ObjectArrayEventType && outputEventType.PropertyDescriptors.Count == 1)
            {
                _lineProcessor = new LineProcessorObjectArray();
            }
            else
            {
                var propertyNameLineToUse = propertyNameLine;
                if (propertyNameLineToUse == null)
                {
                    propertyNameLineToUse = outputEventType.PropertyDescriptors[0].PropertyName;
                }

                if (!outputEventType.IsProperty(propertyNameLineToUse))
                {
                    throw new EPException("Failed to find property name '" + propertyNameLineToUse + "' in type '" + outputEventType.Name + "'");
                }

                Type propertyType;
                try {
                    propertyType = outputEventType.GetPropertyType(propertyNameLineToUse);
                }
                catch (PropertyAccessException ex) {
                    throw new EPException("Invalid property name '" + propertyNameLineToUse + "': " + ex.Message, ex);
                }

                if (propertyType != typeof(string))
                {
                    throw new EPException("Invalid property type for property '" + propertyNameLineToUse + "', expected a property of type String");
                }

                var writeables = EventTypeUtility.GetWriteableProperties(outputEventType, false);
                IList <WriteablePropertyDescriptor> writeableList = new List <WriteablePropertyDescriptor>();

                var writeableLine = EventTypeUtility.FindWritable(propertyNameLineToUse, writeables);
                if (writeableLine == null)
                {
                    throw new EPException("Failed to find writable property property '" + propertyNameLineToUse + "', is the property read-only?");
                }

                writeableList.Add(writeableLine);

                if (propertyNameFile != null)
                {
                    var writeableFile = EventTypeUtility.FindWritable(propertyNameFile, writeables);
                    if (writeableFile == null || writeableFile.PropertyType != typeof(string))
                    {
                        throw new EPException("Failed to find writable String-type property '" + propertyNameFile + "', is the property read-only?");
                    }

                    writeableList.Add(writeableFile);
                }

                EventBeanManufacturer manufacturer;
                try {
                    var writables = writeableList.ToArray();
                    manufacturer = EventTypeUtility
                                   .GetManufacturer(outputEventType, writables, statementContext.ImportServiceRuntime, false, statementContext.EventTypeAvroHandler)
                                   .GetManufacturer(statementContext.EventBeanTypedEventFactory);
                }
                catch (EventBeanManufactureException e) {
                    throw new EPException("Event type '" + outputEventType.Name + "' cannot be written to: " + e.Message, e);
                }

                _lineProcessor = new LineProcessorGeneralPurpose(manufacturer);
            }

            if (factory.OutputPortTypes.Length == 2)
            {
                _eofProcessor = GetBeginEndProcessor(context, 1);
            }
            else if (factory.OutputPortTypes.Length == 3)
            {
                _bofProcessor = GetBeginEndProcessor(context, 1);
                _eofProcessor = GetBeginEndProcessor(context, 2);
            }
            else if (factory.OutputPortTypes.Length > 3)
            {
                throw new EPException("Operator only allows up to 3 output ports");
            }
        }