cosnotification_filter.erl
来自「OTP是开放电信平台的简称」· ERL 代码 · 共 964 行 · 第 1/3 页
ERL
964 行
%%--------------------------------------------------------------------%% ``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 via the world wide web 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.%% %% The Initial Developer of the Original Code is Ericsson Utvecklings AB.%% Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings%% AB. All Rights Reserved.''%% %% $Id$%%%%----------------------------------------------------------------------%% File : cosNotification_Filter.erl%% Purpose : %% Created : 28 Dec 1999%%-----------------------------------------------------------------------module(cosNotification_Filter).%%--------------- INCLUDES ------------------------------------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").%%--------------- EXPORTS ------------------------------------%% Internal Filter Functions-export([eval/1, eval/2, create_filter/1, check_types/1, match_types/3, validate_types/1]).%%--------------- DEFINES -------------------------------------define(EVENT_PATH, [{dotid,"header"}, {dotid,"fixed_header"}, {dotid,"event_name"}]).-define(DOMAIN_PATH, [{dotid,"header"}, {dotid,"fixed_header"}, {dotid,"event_type"}, {dotid,"domain_name"}]).-define(TYPE_PATH, [{dotid,"header"}, {dotid,"fixed_header"}, {dotid,"event_type"}, {dotid,"type_name"}]).-define(VARIABLE_PATH(I), [{dotid,"header"}, {dotid,"variable_header"}, {dotid,I}]).-define(FILTERABLE_PATH(I), [{dotid,"filterable_data"}, {dotid,I}]).%%------------------------------------------------------------%%--------------- FILTER FUNCTIONS ---------------------------%%------------------------------------------------------------%%------------------------------------------------------------%% function : create_filter/1%% Arguments: String - Filter grammar%% Returns : %% Effect : %%------------------------------------------------------------create_filter(Str) -> {ok, Tokens} = cosNotification_Scanner:scan(Str), case cosNotification_Grammar:parse(Tokens) of {ok, Filter} -> {ok, Filter}; _-> corba:raise(#'CosNotifyFilter_InvalidConstraint'{constr = Str}) end.%%------------------------------------------------------------%% function : eval%% Arguments: %% Returns : %% Effect : %%------------------------------------------------------------eval('$empty') -> true;eval(Tree) -> eval(Tree, []).%% Leaf expressions (literals and idents).eval('$empty', _) -> true;eval(Lit, _Env) when number(Lit) -> Lit;eval(Lit, _Env) when list(Lit) -> Lit; %list == stringeval(Lit, _Env) when atom(Lit) -> Lit; %atom == booleval({component, V}, []) -> %% Cannot evaluate variables at this stage. throw({error, {unbound_variable, V}});eval({component, V}, Env) -> case catch lookup(V, Env, undefined) of {ok, Val} -> Val; _X -> {error, {unbound_variable, V}} end;%% CORBA2.3-15/26 states:%% "The name parameters in tk_objref, tk_struct, tk_union, tk_enum, tk_alias, %% tk_value, tk_value_box, tk_abstract_interface, tk_native and tk_except TypeCodes%% and the member name parameters in tk_struct, tk_union, tk_enum, tk_value and%% tk_except TypeCodes are not specified by (or significant in) GIOP. Agents should%% not make assumptions about type equivalence based on these name values; only the%% structural information (including RepositoryId values, if provided) is%% significant. If provided, the strings should be the simple, unscoped names%% supplied in the OMG IDL definition text. If omitted, they are encoded as empty%% strings."%% Makes it rather hard to follow the grammar 100 %.eval({default_component, V}, Env) -> case catch lookup(V, Env, default_component) of {ok, false} -> false; {ok, true} -> true; _X -> {error, {unbound_variable, V}} end;eval({exist_component, V}, Env) -> case catch lookup(V, Env, exist_component) of {ok, false} -> false; {ok, _} -> true; {error, _} -> false; _X -> {error, {unbound_variable, V}} end;%% Arithmetic expressions.eval({'*', X, Y}, Env) -> eval_arith({fun(_X, _Y) -> _X*_Y end, X, Y}, Env);eval({'/', X, Y}, Env) -> eval_arith({fun(_X, _Y) -> _X/_Y end, X, Y}, Env);eval({'+', X, Y}, Env) -> eval_arith({fun(_X, _Y) -> _X+_Y end, X, Y}, Env);eval({'-', X, Y}, Env) -> eval_arith({fun(_X, _Y) -> _X-_Y end, X, Y}, Env);eval({'u-', X}, Env) -> eval_arith({fun(_X) -> -_X end, X}, Env);%% Relational expressions.eval({'==', X, Y}, Env) -> eval_rel({fun(_X, _Y) -> _X == _Y end, X, Y}, Env);eval({'!=', X, Y}, Env) -> eval_rel({fun(_X, _Y) -> _X /= _Y end, X, Y}, Env);eval({'<', X, Y}, Env) -> eval_rel({fun(_X, _Y) -> _X < _Y end, X, Y}, Env);eval({'<=', X, Y}, Env) -> eval_rel({fun(_X, _Y) -> _X =< _Y end, X, Y}, Env);eval({'>', X, Y}, Env) -> eval_rel({fun(_X, _Y) -> _X > _Y end, X, Y}, Env);eval({'>=', X, Y}, Env) -> eval_rel({fun(_X, _Y) -> _X >= _Y end, X, Y}, Env);eval({'~', Needle, Haystack}, Env) -> %substring match N = eval(Needle, Env), H = eval(Haystack, Env), if list(N), list(H) -> string:str(H, N) /= 0; true -> throw({error, {bad_type, Needle, Haystack}}) end;eval({'in', Needle, Haystack}, Env) -> %set membership N = eval(Needle, Env), H = eval(Haystack, Env), if list(H) -> lists:member(N, H); true -> throw({error, {bad_type, Needle, Haystack}}) end;%% Boolean expressions.eval({'and', false, _Y}, _Env) -> false;eval({'and', _X, false}, _Env) -> false;eval({'and', X, Y}, Env) -> eval_and_bool({fun(_X, _Y) -> _X and _Y end, X, Y}, Env);eval({'or', true, _Y}, _Env) -> true;eval({'or', _X, true}, _Env) -> true;eval({'or', X, Y}, Env) -> eval_or_bool({fun(_X, _Y) -> _X or _Y end, X, Y}, Env);eval({'not', X}, Env) -> eval_bool({fun(_X) -> not _X end, X}, Env);%% Catch-alleval(_T, _Env) -> throw({error, internal}).eval_bool({Fun, X}, Env) -> Xe = eval(X, Env), if atom(Xe) -> Fun(Xe); true -> throw({error, {bad_type, X}}) end.eval_and_bool({Fun, X, Y}, Env) -> case eval(X, Env) of false -> %% No need for evaluating the other expression. false; Xe -> Ye = eval(Y, Env), if atom(Xe), atom(Ye) -> Fun(Xe, Ye); true -> throw({error, {bad_type, X, Y}}) end end.eval_or_bool({Fun, X, Y}, Env) -> case eval(X, Env) of true -> %% No need for evaluating the other expression. true; Xe -> Ye = eval(Y, Env), if atom(Xe), atom(Ye) -> Fun(Xe, Ye); true -> throw({error, {bad_type, X, Y}}) end end.%% According to issue 2203, OMG stated that arithmetic operations involving booleans%% is allowed. TRUE equals 1 and FALSE 0. They refer to:%% "We at NEC like this feature, and feel it is both required and%% standard with the way CORBA treats boolean values. We feel it's%% required because it allows the constraint grammar to handle%% expressions that combine the results of boolean comparisons, %% which we feel is typically expected of a constraint grammar%% (e.g., ($.fruit == apples) + ($.color == red) + ($.kind == macintosh) > 2)%% Furthermore, while we have no fundamental opposition to explicitly%% stating that TRUE=1 and FALSE=0, we don't necessarily feel it's%% necessary because section 12.3.1 of CORBA alread states that %% "Boolean values are encoded as single octets, where TRUE is the%% value 1, and FALSE is 0." Essentially, we feel CORBA already %% defines TRUE to be 1 and FALSE to be 0, however we are not %% opposed to adding such a statement into Notification if folks %% feel it's necessary."%% If still valid, see: ftp://ftp.omg.org/pub/docs/telecom/99-07-06.txt%% The section they refer to (CORBA-2.0) merely states that TRUE and FALSE are%% encoded as 1 and 0 in GIOP. Does not imply that booleans may be used as numeric.%% But, they have stated that this should be the case so..... remap_bool(Num) when number(Num) -> Num;remap_bool(true) -> 1;remap_bool(false) -> 0;remap_bool(X) -> throw({error, {bad_type, X}}).eval_arith({Fun, X}, Env) -> Xe = remap_bool(eval(X, Env)), Fun(Xe);eval_arith({Fun, X, Y}, Env) -> Xe = remap_bool(eval(X, Env)), Ye = remap_bool(eval(Y, Env)), Fun(Xe, Ye).eval_rel({Fun, X, Y}, Env) -> Xe = eval(X, Env), Ye = eval(Y, Env), if number(Xe), number(Ye) -> Fun(Xe, Ye); list(Xe), list(Ye) -> Fun(Xe, Ye); atom(Xe), atom(Ye) -> Fun(Xe, Ye); true -> throw({error, {bad_type, X, Y}}) end.%%------------------------------------------------------------%% function : get_variable%% Arguments: A sequence of CosNotification::Property{}, i.e., %% name-value pairs.%% ID - name in the Property%% Any - remainder of body%% Returns : Value in the Property | false%% Comment : When searching for a variable we must start with%% 'variable_header' followed by 'filterable_body'.%% If not found we will then look in the 'remainder_of_body'%%------------------------------------------------------------get_variable([], ID, Any) when record(Any, any) -> case {any:get_value(Any), any:get_typecode(Any)} of {#'CosNotification_Property'{name=ID, value=A}, _} -> any:get_value(A); {_, TC} when atom(TC) -> %% Since TC atom it must be a simple type, which don't have members. throw({error, {bad_id, ID}}); {Value, {tk_alias,_,ID,_}} when record(Value, any) -> %% {tk_alias, IFRId, ID, TypeCode} any:get_value(Value); {Value, {tk_alias,_,ID,_}} -> %% {tk_alias, IFRId, ID, TypeCode} Value; {Value, _TC} -> get_variable([],ID, Value) end;get_variable([], ID, #'CosNotification_Property'{name=ID, value=Any}) -> any:get_value(Any);get_variable([], ID, [#'CosNotification_Property'{name=ID, value=Any}|_]) -> any:get_value(Any);get_variable([], ID, [H|T]) when record(H, 'CosNotification_Property') -> get_variable([], ID, T);get_variable([], ID, false) -> throw({error, {bad_id, ID}});get_variable([], ID, Value) -> M = element(1, Value),
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?