public void CheckAndWrite( string deploymentId, string variableName, int agentInstanceId, object newValue) { var entry = DeploymentsWithVariables.Get(deploymentId); if (entry == null) { throw new ArgumentException("Failed to find variable deployment id '" + deploymentId + "'"); } var variable = entry.GetVariable(variableName); var variableNumber = variable.VariableNumber; if (newValue == null) { Write(variableNumber, agentInstanceId, null); return; } var valueType = newValue.GetType(); if (variable.MetaData.EventType != null) { if (!TypeHelper.IsSubclassOrImplementsInterface( newValue.GetType(), variable.MetaData.EventType.UnderlyingType)) { throw new VariableValueException( "Variable '" + variableName + "' of declared event type '" + variable.MetaData.EventType.Name + "' underlying type '" + variable.MetaData.EventType.UnderlyingType.CleanName() + "' cannot be assigned a value of type '" + valueType.Name + "'"); } var eventBean = eventBeanTypedEventFactory.AdapterForTypedObject(newValue, variable.MetaData.EventType); Write(variableNumber, agentInstanceId, eventBean); return; } var variableType = variable.MetaData.Type; if (valueType.Equals(variableType) || variableType == typeof(object)) { Write(variableNumber, agentInstanceId, newValue); return; } if (TypeHelper.IsSubclassOrImplementsInterface(valueType, variableType)) { Write(variableNumber, agentInstanceId, newValue); return; } if (!variableType.IsNumeric() || !valueType.IsNumeric()) { throw new VariableValueException( VariableUtil.GetAssigmentExMessage(variableName, variableType, valueType)); } // determine if the expression type can be assigned if (!valueType.CanCoerce(variableType)) { throw new VariableValueException( VariableUtil.GetAssigmentExMessage(variableName, variableType, valueType)); } var valueCoerced = TypeHelper.CoerceBoxed(newValue, variableType); Write(variableNumber, agentInstanceId, valueCoerced); }
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); } }