| %% @doc Built in operators. |
| -module(glc_ops). |
| |
| -export([ |
| lt/2, |
| eq/2, |
| gt/2, |
| wc/1, |
| nf/1 |
| ]). |
| |
| -export([ |
| all/1, |
| any/1, |
| null/1, |
| with/2 |
| ]). |
| |
| -export([ |
| union/1 |
| ]). |
| |
| -type op() :: |
| {atom(), '<', term()} | |
| {atom(), '=', term()} | |
| {atom(), '>', term()} | |
| {atom(), '*'} | |
| {atom(), '!'} | |
| {any, [op(), ...]} | |
| {all, [op(), ...]} | |
| {null, true|false}. |
| |
| -export_type([op/0]). |
| |
| %% @doc Test that a field value is less than a term. |
| -spec lt(atom(), term()) -> op(). |
| lt(Key, Term) when is_atom(Key) -> |
| {Key, '<', Term}; |
| lt(Key, Term) -> |
| erlang:error(badarg, [Key, Term]). |
| |
| %% @doc Test that a field value is equal to a term. |
| -spec eq(atom(), term()) -> op(). |
| eq(Key, Term) when is_atom(Key) -> |
| {Key, '=', Term}; |
| eq(Key, Term) -> |
| erlang:error(badarg, [Key, Term]). |
| |
| %% @doc Test that a field value is greater than a term. |
| -spec gt(atom(), term()) -> op(). |
| gt(Key, Term) when is_atom(Key) -> |
| {Key, '>', Term}; |
| gt(Key, Term) -> |
| erlang:error(badarg, [Key, Term]). |
| |
| %% @doc Test that a field exists. |
| -spec wc(atom()) -> op(). |
| wc(Key) when is_atom(Key) -> |
| {Key, '*'}; |
| wc(Key) -> |
| erlang:error(badarg, [Key]). |
| |
| %% @doc Test that a field is not found. |
| -spec nf(atom()) -> op(). |
| nf(Key) when is_atom(Key) -> |
| {Key, '!'}; |
| nf(Key) -> |
| erlang:error(badarg, [Key]). |
| |
| %% @doc Filter the input using multiple filters. |
| %% |
| %% For an input to be considered valid output the all filters specified |
| %% in the list must hold for the input event. The list is expected to |
| %% be a non-empty list. If the list of filters is an empty list a `badarg' |
| %% error will be thrown. |
| -spec all([op()]) -> op(). |
| all([_|_]=Conds) -> |
| {all, Conds}; |
| all(Other) -> |
| erlang:error(badarg, [Other]). |
| |
| %% @doc Filter the input using one of multiple filters. |
| %% |
| %% For an input to be considered valid output on of the filters specified |
| %% in the list must hold for the input event. The list is expected to be |
| %% a non-empty list. If the list of filters is an empty list a `badarg' |
| %% error will be thrown. |
| -spec any([op()]) -> op(). |
| any([_|_]=Conds) -> |
| {any, Conds}; |
| any(Other) -> |
| erlang:error(badarg, [Other]). |
| |
| |
| %% @doc Always return `true' or `false'. |
| -spec null(boolean()) -> op(). |
| null(Result) when is_boolean(Result) -> |
| {null, Result}; |
| null(Result) -> |
| erlang:error(badarg, [Result]). |
| |
| %% @doc Apply a function to each output of a query. |
| %% |
| %% Updating the output action of a query finalizes it. Attempting |
| %% to use a finalized query to construct a new query will result |
| %% in a `badarg' error. |
| -spec with(op(), fun((gre:event()) -> term())) -> op(). |
| with(Query, Fun) when is_function(Fun, 1) -> |
| {with, Query, Fun}; |
| with(Query, Fun) -> |
| erlang:error(badarg, [Query, Fun]). |
| |
| %% @doc Return a union of multiple queries. |
| %% |
| %% The union of multiple queries is the equivalent of executing multiple |
| %% queries separately on the same input event. The advantage is that filter |
| %% conditions that are common to all or some of the queries only need to |
| %% be tested once. |
| %% |
| %% All queries are expected to be valid and have an output action other |
| %% than the default which is `output'. If these expectations don't hold |
| %% a `badarg' error will be thrown. |
| -spec union([op()]) -> op(). |
| union(Queries) -> |
| case [Query || Query <- Queries, glc_lib:onoutput(Query) =:= output] of |
| [] -> {union, Queries}; |
| [_|_] -> erlang:error(badarg, [Queries]) |
| end. |