You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

155 rivejä
4.1 KiB

  1. %% @doc Built in operators.
  2. -module(glc_ops).
  3. -export([
  4. lt/2, lte/2,
  5. eq/2, neq/2,
  6. gt/2, gte/2,
  7. wc/1,
  8. nf/1
  9. ]).
  10. -export([
  11. all/1,
  12. any/1,
  13. null/1,
  14. with/2
  15. ]).
  16. -export([
  17. union/1
  18. ]).
  19. -type op() ::
  20. {atom(), '<', term()} |
  21. {atom(), '=<', term()} |
  22. {atom(), '=', term()} |
  23. {atom(), '!=', term()} |
  24. {atom(), '>', term()} |
  25. {atom(), '>=', term()} |
  26. {atom(), '*'} |
  27. {atom(), '!'} |
  28. {any, [op(), ...]} |
  29. {all, [op(), ...]} |
  30. {null, true|false}.
  31. -export_type([op/0]).
  32. %% @doc Test that a field value is less than a term.
  33. -spec lt(atom(), term()) -> op().
  34. lt(Key, Term) when is_atom(Key) ->
  35. {Key, '<', Term};
  36. lt(Key, Term) ->
  37. erlang:error(badarg, [Key, Term]).
  38. %% @doc Test that a field value is less than or equal to a term.
  39. -spec lte(atom(), term()) -> op().
  40. lte(Key, Term) when is_atom(Key) ->
  41. {Key, '=<', Term};
  42. lte(Key, Term) ->
  43. erlang:error(badarg, [Key, Term]).
  44. %% @doc Test that a field value is equal to a term.
  45. -spec eq(atom(), term()) -> op().
  46. eq(Key, Term) when is_atom(Key) ->
  47. {Key, '=', Term};
  48. eq(Key, Term) ->
  49. erlang:error(badarg, [Key, Term]).
  50. %% @doc Test that a field value is not equal to a term.
  51. -spec neq(atom(), term()) -> op().
  52. neq(Key, Term) when is_atom(Key) ->
  53. {Key, '!=', Term};
  54. neq(Key, Term) ->
  55. erlang:error(badarg, [Key, Term]).
  56. %% @doc Test that a field value is greater than a term.
  57. -spec gt(atom(), term()) -> op().
  58. gt(Key, Term) when is_atom(Key) ->
  59. {Key, '>', Term};
  60. gt(Key, Term) ->
  61. erlang:error(badarg, [Key, Term]).
  62. %% @doc Test that a field value is greater than or equal to a term.
  63. -spec gte(atom(), term()) -> op().
  64. gte(Key, Term) when is_atom(Key) ->
  65. {Key, '>=', Term};
  66. gte(Key, Term) ->
  67. erlang:error(badarg, [Key, Term]).
  68. %% @doc Test that a field exists.
  69. -spec wc(atom()) -> op().
  70. wc(Key) when is_atom(Key) ->
  71. {Key, '*'};
  72. wc(Key) ->
  73. erlang:error(badarg, [Key]).
  74. %% @doc Test that a field is not found.
  75. -spec nf(atom()) -> op().
  76. nf(Key) when is_atom(Key) ->
  77. {Key, '!'};
  78. nf(Key) ->
  79. erlang:error(badarg, [Key]).
  80. %% @doc Filter the input using multiple filters.
  81. %%
  82. %% For an input to be considered valid output the all filters specified
  83. %% in the list must hold for the input event. The list is expected to
  84. %% be a non-empty list. If the list of filters is an empty list a `badarg'
  85. %% error will be thrown.
  86. -spec all([op()]) -> op().
  87. all([_|_]=Conds) ->
  88. {all, Conds};
  89. all(Other) ->
  90. erlang:error(badarg, [Other]).
  91. %% @doc Filter the input using one of multiple filters.
  92. %%
  93. %% For an input to be considered valid output on of the filters specified
  94. %% in the list must hold for the input event. The list is expected to be
  95. %% a non-empty list. If the list of filters is an empty list a `badarg'
  96. %% error will be thrown.
  97. -spec any([op()]) -> op().
  98. any([_|_]=Conds) ->
  99. {any, Conds};
  100. any(Other) ->
  101. erlang:error(badarg, [Other]).
  102. %% @doc Always return `true' or `false'.
  103. -spec null(boolean()) -> op().
  104. null(Result) when is_boolean(Result) ->
  105. {null, Result};
  106. null(Result) ->
  107. erlang:error(badarg, [Result]).
  108. %% @doc Apply a function to each output of a query.
  109. %%
  110. %% Updating the output action of a query finalizes it. Attempting
  111. %% to use a finalized query to construct a new query will result
  112. %% in a `badarg' error.
  113. -spec with(op(), fun((gre:event()) -> term())) -> op().
  114. with(Query, Fun) when is_function(Fun, 1);
  115. is_function(Fun, 2) ->
  116. {with, Query, Fun};
  117. with(Query, Fun) ->
  118. erlang:error(badarg, [Query, Fun]).
  119. %% @doc Return a union of multiple queries.
  120. %%
  121. %% The union of multiple queries is the equivalent of executing multiple
  122. %% queries separately on the same input event. The advantage is that filter
  123. %% conditions that are common to all or some of the queries only need to
  124. %% be tested once.
  125. %%
  126. %% All queries are expected to be valid and have an output action other
  127. %% than the default which is `output'. If these expectations don't hold
  128. %% a `badarg' error will be thrown.
  129. -spec union([op()]) -> op().
  130. union(Queries) ->
  131. case [Query || Query <- Queries, glc_lib:onoutput(Query) =:= output] of
  132. [] -> {union, Queries};
  133. [_|_] -> erlang:error(badarg, [Queries])
  134. end.