예제 #1
0
파일: Validator.cs 프로젝트: yutopp/VJson
        internal ConstraintsViolationException Validate(object o, State state, JsonSchemaRegistory reg)
        {
            if (_schema.Ref != null)
            {
                if (reg == null)
                {
                    reg = JsonSchemaRegistory.GetDefault();
                }
                var schema = reg.Resolve(_schema.Ref);
                if (schema == null)
                {
                    // TODO:
                    throw new NotSupportedException();
                }
                return(schema.Validate(o, state, reg));
            }

            ConstraintsViolationException ex = null;

            if (o is INode)
            {
                // unwrap INode
                return(Validate((o as INode).GenericContent, state, reg));
            }
            var kind = Node.KindOfValue(o);

            if (_schema.Type != null)
            {
                if (_schema.Type.GetType().IsArray)
                {
                    var ts    = (string[])_schema.Type;
                    var found = false;
                    foreach (var t in ts)
                    {
                        if (ValidateKind(kind, t))
                        {
                            found = true;
                            break;
                        }
                    }
                    if (!found)
                    {
                        var actual   = kind.ToString();
                        var expected = String.Join(", ", ts);
                        var msg      = state.CreateMessage("Type is not contained(Actual: {0}; Expected: [{1}])",
                                                           actual, expected);
                        return(new ConstraintsViolationException(msg));
                    }
                }
                else
                {
                    var t = (string)_schema.Type;
                    if (!ValidateKind(kind, t))
                    {
                        var actual   = kind.ToString();
                        var expected = t.ToString();
                        var msg      = state.CreateMessage("Type is not matched(Actual: {0}; Expected: {1})",
                                                           actual, expected);
                        return(new ConstraintsViolationException(msg));
                    }
                }
            }

            if (_schema.Enum != null)
            {
                var oEnum = o;
                if (o != null && TypeHelper.TypeWrap(o.GetType()).IsEnum&& kind == NodeKind.String)
                {
                    oEnum = TypeHelper.GetStringEnumNameOf(o);
                }

                var found = false;
                foreach (var e in _schema.Enum)
                {
                    if (TypeHelper.DeepEquals(oEnum, e))
                    {
                        found = true;
                        break;
                    }
                }
                if (!found)
                {
                    var msg = state.CreateMessage("Enum is not matched");
                    return(new ConstraintsViolationException(msg));
                }
            }

            if (_schema.Not != null)
            {
                ex = _schema.Not.Validate(o, state, reg);
                if (ex == null)
                {
                    var msg = state.CreateMessage("Not");
                    return(new ConstraintsViolationException(msg));
                }
            }

            if (_schema.AllOf != null)
            {
                var i = 0;
                foreach (var jsonSchema in _schema.AllOf)
                {
                    ex = jsonSchema.Validate(o, state, reg);
                    if (ex != null)
                    {
                        var msg = state.CreateMessage("AllOf[{0}] is failed", i);
                        return(new ConstraintsViolationException(msg, ex));
                    }

                    ++i;
                }
            }

            if (_schema.AnyOf != null)
            {
                var schemaChecked = false;
                foreach (var jsonSchema in _schema.AnyOf)
                {
                    ex = jsonSchema.Validate(o, state, reg);
                    if (ex == null)
                    {
                        schemaChecked = true;
                        break;
                    }
                }
                if (!schemaChecked)
                {
                    var msg = state.CreateMessage("None of AnyOf is matched");
                    return(new ConstraintsViolationException(msg));
                }
            }

            if (_schema.OneOf != null)
            {
                var checkedI = -1;
                var i        = 0;
                foreach (var jsonSchema in _schema.OneOf)
                {
                    ex = jsonSchema.Validate(o, state, reg);
                    if (ex == null)
                    {
                        if (checkedI != -1)
                        {
                            var msg = state.CreateMessage("Both of OneOf[{0}] and OneOf[{1}] are matched", checkedI, i);
                            return(new ConstraintsViolationException(msg));
                        }

                        checkedI = i;
                    }

                    ++i;
                }
                if (checkedI == -1)
                {
                    var msg = state.CreateMessage("None of AnyOf is matched");
                    return(new ConstraintsViolationException(msg));
                }
            }

            switch (kind)
            {
            case NodeKind.Boolean:
                break;

            case NodeKind.Float:
            case NodeKind.Integer:
                ex = ValidateNumber(Convert.ToDouble(o), state, reg);

                if (ex != null)
                {
                    return(new ConstraintsViolationException("Number", ex));
                }
                break;

            case NodeKind.String:
                var oConverted =
                    (o != null && TypeHelper.TypeWrap(o.GetType()).IsEnum)
                        ? TypeHelper.GetStringEnumNameOf(o)
                        : (string)o;

                ex = ValidateString(oConverted, state, reg);
                if (ex != null)
                {
                    return(new ConstraintsViolationException("String", ex));
                }
                break;

            case NodeKind.Array:
                ex = ValidateArray(TypeHelper.ToIEnumerable(o), state, reg);
                if (ex != null)
                {
                    return(new ConstraintsViolationException("Array", ex));
                }
                break;

            case NodeKind.Object:
                ex = ValidateObject(o, state, reg);
                if (ex != null)
                {
                    return(new ConstraintsViolationException("Object", ex));
                }
                break;

            case NodeKind.Null:
                break;

            default:
                throw new NotImplementedException(kind.ToString());
            }

            return(null);
        }