public ExprDotNodeFilterAnalyzerDesc GetFilterDesc(EventType[] typesPerStream, DatetimeMethodEnum currentMethod, ICollection <ExprNode> currentParameters, ExprDotNodeFilterAnalyzerInput inputDesc) { return(null); }
public ExprDotNodeFilterAnalyzerDesc GetFilterDesc(EventType[] typesPerStream, DatetimeMethodEnum currentMethod, ICollection <ExprNode> currentParameters, ExprDotNodeFilterAnalyzerInput inputDesc) { if (_includeLow == null || _includeHigh == null) { return(null); } int targetStreamNum; String targetProperty; if (inputDesc is ExprDotNodeFilterAnalyzerInputStream) { var targetStream = (ExprDotNodeFilterAnalyzerInputStream)inputDesc; targetStreamNum = targetStream.StreamNum; EventType targetType = typesPerStream[targetStreamNum]; targetProperty = targetType.StartTimestampPropertyName; } else if (inputDesc is ExprDotNodeFilterAnalyzerInputProp) { var targetStream = (ExprDotNodeFilterAnalyzerInputProp)inputDesc; targetStreamNum = targetStream.StreamNum; targetProperty = targetStream.PropertyName; } else { return(null); } return(new ExprDotNodeFilterAnalyzerDTBetweenDesc(typesPerStream, targetStreamNum, targetProperty, _start, _end, _includeLow.GetValueOrDefault(), _includeHigh.GetValueOrDefault())); }
public FilterExprAnalyzerAffector GetFilterDesc( EventType[] typesPerStream, DatetimeMethodEnum currentMethod, IList <ExprNode> currentParameters, ExprDotNodeFilterAnalyzerInput inputDesc) { if (_includeLow == null || _includeHigh == null) { return(null); } int targetStreamNum; string targetProperty; if (inputDesc is ExprDotNodeFilterAnalyzerInputStream) { var targetStream = (ExprDotNodeFilterAnalyzerInputStream)inputDesc; targetStreamNum = targetStream.StreamNum; var targetType = typesPerStream[targetStreamNum]; targetProperty = targetType.StartTimestampPropertyName; } else if (inputDesc is ExprDotNodeFilterAnalyzerInputProp) { var targetStream = (ExprDotNodeFilterAnalyzerInputProp)inputDesc; targetStreamNum = targetStream.StreamNum; targetProperty = targetStream.PropertyName; } else { return(null); } return(new FilterExprAnalyzerDTBetweenAffector( typesPerStream, targetStreamNum, targetProperty, _start, _end, _includeLow.Value, _includeHigh.Value)); }
public FilterExprAnalyzerAffector GetFilterDesc( EventType[] typesPerStream, DateTimeMethodEnum currentMethod, IList<ExprNode> currentParameters, ExprDotNodeFilterAnalyzerInput inputDesc) { return null; }
/// <summary> /// Obtain information used by filter analyzer to handle this dot-method invocation as part of query planning/indexing. /// </summary> /// <param name="typesPerStream">event types</param> /// <param name="currentMethod">current method</param> /// <param name="currentParameters">current params</param> /// <param name="inputDesc">descriptor of what the input to this interval method is</param> public FilterExprAnalyzerDTIntervalAffector GetFilterDesc( EventType[] typesPerStream, DateTimeMethodEnum currentMethod, IList<ExprNode> currentParameters, ExprDotNodeFilterAnalyzerInput inputDesc) { // with intervals is not currently query planned if (currentParameters.Count > 1) { return null; } // Get input (target) int targetStreamNum; string targetPropertyStart; string targetPropertyEnd; if (inputDesc is ExprDotNodeFilterAnalyzerInputStream) { var targetStream = (ExprDotNodeFilterAnalyzerInputStream) inputDesc; targetStreamNum = targetStream.StreamNum; var targetType = typesPerStream[targetStreamNum]; targetPropertyStart = targetType.StartTimestampPropertyName; targetPropertyEnd = targetType.EndTimestampPropertyName != null ? targetType.EndTimestampPropertyName : targetPropertyStart; } else if (inputDesc is ExprDotNodeFilterAnalyzerInputProp) { var targetStream = (ExprDotNodeFilterAnalyzerInputProp) inputDesc; targetStreamNum = targetStream.StreamNum; targetPropertyStart = targetStream.PropertyName; targetPropertyEnd = targetStream.PropertyName; } else { return null; } // check parameter info if (parameterPropertyStart == null) { return null; } return new FilterExprAnalyzerDTIntervalAffector( currentMethod, typesPerStream, targetStreamNum, targetPropertyStart, targetPropertyEnd, parameterStreamNum, parameterPropertyStart, parameterPropertyEnd); }
public static ExprDotNodeRealizedChain GetChainEvaluators( int?streamOfProviderIfApplicable, EPType inputType, IList <ExprChainedSpec> chainSpec, ExprValidationContext validationContext, bool isDuckTyping, ExprDotNodeFilterAnalyzerInput inputDesc) { var methodEvals = new List <ExprDotEval>(); var currentInputType = inputType; EnumMethodEnum?lastLambdaFunc = null; var lastElement = chainSpec.IsEmpty() ? null : chainSpec[chainSpec.Count - 1]; ExprDotNodeFilterAnalyzerDesc filterAnalyzerDesc = null; var chainSpecStack = new ArrayDeque <ExprChainedSpec>(chainSpec); while (!chainSpecStack.IsEmpty()) { var chainElement = chainSpecStack.RemoveFirst(); lastLambdaFunc = null; // reset // compile parameters for chain element var paramEvals = new ExprEvaluator[chainElement.Parameters.Count]; var paramTypes = new Type[chainElement.Parameters.Count]; for (var i = 0; i < chainElement.Parameters.Count; i++) { paramEvals[i] = chainElement.Parameters[i].ExprEvaluator; paramTypes[i] = paramEvals[i].ReturnType; } // check if special 'size' method if (currentInputType is ClassMultiValuedEPType) { var type = (ClassMultiValuedEPType)currentInputType; if ((chainElement.Name.ToLower() == "size") && paramTypes.Length == 0 && Equals(lastElement, chainElement)) { var sizeExpr = new ExprDotEvalArraySize(); methodEvals.Add(sizeExpr); currentInputType = sizeExpr.TypeInfo; continue; } if ((chainElement.Name.ToLower() == "get") && paramTypes.Length == 1 && paramTypes[0].GetBoxedType() == typeof(int?)) { var componentType = type.Component; var get = new ExprDotEvalArrayGet(paramEvals[0], componentType); methodEvals.Add(get); currentInputType = get.TypeInfo; continue; } } // determine if there is a matching method var matchingMethod = false; var methodTarget = GetMethodTarget(currentInputType); if (methodTarget != null) { try { GetValidateMethodDescriptor(methodTarget, chainElement.Name, chainElement.Parameters, validationContext); matchingMethod = true; } catch (ExprValidationException) { // expected } } // resolve lambda if (chainElement.Name.IsEnumerationMethod() && (!matchingMethod || methodTarget.IsArray || methodTarget.IsImplementsInterface(typeof(ICollection <object>)))) { var enumerationMethod = EnumMethodEnumExtensions.FromName(chainElement.Name); var eval = TypeHelper.Instantiate <ExprDotEvalEnumMethod>(enumerationMethod.GetImplementation()); eval.Init(streamOfProviderIfApplicable, enumerationMethod, chainElement.Name, currentInputType, chainElement.Parameters, validationContext); currentInputType = eval.TypeInfo; if (currentInputType == null) { throw new IllegalStateException("Enumeration method '" + chainElement.Name + "' has not returned type information"); } methodEvals.Add(eval); lastLambdaFunc = enumerationMethod; continue; } // resolve datetime if (chainElement.Name.IsDateTimeMethod() && (!matchingMethod || methodTarget == typeof(DateTimeOffset?))) { var datetimeMethod = DatetimeMethodEnumExtensions.FromName(chainElement.Name); var datetimeImpl = ExprDotEvalDTFactory.ValidateMake( validationContext.StreamTypeService, chainSpecStack, datetimeMethod, chainElement.Name, currentInputType, chainElement.Parameters, inputDesc, validationContext.EngineImportService.TimeZone, validationContext.EngineImportService.TimeAbacus); currentInputType = datetimeImpl.ReturnType; if (currentInputType == null) { throw new IllegalStateException("Date-time method '" + chainElement.Name + "' has not returned type information"); } methodEvals.Add(datetimeImpl.Eval); filterAnalyzerDesc = datetimeImpl.IntervalFilterDesc; continue; } // try to resolve as property if the last method returned a type if (currentInputType is EventEPType) { var inputEventType = ((EventEPType)currentInputType).EventType; var type = inputEventType.GetPropertyType(chainElement.Name); var getter = inputEventType.GetGetter(chainElement.Name); if (type != null && getter != null) { var noduck = new ExprDotEvalProperty(getter, EPTypeHelper.SingleValue(type.GetBoxedType())); methodEvals.Add(noduck); currentInputType = EPTypeHelper.SingleValue(EPTypeHelper.GetClassSingleValued(noduck.TypeInfo)); continue; } } // Finally try to resolve the method if (methodTarget != null) { try { // find descriptor again, allow for duck typing var desc = GetValidateMethodDescriptor(methodTarget, chainElement.Name, chainElement.Parameters, validationContext); var fastMethod = desc.FastMethod; paramEvals = desc.ChildEvals; ExprDotEval eval; if (currentInputType is ClassEPType) { // if followed by an enumeration method, convert array to collection if (fastMethod.ReturnType.IsArray && !chainSpecStack.IsEmpty() && chainSpecStack.First.Name.IsEnumerationMethod()) { eval = new ExprDotMethodEvalNoDuckWrapArray(validationContext.StatementName, fastMethod, paramEvals); } else { eval = new ExprDotMethodEvalNoDuck(validationContext.StatementName, fastMethod, paramEvals); } } else { eval = new ExprDotMethodEvalNoDuckUnderlying(validationContext.StatementName, fastMethod, paramEvals); } methodEvals.Add(eval); currentInputType = eval.TypeInfo; } catch (Exception e) { if (!isDuckTyping) { throw new ExprValidationException(e.Message, e); } else { var duck = new ExprDotMethodEvalDuck(validationContext.StatementName, validationContext.EngineImportService, chainElement.Name, paramTypes, paramEvals); methodEvals.Add(duck); currentInputType = duck.TypeInfo; } } continue; } var message = "Could not find event property, enumeration method or instance method named '" + chainElement.Name + "' in " + currentInputType.ToTypeDescriptive(); throw new ExprValidationException(message); } var intermediateEvals = methodEvals.ToArray(); if (lastLambdaFunc != null) { ExprDotEval finalEval = null; if (currentInputType is EventMultiValuedEPType) { var mvType = (EventMultiValuedEPType)currentInputType; var tableMetadata = validationContext.TableService.GetTableMetadataFromEventType(mvType.Component); if (tableMetadata != null) { finalEval = new ExprDotEvalUnpackCollEventBeanTable(mvType.Component, tableMetadata); } else { finalEval = new ExprDotEvalUnpackCollEventBean(mvType.Component); } } else if (currentInputType is EventEPType) { var epType = (EventEPType)currentInputType; var tableMetadata = validationContext.TableService.GetTableMetadataFromEventType(epType.EventType); if (tableMetadata != null) { finalEval = new ExprDotEvalUnpackBeanTable(epType.EventType, tableMetadata); } else { finalEval = new ExprDotEvalUnpackBean(epType.EventType); } } if (finalEval != null) { methodEvals.Add(finalEval); } } var unpackingEvals = methodEvals.ToArray(); return(new ExprDotNodeRealizedChain(intermediateEvals, unpackingEvals, filterAnalyzerDesc)); }
public static ExprDotEvalDTMethodDesc ValidateMake( StreamTypeService streamTypeService, Deque <ExprChainedSpec> chainSpecStack, DatetimeMethodEnum dtMethod, String dtMethodName, EPType inputType, IList <ExprNode> parameters, ExprDotNodeFilterAnalyzerInput inputDesc, TimeZoneInfo timeZone) { // verify input String message = "Date-time enumeration method '" + dtMethodName + "' requires either a DateTime or long value as input or events of an event type that declares a timestamp property"; if (inputType is EventEPType) { if (((EventEPType)inputType).EventType.StartTimestampPropertyName == null) { throw new ExprValidationException(message); } } else { if (!(inputType is ClassEPType || inputType is NullEPType)) { throw new ExprValidationException(message + " but received " + EPTypeHelper.ToTypeDescriptive(inputType)); } if (inputType is ClassEPType) { ClassEPType classEPType = (ClassEPType)inputType; if (!TypeHelper.IsDateTime(classEPType.Clazz)) { throw new ExprValidationException( message + " but received " + classEPType.Clazz.GetTypeNameFullyQualPretty()); } } } IList <CalendarOp> calendarOps = new List <CalendarOp>(); ReformatOp reformatOp = null; IntervalOp intervalOp = null; DatetimeMethodEnum currentMethod = dtMethod; IList <ExprNode> currentParameters = parameters; String currentMethodName = dtMethodName; // drain all calendar ops ExprDotNodeFilterAnalyzerDesc filterAnalyzerDesc = null; while (true) { // handle the first one only if its a calendar op var evaluators = GetEvaluators(currentParameters); var opFactory = currentMethod.MetaData().OpFactory; // compile parameter abstract for validation against available footprints var footprintProvided = DotMethodUtil.GetProvidedFootprint(currentParameters); // validate parameters DotMethodUtil.ValidateParametersDetermineFootprint( currentMethod.Footprints(), DotMethodTypeEnum.DATETIME, currentMethodName, footprintProvided, DotMethodInputTypeMatcherImpl.DEFAULT_ALL); if (opFactory is CalendarOpFactory) { CalendarOp calendarOp = ((CalendarOpFactory)opFactory).GetOp(currentMethod, currentMethodName, currentParameters, evaluators); calendarOps.Add(calendarOp); } else if (opFactory is ReformatOpFactory) { reformatOp = ((ReformatOpFactory)opFactory).GetOp(timeZone, currentMethod, currentMethodName, currentParameters); // compile filter analyzer information if there are no calendar ops in the chain if (calendarOps.IsEmpty()) { filterAnalyzerDesc = reformatOp.GetFilterDesc(streamTypeService.EventTypes, currentMethod, currentParameters, inputDesc); } else { filterAnalyzerDesc = null; } } else if (opFactory is IntervalOpFactory) { intervalOp = ((IntervalOpFactory)opFactory).GetOp(streamTypeService, currentMethod, currentMethodName, currentParameters, evaluators); // compile filter analyzer information if there are no calendar ops in the chain if (calendarOps.IsEmpty()) { filterAnalyzerDesc = intervalOp.GetFilterDesc(streamTypeService.EventTypes, currentMethod, currentParameters, inputDesc); } else { filterAnalyzerDesc = null; } } else { throw new IllegalStateException("Invalid op factory class " + opFactory); } // see if there is more if (chainSpecStack.IsEmpty() || !DatetimeMethodEnumExtensions.IsDateTimeMethod(chainSpecStack.First.Name)) { break; } // pull next var next = chainSpecStack.RemoveFirst(); currentMethod = DatetimeMethodEnumExtensions.FromName(next.Name); currentParameters = next.Parameters; currentMethodName = next.Name; if ((reformatOp != null || intervalOp != null)) { throw new ExprValidationException("Invalid input for date-time method '" + next.Name + "'"); } } ExprDotEval dotEval; EPType returnType; dotEval = new ExprDotEvalDT(calendarOps, timeZone, reformatOp, intervalOp, EPTypeHelper.GetClassSingleValued(inputType), EPTypeHelper.GetEventTypeSingleValued(inputType)); returnType = dotEval.TypeInfo; return(new ExprDotEvalDTMethodDesc(dotEval, returnType, filterAnalyzerDesc)); }
public static ExprDotDTMethodDesc ValidateMake( StreamTypeService streamTypeService, Deque<Chainable> chainSpecStack, DatetimeMethodDesc dtMethod, string dtMethodName, EPType inputType, IList<ExprNode> parameters, ExprDotNodeFilterAnalyzerInput inputDesc, TimeAbacus timeAbacus, TableCompileTimeResolver tableCompileTimeResolver, ImportServiceCompileTime importService, StatementRawInfo statementRawInfo) { // verify input var message = "Date-time enumeration method '" + dtMethodName + "' requires either a DateTimeEx, DateTimeOffset, DateTime, or long value as input or events of an event type that declares a timestamp property"; if (inputType is EventEPType eventEpType) { if (eventEpType.EventType.StartTimestampPropertyName == null) { throw new ExprValidationException(message); } } else { if (!(inputType is ClassEPType || inputType is NullEPType)) { throw new ExprValidationException( message + " but received " + inputType.ToTypeDescriptive()); } if (inputType is ClassEPType classEpType) { if (!TypeHelper.IsDateTime(classEpType.Clazz)) { throw new ExprValidationException( message + " but received " + classEpType.Clazz.CleanName()); } } } IList<CalendarForge> calendarForges = new List<CalendarForge>(); ReformatForge reformatForge = null; IntervalForge intervalForge = null; var currentMethod = dtMethod; var currentParameters = parameters; var currentMethodName = dtMethodName; // drain all calendar op FilterExprAnalyzerAffector filterAnalyzerDesc = null; while (true) { // handle the first one only if its a calendar op var forges = GetForges(currentParameters); var opFactory = currentMethod.ForgeFactory; // compile parameter abstract for validation against available footprints var footprintProvided = DotMethodUtil.GetProvidedFootprint(currentParameters); // validate parameters var footprintFound = DotMethodUtil.ValidateParametersDetermineFootprint( currentMethod.Footprints, DotMethodTypeEnum.DATETIME, currentMethodName, footprintProvided, DotMethodInputTypeMatcherImpl.DEFAULT_ALL); if (opFactory is CalendarForgeFactory calendarForgeFactory) { var calendarForge = calendarForgeFactory.GetOp( currentMethod, currentMethodName, currentParameters, forges); calendarForges.Add(calendarForge); } else if (opFactory is ReformatForgeFactory reformatForgeFactory) { reformatForge = reformatForgeFactory.GetForge( inputType, timeAbacus, currentMethod, currentMethodName, currentParameters); // compile filter analyzer information if there are no calendar op in the chain if (calendarForges.IsEmpty()) { filterAnalyzerDesc = reformatForge.GetFilterDesc( streamTypeService.EventTypes, currentMethod, currentParameters, inputDesc); } else { filterAnalyzerDesc = null; } } else if (opFactory is IntervalForgeFactory intervalForgeFactory) { intervalForge = intervalForgeFactory.GetForge( streamTypeService, currentMethod, currentMethodName, currentParameters, timeAbacus, tableCompileTimeResolver); // compile filter analyzer information if there are no calendar op in the chain if (calendarForges.IsEmpty()) { filterAnalyzerDesc = intervalForge.GetFilterDesc( streamTypeService.EventTypes, currentMethod, currentParameters, inputDesc); } } else if (opFactory is DTMPluginForgeFactory dtmPluginForgeFactory) { var usageDesc = new DateTimeMethodValidateContext( footprintFound, streamTypeService, currentMethod, currentParameters, statementRawInfo); var ops = dtmPluginForgeFactory.Validate(usageDesc); if (ops == null) { throw new ExprValidationException( "Plug-in datetime method provider " + dtmPluginForgeFactory.GetType() + " returned a null-value for the operations"); } var input = EPTypeHelper.GetClassSingleValued(inputType); if (ops is DateTimeMethodOpsModify dateTimeMethodOpsModify) { calendarForges.Add(new DTMPluginValueChangeForge(input, dateTimeMethodOpsModify, usageDesc.CurrentParameters)); } else if (ops is DateTimeMethodOpsReformat dateTimeMethodOpsReformat) { reformatForge = new DTMPluginReformatForge(input, dateTimeMethodOpsReformat, usageDesc.CurrentParameters); } else { throw new ExprValidationException("Plug-in datetime method ops " + ops.GetType() + " is not recognized"); } // no action } else { throw new IllegalStateException("Invalid op factory class " + opFactory); } // see if there is more if (chainSpecStack.IsEmpty() || !DatetimeMethodResolver.IsDateTimeMethod(chainSpecStack.First.GetRootNameOrEmptyString(), importService)) { break; } // pull next var next = chainSpecStack.RemoveFirst(); currentMethodName = next.GetRootNameOrEmptyString(); currentMethod = DatetimeMethodResolver.FromName(currentMethodName, importService); currentParameters = next.GetParametersOrEmpty(); if (reformatForge != null || intervalForge != null) { throw new ExprValidationException("Invalid input for date-time method '" + currentMethodName + "'"); } } var dotForge = new ExprDotDTForge( calendarForges, timeAbacus, reformatForge, intervalForge, inputType.GetClassSingleValued(), inputType.GetEventTypeSingleValued()); var returnType = dotForge.TypeInfo; return new ExprDotDTMethodDesc(dotForge, returnType, filterAnalyzerDesc); }
public static ExprDotNodeRealizedChain GetChainEvaluators( int? streamOfProviderIfApplicable, EPType inputType, IList<ExprChainedSpec> chainSpec, ExprValidationContext validationContext, bool isDuckTyping, ExprDotNodeFilterAnalyzerInput inputDesc) { IList<ExprDotForge> methodForges = new List<ExprDotForge>(); var currentInputType = inputType; EnumMethodEnum? lastLambdaFunc = null; var lastElement = chainSpec.IsEmpty() ? null : chainSpec[chainSpec.Count - 1]; FilterExprAnalyzerAffector filterAnalyzerDesc = null; Deque<ExprChainedSpec> chainSpecStack = new ArrayDeque<ExprChainedSpec>(chainSpec); while (!chainSpecStack.IsEmpty()) { var chainElement = chainSpecStack.RemoveFirst(); lastLambdaFunc = null; // reset // compile parameters for chain element var paramForges = new ExprForge[chainElement.Parameters.Count]; var paramTypes = new Type[chainElement.Parameters.Count]; for (var i = 0; i < chainElement.Parameters.Count; i++) { paramForges[i] = chainElement.Parameters[i].Forge; paramTypes[i] = paramForges[i].EvaluationType; } // check if special 'size' method if (currentInputType is ClassMultiValuedEPType) { var type = (ClassMultiValuedEPType) currentInputType; if (chainElement.Name.Equals("size", StringComparison.InvariantCultureIgnoreCase) && paramTypes.Length == 0 && lastElement == chainElement) { var sizeExpr = new ExprDotForgeArraySize(); methodForges.Add(sizeExpr); currentInputType = sizeExpr.TypeInfo; continue; } if (chainElement.Name.Equals("get", StringComparison.InvariantCultureIgnoreCase) && paramTypes.Length == 1 && Boxing.GetBoxedType(paramTypes[0]) == typeof(int?)) { var componentType = Boxing.GetBoxedType(type.Component); var get = new ExprDotForgeArrayGet(paramForges[0], componentType); methodForges.Add(get); currentInputType = get.TypeInfo; continue; } } // determine if there is a matching method var matchingMethod = false; var methodTarget = GetMethodTarget(currentInputType); if (methodTarget != null) { try { GetValidateMethodDescriptor( methodTarget, chainElement.Name, chainElement.Parameters, validationContext); matchingMethod = true; } catch (ExprValidationException) { // expected } } if (EnumMethodEnumExtensions.IsEnumerationMethod(chainElement.Name) && (!matchingMethod || methodTarget.IsArray || methodTarget.IsGenericCollection())) { var enumerationMethod = EnumMethodEnumExtensions.FromName(chainElement.Name); if (enumerationMethod == null) { throw new EPException("unable to determine enumeration method from name"); } var eval = TypeHelper.Instantiate<ExprDotForgeEnumMethod>( enumerationMethod.Value.GetImplementation()); eval.Init( streamOfProviderIfApplicable, enumerationMethod.Value, chainElement.Name, currentInputType, chainElement.Parameters, validationContext); currentInputType = eval.TypeInfo; if (currentInputType == null) { throw new IllegalStateException( "Enumeration method '" + chainElement.Name + "' has not returned type information"); } methodForges.Add(eval); lastLambdaFunc = enumerationMethod; continue; } // resolve datetime if (DatetimeMethodEnumHelper.IsDateTimeMethod(chainElement.Name) && (!matchingMethod || methodTarget == typeof(DateTimeEx) || methodTarget == typeof(DateTimeOffset) || methodTarget == typeof(DateTime))) { var dateTimeMethod = DatetimeMethodEnumHelper.FromName(chainElement.Name); var datetimeImpl = ExprDotDTFactory.ValidateMake( validationContext.StreamTypeService, chainSpecStack, dateTimeMethod, chainElement.Name, currentInputType, chainElement.Parameters, inputDesc, validationContext.ImportService.TimeAbacus, null, validationContext.TableCompileTimeResolver); currentInputType = datetimeImpl.ReturnType; if (currentInputType == null) { throw new IllegalStateException( "Date-time method '" + chainElement.Name + "' 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) { var inputEventType = (EventTypeSPI) ((EventEPType) currentInputType).EventType; var type = inputEventType.GetPropertyType(chainElement.Name); var getter = inputEventType.GetGetterSPI(chainElement.Name); if (type != null && getter != null) { var noduck = new ExprDotForgeProperty( getter, EPTypeHelper.SingleValue(Boxing.GetBoxedType(type))); methodForges.Add(noduck); currentInputType = EPTypeHelper.SingleValue(EPTypeHelper.GetClassSingleValued(noduck.TypeInfo)); continue; } } // Finally try to resolve the method if (methodTarget != null) { try { // find descriptor again, allow for duck typing var desc = GetValidateMethodDescriptor( methodTarget, chainElement.Name, chainElement.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() && EnumMethodEnumExtensions.IsEnumerationMethod(chainSpecStack.First.Name)) { 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, chainElement.Name, paramTypes, paramForges); methodForges.Add(duck); currentInputType = duck.TypeInfo; } continue; } var message = "Could not find event property, enumeration method or instance method named '" + chainElement.Name + "' in " + EPTypeHelper.ToTypeDescriptive(currentInputType); throw new ExprValidationException(message); } var intermediateEvals = methodForges.ToArray(); if (lastLambdaFunc != null) { ExprDotForge finalEval = null; if (currentInputType is EventMultiValuedEPType) { var mvType = (EventMultiValuedEPType) currentInputType; 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) { var epType = (EventEPType) currentInputType; 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); }
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)); }
public static ExprDotDTMethodDesc ValidateMake( StreamTypeService streamTypeService, Deque<ExprChainedSpec> chainSpecStack, DateTimeMethodEnum dtMethod, string dtMethodName, EPType inputType, IList<ExprNode> parameters, ExprDotNodeFilterAnalyzerInput inputDesc, TimeAbacus timeAbacus, ExprEvaluatorContext exprEvaluatorContext, TableCompileTimeResolver tableCompileTimeResolver) { // verify input var message = "Date-time enumeration method '" + dtMethodName + "' requires either a DateTimeEx, DateTimeOffset, DateTime, or long value as input or events of an event type that declares a timestamp property"; if (inputType is EventEPType) { if (((EventEPType) inputType).EventType.StartTimestampPropertyName == null) { throw new ExprValidationException(message); } } else { if (!(inputType is ClassEPType || inputType is NullEPType)) { throw new ExprValidationException( message + " but received " + inputType.ToTypeDescriptive()); } if (inputType is ClassEPType) { var classEPType = (ClassEPType) inputType; if (!TypeHelper.IsDateTime(classEPType.Clazz)) { throw new ExprValidationException( message + " but received " + classEPType.Clazz.CleanName()); } } } IList<CalendarForge> calendarForges = new List<CalendarForge>(); ReformatForge reformatForge = null; IntervalForge intervalForge = null; var currentMethod = dtMethod; var currentParameters = parameters; var currentMethodName = dtMethodName; // drain all calendar op FilterExprAnalyzerAffector filterAnalyzerDesc = null; while (true) { // handle the first one only if its a calendar op var forges = GetForges(currentParameters); var opFactory = currentMethod.GetForgeFactory(); // compile parameter abstract for validation against available footprints DotMethodFPProvided footprintProvided = DotMethodUtil.GetProvidedFootprint(currentParameters); // validate parameters DotMethodUtil.ValidateParametersDetermineFootprint( currentMethod.GetFootprints(), DotMethodTypeEnum.DATETIME, currentMethodName, footprintProvided, DotMethodInputTypeMatcherImpl.DEFAULT_ALL); if (opFactory is CalendarForgeFactory) { var calendarForge = ((CalendarForgeFactory) currentMethod.GetForgeFactory()).GetOp( currentMethod, currentMethodName, currentParameters, forges); calendarForges.Add(calendarForge); } else if (opFactory is ReformatForgeFactory) { reformatForge = ((ReformatForgeFactory) opFactory).GetForge( inputType, timeAbacus, currentMethod, currentMethodName, currentParameters, exprEvaluatorContext); // compile filter analyzer information if there are no calendar op in the chain if (calendarForges.IsEmpty()) { filterAnalyzerDesc = reformatForge.GetFilterDesc( streamTypeService.EventTypes, currentMethod, currentParameters, inputDesc); } else { filterAnalyzerDesc = null; } } else if (opFactory is IntervalForgeFactory) { intervalForge = ((IntervalForgeFactory) opFactory).GetForge( streamTypeService, currentMethod, currentMethodName, currentParameters, timeAbacus, tableCompileTimeResolver); // compile filter analyzer information if there are no calendar op in the chain if (calendarForges.IsEmpty()) { filterAnalyzerDesc = intervalForge.GetFilterDesc( streamTypeService.EventTypes, currentMethod, currentParameters, inputDesc); } else { filterAnalyzerDesc = null; } } else { throw new IllegalStateException("Invalid op factory class " + opFactory); } // see if there is more if (chainSpecStack.IsEmpty() || !DatetimeMethodEnumHelper.IsDateTimeMethod(chainSpecStack.First.Name)) { break; } // pull next var next = chainSpecStack.RemoveFirst(); currentMethod = DatetimeMethodEnumHelper.FromName(next.Name); currentParameters = next.Parameters; currentMethodName = next.Name; if (reformatForge != null || intervalForge != null) { throw new ExprValidationException("Invalid input for date-time method '" + next.Name + "'"); } } ExprDotForge dotForge; EPType returnType; dotForge = new ExprDotDTForge( calendarForges, timeAbacus, reformatForge, intervalForge, inputType.GetClassSingleValued(), inputType.GetEventTypeSingleValued()); returnType = dotForge.TypeInfo; return new ExprDotDTMethodDesc(dotForge, returnType, filterAnalyzerDesc); }