From 07bafff0514c29696bccd649a27591b4f6cb1fd2 Mon Sep 17 00:00:00 2001 From: Luis Azedo Date: Sun, 21 May 2017 23:18:56 +0200 Subject: [PATCH] allow extra validator this will extra validations for schema elements example : lookup some value in a database an provide an error --- src/jesse_schema_validator.hrl | 2 +- src/jesse_state.erl | 13 +++++++++++++ src/jesse_validator_draft3.erl | 16 +++++++++++++--- src/jesse_validator_draft4.erl | 15 ++++++++++++--- 4 files changed, 39 insertions(+), 7 deletions(-) diff --git a/src/jesse_schema_validator.hrl b/src/jesse_schema_validator.hrl index 15919940..0d0d7795 100644 --- a/src/jesse_schema_validator.hrl +++ b/src/jesse_schema_validator.hrl @@ -114,7 +114,7 @@ -define(not_one_schema_valid, 'not_one_schema_valid'). -define(not_schema_valid, 'not_schema_valid'). -define(wrong_not_schema, 'wrong_not_schema'). --define(external_error, 'external_error'). +-define(external, 'external'). %% -define(not_found, not_found). diff --git a/src/jesse_state.erl b/src/jesse_state.erl index 875ae3b6..eaced1ed 100644 --- a/src/jesse_state.erl +++ b/src/jesse_state.erl @@ -26,6 +26,7 @@ %% API -export([ add_to_path/2 , get_allowed_errors/1 + , get_external_validator/1 , get_current_path/1 , get_current_schema/1 , get_current_schema_id/1 @@ -68,10 +69,14 @@ jesse:json_term() | ?not_found ) + , external_validator :: external_validator() , id :: http_uri:uri() | 'undefined' } ). +-type external_validator() :: fun((jesse:json_term(), state()) -> state()) + | undefined. + -opaque state() :: #state{}. %%% API @@ -148,6 +153,9 @@ new(JsonSchema, Options) -> , Options , ?default_schema_loader_fun ), + ExternalValidator = proplists:get_value( external_validator + , Options + ), NewState = #state{ root_schema = JsonSchema , current_path = [] , allowed_errors = AllowedErrors @@ -155,6 +163,7 @@ new(JsonSchema, Options) -> , error_handler = ErrorHandler , default_schema_ver = DefaultSchemaVer , schema_loader_fun = LoaderFun + , external_validator = ExternalValidator }, set_current_schema(NewState, JsonSchema). @@ -385,3 +394,7 @@ load_schema(#state{schema_loader_fun = LoaderFun}, SchemaURI) -> %% io:format("load_schema: ~p\n", [{_C, _E, erlang:get_stacktrace()}]), ?not_found end. + +%% @private +get_external_validator(#state{external_validator = Fun}) -> + Fun. diff --git a/src/jesse_validator_draft3.erl b/src/jesse_validator_draft3.erl index 6aecb65d..7a2b4ed2 100644 --- a/src/jesse_validator_draft3.erl +++ b/src/jesse_validator_draft3.erl @@ -48,7 +48,8 @@ | ?not_in_range | ?wrong_length | ?wrong_size - | ?wrong_type. + | ?wrong_type + | ?external. -type data_error_type() :: data_error() | {data_error(), binary()}. @@ -209,11 +210,11 @@ check_value(Value, [{?DISALLOW, Disallow} | Attrs], State) -> check_value(Value, [{?EXTENDS, Extends} | Attrs], State) -> NewState = check_extends(Value, Extends, State), check_value(Value, Attrs, NewState); -check_value(_Value, [], State) -> - State; check_value(Value, [{?REF, RefSchemaURI} | Attrs], State) -> NewState = validate_ref(Value, RefSchemaURI, State), check_value(Value, Attrs, NewState); +check_value(Value, [], State) -> + maybe_external_check_value(Value, State); check_value(Value, [_Attr | Attrs], State) -> check_value(Value, Attrs, State). @@ -1031,3 +1032,12 @@ add_to_path(State, Property) -> %% @private remove_last_from_path(State) -> jesse_state:remove_last_from_path(State). + +%% @private +maybe_external_check_value(Value, State) -> + case jesse_state:get_external_validator(State) of + undefined -> + State; + Fun -> + Fun(Value, State) + end. diff --git a/src/jesse_validator_draft4.erl b/src/jesse_validator_draft4.erl index e8bbc12e..49c77903 100644 --- a/src/jesse_validator_draft4.erl +++ b/src/jesse_validator_draft4.erl @@ -65,7 +65,8 @@ | ?too_many_properties | ?wrong_length | ?wrong_size - | ?wrong_type. + | ?wrong_type + | ?external. -type data_error_type() :: data_error() | {data_error(), binary()}. @@ -246,11 +247,11 @@ check_value(Value, [{?ONEOF, Schemas} | Attrs], State) -> check_value(Value, [{?NOT, Schema} | Attrs], State) -> NewState = check_not(Value, Schema, State), check_value(Value, Attrs, NewState); -check_value(_Value, [], State) -> - State; check_value(Value, [{?REF, RefSchemaURI} | Attrs], State) -> NewState = validate_ref(Value, RefSchemaURI, State), check_value(Value, Attrs, NewState); +check_value(Value, [], State) -> + maybe_external_check_value(Value, State); check_value(Value, [_Attr | Attrs], State) -> check_value(Value, Attrs, State). @@ -1362,3 +1363,11 @@ valid_datetime(DateTimeBin) -> _ -> false end. + +maybe_external_check_value(Value, State) -> + case jesse_state:get_external_validator(State) of + undefined -> + State; + Fun -> + Fun(Value, State) + end.