static private void ValidateCondition(RSConditionData inCondition, RSValidationState ioState, RSValidationContext inContext) { ioState.PushContext("Query"); ValidateResolvableValue(inCondition.Query, null, RSValidationFlags.None.ForConditionQuery(), ioState, inContext); ioState.PopContext(); RSTypeInfo expectedType = inCondition.Query.TypeInfo(inContext.Trigger, inContext.Library); if (inCondition.Query.Mode != ResolvableValueMode.Value && expectedType != null) { ioState.PushContext("Operator"); CompareOperator op = inCondition.Operator; if (!expectedType.IsOperatorAllowed(op)) { ioState.Error("Operator {0} is not allowed for type {1}", op, expectedType); } ioState.PopContext(); if (op.IsBinary()) { ioState.PushContext("Target"); ValidateResolvableValue(inCondition.Target, expectedType, RSValidationFlags.None.ForConditionTarget(), ioState, inContext); ioState.PopContext(); } } }
static private void ValidateRule(RSRuleData inRule, RSValidationState ioState, RSValidationContext inContext) { if (inRule == null) { ioState.Error("Null rule"); return; } ioState.PushContext("Trigger"); RSTriggerInfo triggerInfo = ValidateTriggerId(inRule.TriggerId, RSValidationFlags.None, ioState, inContext); inContext = inContext.WithTrigger(triggerInfo); ioState.PopContext(); if (inRule.Conditions != null && inRule.Conditions.Length > 0) { for (int i = 0; i < inRule.Conditions.Length; ++i) { ioState.PushContext("Condition {0}", i); ValidateCondition(inRule.Conditions[i], ioState, inContext); ioState.PopContext(); } } if (inRule.Actions != null && inRule.Actions.Length > 0) { for (int i = 0; i < inRule.Actions.Length; ++i) { ioState.PushContext("Action {0}", i); ValidateAction(inRule.Actions[i], ioState, inContext); ioState.PopContext(); } } }
static internal void ValidateTable(RSRuleTableData inTable, RSValidationState ioState, RSValidationContext inContext) { if (inContext.Library == null) { ioState.Error("No library provided"); return; } else if (!inContext.Library.IsLoaded()) { ioState.Error("Library not fully loaded"); return; } if (inTable == null || inTable.Rules == null || inTable.Rules.Length == 0) { return; } for (int i = 0; i < inTable.Rules.Length; ++i) { ioState.PushContext("Rule {0}: {1}", i, inTable.Rules[i]?.Name); ValidateRule(inTable.Rules[i], ioState, inContext); ioState.PopContext(); } }
static private void ValidateAction(RSActionData inAction, RSValidationState ioState, RSValidationContext inContext) { ioState.PushContext("Action Id"); RSActionInfo actionInfo = ValidateActionId(inAction.Action, RSValidationFlags.None, ioState, inContext); ioState.PopContext(); ioState.PushContext("Arguments"); if (actionInfo != null) { int argCount = actionInfo.Parameters.Length; if (argCount <= 0) { if (inAction.Arguments != null && inAction.Arguments.Length > 0) { ioState.Error("Arguments provided for action {0} but none required", actionInfo.Name); } } else { if (inAction.Arguments == null) { ioState.Error("No arguments provided for action {0} but {1} required", actionInfo.Name, argCount); } else if (inAction.Arguments.Length != argCount) { ioState.Error("Argument count mismatch for action {0} - {1} required but {2} provided", actionInfo.Name, argCount, inAction.Arguments.Length); } else { for (int i = 0; i < argCount; ++i) { ValidateParameter(actionInfo.Parameters[i], inAction.Arguments[i], ioState, inContext); } } } } ioState.PopContext(); }
static private void ValidateResolvableValue(RSResolvableValueData inValue, RSTypeInfo inExpectedType, RSValidationFlags inFlags, RSValidationState ioState, RSValidationContext inContext) { bool bDisallowDirectValue = (inExpectedType == null || inExpectedType == RSBuiltInTypes.Any || inFlags.Has(RSValidationFlags.DisallowDirectValue)); switch (inValue.Mode) { case ResolvableValueMode.Argument: { ValidateTriggerArgument(inExpectedType, inFlags, ioState, inContext); break; } case ResolvableValueMode.Value: { if (bDisallowDirectValue) { ioState.Error("Cannot specify a direct value in this context"); } else { ValidateValue(inValue.Value, inExpectedType, inFlags, ioState, inContext); } break; } case ResolvableValueMode.Register: { if (inFlags.Has(RSValidationFlags.DisallowRegisters)) { ioState.Error("Cannot use a register in this context"); } break; } case ResolvableValueMode.Query: { ioState.PushContext("Query Id"); RSQueryInfo queryInfo = ValidateQueryId(inValue.Query, inExpectedType, inFlags.ForMethod(true), ioState, inContext); ioState.PopContext(); ioState.PushContext("Arguments"); if (queryInfo != null) { int argCount = queryInfo.Parameters.Length; if (argCount <= 0) { if (inValue.QueryArguments != null && inValue.QueryArguments.Length > 0) { ioState.Error("Arguments provided for action {0} but none required", queryInfo.Name); } } else { if (inValue.QueryArguments == null) { ioState.Error("No arguments provided for action {0} but {1} required", queryInfo.Name, argCount); } else if (inValue.QueryArguments.Length != argCount) { ioState.Error("Argument count mismatch for action {0} - {1} required but {2} provided", queryInfo.Name, argCount, inValue.QueryArguments.Length); } else { for (int i = 0; i < argCount; ++i) { ValidateNestedParameter(queryInfo.Parameters[i], inValue.QueryArguments[i], ioState, inContext); } } } } ioState.PopContext(); break; } } }
static private void ValidateNestedParameter(RSParameterInfo inParameterInfo, NestedValue inValue, RSValidationState ioState, RSValidationContext inContext) { ioState.PushContext("Parameter: {0}", inParameterInfo.Name); ValidateNestedValue(inValue, inParameterInfo.Type, RSValidationFlags.None.ForParameter(inParameterInfo), ioState, inContext.WithParameter(inParameterInfo)); ioState.PopContext(); }