public void CheckAndWrite(String variableName, int agentInstanceId, Object newValue) { var metaData = _variables.Get(variableName); var variableNumber = metaData.VariableNumber; if (newValue == null) { Write(variableNumber, agentInstanceId, null); return; } var valueType = newValue.GetType(); if (metaData.EventType != null) { if ((!TypeHelper.IsSubclassOrImplementsInterface(newValue.GetType(), metaData.EventType.UnderlyingType))) { throw new VariableValueException("Variable '" + variableName + "' of declared event type '" + metaData.EventType.Name + "' underlying type '" + metaData.EventType.UnderlyingType.FullName + "' cannot be assigned a value of type '" + valueType.FullName + "'"); } var eventBean = _eventAdapterService.AdapterForType(newValue, metaData.EventType); Write(variableNumber, agentInstanceId, eventBean); return; } var variableType = metaData.VariableType; if ((valueType == variableType) || (variableType == typeof(object))) { Write(variableNumber, agentInstanceId, newValue); return; } // Look for simple boxing rules var valueTypeBoxed = valueType.GetBoxedType(); var variableTypeBoxed = variableType.GetBoxedType(); if (((valueType != valueTypeBoxed) || (variableType != variableTypeBoxed)) && ((valueTypeBoxed == variableTypeBoxed))) { Write(variableNumber, agentInstanceId, newValue); return; } if ((!variableType.IsNumeric()) || (!valueType.IsNumeric())) { throw new VariableValueException(VariableServiceUtil.GetAssigmentExMessage(variableName, variableType, valueType)); } // determine if the expression type can be assigned if (!(TypeHelper.CanCoerce(valueType, variableType))) { throw new VariableValueException(VariableServiceUtil.GetAssigmentExMessage(variableName, variableType, valueType)); } object valueCoerced = CoercerFactory.CoerceBoxed(newValue, variableType); Write(variableNumber, agentInstanceId, valueCoerced); }
/// <summary> /// Ctor. /// </summary> /// <param name="assignments">the list of variable assignments</param> /// <param name="variableService">variable service</param> /// <param name="eventAdapterService">event adapters</param> /// <throws><seealso cref="ExprValidationException" /> when variables cannot be found</throws> public VariableReadWritePackage(IList <OnTriggerSetAssignment> assignments, VariableService variableService, EventAdapterService eventAdapterService) { _metaData = new VariableMetaData[assignments.Count]; _readersForGlobalVars = new VariableReader[assignments.Count]; _mustCoerce = new bool[assignments.Count]; _writers = new WriteDesc[assignments.Count]; _variableTypes = new Dictionary <String, Object>(); _eventAdapterService = eventAdapterService; _variableService = variableService; IDictionary <EventTypeSPI, CopyMethodDesc> eventTypeWrittenProps = new Dictionary <EventTypeSPI, CopyMethodDesc>(); var count = 0; IList <VariableTriggerSetDesc> assignmentList = new List <VariableTriggerSetDesc>(); foreach (var expressionWithAssignments in assignments) { var possibleVariableAssignment = ExprNodeUtility.CheckGetAssignmentToVariableOrProp(expressionWithAssignments.Expression); if (possibleVariableAssignment == null) { throw new ExprValidationException("Missing variable assignment expression in assignment number " + count); } assignmentList.Add(new VariableTriggerSetDesc(possibleVariableAssignment.First, possibleVariableAssignment.Second.ExprEvaluator)); var fullVariableName = possibleVariableAssignment.First; var variableName = fullVariableName; String subPropertyName = null; var indexOfDot = variableName.IndexOf('.'); if (indexOfDot != -1) { subPropertyName = variableName.Substring(indexOfDot + 1); variableName = variableName.Substring(0, indexOfDot); } VariableMetaData variableMetadata = variableService.GetVariableMetaData(variableName); _metaData[count] = variableMetadata; if (variableMetadata == null) { throw new ExprValidationException("Variable by name '" + variableName + "' has not been created or configured"); } if (variableMetadata.IsConstant) { throw new ExprValidationException("Variable by name '" + variableName + "' is declared constant and may not be set"); } if (variableMetadata.ContextPartitionName == null) { _readersForGlobalVars[count] = variableService.GetReader(variableName, EPStatementStartMethodConst.DEFAULT_AGENT_INSTANCE_ID); } if (subPropertyName != null) { if (variableMetadata.EventType == null) { throw new ExprValidationException("Variable by name '" + variableName + "' does not have a property named '" + subPropertyName + "'"); } var type = variableMetadata.EventType; if (!(type is EventTypeSPI)) { throw new ExprValidationException("Variable by name '" + variableName + "' event type '" + type.Name + "' not writable"); } var spi = (EventTypeSPI)type; var writer = spi.GetWriter(subPropertyName); var getter = spi.GetGetter(subPropertyName); if (writer == null) { throw new ExprValidationException("Variable by name '" + variableName + "' the property '" + subPropertyName + "' is not writable"); } _variableTypes.Put(fullVariableName, spi.GetPropertyType(subPropertyName)); var writtenProps = eventTypeWrittenProps.Get(spi); if (writtenProps == null) { writtenProps = new CopyMethodDesc(variableName, new List <String>()); eventTypeWrittenProps.Put(spi, writtenProps); } writtenProps.PropertiesCopied.Add(subPropertyName); _writers[count] = new WriteDesc(spi, variableName, writer, getter); } else { // determine types var expressionType = possibleVariableAssignment.Second.ExprEvaluator.ReturnType; if (variableMetadata.EventType != null) { if ((expressionType != null) && (!TypeHelper.IsSubclassOrImplementsInterface(expressionType, variableMetadata.EventType.UnderlyingType))) { throw new VariableValueException("Variable '" + variableName + "' of declared event type '" + variableMetadata.EventType.Name + "' underlying type '" + variableMetadata.EventType.UnderlyingType.FullName + "' cannot be assigned a value of type '" + expressionType.FullName + "'"); } _variableTypes.Put(variableName, variableMetadata.EventType.UnderlyingType); } else { var variableType = variableMetadata.VariableType; _variableTypes.Put(variableName, variableType); // determine if the expression type can be assigned if (variableType != typeof(object)) { if ((TypeHelper.GetBoxedType(expressionType) != variableType) && (expressionType != null)) { if ((!TypeHelper.IsNumeric(variableType)) || (!TypeHelper.IsNumeric(expressionType))) { throw new ExprValidationException(VariableServiceUtil.GetAssigmentExMessage(variableName, variableType, expressionType)); } if (!(TypeHelper.CanCoerce(expressionType, variableType))) { throw new ExprValidationException(VariableServiceUtil.GetAssigmentExMessage(variableName, variableType, expressionType)); } _mustCoerce[count] = true; } } } } count++; } _assignments = assignmentList.ToArray(); if (eventTypeWrittenProps.IsEmpty()) { _copyMethods = new Dictionary <EventTypeSPI, EventBeanCopyMethod>(); return; } _copyMethods = new Dictionary <EventTypeSPI, EventBeanCopyMethod>(); foreach (var entry in eventTypeWrittenProps) { var propsWritten = entry.Value.PropertiesCopied; var props = propsWritten.ToArray(); var copyMethod = entry.Key.GetCopyMethod(props); if (copyMethod == null) { throw new ExprValidationException("Variable '" + entry.Value.VariableName + "' of declared type " + entry.Key.UnderlyingType.GetTypeNameFullyQualPretty() + "' cannot be assigned to"); } _copyMethods.Put(entry.Key, copyMethod); } }
internal static FilterSpecParamForge HandleInSetNode( ExprInNode constituent, IDictionary <string, Pair <EventType, string> > taggedEventTypes, IDictionary <string, Pair <EventType, string> > arrayEventTypes, ISet <string> allTagNamesOrdered, StatementRawInfo raw, StatementCompileTimeServices services) { var left = constituent.ChildNodes[0]; ExprFilterSpecLookupableForge lookupable = null; if (left is ExprFilterOptimizableNode) { var filterOptimizableNode = (ExprFilterOptimizableNode)left; lookupable = filterOptimizableNode.FilterLookupable; } else if (FilterSpecCompilerIndexPlannerHelper.HasLevelOrHint(FilterSpecCompilerIndexPlannerHint.LKUPCOMPOSITE, raw, services) && IsLimitedLookupableExpression(left)) { lookupable = MakeLimitedLookupableForgeMayNull(left, raw, services); } if (lookupable == null) { return(null); } var op = FilterOperator.IN_LIST_OF_VALUES; if (constituent.IsNotIn) { op = FilterOperator.NOT_IN_LIST_OF_VALUES; } var expectedNumberOfConstants = constituent.ChildNodes.Length - 1; IList <FilterSpecParamInValueForge> listofValues = new List <FilterSpecParamInValueForge>(); var it = Arrays.AsList(constituent.ChildNodes).GetEnumerator(); it.MoveNext(); // ignore the first node as it's the identifier while (it.MoveNext()) { var subNode = it.Current; if (subNode.Forge.ForgeConstantType.IsCompileTimeConstant) { var constant = subNode.Forge.ExprEvaluator.Evaluate(null, true, null); if (constant is ICollection <object> ) { return(null); } if (constant is IDictionary <object, object> ) { return(null); } if ((constant != null) && (constant is Array arrayConstant)) { for (var i = 0; i < arrayConstant.Length; i++) { var arrayElement = arrayConstant.GetValue(i); var arrayElementCoerced = HandleConstantsCoercion(lookupable, arrayElement); listofValues.Add(new FilterForEvalConstantAnyTypeForge(arrayElementCoerced)); if (i > 0) { expectedNumberOfConstants++; } } } else { constant = HandleConstantsCoercion(lookupable, constant); listofValues.Add(new FilterForEvalConstantAnyTypeForge(constant)); } } else if (subNode is ExprContextPropertyNode) { var contextPropertyNode = (ExprContextPropertyNode)subNode; var returnType = contextPropertyNode.Type; Coercer coercer; if (TypeHelper.IsCollectionMapOrArray(returnType)) { CheckArrayCoercion(returnType, lookupable.ReturnType, lookupable.Expression); coercer = null; } else { coercer = GetNumberCoercer(left.Forge.EvaluationType, contextPropertyNode.Type, lookupable.Expression); } var finalReturnType = coercer != null ? coercer.ReturnType : returnType; listofValues.Add(new FilterForEvalContextPropForge(contextPropertyNode.PropertyName, contextPropertyNode.Getter, coercer, finalReturnType)); } else if (subNode.Forge.ForgeConstantType.IsDeployTimeTimeConstant && subNode is ExprNodeDeployTimeConst) { var deployTimeConst = (ExprNodeDeployTimeConst)subNode; var returnType = subNode.Forge.EvaluationType; Coercer coercer; if (TypeHelper.IsCollectionMapOrArray(returnType)) { CheckArrayCoercion(returnType, lookupable.ReturnType, lookupable.Expression); coercer = null; } else { coercer = GetNumberCoercer(left.Forge.EvaluationType, returnType, lookupable.Expression); } listofValues.Add(new FilterForEvalDeployTimeConstForge(deployTimeConst, coercer, returnType)); } else if (subNode is ExprIdentNode) { var identNodeInner = (ExprIdentNode)subNode; if (identNodeInner.StreamId == 0) { break; // for same event evals use the boolean expression, via count compare failing below } var isMustCoerce = false; var coerceToType = Boxing.GetBoxedType(lookupable.ReturnType); var identReturnType = identNodeInner.Forge.EvaluationType; if (TypeHelper.IsCollectionMapOrArray(identReturnType)) { CheckArrayCoercion(identReturnType, lookupable.ReturnType, lookupable.Expression); coerceToType = identReturnType; // no action } else if (identReturnType != lookupable.ReturnType) { if (TypeHelper.IsNumeric(lookupable.ReturnType)) { if (!TypeHelper.CanCoerce(identReturnType, lookupable.ReturnType)) { ThrowConversionError(identReturnType, lookupable.ReturnType, lookupable.Expression); } isMustCoerce = true; } else { break; // assumed not compatible } } FilterSpecParamInValueForge inValue; var streamName = identNodeInner.ResolvedStreamName; if (arrayEventTypes != null && !arrayEventTypes.IsEmpty() && arrayEventTypes.ContainsKey(streamName)) { var indexAndProp = GetStreamIndex(identNodeInner.ResolvedPropertyName); var innerEventType = GetArrayInnerEventType(arrayEventTypes, streamName); inValue = new FilterForEvalEventPropIndexedForge( identNodeInner.ResolvedStreamName, indexAndProp.First, indexAndProp.Second, innerEventType, isMustCoerce, coerceToType); } else { inValue = new FilterForEvalEventPropForge( identNodeInner.ResolvedStreamName, identNodeInner.ResolvedPropertyName, identNodeInner.ExprEvaluatorIdent, isMustCoerce, coerceToType); } listofValues.Add(inValue); } else if (FilterSpecCompilerIndexPlannerHelper.HasLevelOrHint(FilterSpecCompilerIndexPlannerHint.VALUECOMPOSITE, raw, services) && IsLimitedValueExpression(subNode)) { var convertor = GetMatchEventConvertor(subNode, taggedEventTypes, arrayEventTypes, allTagNamesOrdered); var valueType = subNode.Forge.EvaluationType; var lookupableType = lookupable.ReturnType; var numberCoercer = GetNumberCoercer(lookupableType, valueType, lookupable.Expression); var forge = new FilterForEvalLimitedExprForge(subNode, convertor, numberCoercer); listofValues.Add(forge); } } // Fallback if not all values in the in-node can be resolved to properties or constants if (listofValues.Count == expectedNumberOfConstants) { return(new FilterSpecParamInForge(lookupable, op, listofValues)); } return(null); }
public VariantPropertyDesc ResolveProperty(String propertyName, EventType[] variants) { bool existsInAll = true; Type commonType = null; bool mustCoerce = false; for (int i = 0; i < variants.Length; i++) { Type type = variants[i].GetPropertyType(propertyName); //.GetBoxedType(); if (type == null) { existsInAll = false; continue; } if (commonType == null) { commonType = type; continue; } // compare types if (type == commonType) { continue; } if (type.GetBoxedType() == commonType.GetBoxedType()) { commonType = commonType.GetBoxedType(); continue; } // coercion if (type.IsNumeric()) { if (TypeHelper.CanCoerce(type, commonType)) { mustCoerce = true; continue; } if (TypeHelper.CanCoerce(commonType, type)) { mustCoerce = true; commonType = type; } } else if (commonType == typeof(Object)) { continue; } // common interface or base class else if (!type.IsBuiltinDataType()) { var supersForType = new FIFOHashSet <Type>(); TypeHelper.GetBase(type, supersForType); supersForType.Remove(typeof(Object)); if (supersForType.Contains(commonType)) { continue; // type, or : common type } if (TypeHelper.IsSubclassOrImplementsInterface(commonType, type)) { commonType = type; // common type : type continue; } // find common interface or type both implement var supersForCommonType = new FIFOHashSet <Type>(); TypeHelper.GetBase(commonType, supersForCommonType); supersForCommonType.Remove(typeof(Object)); // Take common classes first, ignoring interfaces bool found = false; foreach (Type superClassType in supersForType) { if (!superClassType.IsInterface && (supersForCommonType.Contains(superClassType))) { break; } } if (found) { continue; } // Take common interfaces foreach (var superClassType in supersForType) { if (superClassType.IsInterface && supersForCommonType.Contains(superClassType)) { commonType = superClassType; found = true; break; } } } commonType = typeof(Object); } if (!existsInAll) { return(null); } if (commonType == null) { return(null); } // property numbers should start at zero since the serve as array index var assignedPropertyNumber = currentPropertyNumber; currentPropertyNumber++; propertyGetterCache.AddGetters(assignedPropertyNumber, propertyName); EventPropertyGetter getter; if (mustCoerce) { SimpleTypeCaster caster = SimpleTypeCasterFactory.GetCaster(null, commonType); getter = new ProxyEventPropertyGetter { ProcGet = eventBean => { var variant = (VariantEvent)eventBean; var propertyGetter = propertyGetterCache.GetGetter(assignedPropertyNumber, variant.UnderlyingEventBean.EventType); if (propertyGetter == null) { return(null); } var value = propertyGetter.Get(variant.UnderlyingEventBean); if (value == null) { return(value); } return(caster.Invoke(value)); }, ProcGetFragment = eventBean => null, ProcIsExistsProperty = eventBean => { var variant = (VariantEvent)eventBean; var propertyGetter = propertyGetterCache.GetGetter(assignedPropertyNumber, variant.UnderlyingEventBean.EventType); if (propertyGetter == null) { return(false); } return(propertyGetter.IsExistsProperty(variant.UnderlyingEventBean)); } }; } else { getter = new ProxyEventPropertyGetter { ProcGet = eventBean => { var variant = (VariantEvent)eventBean; var propertyGetter = propertyGetterCache.GetGetter(assignedPropertyNumber, variant.UnderlyingEventBean.EventType); if (propertyGetter == null) { return(null); } return(propertyGetter.Get(variant.UnderlyingEventBean)); }, ProcGetFragment = eventBean => null, ProcIsExistsProperty = eventBean => { var variant = (VariantEvent)eventBean; var propertyGetter = propertyGetterCache.GetGetter(assignedPropertyNumber, variant.UnderlyingEventBean.EventType); if (propertyGetter == null) { return(false); } return(propertyGetter.IsExistsProperty(variant.UnderlyingEventBean)); } }; } return(new VariantPropertyDesc(commonType, getter, true)); }
public VariableReadWritePackageForge( IList <OnTriggerSetAssignment> assignments, string statementName, StatementCompileTimeServices services) { _variables = new VariableMetaData[assignments.Count]; _mustCoerce = new bool[assignments.Count]; _writers = new VariableTriggerWriteForge[assignments.Count]; _variableTypes = new Dictionary <string, object>(); IDictionary <EventTypeSPI, CopyMethodDesc> eventTypeWrittenProps = new Dictionary <EventTypeSPI, CopyMethodDesc>(); var count = 0; IList <ExprAssignment> assignmentList = new List <ExprAssignment>(); foreach (var spec in assignments) { var assignmentDesc = spec.Validated; assignmentList.Add(assignmentDesc); try { if (assignmentDesc is ExprAssignmentStraight) { var assignment = (ExprAssignmentStraight)assignmentDesc; var identAssignment = assignment.Lhs; var variableName = identAssignment.Ident; var variableMetadata = services.VariableCompileTimeResolver.Resolve(variableName); if (variableMetadata == null) { throw new ExprValidationException("Variable by name '" + variableName + "' has not been created or configured"); } _variables[count] = variableMetadata; var expressionType = assignment.Rhs.Forge.EvaluationType; if (assignment.Lhs is ExprAssignmentLHSIdent) { // determine types if (variableMetadata.EventType != null) { if ((expressionType != null) && (!TypeHelper.IsSubclassOrImplementsInterface(expressionType, variableMetadata.EventType.UnderlyingType))) { throw new ExprValidationException( "Variable '" + variableName + "' of declared event type '" + variableMetadata.EventType.Name + "' underlying type '" + variableMetadata.EventType.UnderlyingType.Name + "' cannot be assigned a value of type '" + expressionType.Name + "'"); } _variableTypes.Put(variableName, variableMetadata.EventType.UnderlyingType); } else { var variableType = variableMetadata.Type; _variableTypes.Put(variableName, variableType); // determine if the expression type can be assigned if (variableType != typeof(object)) { if ((expressionType.GetBoxedType() != variableType.GetBoxedType()) && (expressionType != null)) { if ((!TypeHelper.IsNumeric(variableType)) || (!TypeHelper.IsNumeric(expressionType))) { throw new ExprValidationException(VariableUtil.GetAssigmentExMessage(variableName, variableType, expressionType)); } if (!(TypeHelper.CanCoerce(expressionType, variableType))) { throw new ExprValidationException(VariableUtil.GetAssigmentExMessage(variableName, variableType, expressionType)); } _mustCoerce[count] = true; } } } } else if (assignment.Lhs is ExprAssignmentLHSIdentWSubprop) { var subpropAssignment = (ExprAssignmentLHSIdentWSubprop)assignment.Lhs; var subPropertyName = subpropAssignment.SubpropertyName; if (variableMetadata.EventType == null) { throw new ExprValidationException( "Variable by name '" + variableName + "' does not have a property named '" + subPropertyName + "'"); } var type = variableMetadata.EventType; if (!(type is EventTypeSPI)) { throw new ExprValidationException("Variable by name '" + variableName + "' event type '" + type.Name + "' not writable"); } var spi = (EventTypeSPI)type; var writer = spi.GetWriter(subPropertyName); var getter = spi.GetGetterSPI(subPropertyName); var getterType = spi.GetPropertyType(subPropertyName); if (writer == null) { throw new ExprValidationException( "Variable by name '" + variableName + "' the property '" + subPropertyName + "' is not writable"); } var fullVariableName = variableName + "." + subPropertyName; _variableTypes.Put(fullVariableName, spi.GetPropertyType(subPropertyName)); var writtenProps = eventTypeWrittenProps.Get(spi); if (writtenProps == null) { writtenProps = new CopyMethodDesc(variableName, new List <string>()); eventTypeWrittenProps.Put(spi, writtenProps); } writtenProps.PropertiesCopied.Add(subPropertyName); _writers[count] = new VariableTriggerWriteDescForge( spi, variableName, writer, getter, getterType, assignment.Rhs.Forge.EvaluationType); } else if (assignment.Lhs is ExprAssignmentLHSArrayElement) { var arrayAssign = (ExprAssignmentLHSArrayElement)assignment.Lhs; var variableType = variableMetadata.Type; if (!variableType.IsArray) { throw new ExprValidationException("Variable '" + variableMetadata.VariableName + "' is not an array"); } TypeWidenerSPI widener; try { widener = TypeWidenerFactory.GetCheckPropertyAssignType( ExprNodeUtilityPrint.ToExpressionStringMinPrecedenceSafe(assignment.Rhs), expressionType, variableType.GetElementType(), variableMetadata.VariableName, false, null, statementName); } catch (TypeWidenerException ex) { throw new ExprValidationException(ex.Message, ex); } _writers[count] = new VariableTriggerWriteArrayElementForge(variableName, arrayAssign.IndexExpression.Forge, widener); } else { throw new IllegalStateException("Unrecognized left hand side assignment " + assignment.Lhs); } } else if (assignmentDesc is ExprAssignmentCurly) { var curly = (ExprAssignmentCurly)assignmentDesc; if (curly.Expression is ExprVariableNode) { throw new ExprValidationException("Missing variable assignment expression in assignment number " + count); } var variableVisitor = new ExprNodeVariableVisitor(services.VariableCompileTimeResolver); curly.Expression.Accept(variableVisitor); if (variableVisitor.VariableNames == null || variableVisitor.VariableNames.Count != 1) { throw new ExprValidationException("Assignment expression must receive a single variable value"); } var variable = variableVisitor.VariableNames.First(); _variables[count] = variable.Value; _writers[count] = new VariableTriggerWriteCurlyForge(variable.Key, curly.Expression.Forge); } else { throw new IllegalStateException("Unrecognized assignment expression " + assignmentDesc); } if (_variables[count].IsConstant) { throw new ExprValidationException("Variable by name '" + _variables[count].VariableName + "' is declared constant and may not be set"); } count++; } catch (ExprValidationException ex) { throw new ExprValidationException( "Failed to validate assignment expression '" + ExprNodeUtilityPrint.ToExpressionStringMinPrecedenceSafe(assignmentDesc.OriginalExpression) + "': " + ex.Message, ex); } } _assignments = assignmentList.ToArray(); if (eventTypeWrittenProps.IsEmpty()) { _copyMethods = EmptyDictionary <EventTypeSPI, EventBeanCopyMethodForge> .Instance; return; } _copyMethods = new Dictionary <EventTypeSPI, EventBeanCopyMethodForge>(); foreach (var entry in eventTypeWrittenProps) { var propsWritten = entry.Value.PropertiesCopied; var props = propsWritten.ToArray(); var copyMethod = entry.Key.GetCopyMethodForge(props); if (copyMethod == null) { throw new ExprValidationException( "Variable '" + entry.Value.VariableName + "' of declared type " + entry.Key.UnderlyingType.CleanName() + "' cannot be assigned to"); } _copyMethods.Put(entry.Key, copyMethod); } }