mirror of
https://github.com/valitydev/openapi-generator.git
synced 2024-11-06 02:25:20 +00:00
parent
5b9e7db104
commit
69f37cea0b
@ -10,108 +10,81 @@
|
||||
|
||||
-spec get() -> {{packageName}}:object().
|
||||
get() ->
|
||||
ct_expand:term(enumerate_components(maps:with([?COMPONENTS], load_raw()))).
|
||||
ct_expand:term(enumerate_components(load_raw())).
|
||||
|
||||
-spec enumerate_components(Schema :: map()) ->
|
||||
Schema :: map() | no_return().
|
||||
enumerate_components(Schema = #{?COMPONENTS := Components}) ->
|
||||
%@NOTICE only parents within the same component type are supported
|
||||
Schema#{?COMPONENTS => maps:map(fun enumerate_discriminator_children/2, Components)};
|
||||
Schema#{?COMPONENTS => enumerate_discriminator_children(Components)};
|
||||
enumerate_components(Schema) ->
|
||||
Schema.
|
||||
|
||||
-spec enumerate_discriminator_children(ComponentType :: binary(), Schema :: map()) ->
|
||||
%% When using the discriminator, inline schemas will not be considered.
|
||||
-spec enumerate_discriminator_children(Schema :: map()) ->
|
||||
Schema :: map() | no_return().
|
||||
enumerate_discriminator_children(_ComponentType, Defs) ->
|
||||
enumerate_discriminator_children(#{<<"schemas">> := Defs}) ->
|
||||
try
|
||||
{Parents, _} = maps:fold(
|
||||
fun(Name, Schema, Acc) ->
|
||||
check_definition(Name, Schema, Acc)
|
||||
end,
|
||||
{#{}, #{}},
|
||||
Defs
|
||||
),
|
||||
maps:fold(
|
||||
fun(Parent, Children, Schema) ->
|
||||
correct_schema(Parent, Children, Schema)
|
||||
end,
|
||||
Defs,
|
||||
Parents
|
||||
)
|
||||
maps:fold(fun correct_schema/3, Defs, build_hier(Defs))
|
||||
catch
|
||||
_:Error ->
|
||||
handle_error(Error)
|
||||
end.
|
||||
end;
|
||||
enumerate_discriminator_children(Schema) ->
|
||||
Schema.
|
||||
|
||||
-spec handle_error(_) ->
|
||||
no_return().
|
||||
handle_error(Error) ->
|
||||
erlang:error({schema_invalid, Error}).
|
||||
|
||||
check_definition(Name, Schema, Acc) ->
|
||||
Acc1 = check_discriminator(Name, Schema, Acc),
|
||||
check_backrefs(Name, Schema, Acc1).
|
||||
build_hier(Defs) ->
|
||||
F = fun
|
||||
(Name, #{<<"discriminator">> := _Type}, Acc) ->
|
||||
insert_parent(Name, Acc);
|
||||
|
||||
check_discriminator(Name, Schema, {Parents, Candidates}) ->
|
||||
case maps:get(<<"discriminator">>, Schema, undefined) of
|
||||
undefined ->
|
||||
{Parents, Candidates};
|
||||
_ ->
|
||||
{
|
||||
Parents#{Name => maps:get(Name, Candidates, [])},
|
||||
maps:without([Name], Candidates)
|
||||
}
|
||||
end.
|
||||
(Name, #{<<"allOf">> := Props}, Acc) ->
|
||||
lists:foldl(
|
||||
fun
|
||||
(#{<<"$ref">> := <<"#/components/schemas/", Type/binary>>}, Hier) ->
|
||||
%% check: whether type itself exists
|
||||
%% TODO: Implement according to OAS3:
|
||||
%% In scenarios where the value of the discriminator field does not match
|
||||
%% the schema name or implicit mapping is not possible, an optional mapping
|
||||
%% definition MAY be used.
|
||||
Schema = maps:get(Type, Defs),
|
||||
Discriminator = maps:get(<<"discriminator">>, Schema, undefined),
|
||||
insert_child(Discriminator, Type, Name, Hier);
|
||||
|
||||
check_backrefs(Name, Schema, Acc) ->
|
||||
case maps:get(<<"allOf">>, Schema, undefined) of
|
||||
undefined ->
|
||||
Acc;
|
||||
AllOf ->
|
||||
lists:foldl(fun(E, A) -> check_allOf(E, Name, A) end, Acc, AllOf)
|
||||
end.
|
||||
(_, Hier) ->
|
||||
Hier
|
||||
end,
|
||||
Acc,
|
||||
Props
|
||||
)
|
||||
end,
|
||||
maps:fold(F, #{}, Defs).
|
||||
|
||||
check_allOf(#{<<"$ref">> := RefPath}, Child, {Parents, Candidates}) ->
|
||||
Parent = get_parent_from_ref(RefPath),
|
||||
case maps:get(Parent, Parents, undefined) of
|
||||
undefined ->
|
||||
{Parents, update_candidates(Parent, Child, Candidates)};
|
||||
Children ->
|
||||
{Parents#{Parent => [Child | Children]}, Candidates}
|
||||
end;
|
||||
check_allOf(_, _, Acc) ->
|
||||
Acc.
|
||||
insert_parent(Parent, Hier) when not is_map_key(Parent, Hier) ->
|
||||
Hier#{Parent => []};
|
||||
insert_parent(_, Hier) ->
|
||||
Hier.
|
||||
|
||||
get_parent_from_ref(RefPath) ->
|
||||
Split = binary:split(RefPath, [<<"/">>], [global]),
|
||||
lists:last(Split).
|
||||
|
||||
update_candidates(Parent, Child, Candidates) ->
|
||||
case maps:get(Parent, Candidates, undefined) of
|
||||
undefined ->
|
||||
Candidates#{Parent => [Child]};
|
||||
Children ->
|
||||
Candidates#{Parent => [Child | Children]}
|
||||
end.
|
||||
insert_child(undefined, _Parent, _Child, Hier) ->
|
||||
Hier;
|
||||
insert_child(_Discriminator, Parent, Child, Hier) ->
|
||||
maps:put(Parent, [Child | maps:get(Parent, Hier, [])], Hier).
|
||||
|
||||
correct_schema(Parent, Children, Schema) ->
|
||||
BasePath = [Parent],
|
||||
Discr = maps:get(<<"discriminator">>, get_sub_schema(BasePath, Schema)),
|
||||
PropertyName = maps:get(<<"propertyName">>, Discr),
|
||||
update_schema(Children, [<<"enum">>, PropertyName, <<"properties">> | BasePath], Schema).
|
||||
PropertyName = get_sub_schema([Parent, <<"discriminator">>, <<"propertyName">>], Schema),
|
||||
update_schema([Parent, <<"properties">>, PropertyName, <<"enum">>], Children, Schema).
|
||||
|
||||
update_schema(Value, [], _Schema) ->
|
||||
Value;
|
||||
update_schema(Value, [Key | Path], Schema) ->
|
||||
SubSchema0 = get_sub_schema(Path, Schema),
|
||||
SubSchema1 = update_sub_schema(Key, Value, SubSchema0),
|
||||
update_schema(SubSchema1, Path, Schema).
|
||||
update_schema([Key], Value, Schema) ->
|
||||
Schema#{Key => Value};
|
||||
update_schema([Key | Path], Value, Schema) ->
|
||||
maps:put(Key, update_schema(Path, Value, maps:get(Key, Schema)), Schema).
|
||||
|
||||
get_sub_schema(ReversedPath, Schema) ->
|
||||
lists:foldr(fun(K, S) -> maps:get(K, S) end, Schema, ReversedPath).
|
||||
|
||||
update_sub_schema(Key, Value, Schema) ->
|
||||
Schema#{Key => Value}.
|
||||
get_sub_schema(Path, Schema) ->
|
||||
lists:foldl(fun maps:get/2, Schema, Path).
|
||||
|
||||
-spec get_raw() -> map().
|
||||
get_raw() ->
|
||||
@ -215,7 +188,7 @@ get_openapi_path() ->
|
||||
}}">>).
|
||||
|
||||
get_enum(Parent, Discr, ComponentType, Schema) ->
|
||||
lists:sort(get_sub_schema([<<"enum">>, Discr, <<"properties">>, Parent, ComponentType, ?COMPONENTS], Schema)).
|
||||
lists:sort(get_sub_schema([?COMPONENTS, ComponentType, Parent, <<"properties">>, Discr, <<"enum">>], Schema)).
|
||||
|
||||
-spec test() -> _.
|
||||
-spec enumerate_discriminator_children_test() -> _.
|
||||
@ -223,16 +196,16 @@ enumerate_discriminator_children_test() ->
|
||||
Schema = jsx:decode(?SCHEMA, [return_maps]),
|
||||
FixedSchema = enumerate_components(Schema),
|
||||
?assertEqual(
|
||||
lists:sort([<<"Dog">>, <<"Cat">>, <<"WildMix">>]),
|
||||
[<<"Cat">>, <<"Dog">>, <<"WildMix">>],
|
||||
get_enum(<<"Pet">>, <<"petType">>, <<"schemas">>, FixedSchema)
|
||||
),
|
||||
?assertEqual([<<"WildMix">>], get_enum(<<"Person">>, <<"personType">>, <<"schemas">>, FixedSchema)),
|
||||
?assertEqual([], get_enum(<<"Dummy">>, <<"dummyType">>, <<"schemas">>, FixedSchema)).
|
||||
?assertEqual([<<"WildMix">>], get_enum(<<"Person">>, <<"personType">>, <<"schemas">>, FixedSchema)),
|
||||
?assertEqual([], get_enum(<<"Dummy">>, <<"dummyType">>, <<"schemas">>, FixedSchema)).
|
||||
|
||||
-spec get_test() -> _.
|
||||
get_test() ->
|
||||
?assertEqual(
|
||||
enumerate_components(maps:with([?COMPONENTS], get_raw())),
|
||||
enumerate_components(get_raw()),
|
||||
?MODULE:get()
|
||||
).
|
||||
-endif.
|
||||
|
Loading…
Reference in New Issue
Block a user