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 + -
显示快捷键?