public static bool IsDatetimeOrEnumMethod( string name, ImportServiceCompileTime importService) { return(EnumMethodResolver.IsEnumerationMethod(name, importService) || DatetimeMethodResolver.IsDateTimeMethod(name, importService)); }
public static ExprNodeUtilMethodDesc ResolveMethodAllowWildcardAndStream( string className, Type optionalClass, string methodName, IList<ExprNode> parameters, bool allowWildcard, EventType wildcardType, ExprNodeUtilResolveExceptionHandler exceptionHandler, string functionName, StatementRawInfo statementRawInfo, StatementCompileTimeServices services) { var paramTypes = new Type[parameters.Count]; var childForges = new ExprForge[parameters.Count]; var count = 0; var allowEventBeanType = new bool[parameters.Count]; var allowEventBeanCollType = new bool[parameters.Count]; var childEvalsEventBeanReturnTypesForges = new ExprForge[parameters.Count]; var allConstants = true; foreach (var childNode in parameters) { if (!EnumMethodResolver.IsEnumerationMethod(methodName, services.ImportServiceCompileTime) && childNode is ExprLambdaGoesNode) { throw new ExprValidationException( "Unrecognized lambda-expression encountered as parameter to UDF or static method '" + methodName + "'"); } if (childNode is ExprWildcard) { if (wildcardType == null || !allowWildcard) { throw new ExprValidationException("Failed to resolve wildcard parameter to a given event type"); } childForges[count] = new ExprEvalStreamNumUnd(0, wildcardType.UnderlyingType); childEvalsEventBeanReturnTypesForges[count] = new ExprEvalStreamNumEvent(0); paramTypes[count] = wildcardType.UnderlyingType; allowEventBeanType[count] = true; allConstants = false; count++; continue; } if (childNode is ExprStreamUnderlyingNode) { var und = (ExprStreamUnderlyingNode) childNode; var tableMetadata = services.TableCompileTimeResolver.ResolveTableFromEventType(und.EventType); if (tableMetadata == null) { childForges[count] = childNode.Forge; childEvalsEventBeanReturnTypesForges[count] = new ExprEvalStreamNumEvent(und.StreamId); } else { childForges[count] = new ExprEvalStreamTable( und.StreamId, und.EventType.UnderlyingType, tableMetadata); childEvalsEventBeanReturnTypesForges[count] = new ExprEvalStreamNumEventTable(und.StreamId, tableMetadata); } paramTypes[count] = childForges[count].EvaluationType; allowEventBeanType[count] = true; allConstants = false; count++; continue; } if (childNode.Forge is ExprEnumerationForge) { var enumeration = (ExprEnumerationForge) childNode.Forge; var eventType = enumeration.GetEventTypeSingle(statementRawInfo, services); childForges[count] = childNode.Forge; paramTypes[count] = childForges[count].EvaluationType; allConstants = false; if (eventType != null) { childEvalsEventBeanReturnTypesForges[count] = new ExprEvalStreamNumEnumSingleForge(enumeration); allowEventBeanType[count] = true; count++; continue; } var eventTypeColl = enumeration.GetEventTypeCollection(statementRawInfo, services); if (eventTypeColl != null) { childEvalsEventBeanReturnTypesForges[count] = new ExprEvalStreamNumEnumCollForge(enumeration); allowEventBeanCollType[count] = true; count++; continue; } } paramTypes[count] = childNode.Forge.EvaluationType; childForges[count] = childNode.Forge; count++; if (!childNode.Forge.ForgeConstantType.IsCompileTimeConstant) { allConstants = false; } } // Try to resolve the method MethodInfo method; try { if (optionalClass != null) { method = services.ImportServiceCompileTime.ResolveMethod( optionalClass, methodName, paramTypes, allowEventBeanType); } else { method = services.ImportServiceCompileTime.ResolveMethodOverloadChecked( className, methodName, paramTypes, allowEventBeanType, allowEventBeanCollType, services.ClassProvidedExtension); } } catch (Exception e) { throw exceptionHandler.Handle(e); } var parameterTypes = method.GetParameterTypes(); // rewrite those evaluator that should return the event itself if (CollectionUtil.IsAnySet(allowEventBeanType)) { for (var i = 0; i < parameters.Count; i++) { if (allowEventBeanType[i] && parameterTypes[i] == typeof(EventBean)) { childForges[i] = childEvalsEventBeanReturnTypesForges[i]; } } } // rewrite those evaluators that should return the event collection if (CollectionUtil.IsAnySet(allowEventBeanCollType)) { for (var i = 0; i < parameters.Count; i++) { if (allowEventBeanCollType[i] && (parameterTypes[i] == typeof(ICollection<EventBean>))) { childForges[i] = childEvalsEventBeanReturnTypesForges[i]; } } } // add an evaluator if the method expects a context object if (!method.IsVarArgs() && parameterTypes.Length > 0 && parameterTypes[parameterTypes.Length - 1] == typeof(EPLMethodInvocationContext)) { var node = new ExprEvalMethodContext(functionName); childForges = (ExprForge[]) CollectionUtil.ArrayExpandAddSingle(childForges, node); } // handle varargs if (method.IsVarArgs()) { // handle context parameter var numMethodParams = parameterTypes.Length; if (numMethodParams > 1 && parameterTypes[numMethodParams - 2] == typeof(EPLMethodInvocationContext)) { var rewrittenForges = new ExprForge[childForges.Length + 1]; Array.Copy(childForges, 0, rewrittenForges, 0, numMethodParams - 2); rewrittenForges[numMethodParams - 2] = new ExprEvalMethodContext(functionName); Array.Copy( childForges, numMethodParams - 2, rewrittenForges, numMethodParams - 1, childForges.Length - (numMethodParams - 2)); childForges = rewrittenForges; } childForges = ExprNodeUtilityMake.MakeVarargArrayForges(method, childForges); } var localInlinedClass = services.ClassProvidedExtension.IsLocalInlinedClass(method.DeclaringType); return new ExprNodeUtilMethodDesc(allConstants, childForges, method, localInlinedClass); }
public static ExprDotNodeRealizedChain GetChainEvaluators( int?streamOfProviderIfApplicable, EPType inputType, IList <Chainable> chainSpec, ExprValidationContext validationContext, bool isDuckTyping, ExprDotNodeFilterAnalyzerInput inputDesc) { var methodForges = new List <ExprDotForge>(); var currentInputType = inputType; EnumMethodDesc lastLambdaFunc = null; var lastElement = chainSpec.IsEmpty() ? null : chainSpec[chainSpec.Count - 1]; FilterExprAnalyzerAffector filterAnalyzerDesc = null; Deque <Chainable> chainSpecStack = new ArrayDeque <Chainable>(chainSpec); while (!chainSpecStack.IsEmpty()) { var chainElement = chainSpecStack.RemoveFirst(); var parameters = chainElement.GetParametersOrEmpty(); var chainElementName = chainElement.GetRootNameOrEmptyString(); var last = chainSpecStack.IsEmpty(); lastLambdaFunc = null; // reset // compile parameters for chain element var paramForges = new ExprForge[parameters.Count]; var paramTypes = new Type[parameters.Count]; for (var i = 0; i < parameters.Count; i++) { paramForges[i] = parameters[i].Forge; paramTypes[i] = paramForges[i].EvaluationType; } // check if special 'size' method if (currentInputType is ClassMultiValuedEPType) { var type = (ClassMultiValuedEPType)currentInputType; if (string.Equals(chainElementName, "size", StringComparison.InvariantCultureIgnoreCase) && paramTypes.Length == 0 && lastElement == chainElement) { ExprDotForge size; var containerType = ((ClassMultiValuedEPType)currentInputType).Container; if (containerType.IsArray) { size = new ExprDotForgeSizeArray(); } else { size = new ExprDotForgeSizeCollection(); } methodForges.Add(size); currentInputType = size.TypeInfo; continue; } if (string.Equals(chainElementName, "get", StringComparison.InvariantCultureIgnoreCase) && paramTypes.Length == 1 && paramTypes[0].GetBoxedType() == typeof(int?)) { ExprDotForge get; var componentType = type.Component.GetBoxedType(); if (type.Container.IsArray) { get = new ExprDotForgeGetArray(paramForges[0], componentType); } else { get = new ExprDotForgeGetCollection(paramForges[0], componentType); } methodForges.Add(get); currentInputType = get.TypeInfo; continue; } if (chainElement is ChainableArray && type.Container.IsArray) { var array = (ChainableArray)chainElement; var typeInfo = currentInputType; var indexExpr = ChainableArray.ValidateSingleIndexExpr( array.Indexes, () => "operation on type " + typeInfo.ToTypeDescriptive()); var componentType = type.Component.GetBoxedType(); var get = new ExprDotForgeGetArray(indexExpr.Forge, componentType); methodForges.Add(get); currentInputType = get.TypeInfo; continue; } } // determine if there is a matching method or property var methodTarget = GetMethodTarget(currentInputType); var matchingMethod = false; if (methodTarget != null && (!(chainElement is ChainableArray))) { try { GetValidateMethodDescriptor(methodTarget, chainElementName, parameters, validationContext); matchingMethod = true; } catch (ExprValidationException) { // expected } } if (EnumMethodResolver.IsEnumerationMethod(chainElementName, validationContext.ImportService) && (!matchingMethod || methodTarget.IsArray || methodTarget.IsGenericCollection())) { var enumerationMethod = EnumMethodResolver.FromName(chainElementName, validationContext.ImportService); if (enumerationMethod == null) { throw new EPException("unable to determine enumeration method from name"); } var eval = enumerationMethod.Factory.Invoke(chainElement.GetParametersOrEmpty().Count); if (currentInputType is ClassEPType classEpType && classEpType.Clazz.IsGenericCollection() && !classEpType.Clazz.IsArray) { currentInputType = EPTypeHelper.CollectionOfSingleValue(typeof(object), null); } eval.Init(streamOfProviderIfApplicable, enumerationMethod, chainElementName, currentInputType, parameters, validationContext); currentInputType = eval.TypeInfo; if (currentInputType == null) { throw new IllegalStateException("Enumeration method '" + chainElementName + "' has not returned type information"); } methodForges.Add(eval); lastLambdaFunc = enumerationMethod; continue; } // resolve datetime if (DatetimeMethodResolver.IsDateTimeMethod(chainElementName, validationContext.ImportService) && (!matchingMethod || methodTarget == typeof(DateTimeEx) || methodTarget == typeof(DateTimeOffset) || methodTarget == typeof(DateTime))) { var datetimeMethod = DatetimeMethodResolver.FromName(chainElementName, validationContext.ImportService); var datetimeImpl = ExprDotDTFactory.ValidateMake( validationContext.StreamTypeService, chainSpecStack, datetimeMethod, chainElementName, currentInputType, parameters, inputDesc, validationContext.ImportService.TimeAbacus, validationContext.TableCompileTimeResolver, validationContext.ImportService, validationContext.StatementRawInfo); currentInputType = datetimeImpl.ReturnType; if (currentInputType == null) { throw new IllegalStateException( "Date-time method '" + chainElementName + "' has not returned type information"); } methodForges.Add(datetimeImpl.Forge); filterAnalyzerDesc = datetimeImpl.IntervalFilterDesc; continue; } // try to resolve as property if the last method returned a type if (currentInputType is EventEPType) { if (chainElement is ChainableArray) { throw new ExprValidationException("Could not perform array operation on type " + currentInputType.ToTypeDescriptive()); } var inputEventType = (EventTypeSPI)((EventEPType)currentInputType).EventType; var type = inputEventType.GetPropertyType(chainElementName); var getter = inputEventType.GetGetterSPI(chainElementName); var fragmentType = inputEventType.GetFragmentType(chainElementName); ExprDotForge forge; if (type != null && getter != null) { if (fragmentType == null || last) { forge = new ExprDotForgeProperty(getter, EPTypeHelper.SingleValue(type.GetBoxedType())); currentInputType = forge.TypeInfo; } else { if (!fragmentType.IsIndexed) { currentInputType = EPTypeHelper.SingleEvent(fragmentType.FragmentType); } else { currentInputType = EPTypeHelper.ArrayOfEvents(fragmentType.FragmentType); } forge = new ExprDotForgePropertyFragment(getter, currentInputType); } methodForges.Add(forge); continue; } } if (currentInputType is EventMultiValuedEPType eventMultiValuedEpType && chainElement is ChainableArray chainableArray) { var inputEventType = (EventTypeSPI)eventMultiValuedEpType.Component; var typeInfo = currentInputType; var indexExpr = ChainableArray.ValidateSingleIndexExpr( chainableArray.Indexes, () => "operation on type " + typeInfo.ToTypeDescriptive()); currentInputType = EPTypeHelper.SingleEvent(inputEventType); var forge = new ExprDotForgeEventArrayAtIndex(currentInputType, indexExpr); methodForges.Add(forge); continue; } // Finally try to resolve the method if (methodTarget != null && !(chainElement is ChainableArray)) { try { // find descriptor again, allow for duck typing var desc = GetValidateMethodDescriptor(methodTarget, chainElementName, parameters, validationContext); paramForges = desc.ChildForges; ExprDotForge forge; if (currentInputType is ClassEPType) { // if followed by an enumeration method, convert array to collection if (desc.ReflectionMethod.ReturnType.IsArray && !chainSpecStack.IsEmpty() && EnumMethodResolver.IsEnumerationMethod(chainSpecStack.First.GetRootNameOrEmptyString(), validationContext.ImportService)) { forge = new ExprDotMethodForgeNoDuck( validationContext.StatementName, desc.ReflectionMethod, paramForges, ExprDotMethodForgeNoDuck.DuckType.WRAPARRAY); } else { forge = new ExprDotMethodForgeNoDuck( validationContext.StatementName, desc.ReflectionMethod, paramForges, ExprDotMethodForgeNoDuck.DuckType.PLAIN); } } else { forge = new ExprDotMethodForgeNoDuck( validationContext.StatementName, desc.ReflectionMethod, paramForges, ExprDotMethodForgeNoDuck.DuckType.UNDERLYING); } methodForges.Add(forge); currentInputType = forge.TypeInfo; } catch (Exception e) { if (!isDuckTyping) { throw new ExprValidationException(e.Message, e); } var duck = new ExprDotMethodForgeDuck( validationContext.StatementName, validationContext.ImportService, chainElementName, paramTypes, paramForges); methodForges.Add(duck); currentInputType = duck.TypeInfo; } continue; } string message; if (!(chainElement is ChainableArray)) { message = "Could not find event property or method named '" + chainElementName + "' in " + currentInputType.ToTypeDescriptive(); } else { message = "Could not perform array operation on type " + currentInputType.ToTypeDescriptive(); } throw new ExprValidationException(message); } var intermediateEvals = methodForges.ToArray(); if (lastLambdaFunc != null) { ExprDotForge finalEval = null; if (currentInputType is EventMultiValuedEPType mvType) { var tableMetadata = validationContext.TableCompileTimeResolver.ResolveTableFromEventType(mvType.Component); if (tableMetadata != null) { finalEval = new ExprDotForgeUnpackCollEventBeanTable(mvType.Component, tableMetadata); } else { finalEval = new ExprDotForgeUnpackCollEventBean(mvType.Component); } } else if (currentInputType is EventEPType epType) { var tableMetadata = validationContext.TableCompileTimeResolver.ResolveTableFromEventType(epType.EventType); if (tableMetadata != null) { finalEval = new ExprDotForgeUnpackBeanTable(epType.EventType, tableMetadata); } else { finalEval = new ExprDotForgeUnpackBean(epType.EventType); } } if (finalEval != null) { methodForges.Add(finalEval); } } var unpackingForges = methodForges.ToArray(); return(new ExprDotNodeRealizedChain(intermediateEvals, unpackingForges, filterAnalyzerDesc)); }