aboutsummaryrefslogtreecommitdiffstats
path: root/lib/cosNotification/src/CosNotifyFilter_Filter_impl.erl
diff options
context:
space:
mode:
authorErlang/OTP <[email protected]>2009-11-20 14:54:40 +0000
committerErlang/OTP <[email protected]>2009-11-20 14:54:40 +0000
commit84adefa331c4159d432d22840663c38f155cd4c1 (patch)
treebff9a9c66adda4df2106dfd0e5c053ab182a12bd /lib/cosNotification/src/CosNotifyFilter_Filter_impl.erl
downloadotp-84adefa331c4159d432d22840663c38f155cd4c1.tar.gz
otp-84adefa331c4159d432d22840663c38f155cd4c1.tar.bz2
otp-84adefa331c4159d432d22840663c38f155cd4c1.zip
The R13B03 release.OTP_R13B03
Diffstat (limited to 'lib/cosNotification/src/CosNotifyFilter_Filter_impl.erl')
-rw-r--r--lib/cosNotification/src/CosNotifyFilter_Filter_impl.erl670
1 files changed, 670 insertions, 0 deletions
diff --git a/lib/cosNotification/src/CosNotifyFilter_Filter_impl.erl b/lib/cosNotification/src/CosNotifyFilter_Filter_impl.erl
new file mode 100644
index 0000000000..042e180170
--- /dev/null
+++ b/lib/cosNotification/src/CosNotifyFilter_Filter_impl.erl
@@ -0,0 +1,670 @@
+%%--------------------------------------------------------------------
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 1999-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights 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}
+%%-----------------------------------------------------------
+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 ------------------------------
+