aboutsummaryrefslogtreecommitdiffstats
path: root/lib/diameter/src/compiler/diameter_make.erl
diff options
context:
space:
mode:
authorAnders Svensson <[email protected]>2013-10-04 10:57:07 +0200
committerAnders Svensson <[email protected]>2013-12-01 16:38:52 +0100
commitb4b8a2130348d8828a53303d7003e24abfc692f2 (patch)
tree955fbb5ba98a40bc938811dbd039e8d9ddfb330d /lib/diameter/src/compiler/diameter_make.erl
parent350e7e93696c4a2f553a64232b5a52f256b5c0e7 (diff)
downloadotp-b4b8a2130348d8828a53303d7003e24abfc692f2.tar.gz
otp-b4b8a2130348d8828a53303d7003e24abfc692f2.tar.bz2
otp-b4b8a2130348d8828a53303d7003e24abfc692f2.zip
Fix diameter_make:flatten/1
To set @avp_vendor_id, @codecs and @custom_types as required for imported avps.
Diffstat (limited to 'lib/diameter/src/compiler/diameter_make.erl')
-rw-r--r--lib/diameter/src/compiler/diameter_make.erl96
1 files changed, 87 insertions, 9 deletions
diff --git a/lib/diameter/src/compiler/diameter_make.erl b/lib/diameter/src/compiler/diameter_make.erl
index 411d71ba3b..99034734c5 100644
--- a/lib/diameter/src/compiler/diameter_make.erl
+++ b/lib/diameter/src/compiler/diameter_make.erl
@@ -107,19 +107,97 @@ format([?VERSION | Dict]) ->
-> parsed().
flatten([?VERSION = V | Dict]) ->
- [V | lists:foldl(fun flatten/2, Dict, [[avp_types, import_avps],
- [grouped, import_groups],
- [enum, import_enums]])].
+ [V | lists:foldl(fun flatten/2,
+ Dict,
+ [avp_vendor_id,
+ custom_types,
+ codecs,
+ [avp_types, import_avps],
+ [grouped, import_groups],
+ [enum, import_enums]])].
+
+%% ===========================================================================
+
+%% flatten/2
flatten([_,_] = Keys, Dict) ->
[Values, Imports] = [orddict:fetch(K, Dict) || K <- Keys],
- Vs = lists:append([Values | [V || {_,V} <- Imports]]),
- lists:foldl(fun store/2,
+ Vs = lists:append([Values | [V || {_Mod, V} <- Imports]]),
+ lists:foldl(fun({K,V},D) -> orddict:store(K,V,D) end,
Dict,
- lists:zip([inherits | Keys], [[], Vs, []])).
-
-store({Key, Value}, Dict) ->
- orddict:store(Key, Value, Dict).
+ lists:zip([inherits | Keys], [[], Vs, []]));
+
+%% Inherited avp's setting the 'V' flag get their value either from
+%% @avp_vendor_id in the inheriting dictionary or from @vendor in the
+%% *inherited* (not inheriting) dictionary: add the latter to
+%% @avp_vendor_id as required.
+flatten(avp_vendor_id = Key, Dict) ->
+ Def = orddict:find(vendor, Dict),
+ ModD = imports(Dict),
+ Vids = orddict:fetch(Key, Dict),
+ Avps = lists:append([As || {_,As} <- Vids]),
+ orddict:store(Key,
+ dict:fold(fun(M, As, A) -> vid(M, As -- Avps, Def, A) end,
+ Vids,
+ ModD),
+ Dict);
+
+%% Import @codecs and @custom_types from inherited dictionaries as
+%% required.
+flatten(Key, Dict) ->
+ ImportAvps = orddict:fetch(import_avps, Dict),
+ ImportItems = [{M, As}
+ || {Mod, Avps} <- ImportAvps,
+ [_|D] <- [Mod:dict()],
+ {M,As0} <- orddict:fetch(Key, D),
+ F <- [fun(A) -> lists:keymember(A, 1, Avps) end],
+ [_|_] = As <- [lists:filter(F, As0)]],
+ orddict:store(Key,
+ lists:foldl(fun merge/2,
+ orddict:fetch(Key, Dict),
+ ImportItems),
+ Dict).
+
+%% merge/2
+
+merge({Mod, _Avps} = T, Acc) ->
+ merge(lists:keyfind(Mod, 1, Acc), T, Acc).
+
+merge({Mod, Avps}, {Mod, As}, Acc) ->
+ lists:keyreplace(Mod, 1, Acc, {Mod, Avps ++ As});
+merge(false, T, Acc) ->
+ [T | Acc].
+
+%% imports/1
+%%
+%% Return a module() -> [AVP] dict of inherited AVP's setting the V flag.
+
+imports(Dict) ->
+ lists:foldl(fun imports/2,
+ dict:new(),
+ orddict:fetch(import_avps, Dict)).
+
+imports({Mod, Avps}, Dict) ->
+ dict:store(Mod,
+ [A || {A,_,_,Fs} <- Avps, lists:member($V, Fs)],
+ Dict).
+
+%% vid/4
+
+vid(_, [], _, Acc) ->
+ Acc;
+vid(Mod, Avps, Def, Acc) ->
+ v(Mod:vendor_id(), Avps, Def, Acc).
+
+v(Vid, _, {ok, {Vid, _}}, Acc) -> %% same id as inheriting dictionary's
+ Acc;
+v(Vid, Avps, _, Acc) ->
+ case lists:keyfind(Vid, 1, Acc) of
+ {Vid, As} ->
+ lists:keyreplace(Vid, 1, Acc, {Vid, As ++ Avps});
+ false ->
+ [{Vid, Avps} | Acc]
+ end.
%% ===========================================================================