DBA Data[Home] [Help]

PACKAGE BODY: APPS.AME_DUAL_CHAINS_HANDLER

Source


1 package body ame_dual_chains_handler as
2 /* $Header: ameedcha.pkb 120.3 2007/12/20 20:02:21 prasashe noship $ */
3   /* package variables */
4   approverCategoriesDual ame_util.charList;
5   approverCategories ame_util.charList;
6   parametersCount integer;
7   parameterNumbers ame_util.idList;
8   parameters ame_util.stringList;
9   parameterSigns ame_util.charList;
10   ruleIds ame_util.idList;
11   ruleIdsDual ame_util.idList;
12   ruleSatisfiedYN ame_util.charList;
13   threshholdJobLevel integer;
14   topDogFound boolean;
15   topDogPersonId integer;
16   /* forward declarations */
17   /*
18     getCatSourceAndAuthority does not account for the ALLOW_REQUESTOR_APPROVAL attribute.
19     The handler procedure does that.
20   */
21   procedure getCatSourceAndAuthority(personIdIn in integer,
22                                      jobLevelIn in integer,
23                                      supervisorIdIn in integer,
24                                      categoryOut out nocopy varchar2,
25                                      sourceOut out nocopy varchar2,
26                                      hasFinalAuthorityYNOut out nocopy varchar2,
27                                      supervisorJobLevelOut out nocopy integer,
28                                      nextSupervisorIdOut out nocopy integer);
29   /*
30     parseAndSortRules populates the parameterNumbers and parameterSigns tables in
31     ascending lexicographic order, first by numerical order, then with '+' dominating '-'.
32     Note that it does not sort the parameters proper.
33   */
34   procedure parseAndSortRules(chainNumIn in integer);
35   /* procedures */
36   procedure getCatSourceAndAuthority(personIdIn in integer,
37                                      jobLevelIn in integer,
38                                      supervisorIdIn in integer,
39                                      categoryOut out nocopy varchar2,
40                                      sourceOut out nocopy varchar2,
41                                      hasFinalAuthorityYNOut out nocopy varchar2,
42                                      supervisorJobLevelOut out nocopy integer,
43                                      nextSupervisorIdOut out nocopy integer) as
44     category ame_util.charType;
45     errorCode integer;
46     errorMessage ame_util.longestStringType;
47     hasFinalAuthorityYN ame_util.charType;
48     noSupervisorException exception;
49     personDisplayName ame_util.longStringType;
50     source ame_util.longStringType;
51     supervisorJobLevel integer;
52     tempRuleRequiresApprover boolean;
53     tempRuleSatisfied boolean;
54     begin
55       /* Initialize the two output arguments that might not otherwise get set. */
56      supervisorJobLevelOut := null;
57      nextSupervisorIdOut := null;
58       /*
59         1.  An approver satisfies a rule in any of three cases:
60             A.  The rule's parameter number does not exceed the approver's job level.
61             B.  The rule's parameter sign is '-', and the job level of the approver's
62                 supervisor exceeds the rule's parameter number.
63             C.  The approver is the top dog.
64         2.  An approver has final authority if the approver satisfies all the rules.
65             (The handler procedure proper takes care of adding subsequent approvers at
66             the same job level, if the relevant mandatory attribute so requires.)
67         3.  The source value is a comma-delimited list of the IDs of the rules that
68             require an approver.  This procedure builds up the source value according
69             to the following logic:
70             A.  If a rule has not yet been satisfied, the rule requires the input
71                 approver.
72             B.  Otherwise, the rule requires the input approver only if the approver
73                 does <<not>> satisfy the rule.  (This would happen in the perverse case
74                 that an approver satisfies a rule, but their supervisor has a lower
75                 job level that does not satisfy the rule.)
76         4.  An approver's category is ame_util.approvalApproverCategory if any of the
77             rule usages requiring the approver is of that category; otherwise the
78             approver's category is ame_util.fyiApproverCategory.
79       */
80       category := ame_util.fyiApproverCategory;
81       hasFinalAuthorityYN := ame_util.booleanTrue;
82       for i in 1 .. parameterNumbers.count loop
83         /* Determine whether the approver satisfies the current rule. */
84         if(personIdIn = topDogPersonId) then
85           topDogFound := true;
86           tempRuleSatisfied := true;
87         else
88           topDogFound := false;
89           tempRuleSatisfied := false;
90           if(jobLevelIn >= parameterNumbers(i)) then
91             tempRuleSatisfied := true;
92           elsif(parameterSigns(i) = '-') then
93             if supervisorIdIn is null then
94               supervisorJobLevel := 0;
95             else
96               if(supervisorJobLevel is null) then
97                 if(supervisorIdIn is null) then
98                   raise noSupervisorException;
99                 end if;
100                 ame_absolute_job_level_handler.getJobLevelAndSupervisor(personIdIn => supervisorIdIn,
101                                        jobLevelOut => supervisorJobLevel,
102                                        supervisorIdOut => nextSupervisorIdOut);
103                 supervisorJobLevelOut := supervisorJobLevel;
104               end if;
105               if(supervisorJobLevel > parameterNumbers(i)) then
106                 tempRuleSatisfied := true;
107               end if;
108             end if;
109           end if;
110         end if;
111         /* Update hasFinalAuthorityYN as needed. */
112         if(not tempRuleSatisfied and
113            hasFinalAuthorityYN = ame_util.booleanTrue) then
114           hasFinalAuthorityYN := ame_util.booleanFalse;
115         end if;
116         /* Determine whether the current rule requires the approver. */
117         tempRuleRequiresApprover := false;
118         if(ruleSatisfiedYN(i) = ame_util.booleanTrue) then
119           if(not tempRuleSatisfied) then
120             tempRuleRequiresApprover := true;
121           end if;
122         else
123           tempRuleRequiresApprover := true;
124           if(tempRuleSatisfied) then
125             ruleSatisfiedYN(i) := ame_util.booleanTrue;
126           end if;
127         end if;
128         if(tempRuleRequiresApprover) then
129           /* Update source. */
130           ame_util.appendRuleIdToSource(ruleIdIn => ruleIds(i),
131                                         sourceInOut => source);
132           /* Update category as needed. */
133           if(category = ame_util.fyiApproverCategory and
134              approverCategories(i) = ame_util.approvalApproverCategory) then
135             category := ame_util.approvalApproverCategory;
136           end if;
137         end if;
138       end loop;
139       categoryOut := category;
140       hasFinalAuthorityYNOut := hasFinalAuthorityYN;
141       sourceOut := source;
142       exception
143         when noSupervisorException then
144           personDisplayName := ame_approver_type_pkg.getApproverDisplayName2(
145                                       origSystemIn => ame_util.perOrigSystem,
146                                       origSystemIdIn => personIdIn );
147           errorCode := -20001;
148           errorMessage := ame_util.getMessage(applicationShortNameIn => 'PER',
149             messageNameIn     => 'AME_400297_HAN_LACK_SPVR',
150             tokenNameOneIn    => 'FIRST_NAME',
151             tokenValueOneIn   => personDisplayName,
152             tokenNameTwoIn    => 'LAST_NAME',
153             tokenValueTwoIn   => null ,
154             tokenNameThreeIn  => 'OTHER_NAME',
155             tokenValueThreeIn =>  null );
156           ame_util.runtimeException(packageNameIn => 'ame_dual_chains_handler',
157                                     routineNameIn => 'getCatSourceAndAuthority',
158                                     exceptionNumberIn => errorCode,
159                                     exceptionStringIn => errorMessage);
160           raise_application_error(errorCode,
161                                   errorMessage);
162         when others then
163           categoryOut := null;
164           hasFinalAuthorityYNOut := null;
165           sourceOut := null;
166           ame_util.runtimeException(packageNameIn => 'ame_dual_chains_handler',
167                                     routineNameIn => 'getCatSourceAndAuthority',
168                                     exceptionNumberIn => sqlcode,
169                                     exceptionStringIn => sqlerrm);
170           raise;
171     end getCatSourceAndAuthority;
172   procedure handler as
173     chainOrderMode ame_util.stringType;
174     COAInsertee ame_util.approverRecord2;
175     errorCode integer;
176     errorMessage ame_util.longestStringType;
177     finalAuthorityApproverCategory ame_util.charType;
178     finalAuthorityFound boolean;
179     finalAuthoritySource ame_util.longStringType;
180     firstApproverSource ame_util.longStringType;
181     includeAllJobLevelApprovers boolean;
182     noSupervisorException exception;
183     nullFirstIdException exception;
184     nullSecondIdException exception;
185     firstStartingPointId integer;
186     oneChainException exception;
187     personDisplayName ame_util.longStringType;
188     secondStartingPointId integer;
189     tempApprover ame_util.approverRecord2;
190     tempHasFinalAuthorityYN ame_util.charType;
191     tempJobLevel integer;
192     tempMemberOrderNumber integer;
193     tempOldJobLevel integer;
194     tempSupervisorId integer;
195     tempSupervisorJobLevel integer;
196     tempNextSupervisorId integer;
197     votingRegimeType ame_util.stringType;
198     firstAuthInsExists boolean := false;
199     coaInsAuthForward boolean := false;
200     begin
201       includeAllJobLevelApprovers :=
202         ame_engine.getHeaderAttValue2(attributeNameIn => ame_util.includeAllApproversAttribute) =
203         ame_util.booleanAttributeTrue;
204       /* Populate some of the package variables. */
205       topDogPersonId := to_number(ame_engine.getHeaderAttValue2(attributeNameIn => ame_util.topSupPersonIdAttribute));
206       /* Set the fields in tempApprover that are constant for the entire handler cycle. */
207       tempApprover.orig_system := ame_util.perOrigSystem;
208       tempApprover.authority := ame_util.authorityApprover;
209       tempApprover.action_type_id := ame_engine.getHandlerActionTypeId;
210       tempApprover.item_class := ame_engine.getHandlerItemClassName;
211       tempApprover.item_id := ame_engine.getHandlerItemId;
212       tempApprover.item_class_order_number := ame_engine.getHandlerItemClassOrderNumber;
213       tempApprover.item_order_number := ame_engine.getHandlerItemOrderNumber;
214       tempApprover.sub_list_order_number := ame_engine.getHandlerSublistOrderNum;
215       tempApprover.action_type_order_number := ame_engine.getHandlerActionTypeOrderNum;
216       votingRegimeType := ame_engine.getActionTypeVotingRegime(actionTypeIdIn => tempApprover.action_type_id);
217       chainOrderMode := ame_engine.getActionTypeChainOrderMode(actionTypeIdIn => tempApprover.action_type_id);
218       /*
219         The engine only calls a handler if a rule requiring it exists, so we can assume that
220         the package variables that ame_engine.getHandlerRules initializes are nonempty.
221         Fetch the rules and sort them in increasing parameter order.  (Duplicate parameters
222         are harmless here.)
223       */
224       ame_engine.getHandlerRules2(ruleIdsOut => ruleIdsDual,
225                                   approverCategoriesOut => approverCategoriesDual,
226                                   parametersOut => parameters);
227       parametersCount := parameters.count;
228       for chainCounter in 1..2 loop
229         firstAuthInsExists := false;
230         coaInsAuthForward := false;
231         finalAuthorityApproverCategory := null;
232         finalAuthoritySource := null;
233         /* Check for COA 'firstAuthority' insertions */
234         ame_engine.getHandlerCOAFirstApprover(itemClassIn => tempApprover.item_class,
235                                               itemIdIn => tempApprover.item_id,
236                                               actionTypeIdIn =>tempApprover.action_type_id,
237                                               groupOrChainIdIn => chainCounter,
238                                               nameOut => COAInsertee.name,
239                                               origSystemOut => COAInsertee.orig_system,
240                                               origSystemIdOut =>COAInsertee.orig_system_id,
241                                               displayNameOut => COAInsertee.display_name,
242                                               sourceOut => COAInsertee.source);
243         if COAInsertee.name is  null then
244           if chainCounter = 1 then
245             /* Fetch the required attributes. */
246             firstStartingPointId :=
247               to_number(ame_engine.getHeaderAttValue2(attributeNameIn =>
248                                           ame_util.firstStartingPointAttribute));
249             if(firstStartingPointId is null ) then
250               raise nullFirstIdException;
251             end if;
252             tempApprover.orig_system_id := firstStartingPointId;
253           else  /* Chain is 2*/
254             /* Fetch the required attributes. */
255             secondStartingPointId :=
256               to_number(ame_engine.getHeaderAttValue2(attributeNameIn =>
257                                           ame_util.secondStartingPointAttribute));
258             if( secondStartingPointId is null) then
259               raise nullSecondIdException;
260             end if;
261             tempApprover.orig_system_id :=secondStartingPointId ;
262           end if;
263           tempApprover.api_insertion := ame_util.oamGenerated;
264           ame_approver_type_pkg.getWfRolesNameAndDisplayName(
265                               origSystemIn => ame_util.perOrigSystem,
266                               origSystemIdIn => tempApprover.orig_system_id,
267                               nameOut => tempApprover.name,
268                               displayNameOut => tempApprover.display_name);
269         else
270           tempApprover.name := COAInsertee.name;
271           tempApprover.orig_system := COAInsertee.orig_system;
272           tempApprover.orig_system_id := COAInsertee.orig_system_id;
273           tempApprover.display_name :=  COAInsertee.display_name;
274           firstApproverSource := COAInsertee.source;
275           tempApprover.api_insertion := ame_util.apiAuthorityInsertion;
276           firstAuthInsExists := true;
277         end if;
278         /* Get the threshholdJobLevel to convert parameters to absolute values */
279         ame_absolute_job_level_handler.getJobLevelAndSupervisor(
280                                  personIdIn => tempApprover.orig_system_id,
281                                  jobLevelOut => threshholdJobLevel,
282                                  supervisorIdOut => tempSupervisorId);
283         parseAndSortRules(chainNumIn => chainCounter);
284         tempJobLevel := threshholdJobLevel;
285         /* Check if there are any parameters defined for this chain. */
286         if parameterNumbers.count = 0 then
287           raise oneChainException;
288         end if;
289         for i in 1 .. parameterNumbers.count loop
290           ruleSatisfiedYN(i) := ame_util.booleanFalse;
291         end loop;
292         tempApprover.group_or_chain_id := chainCounter;
293         if (chainOrderMode = ame_util.serialChainsMode) then
294             tempApprover.group_or_chain_order_number := chainCounter;
295         else /* chain Order Mode is parallel */
296             tempApprover.group_or_chain_order_number := 1;
297         end if;
298         /* In this case self approval can not be done so build the chain. */
299         finalAuthorityFound := false;
300         tempMemberOrderNumber := 0; /* pre-increment */
301         loop
302           getCatSourceAndAuthority(personIdIn => tempApprover.orig_system_id,
303                                    jobLevelIn => tempJobLevel,
304                                    supervisorIdIn => tempSupervisorId,
305                                    categoryOut => tempApprover.approver_category,
306                                    sourceOut => tempApprover.source,
307                                    hasFinalAuthorityYNOut => tempHasFinalAuthorityYN,
308                                    supervisorJobLevelOut => tempSupervisorJobLevel,
309                                    nextSupervisorIdOut => tempNextSupervisorId);
310           /* reassign the value of source in case approver was a firstAuthority insertee */
311           if firstApproverSource is not null then
312             tempApprover.source := firstApproverSource;
313             firstApproverSource := null;
314           end if;
315           if(not finalAuthorityFound and
316              tempHasFinalAuthorityYN = ame_util.booleanTrue) then
317             finalAuthorityFound := true;
318             finalAuthorityApproverCategory := tempApprover.approver_category;
319             finalAuthoritySource := tempApprover.source;
320           end if;
321           if (tempApprover.source is null and
322              finalAuthoritySource is not null ) then
323             tempApprover.approver_category := finalAuthorityApproverCategory;
324             tempApprover.source := finalAuthoritySource;
325           end if;
326           tempApprover.occurrence := ame_engine.getHandlerOccurrence(nameIn=>tempApprover.name,
327                                                   itemClassIn => tempApprover.item_class,
328                                                   itemIdIn => tempApprover.item_id,
329                                                   actionTypeIdIn => tempApprover.action_type_id,
330                                                   groupOrChainIdIn => tempApprover.group_or_chain_id);
331 
332           tempMemberOrderNumber := tempMemberOrderNumber + 1;
333           if(votingRegimeType = ame_util.serializedVoting) then
334             tempApprover.member_order_number := tempMemberOrderNumber;
335           else /* votingRegimeType in (ame_util.consensusVoting, ame_util.firstApproverVoting) */
336             tempApprover.member_order_number := 1;
337           end if;
338           tempApprover.approval_status := ame_engine.getHandlerApprovalStatus(approverIn => tempApprover);
339           /* The engine will set tempApprover.approver_order_number; leave it null here. */
340           ame_engine.addApprover(approverIn => tempApprover);
341           /* check to see if there is a COA insertion after this approver. If a COA
342              insertion is found, keep checking till no more COA insertions. The check
343              for final authority will need to be done again.  */
344           loop
345             /* Initialize COAInsertee approverRecord2 */
346             COAInsertee := ame_util.emptyApproverRecord2;
347             /* Check if there are any COAInsertions */
348             ame_engine.getHandlerCOAInsertion(nameIn => tempApprover.name,
349                                             itemClassIn => tempApprover.item_class,
350                                             itemIdIn => tempApprover.item_id,
351                                             actionTypeIdIn => tempApprover.action_type_id,
352                                             groupOrChainIdIn => tempApprover.group_or_chain_id,
353                                             occurrenceIn => tempApprover.occurrence,
354                                             approvalStatusIn => tempApprover.approval_status,
355                                             nameOut => COAInsertee.name,
356                                             origSystemOut => COAInsertee.orig_system,
357                                             origSystemIdOut => COAInsertee.orig_system_id,
358                                             displayNameOut => COAInsertee.display_name,
359                                             sourceOut => COAInsertee.source);
360             if COAInsertee.name is null then
361               exit;
362             else
363               tempApprover.name := COAInsertee.name;
364               tempApprover.orig_system := COAInsertee.orig_system;
365               tempApprover.orig_system_id := COAInsertee.orig_system_id;
366               tempApprover.display_name :=  COAInsertee.display_name;
367               ame_absolute_job_level_handler.getJobLevelAndSupervisor(
368                                        personIdIn => tempApprover.orig_system_id,
369                                        jobLevelOut => tempJobLevel,
370                                        supervisorIdOut => tempSupervisorId);
371               getCatSourceAndAuthority(personIdIn => tempApprover.orig_system_id,
372                                        jobLevelIn => tempJobLevel,
373                                        supervisorIdIn => tempSupervisorId,
374                                        categoryOut => tempApprover.approver_category,
375                                        sourceOut => tempApprover.source,
376                                        hasFinalAuthorityYNOut => tempHasFinalAuthorityYN,
377                                        supervisorJobLevelOut => tempSupervisorJobLevel,
378                                        nextSupervisorIdOut => tempNextSupervisorId);
379               tempApprover.source := COAInsertee.source;
380               tempApprover.approver_category := ame_util.approvalApproverCategory;
381               tempApprover.api_insertion := ame_util.apiAuthorityInsertion;
382               tempMemberOrderNumber := tempMemberOrderNumber + 1;
383               if(votingRegimeType = ame_util.serializedVoting) then
384                 tempApprover.member_order_number := tempMemberOrderNumber;
385               else /* votingRegimeType in (ame_util.consensusVoting, ame_util.firstApproverVoting) */
386                 tempApprover.member_order_number := 1;
387               end if;
388               tempApprover.occurrence := ame_engine.getHandlerOccurrence(nameIn =>  tempApprover.name,
389                                               itemClassIn => tempApprover.item_class,
390                                               itemIdIn => tempApprover.item_id,
391                                               actionTypeIdIn => tempApprover.action_type_id,
392                                               groupOrChainIdIn => tempApprover.group_or_chain_id);
393               tempApprover.approval_status := ame_engine.getHandlerApprovalStatus(approverIn => tempApprover);
394               /* If approver has a status of ame_util.approve or ame_util.approveAndForwardStatus or
395                  ame_util.nullStatus check to see if approver could have final authority */
396               if ((tempApprover.approval_status is null) or
397                 (tempApprover.approval_status in
398                         (ame_util.approvedStatus, ame_util.approveAndForwardStatus,
399                          ame_util.repeatedStatus, ame_util.suppressedStatus,
400                          ame_util.beatByFirstResponderStatus, ame_util.nullStatus)) or
401                 (tempApprover.approver_category = ame_util.approvalApproverCategory and
402                  tempApprover.approval_status = ame_util.notifiedStatus) )
403                 then
404                 if(not finalAuthorityFound and
405                   tempHasFinalAuthorityYN = ame_util.booleanTrue) then
406                   finalAuthorityFound := true;
407                 end if;
408               end if;
409               ame_engine.addApprover(approverIn => tempApprover);
410               coaInsAuthForward := true;
411             end if;
412           end loop;
413           /* Decide whether to end the chain. */
414           if(topDogFound or
415              (finalAuthorityFound and
416              not includeAllJobLevelApprovers)) then
417             exit;
418           end if;
419           /* Check to make sure tempSupervisorId is not null, else raise noSupervisorException */
420           if tempSupervisorId is null then
421             raise noSupervisorException;
422           else
423             tempApprover.orig_system_id := tempSupervisorId;
424           end if;
425           tempOldJobLevel := tempJobLevel;
426           if(tempSupervisorJobLevel is null) then
427             ame_absolute_job_level_handler.getJobLevelAndSupervisor(personIdIn => tempApprover.orig_system_id,
428                                    jobLevelOut => tempJobLevel,
429                                    supervisorIdOut => tempSupervisorId);
430           else
431             tempJobLevel := tempSupervisorJobLevel;
432             tempSupervisorId := tempNextSupervisorId;
433           end if;
434           /*
435           At this point finalAuthorityFound implies includeAllJobLevelApprovers, so the following if
436           doesn't need to check includeAllJobLevelApprovers.  But it's implicit in the if statement.
437           */
438           if(finalAuthorityFound and
439              tempOldJobLevel <> tempJobLevel) then
440             exit;
441           end if;
442           tempApprover.api_insertion := ame_util.oamGenerated;
443           ame_approver_type_pkg.getWfRolesNameAndDisplayName(
444                                     origSystemIn => ame_util.perOrigSystem,
445                                     origSystemIdIn => tempApprover.orig_system_id,
446                                     nameOut => tempApprover.name,
447                                     displayNameOut => tempApprover.display_name);
448           if firstAuthInsExists then
449             ame_engine.setDeviationReasonDate(ame_approver_deviation_pkg.firstauthHandlerInsReason,null);
450           end if;
451           if coaInsAuthForward then
452             ame_engine.setDeviationReasonDate(ame_approver_deviation_pkg.forwarHandlerAuthInsReason,null);
453           end if;
454         end loop;
455       end loop;
456       exception
457         when oneChainException then
458           errorCode := -20001;
459           errorMessage := ame_util.getMessage(applicationShortNameIn => 'PER',
460                                               messageNameIn => 'AME_400253_HAN_ONE_CHN_REQ');
461           ame_util.runtimeException(packageNameIn => 'ame_dual_chains_handler',
462                                     routineNameIn => 'handler',
463                                     exceptionNumberIn => errorCode,
464                                     exceptionStringIn => errorMessage);
465           raise_application_error(errorCode,
466                                   errorMessage);
467         when noSupervisorException then
468           if tempApprover.display_name is null then
469             personDisplayName := ame_approver_type_pkg.getApproverDisplayName2(
470                                       origSystemIn => ame_util.perOrigSystem,
471                                       origSystemIdIn => tempApprover.orig_system_id );
472           else
473             personDisplayName := tempApprover.display_name;
474           end if;
475           errorCode := -20001;
476           errorMessage := ame_util.getMessage(applicationShortNameIn => 'PER',
477             messageNameIn     => 'AME_400297_HAN_LACK_SPVR',
478             tokenNameOneIn    => 'FIRST_NAME',
479             tokenValueOneIn   => personDisplayName,
480             tokenNameTwoIn    => 'LAST_NAME',
481             tokenValueTwoIn   => null ,
482             tokenNameThreeIn  => 'OTHER_NAME',
483             tokenValueThreeIn =>  null );
484           ame_util.runtimeException(packageNameIn => 'ame_dual_chains_handler',
485                                     routineNameIn => 'handler',
486                                     exceptionNumberIn => errorCode,
487                                     exceptionStringIn => errorMessage);
488           raise_application_error(errorCode,
489                                   errorMessage);
490         when nullFirstIdException then
491           errorCode := -20001;
492           errorMessage :=
493           ame_util.getMessage(applicationShortNameIn => 'PER',
494                               messageNameIn   => 'AME_400250_HAN_NULL_FRST_STRT',
495                               tokenNameOneIn  => 'STARTING_POINT_ATTRIBUTE',
496                               tokenValueOneIn => ame_util.firstStartingPointAttribute);
497           ame_util.runtimeException(packageNameIn => 'ame_dual_chains_handler',
498                                     routineNameIn => 'handler',
499                                     exceptionNumberIn => errorCode,
500                                     exceptionStringIn => errorMessage);
501           raise_application_error(errorCode,
502                                   errorMessage);
503         when nullSecondIdException then
504           errorCode := -20001;
505           errorMessage :=
506           ame_util.getMessage(applicationShortNameIn => 'PER',
507                               messageNameIn   => 'AME_400250_HAN_NULL_FRST_STRT',
508                               tokenNameOneIn  => 'STARTING_POINT_ATTRIBUTE',
509                               tokenValueOneIn => ame_util.secondStartingPointAttribute);
510           ame_util.runtimeException(packageNameIn => 'ame_dual_chains_handler',
511                                     routineNameIn => 'handler',
512                                     exceptionNumberIn => errorCode,
513                                     exceptionStringIn => errorMessage);
514           raise_application_error(errorCode,
515                                   errorMessage);
516         when others then
517           ame_util.runtimeException(packageNameIn => 'ame_dual_chains_handler',
518                                     routineNameIn => 'handler',
519                                     exceptionNumberIn => sqlcode,
520                                     exceptionStringIn => sqlerrm);
521           raise;
522     end handler;
523   procedure parseAndSortRules(chainNumIn in integer)  as
524     badParameterException exception;
525     errorCode integer;
526     errorMessage ame_util.longestStringType;
527     tempCategory ame_util.charType;
528     tempIndex integer;
529     tempLength integer;
530     tempNumber integer;
531     tempRuleId integer;
532     tempSign ame_util.charType;
533     upperLimit integer;
534     begin
535       /* Parse. */
536       tempIndex := 0;
537       parameterNumbers.delete;
538       parameterSigns.delete;
539       approverCategories.delete;
540       ruleIds.delete;
541       for i in 1 .. parametersCount  loop
542         if (chainNumIn = 1 and
543            (substrb(parameters(i), 1, 1) = '1')) then
544           tempIndex := tempIndex + 1;
545           tempLength := lengthb(parameters(i));
546           if substrb(parameters(i), 2, 1) = 'R' then
547             parameterNumbers(tempIndex) := threshholdJobLevel +
548                         to_number(substrb(parameters(i), 3, tempLength - 3));
549             parameterSigns(tempIndex) := substrb(parameters(i), -1, 1);
550           else
551             parameterNumbers(tempIndex) := to_number(substrb(parameters(i),3,tempLength- 3));
552             parameterSigns(tempIndex) := substrb(parameters(i), -1, 1);
553           end if;
554           approverCategories(tempIndex) := approverCategoriesDual(i);
555           ruleIds(tempIndex) := ruleIdsDual(i);
556           if(parameterSigns(tempIndex) <> '+' and
557              parameterSigns(tempIndex) <> '-') then
558             raise badParameterException;
559           end if;
560         elsif (chainNumIn = 2 and
561            (substrb(parameters(i), 1, 1) = '2')) then
562           tempIndex := tempIndex + 1;
563           tempLength := lengthb(parameters(i));
564           if substrb(parameters(i), 2, 1) = 'R' then
565             parameterNumbers(tempIndex) := threshholdJobLevel +
566                         to_number(substrb(parameters(i), 3, tempLength - 3));
567             parameterSigns(tempIndex) := substrb(parameters(i), -1, 1);
568           else
569             parameterNumbers(tempIndex) := to_number(substrb(parameters(i),3,tempLength- 3));
570             parameterSigns(tempIndex) := substrb(parameters(i), -1, 1);
571           end if;
572           approverCategories(tempIndex) := approverCategoriesDual(i);
573           ruleIds(tempIndex) := ruleIdsDual(i);
574           if(parameterSigns(tempIndex) <> '+' and
575              parameterSigns(tempIndex) <> '-') then
576             raise badParameterException;
577           end if;
578         end if;
579       end loop;
580       /* Sort. */
581       for i in 2 .. tempIndex loop
582         upperLimit := i - 1;
583         for j in 1 .. upperLimit loop
584           if(parameterNumbers(i) < parameterNumbers(j) or
585              (parameterNumbers(i) = parameterNumbers(j) and
586               parameterSigns(i) = '-' and parameterSigns(j) = '+')) then
587             tempRuleId := ruleIds(j);
588             tempCategory := approverCategories(j);
589             tempNumber := parameterNumbers(j);
590             tempSign := parameterSigns(j);
591             ruleIds(j) := ruleIds(i);
592             approverCategories(j) := approverCategories(i);
593             parameterNumbers(j) := parameterNumbers(i);
594             parameterSigns(j) := parameterSigns(i);
595             ruleIds(i) := tempRuleId;
596             approverCategories(i) := tempCategory;
597             parameterNumbers(i) := tempNumber;
598             parameterSigns(i) := tempSign;
599           end if;
600         end loop;
601       end loop;
602       exception
603         when badParameterException then
604           errorCode := -20001;
605           errorMessage := ame_util.getMessage(applicationShortNameIn => 'PER',
606                                               messageNameIn => 'AME_400234_HAN_ACT_PAR_SIGN');
607           ame_util.runtimeException(packageNameIn => 'ame_dual_chains_handler',
608                                     routineNameIn => 'parseAndSortRules',
609                                     exceptionNumberIn => errorCode,
610                                     exceptionStringIn => errorMessage);
611           raise_application_error(errorCode,
612                                   errorMessage);
613         when others then
614           ame_util.runtimeException(packageNameIn => 'ame_dual_chains_handler',
615                                     routineNameIn => 'parseAndSortRules',
616                                     exceptionNumberIn => sqlcode,
617                                     exceptionStringIn => sqlerrm);
618           raise;
619     end parseAndSortRules;
620 end ame_dual_chains_handler;