Extend hope_kv_list validation API with: 2.2.0
authorSiraaj Khandkar <siraaj@khandkar.net>
Sun, 25 Jan 2015 03:33:49 +0000 (22:33 -0500)
committerSiraaj Khandkar <siraaj@khandkar.net>
Sun, 25 Jan 2015 04:38:27 +0000 (23:38 -0500)
find_unique_presence_violations, which is a subset of validate_unique_presence,
which returns a record of found violations (a list of violating keys per
violation type field), so that a user can directly match a subset of violation
types that they care about without having to search yet another list.

validate_unique_presence keeps the same signature and semantics, but is now
implemented with find_unique_presence_violations.

include/hope_kv_list.hrl [new file with mode: 0644]
src/hope.app.src
src/hope_kv_list.erl
test/hope_kv_list_SUITE.erl

diff --git a/include/hope_kv_list.hrl b/include/hope_kv_list.hrl
new file mode 100644 (file)
index 0000000..a08d7cd
--- /dev/null
@@ -0,0 +1,5 @@
+-record(hope_kv_list_presence_violations,
+    { keys_missing     :: [A]
+    , keys_duplicated  :: [A]
+    , keys_unsupported :: [A]
+    }).
index 3de6e3d..f5048f9 100644 (file)
@@ -1,7 +1,7 @@
 {application, hope,
  [
   {description, "Higher Order Programming in Erlang"},
-  {vsn, "2.1.0"},
+  {vsn, "2.2.0"},
   {registered, []},
   {applications, [
                   kernel,
index d9a8177..394e53d 100644 (file)
@@ -3,6 +3,8 @@
 %%%----------------------------------------------------------------------------
 -module(hope_kv_list).
 
+-include_lib("hope_kv_list.hrl").
+
 -behavior(hope_gen_dictionary).
 
 -export_type(
     , fold/3
     , of_kv_list/1
     , to_kv_list/1
-    , validate_unique_presence/2  % Assume default optional parameter(s)
-    , validate_unique_presence/3  % Specify optional parameter(s)
+    , find_unique_presence_violations/2  % No optional keys
+    , find_unique_presence_violations/3  % Specify optional keys
+    , validate_unique_presence/2  % No optional keys
+    , validate_unique_presence/3  % Specify optional keys
     ]).
 
 
 -type t(K, V) ::
     [{K, V}].
 
+-type presence_violations(A) ::
+    % This is a hack to effectively parametarize the types of record fields.
+    % IMPORTANT: Make sure that the order of fields matches the definition of
+    % #hope_kv_list_presence_violations
+    { hope_kv_list_presence_violations
+    , [A]  % keys_missing
+    , [A]  % keys_duplicated
+    , [A]  % keys_unsupported
+    }.
+
 -type presence_error(A) ::
       {keys_missing     , [A]}
     | {keys_duplicated  , [A]}
@@ -125,35 +139,58 @@ validate_unique_presence(T, KeysRequired) ->
 -spec validate_unique_presence(t(K, _V), [K], [K]) ->
     hope_result:t(ok, [presence_error(K)]).
 validate_unique_presence(T, KeysRequired, KeysOptional) ->
-    KeysSupported   = KeysRequired ++ KeysOptional,
-    KeysGiven       = [K || {K, _V} <- T],
-    KeysGivenUnique = lists:usort(KeysGiven),
-    KeysDups        = lists:usort(KeysGiven -- KeysGivenUnique),
-    KeysMissing     = KeysRequired -- KeysGivenUnique,
-    KeysUnsupported = KeysGivenUnique -- KeysSupported,
-    case {KeysDups, KeysMissing, KeysUnsupported}
-    of  {[], [], []} ->
+    case find_unique_presence_violations(T, KeysRequired, KeysOptional)
+    of  #hope_kv_list_presence_violations
+        { keys_missing     = []
+        , keys_duplicated  = []
+        , keys_unsupported = []
+        } ->
             {ok, ok}
-    ;   {Dups, Missing, Unsupported} ->
-            ErrorDups =
-                case Dups
+    ;   #hope_kv_list_presence_violations
+        { keys_missing     = KeysMissing
+        , keys_duplicated  = KeysDuplicated
+        , keys_unsupported = KeysUnsupported
+        } ->
+            ErrorMissing =
+                case KeysMissing
                 of  []    -> []
-                ;   [_|_] -> [{keys_duplicated, Dups}]
+                ;   [_|_] -> [{keys_missing, KeysMissing}]
                 end,
-            ErrorMissing =
-                case Missing
+            ErrorDups =
+                case KeysDuplicated
                 of  []    -> []
-                ;   [_|_] -> [{keys_missing, Missing}]
+                ;   [_|_] -> [{keys_duplicated, KeysDuplicated}]
                 end,
             ErrorUnsupported =
-                case Unsupported
+                case KeysUnsupported
                 of  []    -> []
-                ;   [_|_] -> [{keys_unsupported, Unsupported}]
+                ;   [_|_] -> [{keys_unsupported, KeysUnsupported}]
                 end,
             Errors = ErrorDups ++ ErrorMissing ++ ErrorUnsupported,
             {error, Errors}
     end.
 
+-spec find_unique_presence_violations(t(K, _V), [K]) ->
+    presence_violations(K).
+find_unique_presence_violations(T, KeysRequired) ->
+    KeysOptional = [],
+    find_unique_presence_violations(T, KeysRequired, KeysOptional).
+
+-spec find_unique_presence_violations(t(K, _V), [K], [K]) ->
+    presence_violations(K).
+find_unique_presence_violations(T, KeysRequired, KeysOptional) ->
+    KeysSupported   = KeysRequired ++ KeysOptional,
+    KeysGiven       = [K || {K, _V} <- T],
+    KeysGivenUnique = lists:usort(KeysGiven),
+    KeysDuplicated  = lists:usort(KeysGiven -- KeysGivenUnique),
+    KeysMissing     = KeysRequired -- KeysGivenUnique,
+    KeysUnsupported = KeysGivenUnique -- KeysSupported,
+    #hope_kv_list_presence_violations
+    { keys_missing     = KeysMissing
+    , keys_duplicated  = KeysDuplicated
+    , keys_unsupported = KeysUnsupported
+    }.
+
 
 %% ============================================================================
 %% Helpers
index 511fc32..3ae5290 100644 (file)
@@ -1,5 +1,7 @@
 -module(hope_kv_list_SUITE).
 
+-include_lib("hope_kv_list.hrl").
+
 %% Callbacks
 -export(
     [ all/0
@@ -40,11 +42,39 @@ t_validate_unique_presence(_Cfg) ->
     DictUnsup   = [{a, 1}, {b, 2}, {c, 3}, {d, 4}],
     DictDups    = [{a, 1}, {b, 2}, {c, 3}, {a, 4}],
     DictMissing = [{a, 1}, {b, 2}],
+
     {ok, ok} =
         hope_kv_list:validate_unique_presence(DictOk, KeysRequired),
+    #hope_kv_list_presence_violations
+    { keys_missing     = []
+    , keys_duplicated  = []
+    , keys_unsupported = []
+    } =
+        hope_kv_list:find_unique_presence_violations(DictOk, KeysRequired),
+
     {error, [{keys_unsupported, [d]}]} =
         hope_kv_list:validate_unique_presence(DictUnsup, KeysRequired),
+    #hope_kv_list_presence_violations
+    { keys_missing     = []
+    , keys_duplicated  = []
+    , keys_unsupported = [d]
+    } =
+        hope_kv_list:find_unique_presence_violations(DictUnsup, KeysRequired),
+
     {error, [{keys_duplicated, [a]}]} =
         hope_kv_list:validate_unique_presence(DictDups, KeysRequired),
+    #hope_kv_list_presence_violations
+    { keys_missing     = []
+    , keys_duplicated  = [a]
+    , keys_unsupported = []
+    } =
+        hope_kv_list:find_unique_presence_violations(DictDups, KeysRequired),
+
     {error, [{keys_missing, [c]}]} =
-        hope_kv_list:validate_unique_presence(DictMissing, KeysRequired).
+        hope_kv_list:validate_unique_presence(DictMissing, KeysRequired),
+    #hope_kv_list_presence_violations
+    { keys_missing     = [c]
+    , keys_duplicated  = []
+    , keys_unsupported = []
+    } =
+        hope_kv_list:find_unique_presence_violations(DictMissing, KeysRequired).
This page took 0.040713 seconds and 4 git commands to generate.