diff options
author | Erlang/OTP <[email protected]> | 2009-11-20 14:54:40 +0000 |
---|---|---|
committer | Erlang/OTP <[email protected]> | 2009-11-20 14:54:40 +0000 |
commit | 84adefa331c4159d432d22840663c38f155cd4c1 (patch) | |
tree | bff9a9c66adda4df2106dfd0e5c053ab182a12bd /lib/cosProperty/src/CosPropertyService_PropertySetDef_impl.erl | |
download | otp-84adefa331c4159d432d22840663c38f155cd4c1.tar.gz otp-84adefa331c4159d432d22840663c38f155cd4c1.tar.bz2 otp-84adefa331c4159d432d22840663c38f155cd4c1.zip |
The R13B03 release.OTP_R13B03
Diffstat (limited to 'lib/cosProperty/src/CosPropertyService_PropertySetDef_impl.erl')
-rw-r--r-- | lib/cosProperty/src/CosPropertyService_PropertySetDef_impl.erl | 1041 |
1 files changed, 1041 insertions, 0 deletions
diff --git a/lib/cosProperty/src/CosPropertyService_PropertySetDef_impl.erl b/lib/cosProperty/src/CosPropertyService_PropertySetDef_impl.erl new file mode 100644 index 0000000000..157b243c53 --- /dev/null +++ b/lib/cosProperty/src/CosPropertyService_PropertySetDef_impl.erl @@ -0,0 +1,1041 @@ +%%-------------------------------------------------------------------- +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2000-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: CosPropertyService_PropertySetDef_impl.erl +%% Modified: +%% +%%----------------------------------------------------------------- +%% README: +%% (1) The OMG specification states that a property name may not +%% be an empty string (""). We may restrict this further +%% but there is no reason for that. +%%----------------------------------------------------------------- +-module('CosPropertyService_PropertySetDef_impl'). + +%%---------------------------------------------------------------------- +%% Include files +%%---------------------------------------------------------------------- +-include_lib("orber/include/corba.hrl"). +-include_lib("orber/src/orber_iiop.hrl"). +-include_lib("cosProperty/include/CosPropertyService.hrl"). +-include("cosProperty.hrl"). + +%%---------------------------------------------------------------------- +%% External exports +%%---------------------------------------------------------------------- +%% Mandatory callbacks +-export([init/1, + terminate/2, + code_change/3]). + +%% Inherrit from CosPropertyService::PropertySet +-export([define_property/4, + define_properties/3, + get_number_of_properties/2, + get_all_property_names/3, + get_property_value/3, + get_properties/3, + get_all_properties/3, + delete_property/3, + delete_properties/3, + delete_all_properties/2, + is_property_defined/3]). + +%% CosPropertyService::PropertySetDef +-export([get_allowed_property_types/2, + get_allowed_properties/2, + define_property_with_mode/5, + define_properties_with_modes/3, + get_property_mode/3, + get_property_modes/3, + set_property_mode/4, + set_property_modes/3]). + +%%---------------------------------------------------------------------- +%% Internal exports +%%---------------------------------------------------------------------- +-export([dump/0]). + +%%---------------------------------------------------------------------- +%% Records +%%---------------------------------------------------------------------- +-record(state, {dbKey, defaultMode, okTypes, okProperties, myType}). + +%%---------------------------------------------------------------------- +%% Macros +%%---------------------------------------------------------------------- + +-define(create_InitState(K, D, AT, AP, MT), #state{dbKey = K, defaultMode = D, + okTypes = AT, okProperties = AP, + myType = MT}). +%% Selectors +-define(get_DBKey(S), S#state.dbKey). +-define(get_DefaultMode(S), S#state.defaultMode). +-define(get_okTypes(S), S#state.okTypes). +-define(get_okProperties(S), S#state.okProperties). +%% MISC +-define(is_NotSetDef(S), S#state.myType =/= ?PropertySetDef). +-define(no_PropertyLimits(S), S#state.okProperties == []). +-define(no_TypeLimits(S), S#state.okTypes == []). +-define(is_NotStatic(S), is_binary(S#state.dbKey)). + +%% Fun:s +-define(Local2Property, fun({N,V,_M}) -> + #'CosPropertyService_Property'{property_name = N, + property_value = V} + end). +-define(Local2Names, fun({N,_V,_M}) -> + N + end). +-define(MemberName(N), fun(R) -> + case R of + Property when is_record(R, 'CosPropertyService_Property') -> + Property#'CosPropertyService_Property'.property_name == N; + PropertyDef when is_record(R, 'CosPropertyService_PropertyDef') -> + PropertyDef#'CosPropertyService_PropertyDef'.property_name == N; + _-> + false + end + end). + +%%====================================================================== +%% External functions +%%====================================================================== +%%---------------------------------------------------------------------- +%% Function : init/1 +%% Description: Initiates the server +%% Returns : {ok, State} | +%% {ok, State, Timeout} | +%% ignore | +%% {stop, Reason} +%%---------------------------------------------------------------------- +init({DefMode, AllowedTypes, AllowedProperties, InitProperties, MyType}) -> + Key = term_to_binary({now(), node()}), + _F = ?write_function(#oe_CosPropertyService{key=Key, + properties=InitProperties}), + write_result(mnesia:transaction(_F)), + {ok, ?create_InitState(Key, DefMode, AllowedTypes, AllowedProperties, MyType)}; +init({static, DefMode, AllowedTypes, AllowedProperties, InitProperties, MyType}) -> + {ok, ?create_InitState(InitProperties, DefMode, AllowedTypes, + AllowedProperties, MyType)}. + +%%---------------------------------------------------------------------% +%% Function : terminate +%% Description: Shutdown the server +%% Returns : any (ignored by gen_server) +%%---------------------------------------------------------------------- +terminate(_Reason, State) when ?is_NotStatic(State) -> + _DF = ?delete_function({oe_CosPropertyService, ?get_DBKey(State)}), + catch write_result(mnesia:transaction(_DF)), + ok; +terminate(_Reason, _State) -> + ok. + +%%---------------------------------------------------------------------% +%% Function : code_change +%% Description: Convert process state when code is changed +%% Returns : {ok, State} +%%---------------------------------------------------------------------- +code_change(_OldVsn, State, _Extra) -> + {ok, State}. + + +%%---------------------------------------------------------------------- +%% Interface CosPropertyService::PropertySet +%%---------------------------------------------------------------------- +%%---------------------------------------------------------------------% +%% Function : define_property +%% Arguments : +%% Description: +%% Returns : {ok, State} +%%---------------------------------------------------------------------- +define_property(_, _, "", _) -> + corba:raise(#'CosPropertyService_InvalidPropertyName'{}); +define_property(_OE_This, State, Name, Value) when ?is_NotStatic(State) -> + evaluate_property_data(State, Value, Name), + _DF = + fun() -> + case mnesia_read(State) of + {'EXCEPTION', E} -> + {'EXCEPTION', E}; + X -> + case catch update_property(X, Name, value, Value, + ?get_DefaultMode(State)) of + {'EXCEPTION', E} when + is_record(E, 'CosPropertyService_PropertyNotFound') -> + mnesia_write(State, [{Name, Value, ?get_DefaultMode(State)}|X]); + {'EXCEPTION', E} -> + {'EXCEPTION', E}; + NewProperties -> + mnesia_write(State, NewProperties) + end + end + end, + {reply, mnesia_transaction(_DF), State}; +define_property(_OE_This, State, Name, Value) -> + evaluate_property_data(State, Value, Name), + X = ?get_DBKey(State), + case catch update_property(X, Name, value, Value, ?get_DefaultMode(State)) of + {'EXCEPTION', E} when is_record(E, 'CosPropertyService_PropertyNotFound') -> + corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO}); + {'EXCEPTION', E} -> + corba:raise(E); + _NewProperties -> + corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO}) + end. + + +%%---------------------------------------------------------------------% +%% Function : get_property_value +%% Arguments : +%% Description: +%% Returns : {ok, State} +%%---------------------------------------------------------------------- +get_property_value(_, _, "") -> + corba:raise(#'CosPropertyService_InvalidPropertyName'{}); +get_property_value(_OE_THIS, State, Name) -> + X = lookup_table(?get_DBKey(State)), + {reply, find_property(X, Name, value), State}. + +%%---------------------------------------------------------------------% +%% Function : delete_property +%% Arguments : +%% Description: +%% Returns : {ok, State} +%%---------------------------------------------------------------------- +delete_property(_, _, "") -> + corba:raise(#'CosPropertyService_InvalidPropertyName'{}); +delete_property(_OE_THIS, State, Name) when ?is_NotStatic(State) -> + _DF = + fun() -> + case mnesia_read(State) of + {'EXCEPTION', E} -> + {'EXCEPTION', E}; + X -> + case catch remove_property(X, Name) of + {'EXCEPTION', E} -> + {'EXCEPTION', E}; + NewProperties -> + mnesia_write(State, NewProperties) + end + end + end, + {reply, mnesia_transaction(_DF), State}; +delete_property(_OE_THIS, State, Name) -> + X = lookup_table(?get_DBKey(State)), + %% Check the properties; must raise an exception. + remove_property(X, Name), + %% Something is not correct. + corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO}). + + +%%---------------------------------------------------------------------% +%% Function : define_properties +%% Arguments : +%% Description: +%% Returns : {ok, State} +%%---------------------------------------------------------------------- +define_properties(_OE_THIS, State, PropertySeq) when ?is_NotStatic(State) -> + {OKProperties, Exc} = evaluate_properties_data(State, PropertySeq), + _DF = + fun() -> + case mnesia_read(State) of + {'EXCEPTION', E} -> + {'EXCEPTION', E}; + X -> + case catch define_properties_helper(State, + OKProperties, X, Exc) of + {'EXCEPTION', E} -> + {'EXCEPTION', E}; + NewProperties -> + mnesia_write(State, NewProperties) + end + end + end, + {reply, mnesia_transaction(_DF), State}; +define_properties(_OE_THIS, State, PropertySeq) -> + {OKProperties, Exc} = evaluate_properties_data(State, PropertySeq), + X = lookup_table(?get_DBKey(State)), + case define_properties_helper(State, OKProperties, X, Exc) of + {'EXCEPTION', E} -> + corba:raise(E); + _ -> + corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO}) + end. + +define_properties_helper(_State, [], NewProperties, []) -> + %% No exceptions, insert the properties. + NewProperties; +define_properties_helper(_State, [], _, MultipleExceptions) -> + {'EXCEPTION', #'CosPropertyService_MultipleExceptions'{exceptions = MultipleExceptions}}; +define_properties_helper(State, [#'CosPropertyService_Property' + {property_name = Name, + property_value = Value}|T], Properties, Exc) -> + case catch update_property(Properties, Name, value, Value, ?get_DefaultMode(State)) of + {'EXCEPTION', E} when is_record(E, 'CosPropertyService_PropertyNotFound') -> + define_properties_helper(State, T, [{Name, Value, ?get_DefaultMode(State)}|Properties], Exc); + {'EXCEPTION', E} -> + define_properties_helper(State, T, Properties, + [#'CosPropertyService_PropertyException' + {reason = remap_exception(E), + failing_property_name = Name}|Exc]); + NewProperties -> + define_properties_helper(State, T, NewProperties, Exc) + end. + +%%---------------------------------------------------------------------% +%% Function : get_number_of_properties +%% Arguments : - +%% Description: Returns the number of properties currently associated +%% with this object. +%% Returns : {ok, ulong(), State} +%%---------------------------------------------------------------------- +get_number_of_properties(_OE_THIS, State) -> + X = lookup_table(?get_DBKey(State)), + {reply, length(X), State}. + +%%---------------------------------------------------------------------% +%% Function : get_all_property_names +%% Arguments : +%% Description: +%% Returns : {ok, State} +%%---------------------------------------------------------------------- +get_all_property_names(_OE_THIS, State, Max) -> + X = lookup_table(?get_DBKey(State)), + {reply, get_all_property_names_helper(X, [], Max), State}. + +get_all_property_names_helper([], Acc, _) -> + %% There are no more properties; return a nil-object refernce. + {ok, Acc, corba:create_nil_objref()}; +get_all_property_names_helper(Left, Acc, 0) -> + %% There are more properties; create Name Iterartor. + PropertyNames = lists:map(?Local2Names, Left), + {ok, Acc, cosProperty:start_PropertyNamesIterator(PropertyNames)}; +get_all_property_names_helper([{Name, _, _}|T], Acc, No) -> + get_all_property_names_helper(T, [Name|Acc], No-1). + + +%%---------------------------------------------------------------------% +%% Function : get_properties +%% Arguments : A list of property names, i.e., string() +%% Description: +%% Returns : {ok, State} +%%---------------------------------------------------------------------- +get_properties(_OE_THIS, State, PropertyNames) -> + X = lookup_table(?get_DBKey(State)), + {reply, locate_names(PropertyNames, X, true, []), State}. + +locate_names([], _, AllOK, Acc) -> + {AllOK, Acc}; +locate_names([""|T], X, _AllOK, Acc) -> + locate_names(T, X, false, [#'CosPropertyService_Property' + {property_name = "", + property_value = + any:create(tk_void, ok)}|Acc]); +locate_names([H|T], X, AllOK, Acc) -> + case catch find_property(X, H, value) of + {'EXCEPTION', _} -> + locate_names(T, X, false, [#'CosPropertyService_Property' + {property_name = H, + property_value = + any:create(tk_void, ok)}|Acc]); + Val -> + locate_names(T, X, AllOK, [#'CosPropertyService_Property' + {property_name = H, + property_value = Val}|Acc]) + end. + +%%---------------------------------------------------------------------% +%% Function : get_all_properties +%% Arguments : +%% Description: +%% Returns : {ok, State} +%%---------------------------------------------------------------------- +get_all_properties(_OE_THIS, State, Max) -> + X = lookup_table(?get_DBKey(State)), + {reply, get_all_properties_helper(X, [], Max), State}. + +get_all_properties_helper([], Acc, _) -> +%% There are no more properties; return a nil-object refernce. + {ok, Acc, corba:create_nil_objref()}; +get_all_properties_helper(Left, Acc, 0) -> + %% There are more properties; create Iterartor. + Properties = lists:map(?Local2Property, Left), + {ok, Acc, cosProperty:start_PropertiesIterator(Properties)}; +get_all_properties_helper([{Name, Val, _}|T], Acc, No) -> + get_all_properties_helper(T, [#'CosPropertyService_Property' + {property_name = Name, + property_value = Val}|Acc], No-1). + +%%---------------------------------------------------------------------% +%% Function : delete_properties +%% Arguments : +%% Description: +%% Returns : {ok, State} +%%---------------------------------------------------------------------- +delete_properties(_OE_THIS, State, []) -> + {reply, ok, State}; +delete_properties(_OE_THIS, State, PropertyNames) when ?is_NotStatic(State) -> + _DF = + fun() -> + case mnesia_read(State) of + {'EXCEPTION', E} -> + {'EXCEPTION', E}; + X -> + case catch delete_properties_helper(X, [], [], + PropertyNames, State, + length(X)) of + {'EXCEPTION', E} -> + {'EXCEPTION', E}; + {{'EXCEPTION', E}, NotDeleted} -> + ok = mnesia_write(State, NotDeleted), + {'EXCEPTION', E}; + {ok, NotDeleted} -> + mnesia_write(State, NotDeleted) + end + end + end, + {reply, mnesia_transaction(_DF), State}; +delete_properties(_OE_THIS, State, PropertyNames) -> + X = lookup_table(?get_DBKey(State)), + case delete_properties_helper(X, [], [], PropertyNames, State, length(X)) of + {'EXCEPTION', E} -> + corba:raise(E); + _-> + %% Not acceptable if it was possible to delete one or more Properties. + corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO}) + end. + +delete_properties_helper([], [], NotDeleted, [], _State, _Len) -> + %% Since there are no exceptions we have been able to delete all + %% properties. + {ok, NotDeleted}; +delete_properties_helper([], MultipleExc, NotDeleted, Names, _State, Len) -> + %% Write remaining events to DB. + case length(NotDeleted) of + Len -> + {'EXCEPTION', #'CosPropertyService_MultipleExceptions' + {exceptions = add_not_found(Names, MultipleExc)}}; + _-> + {{'EXCEPTION', #'CosPropertyService_MultipleExceptions' + {exceptions = add_not_found(Names, MultipleExc)}}, + NotDeleted} + end; +delete_properties_helper([{Name, Val, Mode}|T], MultipleExc, NotDeleted, + Names, State, Len) -> + case lists:member(Name, Names) of + true when Mode =/= fixed_normal, Mode =/= fixed_readonly -> + delete_properties_helper(T, MultipleExc, NotDeleted, + lists:delete(Name, Names), State, Len); + true -> + delete_properties_helper(T, [#'CosPropertyService_PropertyException' + {reason = fixed_property, + failing_property_name = Name}|MultipleExc], + [{Name, Val, Mode}|NotDeleted], + lists:delete(Name, Names), State, Len); + false -> + delete_properties_helper(T, MultipleExc, [{Name, Val, Mode}|NotDeleted], + Names, State, Len) + end. + +add_not_found([], MultipleExc) -> + MultipleExc; +add_not_found([Name|T], MultipleExc) -> + add_not_found(T, [#'CosPropertyService_PropertyException' + {reason = property_not_found, + failing_property_name = Name}|MultipleExc]). + + + +%%---------------------------------------------------------------------% +%% Function : delete_all_properties +%% Arguments : +%% Description: +%% Returns : {ok, State} +%%---------------------------------------------------------------------- +delete_all_properties(_OE_THIS, State) when ?is_NotStatic(State) -> + _DF = + fun() -> + case mnesia_read(State) of + {'EXCEPTION', E} -> + {'EXCEPTION', E}; + X -> + case catch delete_all_properties_helper(X, [], State, + length(X)) of + {'EXCEPTION', E} -> + {'EXCEPTION', E}; + true -> + ok = mnesia_write(State, []), + true; + false -> + false; + {false, NotDeleted} -> + ok = mnesia_write(State, NotDeleted), + false + end + end + end, + {reply, mnesia_transaction(_DF), State}; +delete_all_properties(_OE_THIS, State) -> + X = lookup_table(?get_DBKey(State)), + case delete_all_properties_helper(X, [], State, length(X)) of + false -> + {reply, false, State}; + _-> + corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO}) + end. + +delete_all_properties_helper([], [], _State, _) -> + %% Was able to delete all properties. + true; +delete_all_properties_helper([], NotDeleted, _State, Len) -> + %% Write remaining events to DB. + case length(NotDeleted) of + Len -> + false; + _-> + {false, NotDeleted} + end; +delete_all_properties_helper([{Name, Val, fixed_normal}|T], NotDeleted, State, Len) -> + delete_all_properties_helper(T, [{Name, Val, fixed_normal}|NotDeleted], State, Len); +delete_all_properties_helper([{Name, Val, fixed_readonly}|T], NotDeleted, State, Len) -> + delete_all_properties_helper(T, [{Name, Val, fixed_readonly}|NotDeleted], State, Len); +delete_all_properties_helper([_|T], NotDeleted, State, Len) -> + delete_all_properties_helper(T, NotDeleted, State, Len). + +%%---------------------------------------------------------------------% +%% Function : is_property_defined +%% Arguments : +%% Description: +%% Returns : {ok, State} +%%---------------------------------------------------------------------- +is_property_defined(_, _, "") -> + corba:raise(#'CosPropertyService_InvalidPropertyName'{}); +is_property_defined(_OE_THIS, State, Name) -> + X = lookup_table(?get_DBKey(State)), + {reply, lists:keymember(Name, 1, X), State}. + +%%---------------------------------------------------------------------- +%% Interface CosPropertyService::PropertySetDef +%%---------------------------------------------------------------------- +%%---------------------------------------------------------------------% +%% Function : get_allowed_property_types +%% Arguments : - +%% Description: Returns the initially supplied restrictions. An empty +%% list means no restrictions. +%% Returns : {ok, TypeCodeList,State} +%%---------------------------------------------------------------------- +get_allowed_property_types(_OE_THIS, State) when ?is_NotSetDef(State) -> + corba:raise(#'NO_IMPLEMENT'{completion_status=?COMPLETED_NO}); +get_allowed_property_types(_OE_THIS, State) -> + {reply, {ok, ?get_okTypes(State)}, State}. + +%%---------------------------------------------------------------------% +%% Function : get_allowed_properties +%% Arguments : +%% Description: Returns the initially supplied restrictions. An empty +%% list means no restrictions. +%% Returns : {ok, PropertyDefList, State} +%%---------------------------------------------------------------------- +get_allowed_properties(_OE_THIS, State) when ?is_NotSetDef(State) -> + corba:raise(#'NO_IMPLEMENT'{completion_status=?COMPLETED_NO}); +get_allowed_properties(_OE_THIS, State) -> + {reply, {ok, ?get_okProperties(State)}, State}. + +%%---------------------------------------------------------------------% +%% Function : define_property_with_mode +%% Arguments : +%% Description: +%% Returns : {ok, State} +%%---------------------------------------------------------------------- +define_property_with_mode(_OE_THIS, State, _, _, _) when ?is_NotSetDef(State) -> + corba:raise(#'NO_IMPLEMENT'{completion_status=?COMPLETED_NO}); +define_property_with_mode(_, _, "", _, _) -> + corba:raise(#'CosPropertyService_InvalidPropertyName'{}); +define_property_with_mode(_OE_THIS, State, Name, Value, Mode) + when ?is_NotStatic(State) -> + evaluate_property_data(State, Value, Name), + _DF = + fun() -> + case mnesia_read(State) of + {'EXCEPTION', E} -> + {'EXCEPTION', E}; + X -> + case catch update_property(X, Name, both, Value, Mode) of + {'EXCEPTION', E} + when is_record(E, 'CosPropertyService_PropertyNotFound') -> + mnesia_write(State, [{Name, Value, Mode}|X]); + {'EXCEPTION', E} -> + {'EXCEPTION', E}; + NewProperties -> + mnesia_write(State, NewProperties) + end + end + end, + {reply, mnesia_transaction(_DF), State}; +define_property_with_mode(_OE_THIS, State, Name, Value, Mode) -> + evaluate_property_data(State, Value, Name), + X = lookup_table(?get_DBKey(State)), + case catch update_property(X, Name, both, Value, Mode) of + {'EXCEPTION', E} when is_record(E, 'CosPropertyService_PropertyNotFound') -> + %% Should get not allowed exception. + corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO}); + {'EXCEPTION', E} -> + corba:raise(E); + _ -> + %% Should be impossible. + corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO}) + end. + +%%---------------------------------------------------------------------% +%% Function : define_properties_with_modes +%% Arguments : +%% Description: +%% Returns : {ok, State} +%%---------------------------------------------------------------------- +define_properties_with_modes(_OE_THIS, State, _) when ?is_NotSetDef(State) -> + corba:raise(#'NO_IMPLEMENT'{completion_status=?COMPLETED_NO}); +define_properties_with_modes(_OE_THIS, State, PropertyDefSeq) + when ?is_NotStatic(State)-> + {OKProperteDefs, Exc} = evaluate_properties_data(State, PropertyDefSeq), + _DF = + fun() -> + case mnesia_read(State) of + {'EXCEPTION', E} -> + {'EXCEPTION', E}; + X -> + case catch define_properties_with_modes_helper(OKProperteDefs, + X, Exc, State) of + {'EXCEPTION', E} -> + {'EXCEPTION', E}; + NewProperties -> + mnesia_write(State, NewProperties) + end + end + end, + {reply, mnesia_transaction(_DF), State}; +define_properties_with_modes(_OE_THIS, State, PropertyDefSeq) -> + {OKProperteDefs, Exc} = evaluate_properties_data(State, PropertyDefSeq), + X = lookup_table(?get_DBKey(State)), + case define_properties_with_modes_helper(OKProperteDefs, X, Exc, State) of + {'EXCEPTION', E} -> + corba:raise(E); + _ -> + corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO}) + end. + + +define_properties_with_modes_helper([], NewPropertyDefs, [], _State) -> + %% No exceptions found. + NewPropertyDefs; +define_properties_with_modes_helper([], _, Exc, _) -> + {'EXCEPTION', #'CosPropertyService_MultipleExceptions'{exceptions = Exc}}; +define_properties_with_modes_helper([#'CosPropertyService_PropertyDef' + {property_name = Name, + property_value = Value, + property_mode = Mode}|T], X, Exc, State) -> + case catch update_property(X, Name, both, Value, Mode) of + {'EXCEPTION', E} when is_record(E, 'CosPropertyService_PropertyNotFound') -> + define_properties_with_modes_helper(T, [{Name, Value, Mode}|X], Exc, State); + {'EXCEPTION', E} -> + define_properties_with_modes_helper(T, X, + [#'CosPropertyService_PropertyException' + {reason = remap_exception(E), + failing_property_name = Name}|Exc], + State); + NewX -> + define_properties_with_modes_helper(T, NewX, Exc, State) + end. + +%%---------------------------------------------------------------------% +%% Function : get_property_mode +%% Arguments : +%% Description: +%% Returns : {ok, State} +%%---------------------------------------------------------------------- +get_property_mode(_OE_THIS, State, _) when ?is_NotSetDef(State) -> + corba:raise(#'NO_IMPLEMENT'{completion_status=?COMPLETED_NO}); +get_property_mode(_, _, "") -> + corba:raise(#'CosPropertyService_InvalidPropertyName'{}); +get_property_mode(_OE_THIS, State, Name) -> + X = lookup_table(?get_DBKey(State)), + {reply, find_property(X, Name, mode), State}. + +%%---------------------------------------------------------------------% +%% Function : get_property_modes +%% Arguments : +%% Description: +%% Returns : {ok, State} +%%---------------------------------------------------------------------- +get_property_modes(_OE_THIS, State, _) when ?is_NotSetDef(State) -> + corba:raise(#'NO_IMPLEMENT'{completion_status=?COMPLETED_NO}); +get_property_modes(_OE_THIS, State, PropertyNames) -> + X = lookup_table(?get_DBKey(State)), + {reply, get_property_modes_helper(PropertyNames, X, [], true), State}. + +get_property_modes_helper([], _, Acc, Bool) -> + {Bool, Acc}; +get_property_modes_helper([""|T], Properties, Acc, _) -> + get_property_modes_helper(T, Properties, + [#'CosPropertyService_PropertyMode' + {property_name = "", + property_mode = undefined}|Acc], false); +get_property_modes_helper([Name|T], Properties, Acc, Bool) -> + case lists:keysearch(Name, 1, Properties) of + {value, {Name, _, Mode}} -> + get_property_modes_helper(T, Properties, + [#'CosPropertyService_PropertyMode' + {property_name = Name, + property_mode = Mode}|Acc], Bool); + false -> + get_property_modes_helper(T, Properties, + [#'CosPropertyService_PropertyMode' + {property_name = Name, + property_mode = undefined}|Acc], false) + end. + +%%---------------------------------------------------------------------% +%% Function : set_property_mode +%% Arguments : +%% Description: +%% Returns : {ok, State} +%%---------------------------------------------------------------------- +set_property_mode(_OE_THIS, State, _, _) when ?is_NotSetDef(State) -> + corba:raise(#'NO_IMPLEMENT'{completion_status=?COMPLETED_NO}); +set_property_mode(_, _, "", _) -> + corba:raise(#'CosPropertyService_InvalidPropertyName'{}); +set_property_mode(_OE_THIS, State, Name, Mode) when ?is_NotStatic(State) -> + _DF = + fun() -> + case mnesia_read(State) of + {'EXCEPTION', E} -> + {'EXCEPTION', E}; + X -> + case catch update_property(X, Name, mode, undefined, Mode) of + {'EXCEPTION', E} -> + {'EXCEPTION', E}; + NewProperties -> + mnesia_write(State, NewProperties) + end + end + end, + {reply, mnesia_transaction(_DF), State}; +set_property_mode(_OE_THIS, State, Name, Mode) -> + X = lookup_table(?get_DBKey(State)), + update_property(X, Name, mode, undefined, Mode), + %% Something is not correct, shouldn't be allowed to update a property when + %% static. + corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO}). + +%%---------------------------------------------------------------------% +%% Function : set_property_modes +%% Arguments : +%% Description: +%% Returns : {ok, State} +%%---------------------------------------------------------------------- +set_property_modes(_OE_THIS, State, _) when ?is_NotSetDef(State) -> + corba:raise(#'NO_IMPLEMENT'{completion_status=?COMPLETED_NO}); +set_property_modes(_OE_THIS, State, PropertyModes) when ?is_NotStatic(State) -> + _DF = + fun() -> + case mnesia_read(State) of + {'EXCEPTION', E} -> + {'EXCEPTION', E}; + X -> + case catch set_property_modes_helper(PropertyModes, X, [], + State) of + {'EXCEPTION', E} -> + {'EXCEPTION', E}; + NewProperties -> + mnesia_write(State, NewProperties) + end + end + end, + {reply, mnesia_transaction(_DF), State}; +set_property_modes(_OE_THIS, State, PropertyModes) -> + X = lookup_table(?get_DBKey(State)), + case set_property_modes_helper(PropertyModes, X, [], State) of + {'EXCEPTION', E} -> + corba:raise(E); + _ -> + corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO}) + end. + +set_property_modes_helper([], NewProperties, [], _State) -> + %% No exceptions, write to DB. + NewProperties; +set_property_modes_helper([], _, Exc, _) -> + {'EXCEPTION', #'CosPropertyService_MultipleExceptions'{exceptions = Exc}}; +set_property_modes_helper([#'CosPropertyService_PropertyMode' + {property_name = Name, + property_mode = Mode}|T], X, Exc, State) -> + case catch update_property(X, Name, mode, undefined, Mode) of + {'EXCEPTION', E} -> + set_property_modes_helper(T, X, + [#'CosPropertyService_PropertyException' + {reason = remap_exception(E), + failing_property_name = Name}|Exc], + State); + NewX -> + set_property_modes_helper(T, NewX, Exc, State) + end. + + +%%====================================================================== +%% Internal functions +%%====================================================================== + +remap_exception(#'CosPropertyService_ConflictingProperty'{}) -> conflicting_property; +remap_exception(#'CosPropertyService_FixedProperty'{}) -> fixed_property; +remap_exception(#'CosPropertyService_InvalidPropertyName'{}) -> invalid_property_name; +remap_exception(#'CosPropertyService_PropertyNotFound'{}) -> property_not_found; +remap_exception(#'CosPropertyService_UnsupportedTypeCode'{}) -> unsupported_type_code; +remap_exception(#'CosPropertyService_UnsupportedProperty'{}) -> unsupported_property; +remap_exception(#'CosPropertyService_ReadOnlyProperty'{}) -> read_only_property; +remap_exception(#'CosPropertyService_UnsupportedMode'{}) -> unsupported_mode. + +find_property([], _, _) -> + corba:raise(#'CosPropertyService_PropertyNotFound'{}); +find_property([{Name, Value, _}|_], Name, value) -> + Value; +find_property([{Name, _, Mode}|_], Name, mode) -> + Mode; +% Left out for now to avoid dialyzer warning. +%find_property([{Name, Value, Mode}|_], Name, all) -> +% {Name, Value, Mode}; +find_property([_|T], Name, Which) -> + find_property(T, Name, Which). + +remove_property(PropertList, Name) -> + remove_property(PropertList, Name, []). +remove_property([], _, _) -> + corba:raise(#'CosPropertyService_PropertyNotFound'{}); +remove_property([{Name, _, fixed_normal}|_T], Name, _) -> + corba:raise(#'CosPropertyService_FixedProperty'{}); +remove_property([{Name, _, fixed_readonly}|_T], Name, _) -> + corba:raise(#'CosPropertyService_FixedProperty'{}); +remove_property([{Name, _, _}|T], Name, Acc) -> + T++Acc; +remove_property([H|T], Name, Acc) -> + remove_property(T, Name, [H|Acc]). + + +update_property(_, "", _, _, _) -> + corba:raise(#'CosPropertyService_InvalidPropertyName'{}); +update_property(PropertyList, Name, Which, Value, Mode) -> + update_property(PropertyList, Name, Which, Value, Mode, []). + +update_property([], _, _, _, _, _) -> + corba:raise(#'CosPropertyService_PropertyNotFound'{}); +update_property([{Name, _, fixed_readonly}|_], Name, value, _, _, _) -> + corba:raise(#'CosPropertyService_FixedProperty'{}); +update_property([{Name, _, fixed_normal}|_], Name, both, _, _, _) -> + corba:raise(#'CosPropertyService_FixedProperty'{}); +update_property([{Name, _, fixed_readonly}|_], Name, both, _, _, _) -> + corba:raise(#'CosPropertyService_FixedProperty'{}); +update_property([{Name, #any{typecode = TC}, Mode}|T], Name, + value, #any{typecode = TC, value = Value}, _Mod, Acc) -> + [{Name, #any{typecode = TC, value = Value}, Mode}|T]++Acc; +update_property([{Name, #any{typecode = TC}, _Mode}|T], Name, + both, #any{typecode = TC, value = Value}, Mod, Acc) -> + [{Name, #any{typecode = TC, value = Value}, Mod}|T]++Acc; +update_property([{Name, _, _}|_], Name, value, _, _, _) -> + corba:raise(#'CosPropertyService_ConflictingProperty'{}); +update_property([{Name, _, _}|_], Name, both, _, _, _) -> + corba:raise(#'CosPropertyService_ConflictingProperty'{}); +%% Normally we don't need to raise an exception for the two following cases but +%% to be able to manage static Properties we must raise an exception. Well, +%% on the other hand, why should a user try to change a mode to the same value?! +%% But we have no other option. +update_property([{Name, _Value, fixed_normal}|_T], Name, mode, _, fixed_normal, _Acc) -> + corba:raise(#'CosPropertyService_FixedProperty'{}); +update_property([{Name, _Value, fixed_readonly}|_T], Name, mode, _, fixed_readonly, _Acc) -> + corba:raise(#'CosPropertyService_FixedProperty'{}); +update_property([{Name, _Value, fixed_normal}|_T], Name, mode, _, _Mode, _Acc) -> + corba:raise(#'CosPropertyService_UnsupportedMode'{}); +update_property([{Name, _Value, fixed_readonly}|_T], Name, mode, _, _Mode, _Acc) -> + corba:raise(#'CosPropertyService_UnsupportedMode'{}); +update_property([{Name, Value, _}|T], Name, mode, _, Mode, Acc) -> + [{Name, Value, Mode}|T]++Acc; +update_property([H|T], Name, Which, Value, Mode, Acc) -> + update_property(T, Name, Which, Value, Mode, [H|Acc]). + + +lookup_table(Key) when is_binary(Key) -> + _RF = ?read_function({oe_CosPropertyService, Key}), + case mnesia:transaction(_RF) of + {atomic, [#oe_CosPropertyService{properties=Properties}]} -> + Properties; + {atomic, []} -> + corba:raise(#'OBJECT_NOT_EXIST'{completion_status=?COMPLETED_NO}); + _Other -> + corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO}) + end; +lookup_table(Key) when is_list(Key) -> + Key; +lookup_table(_) -> + corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO}). + +mnesia_transaction(Fun) -> + case mnesia:transaction(Fun) of + {atomic, {'EXCEPTION', E}} -> + corba:raise(E); + {atomic, ok} -> + ok; + {atomic, Reply} -> + Reply; + _Other -> + corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO}) + end. + +mnesia_read(State) -> + case mnesia:wread({oe_CosPropertyService, ?get_DBKey(State)}) of + [#oe_CosPropertyService{properties = X}] -> + X; + {atomic, []} -> + {'EXCEPTION', #'OBJECT_NOT_EXIST'{completion_status=?COMPLETED_NO}}; + _Other -> + {'EXCEPTION', #'INTERNAL'{completion_status=?COMPLETED_NO}} + end. + +mnesia_write(State, X) -> + mnesia:write(#oe_CosPropertyService{key = ?get_DBKey(State), properties = X}). + +%% Check a write transaction +write_result({atomic,ok}) -> ok; +write_result(_Foo) -> + corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO}). + +evaluate_properties_data(State, PropertySeq) -> + evaluate_properties_data(State, PropertySeq, [], []). + +evaluate_properties_data(_State, [], OKProperties, Exc) -> + {OKProperties, Exc}; + +evaluate_properties_data(State, [#'CosPropertyService_Property' + {property_name = Name, + property_value = Value}|T], Acc, Exc) -> + case catch evaluate_property_data(State, Value, Name) of + ok -> + evaluate_properties_data(State, T, [#'CosPropertyService_Property' + {property_name = Name, + property_value = Value}|Acc], Exc); + {'EXCEPTION', E} when is_record(E, 'CosPropertyService_UnsupportedTypeCode') -> + evaluate_properties_data(State, T, Acc, + [#'CosPropertyService_PropertyException' + {reason = unsupported_type_code, + failing_property_name = Name}|Exc]); + {'EXCEPTION', E} when is_record(E, 'CosPropertyService_UnsupportedProperty') -> + evaluate_properties_data(State, T, Acc, + [#'CosPropertyService_PropertyException' + {reason = unsupported_property, + failing_property_name = Name}|Exc]) + end; +evaluate_properties_data(State, [#'CosPropertyService_PropertyDef' + {property_name = Name, + property_value = Value, + property_mode = Mode}|T], Acc, Exc) -> + case catch evaluate_property_data(State, Value, Name) of + ok -> + evaluate_properties_data(State, T, [#'CosPropertyService_PropertyDef' + {property_name = Name, + property_value = Value, + property_mode = Mode}|Acc], Exc); + {'EXCEPTION', E} when is_record(E, 'CosPropertyService_UnsupportedTypeCode') -> + evaluate_properties_data(State, T, Acc, + [#'CosPropertyService_PropertyException' + {reason = unsupported_type_code, + failing_property_name = Name}|Exc]); + {'EXCEPTION', E} when is_record(E, 'CosPropertyService_UnsupportedProperty') -> + evaluate_properties_data(State, T, Acc, + [#'CosPropertyService_PropertyException' + {reason = unsupported_property, + failing_property_name = Name}|Exc]) + end; +evaluate_properties_data(_, _, _, _) -> + corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO}). + +evaluate_property_data(State, _, _) when ?no_PropertyLimits(State), + ?no_TypeLimits(State) -> + ok; +evaluate_property_data(State, Value, _Name) when ?no_PropertyLimits(State) -> + case lists:member(any:get_typecode(Value), ?get_okTypes(State)) of + true -> + ok; + _ -> + corba:raise(#'CosPropertyService_UnsupportedTypeCode'{}) + end; +evaluate_property_data(State, _Value, Name) when ?no_TypeLimits(State) -> + case lists:any(?MemberName(Name), ?get_okProperties(State)) of + true -> + ok; + _ -> + corba:raise(#'CosPropertyService_UnsupportedProperty'{}) + end; +evaluate_property_data(State, Value, Name) -> + case lists:any(?MemberName(Name), ?get_okProperties(State)) of + true -> + case lists:member(any:get_typecode(Value), ?get_okTypes(State)) of + true -> + ok; + _ -> + corba:raise(#'CosPropertyService_UnsupportedTypeCode'{}) + end; + _ -> + corba:raise(#'CosPropertyService_UnsupportedProperty'{}) + end. + + +%%---------------------------------------------------------------------- +%% Debugging functions +%%---------------------------------------------------------------------- +dump() -> + case catch mnesia:dirty_first('oe_CosPropertyService') of + {'EXIT', R} -> + io:format("Exited with ~p\n",[R]); + Key -> + dump_print(Key), + dump_loop(Key) + end. + +dump_loop(PreviousKey) -> + case catch mnesia:dirty_next('oe_CosPropertyService', PreviousKey) of + {'EXIT', R} -> + io:format("Exited with ~p\n",[R]); + '$end_of_table' -> + ok; + Key -> + dump_print(Key), + dump_loop(Key) + end. + +dump_print(Key) -> + case catch mnesia:dirty_read({'oe_CosPropertyService', Key}) of + {'EXIT', R} -> + io:format("Exited with ~p\n",[R]); + [{_,_,X}] -> + io:format("Property: ~p~n", [X]); + _ -> + ok + end. + + +%%-------------------------- END OF MODULE ----------------------------- |