%%--------------------------------------------------------------------
%%
%% %CopyrightBegin%
%%
%% Copyright Ericsson AB 1999-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
%% You may obtain a copy of the License at
%%
%% http://www.apache.org/licenses/LICENSE-2.0
%%
%% Unless required by applicable law or agreed to in writing, software
%% distributed under the License is distributed on an "AS IS" BASIS,
%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
%% See the License for the specific language governing permissions and
%% limitations under the License.
%%
%% %CopyrightEnd%
%%
%%
%%----------------------------------------------------------------------
%% File : CosNotifyFilter_Filter_impl.erl
%% Purpose :
%% Note : For an event to be forwarded it's sufficient that at least
%% one of the constraints return 'true'.
%% ALL functions in this module are internal. May NOT be used
%% externally in ANY WAY; only CosNotification system modules.
%%----------------------------------------------------------------------
-module('CosNotifyFilter_Filter_impl').
%%--------------- INCLUDES -----------------------------------
%% Application files
-include_lib("orber/include/corba.hrl").
-include_lib("orber/include/ifr_types.hrl").
%% Application files
-include("CosNotification.hrl").
-include("CosNotifyChannelAdmin.hrl").
-include("CosNotifyComm.hrl").
-include("CosNotifyFilter.hrl").
-include("CosNotification_Definitions.hrl").
%%--------------- IMPORTS ------------------------------------
%%--------------- EXPORTS ------------------------------------
%% External Attributes
-export(['_get_constraint_grammar'/2]).
%% External Functions
-export([add_constraints/3,
modify_constraints/4,
get_constraints/3,
get_all_constraints/2,
remove_all_constraints/2,
destroy/2,
match/3,
match_structured/3,
match_typed/3,
attach_callback/3,
detach_callback/3,
get_callbacks/2]).
%%--------------- gen_server specific exports ----------------
-export([handle_info/2, code_change/3]).
-export([init/1, terminate/2]).
%%--------------- LOCAL DEFINITIONS --------------------------
%%######### MISC ##########
-define(create_ConstraintInfo(_Types, _Con, _ID),
#'CosNotifyFilter_ConstraintInfo'{
constraint_expression =
#'CosNotifyFilter_ConstraintExp'{
event_types = _Types,
constraint_expr = _Con},
constraint_id = _ID
}).
%%#### Data structures ####
-record(state, {constraint_grammar,
constraints = [],
filters = [],
callbacks = [],
idCounter = 0,
filterFactory,
factoryPid,
etsR}).
%% Data structures constructors
-define(get_InitState(Fac, Pid, Gr),
#state{constraint_grammar=Gr,
filterFactory=Fac,
factoryPid=Pid,
etsR = ets:new(oe_ets, [bag, protected])}).
%%------------------- Data structures selectors -------------------
%% Grammar
-define(get_Grammar(S), S#state.constraint_grammar).
%% Callbacks
% Left out for now to avoid dialyzer warning.
%-define(get_Callback(S,I), find_obj(lists:keysearch(I, 1, S#state.callbacks),
% callback)).
-define(get_AllCallback(S), lists:map(fun({_V, C}) -> C end,
S#state.callbacks)).
-define(get_AllCallbackID(S), lists:map(fun({V, _C}) -> V end,
S#state.callbacks)).
%% ID:s
-define(get_IdCounter(S), S#state.idCounter).
%% Constraints
-define(get_Constraint(S,I), find_obj(lists:keysearch(I, 1, S#state.constraints),
constraint)).
-define(get_AllConstraints(S), lists:map(fun({I, C, _W, _WC, _K, T}) ->
?create_ConstraintInfo(T, C, I)
end,
S#state.constraints)).
-define(get_ConstraintAllData(S), S#state.constraints).
-define(get_ConstraintData(S,I), lists:keysearch(I, 1, S#state.constraints)).
-define(match_Type(S,I,ET), ets:lookup(S#state.etsR, {I, ET})).
%% Parse Tree
-define(get_ParseTree(S,K), find_obj(ets:lookup(S#state.etsR, K), tree)).
%%------------------- Data structures modifiers -------------------
%% Callbacks
-define(del_Callback(S,I), S#state{callbacks =
delete_obj(lists:keydelete(I,1,
S#state.callbacks),
S#state.callbacks, callback)}).
-define(del_AllCallbacks(S), S#state{callbacks=[]}).
-define(add_Callback(S,V,C), S#state{idCounter=V,
callbacks = [{V,C}|S#state.callbacks]}).
%% ID:s
-define(set_IdCounter(S,V), S#state{idCounter=V}).
-define(new_Id(S), 'CosNotification_Common':create_id(S#state.idCounter)).
%% Constraints
-define(del_Constraint(S, I), match_delete(S, S#state.constraints, I)).
-define(del_AllConstraints(S), clear_DB(S)).
-define(add_Constraint(S,I,C,W,_WC,K,T), S#state{constraints =
[{I, C, W, _WC, K, T}|S#state.constraints]}).
-define(set_Constraints(S,C), S#state{constraints = C}).
-define(del_AllTypes(S), ets:match_delete(S#state.etsR, {'_','_',types})).
-define(del_Type(S,I), ets:match_delete(S#state.etsR, {{I, '_'}, '_', types})).
-define(add_Type(S,I,ET,K), ets:insert(S#state.etsR, {{I, ET}, K, types})).
%% Parse Tree
-define(add_ParseTree(S,K,T), ets:insert(S#state.etsR, {K, T, tree})).
-define(del_ParseTree(S,K), ets:delete(S#state.etsR, K)).
-define(del_AllParseTress(S), ets:match_delete(S#state.etsR, {'_','_',tree})).
%%------------------- MISC ----------------------------------------
-define(is_EmptyFilter(S), S#state.constraints==[]).
-define(InfoSeq2EventTypeSeq(L), lists:flatten(
lists:map(fun(#'CosNotifyFilter_ConstraintInfo'
{constraint_expression=
#'CosNotifyFilter_ConstraintExp'
{event_types = ET}}) ->
ET
end,
L))).
%%-----------------------------------------------------------%
%% Function : handle_info, code_change
%% Arguments: See gen_server documentation.
%% Effect : Functions demanded by the gen_server module.
%%------------------------------------------------------------
code_change(_OldVsn, State, _Extra) ->
{ok, State}.
handle_info(Info, State) ->
?debug_print("INFO: ~p DATA: ~p~n", [State, Info]),
case Info of
{'EXIT', _Pid, _Reason} ->
{noreply, State};
_ ->
{noreply, State}
end.
%%----------------------------------------------------------%
%% Function : init, terminate
%% Arguments:
%%-----------------------------------------------------------
init([FiFac, FacPid, ConstraintGr]) ->
process_flag(trap_exit, true),
{ok, ?get_InitState(FiFac, FacPid, ConstraintGr)}.
terminate(_Reason, _State) ->
ok.
%%-----------------------------------------------------------
%%------- Exported external attributes ----------------------
%%-----------------------------------------------------------
%%----------------------------------------------------------%
%% Function : '_get_constraint_grammar'/2
%% Type : readonly
%% Returns : Grammar - string()
%%-----------------------------------------------------------
'_get_constraint_grammar'(_OE_THIS, State) ->
{reply, ?get_Grammar(State), State}.
%%-----------------------------------------------------------
%%------- Exported external functions -----------------------
%%-----------------------------------------------------------
%%----------------------------------------------------------%
%% Function : add_constraints/3
%% Arguments: CL - CosNotifyFilter::ConstraintExpSeq
%% Returns : CosNotifyFilter::ConstraintInfoSeq |
%% {'EXCEPTION', CosNotifyFilter::InvalidConstraint}
%%-----------------------------------------------------------
add_constraints(_OE_THIS, State, CL) ->
{NewState, Filters, Info, EventTSeq} = try_create_filters(State, CL),
NewState2=store_filters(NewState, Filters),
inform_callbacks(?get_AllCallback(NewState2), EventTSeq, []),
{reply, Info, NewState2}.
%%----------------------------------------------------------%
%% Function : modify_constraints/4
%% Arguments: IDs - CosNotifyFilter::ConstraintIDSeq
%% AddConstraintInfoSeq - CosNotifyFilter::ConstraintInfoSeq
%% Returns : ok |
%% {'EXCEPTION', CosNotifyFilter::InvalidConstraint} |
%% {'EXCEPTION', CosNotifyFilter::ConstraintNotFound}
%%-----------------------------------------------------------
%% The OMG specification (TC Document telecom/98-11-01, chapter
%% 3.2.1.3) states (concerning IDs):
%%
%% "If all input values supplied within a particular invocation
%% of this operation are valid, then the specific constraints
%% identified by the values contained in the first input parameter
%% will be deleted from the list of those encapsulated by the target
%% filter object."
%%
%% Hence, first we must check if all ID's exists before deleting.
modify_constraints(_OE_THIS, State, IDs, AddConstraintInfoSeq) ->
%% The following functions are 'safe', i.e., they do not alter any data.
RemoveConstraintInfoSeq = lookup_constraints(IDs, State),
lookup_constraints(AddConstraintInfoSeq, State),
{NewState, Filters, _Info, AddedEventTSeq} =
try_create_filters(State, AddConstraintInfoSeq),
RemovedEventTSeq = ?InfoSeq2EventTypeSeq(RemoveConstraintInfoSeq),
%% We cannot change anything before our checks (see above). Hence,
%% do NOT move the following lines above this point.
NewState2 = delete_constraints(IDs, NewState),
%% The OMG specification (TC Document telecom/98-11-01, chapter
%% 3.2.1.3) states (concerning AddConstraintInfoSeq):
%%
%% "If all input values supplied within a particular invocation of this
%% operation are valid, then the constraint expression associated with the
%% already encapsulated constraint identified by the numeric value contained
%% within each element of the input sequence will be modified to the new
%% constraint expression that is contained within the same sequence element."
%%
%% This, our interpretation, implies that ALL previous data related
%% to each unique ID should be removed and replaced by the new data.
NewState3 = delete_constraints(AddConstraintInfoSeq, NewState2),
NewState4 = store_filters(NewState3, Filters),
inform_callbacks(?get_AllCallback(NewState4),
AddedEventTSeq, RemovedEventTSeq),
{reply, ok, NewState4}.
%%----------------------------------------------------------%
%% Function : get_constraints/3
%% Arguments: IDs - CosNotifyFilter::ConstraintIDSeq
%% Returns : CosNotifyFilter::ConstraintInfoSeq |
%% {'EXCEPTION', CosNotifyFilter::ConstraintNotFound}
%%-----------------------------------------------------------
get_constraints(_OE_THIS, State, IDs) ->
{reply, lookup_constraints(IDs, State), State}.
%%----------------------------------------------------------%
%% Function : get_all_constraints/2
%% Arguments: -
%% Returns : CosNotifyFilter::ConstraintInfoSeq
%%-----------------------------------------------------------
get_all_constraints(_OE_THIS, State) ->
{reply, ?get_AllConstraints(State), State}.
%%----------------------------------------------------------%
%% Function : remove_all_constraints/2
%% Arguments: -
%% Returns : ok
%%-----------------------------------------------------------
remove_all_constraints(_OE_THIS, State) ->
{reply, ok, ?del_AllConstraints(State)}.
%%----------------------------------------------------------%
%% Function : destroy/2
%% Arguments: -
%% Returns : ok
%%-----------------------------------------------------------
destroy(_OE_THIS, State) ->
{stop, normal, ok, State}.
%%----------------------------------------------------------%
%% Function : match/3
%% Arguments: Event - #any{}
%% Returns : boolean() |
%% {'EXCEPTION', CosNotifyFilter::UnsupportedFilterableData}
%%-----------------------------------------------------------
match(_OE_THIS, State, Event) when is_record(Event,'any'), ?is_EmptyFilter(State) ->
{reply, true, State};
match(_OE_THIS, State, Event) when is_record(Event,'any') ->
match_any_event(State, Event, ?get_ConstraintAllData(State));
match(_,_,What) ->
orber:dbg("[~p] CosNotifyFilter_Filter:match(~p);~n"
"Not an CORBA::Any", [?LINE, What], ?DEBUG_LEVEL),
corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO}).
%%----------------------------------------------------------%
%% Function : match_structured/3
%% Arguments: Event - CosNotification::StructuredEvent
%% Returns : boolean() |
%% {'EXCEPTION', CosNotifyFilter::UnsupportedFilterableData}
%%-----------------------------------------------------------
match_structured(_OE_THIS, State, Event) when
is_record(Event,'CosNotification_StructuredEvent') andalso ?is_EmptyFilter(State) ->
{reply, true, State};
match_structured(_OE_THIS, State, Event) when
is_record(Event,'CosNotification_StructuredEvent') ->
match_str_event(State, Event, ?get_ConstraintAllData(State));
match_structured(_,_,What) ->
orber:dbg("[~p] CosNotifyFilter_Filter:match_structured(~p);~n"
"Not a StructuredEvent", [?LINE, What], ?DEBUG_LEVEL),
corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO}).
%%----------------------------------------------------------*
%% Function : match_typed/3
%% Arguments: Data - CosNotification::PropertySeq
%% Returns : boolean() |
%% {'EXCEPTION', CosNotifyFilter::UnsupportedFilterableData}
%%-----------------------------------------------------------
-spec match_typed(_, _, _) -> no_return().
match_typed(_OE_THIS, _State, _Data) ->
corba:raise(#'NO_IMPLEMENT'{completion_status=?COMPLETED_NO}).
%%----------------------------------------------------------%
%% Function : attach_callback/3
%% Arguments: CB - CosNotifyComm::NotifySubscribe
%% Returns : ID - CosNotifyFilter::CallbackID
%%-----------------------------------------------------------
attach_callback(_OE_THIS, State, CB) ->
'CosNotification_Common':type_check(CB, 'CosNotifyComm_NotifySubscribe'),
CBID = ?new_Id(State),
{reply, CBID, ?add_Callback(State, CBID, CB)}.
%%----------------------------------------------------------%
%% Function : detach_callback/3
%% Arguments: ID - CosNotifyFilter::CallbackID
%% Returns : ok | {'EXCEPTION', CosNotifyFilter::CallbackNotFound}
%%-----------------------------------------------------------
detach_callback(_OE_THIS, State, ID) when is_integer(ID) ->
{reply, ok, ?del_Callback(State, ID)};
detach_callback(_,_,What) ->
orber:dbg("[~p] CosNotifyFilter_Filter:detach_callback(~p);~n"
"Not an integer", [?LINE, What], ?DEBUG_LEVEL),
corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO}).
%%----------------------------------------------------------%
%% Function : get_callbacks/2
%% Arguments: -
%% Returns : CosNotifyFilter::CallbackIDSeq
%%-----------------------------------------------------------
get_callbacks(_OE_THIS, State) ->
{reply, ?get_AllCallbackID(State), State}.
%%--------------- LOCAL FUNCTIONS ----------------------------
%% To match callbacks
find_obj({value, {_, Obj}},_) -> Obj;
%% To match constraints
find_obj({value, {Id, Con, _, _, _, Types}}, _) ->
?create_ConstraintInfo(Types, Con, Id);
find_obj([{_, Tree, tree}|_], tree) -> Tree;
% Left out for now to avoid dialyzer warning.
%find_obj(_,callback) -> {'EXCEPTION', #'CosNotifyFilter_CallbackNotFound'{}};
find_obj(_,tree) -> undefined;
find_obj(_,constraint) -> error.
%% Delete a single object.
delete_obj(List,List,callback) -> corba:raise(#'CosNotifyFilter_CallbackNotFound'{});
delete_obj(List,_,_) -> List.
%% Delete given object from list and all related objects in DB (parse tree and types).
match_delete(State, Constraints, ID) ->
match_delete(State, Constraints, ID, []).
match_delete(_, [], _, _) ->
error;
match_delete(State, [{ID, _Con, _Which, _WC, Key, _Types}|T], ID, Acc) ->
?del_Type(State, ID),
?del_ParseTree(State, Key),
{ok, ?set_Constraints(State, Acc++T)};
match_delete(State, [H|T], ID, Acc) ->
match_delete(State, T, ID, [H|Acc]).
%% Remove all data related with constraints; for now, since no other data
%% stored in DB, we do in a rather brutal way.
clear_DB(State) ->
catch ets:delete(State#state.etsR),
State#state{etsR = ets:new(oe_ets, [bag, protected]), constraints=[]}.
%% Given a list of Constrain IDs we want to find the related constraints.
%% !!!!!! This function may not alter any data in DB in any way !!!!!!!!!!
lookup_constraints(IDs, State) ->
lookup_constraints(IDs, State, []).
lookup_constraints([], _State, Accum) ->
Accum;
lookup_constraints([H|T], State, Accum)
when is_record(H, 'CosNotifyFilter_ConstraintInfo') ->
case ?get_Constraint(State, H#'CosNotifyFilter_ConstraintInfo'.constraint_id) of
error ->
corba:raise(#'CosNotifyFilter_ConstraintNotFound'
{id = H#'CosNotifyFilter_ConstraintInfo'.constraint_id});
_Con ->
%% We don't need to collect the result since the input already is of
%% the correct type, i.e., ConstraintInfoSeq
lookup_constraints(T, State, Accum)
end;
lookup_constraints([H|T], State, Accum) when is_integer(H) ->
case ?get_Constraint(State,H) of
error ->
corba:raise(#'CosNotifyFilter_ConstraintNotFound'{id=H});
Con ->
lookup_constraints(T, State, [Con|Accum])
end;
lookup_constraints(_, _, _) ->
corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO}).
%% Given a list of Constrain IDs we want to delet the related constraints.
%% We need also to return the ConstraintInfoSeq described related to the
%% given ID's.
delete_constraints([], State) ->
State;
delete_constraints([H|T], State)
when is_record(H, 'CosNotifyFilter_ConstraintInfo') ->
case catch ?del_Constraint(State,
H#'CosNotifyFilter_ConstraintInfo'.constraint_id) of
{ok, NewState} ->
delete_constraints(T, NewState);
Reason ->
orber:dbg("[~p] 'CosNotifyFilter_Filter':modify_constraints().~n"
"Unable to remove: ~p~n"
"Reason: ~p~n",
[?LINE, H, Reason], ?DEBUG_LEVEL),
delete_constraints(T, State)
end;
delete_constraints([H|T], State) ->
case catch ?del_Constraint(State,H) of
{ok, NewState} ->
delete_constraints(T, NewState);
Reason ->
orber:dbg("[~p] 'CosNotifyFilter_Filter':modify_constraints().~n"
"Unable to remove: ~p~n"
"Reason: ~p~n",
[?LINE, H, Reason], ?DEBUG_LEVEL),
delete_constraints(T, State)
end.
%% Inform all registered callbacks that the constraints have changed.
%% Added and Removed must be a CosNotification::EventTypeSeq
inform_callbacks([],_,_) ->
ok;
inform_callbacks([H|T], Added, Removed) ->
case catch 'CosNotifyComm_NotifySubscribe':subscription_change(H, Added, Removed) of
ok ->
?debug_print("INFORMED CALLBACK: ~p ADDED: ~p REMOVED: ~p",
[H, Added, Removed]),
inform_callbacks(T, Added, Removed);
Other ->
orber:dbg("[~p] 'CosNotifyComm_NotifySubscribe':subscription_change().~n"
"Unable to inform callback: ~p~n"
"Reason: ~p~n",
[?LINE, H, Other], ?DEBUG_LEVEL),
inform_callbacks(T, Added, Removed)
end.
%%-----------------------------------------------------------
%% Function : try_create_filters/2
%% Arguments: CL - #'CosNotifyFilter_ConstraintExp'{
%% event_types = [#'CosNotification_EventType'{
%% domain_name = Str, type_name = Str}]
%% constraint_expr = Str}
%% Returns : {State, AccumList}
%%-----------------------------------------------------------
%% !!!!!! This function may not alter any data in DB in any way !!!!!!!!!!
try_create_filters(State, CL) ->
try_create_filters(State, CL, [], [], []).
try_create_filters(State, [], Accum, InfoSeq, EventTSeq) ->
{State, Accum, InfoSeq, EventTSeq};
try_create_filters(State, [#'CosNotifyFilter_ConstraintExp'{event_types = Types,
constraint_expr = Con}|T],
Accum, InfoSeq, EventTSeq) ->
case catch cosNotification_Filter:create_filter(Con) of
{ok, Tree} ->
case catch cosNotification_Filter:check_types(Types) of
true ->
ID = ?new_Id(State),
Key = ?not_CreateDBKey,
NewETSeq = Types ++ EventTSeq,
try_create_filters(?set_IdCounter(State, ID), T,
[{ID, true, [], Key, Types, Con, Tree}|Accum],
[?create_ConstraintInfo(Types, Con, ID)|InfoSeq],
NewETSeq);
{ok, Which, WC} ->
ID = ?new_Id(State),
Key = ?not_CreateDBKey,
NewETSeq = Types ++ EventTSeq,
try_create_filters(?set_IdCounter(State, ID), T,
[{ID, Which, WC, Key, Types, Con, Tree}|Accum],
[?create_ConstraintInfo(Types, Con, ID)|InfoSeq],
NewETSeq);
_ ->
corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO})
end;
_ ->
corba:raise(#'CosNotifyFilter_InvalidConstraint'
{constr = #'CosNotifyFilter_ConstraintExp'
{event_types = Types, constraint_expr = Con}})
end;
try_create_filters(State, [#'CosNotifyFilter_ConstraintInfo'
{constraint_expression = #'CosNotifyFilter_ConstraintExp'
{event_types = Types, constraint_expr = Con},
constraint_id=ID}|T], Accum, InfoSeq, EventTSeq) ->
case catch cosNotification_Filter:create_filter(Con) of
{ok, Tree} ->
case catch cosNotification_Filter:check_types(Types) of
true ->
Key = ?not_CreateDBKey,
NewETSeq = Types ++ EventTSeq,
try_create_filters(State, T,
[{ID, true, [], Key, Types, Con, Tree}|Accum],
[?create_ConstraintInfo(Types, Con, ID)|InfoSeq],
NewETSeq);
{ok, Which, WC} ->
Key = ?not_CreateDBKey,
NewETSeq = Types ++ EventTSeq,
try_create_filters(State, T,
[{ID, Which, WC, Key, Types, Con, Tree}|Accum],
[?create_ConstraintInfo(Types, Con, ID)|InfoSeq],
NewETSeq);
_ ->
corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO})
end;
_ ->
corba:raise(#'CosNotifyFilter_InvalidConstraint'
{constr = #'CosNotifyFilter_ConstraintExp'
{event_types = Types, constraint_expr = Con}})
end;
try_create_filters(_,_,_,_,_) ->
%% The list contained something else but ConstraintExp.
corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO}).
%%-----------------------------------------------------------
%% Function : store_filters/4
%% Arguments: Filters - a list of filters.
%% Returns :
%%-----------------------------------------------------------
store_filters(State, []) ->
State;
store_filters(State, [{ID, Which, WC, Key, Types, Con, Tree}|T]) ->
?add_ParseTree(State, Key, Tree),
write_types(State, Types, ID, Key),
store_filters(?add_Constraint(State, ID, Con, Which, WC, Key, Types), T).
write_types(_State, [],_, _) ->
ok;
write_types(State, [EventType|T], ID, Key) ->
?add_Type(State, ID, EventType, Key),
?debug_print("FILTER: ~p ~p ~p~n", [ID, Key, EventType]),
write_types(State, T, ID, Key).
%%-----------------------------------------------------------
%% Function : match_any_event
%% Arguments:
%% Returns :
%%-----------------------------------------------------------
match_any_event(State, _Event, []) ->
?debug_print("FILTER REJECTED: ~p~n", [_Event]),
{reply, false, State};
match_any_event(State, Event, [{_, _, _, _, Key, _}|T]) ->
case catch cosNotification_Filter:eval(?get_ParseTree(State,Key), Event) of
true ->
?debug_print("FILTER APPROVED (WC): ~p~n", [Event]),
{reply, true, State};
_ ->
match_any_event(State, Event, T)
end.
%%-----------------------------------------------------------
%% Function : match_str_event
%% Arguments:
%% Returns :
%%-----------------------------------------------------------
match_str_event(State, _Event, []) ->
?debug_print("FILTER REJECTED: ~p~n", [_Event]),
{reply, false, State};
match_str_event(State, Event, [{ID, _Con, Which, WC, Key, _Types}|T]) ->
ET = ((Event#'CosNotification_StructuredEvent'.header)
#'CosNotification_EventHeader'.fixed_header)
#'CosNotification_FixedEventHeader'.event_type,
CheckList =
case Which of
both ->
[ET];
domain ->
[ET,
ET#'CosNotification_EventType'{type_name=""},
ET#'CosNotification_EventType'{type_name="*"}];
type ->
[ET,
ET#'CosNotification_EventType'{domain_name=""},
ET#'CosNotification_EventType'{domain_name="*"}];
_ ->
[ET,
ET#'CosNotification_EventType'{type_name=""},
ET#'CosNotification_EventType'{type_name="*"},
ET#'CosNotification_EventType'{domain_name=""},
ET#'CosNotification_EventType'{domain_name="*"}]
end,
case check_DB(State, ID, CheckList) of
false ->
%% No match, may have used wildcards, e.g., "dom*".
case catch cosNotification_Filter:match_types(
ET#'CosNotification_EventType'.domain_name,
ET#'CosNotification_EventType'.type_name,
WC) of
true ->
case catch cosNotification_Filter:eval(?get_ParseTree(State,Key),
Event) of
true ->
?debug_print("FILTER APPROVED (WC): ~p~n", [Event]),
{reply, true, State};
_ ->
match_str_event(State, Event, T)
end;
_->
match_str_event(State, Event, T)
end;
Key ->
case catch cosNotification_Filter:eval(?get_ParseTree(State,Key),
Event) of
true ->
?debug_print("FILTER APPROVED: ~p~n", [Event]),
{reply, true, State};
_ ->
match_str_event(State, Event, T)
end
end.
check_DB(_, _, []) ->
false;
check_DB(State, ID, [H|T]) ->
case ?match_Type(State, ID, H) of
[] ->
check_DB(State, ID, T);
[{_, K, types}|_] ->
K
end.
%%--------------- MISC FUNCTIONS, E.G. DEBUGGING -------------
%%--------------- END OF MODULE ------------------------------