/// <summary> /// Validates the specified node. /// </summary> /// <param name="node">The node.</param> /// <returns></returns> public static IEnumerable<NodeError> Validate(Node node) { if (node == null) { throw new ArgumentNullException("node"); } NodeSchema schema; IEnumerable<Rule> rules; if ((schema = node.NodeSchema) == null || (rules = schema.Rules) == null) { yield break; } var rulesArr = rules.Where(r => r != null && !String.IsNullOrWhiteSpace(r.Type)).ToList(); if (rulesArr.Count == 0) { yield break; } var indexOfReqRule = rulesArr.FindIndex(r => r.Type == ValidationType.Exist); if (indexOfReqRule >= 0) { var reqRule = rulesArr[indexOfReqRule]; string error; if(TryValidate(node, reqRule, out error)) { rulesArr.RemoveAll(x => x.Type == ValidationType.Exist); } else { yield return new NodeError { Message = error, Level = reqRule.Level, Type = ValidationType.Exist }; yield break; } } foreach (var rule in rulesArr) { string error; if (!TryValidate(node, rule, out error)) { yield return new NodeError { Message = error, Level = rule.Level, Type = rule.Type }; } } }
internal static bool TryValidate(Node node, Rule rule, out string error) { var cfg = node.Context.Config; bool isValid; try { var type = rule.Type; var dataType = node.NodeSchema.DataType; switch (type) { case ValidationType.Exist: isValid = ValidateRequired(node.Value, dataType, node); break; case ValidationType.Positive: isValid = ValidatePositive(node.Value, dataType); break; case ValidationType.Regex: isValid = ValidatePattern(node.Value, rule.Content); break; case ValidationType.MinSize: case ValidationType.MaxSize: int size; if (!Int32.TryParse(rule.Content, out size)) { size = 0; } isValid = ValidateSize(node, dataType, size, type == ValidationType.MaxSize); break; case ValidationType.Min: case ValidationType.Max: case ValidationType.Same: case ValidationType.Different: isValid = ValidateCompare(node, rule.Type, rule.Content); break; case ValidationType.Allow: isValid = ValidateEnumeration(node.Value, dataType, node, rule.Content, false); break; case ValidationType.DisAllow: isValid = ValidateEnumeration(node.Value, dataType, node, rule.Content, true); break; case ValidationType.Unique: isValid = ValidateUniqueNess(node, dataType, rule.Content); break; case ValidationType.Expression: isValid = ValidateExpression(rule.Content, node); break; default: var validator = node.Context.GetValidator(type); Trace.WriteLineIf(validator == null, "Validator not found for rule type:" + rule.Type); isValid = validator == null || validator.Validate(node, rule); break; } error = isValid ? rule.Message ?? Extensions.GetDefaultValidationMessage(rule.Type, cfg).FormatWith(rule.Content) : null; } catch (FormatException) { isValid = false; error = "The input value was in an incorrect format"; } catch (EvaluationException evalEx) { isValid = false; error = "Could not evaluate the rule: [{0}:{1}], ERROR: {2}".FormatWith(rule.Type, rule.Content, evalEx.Message); } catch (KeyNotFoundException kex) { isValid = false; error = "Could not evaluate the rule: [{0}:{1}], missing variable: {2}".FormatWith(rule.Type, rule.Content, kex.Data["name"]); } catch (Exception ex) { isValid = false; error = "Could not validate rule [{0}:{1}], unknown error:{2}".FormatWith(rule.Type, rule.Content, ex.Message); } return isValid; }
private static bool ValidateUniqueNess(Node node, DataType dataType, string colName) { bool result; switch (dataType) { case DataType.List: var listVal = node.Value as IEnumerable; if (listVal != null) { var ienum = listVal.Cast<object>().ToArray(); result = ienum.Distinct().Count() == ienum.Length; } else { result = true; } break; case DataType.Table: var table = node as Table; TableSchema tblSchema; if (table != null && table.Count > 0 && !String.IsNullOrWhiteSpace(colName) && (tblSchema = table.NodeSchema as TableSchema) != null && tblSchema.ContainsKey(colName)) { dynamic tblData = table.Value; var uniqueRowsCount = (tblData[colName] as IEnumerable<object>).Distinct().Count(); result = uniqueRowsCount == table.Count; } else { result = true; } break; default: result = true; break; } return result; }
private static bool ValidateSize(Node node, DataType dataType, int size, bool isMax) { bool result; var isValidsize = size >= 0; switch (dataType) { case DataType.String: var str = node.Value as string; size = isValidsize ? size : isMax ? 256 : 0; result = str == null || (isMax ? str.Length <= size : str.Length >= size); break; case DataType.List: int listSize; IList list; IEnumerable ienum; var value = node.Value; if ((list = node.Value as IList) != null) { listSize = list.Count; } else if ((ienum = value as IEnumerable) != null) { listSize = ienum.Cast<object>().Count(); } else { listSize = -1; } size = isValidsize ? size : isMax ? 32 : 0; result = listSize == -1 || (isMax ? listSize <= size : listSize >= size); break; case DataType.Table: var table = node as Table; size = isValidsize ? size : isMax ? 128 : 0; result = table == null || (isMax ? table.Count <= size : table.Count >= size); break; case DataType.Binary: var bytes = node.Value as byte[]; size = isValidsize ? size : isMax ? 1048576 : 0; result = bytes == null || (isMax ? bytes.Length <= size : bytes.Length >= size); break; default: result = true; break; } return result; }
//NOTE:type dependant private static bool ValidateRequired(object value, DataType type, Node node) { bool result; if (value == null) { result = false; } else { switch (type) { case DataType.String: result = !String.IsNullOrEmpty(value.ToString()); break; case DataType.DateTime: result = !DateTimeOffset.Equals((DateTimeOffset)value, DateTimeOffset.MinValue); break; case DataType.Guid: result = Guid.Empty != (Guid)value; break; case DataType.List: var ienum = value as IEnumerable<object>; result = ienum != null && ienum.Count() > 0; break; case DataType.Table: var container = node as Table; result = container != null && container.Count > 0; break; case DataType.Binary: var stream = value as Stream; result = stream != null && stream.Length > 0; break; default: result = true; break; } } return result; }
private static bool ValidateExpression(string expression, Node node) { return String.IsNullOrWhiteSpace(expression) || node.Evaluate<bool>(expression); }
//NOTE:type dependant private static bool ValidateEnumeration(object value, DataType type, Node node, string listStr, bool isBlackList) { bool result; if (!String.IsNullOrWhiteSpace(listStr) && value != null && type.IsPrimitive()) { var enumSchema = new FieldSchema { DataType = type }; var list = listStr.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries) .Select(x => Parsers.ParseString(x, enumSchema, node.Context)) .Where(x => x != null); var inList = list.Cast<dynamic>() .Any(x => x.Equals(value)); result = isBlackList ? !inList : inList; } else { result = true; } return result; }
private static bool ValidateCompare(Node node, string compareType, string against) { var @operator = GetCompareOperator(compareType); return @operator == null || String.IsNullOrWhiteSpace(against) || node.Evaluate<bool>("value " + @operator + "(" + against + ")"); }
private IContext ResolveContext(Node container) { return container != null ? container.Context : new DefaultContext(); }
/// <summary> /// </summary> protected virtual NodeSchema ResolveSchema(Node container) { ContainerNodeSchema containerSchema; return container != null && (containerSchema = container.NodeSchema as ContainerNodeSchema) != null ? containerSchema[Key] : null; }