/// <summary> /// Validates and returns a fact. /// /// Throws an exception if the id is not in Facts.cs or if the /// value cannot be parsed to the type specified in Facts.cs /// /// </summary> /// <param name="id"></param> /// <param name="value"></param> /// <returns></returns> private static Fact ParseFact(string id, string value) { var fact = new Fact() { Id = id }; // Validate id (must be defined in Facts.cs) var valueType = Facts.GetType(id); // Validate value (must be parsable to type specified in Facts) if (valueType == typeof(string)) { fact.Value = new StringValue(value); if (fact.Value.GetValue() == null) { throw new RulesException("Failed to parse string value"); } } else if (valueType == typeof(int)) { fact.Value = new IntValue(value); if (fact.Value.GetValue() == null) { throw new RulesException("Failed to parse int value"); } } else if (valueType == typeof(decimal)) { fact.Value = new DecimalValue(value); if (fact.Value.GetValue() == null) { throw new RulesException("Failed to parse decimal value"); } } else if (valueType == typeof(bool)) { fact.Value = new BoolValue(value); if (fact.Value.GetValue() == null) { throw new RulesException("Failed to parse bool value"); } } else { throw new RulesException("Don't know how to parse value"); } return(fact); }
private static Condition ReadCondition(YamlNode node) { // Read condition var yamlCondition = GetYamlString(node); if (yamlCondition == null) { throw new RulesException($"Expected a condition (string) but found: {node}"); } Condition.Oper?oper = null; var condition = new Condition(); // Parse condition (allow 3rd token to contain spaces) var tokens = yamlCondition.Split(" ", 3); if (tokens.Length == 1) { // Special prefixes & (IsDefined) and ! (NotDefined) if (tokens[0][0] == '&' || tokens[0][0] == '!') { oper = tokens[0][0] == '&' ? Condition.Oper.IsDefined : Condition.Oper.NotDefined; condition.Id = tokens[0].Substring(1); // Validate id (must be defined in Facts.cs) Facts.GetType(condition.Id); } else { // Boolean Combiners (And/Or) var boolOp = tokens[0].ToLower(); if (boolOp == "and") { oper = Condition.Oper.And; } else if (boolOp == "or") { oper = Condition.Oper.Or; } } } else if (tokens.Length == 3) { switch (tokens[1]) { case "==": oper = Condition.Oper.Equal; break; case "!=": oper = Condition.Oper.NotEqual; break; case "<": oper = Condition.Oper.LessThan; break; case ">": oper = Condition.Oper.GreaterThan; break; case "<=": oper = Condition.Oper.LessThanOrEqual; break; case ">=": oper = Condition.Oper.GreaterThanOrEqual; break; default: break; } try { var fact = ParseFact(tokens[0], tokens[2]); condition.Id = fact.Id; condition.Value = fact.Value; } catch (RulesException ex) { throw new RulesException($"{ex.Message} in condition: {yamlCondition}"); } } if (oper == null) { throw new RulesException($"Expected condition in format: 'AND', 'OR', '!id', 'id [==|!=|<|>|<=|>=] value' but found: {yamlCondition}"); } condition.Op = oper ?? Condition.Oper.Equal; return(condition); }