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);
        }
        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);
        }