private IList<StmtClassForgeableFactory> ValidateContextDetail( ContextSpec contextSpec, int nestingLevel, CreateContextValidationEnv validationEnv) { ISet<string> eventTypesReferenced = new HashSet<string>(); IList<StmtClassForgeableFactory> additionalForgeables = new List<StmtClassForgeableFactory>(); if (contextSpec is ContextSpecKeyed) { var segmented = (ContextSpecKeyed) contextSpec; IDictionary<string, EventType> asNames = new Dictionary<string, EventType>(); var partitionHasNameAssignment = false; Type[] getterTypes = null; foreach (var partition in segmented.Items) { Pair<FilterSpecCompiled, IList<StmtClassForgeableFactory>> pair = CompilePartitionedFilterSpec( partition.FilterSpecRaw, eventTypesReferenced, validationEnv); FilterSpecCompiled filterSpecCompiled = pair.First; additionalForgeables.AddAll(pair.Second); partition.FilterSpecCompiled = filterSpecCompiled; var getters = new EventPropertyGetterSPI[partition.PropertyNames.Count]; var serdes = new DataInputOutputSerdeForge[partition.PropertyNames.Count]; var eventType = (EventTypeSPI) filterSpecCompiled.FilterForEventType; getterTypes = new Type[partition.PropertyNames.Count]; for (var i = 0; i < partition.PropertyNames.Count; i++) { var propertyName = partition.PropertyNames[i]; var getter = eventType.GetGetterSPI(propertyName); if (getter == null) { throw new ExprValidationException( "For context '" + validationEnv.ContextName + "' property name '" + propertyName + "' not found on type " + eventType.Name); } getters[i] = getter; getterTypes[i] = eventType.GetPropertyType(propertyName); serdes[i] = validationEnv.Services.SerdeResolver.SerdeForFilter( getterTypes[i], validationEnv.StatementRawInfo); } partition.Getters = getters; partition.LookupableSerdes = serdes; if (partition.AliasName != null) { partitionHasNameAssignment = true; ValidateAsName(asNames, partition.AliasName, filterSpecCompiled.FilterForEventType); } } // plan multi-key, make sure we use the same multikey for all items MultiKeyPlan multiKeyPlan = MultiKeyPlanner.PlanMultiKey( getterTypes, false, @base.StatementRawInfo, validationEnv.Services.SerdeResolver); additionalForgeables.AddAll(multiKeyPlan.MultiKeyForgeables); foreach (ContextSpecKeyedItem partition in segmented.Items) { partition.KeyMultiKey = multiKeyPlan.ClassRef; } segmented.MultiKeyClassRef = multiKeyPlan.ClassRef; if (segmented.OptionalInit != null) { asNames.Clear(); foreach (var initCondition in segmented.OptionalInit) { ContextDetailMatchPair pair = ValidateRewriteContextCondition( true, nestingLevel, initCondition, eventTypesReferenced, new MatchEventSpec(), new EmptySet<string>(), validationEnv); additionalForgeables.AddAll(pair.AdditionalForgeables); var filterForType = initCondition.FilterSpecCompiled.FilterForEventType; var found = false; foreach (var partition in segmented.Items) { if (partition.FilterSpecCompiled.FilterForEventType == filterForType) { found = true; break; } } if (!found) { throw new ExprValidationException( "Segmented context '" + validationEnv.ContextName + "' requires that all of the event types that are listed in the initialized-by also appear in the partition-by, type '" + filterForType.Name + "' is not one of the types listed in partition-by"); } if (initCondition.OptionalFilterAsName != null) { if (partitionHasNameAssignment) { throw new ExprValidationException( "Segmented context '" + validationEnv.ContextName + "' requires that either partition-by or initialized-by assign stream names, but not both"); } ValidateAsName(asNames, initCondition.OptionalFilterAsName, filterForType); } } } if (segmented.OptionalTermination != null) { var matchEventSpec = new MatchEventSpec(); var allTags = new LinkedHashSet<string>(); foreach (var partition in segmented.Items) { if (partition.AliasName != null) { allTags.Add(partition.AliasName); var eventType = partition.FilterSpecCompiled.FilterForEventType; matchEventSpec.TaggedEventTypes[partition.AliasName] = new Pair<EventType,string>( eventType, partition.FilterSpecRaw.EventTypeName); var serdeForgeables = SerdeEventTypeUtility.Plan( eventType, validationEnv.StatementRawInfo, validationEnv.Services.SerdeEventTypeRegistry, validationEnv.Services.SerdeResolver); additionalForgeables.AddAll(serdeForgeables); } } if (segmented.OptionalInit != null) { foreach (var initCondition in segmented.OptionalInit) { if (initCondition.OptionalFilterAsName != null) { allTags.Add(initCondition.OptionalFilterAsName); matchEventSpec.TaggedEventTypes.Put( initCondition.OptionalFilterAsName, new Pair<EventType, string>( initCondition.FilterSpecCompiled.FilterForEventType, initCondition.FilterSpecRaw.EventTypeName)); } } } var endCondition = ValidateRewriteContextCondition( false, nestingLevel, segmented.OptionalTermination, eventTypesReferenced, matchEventSpec, allTags, validationEnv); additionalForgeables.AddAll(endCondition.AdditionalForgeables); segmented.OptionalTermination = endCondition.Condition; } } else if (contextSpec is ContextSpecCategory) { // compile filter var category = (ContextSpecCategory) contextSpec; ValidateNotTable(category.FilterSpecRaw.EventTypeName, validationEnv.Services); var raw = new FilterStreamSpecRaw( category.FilterSpecRaw, ViewSpec.EMPTY_VIEWSPEC_ARRAY, null, StreamSpecOptions.DEFAULT); var compiledDesc = StreamSpecCompiler.CompileFilter( raw, false, false, true, false, null, validationEnv.StatementRawInfo, validationEnv.Services); var result = (FilterStreamSpecCompiled) compiledDesc.StreamSpecCompiled; additionalForgeables.AddAll(compiledDesc.AdditionalForgeables); category.FilterSpecCompiled = result.FilterSpecCompiled; validationEnv.FilterSpecCompileds.Add(result.FilterSpecCompiled); // compile expressions foreach (var item in category.Items) { ValidateNotTable(category.FilterSpecRaw.EventTypeName, validationEnv.Services); var filterSpecRaw = new FilterSpecRaw( category.FilterSpecRaw.EventTypeName, Collections.SingletonList(item.Expression), null); var rawExpr = new FilterStreamSpecRaw( filterSpecRaw, ViewSpec.EMPTY_VIEWSPEC_ARRAY, null, StreamSpecOptions.DEFAULT); var compiledDescItems = StreamSpecCompiler.CompileFilter( rawExpr, false, false, true, false, null, validationEnv.StatementRawInfo, validationEnv.Services); var compiled = (FilterStreamSpecCompiled) compiledDescItems.StreamSpecCompiled; additionalForgeables.AddAll(compiledDescItems.AdditionalForgeables); compiled.FilterSpecCompiled.TraverseFilterBooleanExpr( node => validationEnv.FilterBooleanExpressions.Add(node)); item.FilterPlan = compiled.FilterSpecCompiled.Parameters; } } else if (contextSpec is ContextSpecHash) { var hashed = (ContextSpecHash) contextSpec; foreach (var hashItem in hashed.Items) { var raw = new FilterStreamSpecRaw( hashItem.FilterSpecRaw, ViewSpec.EMPTY_VIEWSPEC_ARRAY, null, StreamSpecOptions.DEFAULT); ValidateNotTable(hashItem.FilterSpecRaw.EventTypeName, validationEnv.Services); var compiledDesc = StreamSpecCompiler.Compile( raw, eventTypesReferenced, false, false, true, false, null, 0, validationEnv.StatementRawInfo, validationEnv.Services); additionalForgeables.AddAll(compiledDesc.AdditionalForgeables); var result = (FilterStreamSpecCompiled) compiledDesc.StreamSpecCompiled; validationEnv.FilterSpecCompileds.Add(result.FilterSpecCompiled); hashItem.FilterSpecCompiled = result.FilterSpecCompiled; // validate parameters var streamTypes = new StreamTypeServiceImpl( result.FilterSpecCompiled.FilterForEventType, null, true); var validationContext = new ExprValidationContextBuilder( streamTypes, validationEnv.StatementRawInfo, validationEnv.Services) .WithIsFilterExpression(true) .Build(); ExprNodeUtilityValidate.Validate( ExprNodeOrigin.CONTEXT, Collections.SingletonList(hashItem.Function), validationContext); } } else if (contextSpec is ContextSpecInitiatedTerminated) { var def = (ContextSpecInitiatedTerminated) contextSpec; var startCondition = ValidateRewriteContextCondition( true, nestingLevel, def.StartCondition, eventTypesReferenced, new MatchEventSpec(), new LinkedHashSet<string>(), validationEnv); additionalForgeables.AddAll(startCondition.AdditionalForgeables); var endCondition = ValidateRewriteContextCondition( false, nestingLevel, def.EndCondition, eventTypesReferenced, startCondition.Matches, startCondition.AllTags, validationEnv); additionalForgeables.AddAll(endCondition.AdditionalForgeables); def.StartCondition = startCondition.Condition; def.EndCondition = endCondition.Condition; if (def.DistinctExpressions != null) { if (!(startCondition.Condition is ContextSpecConditionFilter)) { throw new ExprValidationException( "Distinct-expressions require a stream as the initiated-by condition"); } var distinctExpressions = def.DistinctExpressions; if (distinctExpressions.Length == 0) { throw new ExprValidationException("Distinct-expressions have not been provided"); } var filter = (ContextSpecConditionFilter) startCondition.Condition; if (filter.OptionalFilterAsName == null) { throw new ExprValidationException( "Distinct-expressions require that a stream name is assigned to the stream using 'as'"); } var types = new StreamTypeServiceImpl( filter.FilterSpecCompiled.FilterForEventType, filter.OptionalFilterAsName, true); var validationContext = new ExprValidationContextBuilder(types, validationEnv.StatementRawInfo, validationEnv.Services) .WithAllowBindingConsumption(true) .Build(); for (var i = 0; i < distinctExpressions.Length; i++) { ExprNodeUtilityValidate.ValidatePlainExpression( ExprNodeOrigin.CONTEXTDISTINCT, distinctExpressions[i]); distinctExpressions[i] = ExprNodeUtilityValidate.GetValidatedSubtree( ExprNodeOrigin.CONTEXTDISTINCT, distinctExpressions[i], validationContext); } var multiKeyPlan = MultiKeyPlanner.PlanMultiKey( distinctExpressions, false, @base.StatementRawInfo, validationEnv.Services.SerdeResolver); def.DistinctMultiKey = multiKeyPlan.ClassRef; additionalForgeables.AddAll(multiKeyPlan.MultiKeyForgeables); } } else if (contextSpec is ContextNested) { var nested = (ContextNested) contextSpec; var level = 0; ISet<string> namesUsed = new HashSet<string>(); namesUsed.Add(validationEnv.ContextName); foreach (var nestedContext in nested.Contexts) { if (namesUsed.Contains(nestedContext.ContextName)) { throw new ExprValidationException( "Context by name '" + nestedContext.ContextName + "' has already been declared within nested context '" + validationEnv.ContextName + "'"); } namesUsed.Add(nestedContext.ContextName); var forgeables = ValidateContextDetail(nestedContext.ContextDetail, level, validationEnv); additionalForgeables.AddAll(forgeables); level++; } } else { throw new IllegalStateException("Unrecognized context detail " + contextSpec); } return additionalForgeables; }
public override ExprNode Validate(ExprValidationContext validationContext) { ExprNodeUtilityValidate.Validate(ExprNodeOrigin.PLUGINSINGLEROWPARAM, ChainSpec, validationContext); // get first chain item IList<ExprChainedSpec> chainList = new List<ExprChainedSpec>(ChainSpec); var firstItem = chainList.DeleteAt(0); // Get the types of the parameters for the first invocation var allowWildcard = validationContext.StreamTypeService.EventTypes.Length == 1; EventType streamZeroType = null; if (validationContext.StreamTypeService.EventTypes.Length > 0) { streamZeroType = validationContext.StreamTypeService.EventTypes[0]; } var staticMethodDesc = ExprNodeUtilityResolve.ResolveMethodAllowWildcardAndStream( clazz.FullName, null, firstItem.Name, firstItem.Parameters, allowWildcard, streamZeroType, new ExprNodeUtilResolveExceptionHandlerDefault(firstItem.Name, true), FunctionName, validationContext.StatementRawInfo, validationContext.StatementCompileTimeService); var allowValueCache = true; bool isReturnsConstantResult; switch (config.ValueCache) { case ConfigurationCompilerPlugInSingleRowFunction.ValueCacheEnum.DISABLED: isReturnsConstantResult = false; allowValueCache = false; break; case ConfigurationCompilerPlugInSingleRowFunction.ValueCacheEnum.CONFIGURED: { var isUDFCache = validationContext.StatementCompileTimeService.Configuration.Compiler.Expression .IsUdfCache; isReturnsConstantResult = isUDFCache && staticMethodDesc.IsAllConstants && chainList.IsEmpty(); allowValueCache = isUDFCache; break; } case ConfigurationCompilerPlugInSingleRowFunction.ValueCacheEnum.ENABLED: isReturnsConstantResult = staticMethodDesc.IsAllConstants && chainList.IsEmpty(); break; default: throw new IllegalStateException("Invalid value cache code " + config.ValueCache); } // this may return a pair of null if there is no lambda or the result cannot be wrapped for lambda-function use ExprDotStaticMethodWrap optionalLambdaWrap = ExprDotStaticMethodWrapFactory.Make( staticMethodDesc.ReflectionMethod, chainList, config.OptionalEventTypeName, validationContext); var typeInfo = optionalLambdaWrap != null ? optionalLambdaWrap.TypeInfo : EPTypeHelper.SingleValue(staticMethodDesc.ReflectionMethod.ReturnType); var eval = ExprDotNodeUtility.GetChainEvaluators( -1, typeInfo, chainList, validationContext, false, new ExprDotNodeFilterAnalyzerInputStatic()) .ChainWithUnpack; var staticMethodForge = new ExprDotNodeForgeStaticMethod( this, isReturnsConstantResult, clazz.Name, staticMethodDesc.ReflectionMethod, staticMethodDesc.ChildForges, allowValueCache && staticMethodDesc.IsAllConstants, eval, optionalLambdaWrap, config.IsRethrowExceptions, null, validationContext.StatementName); // If caching the result, evaluate now and return the result. if (isReturnsConstantResult) { forge = new ExprPlugInSingleRowNodeForgeConst(this, staticMethodForge); } else { forge = new ExprPlugInSingleRowNodeForgeNC(this, staticMethodForge); } return null; }
public override ExprNode Validate(ExprValidationContext validationContext) { // check for plannable methods: these are validated according to different rules var appDotMethod = GetAppDotMethod(validationContext.IsFilterExpression); if (appDotMethod != null) { return appDotMethod; } // validate all parameters ExprNodeUtilityValidate.Validate(ExprNodeOrigin.DOTNODEPARAMETER, ChainSpec, validationContext); // determine if there are enumeration method expressions in the chain var hasEnumerationMethod = false; foreach (var chain in ChainSpec) { if (EnumMethodEnumExtensions.IsEnumerationMethod(chain.Name)) { hasEnumerationMethod = true; break; } } // determine if there is an implied binding, replace first chain element with evaluation node if there is if (validationContext.StreamTypeService.HasTableTypes && validationContext.TableCompileTimeResolver != null && ChainSpec.Count > 1 && ChainSpec[0].IsProperty) { var tableNode = TableCompileTimeUtil.GetTableNodeChainable( validationContext.StreamTypeService, ChainSpec, validationContext.ImportService, validationContext.TableCompileTimeResolver); if (tableNode != null) { var node = ExprNodeUtilityValidate.GetValidatedSubtree( ExprNodeOrigin.DOTNODE, tableNode.First, validationContext); if (tableNode.Second.IsEmpty()) { return node; } ChainSpec.Clear(); ChainSpec.AddAll(tableNode.Second); AddChildNode(node); } } // The root node expression may provide the input value: // Such as "window(*).doIt(...)" or "(select * from Window).doIt()" or "prevwindow(sb).doIt(...)", in which case the expression to act on is a child expression // var streamTypeService = validationContext.StreamTypeService; if (ChildNodes.Length != 0) { // the root expression is the first child node var rootNode = ChildNodes[0]; // the root expression may also provide a lambda-function input (Iterator<EventBean>) // Determine collection-type and evaluator if any for root node var enumSrc = ExprDotNodeUtility.GetEnumerationSource( rootNode, validationContext.StreamTypeService, hasEnumerationMethod, validationContext.IsDisablePropertyExpressionEventCollCache, validationContext.StatementRawInfo, validationContext.StatementCompileTimeService); EPType typeInfoX; if (enumSrc.ReturnType == null) { typeInfoX = EPTypeHelper.SingleValue( rootNode.Forge.EvaluationType); // not a collection type, treat as scalar } else { typeInfoX = enumSrc.ReturnType; } var evalsX = ExprDotNodeUtility.GetChainEvaluators( enumSrc.StreamOfProviderIfApplicable, typeInfoX, ChainSpec, validationContext, isDuckTyping, new ExprDotNodeFilterAnalyzerInputExpr()); forge = new ExprDotNodeForgeRootChild( this, null, null, null, hasEnumerationMethod, rootNode.Forge, enumSrc.Enumeration, typeInfoX, evalsX.Chain, evalsX.ChainWithUnpack, false); return null; } // No root node, and this is a 1-element chain i.e. "something(param,...)". // Plug-in single-row methods are not handled here. // Plug-in aggregation methods are not handled here. if (ChainSpec.Count == 1) { var spec = ChainSpec[0]; if (spec.Parameters.IsEmpty()) { throw HandleNotFound(spec.Name); } // single-parameter can resolve to a property Pair<PropertyResolutionDescriptor, string> propertyInfoPairX = null; try { propertyInfoPairX = ExprIdentNodeUtil.GetTypeFromStream( streamTypeService, spec.Name, streamTypeService.HasPropertyAgnosticType, false, validationContext.TableCompileTimeResolver); } catch (ExprValidationPropertyException) { // fine } // if not a property then try built-in single-row non-grammar functions if (propertyInfoPairX == null && spec.Name.ToLowerInvariant() .Equals(ImportServiceCompileTime.EXT_SINGLEROW_FUNCTION_TRANSPOSE)) { if (spec.Parameters.Count != 1) { throw new ExprValidationException( "The " + ImportServiceCompileTime.EXT_SINGLEROW_FUNCTION_TRANSPOSE + " function requires a single parameter expression"); } forge = new ExprDotNodeForgeTransposeAsStream(this, ChainSpec[0].Parameters[0].Forge); } else if (spec.Parameters.Count != 1) { throw HandleNotFound(spec.Name); } else { if (propertyInfoPairX == null) { throw new ExprValidationException( "Unknown single-row function, aggregation function or mapped or indexed property named '" + spec.Name + "' could not be resolved"); } forge = GetPropertyPairEvaluator(spec.Parameters[0].Forge, propertyInfoPairX, validationContext); } return null; } // handle the case where the first chain spec element is a stream name. ExprValidationException prefixedStreamNumException = null; var prefixedStreamNumber = PrefixedStreamName(ChainSpec, validationContext.StreamTypeService); if (prefixedStreamNumber != -1) { var specAfterStreamName = ChainSpec[1]; // Attempt to resolve as property Pair<PropertyResolutionDescriptor, string> propertyInfoPairX = null; try { var propName = ChainSpec[0].Name + "." + specAfterStreamName.Name; propertyInfoPairX = ExprIdentNodeUtil.GetTypeFromStream( streamTypeService, propName, streamTypeService.HasPropertyAgnosticType, false, validationContext.TableCompileTimeResolver); } catch (ExprValidationPropertyException) { // fine } if (propertyInfoPairX != null) { if (specAfterStreamName.Parameters.Count != 1) { throw HandleNotFound(specAfterStreamName.Name); } forge = GetPropertyPairEvaluator( specAfterStreamName.Parameters[0].Forge, propertyInfoPairX, validationContext); return null; } // Attempt to resolve as event-underlying object instance method var eventType = validationContext.StreamTypeService.EventTypes[prefixedStreamNumber]; var type = eventType.UnderlyingType; IList<ExprChainedSpec> remainderChain = new List<ExprChainedSpec>(ChainSpec); remainderChain.RemoveAt(0); ExprValidationException methodEx = null; ExprDotForge[] underlyingMethodChain = null; try { var typeInfoX = EPTypeHelper.SingleValue(type); if (validationContext.TableCompileTimeResolver.ResolveTableFromEventType(eventType) != null) { typeInfoX = new ClassEPType(typeof(object[])); } underlyingMethodChain = ExprDotNodeUtility.GetChainEvaluators( prefixedStreamNumber, typeInfoX, remainderChain, validationContext, false, new ExprDotNodeFilterAnalyzerInputStream(prefixedStreamNumber)) .ChainWithUnpack; } catch (ExprValidationException ex) { methodEx = ex; // expected - may not be able to find the methods on the underlying } ExprDotForge[] eventTypeMethodChain = null; ExprValidationException enumDatetimeEx = null; FilterExprAnalyzerAffector filterExprAnalyzerAffector = null; try { var typeInfoX = EPTypeHelper.SingleEvent(eventType); var chain = ExprDotNodeUtility.GetChainEvaluators( prefixedStreamNumber, typeInfoX, remainderChain, validationContext, false, new ExprDotNodeFilterAnalyzerInputStream(prefixedStreamNumber)); eventTypeMethodChain = chain.ChainWithUnpack; filterExprAnalyzerAffector = chain.FilterAnalyzerDesc; } catch (ExprValidationException ex) { enumDatetimeEx = ex; // expected - may not be able to find the methods on the underlying } if (underlyingMethodChain != null) { forge = new ExprDotNodeForgeStream( this, filterExprAnalyzerAffector, prefixedStreamNumber, eventType, underlyingMethodChain, true); } else if (eventTypeMethodChain != null) { forge = new ExprDotNodeForgeStream( this, filterExprAnalyzerAffector, prefixedStreamNumber, eventType, eventTypeMethodChain, false); } if (forge != null) { return null; } if (ExprDotNodeUtility.IsDatetimeOrEnumMethod(remainderChain[0].Name)) { prefixedStreamNumException = enumDatetimeEx; } else { prefixedStreamNumException = new ExprValidationException( "Failed to solve '" + remainderChain[0].Name + "' to either an date-time or enumeration method, an event property or a method on the event underlying object: " + methodEx.Message, methodEx); } } // There no root node, in this case the classname or property name is provided as part of the chain. // Such as "MyClass.myStaticLib(...)" or "mycollectionproperty.doIt(...)" // IList<ExprChainedSpec> modifiedChain = new List<ExprChainedSpec>(ChainSpec); var firstItem = modifiedChain.DeleteAt(0); Pair<PropertyResolutionDescriptor, string> propertyInfoPair = null; try { propertyInfoPair = ExprIdentNodeUtil.GetTypeFromStream( streamTypeService, firstItem.Name, streamTypeService.HasPropertyAgnosticType, true, validationContext.TableCompileTimeResolver); } catch (ExprValidationPropertyException) { // not a property } // If property then treat it as such if (propertyInfoPair != null) { var propertyName = propertyInfoPair.First.PropertyName; var streamId = propertyInfoPair.First.StreamNum; var streamType = streamTypeService.EventTypes[streamId]; EPType typeInfoX; ExprEnumerationForge enumerationForge = null; EPType inputType; ExprForge rootNodeForge = null; EventPropertyGetterSPI getter; if (firstItem.Parameters.IsEmpty()) { getter = ((EventTypeSPI) streamType).GetGetterSPI(propertyInfoPair.First.PropertyName); var propertyEval = ExprDotNodeUtility.GetPropertyEnumerationSource( propertyInfoPair.First.PropertyName, streamId, streamType, hasEnumerationMethod, validationContext.IsDisablePropertyExpressionEventCollCache); typeInfoX = propertyEval.ReturnType; enumerationForge = propertyEval.Enumeration; inputType = propertyEval.ReturnType; rootNodeForge = new PropertyDotNonLambdaForge( streamId, getter, propertyInfoPair.First.PropertyType.GetBoxedType()); } else { // property with parameter - mapped or indexed property var desc = EventTypeUtility.GetNestablePropertyDescriptor( streamTypeService.EventTypes[propertyInfoPair.First.StreamNum], firstItem.Name); if (firstItem.Parameters.Count > 1) { throw new ExprValidationException( "Property '" + firstItem.Name + "' may not be accessed passing 2 or more parameters"); } var paramEval = firstItem.Parameters[0].Forge; typeInfoX = EPTypeHelper.SingleValue(desc.PropertyComponentType); inputType = typeInfoX; getter = null; if (desc.IsMapped) { if (paramEval.EvaluationType != typeof(string)) { throw new ExprValidationException( "Parameter expression to mapped property '" + propertyName + "' is expected to return a string-type value but returns " + paramEval.EvaluationType.CleanName()); } var mappedGetter = ((EventTypeSPI) propertyInfoPair.First.StreamEventType).GetGetterMappedSPI( propertyInfoPair.First.PropertyName); if (mappedGetter == null) { throw new ExprValidationException( "Mapped property named '" + propertyName + "' failed to obtain getter-object"); } rootNodeForge = new PropertyDotNonLambdaMappedForge( streamId, mappedGetter, paramEval, desc.PropertyComponentType); } if (desc.IsIndexed) { if (paramEval.EvaluationType.GetBoxedType() != typeof(int?)) { throw new ExprValidationException( "Parameter expression to mapped property '" + propertyName + "' is expected to return a Integer-type value but returns " + paramEval.EvaluationType.CleanName()); } var indexedGetter = ((EventTypeSPI) propertyInfoPair.First.StreamEventType).GetGetterIndexedSPI( propertyInfoPair.First.PropertyName); if (indexedGetter == null) { throw new ExprValidationException( "Mapped property named '" + propertyName + "' failed to obtain getter-object"); } rootNodeForge = new PropertyDotNonLambdaIndexedForge( streamId, indexedGetter, paramEval, desc.PropertyComponentType); } } if (typeInfoX == null) { throw new ExprValidationException( "Property '" + propertyName + "' is not a mapped or indexed property"); } // try to build chain based on the input (non-fragment) ExprDotNodeRealizedChain evalsX; var filterAnalyzerInputProp = new ExprDotNodeFilterAnalyzerInputProp( propertyInfoPair.First.StreamNum, propertyInfoPair.First.PropertyName); var rootIsEventBean = false; try { evalsX = ExprDotNodeUtility.GetChainEvaluators( streamId, inputType, modifiedChain, validationContext, isDuckTyping, filterAnalyzerInputProp); } catch (ExprValidationException) { // try building the chain based on the fragment event type (i.e. A.after(B) based on A-configured start time where A is a fragment) var fragment = propertyInfoPair.First.FragmentEventType; if (fragment == null) { throw; } EPType fragmentTypeInfo; if (fragment.IsIndexed) { fragmentTypeInfo = EPTypeHelper.CollectionOfEvents(fragment.FragmentType); } else { fragmentTypeInfo = EPTypeHelper.SingleEvent(fragment.FragmentType); } rootIsEventBean = true; evalsX = ExprDotNodeUtility.GetChainEvaluators( propertyInfoPair.First.StreamNum, fragmentTypeInfo, modifiedChain, validationContext, isDuckTyping, filterAnalyzerInputProp); rootNodeForge = new PropertyDotNonLambdaFragmentForge(streamId, getter); } var filterExprAnalyzerAffector = evalsX.FilterAnalyzerDesc; var streamNumReferenced = propertyInfoPair.First.StreamNum; var rootPropertyName = propertyInfoPair.First.PropertyName; forge = new ExprDotNodeForgeRootChild( this, filterExprAnalyzerAffector, streamNumReferenced, rootPropertyName, hasEnumerationMethod, rootNodeForge, enumerationForge, inputType, evalsX.Chain, evalsX.ChainWithUnpack, !rootIsEventBean); return null; } // If variable then resolve as such var variable = validationContext.VariableCompileTimeResolver.Resolve(firstItem.Name); if (variable != null) { if (variable.OptionalContextName != null) { throw new ExprValidationException( "Method invocation on context-specific variable is not supported"); } EPType typeInfoX; ExprDotStaticMethodWrap wrap; if (variable.Type.IsArray) { typeInfoX = EPTypeHelper.CollectionOfSingleValue( variable.Type.GetElementType(), variable.Type); wrap = new ExprDotStaticMethodWrapArrayScalar(variable.VariableName, variable.Type); } else if (variable.EventType != null) { typeInfoX = EPTypeHelper.SingleEvent(variable.EventType); wrap = null; } else { typeInfoX = EPTypeHelper.SingleValue(variable.Type); wrap = null; } var evalsX = ExprDotNodeUtility.GetChainEvaluators( null, typeInfoX, modifiedChain, validationContext, false, new ExprDotNodeFilterAnalyzerInputStatic()); forge = new ExprDotNodeForgeVariable(this, variable, wrap, evalsX.ChainWithUnpack); return null; } // try resolve as enumeration class with value var enumconstant = ImportCompileTimeUtil.ResolveIdentAsEnumConst( firstItem.Name, validationContext.ImportService, false); if (enumconstant != null) { // try resolve method var methodSpec = modifiedChain[0]; var enumvalue = firstItem.Name; ExprNodeUtilResolveExceptionHandler handler = new ProxyExprNodeUtilResolveExceptionHandler { ProcHandle = ex => { return new ExprValidationException( "Failed to resolve method '" + methodSpec.Name + "' on enumeration value '" + enumvalue + "': " + ex.Message); } }; var wildcardType = validationContext.StreamTypeService.EventTypes.Length != 1 ? null : validationContext.StreamTypeService.EventTypes[0]; var methodDesc = ExprNodeUtilityResolve.ResolveMethodAllowWildcardAndStream( enumconstant.GetType().Name, enumconstant.GetType(), methodSpec.Name, methodSpec.Parameters, wildcardType != null, wildcardType, handler, methodSpec.Name, validationContext.StatementRawInfo, validationContext.StatementCompileTimeService); // method resolved, hook up modifiedChain.RemoveAt(0); // we identified this piece var optionalLambdaWrapX = ExprDotStaticMethodWrapFactory.Make( methodDesc.ReflectionMethod, modifiedChain, null, validationContext); var typeInfoX = optionalLambdaWrapX != null ? optionalLambdaWrapX.TypeInfo : EPTypeHelper.SingleValue(methodDesc.ReflectionMethod.ReturnType); var evalsX = ExprDotNodeUtility.GetChainEvaluators( null, typeInfoX, modifiedChain, validationContext, false, new ExprDotNodeFilterAnalyzerInputStatic()); forge = new ExprDotNodeForgeStaticMethod( this, false, firstItem.Name, methodDesc.ReflectionMethod, methodDesc.ChildForges, false, evalsX.ChainWithUnpack, optionalLambdaWrapX, false, enumconstant, validationContext.StatementName); return null; } // if prefixed by a stream name, we are giving up if (prefixedStreamNumException != null) { throw prefixedStreamNumException; } // If class then resolve as class var secondItem = modifiedChain.DeleteAt(0); var allowWildcard = validationContext.StreamTypeService.EventTypes.Length == 1; EventType streamZeroType = null; if (validationContext.StreamTypeService.EventTypes.Length > 0) { streamZeroType = validationContext.StreamTypeService.EventTypes[0]; } var method = ExprNodeUtilityResolve.ResolveMethodAllowWildcardAndStream( firstItem.Name, null, secondItem.Name, secondItem.Parameters, allowWildcard, streamZeroType, new ExprNodeUtilResolveExceptionHandlerDefault(firstItem.Name + "." + secondItem.Name, false), secondItem.Name, validationContext.StatementRawInfo, validationContext.StatementCompileTimeService); var isConstantParameters = method.IsAllConstants && isUDFCache; var isReturnsConstantResult = isConstantParameters && modifiedChain.IsEmpty(); // this may return a pair of null if there is no lambda or the result cannot be wrapped for lambda-function use var optionalLambdaWrap = ExprDotStaticMethodWrapFactory.Make( method.ReflectionMethod, modifiedChain, null, validationContext); var typeInfo = optionalLambdaWrap != null ? optionalLambdaWrap.TypeInfo : EPTypeHelper.SingleValue(method.ReflectionMethod.ReturnType); var evals = ExprDotNodeUtility.GetChainEvaluators( null, typeInfo, modifiedChain, validationContext, false, new ExprDotNodeFilterAnalyzerInputStatic()); forge = new ExprDotNodeForgeStaticMethod( this, isReturnsConstantResult, firstItem.Name, method.ReflectionMethod, method.ChildForges, isConstantParameters, evals.ChainWithUnpack, optionalLambdaWrap, false, null, validationContext.StatementName); return null; }