1%%--------------------------------------------------------------------
2%%
3%% %CopyrightBegin%
4%%
5%% Copyright Ericsson AB 1999-2015. All Rights Reserved.
6%%
7%% Licensed under the Apache License, Version 2.0 (the "License");
8%% you may not use this file except in compliance with the License.
9%% You may obtain a copy of the License at
10%%
11%%     http://www.apache.org/licenses/LICENSE-2.0
12%%
13%% Unless required by applicable law or agreed to in writing, software
14%% distributed under the License is distributed on an "AS IS" BASIS,
15%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16%% See the License for the specific language governing permissions and
17%% limitations under the License.
18%%
19%% %CopyrightEnd%
20%%
21%%
22%%--------------------------------------------------------------------
23%% File    : CosNotification_Common.erl
24%% Purpose :
25%%--------------------------------------------------------------------
26
27-module('CosNotification_Common').
28
29
30%%--------------- INCLUDES -----------------------------------
31-include_lib("orber/include/corba.hrl").
32%% Application files
33-include("CosNotification.hrl").
34-include("CosNotifyChannelAdmin.hrl").
35-include("CosNotifyComm.hrl").
36-include("CosNotifyFilter.hrl").
37
38-include("CosNotification_Definitions.hrl").
39
40%%--------------- EXPORTS ------------------------------------
41%% External MISC
42-export([get_option/3,
43         create_name/0,
44         create_name/1,
45         create_name/2,
46	 create_id/0,
47	 create_id/1,
48         is_debug_compiled/0,
49	 type_check/2,
50         send_stubborn/5,
51         create_link/3,
52	 disconnect/3,
53	 do_disconnect/3,
54	 notify/1]).
55
56%% Internal AdminProperties
57-export([init_adm/1,
58	 set_adm/2,
59	 'MaxQueueLength'/6,
60	 'MaxConsumers'/6,
61	 'MaxSuppliers'/6]).
62%% Internal QoS
63-export([init_qos/1,
64	 set_qos/5,
65	 validate_qos/5,
66	 validate_event_qos/2,
67	 'EventReliability'/6,
68	 'ConnectionReliability'/6,
69	 'Priority'/6,
70	 'StartTimeSupported'/6,
71	 'StopTimeSupported'/6,
72	 'Timeout'/6,
73	 'OrderPolicy'/6,
74	 'DiscardPolicy'/6,
75	 'MaximumBatchSize'/6,
76	 'PacingInterval'/6,
77	 'MaxEventsPerConsumer'/6]).
78
79%%--------------- DEFINITIONS OF CONSTANTS -------------------
80%%--------------- EXTERNAL MISC FUNCTIONS --------------------
81%%------------------------------------------------------------
82%% function : create_link
83%% Arguments: Module - which Module to call
84%%            Env/ArgList - ordinary oe_create arguments.
85%% Returns  :
86%% Exception:
87%% Effect   : Necessary since we want the supervisor to be a
88%%            'simple_one_for_one'. Otherwise, using for example,
89%%            'one_for_one', we have to call supervisor:delete_child
90%%            to remove the childs startspecification from the
91%%            supervisors internal state.
92%%------------------------------------------------------------
93create_link(Module, Env, ArgList) ->
94    Module:oe_create_link(Env, ArgList).
95
96%%-----------------------------------------------------------%
97%% function : get_option
98%% Arguments:
99%% Returns  :
100%% Exception:
101%% Effect   :
102%%------------------------------------------------------------
103get_option(Key, OptionList, DefaultList) ->
104    case lists:keysearch(Key, 1, OptionList) of
105        {value,{Key,Value}} ->
106            Value;
107        _ ->
108            case lists:keysearch(Key, 1, DefaultList) of
109                {value,{Key,Value}} ->
110                    Value;
111                _->
112                    {error, "Invalid option"}
113            end
114    end.
115
116%%------------------------------------------------------------
117%% function : create_name
118%% Arguments:
119%% Returns  :
120%% Effect   : Create a unique name to use when, for eaxmple, starting
121%%            a new server.
122%%------------------------------------------------------------
123create_name() ->
124    Time = erlang:system_time(),
125    Unique = erlang:unique_integer([positive]),
126    lists:concat(['oe_',node(),'_',Time,'_',Unique]).
127
128
129%%-----------------------------------------------------------%
130%% function : create_name/1
131%% Arguments:
132%% Returns  :
133%% Exception:
134%% Effect   :
135%%------------------------------------------------------------
136create_name(Type) ->
137    Time = erlang:system_time(),
138    Unique = erlang:unique_integer([positive]),
139    lists:concat(['oe_',node(),'_',Type,'_',Time,'_',Unique]).
140
141%%-----------------------------------------------------------%
142%% function : create_name/2
143%% Arguments:
144%% Returns  :
145%% Exception:
146%% Effect   :
147%%------------------------------------------------------------
148create_name(Name,Type) ->
149    Time = erlang:system_time(),
150    Unique = erlang:unique_integer([positive]),
151    lists:concat(['oe_',node(),'_',Type,'_',Name,'_',Time,'_',Unique]).
152
153%%------------------------------------------------------------
154%% function : create_id/0
155%% Arguments: -
156%% Returns  : id (long) =/= 0
157%%            Both default Admin:s have the unique id 0 (OMG spec, 98-11-01,
158%%            Notification p 148), hence, we may not return 0.
159%% Exception:
160%% Purpose  : Throughout the CosNotification service we use,
161%%            according to the OMG specification, id:s (long),
162%%            which must be "unique", to retrieve object references.
163%%            For example: CosNotifyChannelAdmin::ChannelId/AdminID.
164%%------------------------------------------------------------
165create_id(-1) ->
166    1;
167create_id(2147483647) ->
168    -2147483648;
169create_id(OldID) ->
170    OldID+1.
171
172create_id() ->
173    {_A,_B,C}=erlang:timestamp(),
174    C.
175
176%%------------------------------------------------------------
177%% function : type_check
178%% Arguments: Obj  - objectrefernce to test.
179%%            Mod  - Module which contains typeID/0.
180%% Returns  : 'ok' or raises exception.
181%% Effect   :
182%%------------------------------------------------------------
183type_check(Obj, Mod) ->
184    case cosNotificationApp:type_check() of
185	false ->
186	    ok;
187	_ ->
188	    case catch corba_object:is_a(Obj,Mod:typeID()) of
189		true ->
190		    ok;
191		false ->
192		    orber:dbg("[~p] CosNotification_Common:type_check(~p);~n"
193			      "The supplied Object is not or does not inherrit from: ~p",
194			      [?LINE, Obj, Mod], ?DEBUG_LEVEL),
195		    corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO});
196		{'EXCEPTION', E} ->
197		    orber:dbg("[~p] CosNotification_Common:type_check(~p, ~p);~n"
198			      "Failed due to: ~p",
199			      [?LINE, Obj, Mod, E], ?DEBUG_LEVEL),
200		    corba:raise(E);
201		What ->
202		    orber:dbg("[~p] CosNotification_Common:type_check(~p, ~p);~n"
203			      "Failed due to: ~p",
204			      [?LINE, Obj, Mod, What], ?DEBUG_LEVEL),
205		    corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO})
206	    end
207    end.
208
209
210%%-----------------------------------------------------------%
211%% function : notify
212%% Arguments: Items - [Item]
213%%            Item - {proxy, IOR} | {client, IOR} | {reason, term()}
214%% Returns  : 'ok' or raises exception.
215%% Effect   :
216%%------------------------------------------------------------
217notify(Items) ->
218    case cosNotificationApp:notify() of
219	false ->
220	    ok;
221	Module ->
222	    catch Module:terminated(Items),
223	    ok
224    end.
225
226
227%%------------------------------------------------------------
228%% function : send_stubborn
229%% Arguments: M - module
230%%            F - function
231%%            A - arguments
232%%            MaxR - Maximum no retries
233%%            Wait - sleep Wait seconds before next try.
234%% Returns  : see effect
235%% Exception:
236%% Effect   : Retries repeatidly untill anything else besides
237%%            'EXIT', 'COMM_FAILURE' or 'OBJECT_NOT_EXIST'
238%%------------------------------------------------------------
239
240send_stubborn(M, F, A, MaxR, Wait) when is_list(A) ->
241    send_stubborn(M, F, A, MaxR, Wait, 0);
242send_stubborn(M, F, A, MaxR, Wait) ->
243    send_stubborn(M, F, [A], MaxR, Wait, 0).
244send_stubborn(M, F, A, MaxR, _Wait, MaxR) ->
245    orber:dbg("[~p] CosNotification_Common:send_stubborn( ~p ~p ~p ~p).~n"
246	      "Failed to deliver the event.~n", [?LINE, M,F,A,MaxR], ?DEBUG_LEVEL),
247    corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO});
248send_stubborn(M, F, A, MaxR, Wait, Times) ->
249    ?debug_print("~p:~p(~p)  # of retries: ~p~n", [M,F,A, Times]),
250    case catch apply(M,F,A) of
251        {'EXCEPTION', E} when is_record(E, 'COMM_FAILURE')->
252            NewTimes = Times +1,
253            timer:sleep(Wait),
254            send_stubborn(M, F, A, MaxR, Wait, NewTimes);
255        {'EXIT', _} ->
256            NewTimes = Times +1,
257            timer:sleep(Wait),
258            send_stubborn(M, F, A, MaxR, Wait, NewTimes);
259        Other ->
260            Other
261    end.
262
263
264%%-----------------------------------------------------------%
265%% function : disconnect
266%% Arguments: Module - one of the interfaces defined in CosEventComm.
267%%            Function - the appropriate disconnect function.
268%%            Object - the client object reference.
269%% Returns  : ok
270%% Exception:
271%% Effect   : If the process would try to diconnect itself it could
272%%            result in a deadlock. Hence, we spawn a new process to do it.
273%%------------------------------------------------------------
274disconnect(Module, Function, Object) ->
275    spawn(?MODULE, do_disconnect, [Module, Function, Object]),
276    ok.
277
278do_disconnect(Module, Function, Object) ->
279    catch Module:Function(Object),
280    ?DBG("Disconnect ~p:~p(..).~n", [Module, Function]),
281    ok.
282
283
284
285%%------------------------------------------------------------
286%% function : is_debug_compiled
287%% Arguments:
288%% Returns  :
289%% Exception:
290%% Effect   :
291%%------------------------------------------------------------
292
293-ifdef(debug).
294    is_debug_compiled() -> true.
295-else.
296    is_debug_compiled() -> false.
297-endif.
298
299
300%%------------------------------------------------------------
301%%--------------- AdminPropertiesAdmin -----------------------
302%%------------------------------------------------------------
303%%------------------------------------------------------------
304%% function : init_adm
305%% Arguments: Wanted  - requested Admins to be set.
306%% Returns  : #'CosNotification_UnsupportedAdmin'{} |
307%%            {NewAdmProperties, [MaxQ, MaxC, MaxS]}
308%% Effect   : may only be used when creating a channel!!!!!!!!
309%%------------------------------------------------------------
310init_adm(Wanted) ->
311    {NewA,_} = set_properties(Wanted, ?not_DEFAULT_ADMINPROPERTIES, channelAdm,
312			      ?not_SUPPORTED_ADMINPROPERTIES, [], [],
313			      false, false, false),
314    {NewA, [extract_value(NewA, ?not_MaxQueueLength),
315	    extract_value(NewA, ?not_MaxConsumers),
316	    extract_value(NewA, ?not_MaxSuppliers)]}.
317
318set_adm(Wanted, Current) ->
319    {NewA,_} = set_properties(Wanted, Current, channelAdm,
320			      ?not_SUPPORTED_ADMINPROPERTIES,
321			      [], [], false, false, false),
322    {NewA, [extract_value(NewA, ?not_MaxQueueLength),
323	    extract_value(NewA, ?not_MaxConsumers),
324	    extract_value(NewA, ?not_MaxSuppliers)]}.
325
326'MaxQueueLength'(Req,channelAdm,_, _, _, _) -> admin_ok(Req).
327'MaxConsumers'(Req,channelAdm,_, _, _, _)->    admin_ok(Req).
328'MaxSuppliers'(Req,channelAdm,_, _, _, _)->    admin_ok(Req).
329
330admin_ok(Req) ->
331    case any:get_value(Req#'CosNotification_Property'.value) of
332	Val when is_integer(Val) andalso Val >= 0 ->
333	    {ok, Req};
334	_  ->
335	    {unsupported,
336	     #'CosNotification_PropertyError'{
337	       code = 'BAD_TYPE',
338	       name = Req#'CosNotification_Property'.name,
339	       available_range = #'CosNotification_PropertyRange'{
340		 low_val=any:create(orber_tc:null(), null),
341		 high_val=any:create(orber_tc:null(), null)
342		}
343	      }
344	    }
345    end.
346
347
348%%------------------------------------------------------------
349%%--------------- QOS FUNCTIONS ------------------------------
350%%------------------------------------------------------------
351%%------------------------------------------------------------
352%% function : init_qos
353%% Arguments: Wanted  - requested QoS to be set.
354%% Returns  : see set_properties/9
355%% Effect   : may only be used when creating a channel!!!!!!!!
356%%------------------------------------------------------------
357init_qos(Wanted) ->
358    LQS = set_local_qos(?not_DEFAULT_QOS, ?not_CreateInitQoS()),
359    set_properties(Wanted, ?not_DEFAULT_QOS, channel, ?not_SUPPORTED_QOS,
360		   [], [], false, [], LQS).
361
362%%------------------------------------------------------------
363%% function : set_qos/5
364%% Arguments: Wanted  - requested QoS to be set.
365%%            Current - current QoS OMG style
366%%            LQS     - local representation of QoS.
367%%            Type    - channel | admin | proxy
368%%            Parent  - Factory if Channel, Channel if Admin etc
369%%            Childs  - Admins if Channel etc
370%% Returns  : see set_properties/9
371%%------------------------------------------------------------
372set_qos(Wanted, {Current, LQS}, proxy, Parent, _) ->
373    set_properties(Wanted, Current, proxy, ?not_SUPPORTED_QOS, [], [], Parent, false,LQS);
374set_qos(Wanted, {Current, LQS}, admin, Parent, Childs) ->
375    set_properties(Wanted, Current, admin, ?not_SUPPORTED_QOS, [], [], Parent, Childs,LQS);
376set_qos(Wanted, {Current, LQS}, channel, _, Childs) ->
377    set_properties(Wanted, Current, channel, ?not_SUPPORTED_QOS, [], [], false, Childs,LQS).
378
379%%------------------------------------------------------------
380%% function :
381%% Arguments: Req    - Requested QoS, #'CosNotification_Property'{}
382%%            Type   - Requestee, channel | admin | proxy
383%%            Curr   - Current QoS, #'CosNotification_Property'{}
384%%            Parent - false | ObjRef
385%%            Childs - false | [ObjRef1, .., ObjRefN]
386%%            LQS    - #qos{} defined in CosNotification_Definitions.hrl
387%% Returns  : ok - if requested equal to current value.
388%%            {ok, Req, LQS} - if new and allowed QoS
389%%            {unsupported,#'CosNotification_PropertyError'{}} otherwise.
390%% Effect   :
391%%------------------------------------------------------------
392'EventReliability'(Req,channel, _Curr, _Parent, _Childs, LQS) ->
393    case {any:get_value(Req#'CosNotification_Property'.value),
394	  ?not_GetConnectionReliability(LQS), ?not_BestEffort, ?not_Persistent} of
395	{Val, Val, _, _} ->
396	    %% Is the value requested.
397	    ok;
398	{Val, _, Val, _} ->
399	    {ok, Req, LQS};
400	{Val, _, _, Val} ->
401	    {ok, Req, LQS};
402	_->
403	    {unsupported,
404	     #'CosNotification_PropertyError'{
405	       code = 'BAD_TYPE',
406	       name = Req#'CosNotification_Property'.name,
407	       available_range = #'CosNotification_PropertyRange'{
408		 low_val=any:create(orber_tc:null(), null),
409		 high_val=any:create(orber_tc:null(), null)
410		}
411	      }
412	    }
413    end;
414'EventReliability'(Req,_,_,_,_,_) ->
415    %% only valid to set this QoS for channels (or per-event).
416    {unsupported,
417     #'CosNotification_PropertyError'{
418       code = 'UNAVAILABLE_PROPERTY',
419       name = Req#'CosNotification_Property'.name,
420       available_range = #'CosNotification_PropertyRange'{
421	 low_val=any:create(orber_tc:null(), null),
422	 high_val=any:create(orber_tc:null(), null)
423	}
424      }
425    }.
426
427%%------------------------------------------------------------
428%% function : 'ConnectionReliability'/6
429%% Arguments: Req    - Requested QoS, #'CosNotification_Property'{}
430%%            Type   - Requestee, channel | admin | proxy
431%%            Curr   - Current QoS, #'CosNotification_Property'{}
432%%            Parent - false | ObjRef
433%%            Childs - false | [ObjRef1, .., ObjRefN]
434%%            LQS    - #qos{} defined in CosNotification_Definitions.hrl
435%% Returns  :
436%% Exception:
437%% Effect   :
438%%------------------------------------------------------------
439%% The most complex QoS to set is ConnectionReliability, and the reason for this
440%% is that we cannot set the Channel to offer best effort while its children
441%% offer persistent. A child may only offer Persistent if its parent do, which
442%% is why we must check the following:
443%%
444%%                    #    Persistent        Change to       Best Effort
445%%            _____
446%%           |     | (1)                         ->       Check if children BE
447%%           |Chann| (2)      ok                 <-
448%%            -----
449%%              |
450%%            _____
451%%           |     | (3)                         ->      Check if children BE
452%%           |Admin| (4)  Check if parent Pers.  <-
453%%            -----
454%%              |
455%%            _____
456%%           |     | (5)                         ->               ok
457%%           |Proxy| (6) Check if parent Pers.   <-
458%%            -----
459%% NOTE: a parent always exists but we may change the QoS before creating any
460%% childrens. The cases (2) and (5) is always ok, i.e., no need to confirm
461%% with parent or children.
462%%------------------------------------------------------------
463'ConnectionReliability'(Req, channel, _Curr, _Parent, Childs, LQS) ->
464    case {any:get_value(Req#'CosNotification_Property'.value),
465	  ?not_GetConnectionReliability(LQS), ?not_BestEffort, ?not_Persistent} of
466	{Val, Val, _, _} ->
467	    %% Is the value requested.
468	    ok;
469	{Val, P, Val, P} ->
470	    %% Requested is BestEffort, Current Persistent => (1)
471	    check_with_relatives(Childs, Req, LQS);
472	{Val, B, B, Val} ->
473	    %% Requested is Persistent, Current BestEffort => (2)
474	    {ok, Req, LQS};
475	_->
476	    {unsupported,
477	     #'CosNotification_PropertyError'{
478	       code = 'BAD_TYPE',
479	       name = Req#'CosNotification_Property'.name,
480	       available_range = #'CosNotification_PropertyRange'{
481		 low_val=any:create(orber_tc:null(), null),
482		 high_val=any:create(orber_tc:null(), null)
483		}
484	      }
485	    }
486    end;
487'ConnectionReliability'(Req, admin, _Curr, Parent, Childs, LQS) ->
488    case {any:get_value(Req#'CosNotification_Property'.value),
489	  ?not_GetConnectionReliability(LQS), ?not_BestEffort, ?not_Persistent} of
490	{Val, Val, _, _} ->
491	    %% Is the value requested.
492	    ok;
493	{Val, P, Val, P} ->
494	    %% Requested is BestEffort, Current Persistent => (3)
495	    check_with_relatives(Childs, Req, LQS);
496	{Val, B, B, Val} ->
497	    %% Requested is Persistent, Current BestEffort => (4)
498	    check_with_relatives([Parent], Req, LQS);
499	_->
500	    {unsupported,
501	     #'CosNotification_PropertyError'{
502	       code = 'BAD_TYPE',
503	       name = Req#'CosNotification_Property'.name,
504	       available_range = #'CosNotification_PropertyRange'{
505		 low_val=any:create(orber_tc:null(), null),
506		 high_val=any:create(orber_tc:null(), null)
507		}
508	      }
509	    }
510    end;
511'ConnectionReliability'(Req, proxy, _Curr, Parent, _Childs, LQS) ->
512    case {any:get_value(Req#'CosNotification_Property'.value),
513	  ?not_GetConnectionReliability(LQS), ?not_BestEffort, ?not_Persistent} of
514	{Val, Val, _, _} ->
515	    %% Is the value requested.
516	    ok;
517	{Val, P, Val, P} ->
518	    %% Requested is BestEffort, Current Persistent => (5)
519	    {ok, Req, LQS};
520	{Val, B, B, Val} ->
521	    %% Requested is Persistent, Current BestEffort => (6)
522	    check_with_relatives([Parent], Req, LQS);
523	_->
524	    {unsupported,
525	     #'CosNotification_PropertyError'{
526	       code = 'BAD_TYPE',
527	       name = Req#'CosNotification_Property'.name,
528	       available_range = #'CosNotification_PropertyRange'{
529		 low_val=any:create(orber_tc:null(), null),
530		 high_val=any:create(orber_tc:null(), null)
531		}
532	      }
533	    }
534    end.
535
536%%------------------------------------------------------------
537%% function : 'Priority'/6
538%% Arguments: Req    - Requested QoS, #'CosNotification_Property'{}
539%%            Type   - Requestee, channel | admin | proxy
540%%            Curr   - Current QoS, #'CosNotification_Property'{}
541%%            Parent - false | ObjRef
542%%            Childs - false | [ObjRef1, .., ObjRefN]
543%%            LQS    - #qos{} defined in CosNotification_Definitions.hrl
544%% Returns  :
545%% Effect   :
546%%------------------------------------------------------------
547'Priority'(Req, _Type, _Curr, _Parent, _Childs, LQS) ->
548    case {any:get_value(Req#'CosNotification_Property'.value),
549	  ?not_GetPriority(LQS), ?not_HighestPriority, ?not_LowestPriority} of
550	{Val, Val, _, _} ->
551	    ok;
552	{Val, _, H, L} when Val =< H, Val >= L ->
553	    {ok, Req, LQS};
554	{_, _, H, L} ->
555	    {unsupported,
556	     #'CosNotification_PropertyError'{
557	       code = 'BAD_VALUE',
558	       name = Req#'CosNotification_Property'.name,
559	       available_range =
560	       #'CosNotification_PropertyRange'{
561		 low_val=any:create(orber_tc:short(), L),
562		 high_val=any:create(orber_tc:short(), H)
563		}
564	      }
565	    }
566    end.
567
568%%------------------------------------------------------------
569%% function : 'StartTimeSupported'/6
570%% Arguments: Req    - Requested QoS, #'CosNotification_Property'{}
571%%            Type   - Requestee, channel | admin | proxy
572%%            Curr   - Current QoS, #'CosNotification_Property'{}
573%%            Parent - false | ObjRef
574%%            Childs - false | [ObjRef1, .., ObjRefN]
575%%            LQS    - #qos{} defined in CosNotification_Definitions.hrl
576%% Returns  :
577%% Effect   :
578%%------------------------------------------------------------
579'StartTimeSupported'(Req, _Type, _Curr, _, _, LQS) ->
580    case {any:get_value(Req#'CosNotification_Property'.value),
581	  ?not_GetStartTimeSupported(LQS)} of
582	{Val, Val} ->
583	    ok;
584	{Val, _} when Val =/= true, Val =/= false ->
585	    {unsupported,
586	     #'CosNotification_PropertyError'{
587	       code = 'BAD_VALUE',
588	       name = Req#'CosNotification_Property'.name,
589	       available_range =
590	       #'CosNotification_PropertyRange'{
591		 low_val=any:create(orber_tc:boolean(), false),
592		 high_val=any:create(orber_tc:boolean(), true)
593		}
594	      }
595	    };
596	_->
597	    {ok, Req, LQS}
598    end.
599
600%%------------------------------------------------------------
601%% function : 'StopTimeSupported'/6
602%% Arguments: Req    - Requested QoS, #'CosNotification_Property'{}
603%%            Type   - Requestee, channel | admin | proxy
604%%            Curr   - Current QoS, #'CosNotification_Property'{}
605%%            Parent - false | ObjRef
606%%            Childs - false | [ObjRef1, .., ObjRefN]
607%%            LQS    - #qos{} defined in CosNotification_Definitions.hrl
608%% Returns  :
609%% Effect   :
610%%------------------------------------------------------------
611'StopTimeSupported'(Req, _Type, _Curr, _, _, LQS) ->
612    case {any:get_value(Req#'CosNotification_Property'.value),
613	  ?not_GetStopTimeSupported(LQS)} of
614	{Val, Val} ->
615	    ok;
616	{Val, _} when Val =/= true, Val =/= false ->
617	    {unsupported,
618	     #'CosNotification_PropertyError'{
619	       code = 'BAD_VALUE',
620	       name = Req#'CosNotification_Property'.name,
621	       available_range =
622	       #'CosNotification_PropertyRange'{
623		 low_val=any:create(orber_tc:boolean(), false),
624		 high_val=any:create(orber_tc:boolean(), true)
625		}
626	      }
627	    };
628	_->
629	    {ok, Req, LQS}
630    end.
631
632%%------------------------------------------------------------
633%% function : 'Timeout'/6
634%% Arguments: Req    - Requested QoS, #'CosNotification_Property'{}
635%%            Type   - Requestee, channel | admin | proxy
636%%            Curr   - Current QoS, #'CosNotification_Property'{}
637%%            Parent - false | ObjRef
638%%            Childs - false | [ObjRef1, .., ObjRefN]
639%%            LQS    - #qos{} defined in CosNotification_Definitions.hrl
640%% Returns  :
641%% Effect   :
642%%------------------------------------------------------------
643'Timeout'(Req, _Type, _Curr, _Parent, _Childs, LQS) ->
644    case {any:get_value(Req#'CosNotification_Property'.value),
645	  ?not_GetTimeout(LQS)} of
646	{Val, Val} ->
647	    ok;
648	{Val, _} when Val >= ?not_MinTimeout, Val =< ?not_MaxTimeout ->
649	    {ok, Req, LQS};
650	{Val, _} when is_integer(Val) ->
651	    {unsupported,
652	     #'CosNotification_PropertyError'{
653	       code = 'BAD_VALUE',
654	       name = Req#'CosNotification_Property'.name,
655	       available_range =
656	       #'CosNotification_PropertyRange'{
657		 low_val=any:create(orber_tc:unsigned_long_long(), ?not_MinTimeout),
658		 high_val=any:create(orber_tc:unsigned_long_long(), ?not_MaxTimeout)
659		}
660	      }
661	    };
662	_->
663	    {unsupported,
664	     #'CosNotification_PropertyError'{
665	       code = 'BAD_TYPE',
666	       name = Req#'CosNotification_Property'.name,
667	       available_range = #'CosNotification_PropertyRange'{
668		 low_val=any:create(orber_tc:null(), null),
669		 high_val=any:create(orber_tc:null(), null)
670		}
671	      }
672	    }
673    end.
674
675%%------------------------------------------------------------
676%% function : 'OrderPolicy'/6
677%% Arguments: Req    - Requested QoS, #'CosNotification_Property'{}
678%%            Type   - Requestee, channel | admin | proxy
679%%            Curr   - Current QoS, #'CosNotification_Property'{}
680%%            Parent - false | ObjRef
681%%            Childs - false | [ObjRef1, .., ObjRefN]
682%%            LQS    - #qos{} defined in CosNotification_Definitions.hrl
683%% Returns  :
684%% Effect   :
685%%------------------------------------------------------------
686'OrderPolicy'(Req, _Type, _Curr, _Parent, _Childs, LQS) ->
687    case {any:get_value(Req#'CosNotification_Property'.value),
688	  ?not_GetOrderPolicy(LQS), 'CosNotification':'AnyOrder'(),
689	  'CosNotification':'PriorityOrder'()} of
690	{Val, Val,_,_} ->
691	    ok;
692	{Val, _, L, H} when Val >= L, Val =< H ->
693	    {ok, Req, LQS};
694	{Val, _, L, H} when is_integer(Val) ->
695	    {unsupported,
696	     #'CosNotification_PropertyError'{
697	       code = 'BAD_VALUE',
698	       name = Req#'CosNotification_Property'.name,
699	       available_range =
700	       #'CosNotification_PropertyRange'{
701		 low_val=any:create(orber_tc:short(), L),
702		 high_val=any:create(orber_tc:short(), H)
703		}
704	      }
705	    };
706	_->
707	    {unsupported,
708	     #'CosNotification_PropertyError'{
709	       code = 'BAD_TYPE',
710	       name = Req#'CosNotification_Property'.name,
711	       available_range = #'CosNotification_PropertyRange'{
712		 low_val=any:create(orber_tc:null(), null),
713		 high_val=any:create(orber_tc:null(), null)
714		}
715	      }
716	    }
717    end.
718
719
720%%------------------------------------------------------------
721%% function : 'DiscardPolicy'/6
722%% Arguments: Req    - Requested QoS, #'CosNotification_Property'{}
723%%            Type   - Requestee, channel | admin | proxy
724%%            Curr   - Current QoS, #'CosNotification_Property'{}
725%%            Parent - false | ObjRef
726%%            Childs - false | [ObjRef1, .., ObjRefN]
727%%            LQS    - #qos{} defined in CosNotification_Definitions.hrl
728%% Returns  :
729%% Effect   :
730%%------------------------------------------------------------
731'DiscardPolicy'(Req, _Type, _Curr, _Parent, _Childs, LQS) ->
732    case {any:get_value(Req#'CosNotification_Property'.value),
733	  ?not_GetDiscardPolicy(LQS), ?not_AnyOrder, ?not_PriorityOrder} of
734	{Val, Val,_,_} ->
735	    ok;
736	{Val, _, L, H} when Val >= L, Val =< H ->
737	    {ok, Req, LQS};
738	{Val, _, L, H} when is_integer(Val) ->
739	    {unsupported,
740	     #'CosNotification_PropertyError'{
741	       code = 'BAD_VALUE',
742	       name = Req#'CosNotification_Property'.name,
743	       available_range =
744	       #'CosNotification_PropertyRange'{
745		 low_val=any:create(orber_tc:short(), L),
746		 high_val=any:create(orber_tc:short(), H)
747		}
748	      }
749	    };
750	_->
751	    {unsupported,
752	     #'CosNotification_PropertyError'{
753	       code = 'BAD_TYPE',
754	       name = Req#'CosNotification_Property'.name,
755	       available_range = #'CosNotification_PropertyRange'{
756		 low_val=any:create(orber_tc:null(), null),
757		 high_val=any:create(orber_tc:null(), null)
758		}
759	      }
760	    }
761    end.
762
763%%------------------------------------------------------------
764%% function : 'DiscardPolicy'/6
765%% Arguments: Req    - Requested QoS, #'CosNotification_Property'{}
766%%            Type   - Requestee, channel | admin | proxy
767%%            Curr   - Current QoS, #'CosNotification_Property'{}
768%%            Parent - false | ObjRef
769%%            Childs - false | [ObjRef1, .., ObjRefN]
770%%            LQS    - #qos{} defined in CosNotification_Definitions.hrl
771%% Returns  :
772%% Effect   :
773%%------------------------------------------------------------
774'MaximumBatchSize'(Req, _Type, _Curr, _Parent, _Childs, LQS) ->
775    case {any:get_value(Req#'CosNotification_Property'.value),
776	  ?not_GetMaximumBatchSize(LQS)} of
777	{Val, Val} ->
778	    ok;
779	{Val, _} when Val >= ?not_MinBatchSize, Val =< ?not_MaxBatchSize ->
780	    {ok, Req, LQS};
781	{Val, _} when is_integer(Val) ->
782	    {unsupported,
783	     #'CosNotification_PropertyError'{
784	       code = 'BAD_VALUE',
785	       name = Req#'CosNotification_Property'.name,
786	       available_range =
787	       #'CosNotification_PropertyRange'{
788		 low_val=any:create(orber_tc:unsigned_long_long(), ?not_MinBatchSize),
789		 high_val=any:create(orber_tc:unsigned_long_long(), ?not_MaxBatchSize)
790		}
791	      }
792	    };
793	_->
794	    {unsupported,
795	     #'CosNotification_PropertyError'{
796	       code = 'UNSUPPORTED_VALUE',
797	       name = Req#'CosNotification_Property'.name,
798	       available_range =
799	       #'CosNotification_PropertyRange'{
800		 low_val=any:create(orber_tc:long(), ?not_MinBatchSize),
801		 high_val=any:create(orber_tc:long(), ?not_MaxBatchSize)
802		}
803	      }
804	    }
805    end.
806
807%%------------------------------------------------------------
808%% function : 'PacingInterval'/6
809%% Arguments: Req    - Requested QoS, #'CosNotification_Property'{}
810%%            Type   - Requestee, channel | admin | proxy
811%%            Curr   - Current QoS, #'CosNotification_Property'{}
812%%            Parent - false | ObjRef
813%%            Childs - false | [ObjRef1, .., ObjRefN]
814%%            LQS    - #qos{} defined in CosNotification_Definitions.hrl
815%% Returns  :
816%% Comment  : PacingInterval is defined to be:
817%%            * TimeBase::UtcT (p 57, 2.5.5, OMG TC Document telecom/98-11-01)
818%%            * TimeBase::TimeT (p 189, appendix B, OMG TC Document telecom/98-11-01)
819%%            This implementation use TimeBase::TimeT, especially since
820%%            TimeBase::UtcT contains information which are of no importance.
821%%            When writing this, the OMG homepage contained no information
822%%            regarding this.
823%%------------------------------------------------------------
824'PacingInterval'(Req, _Type, _Curr, _Parent, _Childs, LQS) ->
825    case {any:get_value(Req#'CosNotification_Property'.value),
826	  ?not_GetPacingInterval(LQS)} of
827	{Val, Val} ->
828	    ok;
829	{Val, _} when Val >= ?not_MinPacing, Val =< ?not_MaxPacing ->
830	    {ok, Req, LQS};
831	{Val, _} when is_integer(Val) ->
832	    {unsupported,
833	     #'CosNotification_PropertyError'{
834	       code = 'BAD_VALUE',
835	       name = Req#'CosNotification_Property'.name,
836	       available_range =
837	       #'CosNotification_PropertyRange'{
838		 low_val=any:create(orber_tc:unsigned_long_long(), ?not_MinPacing),
839		 high_val=any:create(orber_tc:unsigned_long_long(), ?not_MaxPacing)
840		}
841	      }
842	    };
843	_->
844	    {unsupported,
845	     #'CosNotification_PropertyError'{
846	       code = 'BAD_TYPE',
847	       name = Req#'CosNotification_Property'.name,
848	       available_range = #'CosNotification_PropertyRange'{
849		 low_val=any:create(orber_tc:null(), null),
850		 high_val=any:create(orber_tc:null(), null)
851		}
852	      }
853	    }
854    end.
855
856%%------------------------------------------------------------
857%% function : 'MaxEventsPerConsumer'/6
858%% Arguments: Req    - Requested QoS, #'CosNotification_Property'{}
859%%            Type   - Requestee, channel | admin | proxy
860%%            Curr   - Current QoS, #'CosNotification_Property'{}
861%%            Parent - false | ObjRef
862%%            Childs - false | [ObjRef1, .., ObjRefN]
863%%            LQS    - #qos{} defined in CosNotification_Definitions.hrl
864%% Returns  :
865%% Effect   :
866%%------------------------------------------------------------
867'MaxEventsPerConsumer'(Req, _Type, _Curr, _Parent, _Childs, LQS) ->
868    case {any:get_value(Req#'CosNotification_Property'.value),
869	  ?not_GetMaxEventsPerConsumer(LQS)} of
870	{Val, Val} ->
871	    ok;
872	{Val, _} when is_integer(Val) andalso
873		      Val >= ?not_MinConsumerEvents andalso
874		      Val =< ?not_MaxConsumerEvents ->
875	    {ok, Req, LQS};
876	{Val, _} when is_integer(Val) ->
877	    {unsupported,
878	     #'CosNotification_PropertyError'{
879	       code = 'BAD_VALUE',
880	       name = Req#'CosNotification_Property'.name,
881	       available_range =
882	       #'CosNotification_PropertyRange'{
883		 low_val=any:create(orber_tc:unsigned_long_long(), ?not_MinConsumerEvents),
884		 high_val=any:create(orber_tc:unsigned_long_long(), ?not_MaxConsumerEvents)
885		}
886	      }
887	    };
888	_->
889	    {unsupported,
890	     #'CosNotification_PropertyError'{
891	       code = 'UNSUPPORTED_VALUE',
892	       name = Req#'CosNotification_Property'.name,
893	       available_range =
894	       #'CosNotification_PropertyRange'{
895		 low_val=any:create(orber_tc:long(), ?not_MinConsumerEvents),
896		 high_val=any:create(orber_tc:long(), ?not_MaxConsumerEvents)
897		}
898	      }
899	    }
900    end.
901
902%%------------------------------------------------------------
903%% function : validate_qos/5
904%% Arguments: Wanted  - requested QoS to be set.
905%%            Curr    - current QoS OMG style and LQS, local
906%%                      representation of QoS, grouped as {OMGQ, LQS}
907%%            Type    - channel | admin | proxy
908%%            Parent  - Factory if Channel, Channel if Admin etc
909%%            Childs  - Admins if Channel etc
910%% Returns  : NamedPropertySeq | #'CosNotification_UnsupportedQoS'{}
911%%            case 1 if all supported, case 2 if at least 1 QoS not
912%%            supported.
913%% See also p59, 2.5.6.4, OMG TC Document telecom/98-11-01. Quote:
914%% "If the supplied QoS is supported, it returns additional QoS
915%%  properties which could be optionally added as well."
916%%------------------------------------------------------------
917validate_qos(Wanted, Curr, Type, Parent, Childs) ->
918    %% If not supported this function will raise an exception, which we should
919    %% not catch, but all we need to is to raise the exception as it is.
920    {_, LQS}=set_qos(Wanted, Curr, Type, Parent, Childs),
921    NewNPR = check_limits(LQS, ?not_QOS_LIMITS),
922    remove_qos(Wanted, LQS, NewNPR).
923
924remove_qos([], _, NPR) ->
925    NPR;
926remove_qos([H|T], LQS, NPR) ->
927    NewNPR=remove(NPR, H#'CosNotification_Property'.name),
928    remove_qos(T, LQS, NewNPR).
929
930check_limits(LQS, NPR) ->
931    case {?not_GetEventReliability(LQS), ?not_GetConnectionReliability(LQS),
932	  ?not_Persistent, ?not_BestEffort} of
933	{P,P,P,_B} ->
934	    New = #'CosNotification_NamedPropertyRange'
935	      {name=?not_EventReliability,
936	       range=
937	       #'CosNotification_PropertyRange'{
938		 low_val=any:create(orber_tc:short(), ?not_BestEffort),
939		 high_val=any:create(orber_tc:short(), ?not_BestEffort)
940		}},
941	    NewNPR=change(NPR, ?not_EventReliability, New),
942	    remove(NewNPR, ?not_ConnectionReliability);
943	{_,B,_P,B} ->
944	    remove(NPR, ?not_EventReliability);
945	{B,P,P,B} ->
946	    New = #'CosNotification_NamedPropertyRange'
947	      {name=?not_ConnectionReliability,
948	       range=
949	       #'CosNotification_PropertyRange'{
950		 low_val=any:create(orber_tc:short(), ?not_BestEffort),
951		 high_val=any:create(orber_tc:short(), ?not_BestEffort)
952		}},
953	    change(NPR, ?not_ConnectionReliability, New)
954    end.
955
956%%------------------------------------------------------------
957%% function : validate_event_qos/2
958%% Arguments: Wanted  - requested QoS to be set.
959%%            Curr    - LQS, local representation of QoS
960%% Returns  : NamedPropertySeq | #'CosNotification_UnsupportedQoS'{}
961%%            case 1 if all supported, case 2 if at least 1 QoS not
962%%            supported.
963%%------------------------------------------------------------
964validate_event_qos(Wanted, Curr) ->
965    case v_e_q_helper(Wanted, Curr, []) of
966	ok ->
967	    [];
968	{error, Unsupp} ->
969	    corba:raise(#'CosNotification_UnsupportedQoS'{qos_err = Unsupp})
970    end.
971
972v_e_q_helper([], _Curr, []) ->
973    %% Parsed all and found no conflicts.
974    ok;
975v_e_q_helper([], _Curr, Unsupp) ->
976    %% Not possible to use these requested QoS.
977    {error, Unsupp};
978
979%%--- EventReliability ---%%
980v_e_q_helper([#'CosNotification_Property'{name=?not_EventReliability,
981					  value=#any{value=?not_BestEffort}}|T], Curr, Unsupp) ->
982    %% Always ok.
983    v_e_q_helper(T, Curr, Unsupp);
984v_e_q_helper([#'CosNotification_Property'{name=?not_EventReliability,
985					  value=#any{value=?not_Persistent}}|T], Curr, Unsupp)
986  when ?not_GetConnectionReliability(Curr) =/= ?not_BestEffort,
987       ?not_GetEventReliability(Curr) =/= ?not_BestEffort,
988       ?not_GetStopTimeSupported(Curr) =/= true ->
989    v_e_q_helper(T, Curr, Unsupp);
990v_e_q_helper([#'CosNotification_Property'{name=?not_EventReliability}|T],
991	     Curr, Unsupp) ->
992    %% Impossible to set to Persistent if the connection reliability is best effort.
993    v_e_q_helper(T, Curr, [#'CosNotification_PropertyError'
994			   {code = 'UNAVAILABLE_VALUE', name = ?not_EventReliability,
995			    available_range =
996			    #'CosNotification_PropertyRange'{
997			      low_val=any:create(orber_tc:null(), null),
998			      high_val=any:create(orber_tc:null(), null)}}|Unsupp]);
999
1000%%--- Priority ---%%
1001v_e_q_helper([#'CosNotification_Property'{name=?not_Priority, value=#any{value=V}}|T], Curr,
1002	     Unsupp) ->
1003    if
1004	?not_GetOrderPolicy(Curr) =/= ?not_AnyOrder,
1005	?not_GetOrderPolicy(Curr) =/= ?not_Priority,
1006	?not_GetDiscardPolicy(Curr) =/= ?not_Priority ->
1007	    %% No use setting Priority since it's not currently used.
1008	    v_e_q_helper(T, Curr, [#'CosNotification_PropertyError'
1009				   {code = 'UNAVAILABLE_VALUE', name = ?not_Priority,
1010				    available_range = #'CosNotification_PropertyRange'{
1011				      low_val=any:create(orber_tc:null(), null),
1012				      high_val=any:create(orber_tc:null(), null)
1013				     }}|Unsupp]);
1014	V =< ?not_HighestPriority, V >= ?not_LowestPriority ->
1015	    v_e_q_helper(T, Curr, Unsupp);
1016	true ->
1017	    v_e_q_helper(T, Curr, [#'CosNotification_PropertyError'
1018				   {code = 'BAD_VALUE', name = ?not_Priority,
1019				    available_range =
1020				    #'CosNotification_PropertyRange'{
1021				      low_val=any:create(orber_tc:short(),
1022							 ?not_LowestPriority),
1023				      high_val=any:create(orber_tc:short(),
1024							  ?not_HighestPriority)}}|Unsupp])
1025    end;
1026
1027%%--- StartTime ---%%
1028v_e_q_helper([#'CosNotification_Property'{name=?not_StartTime}|T], Curr, Unsupp)
1029  when ?not_GetStartTimeSupported(Curr) =/= false,
1030       ?not_GetEventReliability(Curr) =/= ?not_Persistent ->
1031    v_e_q_helper(T, Curr, Unsupp);
1032v_e_q_helper([#'CosNotification_Property'{name=?not_StartTime}|T], Curr, Unsupp) ->
1033    v_e_q_helper(T, Curr, [#'CosNotification_PropertyError'
1034			   {code = 'UNAVAILABLE_VALUE', name = ?not_StartTime,
1035			    available_range = #'CosNotification_PropertyRange'{
1036			      low_val=any:create(orber_tc:null(), null),
1037			      high_val=any:create(orber_tc:null(), null)
1038			     }}|Unsupp]);
1039
1040%%--- StopTime ---%%
1041v_e_q_helper([#'CosNotification_Property'{name=?not_StopTime}|T], Curr, Unsupp)
1042  when ?not_GetStopTimeSupported(Curr) =/= false,
1043       ?not_GetEventReliability(Curr) =/= ?not_Persistent ->
1044    v_e_q_helper(T, Curr, Unsupp);
1045v_e_q_helper([#'CosNotification_Property'{name=?not_StopTime}|T], Curr, Unsupp) ->
1046    v_e_q_helper(T, Curr, [#'CosNotification_PropertyError'
1047			   {code = 'UNAVAILABLE_VALUE', name = ?not_StopTime,
1048			    available_range = #'CosNotification_PropertyRange'{
1049			      low_val=any:create(orber_tc:null(), null),
1050			      high_val=any:create(orber_tc:null(), null)
1051			     }}|Unsupp]);
1052
1053%%--- Timeout ---%%
1054v_e_q_helper([#'CosNotification_Property'{name=?not_Timeout}|T], Curr, Unsupp)
1055  when  ?not_GetStopTimeSupported(Curr) =/= false,
1056	?not_GetEventReliability(Curr) =/= ?not_Persistent ->
1057    v_e_q_helper(T, Curr, Unsupp);
1058v_e_q_helper([#'CosNotification_Property'{name=?not_Timeout}|T], Curr, Unsupp) ->
1059    v_e_q_helper(T, Curr, [#'CosNotification_PropertyError'
1060			   {code = 'UNAVAILABLE_VALUE', name = ?not_Timeout,
1061			    available_range = #'CosNotification_PropertyRange'{
1062			      low_val=any:create(orber_tc:null(), null),
1063			      high_val=any:create(orber_tc:null(), null)
1064			     }}|Unsupp]);
1065
1066%%--- Unknown Event QoS ---%%
1067v_e_q_helper([#'CosNotification_Property'{name=Name}|T], Curr, Unsupp) ->
1068    %% Unsupported property.
1069    v_e_q_helper(T, Curr, [#'CosNotification_PropertyError'
1070			   {code = 'BAD_PROPERTY', name = Name,
1071			    available_range = #'CosNotification_PropertyRange'{
1072			      low_val=any:create(orber_tc:null(), null),
1073			      high_val=any:create(orber_tc:null(), null)
1074			     }}|Unsupp]);
1075v_e_q_helper(What, _, _) ->
1076    %% Not a Property struct.
1077    orber:dbg("[~p] CosNotification_Common:v_e_q_helper(~p);~n"
1078	      "Not a CosNotification_Property struct.",
1079	      [?LINE, What], ?DEBUG_LEVEL),
1080    corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO}).
1081
1082%%-------------- QOS HELP FUNCTIONS --------------------------
1083%%------------------------------------------------------------
1084%% function : set_properties/9
1085%% Arguments: Wanted  - requested QoS to be set.
1086%%            Current - current QoS OMG style
1087%%            Type    - channel | admin | proxy
1088%%            Supported - List of supported QoS
1089%%            Unsupp  - acc
1090%%            NewQoS  - acc
1091%%            Parent  - Factory if Channel, Channel if Admin etc
1092%%            Childs  - Admins if Channel etc
1093%%            LQS     - local representation of QoS.
1094%% Returns  : {NewOMGStyleQoS, NewLocalQoS} | #'CosNotification_UnsupportedQoS'{}
1095%%------------------------------------------------------------
1096set_properties(Wanted, Current, Type, Supported, Unsupp, NewQoS, Parent, Childs, LQS) ->
1097    case do_set_properties(Wanted, Current, Type, Supported, Unsupp, NewQoS, Parent, Childs, LQS) of
1098	{error, Exc} ->
1099	     corba:raise(Exc);
1100	Result ->
1101	    Result
1102    end.
1103
1104do_set_properties([], Curr, channelAdm, _, [], NewQoS,_,_,LAS) ->
1105    merge_properties(NewQoS, Curr, LAS);
1106do_set_properties([], Curr, _, _, [], NewQoS,_,_,LQS) ->
1107    %% set_local_qos and merge_properties are help functions found at the end of QoS
1108    %% functions.
1109    NewLQS = set_local_qos(NewQoS, LQS),
1110    merge_properties(NewQoS, Curr, NewLQS);
1111do_set_properties([], _, channelAdm, _, Unsupp, _,_,_,_) ->
1112    {error, #'CosNotification_UnsupportedAdmin'{admin_err = Unsupp}};
1113do_set_properties([], _, _, _, Unsupp, _,_,_,_) ->
1114    {error, #'CosNotification_UnsupportedQoS'{qos_err = Unsupp}};
1115
1116do_set_properties([Req|Tail], Curr, Type, Supported, Unsupp, NewQoS, Parent, Childs,LQS) ->
1117    %% set_values and is_supported are help functions found at the end of QoS
1118    %% functions.
1119    case set_values(is_supported(Supported, Req), Req, Type, Curr, Parent, Childs,LQS) of
1120	{unsupported, U} ->
1121	    do_set_properties(Tail, Curr, Type, Supported, [U|Unsupp], NewQoS, Parent, Childs,LQS);
1122	{ok, S, NewLQS} ->
1123	    do_set_properties(Tail, Curr, Type, Supported, Unsupp, [S|NewQoS], Parent, Childs,NewLQS);
1124	{ok, S} ->
1125	    do_set_properties(Tail, Curr, Type, Supported, Unsupp, [S|NewQoS], Parent, Childs,LQS);
1126	ok ->
1127	    do_set_properties(Tail, Curr, Type, Supported, Unsupp, NewQoS, Parent, Childs,LQS)
1128    end.
1129
1130
1131set_values(unsupported,Req,_,_,_,_,_) ->
1132    {unsupported,
1133     #'CosNotification_PropertyError'{
1134       code = 'BAD_PROPERTY',
1135       name = Req#'CosNotification_Property'.name,
1136       available_range = #'CosNotification_PropertyRange'{
1137	 low_val=any:create(orber_tc:null(), null),
1138	 high_val=any:create(orber_tc:null(), null)
1139	}
1140      }
1141    };
1142set_values({ok, Func}, Req, Type, Curr, Parent, Childs, LQS) ->
1143    ?MODULE:Func(Req, Type, Curr, Parent, Childs, LQS).
1144
1145%% Update OMG style QoS list with new values.
1146merge_properties([], NewCurrQoS, LQS) ->
1147    {NewCurrQoS, LQS};
1148merge_properties([H|T], Curr, LQS) ->
1149    merge_properties(T, lists:keyreplace(H#'CosNotification_Property'.name, %% get key.
1150					 #'CosNotification_Property'.name, %% get index.
1151					 Curr, H), LQS).
1152
1153%% Is the Property S among our supported QoS?
1154is_supported([], _) ->
1155    unsupported;
1156is_supported([{Name, Func}|_], #'CosNotification_Property'{name=Name}) ->
1157    {ok, Func};
1158is_supported([_|T], S) ->
1159    is_supported(T, S).
1160
1161%% Find matching S-Property from a list of OMG style QoS
1162extract([], _) -> unsupported;
1163extract([H|_T], S) when H#'CosNotification_Property'.name==
1164		       S#'CosNotification_Property'.name ->
1165    {ok, H};
1166extract([_|T], S) -> extract(T,S).
1167
1168%% Find matching Property name from a list of OMG style QoS
1169extract_value([], _) -> unsupported;
1170extract_value([H|_T], Key) when H#'CosNotification_Property'.name== Key ->
1171    {ok, any:get_value(H#'CosNotification_Property'.value)};
1172extract_value([_|T], Key) -> extract(T,Key).
1173
1174%% Remove matching S-QoS from a list of OMG style QoS
1175remove(List, Key) ->
1176    lists:keydelete(Key,
1177		    #'CosNotification_NamedPropertyRange'.name, %% get index.
1178		    List).
1179
1180change(List, Key, New) ->
1181    lists:keyreplace(Key,
1182		     #'CosNotification_NamedPropertyRange'.name, %% get index.
1183		     List, New).
1184%% Get QoS from supplied objects and check if it's the same as S.
1185check_with_relatives([], S, LQS) ->
1186    {ok, S, LQS};
1187check_with_relatives([undefined|T], S, LQS) ->
1188    check_with_relatives(T, S, LQS);
1189check_with_relatives([H|T], S, LQS) ->
1190    case catch extract('CosNotification_QoSAdmin':get_qos(H), S) of
1191	{ok, S} ->
1192	    check_with_relatives(T, S, LQS);
1193	_->
1194	    %% Varioues reasons for this case (Object not responding, not supported)
1195	    {unsupported,
1196	     #'CosNotification_PropertyError'{
1197	       code = 'UNAVAILABLE_PROPERTY',
1198	       name = S#'CosNotification_Property'.name,
1199	       available_range = #'CosNotification_PropertyRange'{
1200		 low_val=any:create(orber_tc:null(), null),
1201		 high_val=any:create(orber_tc:null(), null)
1202		}
1203	      }
1204	    }
1205    end.
1206
1207%% Set new values to locally defined representation of QoS. Using this approach is
1208%% necessary since we must state the record-field at compile-time.
1209set_local_qos([], LQS) -> LQS;
1210set_local_qos([#'CosNotification_Property'{name=N,value=V}|T], LQS) ->
1211    NewLQS =
1212	case N of
1213	    "EventReliability" ->
1214		?not_SetEventReliability(LQS, any:get_value(V));
1215	    "ConnectionReliability" ->
1216		?not_SetConnectionReliability(LQS, any:get_value(V));
1217	    "Priority" ->
1218		?not_SetPriority(LQS, any:get_value(V));
1219	    "Timeout" ->
1220		?not_SetTimeout(LQS, any:get_value(V));
1221	    "OrderPolicy" ->
1222		?not_SetOrderPolicy(LQS, any:get_value(V));
1223	    "DiscardPolicy" ->
1224		?not_SetDiscardPolicy(LQS, any:get_value(V));
1225	    "MaximumBatchSize" ->
1226		?not_SetMaximumBatchSize(LQS, any:get_value(V));
1227	    "PacingInterval" ->
1228		?not_SetPacingInterval(LQS, any:get_value(V));
1229	    "StartTimeSupported" ->
1230		?not_SetStartTimeSupported(LQS, any:get_value(V));
1231	    "StopTimeSupported" ->
1232		?not_SetStopTimeSupported(LQS, any:get_value(V));
1233	    "MaxEventsPerConsumer" ->
1234		?not_SetMaxEventsPerConsumer(LQS, any:get_value(V))
1235	end,
1236    set_local_qos(T, NewLQS).
1237
1238%%%%%%%%%%%%%%%%% END QOS FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%
1239
1240%%--------------- END OF MODULE ------------------------------
1241